Index: wp-admin/includes/ajax-actions.php
===================================================================
--- wp-admin/includes/ajax-actions.php	(revision 22533)
+++ wp-admin/includes/ajax-actions.php	(working copy)
@@ -1850,19 +1850,39 @@
 		wp_send_json_error();
 
 	$changes = $_REQUEST['changes'];
-	$args    = array();
+	$post    = get_post( $id, ARRAY_A );
 
-	if ( ! empty( $changes['title'] ) )
-		$args['post_title'] = $changes['title'];
+	if ( 'attachment' != $post['post_type'] )
+		wp_send_json_error();
 
-	if ( ! empty( $changes['caption'] ) )
-		$args['post_excerpt'] = $changes['caption'];
+	if ( isset( $changes['title'] ) )
+		$post['post_title'] = $changes['title'];
 
-	if ( ! empty( $changes['alt'] ) )
-		$args['_wp_attachment_image_alt'] = $changes['alt'];
+	if ( isset( $changes['caption'] ) )
+		$post['post_excerpt'] = $changes['caption'];
 
-	if ( $args )
-		edit_post( array_merge( $args, array( 'post_ID' => $id ) ) );
+	$post = apply_filters( 'attachment_fields_to_save', $post, $attachment );
 
+	if ( isset( $post['errors'] ) ) {
+		$errors = array( $attachment_id => $post['errors'] ); // @todo return me and display me!
+		unset( $post['errors'] );
+	}
+
+	if ( isset( $changes['alt'] ) ) {
+		$alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
+		$new_alt = stripslashes( $changes['alt'] );
+		if ( $alt != $new_alt ) {
+			$new_alt = wp_strip_all_tags( $new_alt, true );
+			update_post_meta( $id, '_wp_attachment_image_alt', addslashes( $new_alt ) );
+		}
+	}
+
+	wp_update_post( $post );
+
+	foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) {
+		if ( isset( $changes[ $taxonomy ] ) )
+			wp_set_object_terms( $id, array_map( 'trim', preg_split( '/,+/', $changes[ $taxonomy ] ) ), $taxonomy, false );
+	}
+
 	wp_send_json_success();
 }
Index: wp-admin/includes/media.php
===================================================================
--- wp-admin/includes/media.php	(revision 22533)
+++ wp-admin/includes/media.php	(working copy)
@@ -1269,6 +1269,100 @@
 	return $item;
 }
 
+function get_bastardized_media_item( $attachment_id, $args = null ) {
+	$post = get_post( $attachment_id );
+
+	$default_args = array(
+		'errors' => null,
+	);
+
+	$args = wp_parse_args( $args, $default_args );
+	$args = apply_filters( 'get_media_item_args', $args );
+
+	$errors = $args['errors'];
+
+	$form_fields = get_attachment_fields_to_edit( $post, $errors );
+
+	$media_meta = apply_filters( 'media_meta', '', $post );
+
+	$defaults = array(
+		'input'      => 'text',
+		'required'   => false,
+		'value'      => '',
+		'extra_rows' => array(),
+	);
+
+	$hidden_fields = array();
+
+	unset( $form_fields['image-size'], $form_fields['align'], $form_fields['image_alt'],
+		$form_fields['post_title'], $form_fields['post_excerpt'], $form_fields['post_content'],
+		$form_fields['url'], $form_fields['menu_order'], $form_fields['image_url'] );
+
+	$item = '';
+	foreach ( $form_fields as $name => $field ) {
+		if ( $name[0] == '_' )
+			continue;
+
+		if ( !empty( $field['tr'] ) ) {
+			$item .= $field['tr'];
+			continue;
+		}
+
+		$field = array_merge( $defaults, $field );
+
+		if ( $field['input'] == 'hidden' ) {
+			$hidden_fields[$name] = $field['value'];
+			continue;
+		}
+
+		$required      = $field['required'] ? '<span class="alignright"><abbr title="required" class="required">*</abbr></span>' : '';
+		$aria_required = $field['required'] ? " aria-required='true' " : '';
+		$class  = $name;
+		$class .= $field['required'] ? ' form-required' : '';
+
+		$item .= "\t\t<tr class='$class'>";
+		$item .= "\t\t\t<th valign='top' scope='row' class='label'><label for='$name'><span class='alignleft'>{$field['label']}</span>$required<br class='clear' /></label>";
+		$item .= "</th>\n\t\t\t<td class='field'>";
+
+		if ( !empty( $field[ $field['input'] ] ) )
+			$item .= $field[ $field['input'] ];
+		elseif ( $field['input'] == 'textarea' ) {
+			if ( 'post_content' == $name && user_can_richedit() ) {
+				// sanitize_post() skips the post_content when user_can_richedit
+				$field['value'] = htmlspecialchars( $field['value'], ENT_QUOTES );
+			}
+			$item .= "<textarea id='$name' name='$name' $aria_required>" . $field['value'] . '</textarea>';
+		} else {
+			$item .= "<input type='text' class='text' id='$name' name='$name' value='" . esc_attr( $field['value'] ) . "' $aria_required />";
+		}
+		if ( !empty( $field['helps'] ) )
+			$item .= "<p class='help'>" . join( "</p>\n<p class='help'>", array_unique( (array) $field['helps'] ) ) . '</p>';
+		$item .= "</td>\n\t\t</tr>\n";
+
+		$extra_rows = array();
+
+		if ( !empty( $field['errors'] ) )
+			foreach ( array_unique( (array) $field['errors'] ) as $error )
+				$extra_rows['error'][] = $error;
+
+		if ( !empty( $field['extra_rows'] ) )
+			foreach ( $field['extra_rows'] as $class => $rows )
+				foreach ( (array) $rows as $html )
+					$extra_rows[$class][] = $html;
+
+		foreach ( $extra_rows as $class => $rows )
+			foreach ( $rows as $html )
+				$item .= "\t\t<tr><td></td><td class='$class'>$html</td></tr>\n";
+	}
+
+	if ( !empty( $form_fields['_final'] ) )
+		$item .= "\t\t<tr class='final'><td colspan='2'>{$form_fields['_final']}</td></tr>\n";
+	if ( $item )
+		$item = '<table>' . $item . '</table>';
+
+	return compact( 'item', 'hidden_fields', 'media_meta' );
+}
+
 /**
  * {@internal Missing Short Description}}
  *
