137 * The filename is based off the passed parameter or defaults to the current unix timestamp, |
135 * The filename is based off the passed parameter or defaults to the current unix timestamp, |
138 * while the directory can either be passed as well, or by leaving it blank, default to a writable temporary directory. |
136 * while the directory can either be passed as well, or by leaving it blank, default to a writable temporary directory. |
139 * |
137 * |
140 * @since 2.6.0 |
138 * @since 2.6.0 |
141 * |
139 * |
142 * @param string $filename (optional) Filename to base the Unique file off |
140 * @param string $filename Optional. Filename to base the Unique file off. Default empty. |
143 * @param string $dir (optional) Directory to store the file in |
141 * @param string $dir Optional. Directory to store the file in. Default empty. |
144 * @return string a writable filename |
142 * @return string a writable filename |
145 */ |
143 */ |
146 function wp_tempnam($filename = '', $dir = '') { |
144 function wp_tempnam( $filename = '', $dir = '' ) { |
147 if ( empty($dir) ) |
145 if ( empty( $dir ) ) { |
148 $dir = get_temp_dir(); |
146 $dir = get_temp_dir(); |
149 $filename = basename($filename); |
147 } |
150 if ( empty($filename) ) |
148 |
|
149 if ( empty( $filename ) || '.' == $filename || '/' == $filename ) { |
151 $filename = time(); |
150 $filename = time(); |
152 |
151 } |
153 $filename = preg_replace('|\..*$|', '.tmp', $filename); |
152 |
154 $filename = $dir . wp_unique_filename($dir, $filename); |
153 // Use the basename of the given file without the extension as the name for the temporary directory |
155 touch($filename); |
154 $temp_filename = basename( $filename ); |
156 return $filename; |
155 $temp_filename = preg_replace( '|\.[^.]*$|', '', $temp_filename ); |
|
156 |
|
157 // If the folder is falsey, use it's parent directory name instead |
|
158 if ( ! $temp_filename ) { |
|
159 return wp_tempnam( dirname( $filename ), $dir ); |
|
160 } |
|
161 |
|
162 $temp_filename .= '.tmp'; |
|
163 $temp_filename = $dir . wp_unique_filename( $dir, $temp_filename ); |
|
164 touch( $temp_filename ); |
|
165 |
|
166 return $temp_filename; |
157 } |
167 } |
158 |
168 |
159 /** |
169 /** |
160 * Make sure that the file that was requested to edit, is allowed to be edited |
170 * Make sure that the file that was requested to edit, is allowed to be edited |
161 * |
171 * |
162 * Function will die if if you are not allowed to edit the file |
172 * Function will die if if you are not allowed to edit the file |
163 * |
173 * |
164 * @since 1.5.0 |
174 * @since 1.5.0 |
165 * |
175 * |
166 * @uses wp_die |
|
167 * @uses validate_file |
|
168 * @param string $file file the users is attempting to edit |
176 * @param string $file file the users is attempting to edit |
169 * @param array $allowed_files Array of allowed files to edit, $file must match an entry exactly |
177 * @param array $allowed_files Array of allowed files to edit, $file must match an entry exactly |
170 * @return null |
178 * @return string|null |
171 */ |
179 */ |
172 function validate_file_to_edit( $file, $allowed_files = '' ) { |
180 function validate_file_to_edit( $file, $allowed_files = '' ) { |
173 $code = validate_file( $file, $allowed_files ); |
181 $code = validate_file( $file, $allowed_files ); |
174 |
182 |
175 if (!$code ) |
183 if (!$code ) |
176 return $file; |
184 return $file; |
177 |
185 |
178 switch ( $code ) { |
186 switch ( $code ) { |
179 case 1 : |
187 case 1 : |
180 wp_die( __('Sorry, can’t edit files with “..” in the name. If you are trying to edit a file in your WordPress home directory, you can just type the name of the file in.' )); |
188 wp_die( __( 'Sorry, that file cannot be edited.' ) ); |
181 |
189 |
182 //case 2 : |
190 // case 2 : |
183 // wp_die( __('Sorry, can’t call files with their real path.' )); |
191 // wp_die( __('Sorry, can’t call files with their real path.' )); |
184 |
192 |
185 case 3 : |
193 case 3 : |
186 wp_die( __('Sorry, that file cannot be edited.' )); |
194 wp_die( __( 'Sorry, that file cannot be edited.' ) ); |
187 } |
195 } |
188 } |
196 } |
189 |
197 |
190 /** |
198 /** |
191 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type, |
199 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type, |
192 * and moving the file to the appropriate directory within the uploads directory. |
200 * and moving the file to the appropriate directory within the uploads directory. |
193 * |
201 * |
194 * @since 2.0 |
202 * @since 4.0.0 |
195 * |
203 * |
196 * @uses wp_handle_upload_error |
204 * @see wp_handle_upload_error |
197 * @uses apply_filters |
205 * |
198 * @uses is_multisite |
206 * @param array $file Reference to a single element of $_FILES. Call the function once for each uploaded file. |
199 * @uses wp_check_filetype_and_ext |
207 * @param array|false $overrides An associative array of names => values to override default variables. Default false. |
200 * @uses current_user_can |
208 * @param string $time Time formatted in 'yyyy/mm'. |
201 * @uses wp_upload_dir |
209 * @param string $action Expected value for $_POST['action']. |
202 * @uses wp_unique_filename |
210 * @return array On success, returns an associative array of file attributes. On failure, returns |
203 * @uses delete_transient |
211 * $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). |
204 * @param array $file Reference to a single element of $_FILES. Call the function once for each uploaded file. |
212 */ |
205 * @param array $overrides Optional. An associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ). |
213 function _wp_handle_upload( &$file, $overrides, $time, $action ) { |
206 * @param string $time Optional. Time formatted in 'yyyy/mm'. |
|
207 * @return array On success, returns an associative array of file attributes. On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). |
|
208 */ |
|
209 function wp_handle_upload( &$file, $overrides = false, $time = null ) { |
|
210 // The default error handler. |
214 // The default error handler. |
211 if ( ! function_exists( 'wp_handle_upload_error' ) ) { |
215 if ( ! function_exists( 'wp_handle_upload_error' ) ) { |
212 function wp_handle_upload_error( &$file, $message ) { |
216 function wp_handle_upload_error( &$file, $message ) { |
213 return array( 'error'=>$message ); |
217 return array( 'error' => $message ); |
214 } |
218 } |
215 } |
219 } |
216 |
220 |
217 $file = apply_filters( 'wp_handle_upload_prefilter', $file ); |
221 /** |
|
222 * Filter the data for a file before it is uploaded to WordPress. |
|
223 * |
|
224 * The dynamic portion of the hook name, `$action`, refers to the post action. |
|
225 * |
|
226 * @since 2.9.0 as 'wp_handle_upload_prefilter'. |
|
227 * @since 4.0.0 Converted to a dynamic hook with `$action`. |
|
228 * |
|
229 * @param array $file An array of data for a single file. |
|
230 */ |
|
231 $file = apply_filters( "{$action}_prefilter", $file ); |
218 |
232 |
219 // You may define your own function and pass the name in $overrides['upload_error_handler'] |
233 // You may define your own function and pass the name in $overrides['upload_error_handler'] |
220 $upload_error_handler = 'wp_handle_upload_error'; |
234 $upload_error_handler = 'wp_handle_upload_error'; |
|
235 if ( isset( $overrides['upload_error_handler'] ) ) { |
|
236 $upload_error_handler = $overrides['upload_error_handler']; |
|
237 } |
221 |
238 |
222 // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully. |
239 // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully. |
223 if ( isset( $file['error'] ) && !is_numeric( $file['error'] ) && $file['error'] ) |
240 if ( isset( $file['error'] ) && ! is_numeric( $file['error'] ) && $file['error'] ) { |
224 return $upload_error_handler( $file, $file['error'] ); |
241 return $upload_error_handler( $file, $file['error'] ); |
|
242 } |
|
243 |
|
244 // Install user overrides. Did we mention that this voids your warranty? |
225 |
245 |
226 // You may define your own function and pass the name in $overrides['unique_filename_callback'] |
246 // You may define your own function and pass the name in $overrides['unique_filename_callback'] |
227 $unique_filename_callback = null; |
247 $unique_filename_callback = null; |
228 |
248 if ( isset( $overrides['unique_filename_callback'] ) ) { |
229 // $_POST['action'] must be set and its value must equal $overrides['action'] or this: |
249 $unique_filename_callback = $overrides['unique_filename_callback']; |
230 $action = 'wp_handle_upload'; |
250 } |
231 |
251 |
232 // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error']. |
252 /* |
233 $upload_error_strings = array( false, |
253 * This may not have orignially been intended to be overrideable, |
234 __( "The uploaded file exceeds the upload_max_filesize directive in php.ini." ), |
254 * but historically has been. |
235 __( "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form." ), |
255 */ |
236 __( "The uploaded file was only partially uploaded." ), |
256 if ( isset( $overrides['upload_error_strings'] ) ) { |
237 __( "No file was uploaded." ), |
257 $upload_error_strings = $overrides['upload_error_strings']; |
238 '', |
258 } else { |
239 __( "Missing a temporary folder." ), |
259 // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error']. |
240 __( "Failed to write file to disk." ), |
260 $upload_error_strings = array( |
241 __( "File upload stopped by extension." )); |
261 false, |
|
262 __( 'The uploaded file exceeds the upload_max_filesize directive in php.ini.' ), |
|
263 __( 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.' ), |
|
264 __( 'The uploaded file was only partially uploaded.' ), |
|
265 __( 'No file was uploaded.' ), |
|
266 '', |
|
267 __( 'Missing a temporary folder.' ), |
|
268 __( 'Failed to write file to disk.' ), |
|
269 __( 'File upload stopped by extension.' ) |
|
270 ); |
|
271 } |
242 |
272 |
243 // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false; |
273 // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false; |
244 $test_form = true; |
274 $test_form = isset( $overrides['test_form'] ) ? $overrides['test_form'] : true; |
245 $test_size = true; |
275 $test_size = isset( $overrides['test_size'] ) ? $overrides['test_size'] : true; |
246 $test_upload = true; |
276 |
247 |
277 // If you override this, you must provide $ext and $type!! |
248 // If you override this, you must provide $ext and $type!!!! |
278 $test_type = isset( $overrides['test_type'] ) ? $overrides['test_type'] : true; |
249 $test_type = true; |
279 $mimes = isset( $overrides['mimes'] ) ? $overrides['mimes'] : false; |
250 $mimes = false; |
|
251 |
|
252 // Install user overrides. Did we mention that this voids your warranty? |
|
253 if ( is_array( $overrides ) ) |
|
254 extract( $overrides, EXTR_OVERWRITE ); |
|
255 |
280 |
256 // A correct form post will pass this test. |
281 // A correct form post will pass this test. |
257 if ( $test_form && (!isset( $_POST['action'] ) || ($_POST['action'] != $action ) ) ) |
282 if ( $test_form && ( ! isset( $_POST['action'] ) || ( $_POST['action'] != $action ) ) ) { |
258 return call_user_func($upload_error_handler, $file, __( 'Invalid form submission.' )); |
283 return call_user_func( $upload_error_handler, $file, __( 'Invalid form submission.' ) ); |
259 |
284 } |
260 // A successful upload will pass this test. It makes no sense to override this one. |
285 // A successful upload will pass this test. It makes no sense to override this one. |
261 if ( $file['error'] > 0 ) |
286 if ( isset( $file['error'] ) && $file['error'] > 0 ) { |
262 return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']] ); |
287 return call_user_func( $upload_error_handler, $file, $upload_error_strings[ $file['error'] ] ); |
263 |
288 } |
|
289 |
|
290 $test_file_size = 'wp_handle_upload' === $action ? $file['size'] : filesize( $file['tmp_name'] ); |
264 // A non-empty file will pass this test. |
291 // A non-empty file will pass this test. |
265 if ( $test_size && !($file['size'] > 0 ) ) { |
292 if ( $test_size && ! ( $test_file_size > 0 ) ) { |
266 if ( is_multisite() ) |
293 if ( is_multisite() ) { |
267 $error_msg = __( 'File is empty. Please upload something more substantial.' ); |
294 $error_msg = __( 'File is empty. Please upload something more substantial.' ); |
268 else |
295 } else { |
269 $error_msg = __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.' ); |
296 $error_msg = __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.' ); |
270 return call_user_func($upload_error_handler, $file, $error_msg); |
297 } |
|
298 return call_user_func( $upload_error_handler, $file, $error_msg ); |
271 } |
299 } |
272 |
300 |
273 // A properly uploaded file will pass this test. There should be no reason to override this one. |
301 // A properly uploaded file will pass this test. There should be no reason to override this one. |
274 if ( $test_upload && ! @ is_uploaded_file( $file['tmp_name'] ) ) |
302 $test_uploaded_file = 'wp_handle_upload' === $action ? @ is_uploaded_file( $file['tmp_name'] ) : @ is_file( $file['tmp_name'] ); |
275 return call_user_func($upload_error_handler, $file, __( 'Specified file failed upload test.' )); |
303 if ( ! $test_uploaded_file ) { |
|
304 return call_user_func( $upload_error_handler, $file, __( 'Specified file failed upload test.' ) ); |
|
305 } |
276 |
306 |
277 // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter. |
307 // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter. |
278 if ( $test_type ) { |
308 if ( $test_type ) { |
279 $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes ); |
309 $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes ); |
280 |
310 $ext = empty( $wp_filetype['ext'] ) ? '' : $wp_filetype['ext']; |
281 extract( $wp_filetype ); |
311 $type = empty( $wp_filetype['type'] ) ? '' : $wp_filetype['type']; |
|
312 $proper_filename = empty( $wp_filetype['proper_filename'] ) ? '' : $wp_filetype['proper_filename']; |
282 |
313 |
283 // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect |
314 // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect |
284 if ( $proper_filename ) |
315 if ( $proper_filename ) { |
285 $file['name'] = $proper_filename; |
316 $file['name'] = $proper_filename; |
286 |
317 } |
287 if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) |
318 if ( ( ! $type || !$ext ) && ! current_user_can( 'unfiltered_upload' ) ) { |
288 return call_user_func($upload_error_handler, $file, __( 'Sorry, this file type is not permitted for security reasons.' )); |
319 return call_user_func( $upload_error_handler, $file, __( 'Sorry, this file type is not permitted for security reasons.' ) ); |
289 |
320 } |
290 if ( !$ext ) |
321 if ( ! $type ) { |
291 $ext = ltrim(strrchr($file['name'], '.'), '.'); |
|
292 |
|
293 if ( !$type ) |
|
294 $type = $file['type']; |
322 $type = $file['type']; |
|
323 } |
295 } else { |
324 } else { |
296 $type = ''; |
325 $type = ''; |
297 } |
326 } |
298 |
327 |
299 // A writable uploads dir will pass this test. Again, there's no point overriding this one. |
328 /* |
300 if ( ! ( ( $uploads = wp_upload_dir($time) ) && false === $uploads['error'] ) ) |
329 * A writable uploads dir will pass this test. Again, there's no point |
301 return call_user_func($upload_error_handler, $file, $uploads['error'] ); |
330 * overriding this one. |
|
331 */ |
|
332 if ( ! ( ( $uploads = wp_upload_dir( $time ) ) && false === $uploads['error'] ) ) { |
|
333 return call_user_func( $upload_error_handler, $file, $uploads['error'] ); |
|
334 } |
302 |
335 |
303 $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback ); |
336 $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback ); |
304 |
337 |
305 // Move the file to the uploads dir |
338 // Move the file to the uploads dir. |
306 $new_file = $uploads['path'] . "/$filename"; |
339 $new_file = $uploads['path'] . "/$filename"; |
307 if ( false === @ move_uploaded_file( $file['tmp_name'], $new_file ) ) { |
340 if ( 'wp_handle_upload' === $action ) { |
308 if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) |
341 $move_new_file = @ move_uploaded_file( $file['tmp_name'], $new_file ); |
|
342 } else { |
|
343 $move_new_file = @ rename( $file['tmp_name'], $new_file ); |
|
344 } |
|
345 |
|
346 if ( false === $move_new_file ) { |
|
347 if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) { |
309 $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; |
348 $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; |
310 else |
349 } else { |
311 $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; |
350 $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; |
312 |
351 } |
313 return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $error_path ) ); |
352 return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $error_path ) ); |
314 } |
353 } |
315 |
354 |
316 // Set correct file permissions |
355 // Set correct file permissions. |
317 $stat = stat( dirname( $new_file )); |
356 $stat = stat( dirname( $new_file )); |
318 $perms = $stat['mode'] & 0000666; |
357 $perms = $stat['mode'] & 0000666; |
319 @ chmod( $new_file, $perms ); |
358 @ chmod( $new_file, $perms ); |
320 |
359 |
321 // Compute the URL |
360 // Compute the URL. |
322 $url = $uploads['url'] . "/$filename"; |
361 $url = $uploads['url'] . "/$filename"; |
323 |
362 |
324 if ( is_multisite() ) |
363 if ( is_multisite() ) { |
325 delete_transient( 'dirsize_cache' ); |
364 delete_transient( 'dirsize_cache' ); |
326 |
365 } |
327 return apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ), 'upload' ); |
366 |
328 } |
367 /** |
329 |
368 * Filter the data array for the uploaded file. |
330 /** |
369 * |
331 * Handle sideloads, which is the process of retrieving a media item from another server instead of |
370 * @since 2.1.0 |
332 * a traditional media upload. This process involves sanitizing the filename, checking extensions |
371 * |
333 * for mime type, and moving the file to the appropriate directory within the uploads directory. |
372 * @param array $upload { |
|
373 * Array of upload data. |
|
374 * |
|
375 * @type string $file Filename of the newly-uploaded file. |
|
376 * @type string $url URL of the uploaded file. |
|
377 * @type string $type File type. |
|
378 * } |
|
379 * @param string $context The type of upload action. Values include 'upload' or 'sideload'. |
|
380 */ |
|
381 return apply_filters( 'wp_handle_upload', array( |
|
382 'file' => $new_file, |
|
383 'url' => $url, |
|
384 'type' => $type |
|
385 ), 'wp_handle_sideload' === $action ? 'sideload' : 'upload' ); } |
|
386 |
|
387 /** |
|
388 * Wrapper for _wp_handle_upload(), passes 'wp_handle_upload' action. |
|
389 * |
|
390 * @since 2.0.0 |
|
391 * |
|
392 * @see _wp_handle_upload() |
|
393 * |
|
394 * @param array $file Reference to a single element of $_FILES. Call the function once for |
|
395 * each uploaded file. |
|
396 * @param array|bool $overrides Optional. An associative array of names=>values to override default |
|
397 * variables. Default false. |
|
398 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. |
|
399 * @return array On success, returns an associative array of file attributes. On failure, returns |
|
400 * $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). |
|
401 */ |
|
402 function wp_handle_upload( &$file, $overrides = false, $time = null ) { |
|
403 /* |
|
404 * $_POST['action'] must be set and its value must equal $overrides['action'] |
|
405 * or this: |
|
406 */ |
|
407 $action = 'wp_handle_upload'; |
|
408 if ( isset( $overrides['action'] ) ) { |
|
409 $action = $overrides['action']; |
|
410 } |
|
411 |
|
412 return _wp_handle_upload( $file, $overrides, $time, $action ); |
|
413 } |
|
414 |
|
415 /** |
|
416 * Wrapper for _wp_handle_upload(), passes 'wp_handle_sideload' action |
334 * |
417 * |
335 * @since 2.6.0 |
418 * @since 2.6.0 |
336 * |
419 * |
337 * @uses wp_handle_upload_error |
420 * @see _wp_handle_upload() |
338 * @uses apply_filters |
421 * |
339 * @uses wp_check_filetype_and_ext |
422 * @param array $file An array similar to that of a PHP $_FILES POST array |
340 * @uses current_user_can |
423 * @param array|bool $overrides Optional. An associative array of names=>values to override default |
341 * @uses wp_upload_dir |
424 * variables. Default false. |
342 * @uses wp_unique_filename |
425 * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null. |
343 * @param array $file an array similar to that of a PHP $_FILES POST array |
426 * @return array On success, returns an associative array of file attributes. On failure, returns |
344 * @param array $overrides Optional. An associative array of names=>values to override default variables with extract( $overrides, EXTR_OVERWRITE ). |
427 * $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). |
345 * @param string $time Optional. Time formatted in 'yyyy/mm'. |
|
346 * @return array On success, returns an associative array of file attributes. On failure, returns $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ). |
|
347 */ |
428 */ |
348 function wp_handle_sideload( &$file, $overrides = false, $time = null ) { |
429 function wp_handle_sideload( &$file, $overrides = false, $time = null ) { |
349 // The default error handler. |
430 /* |
350 if (! function_exists( 'wp_handle_upload_error' ) ) { |
431 * $_POST['action'] must be set and its value must equal $overrides['action'] |
351 function wp_handle_upload_error( &$file, $message ) { |
432 * or this: |
352 return array( 'error'=>$message ); |
433 */ |
353 } |
|
354 } |
|
355 |
|
356 // You may define your own function and pass the name in $overrides['upload_error_handler'] |
|
357 $upload_error_handler = 'wp_handle_upload_error'; |
|
358 |
|
359 // You may define your own function and pass the name in $overrides['unique_filename_callback'] |
|
360 $unique_filename_callback = null; |
|
361 |
|
362 // $_POST['action'] must be set and its value must equal $overrides['action'] or this: |
|
363 $action = 'wp_handle_sideload'; |
434 $action = 'wp_handle_sideload'; |
364 |
435 if ( isset( $overrides['action'] ) ) { |
365 // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error']. |
436 $action = $overrides['action']; |
366 $upload_error_strings = array( false, |
437 } |
367 __( "The uploaded file exceeds the <code>upload_max_filesize</code> directive in <code>php.ini</code>." ), |
438 return _wp_handle_upload( $file, $overrides, $time, $action ); |
368 __( "The uploaded file exceeds the <em>MAX_FILE_SIZE</em> directive that was specified in the HTML form." ), |
439 } |
369 __( "The uploaded file was only partially uploaded." ), |
440 |
370 __( "No file was uploaded." ), |
|
371 '', |
|
372 __( "Missing a temporary folder." ), |
|
373 __( "Failed to write file to disk." ), |
|
374 __( "File upload stopped by extension." )); |
|
375 |
|
376 // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false; |
|
377 $test_form = true; |
|
378 $test_size = true; |
|
379 |
|
380 // If you override this, you must provide $ext and $type!!!! |
|
381 $test_type = true; |
|
382 $mimes = false; |
|
383 |
|
384 // Install user overrides. Did we mention that this voids your warranty? |
|
385 if ( is_array( $overrides ) ) |
|
386 extract( $overrides, EXTR_OVERWRITE ); |
|
387 |
|
388 // A correct form post will pass this test. |
|
389 if ( $test_form && (!isset( $_POST['action'] ) || ($_POST['action'] != $action ) ) ) |
|
390 return $upload_error_handler( $file, __( 'Invalid form submission.' )); |
|
391 |
|
392 // A successful upload will pass this test. It makes no sense to override this one. |
|
393 if ( ! empty( $file['error'] ) ) |
|
394 return $upload_error_handler( $file, $upload_error_strings[$file['error']] ); |
|
395 |
|
396 // A non-empty file will pass this test. |
|
397 if ( $test_size && !(filesize($file['tmp_name']) > 0 ) ) |
|
398 return $upload_error_handler( $file, __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini.' )); |
|
399 |
|
400 // A properly uploaded file will pass this test. There should be no reason to override this one. |
|
401 if (! @ is_file( $file['tmp_name'] ) ) |
|
402 return $upload_error_handler( $file, __( 'Specified file does not exist.' )); |
|
403 |
|
404 // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter. |
|
405 if ( $test_type ) { |
|
406 $wp_filetype = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes ); |
|
407 |
|
408 extract( $wp_filetype ); |
|
409 |
|
410 // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect |
|
411 if ( $proper_filename ) |
|
412 $file['name'] = $proper_filename; |
|
413 |
|
414 if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) |
|
415 return $upload_error_handler( $file, __( 'Sorry, this file type is not permitted for security reasons.' )); |
|
416 |
|
417 if ( !$ext ) |
|
418 $ext = ltrim(strrchr($file['name'], '.'), '.'); |
|
419 |
|
420 if ( !$type ) |
|
421 $type = $file['type']; |
|
422 } |
|
423 |
|
424 // A writable uploads dir will pass this test. Again, there's no point overriding this one. |
|
425 if ( ! ( ( $uploads = wp_upload_dir( $time ) ) && false === $uploads['error'] ) ) |
|
426 return $upload_error_handler( $file, $uploads['error'] ); |
|
427 |
|
428 $filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback ); |
|
429 |
|
430 // Strip the query strings. |
|
431 $filename = str_replace('?','-', $filename); |
|
432 $filename = str_replace('&','-', $filename); |
|
433 |
|
434 // Move the file to the uploads dir |
|
435 $new_file = $uploads['path'] . "/$filename"; |
|
436 if ( false === @ rename( $file['tmp_name'], $new_file ) ) { |
|
437 if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) |
|
438 $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir']; |
|
439 else |
|
440 $error_path = basename( $uploads['basedir'] ) . $uploads['subdir']; |
|
441 return $upload_error_handler( $file, sprintf( __('The uploaded file could not be moved to %s.' ), $error_path ) ); |
|
442 } |
|
443 |
|
444 // Set correct file permissions |
|
445 $stat = stat( dirname( $new_file )); |
|
446 $perms = $stat['mode'] & 0000666; |
|
447 @ chmod( $new_file, $perms ); |
|
448 |
|
449 // Compute the URL |
|
450 $url = $uploads['url'] . "/$filename"; |
|
451 |
|
452 $return = apply_filters( 'wp_handle_upload', array( 'file' => $new_file, 'url' => $url, 'type' => $type ), 'sideload' ); |
|
453 |
|
454 return $return; |
|
455 } |
|
456 |
441 |
457 /** |
442 /** |
458 * Downloads a url to a local temporary file using the WordPress HTTP Class. |
443 * Downloads a url to a local temporary file using the WordPress HTTP Class. |
459 * Please note, That the calling function must unlink() the file. |
444 * Please note, That the calling function must unlink() the file. |
460 * |
445 * |
872 |
884 |
873 return true; |
885 return true; |
874 } |
886 } |
875 |
887 |
876 /** |
888 /** |
877 * Determines which Filesystem Method to use. |
889 * Determines which method to use for reading, writing, modifying, or deleting |
878 * The priority of the Transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets (Via Sockets class, or fsockopen()) |
890 * files on the filesystem. |
879 * |
891 * |
880 * Note that the return value of this function can be overridden in 2 ways |
892 * The priority of the transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets |
881 * - By defining FS_METHOD in your <code>wp-config.php</code> file |
893 * (Via Sockets class, or `fsockopen()`). Valid values for these are: 'direct', 'ssh2', |
882 * - By using the filesystem_method filter |
894 * 'ftpext' or 'ftpsockets'. |
883 * Valid values for these are: 'direct', 'ssh', 'ftpext' or 'ftpsockets' |
895 * |
884 * Plugins may also define a custom transport handler, See the WP_Filesystem function for more information. |
896 * The return value can be overridden by defining the `FS_METHOD` constant in `wp-config.php`, |
|
897 * or filtering via {@see 'filesystem_method'}. |
|
898 * |
|
899 * @link https://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants |
|
900 * |
|
901 * Plugins may define a custom transport handler, See WP_Filesystem(). |
885 * |
902 * |
886 * @since 2.5.0 |
903 * @since 2.5.0 |
887 * |
904 * |
888 * @param array $args Connection details. |
905 * @param array $args Optional. Connection details. Default empty array. |
889 * @param string $context Full path to the directory that is tested for being writable. |
906 * @param string $context Optional. Full path to the directory that is tested |
|
907 * for being writable. Default false. |
|
908 * @param bool $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable. |
|
909 * Default false. |
890 * @return string The transport to use, see description for valid return values. |
910 * @return string The transport to use, see description for valid return values. |
891 */ |
911 */ |
892 function get_filesystem_method($args = array(), $context = false) { |
912 function get_filesystem_method( $args = array(), $context = false, $allow_relaxed_file_ownership = false ) { |
893 $method = defined('FS_METHOD') ? FS_METHOD : false; //Please ensure that this is either 'direct', 'ssh', 'ftpext' or 'ftpsockets' |
913 $method = defined('FS_METHOD') ? FS_METHOD : false; // Please ensure that this is either 'direct', 'ssh2', 'ftpext' or 'ftpsockets' |
894 |
914 |
895 if ( ! $method && function_exists('getmyuid') && function_exists('fileowner') ){ |
915 if ( ! $context ) { |
896 if ( !$context ) |
916 $context = WP_CONTENT_DIR; |
897 $context = WP_CONTENT_DIR; |
917 } |
898 |
918 |
899 // If the directory doesn't exist (wp-content/languages) then use the parent directory as we'll create it. |
919 // If the directory doesn't exist (wp-content/languages) then use the parent directory as we'll create it. |
900 if ( WP_LANG_DIR == $context && ! is_dir( $context ) ) |
920 if ( WP_LANG_DIR == $context && ! is_dir( $context ) ) { |
901 $context = dirname( $context ); |
921 $context = dirname( $context ); |
902 |
922 } |
903 $context = trailingslashit($context); |
923 |
|
924 $context = trailingslashit( $context ); |
|
925 |
|
926 if ( ! $method ) { |
|
927 |
904 $temp_file_name = $context . 'temp-write-test-' . time(); |
928 $temp_file_name = $context . 'temp-write-test-' . time(); |
905 $temp_handle = @fopen($temp_file_name, 'w'); |
929 $temp_handle = @fopen($temp_file_name, 'w'); |
906 if ( $temp_handle ) { |
930 if ( $temp_handle ) { |
907 if ( getmyuid() == @fileowner($temp_file_name) ) |
931 |
|
932 // Attempt to determine the file owner of the WordPress files, and that of newly created files |
|
933 $wp_file_owner = $temp_file_owner = false; |
|
934 if ( function_exists('fileowner') ) { |
|
935 $wp_file_owner = @fileowner( __FILE__ ); |
|
936 $temp_file_owner = @fileowner( $temp_file_name ); |
|
937 } |
|
938 |
|
939 if ( $wp_file_owner !== false && $wp_file_owner === $temp_file_owner ) { |
|
940 // WordPress is creating files as the same owner as the WordPress files, |
|
941 // this means it's safe to modify & create new files via PHP. |
908 $method = 'direct'; |
942 $method = 'direct'; |
|
943 $GLOBALS['_wp_filesystem_direct_method'] = 'file_owner'; |
|
944 } elseif ( $allow_relaxed_file_ownership ) { |
|
945 // The $context directory is writable, and $allow_relaxed_file_ownership is set, this means we can modify files |
|
946 // safely in this directory. This mode doesn't create new files, only alter existing ones. |
|
947 $method = 'direct'; |
|
948 $GLOBALS['_wp_filesystem_direct_method'] = 'relaxed_ownership'; |
|
949 } |
|
950 |
909 @fclose($temp_handle); |
951 @fclose($temp_handle); |
910 @unlink($temp_file_name); |
952 @unlink($temp_file_name); |
911 } |
953 } |
912 } |
954 } |
913 |
955 |
914 if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2'; |
956 if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && function_exists('stream_get_contents') ) $method = 'ssh2'; |
915 if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext'; |
957 if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext'; |
916 if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread |
958 if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread |
917 return apply_filters('filesystem_method', $method, $args); |
959 |
918 } |
960 /** |
919 |
961 * Filter the filesystem method to use. |
920 /** |
962 * |
921 * Displays a form to the user to request for their FTP/SSH details in order to connect to the filesystem. |
963 * @since 2.6.0 |
|
964 * |
|
965 * @param string $method Filesystem method to return. |
|
966 * @param array $args An array of connection details for the method. |
|
967 * @param string $context Full path to the directory that is tested for being writable. |
|
968 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. |
|
969 */ |
|
970 return apply_filters( 'filesystem_method', $method, $args, $context, $allow_relaxed_file_ownership ); |
|
971 } |
|
972 |
|
973 /** |
|
974 * Displays a form to the user to request for their FTP/SSH details in order |
|
975 * to connect to the filesystem. |
|
976 * |
922 * All chosen/entered details are saved, Excluding the Password. |
977 * All chosen/entered details are saved, Excluding the Password. |
923 * |
978 * |
924 * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) to specify an alternate FTP/SSH port. |
979 * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467) |
925 * |
980 * to specify an alternate FTP/SSH port. |
926 * Plugins may override this form by returning true|false via the <code>request_filesystem_credentials</code> filter. |
981 * |
927 * |
982 * Plugins may override this form by returning true|false via the |
928 * @since 2.5.0 |
983 * {@see 'request_filesystem_credentials'} filter. |
|
984 * |
|
985 * @since 2.5. |
|
986 * |
|
987 * @todo Properly mark optional arguments as such |
929 * |
988 * |
930 * @param string $form_post the URL to post the form to |
989 * @param string $form_post the URL to post the form to |
931 * @param string $type the chosen Filesystem method in use |
990 * @param string $type the chosen Filesystem method in use |
932 * @param boolean $error if the current request has failed to connect |
991 * @param boolean $error if the current request has failed to connect |
933 * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method() |
992 * @param string $context The directory which is needed access to, The write-test will be performed on this directory by get_filesystem_method() |
934 * @param string $extra_fields Extra POST fields which should be checked for to be included in the post. |
993 * @param array $extra_fields Extra POST fields which should be checked for to be included in the post. |
|
994 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. |
935 * @return boolean False on failure. True on success. |
995 * @return boolean False on failure. True on success. |
936 */ |
996 */ |
937 function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null) { |
997 function request_filesystem_credentials($form_post, $type = '', $error = false, $context = false, $extra_fields = null, $allow_relaxed_file_ownership = false ) { |
938 $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields ); |
998 |
|
999 /** |
|
1000 * Filter the filesystem credentials form output. |
|
1001 * |
|
1002 * Returning anything other than an empty string will effectively short-circuit |
|
1003 * output of the filesystem credentials form, returning that value instead. |
|
1004 * |
|
1005 * @since 2.5.0 |
|
1006 * |
|
1007 * @param mixed $output Form output to return instead. Default empty. |
|
1008 * @param string $form_post URL to POST the form to. |
|
1009 * @param string $type Chosen type of filesystem. |
|
1010 * @param bool $error Whether the current request has failed to connect. |
|
1011 * Default false. |
|
1012 * @param string $context Full path to the directory that is tested for |
|
1013 * being writable. |
|
1014 * @param bool $allow_relaxed_file_ownership Whether to allow Group/World writable. |
|
1015 * @param array $extra_fields Extra POST fields. |
|
1016 */ |
|
1017 $req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership ); |
939 if ( '' !== $req_cred ) |
1018 if ( '' !== $req_cred ) |
940 return $req_cred; |
1019 return $req_cred; |
941 |
1020 |
942 if ( empty($type) ) |
1021 if ( empty($type) ) { |
943 $type = get_filesystem_method(array(), $context); |
1022 $type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership ); |
|
1023 } |
944 |
1024 |
945 if ( 'direct' == $type ) |
1025 if ( 'direct' == $type ) |
946 return true; |
1026 return true; |
947 |
1027 |
948 if ( is_null( $extra_fields ) ) |
1028 if ( is_null( $extra_fields ) ) |