PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.0
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.0
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
profile-builder / front-end / default-fields / upload / upload_helper_functions.php

upload_helper_functions.php in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 4.0.0, at front-end/default-fields/upload/upload_helper_functions.php

655 lines 33.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly
3 if ( ! defined( 'ABSPATH' ) ) exit;
4
5 /* Set up upload field for frontend */
6 /* overwrite the two functions for when an upload is made from the frontend so they don't check for a logged in user */
7 if( strpos( wp_get_referer(), 'wp-admin' ) === false && isset( $_REQUEST['action'] ) && 'upload-attachment' == $_REQUEST['action'] ){
8
9 if( isset( $_REQUEST['wppb_upload'] ) && 'true' == $_REQUEST['wppb_upload'] &&
10 isset( $_REQUEST['meta_name'] ) && wppb_check_that_field_is_defined( sanitize_text_field( $_REQUEST['meta_name'] ), array( 'Avatar', 'Upload' ) ) ){
11
12 if( !function_exists( 'check_ajax_referer' ) ){
13 function check_ajax_referer( ) {
14 return true;
15 }
16 }
17
18 if( !function_exists( 'auth_redirect' ) ){
19 function auth_redirect() {
20 return true;
21 }
22 }
23
24 }
25
26 }
27
28 /* Front-end Avatar/Upload async-upload bypass when the real user lacks upload caps.
29 * Guests use WP_User(0) (author-less until registration). Logged-in users keep their ID
30 * and only gain temporary caps so the attachment is owned by them (see wppb_verify_attachment_id). */
31 add_action( 'current_screen', 'wppb_create_fake_user_when_uploading_and_not_logged_in' );
32 if( !function_exists( 'wppb_create_fake_user_when_uploading_and_not_logged_in' ) ) {
33 function wppb_create_fake_user_when_uploading_and_not_logged_in() {
34 // don't do anything if this request is coming from the back-end
35 if( !( strpos( wp_get_referer(), 'wp-admin' ) === false ) )
36 return;
37
38 if ( isset($_REQUEST['action']) && 'upload-attachment' == $_REQUEST['action'] &&
39 isset($_REQUEST['wppb_upload']) && 'true' == $_REQUEST['wppb_upload'] &&
40 isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( $_REQUEST['_wpnonce'] ), 'media-form' ) &&
41 isset( $_REQUEST['meta_name'] ) && wppb_check_that_field_is_defined( sanitize_text_field( $_REQUEST['meta_name'] ), array( 'Avatar', 'Upload' ) ) ) {
42
43 if ( !is_user_logged_in() || !current_user_can( 'upload_files' ) || !current_user_can( 'edit_posts' ) ) {
44 global $current_user;
45
46 $upload_caps = array(
47 'upload_files' => true,
48 'edit_posts' => true,
49 'edit_others_posts' => true,
50 'edit_pages' => true,
51 'edit_others_pages' => true,
52 );
53
54 if ( is_user_logged_in() ) {
55 $current_user->allcaps = array_merge( (array) $current_user->allcaps, $upload_caps );
56 } else {
57 $current_user = new WP_User( 0, 'frontend_uploader' );
58 $current_user->allcaps = $upload_caps;
59 }
60 }
61 }
62 }
63 }
64
65 /* for a request of a upload from the frontend and no user is logged in don't query for attachments */
66 add_action( 'after_setup_theme', 'wppb_modify_query_attachements_when_not_logged_in' );
67 if( !function_exists( 'wppb_modify_query_attachements_when_not_logged_in' ) ) {
68 function wppb_modify_query_attachements_when_not_logged_in()
69 {
70 if ( strpos(wp_get_referer(), 'wp-admin') === false && !is_user_logged_in() ) {
71 add_action('wp_ajax_query-attachments', 'wppb_wp_ajax_not_loggedin_query_attachments', 0);
72 add_action('wp_ajax_nopriv_query-attachments', 'wppb_wp_ajax_not_loggedin_query_attachments', 0);
73 function wppb_wp_ajax_not_loggedin_query_attachments()
74 {
75 wp_send_json_success();
76 }
77 }
78 }
79 }
80
81 /* restrict file types of the upload field functionality */
82 add_filter('wp_handle_upload_prefilter', 'wppb_upload_file_type');
83 if( !function_exists( 'wppb_upload_file_type' ) ) {
84 function wppb_upload_file_type($file)
85 {
86 if( isset( $_POST['wppb_upload'] ) && $_POST['wppb_upload'] == 'true' && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( $_POST['_wpnonce'] ), 'media-form' ) ) {
87
88 // file size limits.
89 $size = $file['size'];
90 $limit = apply_filters('wppb_server_max_upload_size_byte_constant', wppb_return_bytes(ini_get('upload_max_filesize')));
91 if ( $size > $limit ) {
92 $limit = $limit / ( 1024 * 1024 ) ;
93 $file['error'] = __("Files must be smaller than ", "profile-builder") . $limit . 'MB';
94 }
95
96 if (isset($_POST['meta_name']) && !empty($_POST['meta_name'])) {
97 $meta_name = sanitize_text_field( $_POST['meta_name'] );
98 /*let's get the field details so we can see if we have any file restrictions */
99 $all_fields = apply_filters( 'wppb_form_fields', get_option('wppb_manage_fields'), array( 'context' => 'upload_helper', 'upload_meta_name' => $meta_name ) );
100 if (!empty($all_fields)) {
101 foreach ($all_fields as $field) {
102 if ($field['meta-name'] == $meta_name) {
103
104 // per-field file size limit
105 if ( !empty( $field['max-file-size'] ) && is_numeric( $field['max-file-size'] ) && floatval( $field['max-file-size'] ) > 0 ) {
106 $field_limit = floatval( $field['max-file-size'] ) * 1024 * 1024;
107 $effective_limit = min( $field_limit, $limit );
108 if ( $size > $effective_limit ) {
109 $file['error'] = __( "Files must be smaller than ", "profile-builder" ) . floatval( $field['max-file-size'] ) . 'MB';
110 return $file;
111 }
112 }
113
114 $allowed_upload_extensions = '';
115
116 if ($field['field'] == 'Upload' && !empty($field['allowed-upload-extensions']))
117 $allowed_upload_extensions = $field['allowed-upload-extensions'];
118 if ($field['field'] == 'Avatar' && !empty($field['allowed-image-extensions'])) {
119 if (trim($field['allowed-image-extensions']) == '.*')
120 $allowed_upload_extensions = '.jpg,.jpeg,.gif,.png,.ico';
121 else
122 $allowed_upload_extensions = $field['allowed-image-extensions'];
123 }
124
125 $ext = strtolower( substr(strrchr($file['name'], '.'), 1) );
126
127 if (!empty($allowed_upload_extensions) && $allowed_upload_extensions != '.*') {
128 $allowed = str_replace('.', '', array_map('trim', explode(",", strtolower( $allowed_upload_extensions))));
129 //first check if the user uploaded the right type
130 if (!in_array($ext, (array)$allowed)) {
131 $file['error'] = __("Sorry, you cannot upload this file type for this field.", 'profile-builder');
132 return $file;
133 }
134 }
135
136 //check if the type is allowed at all by WordPress
137 foreach (get_allowed_mime_types() as $key => $value) {
138 if (strpos($key, $ext) !== false || $key == $ext)
139 return $file;
140 }
141
142 $file['error'] = __("Sorry, you cannot upload this file type for this field.", 'profile-builder');
143
144 break;
145 }
146 }
147 }
148 }
149
150 if (empty($_POST['meta_name']))
151 $file['error'] = __("An error occurred, please try again later.", 'profile-builder');
152 }
153
154 return $file;
155 }
156 }
157
158 /**
159 * Function that performs validation for the simple upload field
160 *
161 * @param $field - simple upload field
162 * @param $upload - data to be uploaded
163 *
164 * @return bool
165 */
166 function wppb_valid_simple_upload( $field, $upload ){
167 $limit = apply_filters( 'wppb_server_max_upload_size_byte_constant', wppb_return_bytes( ini_get( 'upload_max_filesize' ) ) );
168 $allowed_mime_types = get_allowed_mime_types();
169 $all_fields = apply_filters( 'wppb_form_fields', get_option( 'wppb_manage_fields' ), array( 'context' => 'upload_helper', 'upload_meta_name' => $field[ 'meta-name' ] ) );
170 if ( !empty( $all_fields ) ) {
171 foreach ( $all_fields as $form_field ) {
172 if ($form_field[ 'meta-name' ] == $field[ 'meta-name' ] ) {
173 // apply per-field size limit if set
174 if ( !empty( $form_field['max-file-size'] ) && is_numeric( $form_field['max-file-size'] ) && floatval( $form_field['max-file-size'] ) > 0 ) {
175 $field_limit = floatval( $form_field['max-file-size'] ) * 1024 * 1024;
176 $limit = min( $field_limit, $limit );
177 }
178 $allowed_upload_extensions = '';
179 if ( $form_field[ 'field' ] == 'Upload' && !empty( $form_field[ 'allowed-upload-extensions' ] ) ) {
180 $allowed_upload_extensions = $form_field[ 'allowed-upload-extensions' ];
181 }
182 if ( $form_field[ 'field' ] == 'Avatar' ) {
183 if ( trim( $field[ 'allowed-image-extensions' ] ) == '.*' || trim( $field[ 'allowed-image-extensions' ] ) == '' ) {
184 $allowed_upload_extensions = '.jpg,.jpeg,.gif,.png';
185 }
186 else {
187 $allowed_upload_extensions = $form_field[ 'allowed-image-extensions' ];
188 }
189 }
190 if ( !empty( $allowed_upload_extensions ) && $allowed_upload_extensions != '.*' ) {
191 $allowed_upload_extensions = str_replace( '.', '', array_map( 'trim', explode( ",", strtolower( $allowed_upload_extensions ) ) ) );
192 } else {
193 $allowed = true;
194 }
195 $allowed_by_wordpress = false;
196 foreach ( $allowed_mime_types as $key => $val ){
197 if ( $val == $upload[ 'type' ] ){
198 $possible_extensions = explode( '|', $key );
199 $allowed_by_wordpress = true;
200 }
201 }
202 if ( isset( $possible_extensions ) && $allowed_by_wordpress == true ){
203 if ( !isset( $allowed ) ){
204 $allowed = false;
205 foreach ( $allowed_upload_extensions as $extension ){
206 if ( in_array( $extension, $possible_extensions ) ){
207 $allowed = true;
208 }
209 }
210 }
211 if ( $upload[ 'size' ] > $limit ){
212 $allowed = false;
213 }
214 return $allowed;
215 }
216 else{
217 return false;
218 }
219 }
220 }
221 }
222 }
223
224 /**
225 * Function that registers intermediate avatar sizes
226 *
227 * @param $field - avatar field
228 *
229 */
230 function wppb_add_avatar_sizes( $field ){
231 if( !empty( $field['avatar-size'] ) )
232 add_image_size( 'wppb-avatar-size-'.$field['avatar-size'], $field['avatar-size'], $field['avatar-size'], true );
233 else
234 add_image_size( 'wppb-avatar-size-100', 100, 100, true );
235
236 add_image_size( 'wppb-avatar-size-64', 64, 64, true );
237 add_image_size( 'wppb-avatar-size-26', 26, 26, true );
238 }
239
240 //Function that registers avatar sizes for userlisting
241 function wppb_userlisting_avatar(){
242 $userlisting_posts = get_posts( array( 'posts_per_page' => -1, 'post_status' =>'publish', 'post_type' => 'wppb-ul-cpt', 'orderby' => 'post_date', 'order' => 'ASC' ) );
243 if( !empty( $userlisting_posts ) ){
244 foreach ( $userlisting_posts as $post ){
245 $this_form_settings = get_post_meta( $post->ID, 'wppb_ul_page_settings', true );
246 $all_userlisting_avatar_size = apply_filters( 'all_userlisting_avatar_size', ( isset( $this_form_settings[0]['avatar-size-all-userlisting'] ) ? (int)$this_form_settings[0]['avatar-size-all-userlisting'] : 100 ) );
247 $single_userlisting_avatar_size = apply_filters( 'single_userlisting_avatar_size', ( isset( $this_form_settings[0]['avatar-size-single-userlisting'] ) ? (int)$this_form_settings[0]['avatar-size-single-userlisting'] : 100 ) );
248
249 add_image_size( 'wppb-avatar-size-'.$all_userlisting_avatar_size, $all_userlisting_avatar_size, $all_userlisting_avatar_size, true );
250 add_image_size( 'wppb-avatar-size-'.$single_userlisting_avatar_size, $single_userlisting_avatar_size, $single_userlisting_avatar_size, true );
251 }
252 }
253 }
254
255 /**
256 * Function that checks if the simple upload field belongs to a repeater field with conditional logic enabled
257 *
258 * @param $field - simple upload field
259 *
260 * @return bool
261 */
262 function wppb_belongs_to_repeater_with_conditional_logic( $field ){
263 $all_fields = apply_filters( 'wppb_form_fields', get_option( 'wppb_manage_fields' ), array( 'context' => 'upload_helper', 'upload_meta_name' => $field[ 'meta-name' ] ) );
264 if ( !empty( $all_fields ) ) {
265 foreach ( $all_fields as $form_field ) {
266 if ( $form_field[ 'field' ] == 'Repeater' && isset( $form_field[ 'conditional-logic-enabled' ] ) && $form_field[ 'conditional-logic-enabled' ] == 'yes' ) {
267 $repeater_group = get_option( $form_field[ 'meta-name' ], 'not_set' );
268 if ( $repeater_group == 'not_set' ) {
269 continue;
270 }
271 else{
272 $repeater_count = count( $repeater_group );
273 for ( $i = 0; $i < $repeater_count; $i++ ){
274 if ( $repeater_group[ $i ][ 'field' ] == 'Upload' && isset( $repeater_group[ $i ][ 'simple-upload' ] ) && $repeater_group[ $i ][ 'simple-upload' ] == 'yes' && isset( $_REQUEST[ $form_field[ 'meta-name' ] . '_extra_groups_count' ] ) ){
275 $groups = absint( $_REQUEST[ $form_field[ 'meta-name' ] . '_extra_groups_count' ] );
276 for ( $j = 0; $j <= $groups; $j++ ){
277 $name = $repeater_group[ $i ][ 'meta-name' ];
278 if ( $j != 0 ){
279 $name .= '_' . $j;
280 }
281 if ( $field[ 'meta-name' ] == $name ){
282 return true;
283 }
284 }
285 }
286 }
287 }
288 }
289 }
290 }
291 return false;
292 }
293
294 function wppb_default_fields_make_upload_button( $field, $input_value, $extra_attr = '' ){
295 // change the upload limit displayed in the upload window (per-field aware)
296 $per_field_max = $field;
297 add_filter('upload_size_limit', function($wp_limit) use ($per_field_max) {
298 $server_limit = apply_filters('wppb_server_max_upload_size_byte_constant', wppb_return_bytes(ini_get('upload_max_filesize')));
299 if ( !empty( $per_field_max['max-file-size'] ) && is_numeric( $per_field_max['max-file-size'] ) && floatval( $per_field_max['max-file-size'] ) > 0 ) {
300 $field_limit = floatval( $per_field_max['max-file-size'] ) * 1024 * 1024;
301 return min( $field_limit, $server_limit );
302 }
303 return $server_limit;
304 }, 10, 1);
305
306 $upload_button = '';
307 $upload_input_id = str_replace( '-', '_', Wordpress_Creation_Kit_PB::wck_generate_slug( $field['meta-name'] ) );
308
309 /* container for the image preview (or file ico) and name and file type */
310 if( !empty( $input_value ) ){
311 /* it can hold multiple attachments separated by comma */
312 $values = explode( ',', $input_value );
313 foreach( $values as $value ) {
314 if( !empty( $value ) && is_numeric( $value ) ){
315 $thumbnail = wp_get_attachment_image($value, array(80, 80), true);
316 $file_name = get_the_title($value);
317 $file_type = get_post_mime_type($value);
318 $attachment_url = wp_get_attachment_url($value);
319 $upload_button .= '<div id="' . esc_attr($upload_input_id) . '_info_container" class="upload-field-details" data-attachment_id="' . $value . '">';
320 $upload_button .= '<div class="file-thumb">';
321 $upload_button .= "<a href='{$attachment_url}' target='_blank' class='wppb-attachment-link'>" . $thumbnail . "</a>";
322 $upload_button .= '</div>';
323 $upload_button .= '<p><span class="file-name">';
324 $upload_button .= $file_name;
325 $upload_button .= '</span><span class="file-type">';
326 $upload_button .= $file_type;
327 $upload_button .= '</span>';
328 $upload_button .= '<span class="wppb-remove-upload" tabindex="0">' . apply_filters( 'wppb_upload_button_remove_label', __( 'Remove', 'profile-builder' ) ) . '</span>';
329 $upload_button .= '</p></div>';
330 }
331 }
332 $hide_upload_button = ' style="display:none;"';
333 }
334 else{
335 $hide_upload_button = '';
336 }
337
338 if ( isset( $field[ 'simple-upload' ] ) && $field[ 'simple-upload' ] == 'yes' ){
339 //If selected accordingly in form fields, generate a simple upload button
340 $upload_button .= '<input type="file" id="upload_' . esc_attr(Wordpress_Creation_Kit_PB::wck_generate_slug($field['meta-name'], $field)) . '_button" class="wppb_simple_upload" data-field_type="'. esc_attr( $field['field'] ) .'" name="simple_upload_'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $field['meta-name'], $field ) ) .'"';
341 $upload_button .= $hide_upload_button . '>';
342 $upload_button .= '<p id="p_simple_upload_'. esc_attr(Wordpress_Creation_Kit_PB::wck_generate_slug($field['meta-name'], $field)) .'"></p>';
343 $limit = apply_filters( 'wppb_server_max_upload_size_byte_constant', wppb_return_bytes( ini_get( 'upload_max_filesize' ) ) );
344 $all_fields = apply_filters( 'wppb_form_fields', get_option( 'wppb_manage_fields' ), array( 'context' => 'upload_helper', 'upload_meta_name' => $field[ 'meta-name' ] ) );
345 if ( !empty( $all_fields ) ) {
346 foreach ( $all_fields as $form_field ) {
347 if ($form_field[ 'meta-name' ] == $field[ 'meta-name' ] ) {
348 // apply per-field size limit if set
349 if ( !empty( $form_field['max-file-size'] ) && is_numeric( $form_field['max-file-size'] ) && floatval( $form_field['max-file-size'] ) > 0 ) {
350 $field_limit = floatval( $form_field['max-file-size'] ) * 1024 * 1024;
351 $limit = min( $field_limit, $limit );
352 }
353 $allowed_upload_extensions = '';
354 if ( $form_field[ 'field' ] == 'Upload' && !empty( $form_field[ 'allowed-upload-extensions' ] ) ) {
355 $allowed_upload_extensions = $form_field[ 'allowed-upload-extensions' ];
356 }
357 if ( $form_field[ 'field' ] == 'Avatar' ) {
358 if ( trim( $field[ 'allowed-image-extensions' ] ) == '.*' || trim( $field[ 'allowed-image-extensions' ] ) == '' ) {
359 $allowed_upload_extensions = '.jpg,.jpeg,.gif,.png';
360 }
361 else {
362 $allowed_upload_extensions = $form_field[ 'allowed-image-extensions' ];
363 }
364 }
365 }
366 if ( !empty( $allowed_upload_extensions ) && $allowed_upload_extensions != '.*' ) {
367 $allowed_extensions = str_replace( '.', '', array_map( 'trim', explode( ",", strtolower( $allowed_upload_extensions ) ) ) );
368 $allowed_extensions = implode( ',', $allowed_extensions );
369 } else {
370 $allowed_extensions = '';
371 }
372 }
373 }
374 $upload_button .= '<input id="allowed_extensions_simple_upload_'. esc_attr( $upload_input_id ) .'" type="hidden" size="36" name="allowed_extensions_simple_upload_'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $field['meta-name'], $field ) ) .'" value="'. esc_attr( $allowed_extensions ) .'"/>';
375 $upload_button .= '<input id="size_limit_simple_upload_'. esc_attr( $upload_input_id ) .'" type="hidden" name="size_limit_simple_upload_'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $field['meta-name'], $field ) ) .'" value="'. esc_attr( $limit ) .'"/>';
376 $allowed_mime_types = get_allowed_mime_types();
377 $allowed_types = '';
378 if ( !empty( $allowed_mime_types ) ) {
379 foreach ($allowed_mime_types as $key => $val){
380 $allowed_types .= $key . '=>' . $val . ',';
381 }
382 }
383 $error_messages = array(
384 'limit_error_message' => __( 'Files must be smaller than ', 'profile-builder' ),
385 'upload_type_error_message' => __( 'Sorry, you cannot upload this file type for this field.', 'profile-builder' ),
386 );
387 $size_limit = array(
388 'size_limit' => $limit
389 );
390 $allowed_wordpress_formats = array(
391 'allowed_wordpress_formats' => $allowed_mime_types
392 );
393 wp_localize_script( 'wppb-upload-script', 'wppb_error_messages', $error_messages );
394 wp_localize_script( 'wppb-upload-script', 'wppb_limit', $size_limit );
395 wp_localize_script( 'wppb-upload-script', 'wppb_allowed_wordpress_formats', $allowed_wordpress_formats );
396 }
397 else{
398 //Otherwise, generate the WordPress upload button
399 $upload_button .= '<a href="#" class="button wppb_upload_button" id="upload_' . esc_attr(Wordpress_Creation_Kit_PB::wck_generate_slug($field['meta-name'], $field)) . '_button" '.$hide_upload_button.' data-uploader_title="' . $field["field-title"] . '" data-uploader_button_text="'. __( 'Select File', 'profile-builder' ) .'" data-upload_mn="'. $field['meta-name'] .'" data-upload_input="' . esc_attr($upload_input_id) . '"';
400
401 if (is_user_logged_in())
402 $upload_button .= ' data-uploader_logged_in="true"';
403 $upload_button .= ' data-multiple_upload="false"';
404
405 $upload_button .= '>' . apply_filters( 'wppb_upload_button_select_label', __( 'Upload ', 'profile-builder' ) ) . '</a>';
406 }
407
408 $upload_button .= '<input id="'. esc_attr( $upload_input_id ) .'" type="hidden" size="36" name="'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $field['meta-name'], $field ) ) .'" value="'. esc_attr( wp_unslash( $input_value ) ) .'"/>';
409 return $upload_button;
410 }
411
412 /**
413 * Function to save an attachment from the simple upload field
414 * @param $field_name
415 * @return string|WP_Error
416 */
417 function wppb_default_fields_save_simple_upload_file( $field_name ) {
418 require_once(ABSPATH . 'wp-admin/includes/file.php');
419 $upload_overrides = array('test_form' => false);
420
421 if( isset( $_FILES[$field_name] ) )
422 $file = wp_handle_upload($_FILES[$field_name], $upload_overrides);
423
424 if (isset($file['error'])) {
425 return new WP_Error('upload_error', $file['error']);
426 }
427 $filename = isset( $_FILES[$field_name]['name'] ) ? sanitize_text_field( $_FILES[$field_name]['name'] ) : '';
428 $wp_filetype = wp_check_filetype($filename, null);
429 $attachment = array(
430 'post_mime_type' => $wp_filetype['type'],
431 'post_title' => $filename,
432 'post_content' => '',
433 'post_status' => 'inherit'
434 );
435 $attachment_id = wp_insert_attachment($attachment, $file['file']);
436 if (!is_wp_error($attachment_id) && is_numeric($attachment_id)) {
437 require_once(ABSPATH . 'wp-admin/includes/image.php');
438 $attachment_data = wp_generate_attachment_metadata($attachment_id, $file['file']);
439 wp_update_attachment_metadata($attachment_id, $attachment_data);
440 return trim($attachment_id);
441 } else {
442 return '';
443 }
444 }
445
446 // Deferred to plugins_loaded so older Profile Builder Pro versions (which declare
447 // wppb_verify_attachment_id unconditionally during their own file load) win the
448 // declaration race and our function_exists guard then skips — avoiding a fatal.
449 add_action( 'plugins_loaded', 'wppb_register_attachment_ownership_helpers', 20 );
450 function wppb_register_attachment_ownership_helpers() {
451
452 /**
453 * Verifies if an attachment either doesn't exist or already belongs to the user.
454 * Used for IDOR protection on both Upload and Avatar fields.
455 *
456 * @param string|int $attachment_id The attachment post ID to verify.
457 * @param int|null $user_id The user ID to check ownership against.
458 *
459 * @return bool True if the attachment is valid for this user, false otherwise.
460 */
461 if ( !function_exists( 'wppb_verify_attachment_id' ) ) {
462 function wppb_verify_attachment_id( $attachment_id, $user_id = null ) {
463 if ( $attachment_id !== '' && is_numeric( $attachment_id ) ) {
464 $attachment = get_post( absint( trim( $attachment_id ) ) );
465 if ( $attachment && $attachment->post_type === 'attachment' ) {
466
467 // Get current user info for admin bypass checks
468 $current_user_id = get_current_user_id();
469 $current_user = $current_user_id ? get_userdata( $current_user_id ) : null;
470 $is_admin = $current_user && current_user_can( 'manage_options' );
471
472 if ( $user_id ) {
473 // Allow admins to upload files for users
474 if ( $is_admin ) {
475 return true;
476 }
477 // The attachment is claimable when it already belongs to the target
478 // user, or to the user performing the request. An author-less
479 // attachment (post_author == 0) is only claimable by an
480 // unauthenticated request (e.g. a visitor registering, whose upload
481 // has no author yet). This prevents an authenticated user from
482 // claiming (IDOR) an author-0 attachment created by someone else's
483 // anonymous/nopriv upload.
484 if ( $attachment->post_author == $user_id
485 || ( $current_user_id && $attachment->post_author == $current_user_id )
486 || ( 0 === (int) $current_user_id && 0 === (int) $attachment->post_author ) ) {
487 return true;
488 }
489 } else {
490 // If no user ID is provided, check if current user is admin
491 if ( $is_admin ) {
492 return true;
493 }
494 // Without an explicit target user, an authenticated user may only
495 // reference an attachment they already own; an author-less
496 // attachment is only claimable by an unauthenticated request.
497 if ( ( $current_user_id && $attachment->post_author == $current_user_id )
498 || ( 0 === (int) $current_user_id && 0 === (int) $attachment->post_author ) ) {
499 return true;
500 }
501 }
502 }
503 }
504 return false;
505 }
506 }
507
508 /**
509 * Validates attachment ownership and updates the user meta and post author.
510 * Used for IDOR-safe saving on both Upload and Avatar fields.
511 *
512 * @param string|int $attachment_id The attachment post ID.
513 * @param array $field The field definition array (must contain 'meta-name').
514 * @param int $user_id The user ID to save for.
515 */
516 if ( !function_exists( 'wppb_save_attachment_id' ) ) {
517 function wppb_save_attachment_id( $attachment_id, $field, $user_id ) {
518 // Verify that the attachment either doesn't exist or already belongs to the user
519 if ( wppb_verify_attachment_id( $attachment_id, $user_id ) ) {
520 update_user_meta( $user_id, $field['meta-name'], absint( $attachment_id ) );
521 wp_update_post( array(
522 'ID' => absint( trim( $attachment_id ) ),
523 'post_author' => $user_id
524 ) );
525 } else {
526 update_user_meta( $user_id, $field['meta-name'], '' );
527 }
528 }
529 }
530 }
531
532 /**
533 * Resolves a simple-upload AJAX `name` parameter to a configured form field.
534 *
535 * @param string $post_name Sanitized value of $_POST['name'] from the AJAX request.
536 * @param string|array $field_type Expected field type(s), e.g. 'Avatar' or 'Upload'.
537 *
538 * @return array|false Field definition array, or false when not found or not simple-upload.
539 */
540 function wppb_resolve_simple_upload_ajax_field( $post_name, $field_type ) {
541 if ( empty( $post_name ) ) {
542 return false;
543 }
544
545 $field_types = is_array( $field_type ) ? $field_type : array( $field_type );
546 $all_fields = apply_filters( 'wppb_form_fields', get_option( 'wppb_manage_fields' ), array( 'context' => 'simple_upload_ajax', 'upload_post_name' => $post_name ) );
547
548 if ( empty( $all_fields ) ) {
549 return false;
550 }
551
552 foreach ( $all_fields as $field ) {
553 if ( ! in_array( $field['field'], $field_types, true ) ) {
554 continue;
555 }
556 if ( ! isset( $field['simple-upload'] ) || $field['simple-upload'] !== 'yes' ) {
557 continue;
558 }
559 if ( isset( $field['woocommerce-checkout-field'] ) && $field['woocommerce-checkout-field'] === 'Yes' ) {
560 continue;
561 }
562
563 $field_slug = str_replace( '-', '_', Wordpress_Creation_Kit_PB::wck_generate_slug( $field['meta-name'], $field ) );
564 if ( $field_slug === $post_name ) {
565 return $field;
566 }
567 }
568
569 // The field was not found among the top-level form fields. Repeater fields store
570 // their inner Upload fields in a separate option keyed by the repeater's
571 // meta-name, so those fields are never part of the wppb_manage_fields list scanned
572 // above. Scan the repeater groups as well, otherwise Simple Upload inside a
573 // Repeater field is silently rejected (the lookup fails and the file input clears).
574 return wppb_resolve_simple_upload_ajax_field_in_repeater( $post_name, $field_types, $all_fields );
575 }
576
577 /**
578 * Resolves a simple-upload AJAX `name` parameter to an Upload field nested inside a
579 * Repeater field.
580 *
581 * Repeater sub-fields are stored unindexed in an option keyed by the repeater's
582 * meta-name. On the front-end each group posts either "<slug>" (the first group) or
583 * "<slug>_N" (the Nth extra group), where <slug> is the dash-normalized wck slug of
584 * the inner field's meta-name.
585 *
586 * @param string $post_name Sanitized value of $_POST['name'] from the AJAX request.
587 * @param array $field_types Expected field type(s), e.g. array( 'Upload' ).
588 * @param array $all_fields The already-resolved top-level form fields.
589 *
590 * @return array|false Inner field definition array, or false when not found.
591 */
592 function wppb_resolve_simple_upload_ajax_field_in_repeater( $post_name, $field_types, $all_fields ) {
593 foreach ( $all_fields as $form_field ) {
594 if ( empty( $form_field['field'] ) || $form_field['field'] !== 'Repeater' ) {
595 continue;
596 }
597
598 $repeater_group = get_option( $form_field['meta-name'], 'not_set' );
599 if ( $repeater_group === 'not_set' || ! is_array( $repeater_group ) ) {
600 continue;
601 }
602
603 foreach ( $repeater_group as $inner_field ) {
604 if ( empty( $inner_field['field'] ) || ! in_array( $inner_field['field'], $field_types, true ) ) {
605 continue;
606 }
607 if ( ! isset( $inner_field['simple-upload'] ) || $inner_field['simple-upload'] !== 'yes' ) {
608 continue;
609 }
610 if ( isset( $inner_field['woocommerce-checkout-field'] ) && $inner_field['woocommerce-checkout-field'] === 'Yes' ) {
611 continue;
612 }
613
614 $base_slug = str_replace( '-', '_', Wordpress_Creation_Kit_PB::wck_generate_slug( $inner_field['meta-name'], $inner_field ) );
615 if ( $base_slug === $post_name || preg_match( '/^' . preg_quote( $base_slug, '/' ) . '_[0-9]+$/', $post_name ) ) {
616 return $inner_field;
617 }
618 }
619 }
620
621 return false;
622 }
623
624 function wppb_check_that_field_is_defined( $meta_name, $field_types = array() ){
625
626 if( empty( $meta_name ) )
627 return false;
628
629 $defined_fields = apply_filters( 'wppb_form_fields', get_option( 'wppb_manage_fields' ), array( 'context' => 'upload_helper', 'upload_meta_name' => $meta_name ) );
630
631 if( empty( $defined_fields ) )
632 return false;
633 else {
634
635 if( empty( $field_types ) ){
636 foreach( $defined_fields as $field ){
637
638 if( $field['meta-name'] == $meta_name )
639 return true;
640
641 }
642 } else {
643 foreach( $defined_fields as $field ){
644
645 if( in_array( $field['field'], $field_types ) && $field['meta-name'] == $meta_name )
646 return true;
647
648 }
649 }
650
651 }
652
653 return false;
654
655 }