Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 8525)
+++ wp-includes/post.php	(working copy)
@@ -482,6 +482,8 @@
 	} elseif ( ! empty($r['exclude']) )
 		$r['post__not_in'] = preg_split('/[\s,]+/',$r['exclude']);
 
+	$r['caller_get_posts'] = true;
+
 	$get_posts = new WP_Query;
 	return $get_posts->query($r);
 
@@ -750,6 +752,30 @@
 }
 
 /**
+ * is_sticky() - Check if post is sticky
+ *
+ * {@internal Missing Long Description}}
+ *
+ * @package WordPress
+ * @subpackage Post
+ * @since 2.7
+ *
+ * @param int $post_id A post ID
+ * @return bool
+ */
+function is_sticky($post_id) {
+	$stickies = get_option('sticky_posts');
+
+	if ( !is_array($stickies) )
+		return false;
+
+	if ( in_array($post_id, $stickies) )
+		return true;
+
+	return false;
+}
+
+/**
  * sanitize_post() - Sanitize every post field
  *
  * {@internal Missing Long Description}}
@@ -847,6 +873,36 @@
 	return $value;
 }
 
+function stick_post($post_id) {
+	$stickies = get_option('sticky_posts');
+
+	if ( !is_array($stickies) )
+		$stickies = array($post_id);
+
+	if ( ! in_array($post_id, $stickies) )
+		$stickies[] = $post_id;
+
+	update_option('sticky_posts', $stickies);
+}
+
+function unstick_post($post_id) {
+	$stickies = get_option('sticky_posts');
+
+	if ( !is_array($stickies) )
+		return;
+
+	if ( ! in_array($post_id, $stickies) )
+		return;
+
+	$offset = array_search($post_id, $stickies);
+	if ( false === $offset )
+		return;
+
+	array_splice($stickies, $offset, 1);
+	
+	update_option('sticky_posts', $stickies);
+}
+
 /**
  * Count number of posts of a post type and is user has permissions to view.
  *
Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 8525)
+++ wp-includes/query.php	(working copy)
@@ -831,6 +831,9 @@
 		$groupby = '';
 		$post_status_join = false;
 
+		if ( !isset($q['caller_get_posts']) )
+			$q['caller_get_posts'] = false;
+
 		if ( !isset($q['post_type']) ) {
 			if ( $this->is_search )
 				$q['post_type'] = 'any';
@@ -1497,6 +1500,40 @@
 			}
 		}
 
+		// Put sticky posts at the top of the posts array
+		$sticky_posts = get_option('sticky_posts');
+		if ( $this->is_home && $page <= 1 && !empty($sticky_posts) && !$q['caller_get_posts'] ) {
+			$num_posts = count($this->posts);
+			$post_ids = array();
+			$sticky_offset = 0;
+			// Loop over posts and relocate stickies to the front.
+			for ( $i = 0; $i < $num_posts; $i++ ) {
+				if ( in_array($this->posts[$i]->ID, $sticky_posts) ) {
+					$sticky_post = $this->posts[$i];
+					// Remove sticky from current position
+					array_splice($this->posts, $i, 1);
+					// Move to front, after other stickies
+					array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
+					//Increment the sticky offset.  The next sticky goes here.
+					$sticky_offset++;
+					// Remove post from sticky posts array
+					$offset = array_search($sticky_post->ID, $sticky_posts);
+					array_splice($sticky_posts, $offset, 1);
+				}
+			}
+
+			// Fetch sticky posts that weren't in the query results
+			$stickies__in = implode(',', array_map( 'absint', $sticky_posts ));
+			$stickies = $wpdb->get_results( "SELECT * FROM $wpdb->posts WHERE $wpdb->posts.ID IN ($stickies__in)" );
+			// TODO Make sure post is published or viewable by the current user
+			foreach ( $stickies as $sticky_post ) {
+				if ( 'publish' != $sticky_post->post_status )
+					continue;
+				array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
+				$sticky_offset++;
+			}
+		}
+
 		$this->posts = apply_filters('the_posts', $this->posts);
 
 		update_post_caches($this->posts);
Index: wp-admin/includes/post.php
===================================================================
--- wp-admin/includes/post.php	(revision 8525)
+++ wp-admin/includes/post.php	(working copy)
@@ -161,6 +161,11 @@
 
 	wp_set_post_lock( $post_ID, $GLOBALS['current_user']->ID );
 
+	if ( !empty($_POST['sticky']) )
+		stick_post($post_ID);
+	else
+		unstick_post($post_ID);
+
 	return $post_ID;
 }
 
Index: wp-admin/edit-form-advanced.php
===================================================================
--- wp-admin/edit-form-advanced.php	(revision 8525)
+++ wp-admin/edit-form-advanced.php	(working copy)
@@ -117,7 +117,8 @@
 </p>
 
 <?php if ( current_user_can( 'publish_posts' ) ) : ?>
-<p><label for="post_status_private" class="selectit"><input id="post_status_private" name="post_status" type="checkbox" value="private" <?php checked($post->post_status, 'private'); ?> tabindex="4" /> <?php _e('Keep this post private') ?></label></p>
+<p><label for="post_status_private" class="selectit"><input id="post_status_private" name="post_status" type="checkbox" value="private" <?php checked($post->post_status, 'private'); ?> tabindex="4" /> <?php _e('Keep this post private') ?></label><br />
+<label for="sticky" class="selectit"><input id="sticky" name="sticky" type="checkbox" value="sticky" <?php checked(is_sticky($post->ID), true); ?> tabindex="4" /> <?php _e('Stick this post to the front page') ?></label></p>
 <?php endif; ?>
 <?php
 if ($post_ID) {
