wp_check_filetype_and_ext

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

WordPress Version: 6.5

/**
 * Attempts to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string        $file     Full path to the file.
 * @param string        $filename The name of the file (may differ from $file due to $file being
 *                                in a tmp directory).
 * @param string[]|null $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
 *                                Defaults to the result of get_allowed_mime_types().
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && str_starts_with($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime !== $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif', 'image/webp' => 'webp', 'image/avif' => 'avif'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename !== $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        $google_docs_types = array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        foreach ($google_docs_types as $google_docs_type) {
            /*
             * finfo_file() can return duplicate mime type for Google docs,
             * this conditional reduces it to a single instance.
             *
             * @see https://bugs.php.net/bug.php?id=77784
             * @see https://core.trac.wordpress.org/ticket/57898
             */
            if (2 === substr_count($real_mime, $google_docs_type)) {
                $real_mime = $google_docs_type;
            }
        }
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (str_starts_with($real_mime, 'video/') || str_starts_with($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array         $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string        $file                      Full path to the file.
     * @param string        $filename                  The name of the file (may differ from $file due to
     *                                                 $file being in a tmp directory).
     * @param string[]|null $mimes                     Array of mime types keyed by their file extension regex, or null if
     *                                                 none were provided.
     * @param string|false  $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 6.4

/**
 * Attempts to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string        $file     Full path to the file.
 * @param string        $filename The name of the file (may differ from $file due to $file being
 *                                in a tmp directory).
 * @param string[]|null $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
 *                                Defaults to the result of get_allowed_mime_types().
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && str_starts_with($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime !== $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif', 'image/webp' => 'webp'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename !== $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        $google_docs_types = array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        foreach ($google_docs_types as $google_docs_type) {
            /*
             * finfo_file() can return duplicate mime type for Google docs,
             * this conditional reduces it to a single instance.
             *
             * @see https://bugs.php.net/bug.php?id=77784
             * @see https://core.trac.wordpress.org/ticket/57898
             */
            if (2 === substr_count($real_mime, $google_docs_type)) {
                $real_mime = $google_docs_type;
            }
        }
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (str_starts_with($real_mime, 'video/') || str_starts_with($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array         $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string        $file                      Full path to the file.
     * @param string        $filename                  The name of the file (may differ from $file due to
     *                                                 $file being in a tmp directory).
     * @param string[]|null $mimes                     Array of mime types keyed by their file extension regex, or null if
     *                                                 none were provided.
     * @param string|false  $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 6.3

/**
 * Attempts to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string        $file     Full path to the file.
 * @param string        $filename The name of the file (may differ from $file due to $file being
 *                                in a tmp directory).
 * @param string[]|null $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
 *                                Defaults to the result of get_allowed_mime_types().
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && str_starts_with($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif', 'image/webp' => 'webp'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (str_starts_with($real_mime, 'video/') || str_starts_with($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array         $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string        $file                      Full path to the file.
     * @param string        $filename                  The name of the file (may differ from $file due to
     *                                                 $file being in a tmp directory).
     * @param string[]|null $mimes                     Array of mime types keyed by their file extension regex, or null if
     *                                                 none were provided.
     * @param string|false  $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 6.2

/**
 * Attempts to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string   $file     Full path to the file.
 * @param string   $filename The name of the file (may differ from $file due to $file being
 *                           in a tmp directory).
 * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
 *                           Defaults to the result of get_allowed_mime_types().
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif', 'image/webp' => 'webp'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array        $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string       $file                      Full path to the file.
     * @param string       $filename                  The name of the file (may differ from $file due to
     *                                                $file being in a tmp directory).
     * @param string[]     $mimes                     Array of mime types keyed by their file extension regex.
     * @param string|false $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 6.1

/**
 * Attempts to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string   $file     Full path to the file.
 * @param string   $filename The name of the file (may differ from $file due to $file being
 *                           in a tmp directory).
 * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif', 'image/webp' => 'webp'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array        $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string       $file                      Full path to the file.
     * @param string       $filename                  The name of the file (may differ from $file due to
     *                                                $file being in a tmp directory).
     * @param string[]     $mimes                     Array of mime types keyed by their file extension regex.
     * @param string|false $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 5.8

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string   $file     Full path to the file.
 * @param string   $filename The name of the file (may differ from $file due to $file being
 *                           in a tmp directory).
 * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif', 'image/webp' => 'webp'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array        $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string       $file                      Full path to the file.
     * @param string       $filename                  The name of the file (may differ from $file due to
     *                                                $file being in a tmp directory).
     * @param string[]     $mimes                     Array of mime types keyed by their file extension regex.
     * @param string|false $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 5.7

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string   $file     Full path to the file.
 * @param string   $filename The name of the file (may differ from $file due to $file being
 *                           in a tmp directory).
 * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array        $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string       $file                      Full path to the file.
     * @param string       $filename                  The name of the file (may differ from $file due to
     *                                                $file being in a tmp directory).
     * @param string[]     $mimes                     Array of mime types keyed by their file extension regex.
     * @param string|false $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 5.6

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string   $file     Full path to the file.
 * @param string   $filename The name of the file (may differ from $file due to $file being
 *                           in a tmp directory).
 * @param string[] $mimes    Optional. Array of mime types keyed by their file extension regex.
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'application/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('application/csv' === $real_mime) {
            // Special casing for CSV files.
            if (!in_array($type, array('text/csv', 'text/plain', 'application/csv'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array       $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string      $file                      Full path to the file.
     * @param string      $filename                  The name of the file (may differ from $file due to
     *                                               $file being in a tmp directory).
     * @param string[]    $mimes                     Array of mime types keyed by their file extension regex.
     * @param string|bool $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 5.5

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string   $file     Full path to the file.
 * @param string   $filename The name of the file (may differ from $file due to $file being
 *                           in a tmp directory).
 * @param string[] $mimes    Optional. Array of mime types keyed by their file extension regex.
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'), true)) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'), true)) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed, true)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array       $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string      $file                      Full path to the file.
     * @param string      $filename                  The name of the file (may differ from $file due to
     *                                               $file being in a tmp directory).
     * @param string[]    $mimes                     Array of mime types keyed by their file extension regex.
     * @param string|bool $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 5.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string   $file     Full path to the file.
 * @param string   $filename The name of the file (may differ from $file due to $file being
 *                           in a tmp directory).
 * @param string[] $mimes    Optional. Array of mime types keyed by their file extension regex.
 * @return array {
 *     Values for the extension, mime type, and corrected filename.
 *
 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 * }
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping.
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with.
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is.
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension.
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed.
                }
                // Redefine the extension / MIME.
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types.
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'))) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed.
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array       $wp_check_filetype_and_ext {
     *     Values for the extension, mime type, and corrected filename.
     *
     *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
     *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
     *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
     * }
     * @param string      $file                      Full path to the file.
     * @param string      $filename                  The name of the file (may differ from $file due to
     *                                               $file being in a tmp directory).
     * @param string[]    $mimes                     Array of mime types keyed by their file extension regex.
     * @param string|bool $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 5.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = false;
                $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'))) {
                $type = false;
                $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'))) {
                $type = false;
                $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = false;
            $ext = false;
        }
    }
    // The mime type must be allowed
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = false;
            $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array       $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                               'proper_filename' keys.
     * @param string      $file                      Full path to the file.
     * @param string      $filename                  The name of the file (may differ from $file due to
     *                                               $file being in a tmp directory).
     * @param array       $mimes                     Key is the file extension with value as the mime type.
     * @param string|bool $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 5.1

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'))) {
                $type = $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     * @since 5.1.0 The $real_mime parameter was added.
     *
     * @param array       $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                               'proper_filename' keys.
     * @param string      $file                      Full path to the file.
     * @param string      $filename                  The name of the file (may differ from $file due to
     *                                               $file being in a tmp directory).
     * @param array       $mimes                     Key is the file extension with value as the mime type.
     * @param string|bool $real_mime                 The actual mime type or false if the type cannot be determined.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes, $real_mime);
}

WordPress Version: 0.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'))) {
                $type = $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'))) {
                $type = $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 0.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .18

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'))) {
                $type = $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .10

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } elseif ('text/plain' === $real_mime) {
            // A few common file types are occasionally detected as text/plain; allow those.
            if (!in_array($type, array('text/plain', 'text/csv', 'text/richtext', 'text/tsv', 'text/vtt'))) {
                $type = $ext = false;
            }
        } elseif ('text/rtf' === $real_mime) {
            // Special casing for RTF files.
            if (!in_array($type, array('text/rtf', 'text/plain', 'application/rtf'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 0.1

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 5.0

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        /*
         * If $real_mime doesn't match what we're expecting, we need to do some extra
         * vetting of application mime types to make sure this type of file is allowed.
         * Other mime types are assumed to be safe, but should be considered unverified.
         */
        if ($real_mime && $real_mime !== $type && 0 === strpos($real_mime, 'application')) {
            $allowed = get_allowed_mime_types();
            if (!in_array($real_mime, $allowed)) {
                $type = $ext = false;
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 9.9

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 9.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        /*
         * If $real_mime doesn't match what we're expecting, we need to do some extra
         * vetting of application mime types to make sure this type of file is allowed.
         * Other mime types are assumed to be safe, but should be considered unverified.
         */
        if ($real_mime && $real_mime !== $type && 0 === strpos($real_mime, 'application')) {
            $allowed = get_allowed_mime_types();
            if (!in_array($real_mime, $allowed)) {
                $type = $ext = false;
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .22

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 9.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        /*
         * If $real_mime doesn't match what we're expecting, we need to do some extra
         * vetting of application mime types to make sure this type of file is allowed.
         * Other mime types are assumed to be safe, but should be considered unverified.
         */
        if ($real_mime && $real_mime !== $type && 0 === strpos($real_mime, 'application')) {
            $allowed = get_allowed_mime_types();
            if (!in_array($real_mime, $allowed)) {
                $type = $ext = false;
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .10

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.9

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        /*
         * If $real_mime doesn't match what we're expecting, we need to do some extra
         * vetting of application mime types to make sure this type of file is allowed.
         * Other mime types are assumed to be safe, but should be considered unverified.
         */
        if ($real_mime && $real_mime !== $type && 0 === strpos($real_mime, 'application')) {
            $allowed = get_allowed_mime_types();
            if (!in_array($real_mime, $allowed)) {
                $type = $ext = false;
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 8.8

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 8.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        /*
         * If $real_mime doesn't match what we're expecting, we need to do some extra
         * vetting of application mime types to make sure this type of file is allowed.
         * Other mime types are assumed to be safe, but should be considered unverified.
         */
        if ($real_mime && $real_mime !== $type && 0 === strpos($real_mime, 'application')) {
            $allowed = get_allowed_mime_types();
            if (!in_array($real_mime, $allowed)) {
                $type = $ext = false;
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .10

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 7.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    $real_mime = false;
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if ($real_mime && $real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                // Reset $real_mime and try validating again.
                $real_mime = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        /*
         * If $real_mime doesn't match what we're expecting, we need to do some extra
         * vetting of application mime types to make sure this type of file is allowed.
         * Other mime types are assumed to be safe, but should be considered unverified.
         */
        if ($real_mime && $real_mime !== $type && 0 === strpos($real_mime, 'application')) {
            $allowed = get_allowed_mime_types();
            if (!in_array($real_mime, $allowed)) {
                $type = $ext = false;
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 7.1

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.7

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 6.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .28

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*:
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 6.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .13

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .10

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.6

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filters the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filters the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 5.5

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 5.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 5.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 5.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .16

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .10

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.5

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.6

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .17

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .10

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 3.7

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 3.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 3.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 3.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .18

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .10

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 2.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 2.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .22

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 2.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .11

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 1.5

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .40

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 1.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 1.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .25

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 1.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .14

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 0.4

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 0.3

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .25

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 0.2

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .14

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 4.0

/**
 * Attempt to determine the real file type of a file.
 *
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file     Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being
 *                         in a tmp directory).
 * @param array   $mimes   Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false
 *               if original $filename is valid.
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                    // Mark that it changed
                }
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                $ext = $wp_filetype['ext'];
                $type = $wp_filetype['type'];
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 9.2

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .15

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 3.9

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            /**
             * Filter the list mapping image mime types to their respective extensions.
             *
             * @since 3.0.0
             *
             * @param  array $mime_to_ext Array of image mime types and their matching extensions.
             */
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    /**
     * Filter the "real" file type of the given file.
     *
     * @since 3.0.0
     *
     * @param array  $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
     *                                          'proper_filename' keys.
     * @param string $file                      Full path to the file.
     * @param string $filename                  The name of the file (may differ from $file due to
     *                                          $file being in a tmp directory).
     * @param array  $mimes                     Key is the file extension with value as the mime type.
     */
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 8.4

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 8.3

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .28

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 8.2

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .17

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 7.5

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .40

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 7.4

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .30

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 7.3

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .28

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    }
    // Validate files that didn't get validated during previous checks.
    if ($type && !$real_mime && extension_loaded('fileinfo')) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // fileinfo often misidentifies obscure files as one of these types
        $nonspecific_types = array('application/octet-stream', 'application/encrypted', 'application/CDFV2-encrypted', 'application/zip');
        /*
         * If $real_mime doesn't match the content type we're expecting from the file's extension,
         * we need to do some additional vetting. Media types and those listed in $nonspecific_types are
         * allowed some leeway, but anything else must exactly match the real content type.
         */
        if (in_array($real_mime, $nonspecific_types, true)) {
            // File is a non-specific binary type. That's ok if it's a type that generally tends to be binary.
            if (!in_array(substr($type, 0, strcspn($type, '/')), array('application', 'video', 'audio'))) {
                $type = $ext = false;
            }
        } elseif (0 === strpos($real_mime, 'video/') || 0 === strpos($real_mime, 'audio/')) {
            /*
             * For these types, only the major type must match the real value.
             * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
             * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
             */
            if (substr($real_mime, 0, strcspn($real_mime, '/')) !== substr($type, 0, strcspn($type, '/'))) {
                $type = $ext = false;
            }
        } else if ($type !== $real_mime) {
            /*
             * Everything else including image/* and application/*: 
             * If the real content type doesn't match the file extension, assume it's dangerous.
             */
            $type = $ext = false;
        }
    }
    // The mime type must be allowed 
    if ($type) {
        $allowed = get_allowed_mime_types();
        if (!in_array($type, $allowed)) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .20

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 7.2

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: .17

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports renaming images validated via wp_get_image_mime().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // Validate image types.
    if ($type && 0 === strpos($type, 'image/')) {
        // Attempt to figure out what type of image it actually is
        $real_mime = wp_get_image_mime($file);
        if (!$real_mime) {
            $type = $ext = false;
        } elseif ($real_mime != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$real_mime])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$real_mime];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            } else {
                $type = $ext = false;
            }
        }
    } elseif (function_exists('finfo_file')) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $real_mime = finfo_file($finfo, $file);
        finfo_close($finfo);
        // If the extension does not match the file's real type, return false.
        if ($real_mime !== $type) {
            $type = $ext = false;
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}

WordPress Version: 3.7

/**
 * Attempt to determine the real file type of a file.
 * If unable to, the file name extension will be used to determine type.
 *
 * If it's determined that the extension does not match the file's real type,
 * then the "proper_filename" value will be set with a proper filename and extension.
 *
 * Currently this function only supports validating images known to getimagesize().
 *
 * @since 3.0.0
 *
 * @param string $file Full path to the file.
 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
 * @param array $mimes Optional. Key is the file extension with value as the mime type.
 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
 */
function wp_check_filetype_and_ext($file, $filename, $mimes = null)
{
    $proper_filename = false;
    // Do basic extension validation and MIME mapping
    $wp_filetype = wp_check_filetype($filename, $mimes);
    extract($wp_filetype);
    // We can't do any further validation without a file to work with
    if (!file_exists($file)) {
        return compact('ext', 'type', 'proper_filename');
    }
    // We're able to validate images using GD
    if ($type && 0 === strpos($type, 'image/') && function_exists('getimagesize')) {
        // Attempt to figure out what type of image it actually is
        $imgstats = @getimagesize($file);
        // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
        if (!empty($imgstats['mime']) && $imgstats['mime'] != $type) {
            // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
            // You shouldn't need to use this filter, but it's here just in case
            $mime_to_ext = apply_filters('getimagesize_mimes_to_exts', array('image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/bmp' => 'bmp', 'image/tiff' => 'tif'));
            // Replace whatever is after the last period in the filename with the correct extension
            if (!empty($mime_to_ext[$imgstats['mime']])) {
                $filename_parts = explode('.', $filename);
                array_pop($filename_parts);
                $filename_parts[] = $mime_to_ext[$imgstats['mime']];
                $new_filename = implode('.', $filename_parts);
                if ($new_filename != $filename) {
                    $proper_filename = $new_filename;
                }
                // Mark that it changed
                // Redefine the extension / MIME
                $wp_filetype = wp_check_filetype($new_filename, $mimes);
                extract($wp_filetype);
            }
        }
    }
    // Let plugins try and validate other types of files
    // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
    return apply_filters('wp_check_filetype_and_ext', compact('ext', 'type', 'proper_filename'), $file, $filename, $mimes);
}