Index: wp-includes/functions-post.php
===================================================================
--- wp-includes/functions-post.php	(revision 2920)
+++ wp-includes/functions-post.php	(working copy)
@@ -128,9 +128,9 @@
 	} else {
 		$postquery =
 			"INSERT INTO $wpdb->posts
-			(ID, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,  post_status, comment_status, ping_status, post_password, post_name, to_ping, post_modified, post_modified_gmt, post_parent, menu_order)
+			(ID, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,  post_status, comment_status, ping_status, post_password, post_name, to_ping, post_modified, post_modified_gmt, post_parent, menu_order, post_type)
 			VALUES
-			('$post_ID', '$post_author', '$post_date', '$post_date_gmt', '$post_content', '$post_title', '$post_excerpt', '$post_status', '$comment_status', '$ping_status', '$post_password', '$post_name', '$to_ping', '$post_date', '$post_date_gmt', '$post_parent', '$menu_order')";
+			('$post_ID', '$post_author', '$post_date', '$post_date_gmt', '$post_content', '$post_title', '$post_excerpt', '$post_status', '$comment_status', '$ping_status', '$post_password', '$post_name', '$to_ping', '$post_date', '$post_date_gmt', '$post_parent', '$menu_order', '$post_type')";
 	}
 	
 	$result = $wpdb->query($postquery);
@@ -185,6 +185,124 @@
 	return $post_ID;
 }
 
+function wp_attach_object($object, $post_parent = 0) {
+	global $wpdb, $user_ID;
+	
+	// Export array as variables
+	extract($object);
+
+	// Get the basics.
+	$post_content    = apply_filters('content_save_pre',   $post_content);
+	$post_excerpt    = apply_filters('excerpt_save_pre',   $post_excerpt);
+	$post_title      = apply_filters('title_save_pre',     $post_title);
+	$post_category   = apply_filters('category_save_pre',  $post_category);
+	$post_name       = apply_filters('name_save_pre',      $post_name);
+	$comment_status  = apply_filters('comment_status_pre', $comment_status);
+	$ping_status     = apply_filters('ping_status_pre',    $ping_status);
+	$post_type       = apply_filters('post_type_pre',      $post_type);
+
+	// Make sure we set a valid category
+	if (0 == count($post_category) || !is_array($post_category)) {
+		$post_category = array(get_option('default_category'));
+	}
+	$post_cat = $post_category[0];
+
+	if ( empty($post_author) )
+		$post_author = $user_ID;
+
+	$post_status = 'object';
+
+	// Get the post ID.
+	if ( $update ) {
+		$post_ID = $ID;
+	} else {
+		$id_result = $wpdb->get_row("SHOW TABLE STATUS LIKE '$wpdb->posts'");
+		$post_ID = $id_result->Auto_increment;
+	}
+
+	// Create a valid post name.
+	if ( empty($post_name) ) {
+		$post_name = sanitize_title($post_title, $post_ID);
+	} else {
+		$post_name = sanitize_title($post_name, $post_ID);
+	}
+	
+	if (empty($post_date))
+		$post_date = current_time('mysql');
+	if (empty($post_date_gmt)) 
+		$post_date_gmt = current_time('mysql', 1);
+
+	if ( empty($comment_status) ) {
+		if ( $update )
+			$comment_status = 'closed';
+		else
+			$comment_status = get_settings('default_comment_status');
+	}
+	if ( empty($ping_status) )
+		$ping_status = get_settings('default_ping_status');
+	if ( empty($post_pingback) )
+		$post_pingback = get_option('default_pingback_flag');
+
+	if ( isset($to_ping) )
+		$to_ping = preg_replace('|\s+|', "\n", $to_ping);
+	else
+		$to_ping = '';
+	
+	$post_parent = (int) $post_parent;
+
+	if ( isset($menu_order) )
+		$menu_order = (int) $menu_order;
+	else
+		$menu_order = 0;
+
+	if ( !isset($post_password) )
+		$post_password = '';
+
+	if ($update) {
+		$postquery =
+			"UPDATE $wpdb->posts SET
+			post_author = '$post_author',
+			post_date = '$post_date',
+			post_date_gmt = '$post_date_gmt',
+			post_content = '$post_content',
+			post_title = '$post_title',
+			post_excerpt = '$post_excerpt',
+			post_status = '$post_status',
+			comment_status = '$comment_status',
+			ping_status = '$ping_status',
+			post_password = '$post_password',
+			post_name = '$post_name',
+			to_ping = '$to_ping',
+			post_modified = '$post_date',
+			post_modified_gmt = '$post_date_gmt',
+			post_parent = '$post_parent',
+			menu_order = '$menu_order',
+			post_type = '$post_type',
+			guid = '$guid'
+			WHERE ID = $post_ID";
+	} else {
+		$postquery =
+			"INSERT INTO $wpdb->posts
+			(ID, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt,  post_status, comment_status, ping_status, post_password, post_name, to_ping, post_modified, post_modified_gmt, post_parent, menu_order, post_type, guid)
+			VALUES
+			('$post_ID', '$post_author', '$post_date', '$post_date_gmt', '$post_content', '$post_title', '$post_excerpt', '$post_status', '$comment_status', '$ping_status', '$post_password', '$post_name', '$to_ping', '$post_date', '$post_date_gmt', '$post_parent', '$menu_order', '$post_type', '$guid')";
+	}
+	
+	$result = $wpdb->query($postquery);
+
+	wp_set_post_cats('', $post_ID, $post_category);
+
+	clean_post_cache($post_ID);
+
+	if ( $update) {
+		do_action('edit_object', $post_ID);
+	} else {
+		do_action('attach_object', $post_ID);
+	}
+	
+	return $post_ID;
+}
+
 function wp_get_single_post($postid = 0, $mode = OBJECT) {
 	global $wpdb;
 
Index: wp-admin/wp-admin.css
===================================================================
--- wp-admin/wp-admin.css	(revision 2920)
+++ wp-admin/wp-admin.css	(working copy)
@@ -148,7 +148,7 @@
 	line-height: 130%;
 }
 
-textarea, input, select {
+textarea, input, select, iframe#imageup {
 	background: #f4f4f4;
 	border: 1px solid #b2b2b2;
 	color: #000;
@@ -157,6 +157,14 @@
 	padding: 3px;
 }
 
+iframe#imageup {
+	margin: 0px;
+	padding: 0px;
+	border: 1px solid #ccc;
+	height: 13em;
+	width: 98%;
+}
+
 .alignleft {
 	float: left
 }
Index: wp-admin/admin-functions.php
===================================================================
--- wp-admin/admin-functions.php	(revision 2920)
+++ wp-admin/admin-functions.php	(working copy)
@@ -60,9 +60,19 @@
 	$post_ID = wp_insert_post($_POST);
 	add_meta($post_ID);
 
+	// Reunite any orphaned subposts with their parent
+	if ( $_POST['temp_ID'] )
+		relocate_children($_POST['temp_ID'], $post_ID);
+
 	return $post_ID;
 }
 
+// Move child posts to a new parent
+function relocate_children($old_ID, $new_ID) {
+	global $wpdb;
+	$wpdb->query("UPDATE $wpdb->posts SET post_parent = $new_ID WHERE post_parent = $old_ID");
+}
+
 // Update an existing post with values provided in $_POST.
 function edit_post() {
 	global $user_ID;
@@ -1739,4 +1749,46 @@
 	$ct->author = $themes[$current_theme]['Author'];
 	return $ct;
 }
-?>
\ No newline at end of file
+
+// Returns an array containing the current upload directory's path and url, or an error message.
+function wp_upload_dir() {
+        if ( defined('UPLOADS') )
+                $dir = UPLOADS;
+        else
+                $dir = 'wp-content/uploads';
+
+	$path = ABSPATH . $dir;
+
+        // Make sure we have an uploads dir
+        if ( ! file_exists( $path ) ) {
+                if ( ! mkdir( $path ) )
+                        return array('error' => "Unable to create directory $path. Is its parent directory writable by the server?");
+		@ chmod( ABSPATH . $path, 0774 );
+	}
+
+        // Generate the yearly and monthly dirs
+        $time = current_time( 'mysql' );
+        $y = substr( $time, 0, 4 );
+        $m = substr( $time, 5, 2 );
+        $pathy = "$path/$y";
+        $pathym = "$path/$y/$m";
+
+        // Make sure we have a yearly dir
+        if ( ! file_exists( $pathy ) ) {
+                if ( ! mkdir( $pathy ) )
+                        return array('error' => "Unable to create directory $pathy. Is $path writable?");
+		@ chmod( $pathy, 0774 );
+	}
+
+        // Make sure we have a monthly dir
+        if ( ! file_exists( $pathym ) ) {
+                if ( ! mkdir( $pathym ) )
+                        return array('error' => "Unable to create directory $pathym. Is $pathy writable?");
+		@ chmod( $pathym, 0774 );
+	}
+
+        $uploads = array('path' => $pathym, 'url' => get_bloginfo('home') . "/$dir/$y/$m", 'error' => false);
+	return apply_filters('upload_dir', $uploads);
+}
+
+?>
Index: wp-admin/edit-form-advanced.php
===================================================================
--- wp-admin/edit-form-advanced.php	(revision 2920)
+++ wp-admin/edit-form-advanced.php	(working copy)
@@ -17,6 +17,8 @@
 
 if (0 == $post_ID) {
 	$form_action = 'post';
+	$temp_ID = -1 * time();
+	$form_extra = "<input type='hidden' name='temp_ID' value='$temp_ID' />";
 } else {
 	$form_action = 'editpost';
 	$form_extra = "<input type='hidden' name='post_ID' value='$post_ID' />";
@@ -172,6 +174,11 @@
 
 <div id="advancedstuff" class="dbx-group" >
 
+<fieldset id="imageuploading" class="dbx-box">
+<h3 class="dbx-handle"><?php _e('Image Uploading') ?></h3>
+<div class="dbx-content"><iframe src="image-uploading.php?action=view&amp;post=<?php echo 0 == $post_ID ? $temp_ID : $post_ID; ?>" id="imageup"></iframe></div>
+</fieldset>
+
 <fieldset id="postexcerpt" class="dbx-box">
 <h3 class="dbx-handle"><?php _e('Optional Excerpt') ?></h3>
 <div class="dbx-content"><textarea rows="1" cols="40" name="excerpt" tabindex="7" id="excerpt"><?php echo $post->post_excerpt ?></textarea></div>
@@ -213,4 +220,4 @@
 
 </div>
 
-</form>
\ No newline at end of file
+</form>
Index: wp-admin/upgrade-schema.php
===================================================================
--- wp-admin/upgrade-schema.php	(revision 2920)
+++ wp-admin/upgrade-schema.php	(working copy)
@@ -119,6 +119,7 @@
   post_parent bigint(20) NOT NULL default '0',
   guid varchar(255) NOT NULL default '',
   menu_order int(11) NOT NULL default '0',
+  post_type varchar(100) NOT NULL,
   PRIMARY KEY  (ID),
   KEY post_name (post_name)
 );
