_wp_handle_upload

The timeline below displays how wordpress function _wp_handle_upload has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.4

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      {
 *     Reference to a single element from `$_FILES`. Call the function once for each uploaded file.
 *
 *     @type string $name     The original name of the file on the client machine.
 *     @type string $type     The mime type of the file, if the browser provided this information.
 *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
 *     @type int    $size     The size, in bytes, of the uploaded file.
 *     @type int    $error    The error code associated with this file upload.
 * }
 * @param array|false $overrides {
 *     An array of override parameters for this file, or boolean false if none are provided.
 *
 *     @type callable $upload_error_handler     Function to call when there is an error during the upload process.
 *                                              See {@see wp_handle_upload_error()}.
 *     @type callable $unique_filename_callback Function to call when determining a unique file name for the file.
 *                                              See {@see wp_unique_filename()}.
 *     @type string[] $upload_error_strings     The strings that describe the error indicated in
 *                                              `$_FILES[{form field}]['error']`.
 *     @type bool     $test_form                Whether to test that the `$_POST['action']` parameter is as expected.
 *     @type bool     $test_size                Whether to test that the file size is greater than zero bytes.
 *     @type bool     $test_type                Whether to test that the mime type of the file is as expected.
 *     @type string[] $mimes                    Array of allowed mime types keyed by their file extension regex.
 * }
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for `$_POST['action']`.
 * @return array {
 *     On success, returns an associative array of file attributes.
 *     On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *     or `array( 'error' => $message )`.
 *
 *     @type string $file Filename of the newly-uploaded file.
 *     @type string $url  URL of the newly-uploaded file.
 *     @type string $type Mime type of the newly-uploaded file.
 * }
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_prefilter`
     *  - `wp_handle_upload_prefilter`
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     */
    $file = apply_filters("{$action}_prefilter", $file);
    /**
     * Filters the override parameters for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_overrides`
     *  - `wp_handle_upload_overrides`
     *
     * @since 5.7.0
     *
     * @param array|false $overrides An array of override parameters for this file. Boolean false if none are
     *                               provided. See {@see _wp_handle_upload()}.
     * @param array       $file      {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     */
    $overrides = apply_filters("{$action}_overrides", $overrides, $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : null;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] !== $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, you are not allowed to upload this file type.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is returned from the filter, moving the file and any related
     * error reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param array    $file          {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          Mime type of the newly-uploaded file.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (str_starts_with($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        clean_dirsize_cache($new_file);
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the newly-uploaded file.
     *     @type string $type Mime type of the newly-uploaded file.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 6.3

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      {
 *     Reference to a single element from `$_FILES`. Call the function once for each uploaded file.
 *
 *     @type string $name     The original name of the file on the client machine.
 *     @type string $type     The mime type of the file, if the browser provided this information.
 *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
 *     @type int    $size     The size, in bytes, of the uploaded file.
 *     @type int    $error    The error code associated with this file upload.
 * }
 * @param array|false $overrides {
 *     An array of override parameters for this file, or boolean false if none are provided.
 *
 *     @type callable $upload_error_handler     Function to call when there is an error during the upload process.
 *                                              @see wp_handle_upload_error().
 *     @type callable $unique_filename_callback Function to call when determining a unique file name for the file.
 *                                              @see wp_unique_filename().
 *     @type string[] $upload_error_strings     The strings that describe the error indicated in
 *                                              `$_FILES[{form field}]['error']`.
 *     @type bool     $test_form                Whether to test that the `$_POST['action']` parameter is as expected.
 *     @type bool     $test_size                Whether to test that the file size is greater than zero bytes.
 *     @type bool     $test_type                Whether to test that the mime type of the file is as expected.
 *     @type string[] $mimes                    Array of allowed mime types keyed by their file extension regex.
 * }
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for `$_POST['action']`.
 * @return array {
 *     On success, returns an associative array of file attributes.
 *     On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *     or `array( 'error' => $message )`.
 *
 *     @type string $file Filename of the newly-uploaded file.
 *     @type string $url  URL of the newly-uploaded file.
 *     @type string $type Mime type of the newly-uploaded file.
 * }
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_prefilter`
     *  - `wp_handle_upload_prefilter`
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     */
    $file = apply_filters("{$action}_prefilter", $file);
    /**
     * Filters the override parameters for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_overrides`
     *  - `wp_handle_upload_overrides`
     *
     * @since 5.7.0
     *
     * @param array|false $overrides An array of override parameters for this file. Boolean false if none are
     *                               provided. @see _wp_handle_upload().
     * @param array       $file      {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     */
    $overrides = apply_filters("{$action}_overrides", $overrides, $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : null;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] !== $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, you are not allowed to upload this file type.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is returned from the filter, moving the file and any related
     * error reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param array    $file          {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          Mime type of the newly-uploaded file.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (str_starts_with($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        clean_dirsize_cache($new_file);
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the newly-uploaded file.
     *     @type string $type Mime type of the newly-uploaded file.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.9

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      {
 *     Reference to a single element from `$_FILES`. Call the function once for each uploaded file.
 *
 *     @type string $name     The original name of the file on the client machine.
 *     @type string $type     The mime type of the file, if the browser provided this information.
 *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
 *     @type int    $size     The size, in bytes, of the uploaded file.
 *     @type int    $error    The error code associated with this file upload.
 * }
 * @param array|false $overrides {
 *     An array of override parameters for this file, or boolean false if none are provided.
 *
 *     @type callable $upload_error_handler     Function to call when there is an error during the upload process.
 *                                              @see wp_handle_upload_error().
 *     @type callable $unique_filename_callback Function to call when determining a unique file name for the file.
 *                                              @see wp_unique_filename().
 *     @type string[] $upload_error_strings     The strings that describe the error indicated in
 *                                              `$_FILES[{form field}]['error']`.
 *     @type bool     $test_form                Whether to test that the `$_POST['action']` parameter is as expected.
 *     @type bool     $test_size                Whether to test that the file size is greater than zero bytes.
 *     @type bool     $test_type                Whether to test that the mime type of the file is as expected.
 *     @type string[] $mimes                    Array of allowed mime types keyed by their file extension regex.
 * }
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for `$_POST['action']`.
 * @return array {
 *     On success, returns an associative array of file attributes.
 *     On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *     or `array( 'error' => $message )`.
 *
 *     @type string $file Filename of the newly-uploaded file.
 *     @type string $url  URL of the newly-uploaded file.
 *     @type string $type Mime type of the newly-uploaded file.
 * }
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_prefilter`
     *  - `wp_handle_upload_prefilter`
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     */
    $file = apply_filters("{$action}_prefilter", $file);
    /**
     * Filters the override parameters for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_overrides`
     *  - `wp_handle_upload_overrides`
     *
     * @since 5.7.0
     *
     * @param array|false $overrides An array of override parameters for this file. Boolean false if none are
     *                               provided. @see _wp_handle_upload().
     * @param array       $file      {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     */
    $overrides = apply_filters("{$action}_overrides", $overrides, $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] !== $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, you are not allowed to upload this file type.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is returned from the filter, moving the file and any related
     * error reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param array    $file          {
     *     Reference to a single element from `$_FILES`.
     *
     *     @type string $name     The original name of the file on the client machine.
     *     @type string $type     The mime type of the file, if the browser provided this information.
     *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
     *     @type int    $size     The size, in bytes, of the uploaded file.
     *     @type int    $error    The error code associated with this file upload.
     * }
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          Mime type of the newly-uploaded file.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        clean_dirsize_cache($new_file);
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the newly-uploaded file.
     *     @type string $type Mime type of the newly-uploaded file.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.8

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param string[]       $file      Reference to a single element of `$_FILES`.
 *                                  Call the function once for each uploaded file.
 * @param array|false    $overrides {
 *     An array of override parameters for this file, or boolean false if none are provided.
 *
 *     @type callable $upload_error_handler     Function to call when there is an error during the upload process.
 *                                              @see wp_handle_upload_error().
 *     @type callable $unique_filename_callback Function to call when determining a unique file name for the file.
 *                                              @see wp_unique_filename().
 *     @type string[] $upload_error_strings     The strings that describe the error indicated in
 *                                              `$_FILES[{form field}]['error']`.
 *     @type bool     $test_form                Whether to test that the `$_POST['action']` parameter is as expected.
 *     @type bool     $test_size                Whether to test that the file size is greater than zero bytes.
 *     @type bool     $test_type                Whether to test that the mime type of the file is as expected.
 *     @type string[] $mimes                    Array of allowed mime types keyed by their file extension regex.
 * }
 * @param string         $time      Time formatted in 'yyyy/mm'.
 * @param string         $action    Expected value for `$_POST['action']`.
 * @return string[] On success, returns an associative array of file attributes.
 *                  On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *                  or `array( 'error' => $message )`.
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_prefilter`
     *  - `wp_handle_upload_prefilter`
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param string[] $file An array of data for the file. Reference to a single element of `$_FILES`.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    /**
     * Filters the override parameters for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * Possible hook names include:
     *
     *  - `wp_handle_sideload_overrides`
     *  - `wp_handle_upload_overrides`
     *
     * @since 5.7.0
     *
     * @param array|false $overrides An array of override parameters for this file. Boolean false if none are
     *                               provided. @see _wp_handle_upload().
     * @param string[]    $file      An array of data for the file. Reference to a single element of `$_FILES`.
     */
    $overrides = apply_filters("{$action}_overrides", $overrides, $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] !== $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is returned from the filter, moving the file and any related
     * error reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param string[] $file          An array of data for a single file.
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          Mime type of the newly-uploaded file.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        clean_dirsize_cache($new_file);
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the newly-uploaded file.
     *     @type string $type Mime type of the newly-uploaded file.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.7

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param string[]       $file      Reference to a single element of `$_FILES`.
 *                                  Call the function once for each uploaded file.
 * @param array|false    $overrides {
 *     An array of override parameters for this file, or boolean false if none are provided.
 *
 *     @type callable $upload_error_handler     Function to call when there is an error during the upload process.
 *                                              @see wp_handle_upload_error().
 *     @type callable $unique_filename_callback Function to call when determining a unique file name for the file.
 *                                              @see wp_unique_filename().
 *     @type string[] $upload_error_strings     The strings that describe the error indicated in
 *                                              `$_FILES[{form field}]['error']`.
 *     @type bool     $test_form                Whether to test that the `$_POST['action']` parameter is as expected.
 *     @type bool     $test_size                Whether to test that the file size is greater than zero bytes.
 *     @type bool     $test_type                Whether to test that the mime type of the file is as expected.
 *     @type string[] $mimes                    Array of allowed mime types keyed by their file extension regex.
 * }
 * @param string         $time      Time formatted in 'yyyy/mm'.
 * @param string         $action    Expected value for `$_POST['action']`.
 * @return string[] On success, returns an associative array of file attributes.
 *                  On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *                  or `array( 'error' => $message )`.
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     * Possible filter names include:
     *
     *  - `wp_handle_sideload_prefilter`
     *  - `wp_handle_upload_prefilter`
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param string[] $file An array of data for the file. Reference to a single element of `$_FILES`.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    /**
     * Filters the override parameters for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     * Possible filter names include:
     *
     *  - `wp_handle_sideload_overrides`
     *  - `wp_handle_upload_overrides`
     *
     * @since 5.7.0
     *
     * @param array|false $overrides An array of override parameters for this file. Boolean false if none are
     *                               provided. @see _wp_handle_upload().
     * @param string[]    $file      An array of data for the file. Reference to a single element of `$_FILES`.
     */
    $overrides = apply_filters("{$action}_overrides", $overrides, $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is returned from the filter, moving the file and any related
     * error reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param string[] $file          An array of data for a single file.
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          Mime type of the newly-uploaded file.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        clean_dirsize_cache($new_file);
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the newly-uploaded file.
     *     @type string $type Mime type of the newly-uploaded file.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.6

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param string[]       $file      Reference to a single element of `$_FILES`.
 *                                  Call the function once for each uploaded file.
 * @param string[]|false $overrides An associative array of names => values
 *                                  to override default variables. Default false.
 * @param string         $time      Time formatted in 'yyyy/mm'.
 * @param string         $action    Expected value for `$_POST['action']`.
 * @return string[] On success, returns an associative array of file attributes.
 *                  On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *                  or `array( 'error' => $message )`.
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param string[] $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is returned from the filter, moving the file and any related
     * error reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param string[] $file          An array of data for a single file.
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          Mime type of the newly-uploaded file.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        clean_dirsize_cache($new_file);
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the newly-uploaded file.
     *     @type string $type Mime type of the newly-uploaded file.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.5

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param string[]       $file      Reference to a single element of `$_FILES`.
 *                                  Call the function once for each uploaded file.
 * @param string[]|false $overrides An associative array of names => values
 *                                  to override default variables. Default false.
 * @param string         $time      Time formatted in 'yyyy/mm'.
 * @param string         $action    Expected value for `$_POST['action']`.
 * @return string[] On success, returns an associative array of file attributes.
 *                  On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *                  or `array( 'error' => $message )`.
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param string[] $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is returned from the filter, moving the file and any related
     * error reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param string[] $file          An array of data for a single file.
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          Mime type of the newly-uploaded file.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the newly-uploaded file.
     *     @type string $type Mime type of the newly-uploaded file.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.4

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param string[]       $file      Reference to a single element of `$_FILES`. Call the function once for each uploaded file.
 * @param string[]|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string         $time      Time formatted in 'yyyy/mm'.
 * @param string         $action    Expected value for `$_POST['action']`.
 * @return string[] On success, returns an associative array of file attributes. On failure, returns
 *                  `$overrides['upload_error_handler']( &$file, $message )` or `array( 'error' => $message )`.
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param string[] $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler'].
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback'].
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, sprintf(
            /* translators: 1: upload_max_filesize, 2: php.ini */
            __('The uploaded file exceeds the %1$s directive in %2$s.'),
            'upload_max_filesize',
            'php.ini'
        ), sprintf(
            /* translators: %s: MAX_FILE_SIZE */
            __('The uploaded file exceeds the %s directive that was specified in the HTML form.'),
            'MAX_FILE_SIZE'
        ), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $error_msg = sprintf(
                /* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
                __('File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.'),
                'php.ini',
                'post_max_size',
                'upload_max_filesize'
            );
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is passed to the filter, moving the file and any related error
     * reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param string[] $file          An array of data for a single file.
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          File type.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // Use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.3

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param string[]       $file      Reference to a single element of `$_FILES`. Call the function once for each uploaded file.
 * @param string[]|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string         $time      Time formatted in 'yyyy/mm'.
 * @param string         $action    Expected value for `$_POST['action']`.
 * @return string[] On success, returns an associative array of file attributes. On failure, returns
 *                  `$overrides['upload_error_handler']( &$file, $message )` or `array( 'error' => $message )`.
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param string[] $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have originally been intended to be overridable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    $uploads = wp_upload_dir($time);
    if (!($uploads && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is passed to the filter, moving the file and any related error
     * reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param mixed    $move_new_file If null (default) move the file after the upload.
     * @param string[] $file          An array of data for a single file.
     * @param string   $new_file      Filename of the newly-uploaded file.
     * @param string   $type          File type.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // use copy and unlink because rename breaks streams.
            // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(
                /* translators: %s: Destination file path. */
                __('The uploaded file could not be moved to %s.'),
                $error_path
            ));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 5.1

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param string[]       $file      Reference to a single element of `$_FILES`. Call the function once for each uploaded file.
 * @param string[]|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string         $time      Time formatted in 'yyyy/mm'.
 * @param string         $action    Expected value for `$_POST['action']`.
 * @return string[] On success, returns an associative array of file attributes. On failure, returns
 *               `$overrides['upload_error_handler'](&$file, $message )` or `array( 'error'=>$message )`.
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param string[] $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_readable($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is passed to the filter, moving the file and any related error
     * reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param string $move_new_file If null (default) move the file after the upload.
     * @param string $file          An array of data for a single file.
     * @param string $new_file      Filename of the newly-uploaded file.
     * @param string $type          File type.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // use copy and unlink because rename breaks streams.
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 4.9

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      Reference to a single element of $_FILES. Call the function once for each uploaded file.
 * @param array|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    /**
     * Filters whether to short-circuit moving the uploaded file after passing all checks.
     *
     * If a non-null value is passed to the filter, moving the file and any related error
     * reporting will be completely skipped.
     *
     * @since 4.9.0
     *
     * @param string $move_new_file If null (default) move the file after the upload.
     * @param string $file          An array of data for a single file.
     * @param string $new_file      Filename of the newly-uploaded file.
     * @param string $type          File type.
     */
    $move_new_file = apply_filters('pre_move_uploaded_file', null, $file, $new_file, $type);
    if (null === $move_new_file) {
        if ('wp_handle_upload' === $action) {
            $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
        } else {
            // use copy and unlink because rename breaks streams.
            $move_new_file = @copy($file['tmp_name'], $new_file);
            unlink($file['tmp_name']);
        }
        if (false === $move_new_file) {
            if (0 === strpos($uploads['basedir'], ABSPATH)) {
                $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
            } else {
                $error_path = basename($uploads['basedir']) . $uploads['subdir'];
            }
            return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
        }
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 4.6

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      Reference to a single element of $_FILES. Call the function once for each uploaded file.
 * @param array|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filters the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return call_user_func_array($upload_error_handler, array(&$file, $file['error']));
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Invalid form submission.')));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func_array($upload_error_handler, array(&$file, $upload_error_strings[$file['error']]));
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func_array($upload_error_handler, array(&$file, $error_msg));
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func_array($upload_error_handler, array(&$file, __('Specified file failed upload test.')));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func_array($upload_error_handler, array(&$file, __('Sorry, this file type is not permitted for security reasons.')));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func_array($upload_error_handler, array(&$file, $uploads['error']));
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    if ('wp_handle_upload' === $action) {
        $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
    } else {
        // use copy and unlink because rename breaks streams.
        $move_new_file = @copy($file['tmp_name'], $new_file);
        unlink($file['tmp_name']);
    }
    if (false === $move_new_file) {
        if (0 === strpos($uploads['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
        } else {
            $error_path = basename($uploads['basedir']) . $uploads['subdir'];
        }
        return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filters the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 4.5

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      Reference to a single element of $_FILES. Call the function once for each uploaded file.
 * @param array|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
 */
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filter the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return $upload_error_handler($file, $file['error']);
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func($upload_error_handler, $file, __('Invalid form submission.'));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']]);
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func($upload_error_handler, $file, $error_msg);
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func($upload_error_handler, $file, __('Specified file failed upload test.'));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func($upload_error_handler, $file, __('Sorry, this file type is not permitted for security reasons.'));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func($upload_error_handler, $file, $uploads['error']);
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    if ('wp_handle_upload' === $action) {
        $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
    } else {
        // use copy and unlink because rename breaks streams.
        $move_new_file = @copy($file['tmp_name'], $new_file);
        unlink($file['tmp_name']);
    }
    if (false === $move_new_file) {
        if (0 === strpos($uploads['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
        } else {
            $error_path = basename($uploads['basedir']) . $uploads['subdir'];
        }
        return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filter the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 4.4

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      Reference to a single element of $_FILES. Call the function once for each uploaded file.
 * @param array|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
*/
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filter the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return $upload_error_handler($file, $file['error']);
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func($upload_error_handler, $file, __('Invalid form submission.'));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']]);
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func($upload_error_handler, $file, $error_msg);
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func($upload_error_handler, $file, __('Specified file failed upload test.'));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func($upload_error_handler, $file, __('Sorry, this file type is not permitted for security reasons.'));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func($upload_error_handler, $file, $uploads['error']);
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    if ('wp_handle_upload' === $action) {
        $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
    } else {
        // use copy and unlink because rename breaks streams.
        $move_new_file = @copy($file['tmp_name'], $new_file);
        unlink($file['tmp_name']);
    }
    if (false === $move_new_file) {
        if (0 === strpos($uploads['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
        } else {
            $error_path = basename($uploads['basedir']) . $uploads['subdir'];
        }
        return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filter the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 4.2

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      Reference to a single element of $_FILES. Call the function once for each uploaded file.
 * @param array|false $overrides An associative array of names => values to override default variables. Default false.
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
*/
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filter the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return $upload_error_handler($file, $file['error']);
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func($upload_error_handler, $file, __('Invalid form submission.'));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']]);
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func($upload_error_handler, $file, $error_msg);
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func($upload_error_handler, $file, __('Specified file failed upload test.'));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func($upload_error_handler, $file, __('Sorry, this file type is not permitted for security reasons.'));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func($upload_error_handler, $file, $uploads['error']);
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    if ('wp_handle_upload' === $action) {
        $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
    } else {
        $move_new_file = @rename($file['tmp_name'], $new_file);
    }
    if (false === $move_new_file) {
        if (0 === strpos($uploads['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
        } else {
            $error_path = basename($uploads['basedir']) . $uploads['subdir'];
        }
        return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filter the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 4.1

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array  $file      Reference to a single element of $_FILES. Call the function once for
 *                          each uploaded file.
 * @param array  $overrides An associative array of names => values to override default variables.
 * @param string $time      Time formatted in 'yyyy/mm'.
 * @param string $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
*/
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * Filter the data for a file before it is uploaded to WordPress.
     *
     * The dynamic portion of the hook name, `$action`, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'.
     * @since 4.0.0 Converted to a dynamic hook with `$action`.
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return $upload_error_handler($file, $file['error']);
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func($upload_error_handler, $file, __('Invalid form submission.'));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']]);
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func($upload_error_handler, $file, $error_msg);
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if (!$test_uploaded_file) {
        return call_user_func($upload_error_handler, $file, __('Specified file failed upload test.'));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func($upload_error_handler, $file, __('Sorry, this file type is not permitted for security reasons.'));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func($upload_error_handler, $file, $uploads['error']);
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    if ('wp_handle_upload' === $action) {
        $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
    } else {
        $move_new_file = @rename($file['tmp_name'], $new_file);
    }
    if (false === $move_new_file) {
        if (0 === strpos($uploads['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
        } else {
            $error_path = basename($uploads['basedir']) . $uploads['subdir'];
        }
        return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filter the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}

WordPress Version: 4.0

/**
 * Handle PHP uploads in WordPress, sanitizing file names, checking extensions for mime type,
 * and moving the file to the appropriate directory within the uploads directory.
 *
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array  $file      Reference to a single element of $_FILES. Call the function once for
 *                          each uploaded file.
 * @param array  $overrides An associative array of names => values to override default variables.
 * @param string $time      Time formatted in 'yyyy/mm'.
 * @param string $action    Expected value for $_POST['action'].
 * @return array On success, returns an associative array of file attributes. On failure, returns
 *               $overrides['upload_error_handler'](&$file, $message ) or array( 'error'=>$message ).
*/
function _wp_handle_upload(&$file, $overrides, $time, $action)
{
    // The default error handler.
    if (!function_exists('wp_handle_upload_error')) {
        function wp_handle_upload_error(&$file, $message)
        {
            return array('error' => $message);
        }
    }
    /**
     * The dynamic portion of the hook name, $action, refers to the post action.
     *
     * @since 2.9.0 as 'wp_handle_upload_prefilter'
     * @since 4.0.0 Converted to a dynamic hook with $action
     *
     * @param array $file An array of data for a single file.
     */
    $file = apply_filters("{$action}_prefilter", $file);
    // You may define your own function and pass the name in $overrides['upload_error_handler']
    $upload_error_handler = 'wp_handle_upload_error';
    if (isset($overrides['upload_error_handler'])) {
        $upload_error_handler = $overrides['upload_error_handler'];
    }
    // You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
    if (isset($file['error']) && !is_numeric($file['error']) && $file['error']) {
        return $upload_error_handler($file, $file['error']);
    }
    // Install user overrides. Did we mention that this voids your warranty?
    // You may define your own function and pass the name in $overrides['unique_filename_callback']
    $unique_filename_callback = null;
    if (isset($overrides['unique_filename_callback'])) {
        $unique_filename_callback = $overrides['unique_filename_callback'];
    }
    /*
     * This may not have orignially been intended to be overrideable,
     * but historically has been.
     */
    if (isset($overrides['upload_error_strings'])) {
        $upload_error_strings = $overrides['upload_error_strings'];
    } else {
        // Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
        $upload_error_strings = array(false, __('The uploaded file exceeds the upload_max_filesize directive in php.ini.'), __('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'), __('The uploaded file was only partially uploaded.'), __('No file was uploaded.'), '', __('Missing a temporary folder.'), __('Failed to write file to disk.'), __('File upload stopped by extension.'));
    }
    // All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
    $test_form = isset($overrides['test_form']) ? $overrides['test_form'] : true;
    $test_size = isset($overrides['test_size']) ? $overrides['test_size'] : true;
    // If you override this, you must provide $ext and $type!!
    $test_type = isset($overrides['test_type']) ? $overrides['test_type'] : true;
    $mimes = isset($overrides['mimes']) ? $overrides['mimes'] : false;
    $test_upload = isset($overrides['test_upload']) ? $overrides['test_upload'] : true;
    // A correct form post will pass this test.
    if ($test_form && (!isset($_POST['action']) || $_POST['action'] != $action)) {
        return call_user_func($upload_error_handler, $file, __('Invalid form submission.'));
    }
    // A successful upload will pass this test. It makes no sense to override this one.
    if (isset($file['error']) && $file['error'] > 0) {
        return call_user_func($upload_error_handler, $file, $upload_error_strings[$file['error']]);
    }
    $test_file_size = ('wp_handle_upload' === $action) ? $file['size'] : filesize($file['tmp_name']);
    // A non-empty file will pass this test.
    if ($test_size && !($test_file_size > 0)) {
        if (is_multisite()) {
            $error_msg = __('File is empty. Please upload something more substantial.');
        } else {
            $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.');
        }
        return call_user_func($upload_error_handler, $file, $error_msg);
    }
    // A properly uploaded file will pass this test. There should be no reason to override this one.
    $test_uploaded_file = ('wp_handle_upload' === $action) ? @is_uploaded_file($file['tmp_name']) : @is_file($file['tmp_name']);
    if ($test_upload && !$test_uploaded_file) {
        return call_user_func($upload_error_handler, $file, __('Specified file failed upload test.'));
    }
    // A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
    if ($test_type) {
        $wp_filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name'], $mimes);
        $ext = empty($wp_filetype['ext']) ? '' : $wp_filetype['ext'];
        $type = empty($wp_filetype['type']) ? '' : $wp_filetype['type'];
        $proper_filename = empty($wp_filetype['proper_filename']) ? '' : $wp_filetype['proper_filename'];
        // Check to see if wp_check_filetype_and_ext() determined the filename was incorrect
        if ($proper_filename) {
            $file['name'] = $proper_filename;
        }
        if ((!$type || !$ext) && !current_user_can('unfiltered_upload')) {
            return call_user_func($upload_error_handler, $file, __('Sorry, this file type is not permitted for security reasons.'));
        }
        if (!$type) {
            $type = $file['type'];
        }
    } else {
        $type = '';
    }
    /*
     * A writable uploads dir will pass this test. Again, there's no point
     * overriding this one.
     */
    if (!(($uploads = wp_upload_dir($time)) && false === $uploads['error'])) {
        return call_user_func($upload_error_handler, $file, $uploads['error']);
    }
    $filename = wp_unique_filename($uploads['path'], $file['name'], $unique_filename_callback);
    // Move the file to the uploads dir.
    $new_file = $uploads['path'] . "/{$filename}";
    if ('wp_handle_upload' === $action) {
        $move_new_file = @move_uploaded_file($file['tmp_name'], $new_file);
    } else {
        $move_new_file = @rename($file['tmp_name'], $new_file);
    }
    if (false === $move_new_file) {
        if (0 === strpos($uploads['basedir'], ABSPATH)) {
            $error_path = str_replace(ABSPATH, '', $uploads['basedir']) . $uploads['subdir'];
        } else {
            $error_path = basename($uploads['basedir']) . $uploads['subdir'];
        }
        return $upload_error_handler($file, sprintf(__('The uploaded file could not be moved to %s.'), $error_path));
    }
    // Set correct file permissions.
    $stat = stat(dirname($new_file));
    $perms = $stat['mode'] & 0666;
    @chmod($new_file, $perms);
    // Compute the URL.
    $url = $uploads['url'] . "/{$filename}";
    if (is_multisite()) {
        delete_transient('dirsize_cache');
    }
    /**
     * Filter the data array for the uploaded file.
     *
     * @since 2.1.0
     *
     * @param array  $upload {
     *     Array of upload data.
     *
     *     @type string $file Filename of the newly-uploaded file.
     *     @type string $url  URL of the uploaded file.
     *     @type string $type File type.
     * }
     * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
     */
    return apply_filters('wp_handle_upload', array('file' => $new_file, 'url' => $url, 'type' => $type), ('wp_handle_sideload' === $action) ? 'sideload' : 'upload');
}