PluginProbe
weForms – Easy Drag & Drop Contact Form Builder For WordPress / 1.6.28
weForms – Easy Drag & Drop Contact Form Builder For WordPress v1.6.28
1.6.7 1.6.8 1.6.9 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.18 1.6.19 1.6.2 1.6.20 1.6.21 1.6.22 1.6.23 1.6.24 1.6.25 1.6.26 1.6.27 1.6.28 1.6.3 1.6.4 1.6.5 1.6.6 All 74 releases
weforms / includes / class-ajax-upload.php

class-ajax-upload.php in weForms – Easy Drag & Drop Contact Form Builder For WordPress 1.6.28, at includes/class-ajax-upload.php

254 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Attachment Uploader class
5 *
6 * @since 1.1.0
7 */
8 class WeForms_Ajax_Upload {
9
10 public function __construct() {
11
12 // let WPUF handle the upload if installed
13 if ( class_exists( 'WPUF_Upload' ) ) {
14 return;
15 }
16
17 add_action( 'wp_ajax_wpuf_upload_file', [$this, 'upload_file'] );
18 add_action( 'wp_ajax_nopriv_wpuf_upload_file', [$this, 'upload_file'] );
19
20 add_action( 'wp_ajax_wpuf_file_del', [$this, 'delete_file'] );
21 add_action( 'wp_ajax_nopriv_wpuf_file_del', [$this, 'delete_file'] );
22 }
23
24 /**
25 * Validate if it's coming from WordPress with a valid nonce
26 *
27 * @return void
28 */
29 function validate_nonce() {
30 $nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : '';
31
32 if ( !wp_verify_nonce( $nonce, 'wpuf-upload-nonce' ) ) {
33 die( 'error' );
34 }
35 }
36
37 /**
38 * Upload a file
39 *
40 * @param bool $image_only
41 *
42 * @return string
43 */
44 public function upload_file( $image_only = false ) {
45 $this->validate_nonce();
46 $nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : '';
47
48 if ( ! wp_verify_nonce( $nonce, 'wpuf-upload-nonce' ) ) {
49 die( 'error' );
50 }
51
52 // a valid request will have a form ID
53 $form_id = isset( $_POST['form_id'] ) ? intval( sanitize_text_field( wp_unslash( $_POST['form_id'] ) ) ) : false;
54
55 if ( !$form_id ) {
56 die( 'error' );
57 }
58
59
60 $file = isset( $_FILES['wpuf_file'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_FILES['wpuf_file'] ) ) : [];
61
62 $upload = array(
63 'name' => isset( $file['name'] ) ? $file['name'] : '',
64 'type' => isset( $file['type'] ) ? $file['type'] : '',
65 'tmp_name' => $_FILES['wpuf_file']['tmp_name'],
66 'error' => isset( $file['error'] ) ? $file['error'] : '',
67 'size' => isset( $file['size'] ) ? $file['size'] : '',
68 );
69
70 // $upload = array(
71 // 'name' => isset( $_FILES['wpuf_file']['name'] ) ? sanitize_file_name( wp_unslash( $_FILES['wpuf_file']['name'] ) ) : '',
72 // 'type' => isset( $_FILES['wpuf_file']['type'] ) ? sanitize_mime_type( wp_unslash( $_FILES['wpuf_file']['type'] ) ) : '',
73 // 'tmp_name' => $_FILES['wpuf_file']['tmp_name'],
74 // 'error' => isset( $_FILES['wpuf_file']['error'] ) ? sanitize_text_field( wp_unslash( $_FILES['wpuf_file']['error'] ) ) : '',
75 // 'size' => isset( $_FILES['wpuf_file']['size'] ) ? sanitize_text_field( wp_unslash( $_FILES['wpuf_file']['size'] ) ) : ''
76 // );
77
78 header( 'Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );
79
80 $attach = $this->handle_upload( $upload );
81
82 if ( $attach['success'] ) {
83 $response = [ 'success' => true ];
84 $response['html'] = $this->attach_html( $attach['attach_id'] );
85
86 echo wp_kses( $response['html'], [
87 'li' => [
88 'class' => []
89 ],
90 'div' => [
91 'class' => []
92 ],
93 'img' => [
94 'src' => [],
95 'alt' => []
96 ],
97
98 'input' => [
99 'type' => [],
100 'name' => [],
101 'value' => []
102 ],
103 'a' => [
104 'data-attach_id' => [],
105 'href' => [],
106 'class' => []
107 ],
108 'span' => [
109 'class' => []
110 ]
111 ]);
112 } else {
113 echo 'error';
114 }
115
116 exit;
117 }
118
119 /**
120 * Generic function to upload a file
121 *
122 * @param string $field_name file input field name
123 *
124 * @return bool|int attachment id on success, bool false instead
125 */
126 public function handle_upload( $upload_data ) {
127 $uploaded_file = wp_handle_upload( $upload_data, ['test_form' => false] );
128
129 // If the wp_handle_upload call returned a local path for the image
130 if ( isset( $uploaded_file['file'] ) ) {
131 $file_loc = $uploaded_file['file'];
132 $file_name = basename( $upload_data['name'] );
133 $file_type = wp_check_filetype( $file_name );
134
135 $attachment = [
136 'post_mime_type' => $file_type['type'],
137 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $file_name ) ),
138 'post_content' => '',
139 'post_status' => 'inherit',
140 ];
141
142 $attach_id = wp_insert_attachment( $attachment, $file_loc );
143 $attach_data = wp_generate_attachment_metadata( $attach_id, $file_loc );
144
145 wp_update_attachment_metadata( $attach_id, $attach_data );
146
147 // Store a unique deletion token for security (prevents IDOR attacks)
148 $delete_token = wp_generate_password( 32, false );
149 update_post_meta( $attach_id, '_wpuf_delete_token', $delete_token );
150
151 return ['success' => true, 'attach_id' => $attach_id];
152 }
153
154 return ['success' => false, 'error' => $uploaded_file['error']];
155 }
156
157 /**
158 * Image attachment response
159 *
160 * @param int $attach_id
161 * @param string $type
162 *
163 * @return string
164 */
165 public static function attach_html( $attach_id, $type = NULL ) {
166 if ( ! $type ) {
167 $type = isset( $_GET['type'] ) ? sanitize_text_field( wp_unslash( $_GET['type'] ) ) : 'image';
168 }
169
170 $attachment = get_post( $attach_id );
171
172 if ( !$attachment ) {
173 return;
174 }
175
176 if ( wp_attachment_is_image( $attach_id ) ) {
177 $image = wp_get_attachment_image_src( $attach_id, 'thumbnail' );
178 $image = $image[0];
179 } else {
180 $image = wp_mime_type_icon( $attach_id );
181 }
182
183 // Get deletion token for security (prevents IDOR attacks)
184 $delete_token = get_post_meta( $attach_id, '_wpuf_delete_token', true );
185 // If no token exists (legacy files), generate one now
186 if ( empty( $delete_token ) ) {
187 $delete_token = wp_generate_password( 32, false );
188 update_post_meta( $attach_id, '_wpuf_delete_token', $delete_token );
189 }
190
191 $html = '<li class="ui-state-default wpuf-image-wrap thumbnail">';
192 $html .= sprintf( '<div class="attachment-name"><img src="%s" alt="%s" /></div>', $image, esc_attr( $attachment->post_title ) );
193
194 $html .= sprintf( '<input type="hidden" name="wpuf_files[%s][]" value="%d">', $type, $attach_id );
195 $html .= '<div class="caption">';
196 $html .= sprintf( '<a href="#" class="attachment-delete" data-attach_id="%d" data-delete-token="%s"> <img src="%s" /></a>', $attach_id, esc_attr( $delete_token ), WEFORMS_ASSET_URI . '/images/del-img.png' );
197 $html .= sprintf( '<span class="wpuf-drag-file"> <img src="%s" /></span>', WEFORMS_ASSET_URI . '/images/move-img.png' );
198 $html .= '</div>';
199 $html .= '</li>';
200
201 return $html;
202 }
203
204 /**
205 * Delete a file
206 *
207 * @return void
208 */
209 public function delete_file() {
210 check_ajax_referer( 'wpuf_nonce', 'nonce' );
211
212 $attach_id = isset( $_POST['attach_id'] ) ? intval( $_POST['attach_id'] ) : 0;
213 $attachment = get_post( $attach_id );
214
215 // Validate attachment exists
216 if ( ! $attachment || 'attachment' !== $attachment->post_type ) {
217 echo 'error';
218 exit;
219 }
220
221 $current_user_id = get_current_user_id();
222 $is_authenticated = $current_user_id > 0;
223 $can_delete = false;
224
225 if ( $is_authenticated ) {
226 // For authenticated users: must own the file OR have admin/editor capabilities
227 if ( $current_user_id == $attachment->post_author || current_user_can( 'delete_private_pages' ) ) {
228 $can_delete = true;
229 }
230 } else {
231 // For unauthenticated users: must provide the correct deletion token
232 // This prevents IDOR attacks where 0 == 0 would allow deletion of any guest upload
233 $delete_token = isset( $_POST['delete_token'] ) ? sanitize_text_field( wp_unslash( $_POST['delete_token'] ) ) : '';
234 $stored_token = get_post_meta( $attach_id, '_wpuf_delete_token', true );
235
236 // Only allow deletion if token matches AND file was uploaded by guest (post_author == 0)
237 if ( ! empty( $delete_token ) && ! empty( $stored_token ) &&
238 hash_equals( $stored_token, $delete_token ) &&
239 $attachment->post_author == 0 ) {
240 $can_delete = true;
241 }
242 }
243
244 if ( $can_delete ) {
245 wp_delete_attachment( $attach_id, true );
246 echo 'success';
247 } else {
248 echo 'error';
249 }
250
251 exit;
252 }
253 }
254