PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.5.2
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.5.2
3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / includes / abstracts / class-evf-form-fields-upload.php
everest-forms / includes / abstracts Last commit date
legacy 6 years ago class-evf-background-process.php 7 years ago class-evf-deprecated-hooks.php 2 months ago class-evf-form-fields-upload.php 2 weeks ago class-evf-form-fields.php 1 month ago class-evf-integration.php 5 years ago class-evf-log-handler.php 6 years ago class-evf-session.php 1 year ago class-evf-settings-api.php 4 years ago
class-evf-form-fields-upload.php
1923 lines
1 <?php
2 /**
3 * Abstract uploader helper class
4 *
5 * @package EverestForms_Pro\Abstracts
6 * @version 1.3.0
7 * @since 1.0.0
8 */
9
10 use EverestForms\Helpers\FormHelper;
11
12 defined( 'ABSPATH' ) || exit;
13
14 /**
15 * EVF_Form_Fields_Upload
16 */
17 abstract class EVF_Form_Fields_Upload extends EVF_Form_Fields {
18
19 /**
20 * Files that are not allowed.
21 *
22 * @var array
23 */
24 protected $blacklist = array( 'ade', 'adp', 'app', 'asp', 'bas', 'bat', 'cer', 'cgi', 'chm', 'cmd', 'com', 'cpl', 'crt', 'csh', 'csr', 'dll', 'drv', 'exe', 'fxp', 'flv', 'hlp', 'hta', 'htaccess', 'htm', 'htpasswd', 'inf', 'ins', 'isp', 'jar', 'js', 'jse', 'jsp', 'ksh', 'lnk', 'mdb', 'mde', 'mdt', 'mdw', 'msc', 'msi', 'msp', 'mst', 'ops', 'pcd', 'php', 'pif', 'pl', 'prg', 'ps1', 'ps2', 'py', 'rb', 'reg', 'scr', 'sct', 'sh', 'shb', 'shs', 'sys', 'swf', 'tmp', 'torrent', 'url', 'vb', 'vbe', 'vbs', 'vbscript', 'wsc', 'wsf', 'wsf', 'wsh' );
25
26 /**
27 * Files that are not allowed to be deleted.
28 *
29 * @var array
30 */
31 protected $protected_files = array( 'index.html', 'index.php', '.htaccess', '.htpasswd' );
32
33 /**
34 * Hook in tabs.
35 */
36 public function init_hooks() {
37 add_action( 'everest_forms_shortcode_scripts', array( $this, 'load_assets' ) );
38 add_filter( 'everest_forms_html_field_value', array( $this, 'html_field_value' ), 10, 5 );
39 add_filter( 'everest_forms_plaintext_field_value', array( $this, 'plaintext_field_value' ), 10, 4 );
40 add_filter( 'everest_forms_field_exporter_' . $this->type, array( $this, 'field_exporter' ) );
41 add_filter( 'everest_forms_email_file_attachments', array( $this, 'send_file_as_email_attachment' ), 99, 6 );
42 add_filter( 'everest_forms_email_file_attachments', array( $this, 'send_csv_file_as_email_attachment' ), 100, 6 );
43 add_action( 'everest_forms_remove_attachments_after_send_email', array( $this, 'remove_csv_file_after_email_send' ), 10, 6 );
44 add_action( 'everest_forms_woocommerce_js', array( $this, 'load_assets' ) );
45
46 if ( is_callable( array( $this, 'field_properties' ) ) ) {
47 add_filter( 'everest_forms_field_properties_' . $this->type, array( $this, 'field_properties' ), 5, 3 );
48 }
49
50 // AJAX Events.
51 $this->add_ajax_events();
52 }
53
54 /**
55 * Register/queue frontend scripts.
56 *
57 * @param array $atts Shortcode attributes.
58 */
59 public function load_assets( $atts ) {
60 $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
61 wp_register_script( 'dropzone', plugins_url( "/assets/js/dropzone/dropzone{$suffix}.js", EVF_PLUGIN_FILE ), array( 'jquery' ), '5.5.0', true );
62 wp_register_script( 'everest-forms-file-upload', plugins_url( "/assets/js/frontend/everest-forms-file-upload{$suffix}.js", EVF_PLUGIN_FILE ), array( 'dropzone', 'wp-util' ), EVF_VERSION, true );
63 wp_localize_script(
64 'everest-forms-file-upload',
65 'everest_forms_upload_parms',
66 array(
67 'url' => admin_url( 'admin-ajax.php' ),
68 'errors' => array(
69 'file_not_uploaded' => esc_html__( 'This file was not uploaded.', 'everest-forms' ),
70 'file_limit' => esc_html__( 'File limit has been reached ({fileLimit}).', 'everest-forms' ),
71 'file_extension' => get_option( 'everest_forms_fileextension_validation' ),
72 'file_size' => get_option( 'everest_forms_filesize_validation', __( 'File exceeds max size allowed.', 'everest-forms' ) ),
73 'post_max_size' => sprintf(
74 /* translators: %s: Max upload size */
75 esc_html__( 'File exceeds the upload limit allowed (%s).', 'everest-forms' ),
76 evf_max_upload()
77 ),
78 ),
79 'max_timeout' => apply_filters( 'evf_fileupload_max_timeout', absint( 30000 ) ),
80 'loading_message' => esc_html__( 'Do not submit the form until the upload process is finished', 'everest-forms' ),
81 )
82 );
83
84 if ( 'everest_forms_woocommerce_js' === current_action() ) {
85 wp_enqueue_script( 'dropzone' );
86 wp_enqueue_script( 'everest-forms-file-upload' );
87 return;
88 }
89
90 $form_id = is_array( $atts ) && isset( $atts['id'] ) ? absint( $atts['id'] ) : ( is_numeric( $atts ) ? absint( $atts ) : 0 );
91 $form_fields = evf_get_form_fields( $form_id );
92 $form_data = EVF()->form->get( $form_id, array( 'content_only' => true ) );
93 $form_fields = isset( $form_data['form_fields'] ) ? $form_data['form_fields'] : array();
94
95 foreach ( $form_fields as $form_field ) {
96 if ( 'file-upload' === $form_field['type'] || 'image-upload' === $form_field['type'] ) {
97 wp_enqueue_script( 'dropzone' );
98 wp_enqueue_script( 'everest-forms-file-upload' );
99 break;
100 }
101 }
102 }
103
104 /**
105 * Hook in methods - uses WordPress ajax handlers (admin-ajax).
106 */
107 public function add_ajax_events() {
108 $ajax_events = array(
109 'upload_file',
110 'remove_file',
111 );
112
113 foreach ( $ajax_events as $ajax_event ) {
114 add_action( 'wp_ajax_everest_forms_' . $ajax_event, array( $this, $ajax_event ) );
115 add_action( 'wp_ajax_nopriv_everest_forms_' . $ajax_event, array( $this, $ajax_event ) );
116 }
117 }
118
119 /**
120 * Remove the file from the temporary directory.
121 *
122 * @since 1.3.0
123 */
124 public function remove_file() {
125 $default_error = esc_html__( 'Something went wrong while removing the file.', 'everest-forms' );
126
127 $validated_form_field = $this->ajax_validate_form_field();
128 if ( empty( $validated_form_field ) ) {
129 wp_send_json_error( $default_error );
130 }
131
132 if ( empty( $_POST['file'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
133 wp_send_json_error( $default_error );
134 }
135
136 $file = sanitize_file_name( wp_unslash( $_POST['file'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
137
138 // Strip any path traversal sequences and null bytes
139 $file = str_replace( array( '../', '..\\', '\\', "\0" ), '', $file );
140
141 if ( in_array( strtolower( $file ), array_map( 'strtolower', $this->protected_files ), true ) ) {
142 wp_send_json_error( esc_html__( 'This file cannot be deleted for security reasons.', 'everest-forms' ) );
143 }
144
145 // Only allow deletion from whitelisted directories
146 $allowed_dirs = array(
147 $this->get_tmp_dir(),
148 $this->get_form_files_dir()['path'],
149 );
150
151 $tmp_path = wp_normalize_path( $this->get_tmp_dir() . '/' . $file );
152
153 // Validate that the target path is within allowed directories
154 $is_allowed = false;
155 foreach ( $allowed_dirs as $allowed_dir ) {
156 $allowed_dir = wp_normalize_path( $allowed_dir );
157 if ( strpos( $tmp_path, $allowed_dir ) === 0 ) {
158 $is_allowed = true;
159 break;
160 }
161 }
162
163 if ( ! $is_allowed ) {
164 wp_send_json_error( esc_html__( 'Access denied: File location not allowed.', 'everest-forms' ) );
165 }
166
167 // Requested file does not exist, which is good.
168 if ( ! is_file( $tmp_path ) ) {
169 wp_send_json_success( $file );
170 }
171
172 if ( @unlink( $tmp_path ) ) { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
173 wp_send_json_success( $file );
174 }
175
176 wp_send_json_error( $default_error );
177 }
178
179 /**
180 * Ajax handler for file upload.
181 *
182 * @since 1.3.0
183 */
184 public function upload_file() {
185 $default_error = esc_html__( 'Something went wrong, please try again.', 'everest-forms' );
186
187 $validated_form_field = $this->ajax_validate_form_field();
188 if ( empty( $validated_form_field ) ) {
189 wp_send_json_error( $default_error );
190 }
191
192 if ( empty( $_FILES['file'] ) ) {
193 wp_send_json_error( esc_html__( 'No file was uploaded', 'everest-forms' ) );
194 }
195
196 if ( isset( $_FILES['file']['error'] ) && UPLOAD_ERR_OK !== $_FILES['file']['error'] ) {
197 $error = $_FILES['file']['error']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
198 $error_message = $this->get_upload_validation_errors( $error );
199 wp_send_json_error( $error_message );
200 }
201
202 // Make sure we have required values from $_FILES.
203 if ( empty( $_FILES['file']['name'] ) ) {
204 wp_send_json_error( $default_error );
205 }
206 if ( empty( $_FILES['file']['tmp_name'] ) ) {
207 wp_send_json_error( $default_error );
208 }
209
210 // Make data available always.
211 $this->form_data = $validated_form_field['form_data'];
212 $this->form_id = $this->form_data['id'];
213 $this->field_id = $validated_form_field['field_id'];
214 $this->field_data = $this->form_data['form_fields'][ $this->field_id ];
215
216 $error = empty( $_FILES['file']['error'] ) ? UPLOAD_ERR_OK : intval( $_FILES['file']['error'] );
217 $path = $_FILES['file']['tmp_name']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
218 $name = sanitize_file_name( wp_unslash( $_FILES['file']['name'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
219 $extension = strtolower( pathinfo( $name, PATHINFO_EXTENSION ) );
220 $errors = $this->ajax_validate( $error, $extension, $path, $name );
221 if ( isset( $this->field_data['custom_file_name'] ) && ! empty( $this->field_data['custom_file_name'] ) ) {
222 $custom_file_name = apply_filters( 'everest_forms_process_smart_tags', $this->field_data['custom_file_name'], $this->form_data );
223 $name_of_file = sanitize_file_name( $custom_file_name ) . '_' . uniqid( '', true ) . '.' . $extension;
224 } else {
225 $name_of_file = sanitize_file_name( wp_unslash( $_FILES['file']['name'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
226 }
227
228 if ( count( $errors ) ) {
229 wp_send_json_error( implode( ',', $errors ), 400 );
230 }
231
232 $tmp_dir = $this->get_tmp_dir();
233 $tmp_name = $this->get_tmp_file_name( $extension );
234 $tmp_path = wp_normalize_path( $tmp_dir . '/' . $tmp_name );
235 $tmp = $this->move_file( $path, $tmp_path );
236
237 if ( ! $tmp ) {
238 wp_send_json_error( $default_error );
239 }
240
241 $this->clean_tmp_files();
242
243 wp_send_json_success(
244 array(
245 'file' => pathinfo( $tmp, PATHINFO_FILENAME ) . '.' . pathinfo( $tmp, PATHINFO_EXTENSION ),
246 'name' => $name_of_file,
247 )
248 );
249 }
250
251 /**
252 * Clean up the tmp folder - remove all old files every day (filterable interval).
253 */
254 protected function clean_tmp_files() {
255 $files = glob( trailingslashit( $this->get_tmp_dir() ) . '*' );
256
257 if ( ! is_array( $files ) || empty( $files ) ) {
258 return;
259 }
260
261 $lifespan = (int) apply_filters( 'everest_forms_field_' . $this->type . '_clean_tmp_files_lifespan', DAY_IN_SECONDS );
262
263 foreach ( $files as $file ) {
264 if ( ! is_file( $file ) ) {
265 continue;
266 }
267
268 // In some cases filemtime() can return false, in that case - pretend this is a new file and do nothing.
269 $modified = (int) filemtime( $file );
270 if ( empty( $modified ) ) {
271 $modified = time();
272 }
273
274 if ( ( time() - $modified ) >= $lifespan ) {
275 @unlink( $file ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
276 }
277 }
278 }
279
280 /**
281 * Ajax handler for errors.
282 *
283 * @param int $error Errors.
284 * @param string $ext Extension.
285 * @param string $path Path to a newly uploaded file.
286 * @param string $name Name of a newly uploaded file.
287 *
288 * @return array of errors.
289 */
290 public function ajax_validate( $error, $ext, $path, $name ) {
291 $errors = array();
292
293 // Basic file upload validation.
294 if ( UPLOAD_ERR_OK !== $error ) {
295 $upload_error_message = $this->get_upload_validation_errors( $error );
296 if ( is_string( $upload_error_message ) ) {
297 /* translators: %s - error text. */
298 $errors[] = sprintf( esc_html__( 'File upload error. %s', 'everest-forms' ), $upload_error_message );
299 }
300 }
301
302 if ( 'pdf' === $ext ) {
303
304 $content = file_get_contents( $path );
305 $patterns = array(
306 '/\/JavaScript\b/',
307 '/eval\(/i',
308 '/app\.alert/i',
309 '/console\.log\b/i',
310 '/document\.write\b/i',
311 '/\/SubmitForm\b/i',
312 '/\/Launch\b/i',
313 '/\/RichMedia\b/i',
314 '/\/EmbeddedFile\b/i',
315 '/\/FileAttachment\b/i',
316 '/\/GoTo\b/i',
317 );
318
319 // Initialize errors array
320 $errors = array();
321
322 // Check for malicious patterns
323 foreach ( $patterns as $pattern ) {
324 if ( preg_match( $pattern, $content ) ) {
325 $errors[] = esc_html__( ' Malicious file detected', 'everest-forms' );
326 }
327 }
328 }
329
330 // Validate file size.
331 $max_size = min( wp_max_upload_size(), $this->max_file_size() );
332
333 if ( ! empty( $_FILES ) ) {
334 foreach ( $_FILES as $file ) {
335 if ( $file['size'] > $max_size ) {
336 $errors[] = sprintf(
337 /* translators: %s: max upload size */
338 esc_html__( 'File exceeds max size allowed (%s).', 'everest-forms' ),
339 evf_size_to_megabytes( $max_size )
340 );
341 }
342 }
343 }
344
345 // Make sure file has an extension first.
346 if ( empty( $ext ) ) {
347 $errors[] = esc_html__( 'File must have an extension.', 'everest-forms' );
348 }
349
350 // Validate extension against all allowed values.
351 if ( ! in_array( $ext, $this->get_extensions(), true ) ) {
352 $errors[] = esc_html__( 'File type is not allowed.', 'everest-forms' );
353 }
354
355 /*
356 * Validate file against what WordPress is set to allow.
357 * At the end of the day, if you try to upload a file that WordPress
358 * doesn't allow, we won't allow it either. Users can use a plugin to
359 * filter the allowed mime types in WordPress if this is an issue.
360 */
361 if ( ! defined( 'ALLOW_UNFILTERED_UPLOADS' ) || false === ALLOW_UNFILTERED_UPLOADS ) {
362 $wp_filetype = wp_check_filetype_and_ext( $path, $name );
363
364 $ext = empty( $wp_filetype['ext'] ) ? '' : $wp_filetype['ext'];
365 $type = empty( $wp_filetype['type'] ) ? '' : $wp_filetype['type'];
366 $proper_filename = empty( $wp_filetype['proper_filename'] ) ? '' : $wp_filetype['proper_filename'];
367
368 if ( $proper_filename || ! $ext || ! $type ) {
369 $errors[] = esc_html__( 'File type is not allowed.', 'everest-forms' );
370 }
371 }
372
373 return $errors;
374 }
375
376 /**
377 * Get all allowed extensions.
378 * Check against user-entered extensions.
379 *
380 * @since 1.3.1
381 *
382 * @param mixed $ext_type Extension type.
383 *
384 * @return array of allowed extensions.
385 */
386 protected function get_extensions( $ext_type = '' ) {
387 $ext_types = wp_get_ext_types();
388 $mime_types = wp_get_mime_types();
389
390 if ( ! empty( $this->field_data['extensions'] ) ) {
391 // User provided specific extensions.
392 $extensions = array_diff( explode( ',', strtolower( preg_replace( '/[^A-Za-z0-9,]/', '', $this->field_data['extensions'] ) ) ), $this->blacklist );
393 } elseif ( '' !== $ext_type ) {
394 $extensions = array_diff( $ext_types[ $ext_type ], $this->blacklist );
395 } else {
396 // Get default extensions supported by WordPress.
397 $extensions = array_diff( explode( '|', implode( '|', array_keys( $mime_types ) ) ), $this->blacklist );
398 }
399
400 return $extensions;
401 }
402
403 /**
404 * Move file to a permanent location.
405 *
406 * @since 1.3.0
407 *
408 * @param string $filename The filename of the uploaded file.
409 * @param string $destination The destination of the moved file.
410 *
411 * @return false|string False on error.
412 */
413 protected function move_file( $filename, $destination ) {
414 $this->create_dir( dirname( $destination ) );
415
416 if ( false === move_uploaded_file( $filename, $destination ) ) {
417 $logger = evf_get_logger();
418 $logger->error(
419 sprintf( 'Upload Error, could not upload file: %s', $filename ),
420 array(
421 'source' => 'file-upload',
422 )
423 );
424
425 return false;
426 }
427
428 $this->set_file_fs_permissions( $destination );
429
430 return $destination;
431 }
432
433 /**
434 * Create both the directory and index.html file in it if any of them doesn't exist.
435 *
436 * @since 1.3.0
437 *
438 * @param string $path Path to the directory.
439 *
440 * @return string Path to the newly created directory.
441 */
442 protected function create_dir( $path ) {
443 if ( ! file_exists( $path ) ) {
444 wp_mkdir_p( $path );
445 }
446
447 $index = wp_normalize_path( $path . '/index.html' );
448
449 if ( ! file_exists( $index ) ) {
450 file_put_contents( $index, '' ); // phpcs:ignore WordPress.WP.AlternativeFunctions
451 }
452
453 return $path;
454 }
455
456 /**
457 * Set correct file permissions in the file system.
458 *
459 * @since 1.3.0
460 *
461 * @param string $path File to set permissions for.
462 */
463 protected function set_file_fs_permissions( $path ) {
464 // Set correct file permissions.
465 $stat = stat( dirname( $path ) );
466
467 @chmod( $path, $stat['mode'] & 0000666 ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
468 }
469
470 /**
471 * Get tmp file name.
472 *
473 * @since 1.3.0
474 *
475 * @param string $extension File extension.
476 *
477 * @return string
478 */
479 protected function get_tmp_file_name( $extension ) {
480 return wp_hash( wp_rand() . microtime() . $this->form_id . $this->field_id ) . '.' . $extension;
481 }
482
483 /**
484 * Get tmp dir for files.
485 *
486 * @since 1.3.0
487 *
488 * @return string
489 */
490 protected function get_tmp_dir() {
491 $uploads = wp_upload_dir();
492 $tmp_root = untrailingslashit( $uploads['basedir'] ) . '/everest_forms_uploads/tmp';
493
494 if ( ! file_exists( $tmp_root ) || ! wp_is_writable( $tmp_root ) ) {
495 wp_mkdir_p( $tmp_root );
496 }
497
498 $index = trailingslashit( $tmp_root ) . 'index.html';
499
500 if ( ! file_exists( $index ) ) {
501 file_put_contents( $index, '' ); // phpcs:ignore WordPress.WP.AlternativeFunctions
502 }
503
504 return $tmp_root;
505 }
506
507 /**
508 * Ajax validation for form fields.
509 *
510 * @since 1.3.0
511 */
512 protected function ajax_validate_form_field() {
513 if ( empty( $_POST['form_id'] ) || empty( $_POST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
514 return array();
515 }
516
517 $field_id = sanitize_text_field( wp_unslash( $_POST['field_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
518 $form_data = evf()->form->get(
519 (int) $_POST['form_id'], // phpcs:ignore WordPress.Security.NonceVerification
520 array(
521 'content_only' => true,
522 )
523 );
524
525 if ( empty( $form_data ) || ! is_array( $form_data ) || ( isset( $form_data['form_enabled'] ) && 1 !== absint( $form_data['form_enabled'] ) ) ) {
526 return array();
527 }
528
529 // For checking form is published or not.
530 $the_post = get_post( absint( $form_data['id'] ) );
531 if ( $the_post && 'publish' !== $the_post->post_status ) {
532 return array();
533 }
534
535 return array(
536 'form_data' => $form_data,
537 'field_id' => $field_id,
538 );
539 }
540
541 /**
542 * Allowed Extensions field option.
543 *
544 * @param array $field Field data.
545 */
546 public function extensions( $field ) {
547 $lbl = $this->field_element(
548 'label',
549 $field,
550 array(
551 'slug' => 'extensions',
552 'value' => esc_html__( 'Allowed File Extensions', 'everest-forms' ),
553 'tooltip' => esc_html__( 'Enter the extensions you would like to allow, comma separated.', 'everest-forms' ),
554 ),
555 false
556 );
557 $fld = $this->field_element(
558 'text',
559 $field,
560 array(
561 'slug' => 'extensions',
562 'value' => ! empty( $field['extensions'] ) ? $field['extensions'] : '',
563 ),
564 false
565 );
566 $args = array(
567 'slug' => 'extensions',
568 'content' => $lbl . $fld,
569 );
570 $this->field_element( 'row', $field, $args );
571 }
572
573 /**
574 * Upload message field option.
575 *
576 * @param array $field Field data.
577 */
578 public function upload_message( $field ) {
579 $max_file_number = ! empty( $field['max_file_number'] ) ? max( 1, absint( $field['max_file_number'] ) ) : 1;
580 $lbl = $this->field_element(
581 'label',
582 $field,
583 array(
584 'slug' => 'upload_message',
585 'value' => esc_html__( 'File Upload Message', 'everest-forms' ),
586 'tooltip' => esc_html__( 'Enter text to be displayed as file upload message', 'everest-forms' ),
587 ),
588 false
589 );
590 $fld = $this->field_element(
591 'text',
592 $field,
593 array(
594 'slug' => 'upload_message',
595 'value' => ! empty( $field['upload_message'] ) ? $field['upload_message'] : esc_html( sprintf( _n( 'Drop your file here or click here to upload', 'Drop your files here or click here to upload', (int) $max_file_number, 'everest-forms' ), (int) $max_file_number ) ),
596 ),
597 false
598 );
599 $args = array(
600 'slug' => 'upload_message',
601 'content' => $lbl . $fld,
602 );
603 $this->field_element( 'row', $field, $args );
604 }
605
606 /**
607 * Get the custom user defined file name
608 *
609 * @param array $field Field data.
610 */
611 public function custom_file_name( $field ) {
612 $lbl = $this->field_element(
613 'label',
614 $field,
615 array(
616 'slug' => 'custom_file_name',
617 'value' => esc_html__( 'Custom File Name', 'everest-forms' ),
618 'tooltip' => esc_html__( 'Enter text to be displayed as file name. Supports smart tags.', 'everest-forms' ),
619 ),
620 false
621 );
622 $fld = $this->field_element(
623 'text',
624 $field,
625 array(
626 'slug' => 'custom_file_name',
627 'value' => ! empty( $field['custom_file_name'] ) ? $field['custom_file_name'] : '',
628 ),
629 false
630 );
631
632 $smart_tag_toggle = '<a href="#" class="evf-toggle-smart-tag-display" data-type="all"><span class="dashicons dashicons-editor-code"></span></a>';
633 $smart_tag_toggle .= '<div class="evf-smart-tag-lists" style="display: none">';
634 $smart_tag_toggle .= '<div class="smart-tag-title">' . esc_html__( 'Available Fields', 'everest-forms' ) . '</div><ul class="evf-fields"></ul>';
635 $smart_tag_toggle .= '<div class="smart-tag-title other-tag-title">' . esc_html__( 'Others', 'everest-forms' ) . '</div><ul class="evf-others"></ul>';
636 $smart_tag_toggle .= '</div>';
637
638 $args = array(
639 'slug' => 'custom_file_name',
640 'content' => $lbl . $fld . $smart_tag_toggle,
641 'class' => 'evf_smart_tag',
642 );
643
644 $this->field_element( 'row', $field, $args );
645 }
646
647 /**
648 * Limit message field option.
649 *
650 * @param array $field Field data.
651 */
652 public function limit_message( $field ) {
653 $max_file_number = ! empty( $field['max_file_number'] ) ? max( 1, absint( $field['max_file_number'] ) ) : 1;
654 $lbl = $this->field_element(
655 'label',
656 $field,
657 array(
658 'slug' => 'limit_message',
659 'value' => esc_html__( 'Upload Limit Message', 'everest-forms' ),
660 'tooltip' => esc_html__( 'Enter text to be displayed as file upload limit message', 'everest-forms' ),
661 ),
662 false
663 );
664 $fld = $this->field_element(
665 'text',
666 $field,
667 array(
668 'slug' => 'limit_message',
669 /* translators: 1: Number of Files */
670 'value' => ! empty( $field['limit_message'] ) ? $field['limit_message'] : sprintf( __( 'You can upload up to %s files.', 'everest-forms' ), (int) $max_file_number ),
671 ),
672 false
673 );
674 $args = array(
675 'slug' => 'limit_message',
676 'content' => $lbl . $fld,
677 );
678 $this->field_element( 'row', $field, $args );
679 }
680
681
682 /**
683 * Max file size field option.
684 *
685 * @param array $field Field data.
686 */
687 public function max_size( $field ) {
688 $lbl = $this->field_element(
689 'label',
690 $field,
691 array(
692 'slug' => 'max_size',
693 'value' => esc_html__( 'Max File Size', 'everest-forms' ),
694 /* translators: %s - max upload size. */
695 'tooltip' => sprintf( esc_html__( 'Enter the max file size, in megabytes, to allow. If left blank, the value defaults to the maximum size the server allows which is %s.', 'everest-forms' ), evf_max_upload() ),
696 ),
697 false
698 );
699 $fld = $this->field_element(
700 'text',
701 $field,
702 array(
703 'slug' => 'max_size',
704 'value' => ! empty( $field['max_size'] ) ? $field['max_size'] : '',
705 ),
706 false
707 );
708 $args = array(
709 'slug' => 'max_size',
710 'content' => $lbl . $fld,
711 );
712 $this->field_element( 'row', $field, $args );
713 }
714
715 /**
716 * File upload limit option.
717 *
718 * @param array $field Field data.
719 */
720 public function max_file_number( $field ) {
721 $lbl = $this->field_element(
722 'label',
723 $field,
724 array(
725 'slug' => 'max_file_number',
726 'value' => esc_html__( 'Maximum number limit on uploads', 'everest-forms' ),
727 'tooltip' => sprintf( esc_html__( 'Enter the number of files you wish the user to upload.', 'everest-forms' ) ),
728 ),
729 true
730 );
731 $fld = $this->field_element(
732 'number',
733 $field,
734 array(
735 'slug' => 'max_file_number',
736 'type' => 'number',
737 'min' => '1',
738 'max' => $max_file_number = ( ( ( defined( 'EFP_PLUGIN_FILE' ) ) && ! ( empty( $field['max_file_number'] ) && 0 < intval( $field['max_file_number'] ) ) ) || ! empty( $field['max_file_number'] ) ) ? $field['max_file_number'] : 1,
739 'value' => $max_file_number = ( ( ( defined( 'EFP_PLUGIN_FILE' ) ) && ! ( empty( $field['max_file_number'] ) && 0 < intval( $field['max_file_number'] ) ) ) || ! empty( $field['max_file_number'] ) ) ? $field['max_file_number'] : 1,
740 'desc' => esc_html__( 'Maximum number limit on uploads', 'everest-forms' ),
741 'tooltip' => esc_html__( 'Enter the number of files you wish the user to upload.', 'everest-forms' ),
742 ),
743 false
744 );
745 $args = array(
746 'slug' => 'max_file_number',
747 'content' => $fld,
748 );
749 $this->field_element( 'row', $field, $args );
750 }
751
752 /**
753 * Media Library field option.
754 *
755 * @param array $field Field data.
756 */
757 public function media_library( $field ) {
758 $fld = $this->field_element(
759 'toggle',
760 $field,
761 array(
762 'slug' => 'media_library',
763 'value' => ! empty( $field['media_library'] ) ? 1 : '',
764 'desc' => esc_html__( 'Store file in WordPress Media Library', 'everest-forms' ),
765 'tooltip' => esc_html__( 'Check this option to store the final uploaded file in the WordPress Media Library', 'everest-forms' ),
766 ),
767 false
768 );
769 $args = array(
770 'slug' => 'media_library',
771 'content' => $fld,
772 );
773 $this->field_element( 'row', $field, $args );
774 }
775
776 /**
777 * Customize format for HTML field value.
778 *
779 * @param string $val Field value.
780 * @param array $field_val Field settings.
781 * @param array $form_data Form data.
782 * @param string $context Value display context.
783 * @return string $val Html Value.
784 */
785 public function html_field_value( $val, $field_val, $form_data = array(), $context = '', $field_meta_key = '' ) {
786 $meta_key = '';
787 $entry_id = false;
788 $uploads = wp_upload_dir();
789
790 if ( 'evffl-display-popup' === $context ) {
791 foreach ( $form_data['form_fields'] as $fields_data ) {
792 if ( $field_val['meta-key'] === $fields_data['meta-key'] ) {
793 if ( 'image-upload' === $fields_data['type'] ) {
794 $val = '';
795 foreach ( $field_val['field_value']['value_raw'] as $key => $value ) {
796 $image_url = isset( $value['value'] ) ? esc_url( $value['value'] ) : '';
797
798 $val .= sprintf(
799 '<a href="%1$s" target="_blank" rel="noopener noreferrer"><img src="%1$s" style="width:200px;" alt="" /></a>',
800 $image_url
801 );
802 }
803
804 return $val;
805 }
806
807 if ( 'file-upload' === $fields_data['type'] ) {
808 $count = count( $field_val['field_value']['value_raw'] );
809 $val = '';
810
811 if ( $count > 1 ) {
812 foreach ( $field_val['field_value']['value_raw'] as $key => $value ) {
813 $file_url = isset( $value['value'] ) ? esc_url( $value['value'] ) : '';
814 $file_name = isset( $value['name'] ) ? esc_html( $value['name'] ) : '';
815
816 if ( 1 === $count ) {
817 $val .= sprintf(
818 '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>',
819 $file_url,
820 $file_name
821 );
822 } else {
823 $val .= sprintf(
824 '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>, ',
825 $file_url,
826 $file_name
827 );
828 }
829
830 --$count;
831 }
832 } else {
833 $file_url = isset( $field_val['value'] ) ? esc_url( $field_val['value'] ) : '';
834 $file_name = isset( $field_val['field_value']['value_raw'][0]['name'] ) ? esc_html( $field_val['field_value']['value_raw'][0]['name'] ) : '';
835
836 $val .= sprintf(
837 '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>',
838 $file_url,
839 $file_name
840 );
841 }
842
843 return $val;
844 }
845 }
846 }
847 }
848
849 if ( isset( $_GET['view-entry'] ) && 'entry-single' === $context ) { // phpcs:ignore WordPress.Security.NonceVerification
850 $entry_id = absint( $_GET['view-entry'] ); // phpcs:ignore WordPress.Security.NonceVerification
851 $meta_key = ! empty( $field_meta_key ) ? evf_clean( $field_meta_key ) : array_search( $val, $form_data, true );
852 } elseif ( isset( $_GET['edit-entry'], $field_val['meta_key'] ) && 'entry-single' === $context ) { // phpcs:ignore WordPress.Security.NonceVerification
853 $entry_id = absint( $_GET['edit-entry'] ); // phpcs:ignore WordPress.Security.NonceVerification
854 $meta_key = evf_clean( $field_val['meta_key'] );
855 } elseif ( isset( $form_data, $field_val['meta_key'] ) && 'email-html' === $context ) {
856 $entry_id = absint( $form_data['entry_id'] );
857 $meta_key = evf_clean( $field_val['meta_key'] );
858 } elseif ( is_object( $form_data ) ) {
859 $entry_id = absint( $form_data->entry_id );
860 $meta_key = array_search( $val, $form_data->meta, true );
861 } elseif ( isset( $_GET['entry_id'], $_GET['list_id'] ) && 'entry-single' === $context ) { // phpcs:ignore WordPress.Security.NonceVerification
862 $entry_id = absint( $_GET['entry_id'] ); // phpcs:ignore WordPress.Security.NonceVerification
863 $meta_key = array_search( $val, $form_data, true );
864 }
865
866 $entry = $entry_id ? evf_get_entry( $entry_id, true ) : false;
867 $fields = isset( $entry->fields ) ? evf_decode( $entry->fields ) : array();
868
869 if ( ! empty( $fields ) && ! is_serialized( $field_val ) ) {
870 $output = array();
871
872 foreach ( $fields as $field ) {
873 if ( empty( $field['value'] ) || $field['type'] !== $this->type || $field['meta_key'] !== $meta_key ) {
874 continue;
875 }
876
877 if ( ! empty( $field['value_raw'] ) ) {
878 foreach ( $field['value_raw'] as $file ) {
879 if ( empty( $file['value'] ) || empty( $file['file_original'] ) ) {
880 $output[ $meta_key ] = '';
881 continue;
882 }
883
884 $file_url = esc_url( $file['value'] );
885 $file_original = esc_html( $file['file_original'] );
886
887 if ( 'export-csv' === $context ) {
888 $output[ $meta_key ][] = $file_url;
889 } elseif ( 'image-upload' === $field['type'] ) {
890 if ( 'email-html' === $context ) {
891 $output[ $meta_key ][] = apply_filters(
892 'everest_forms_image_value',
893 sprintf(
894 '<a href="%1$s" rel="noopener noreferrer" target="_blank"><img src="%1$s" style="width:200px;" alt="" /></a>',
895 $file_url
896 ),
897 $file_url
898 );
899 } elseif ( 'entry-single' === $context ) {
900 $output[ $meta_key ][] = sprintf(
901 '<a href="%1$s" rel="noopener noreferrer" target="_blank"><img src="%1$s" style="width:200px;" alt="" /></a>',
902 $file_url
903 );
904 } else {
905 $output[ $meta_key ][] = sprintf(
906 '<a href="%1$s" rel="noopener noreferrer" target="_blank">%2$s</a>',
907 $file_url,
908 $file_original
909 );
910 }
911 } else {
912 $output[ $meta_key ][] = sprintf(
913 '<a href="%1$s" rel="noopener noreferrer" target="_blank">%2$s</a>',
914 $file_url,
915 $file_original
916 );
917 }
918 }
919 }
920 }
921
922 if ( ! empty( $output[ $meta_key ] ) ) {
923 $val = implode( 'export-csv' !== $context ? '<br>' : '|', $output[ $meta_key ] );
924 }
925 } elseif ( is_serialized( $field_val ) ) {
926 $value = maybe_unserialize( $field_val );
927
928 if ( isset( $value['type'] ) && in_array( $value['type'], array( 'image-upload', 'file-upload' ), true ) ) {
929 $val = empty( $value['file_url'] ) ? '<em>' . esc_html__( '(empty)', 'everest-forms' ) . '</em>' : $val;
930 }
931
932 if ( isset( $value['type'], $value['file_url'] ) && $value['type'] === $this->type ) {
933 $file = $uploads['basedir'] . str_replace( '/uploads/', '/', str_replace( content_url(), '', esc_url( $value['file_url'] ) ) );
934
935 switch ( $this->type ) {
936 case 'image-upload':
937 if ( '' !== $value['file_url'] ) {
938 $file_url = esc_url( $value['file_url'] );
939 $file_original = isset( $value['file_original'] ) ? esc_html( $value['file_original'] ) : '';
940
941 if ( 'export-pdf' === $context ) {
942 $val = sprintf(
943 '<img src="%s" style="width:200px;height:100px;" alt="" />',
944 esc_attr( $file )
945 );
946 } elseif ( 'entry-single' === $context ) {
947 $alt_text = esc_attr( basename( $file_url ) );
948 $val = sprintf(
949 '<a href="%1$s" rel="noopener noreferrer" target="_blank">
950 <img src="%1$s" style="width:200px;" alt="%2$s" />
951 </a>',
952 esc_url( $file_url ),
953 $alt_text
954 );
955 } else {
956 $val = sprintf(
957 '<a href="%1$s" target="_blank" rel="noopener noreferrer" class="image">%2$s</a>',
958 $file_url,
959 $file_original
960 );
961 }
962 }
963 break;
964
965 default:
966 if ( '' !== $value['file_url'] ) {
967 $file_url = esc_url( $value['file_url'] );
968 $file_original = isset( $value['file_original'] ) ? esc_html( $value['file_original'] ) : '';
969
970 $val = sprintf(
971 '<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>',
972 $file_url,
973 $file_original
974 );
975 }
976 break;
977 }
978
979 if ( in_array( $context, array( 'export-csv' ), true ) ) {
980 $val = esc_url( $value['file_url'] );
981 }
982 }
983 }
984
985 return $val;
986 }
987
988 /**
989 * Customize format for Plain field value.
990 *
991 * @param string $val Field value.
992 * @param array $field_val Field settings.
993 * @param array $form_data Form data.
994 * @param string $context Value display context.
995 *
996 * @return string $val Formatted file url.
997 */
998 public function plaintext_field_value( $val, $field_val, $form_data = array(), $context = '' ) {
999 if ( is_array( $field_val ) && 'email-plain' === $context ) {
1000 if ( isset( $field_val['type'], $field_val['file_url'] ) && $field_val['type'] === $this->type ) {
1001 return esc_url( $field_val['file_url'] ) . "\r\n\r\n";
1002 }
1003 }
1004
1005 return $val;
1006 }
1007
1008 /**
1009 * Filter callback for outputting formatted data.
1010 *
1011 * @param array $field Field Data.
1012 */
1013 public function field_exporter( $field ) {
1014 $value = array();
1015
1016 if ( ! empty( $field['value_raw'] ) ) {
1017 if ( ! is_array( $field['value_raw'] ) ) {
1018 $field['value_raw'] = (array) $field['value_raw'];
1019 }
1020
1021 array_walk(
1022 $field['value_raw'],
1023 function ( &$val, $key, $img ) {
1024 $img['data'][] = ! empty( $val['value'] ) ? apply_filters(
1025 'everest_forms_field_exporter_image',
1026 sprintf(
1027 '<a href="%s" rel="noopener noreferrer" target="_blank">%s</a>',
1028 esc_url( $val['value'] ),
1029 esc_html( $val['name'] )
1030 ),
1031 $val
1032 ) : '';
1033 },
1034 array(
1035 'data' => &$value,
1036 )
1037 );
1038 }
1039
1040 return array(
1041 'label' => ! empty( $field['name'] ) ? $field['name'] : ucfirst( str_replace( '_', ' ', $field['type'] ) ) . " - {$field['id']}",
1042 'value' => is_array( $value ) ? count( $value ) ? implode( '<br>', $value ) : false : $value,
1043 );
1044 }
1045
1046 /**
1047 * Field preview inside the builder.
1048 *
1049 * @param array $field Field data.
1050 */
1051 public function field_preview( $field ) {
1052 // Label.
1053 $this->field_preview_option( 'label', $field );
1054
1055 $max_file_number = ! empty( $field['max_file_number'] ) ? max( 1, absint( $field['max_file_number'] ) ) : 1;
1056 $upload_message = isset( $field['upload_message'] ) ? $field['upload_message'] : esc_html( sprintf( _n( 'Drop your file here or click here to upload', 'Drop your files here or click here to upload', (int) $max_file_number, 'everest-forms' ), (int) $max_file_number ) );
1057 /* translators: 1: Number of Files */
1058 $limit_message = isset( $field['limit_message'] ) ? $field['limit_message'] : sprintf( __( 'You can upload up to %s files.', 'everest-forms' ), (int) $max_file_number );
1059
1060 // Primary input.
1061 ?>
1062 <div class="everest-forms-uploader">
1063 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32px" height="32px" fill="#868e96"><path class="cls-1" d="M18.12,17.52,17,16.4V25a1,1,0,0,1-2,0V16.4l-1.12,1.12a1,1,0,0,1-1.42,0,1,1,0,0,1,0-1.41l2.83-2.83a1,1,0,0,1,1.42,0l2.83,2.83a1,1,0,0,1-.71,1.7A1,1,0,0,1,18.12,17.52ZM22,22H20a1,1,0,0,1,0-2h2a4,4,0,0,0,.27-8,1,1,0,0,1-.84-.57,6,6,0,0,0-11.36,1.69,1,1,0,0,1-1,.86H9A3,3,0,0,0,9,20h3a1,1,0,0,1,0,2H9a5,5,0,0,1-.75-9.94A8,8,0,0,1,23,10.1,6,6,0,0,1,22,22Z"></path></svg>
1064 <span class="everest-forms-upload-title"><?php echo esc_html( $upload_message ); ?></span>
1065 <span class="everest-forms-upload-hint">
1066 <?php
1067 echo wp_kses( $limit_message, array( 'span' ) );
1068 ?>
1069 </span>
1070 </div>
1071 <input type="file" class="widefat" disabled>
1072 <?php
1073
1074 // Description.
1075 $this->field_preview_option( 'description', $field );
1076 }
1077
1078 /**
1079 * Field display on the form front-end.
1080 *
1081 * @since 1.0.0
1082 *
1083 * @param array $field Field Data.
1084 * @param array $field_atts Field attributes.
1085 * @param array $form_data All Form Data.
1086 */
1087 public function field_display( $field, $field_atts, $form_data ) {
1088
1089 // Define data.
1090 $primary = $field['properties']['inputs']['primary'];
1091 $conditional_rules = isset( $field['properties']['inputs']['primary']['attr']['conditional_rules'] ) ? $field['properties']['inputs']['primary']['attr']['conditional_rules'] : '';
1092 $conditional_id = isset( $field['properties']['inputs']['primary']['attr']['conditional_id'] ) ? $field['properties']['inputs']['primary']['attr']['conditional_id'] : '';
1093 $field_id = $field['id'];
1094 $form_id = (int) $form_data['id'];
1095 $url = admin_url( 'admin-ajax.php' );
1096 $input_name = 'everest_forms_' . $form_data['id'] . '_' . $field['id'];
1097 $required = $primary['required'];
1098 $extensions = $primary['data']['rule-extension'];
1099 $max_size = abs( $primary['data']['rule-maxsize'] );
1100 $max_file_number = isset( $field['max_file_number'] ) ? $field['max_file_number'] : 1;
1101 $max_file_number = max( 1, absint( $max_file_number ) );
1102 $post_max_size = wp_max_upload_size();
1103 $upload_message = isset( $field['upload_message'] ) ? $field['upload_message'] : esc_html( sprintf( _n( 'Drop your file here or click here to upload', 'Drop your files here or click here to upload', (int) $max_file_number, 'everest-forms' ), (int) $max_file_number ) );
1104 /* translators: 1: Number of Files */
1105 $limit_message = isset( $field['limit_message'] ) ? $field['limit_message'] : sprintf( __( 'You can upload up to %s files.', 'everest-forms' ), (int) $max_file_number );
1106
1107 $files = ! empty( $primary['attr']['value'] ) ? explode( ' ', $primary['attr']['value'] ) : array();
1108 $old_input_name = sprintf( 'everest_forms_%d_old_%s[]', $this->form_id, $this->field_id );
1109 $delete_input_name = sprintf( 'everest_forms_%d_delete_%s', $this->form_id, $this->field_id );
1110
1111 ?>
1112 <div class="everest-forms-uploader"
1113 data-field-id="<?php echo esc_attr( $field_id ); ?>"
1114 data-form-id="<?php echo (int) $form_id; ?>"
1115 data-input-name="<?php echo esc_attr( $input_name ); ?>"
1116 data-extensions="<?php echo esc_attr( $extensions ); ?>"
1117 data-max-size="<?php echo (int) $max_size; ?>"
1118 data-max-file-number="<?php echo (int) $max_file_number; ?>"
1119 data-post-max-size="<?php echo (int) $post_max_size; ?>"
1120 data-current-file-count="<?php echo count( $files ); ?>"
1121 >
1122 <div class="dz-message">
1123 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32px" height="32px" fill="#868e96"><path class="cls-1" d="M18.12,17.52,17,16.4V25a1,1,0,0,1-2,0V16.4l-1.12,1.12a1,1,0,0,1-1.42,0,1,1,0,0,1,0-1.41l2.83-2.83a1,1,0,0,1,1.42,0l2.83,2.83a1,1,0,0,1-.71,1.7A1,1,0,0,1,18.12,17.52ZM22,22H20a1,1,0,0,1,0-2h2a4,4,0,0,0,.27-8,1,1,0,0,1-.84-.57,6,6,0,0,0-11.36,1.69,1,1,0,0,1-1,.86H9A3,3,0,0,0,9,20h3a1,1,0,0,1,0,2H9a5,5,0,0,1-.75-9.94A8,8,0,0,1,23,10.1,6,6,0,0,1,22,22Z"/></svg>
1124 <span class="everest-forms-upload-title">
1125 <?php
1126 echo esc_html( $upload_message );
1127 ?>
1128 </span>
1129
1130 <?php if ( (int) $max_file_number >= 1 ) : ?>
1131 <span class="everest-forms-upload-hint">
1132 <?php
1133 /* translators: %d - max number of files. */
1134 echo wp_kses( $limit_message, array( 'span' ) );
1135 ?>
1136 </span>
1137 <?php endif; ?>
1138 </div>
1139 <?php
1140 if ( ! empty( $files ) ) {
1141 $key = $field['meta-key'];
1142 foreach ( $files as $attachment_url ) {
1143 if ( empty( $attachment_url ) || ! $attachment_url ) {
1144 continue;
1145 }
1146 ?>
1147 <div class="dz-preview dz-processing dz-image-preview dz-success dz-complete">
1148 <div class="dz-image">
1149 <?php
1150
1151 if ( empty( $attachment_url ) ) {
1152 $attachment_url = home_url() . '/wp-includes/images/media/text.png';
1153 }
1154
1155 $filename_only = basename( $attachment_url ); // Just the file name.
1156 $file_original = preg_replace( '/-[a-f0-9]{32}/', '', $filename_only ); // Remove hash to get original name
1157
1158 $filesize_only = $this->get_local_file_size( $attachment_url );
1159
1160 if ( false !== $filesize_only ) {
1161 $filesize_only = size_format( $filesize_only, 1 );
1162 }
1163
1164 $ext = pathinfo( $attachment_url, PATHINFO_EXTENSION );
1165 $fileIcon = FormHelper::evf_file_upload_check_file_types( $ext );
1166
1167 $fileIcon = ! is_null( $fileIcon ) ? evf()->plugin_url() . '/assets/images/filetypes/' . $fileIcon . '.png' : $attachment_url;
1168
1169 $file = array(
1170 'name' => $file_original,
1171 'value' => $attachment_url,
1172 'file' => $filename_only,
1173 'file_original' => $file_original,
1174 'ext' => $ext,
1175 'attachment_id' => 0,
1176 'id' => $field_id,
1177 'type' => $this->get_file_mime_type( $attachment_url ),
1178 );
1179 ?>
1180
1181 <img data-dz-thumbnail="" alt="<?php echo esc_html( sanitize_text_field( $filename_only ) ); ?>" src="<?php echo esc_url( $fileIcon ); ?>"/>
1182 </div>
1183 <div class="dz-details">
1184 <div class="dz-size">
1185 <span data-dz-size=""><strong><?php echo esc_html( sanitize_text_field( $filesize_only ) ); ?></strong></span>
1186 </div>
1187 <div class="dz-filename">
1188 <span data-dz-name=""><?php echo esc_html( sanitize_text_field( $filename_only ) ); ?></span>
1189 </div>
1190 <input type="hidden" class="existing-file" name="<?php echo $old_input_name; ?>" value='<?php echo json_encode( $file ); ?>' />
1191 </div>
1192 <a class="evf-download-file" href="<?php echo esc_url( $attachment_url ); ?>" title="Download" target="_blank" download ><span class="dashicons dashicons-arrow-down-alt"></span></a>
1193 <a class="dz-remove evf-remove-file" href="javascript:undefined;" title="Remove" data-dz-remove="" data-form-id="<?php echo absint( $form_id ); ?>" data-field-name="<?php echo esc_attr( $key ); ?>"></a>
1194 </div>
1195 <?php
1196 }
1197 ?>
1198 <input type="hidden" class="deleted-input" name="<?php echo $delete_input_name; ?>" value='' />
1199 <?php
1200 }
1201 ?>
1202 </div>
1203 <input type="text" class="dropzone-input input-text" id="everest-forms-<?php echo absint( $form_id ); ?>-field_<?php echo esc_attr( $field_id ); ?>" name="<?php echo esc_attr( $input_name ); ?>" <?php echo esc_attr( $required ); ?> conditional_id="<?php echo esc_attr( $conditional_id ); ?>" conditional_rules='<?php echo $conditional_rules; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>'>
1204 <?php
1205 }
1206
1207 /**
1208 * Validates field on form submit.
1209 *
1210 * @param int $field_id Field ID.
1211 * @param array $field_submit Submitted field value.
1212 * @param array $form_data Form data and settings.
1213 */
1214 public function validate( $field_id, $field_submit, $form_data ) {
1215 $this->form_data = (array) $form_data;
1216 $this->form_id = absint( $this->form_data['id'] );
1217 $this->field_id = $field_id;
1218 $this->field_data = $this->form_data['form_fields'][ $this->field_id ];
1219 $entry = isset( $form_data['entry'] ) ? $form_data['entry'] : array();
1220 $visible = apply_filters( 'everest_forms_visible_fields', true, $form_data['form_fields'][ $field_id ], $entry, $form_data );
1221 $required_message = isset( $form_data['form_fields'][ $field_id ]['required-field-message'], $form_data['form_fields'][ $field_id ]['required_field_message_setting'] ) && 'individual' == $form_data['form_fields'][ $field_id ]['required_field_message_setting'] ? $form_data['form_fields'][ $field_id ]['required-field-message'] : get_option( 'everest_forms_required_validation' );
1222
1223 $input_name = sprintf( 'everest_forms_%d_%s', $this->form_id, $this->field_id );
1224
1225 if ( false === $visible || empty( $this->field_data['required'] ) ) {
1226 return;
1227 }
1228
1229 $value = '';
1230 if ( ! empty( $_POST[ $input_name ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
1231 $value = json_decode( wp_unslash( $_POST[ $input_name ] ), true ); // phpcs:ignore WordPress.Security
1232 }
1233
1234 if ( empty( $value ) ) {
1235 evf()->task->errors[ $this->form_id ][ $this->field_id ] = $required_message;
1236 update_option( 'evf_validation_error', 'yes' );
1237 }
1238 }
1239
1240 private function get_file_mime_type( $file_path ) {
1241 if ( function_exists( 'mime_content_type' ) && file_exists( $file_path ) ) {
1242 return mime_content_type( $file_path );
1243 }
1244
1245 $extension = strtolower( pathinfo( $file_path, PATHINFO_EXTENSION ) );
1246 $mime_types = wp_get_mime_types();
1247
1248 return $mime_types[ $extension ] ?? 'application/octet-stream';
1249 }
1250
1251 /**
1252 * Get the local file size
1253 *
1254 * @param [type] $file_path The path.
1255 */
1256 private function get_local_file_size( $file_path ) {
1257 // If it's already a local path
1258 if ( file_exists( $file_path ) ) {
1259 return filesize( $file_path );
1260 }
1261
1262 // Convert URL to local path
1263 $upload_dir = wp_upload_dir();
1264 $local_path = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $file_path );
1265
1266 if ( file_exists( $local_path ) ) {
1267 return filesize( $local_path );
1268 }
1269
1270 // Try remote URL as last resort
1271 if ( filter_var( $file_path, FILTER_VALIDATE_URL ) ) {
1272 $response = wp_remote_head( $file_path );
1273 if ( ! is_wp_error( $response ) && isset( $response['headers']['content-length'] ) ) {
1274 return (int) $response['headers']['content-length'];
1275 }
1276 }
1277
1278 return 0;
1279 }
1280 /**
1281 * Formats and sanitizes field.
1282 *
1283 * @param int $field_id Field ID.
1284 * @param array $field_submit Submitted field value.
1285 * @param array $form_data Form data and settings.
1286 * @param string $meta_key Field Meta Key.
1287 */
1288 public function format( $field_id, $field_submit, $form_data, $meta_key ) {
1289 // Setup class properties to reuse everywhere.
1290 $this->form_data = (array) $form_data;
1291 $this->form_id = absint( $this->form_data['id'] );
1292 $this->field_id = $field_id;
1293 $this->field_data = $this->form_data['form_fields'][ $this->field_id ];
1294
1295 $field_label = ! empty( $this->form_data['form_fields'][ $this->field_id ]['label'] ) ? $this->form_data['form_fields'][ $this->field_id ]['label'] : '';
1296 $input_name = sprintf( 'everest_forms_%d_%s', $this->form_id, $this->field_id );
1297
1298 $processed = array(
1299 'name' => make_clickable( $field_label ),
1300 'value' => '',
1301 'value_raw' => '',
1302 'id' => $this->field_id,
1303 'type' => $this->type,
1304 'meta_key' => $meta_key,
1305 );
1306
1307 // We should actually receive some files info.
1308 $raw_files = isset( $_POST[ $input_name ] ) ? $_POST[ $input_name ] : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing
1309 if ( empty( $raw_files ) ) {
1310 if ( empty( $field_submit ) ) {
1311 evf()->task->form_fields[ $this->field_id ] = $processed;
1312 return;
1313 } else {
1314 // For handle update entry case.
1315 $raw_files = isset( $field_submit['new_files'] ) ? $field_submit['new_files'] : array();
1316 }
1317 }
1318
1319 // Make sure form fields are stored.
1320 if ( ! empty( evf()->task->form_fields[ $this->field_id ] ) ) { // @codingStandardsIgnoreLine
1321 return;
1322 }
1323
1324 $data = array();
1325
1326 if ( ! empty( $raw_files ) ) {
1327 // Make sure json_decode() doesn't fail on newer PHP.
1328 try {
1329 $raw_files = json_decode( wp_unslash( $raw_files ), true ); // phpcs:ignore WordPress.Security
1330 } catch ( Exception $e ) {
1331 evf()->task->form_fields[ $this->field_id ] = $processed;
1332 return;
1333 }
1334
1335 // Make sure we process only submitted files with the expected structure and keys.
1336 $files = array_filter(
1337 $raw_files,
1338 static function ( $file ) {
1339 return ( is_array( $file ) || is_object( $file ) && count( $file ) === 2 ) && ! empty( $file['file'] ) && ! empty( $file['name'] );
1340 }
1341 );
1342
1343 foreach ( $files as $file ) {
1344 $file = $this->generate_file_info( $file );
1345
1346 $wp_filetype = wp_check_filetype_and_ext( $file['tmp_path'], $file['name'] );
1347
1348 $ext = empty( $wp_filetype['ext'] ) ? '' : $wp_filetype['ext'];
1349 $type = empty( $wp_filetype['type'] ) ? '' : $wp_filetype['type'];
1350 $proper_filename = empty( $wp_filetype['proper_filename'] ) ? '' : $wp_filetype['proper_filename'];
1351
1352 if ( $proper_filename || ! $ext || ! $type ) {
1353 evf()->task->errors[ $form_data['id'] ][ $field_id ] = esc_html__( 'File type is not allowed.', 'everest-forms' );
1354 update_option( 'evf_validation_error', 'yes' );
1355 wp_die( 'File type is not allowed' );
1356 }
1357
1358 // Allow third-party integrations.
1359 if ( has_filter( 'everest_forms_integration_uploads' ) ) {
1360 $file = apply_filters( 'everest_forms_integration_uploads', $file, $this->form_data );
1361 }
1362
1363 if ( $this->is_media_integrated() ) {
1364 $file['path'] = $file['tmp_path'];
1365
1366 $file = $this->generate_file_attachment( $file );
1367 } elseif (
1368 ! isset( $file['external'] )
1369 && file_exists( $file['tmp_path'] )
1370 ) {
1371
1372 $this->create_dir( dirname( $file['path'] ) );
1373 @rename( $file['tmp_path'], $file['path'] ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
1374 $this->set_file_fs_permissions( $file['path'] );
1375 }
1376
1377 $data[] = $this->generate_file_data( $file );
1378 }
1379 }
1380
1381 if ( isset( $field_submit['old_files'] ) && is_array( $field_submit['old_files'] ) ) {
1382
1383 $validated_old_data = array();
1384
1385 foreach ( $field_submit['old_files'] as $file ) {
1386 $decoded = json_decode( $file, true );
1387
1388 if ( ! is_array( $decoded ) || empty( $decoded['value'] ) || ! is_string( $decoded['value'] ) ) {
1389 continue;
1390 }
1391
1392 $resolved_path = $this->resolve_uploads_file_from_url( $decoded['value'] );
1393
1394 if ( false === $resolved_path ) {
1395 continue;
1396 }
1397
1398 $decoded['value'] = esc_url_raw( $decoded['value'] );
1399 $validated_old_data[] = $decoded;
1400 }
1401
1402 if ( ! empty( $validated_old_data ) ) {
1403 $data = array_merge( $data, $validated_old_data );
1404 }
1405 }
1406
1407 if ( ! empty( $data ) ) {
1408 $mapped_value = array_map(
1409 function ( $file ) {
1410 return $file['value'];
1411 },
1412 $data
1413 );
1414 $mapped_value = implode( "\n", $mapped_value );
1415 $processed = wp_parse_args(
1416 array(
1417 'value_raw' => $data,
1418 'value' => $mapped_value,
1419 ),
1420 $processed
1421 );
1422 }
1423
1424 evf()->task->form_fields[ $this->field_id ] = $processed;
1425 }
1426
1427 /**
1428 * Generate a ready for DB data for each file.
1429 *
1430 * @since 1.3.0
1431 *
1432 * @param array $file File to generate data for.
1433 *
1434 * @return array
1435 */
1436 protected function generate_file_data( $file ) {
1437 $field_label = ! empty( $this->form_data['form_fields'][ $this->field_id ]['label'] ) ? $this->form_data['form_fields'][ $this->field_id ]['label'] : '';
1438 $file['name'] = apply_filters( 'everest_forms_upload_file_name', sanitize_text_field( $file['name'] ), $field_label );
1439 $file_path = $file['path'];
1440
1441 if ( isset( $this->form_data['settings']['dropbox_enabled'] ) && 1 === $this->form_data['settings']['dropbox_enabled'] && ! file_exists( $file_path ) ) {
1442 evf()->task->errors[ $this->form_id ][ $this->field_id ] = __( 'Something went wrong while uploading file,Please try again', 'everest-forms' );
1443 update_option( 'evf_validation_error', 'yes' );
1444 }
1445
1446 return array(
1447 'name' => sanitize_text_field( $file['name'] ),
1448 'value' => esc_url_raw( $file['file_url'] ),
1449 'file' => $file['file_name_new'],
1450 'file_original' => $file['name'],
1451 'ext' => pathinfo( $file['name'], PATHINFO_EXTENSION ),
1452 'attachment_id' => isset( $file['attachment_id'] ) ? absint( $file['attachment_id'] ) : 0,
1453 'id' => $this->field_id,
1454 'type' => $file['type'],
1455 );
1456 }
1457
1458 /**
1459 * Add additional information to the files array for each file.
1460 *
1461 * @since 1.3.0
1462 *
1463 * @param array $file Submitted file basic info.
1464 */
1465 protected function generate_file_info( $file ) {
1466 $dir = $this->get_form_files_dir();
1467 $file['tmp_path'] = trailingslashit( $this->get_tmp_dir() ) . sanitize_file_name( $file['file'] );
1468 $file['type'] = 'application/octet-stream';
1469 if ( is_file( $file['tmp_path'] ) ) {
1470 $filetype = wp_check_filetype( $file['tmp_path'] );
1471 $file['type'] = $filetype['type'];
1472 }
1473
1474 // Data for no media case.
1475 $file_ext = pathinfo( $file['name'], PATHINFO_EXTENSION );
1476
1477 if ( ! empty( $this->field_data['custom_file_name'] ) ) {
1478 $processed_custom_name = apply_filters( 'everest_forms_process_smart_tags', $this->field_data['custom_file_name'], $this->form_data, evf()->task->form_fields );
1479 $file_base = sanitize_file_name( $processed_custom_name );
1480 } else {
1481 $file_base = wp_basename( $file['name'], ".$file_ext" );
1482 }
1483
1484 $file['file_name_new'] = apply_filters(
1485 'everest_forms_modify_file_name',
1486 sprintf('%s-%s.%s', $file_base, wp_hash($dir['path'] . $this->form_data['id'] . $this->field_id), strtolower($file_ext)),
1487 $file_base,
1488 $file_ext
1489 );
1490 $file['file_name_new'] = wp_unique_filename( trailingslashit( $dir['path'] ), sanitize_file_name( $file['file_name_new'] ) );
1491 $file['file_url'] = trailingslashit( $dir['url'] ) . $file['file_name_new'];
1492 $file['path'] = trailingslashit( $dir['path'] ) . $file['file_name_new'];
1493 $file['attachment_id'] = 0;
1494
1495 return $file;
1496 }
1497
1498 /**
1499 * Whether field is integrated with WordPress Media Library.
1500 *
1501 * @uses $this->field_data
1502 *
1503 * @since 1.3.0
1504 */
1505 protected function is_media_integrated() {
1506 return ! empty( $this->field_data['media_library'] ) && '1' === $this->field_data['media_library'];
1507 }
1508
1509 /**
1510 * Get form-specific uploads directory path and URL.
1511 *
1512 * @since 1.3.0
1513 */
1514 protected function get_form_files_dir() {
1515 $uploads = wp_upload_dir();
1516 $folder = absint( $this->form_data['id'] ) . '-' . wp_hash( $this->form_data['id'] . $this->form_data['created'] );
1517
1518 return array(
1519 'path' => "{$uploads['basedir']}/everest_forms_uploads/{$folder}",
1520 'url' => "{$uploads['baseurl']}/everest_forms_uploads/{$folder}",
1521 );
1522 }
1523
1524 /**
1525 * Create a Media Library attachment.
1526 *
1527 * @since 1.3.0
1528 *
1529 * @param array $file File to create Media Library attachment for.
1530 *
1531 * @return array
1532 */
1533 protected function generate_file_attachment( $file ) {
1534 // Include necessary code from core.
1535 require_once ABSPATH . 'wp-admin/includes/media.php';
1536 require_once ABSPATH . 'wp-admin/includes/file.php';
1537 require_once ABSPATH . 'wp-admin/includes/image.php';
1538
1539 $file_args = array(
1540 'error' => '',
1541 'tmp_name' => $file['path'],
1542 'name' => $file['file_name_new'],
1543 'type' => $file['type'],
1544 );
1545 $upload = wp_handle_sideload( $file_args, array( 'test_form' => false ) );
1546
1547 if ( empty( $upload['file'] ) ) {
1548 return $file;
1549 }
1550
1551 // Create a Media attachment for the file.
1552 $attachment_id = wp_insert_attachment(
1553 array(
1554 'post_title' => $this->field_data['label'],
1555 'post_status' => 'publish',
1556 'post_mime_type' => $file['type'],
1557 ),
1558 $upload['file']
1559 );
1560
1561 if ( empty( $attachment_id ) ) {
1562 return $file;
1563 }
1564
1565 // Generate and update attachment meta.
1566 wp_update_attachment_metadata(
1567 $attachment_id,
1568 wp_generate_attachment_metadata( $attachment_id, $upload['file'] )
1569 );
1570
1571 // Update file information.
1572 $file_url = wp_get_attachment_url( $attachment_id );
1573 $file['path'] = $upload['file'];
1574 $file['file_url'] = $file_url;
1575 $file['file_name_new'] = wp_basename( $file_url );
1576 $file['attachment_id'] = $attachment_id;
1577
1578 return $file;
1579 }
1580
1581 /**
1582 * Determine max file size allowed.
1583 *
1584 * @return int Number of bytes allowed.
1585 */
1586 public function max_file_size() {
1587 if ( ! empty( $this->field_data['max_size'] ) ) {
1588 // Strip any suffix provided (eg M, MB etc), which leaves is wit the raw MB value.
1589 $max_size = preg_replace( '/[^0-9.]/', '', $this->field_data['max_size'] );
1590 $max_size = evf_size_to_bytes( $max_size . 'M' );
1591 } else {
1592 $max_size = evf_max_upload( true );
1593 }
1594
1595 return $max_size;
1596 }
1597
1598 /**
1599 * Send File as email attachment.
1600 *
1601 * @param string $attachment Attachment enable parameter.
1602 * @param integer $entry Form entry data object.
1603 * @param array $form_data Form data with field params.
1604 * @param string $context Context for the render, email or backend.
1605 * @param integer $connection_id Connection id for the attachment.
1606 * @param integer $entry_id Entry id for the form.
1607 */
1608 public function send_file_as_email_attachment( $attachment, $entry, $form_data, $context, $connection_id, $entry_id ) {
1609
1610 $file_email_attachments = isset( $form_data['settings']['email'][ $connection_id ]['file-email-attachments'] ) ? $form_data['settings']['email'][ $connection_id ]['file-email-attachments'] : 0;
1611 if ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] && '1' === $file_email_attachments ) {
1612 $attachment = $this->attach_entry_files_upload( $entry );
1613 } elseif ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] && ! defined( 'EFP_PLUGIN_FILE' ) ) {
1614 $attachment = $this->attach_entry_files_upload( $entry );
1615 }
1616
1617 if ( '1' === $file_email_attachments ) {
1618 $attachment = array_unique( array_merge( (array) $attachment, $this->attach_entry_files( $entry_id ) ) );
1619 return $attachment;
1620 }
1621
1622 return $attachment;
1623 }
1624
1625 /**
1626 * Send CSV file as email attachment.
1627 *
1628 * @param string $attachment Attachment enable parameter.
1629 * @param integer $entry Form entry data object.
1630 * @param array $form_data Form data with field params.
1631 * @param string $context Context for the render, email or backend.
1632 * @param integer $connection_id Connection id for the attachment.
1633 * @param integer $entry_id Entry id for the form.
1634 */
1635 public function send_csv_file_as_email_attachment( $attachment, $entry, $form_data, $context, $connection_id, $entry_id ) {
1636
1637 $csv_file_email_attachments = isset( $form_data['settings']['email'][ $connection_id ]['csv-file-email-attachments'] ) ? $form_data['settings']['email'][ $connection_id ]['csv-file-email-attachments'] : 0;
1638 if ( '1' !== $csv_file_email_attachments ) {
1639 return $attachment;
1640 }
1641 $attachment = array_merge( (array) $attachment, $this->csv_entry_files( $entry_id ) );
1642 return $attachment;
1643 }
1644
1645 /**
1646 * Remove CSV file attachment after email sent.
1647 *
1648 * @param string $attachment Attachment enable parameter.
1649 * @param integer $entry Form entry data object.
1650 * @param array $form_data Form data with field params.
1651 * @param string $context Context for the render, email or backend.
1652 * @param integer $connection_id Connection id for the attachment.
1653 * @param integer $entry_id Entry id for the form.
1654 */
1655 public function remove_csv_file_after_email_send( $attachment, $entry, $form_data, $context, $connection_id, $entry_id ) {
1656
1657 if ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] ) {
1658 if ( ! empty( $entry ) && is_array( $entry ) ) {
1659 foreach ( $entry as $meta_key => $meta_value ) {
1660 if ( empty( $meta_value ) ) {
1661 continue;
1662 }
1663
1664 if ( preg_match( '/signature_/', $meta_key ) && file_exists( $meta_value ) ) {
1665 unlink( $meta_value );
1666 }
1667
1668 if ( isset( $meta_value['type'] ) && ( 'file-upload' === $meta_value['type'] && ! empty( $meta_value['value_raw'] ) || 'image-upload' === $meta_value['type'] && isset( $meta_value['value_raw'] ) ) ) {
1669
1670 foreach ( $meta_value['value_raw'] as $file_data ) {
1671 if ( isset( $file_data['value'] ) ) {
1672 $file_url = $file_data['value'];
1673
1674 $uploaded_file = ABSPATH . preg_replace( '/.*wp-content/', 'wp-content', wp_parse_url( $file_url, PHP_URL_PATH ) );
1675 if ( file_exists( $uploaded_file ) ) {
1676 unlink( $uploaded_file );
1677 }
1678 }
1679 }
1680 }
1681 }
1682 }
1683 }
1684
1685 if ( ! $entry_id ) {
1686 return;
1687 }
1688
1689 $file_email_attachments = isset( $form_data['settings']['email'][ $connection_id ]['file-email-attachments'] ) ? $form_data['settings']['email'][ $connection_id ]['file-email-attachments'] : 0;
1690 $csv_file_email_attachments = isset( $form_data['settings']['email'][ $connection_id ]['csv-file-email-attachments'] ) ? $form_data['settings']['email'][ $connection_id ]['csv-file-email-attachments'] : 0;
1691 $csv_file_email_attachments = apply_filters( 'everest_forms_change_csv_attachments', $csv_file_email_attachments );
1692
1693 if ( '1' === $csv_file_email_attachments ) {
1694 $upload_dir = WP_CONTENT_DIR . '/uploads/Everes-Froms-Entries-CSV-file/';
1695 $csv_path = $upload_dir . 'Entry data-' . $entry_id . '.csv';
1696 if ( file_exists( $csv_path ) ) {
1697 unlink( $csv_path );
1698 }
1699 }
1700 }
1701
1702 /**
1703 * Attach the entry file.
1704 *
1705 * @param int $entry_id Entry ID for which file should be attached.
1706 */
1707 public function attach_entry_files( $entry_id ) {
1708 $entry_files = array();
1709 if ( $entry_id ) {
1710 $get_entry = evf_get_entry( $entry_id, 'meta' );
1711 }
1712
1713 if ( ! empty( $get_entry->meta ) ) {
1714 foreach ( $get_entry->meta as $meta_key => $meta_value ) {
1715 if ( empty( $meta_value ) ) {
1716 continue;
1717 }
1718
1719 if ( preg_match( '/signature_/', $meta_key ) ) {
1720 if ( file_exists( $meta_value ) ) {
1721 $entry_files [] = $meta_value;
1722 }
1723 } else {
1724 $files = explode( "\n", $meta_value );
1725
1726 foreach ( $files as $file ) {
1727 $resolved = $this->resolve_uploads_file_from_url( $file );
1728
1729 if ( false !== $resolved && ! in_array( $resolved, $entry_files, true ) ) {
1730 $entry_files[] = $resolved;
1731 }
1732 }
1733 }
1734 }
1735 }
1736
1737 return $entry_files;
1738 }
1739
1740 /**
1741 * Attach the entry file.
1742 *
1743 * @param int $entry Entry for which file should be attached.
1744 */
1745 public function attach_entry_files_upload( $entry ) {
1746 $entry_files = array();
1747
1748 if ( ! empty( $entry ) && is_array( $entry ) ) {
1749 foreach ( $entry as $meta_key => $meta_value ) {
1750 if ( empty( $meta_value ) ) {
1751 continue;
1752 }
1753
1754 if ( preg_match( '/signature_/', $meta_key ) ) {
1755 if ( file_exists( $meta_value ) ) {
1756 $entry_files[] = $meta_value;
1757 }
1758 } elseif ( isset( $meta_value['type'] ) && ( 'file-upload' === $meta_value['type'] && ! empty( $meta_value['value_raw'] ) || 'image-upload' === $meta_value['type'] && isset( $meta_value['value_raw'] ) ) ) {
1759 foreach ( $meta_value['value_raw'] as $file_data ) {
1760 $file_url = isset( $file_data['value'] ) && is_string( $file_data['value'] ) ? $file_data['value'] : '';
1761 $resolved = $this->resolve_uploads_file_from_url( $file_url );
1762
1763 if ( false !== $resolved && ! in_array( $resolved, $entry_files, true ) ) {
1764 $entry_files[] = $resolved;
1765 }
1766 }
1767 }
1768 }
1769 }
1770
1771 return $entry_files;
1772 }
1773
1774
1775 /**
1776 * Resolve a file URL to a real local uploads path.
1777 *
1778 * Validates that the URL belongs to this site's uploads directory and that
1779 * the resolved real path stays within that directory (no traversal). Returns
1780 * the canonical filesystem path on success, or false on failure.
1781 *
1782 * @param string $file_url File URL to resolve.
1783 * @return string|false
1784 */
1785 protected function resolve_uploads_file_from_url( $file_url ) {
1786 if ( empty( $file_url ) || ! is_string( $file_url ) ) {
1787 return false;
1788 }
1789
1790 $file_url = esc_url_raw( $file_url );
1791 $upload_dir = wp_get_upload_dir();
1792 $uploads_baseurl = trailingslashit( $upload_dir['baseurl'] );
1793 $uploads_basedir = wp_normalize_path( trailingslashit( $upload_dir['basedir'] ) );
1794
1795 if ( 0 !== strpos( $file_url, $uploads_baseurl ) ) {
1796 return false;
1797 }
1798
1799 $path = wp_parse_url( $file_url, PHP_URL_PATH );
1800 $base_path = wp_parse_url( $uploads_baseurl, PHP_URL_PATH );
1801
1802 if ( ! is_string( $path ) || ! is_string( $base_path ) || 0 !== strpos( $path, $base_path ) ) {
1803 return false;
1804 }
1805
1806 $relative_path = ltrim( substr( $path, strlen( $base_path ) ), '/' );
1807 $candidate = wp_normalize_path( $uploads_basedir . $relative_path );
1808 $resolved_path = realpath( $candidate );
1809
1810 if ( false === $resolved_path ) {
1811 return false;
1812 }
1813
1814 $resolved_path = wp_normalize_path( $resolved_path );
1815
1816 if ( 0 !== strpos( $resolved_path, $uploads_basedir ) || ! is_file( $resolved_path ) ) {
1817 return false;
1818 }
1819
1820 return $resolved_path;
1821 }
1822
1823 /**
1824 * Attach the csv file.
1825 *
1826 * @param int $entry_id Entry ID for which file should be attached.
1827 */
1828 public function csv_entry_files( $entry_id ) {
1829 $csv_entry_file = array();
1830 if ( $entry_id ) {
1831 $get_entry = evf_get_entry( $entry_id, 'meta' );
1832 }
1833
1834 if ( ! empty( $get_entry->meta ) ) {
1835 include_once EVF_ABSPATH . 'includes/export/class-evf-entry-csv-exporter.php';
1836 include_once EFP_ABSPATH . 'includes/export/class-evf-entry-exporter.php';
1837
1838 $exporter = new EVF_Entry_CSV_Exporter( $get_entry->form_id, $get_entry->entry_id, array() );
1839 $column_names = $exporter->get_default_column_names();
1840 $row_data = $exporter->prepare_data_to_export();
1841
1842 $keys_to_remove = array(
1843 'status',
1844 'date_created',
1845 'date_created_gmt',
1846 'user_device',
1847 'user_ip_address',
1848 );
1849
1850 foreach ( $keys_to_remove as $key ) {
1851 unset( $column_names[ $key ] );
1852 unset( $row_data[0][ $key ] );
1853 }
1854
1855 $csv_entry_data = implode( ',', $column_names ) . "\n";
1856 foreach ( $row_data[0] as $row_value ) {
1857 $csv_entry_data .= '"' . $row_value . '",';
1858 }
1859
1860 // WordPress upload folder path.
1861 $upload_dir = WP_CONTENT_DIR . '/uploads/Everes-Froms-Entries-CSV-file/';
1862 if ( ! is_dir( $upload_dir ) ) {
1863 mkdir( $upload_dir, 0755, true );
1864 file_put_contents( $upload_dir . '.htaccess', "deny from all\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
1865 file_put_contents( $upload_dir . 'index.php', "<?php\n// Silence is golden.\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
1866 }
1867 $csv_path = $upload_dir . 'Entry data-' . $get_entry->entry_id . '.csv';
1868
1869 // Save CSV file.
1870 if ( file_put_contents( $csv_path, $csv_entry_data ) !== false ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
1871 array_push( $csv_entry_file, $csv_path );
1872 }
1873 /**
1874 * Enable SSL Certificate verification.
1875 */
1876 $context_options = array(
1877 'ssl' => array(
1878 'verify_peer' => true,
1879 'verify_peer_name' => true,
1880 ),
1881 );
1882 stream_context_set_default( $context_options );
1883 }
1884
1885 return $csv_entry_file;
1886 }
1887
1888
1889 /**
1890 * Return upload validation errors messages.
1891 *
1892 * @since 1.3.1
1893 *
1894 * @param int|string $error PHP file upload error code.
1895 *
1896 * @return array|string|boolean Get validationr message
1897 */
1898 protected function get_upload_validation_errors( $error = null ) {
1899 $errors = apply_filters(
1900 'evf_upload_validation_errors',
1901 array(
1902 UPLOAD_ERR_INI_SIZE => esc_html__( 'The uploaded file exceeds the upload_max_filesize directive in php.ini.', 'everest-forms' ),
1903 UPLOAD_ERR_FORM_SIZE => esc_html__( 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', 'everest-forms' ),
1904 UPLOAD_ERR_PARTIAL => esc_html__( 'The uploaded file was only partially uploaded.', 'everest-forms' ),
1905 UPLOAD_ERR_NO_FILE => esc_html__( 'No file was uploaded.', 'everest-forms' ),
1906 UPLOAD_ERR_NO_TMP_DIR => esc_html__( 'Missing a temporary folder.', 'everest-forms' ),
1907 UPLOAD_ERR_CANT_WRITE => esc_html__( 'Failed to write file to disk.', 'everest-forms' ),
1908 UPLOAD_ERR_EXTENSION => esc_html__( 'File upload stopped by extension.', 'everest-forms' ),
1909 )
1910 );
1911
1912 if ( null === $error ) {
1913 return $errors;
1914 }
1915
1916 if ( isset( $errors[ $error ] ) ) {
1917 return $errors[ $error ];
1918 }
1919
1920 return true;
1921 }
1922 }
1923