+ if ( empty( $name ) )
+ return array( 'error' => __( 'Empty filename' ) );
+
+ $wp_filetype = wp_check_filetype( $name );
+ if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) )
+ return array( 'error' => __( 'Invalid file type' ) );
+
+ $upload = wp_upload_dir( $time );
+
+ if ( $upload['error'] !== false )
+ return $upload;
+
+ $upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) );
+ if ( !is_array( $upload_bits_error ) ) {
+ $upload[ 'error' ] = $upload_bits_error;
+ return $upload;
+ }
+
+ $filename = wp_unique_filename( $upload['path'], $name );
+
+ $new_file = $upload['path'] . "/$filename";
+ if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
+ if ( 0 === strpos( $upload['basedir'], ABSPATH ) )
+ $error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir'];
+ else
+ $error_path = basename( $upload['basedir'] ) . $upload['subdir'];
+
+ $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
+ return array( 'error' => $message );
+ }
+
+ $ifp = @ fopen( $new_file, 'wb' );
+ if ( ! $ifp )
+ return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
+
+ @fwrite( $ifp, $bits );
+ fclose( $ifp );
+ clearstatcache();
+
+ // Set correct file permissions
+ $stat = @ stat( dirname( $new_file ) );
+ $perms = $stat['mode'] & 0007777;
+ $perms = $perms & 0000666;
+ @ chmod( $new_file, $perms );
+ clearstatcache();
+
+ // Compute the URL
+ $url = $upload['url'] . "/$filename";
+
+ return array( 'file' => $new_file, 'url' => $url, 'error' => false );
+}
+
+/**
+ * Retrieve the file type based on the extension name.
+ *
+ * @package WordPress
+ * @since 2.5.0
+ * @uses apply_filters() Calls 'ext2type' hook on default supported types.
+ *
+ * @param string $ext The extension to search.
+ * @return string|null The file type, example: audio, video, document, spreadsheet, etc. Null if not found.
+ */
+function wp_ext2type( $ext ) {
+ $ext2type = apply_filters( 'ext2type', array(
+ 'audio' => array( 'aac', 'ac3', 'aif', 'aiff', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
+ 'video' => array( 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ),
+ 'document' => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'rtf', 'wp', 'wpd' ),
+ 'spreadsheet' => array( 'numbers', 'ods', 'xls', 'xlsx', 'xlsm', 'xlsb' ),
+ 'interactive' => array( 'swf', 'key', 'ppt', 'pptx', 'pptm', 'pps', 'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
+ 'text' => array( 'asc', 'csv', 'tsv', 'txt' ),
+ 'archive' => array( 'bz2', 'cab', 'dmg', 'gz', 'rar', 'sea', 'sit', 'sqx', 'tar', 'tgz', 'zip', '7z' ),
+ 'code' => array( 'css', 'htm', 'html', 'php', 'js' ),
+ ));
+ foreach ( $ext2type as $type => $exts )
+ if ( in_array( $ext, $exts ) )
+ return $type;
+}
+
+/**
+ * Retrieve the file type from the file name.
+ *
+ * You can optionally define the mime array, if needed.
+ *
+ * @since 2.0.4
+ *
+ * @param string $filename File name or path.
+ * @param array $mimes Optional. Key is the file extension with value as the mime type.
+ * @return array Values with extension first and mime type.
+ */
+function wp_check_filetype( $filename, $mimes = null ) {
+ if ( empty($mimes) )
+ $mimes = get_allowed_mime_types();
+ $type = false;
+ $ext = false;
+
+ foreach ( $mimes as $ext_preg => $mime_match ) {
+ $ext_preg = '!\.(' . $ext_preg . ')$!i';
+ if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
+ $type = $mime_match;
+ $ext = $ext_matches[1];
+ break;
+ }
+ }
+
+ return compact( 'ext', 'type' );
+}
+
+/**
+ * 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 image.
+ * @param string $filename The filename of the image (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 );
+ }