Index: wp-admin/includes/meta-boxes.php
===================================================================
--- wp-admin/includes/meta-boxes.php	(revision 24974)
+++ wp-admin/includes/meta-boxes.php	(revision )
@@ -14,7 +14,15 @@
 
 	$post_type = $post->post_type;
 	$post_type_object = get_post_type_object($post_type);
-	$can_publish = current_user_can($post_type_object->cap->publish_posts);
+    $can_publish = current_user_can($post_type_object->cap->publish_posts);
+    $unpublished_parent = false;
+    if ( isset( $post->post_parent ) && $post->post_parent ) {
+        $parent_status = get_post_status( $post->post_parent );
+        if ( 'publish' !== $parent_status ) {
+            $unpublished_parent = true;
+            $post->post_status = $parent_status;
+        }
+    }
 ?>
 <div class="submitbox" id="submitpost">
 
@@ -23,6 +31,8 @@
 <?php // Hidden submit button early on so that the browser chooses the right button when form is submitted with Return key ?>
 <div style="display:none;">
 <?php submit_button( __( 'Save' ), 'button', 'save' ); ?>
+<input type="hidden" name="unpublished_parent" id="unpublished_parent" value="<?php if ( $unpublished_parent ) echo
+1; else echo 0; ?>" />
 </div>
 
 <div id="minor-publishing-actions">
@@ -124,7 +134,9 @@
 }
 
 echo esc_html( $visibility_trans ); ?></span>
-<?php if ( $can_publish ) { ?>
+<?php if ( $unpublished_parent ) { ?>
+<p><?php printf('To publish this page, you must first <a href="%s">publish its parent page</a>.', get_edit_post_link( $post->post_parent ) ); ?></p>
+<?php } elseif ( $can_publish ) { ?>
 <a href="#visibility" class="edit-visibility hide-if-no-js"><?php _e('Edit'); ?></a>
 
 <div id="post-visibility-select" class="hide-if-js">
@@ -220,7 +232,8 @@
 <div id="publishing-action">
 <span class="spinner"></span>
 <?php
-if ( !in_array( $post->post_status, array('publish', 'future', 'private') ) || 0 == $post->ID ) {
+if ( !$unpublished_parent && !in_array( $post->post_status, array('publish', 'future',
+        'private') ) || 0 == $post->ID ) {
 	if ( $can_publish ) :
 		if ( !empty($post->post_date_gmt) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) : ?>
 		<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Schedule') ?>" />
Index: wp-includes/post-template.php
===================================================================
--- wp-includes/post-template.php	(revision 24974)
+++ wp-includes/post-template.php	(revision )
@@ -784,6 +784,11 @@
 	);
 
 	$r = wp_parse_args( $args, $defaults );
+	$r = apply_filters( 'wp_dropdown_pages_args', $r );
+    // revert to default (public) post_status on the Reading Settings page
+    $screen = get_current_screen();
+    if ( 'options-reading' == $screen->base )
+        unset( $r['post_status'] );
 	extract( $r, EXTR_SKIP );
 
 	$pages = get_pages($r);
@@ -829,6 +834,7 @@
 	);
 
 	$r = wp_parse_args( $args, $defaults );
+	$r = apply_filters( 'wp_list_pages_args', $r );
 	extract( $r, EXTR_SKIP );
 
 	$output = '';
Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 24974)
+++ wp-includes/post.php	(revision )
@@ -2675,8 +2675,23 @@
 	if ( empty($post_type) )
 		$post_type = 'post';
 
+    if ( isset($post_parent) )
+        $post_parent = (int) $post_parent;
+    else
+        $post_parent = 0;
+
+    // Check the post_parent to see if it will cause a hierarchy loop
+    $post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr ) ), $postarr );
+
+    // Check to see if the post parent is unpublished. If so, set this post status to match.
+	if ( isset( $post_parent ) && $post_parent ) {
+        $post_parent_object = get_post( $post_parent );
+        if ( 'publish' !== $post_parent_object->post_status ) {
+            $post_status = $post_parent_object->post_status;
+        }
+    }
-	if ( empty($post_status) )
-		$post_status = 'draft';
+    if ( empty($post_status) )
+        $post_status = 'draft';
 
 	if ( !empty($post_category) )
 		$post_category = array_filter($post_category); // Filter out empty terms
@@ -2770,14 +2785,6 @@
 
 	if ( ! isset($pinged) )
 		$pinged = '';
-
-	if ( isset($post_parent) )
-		$post_parent = (int) $post_parent;
-	else
-		$post_parent = 0;
-
-	// Check the post_parent to see if it will cause a hierarchy loop
-	$post_parent = apply_filters( 'wp_insert_post_parent', $post_parent, $post_ID, compact( array_keys( $postarr ) ), $postarr );
 
 	if ( isset($menu_order) )
 		$menu_order = (int) $menu_order;
Index: wp-admin/js/post.js
===================================================================
--- wp-admin/js/post.js	(revision 24974)
+++ wp-admin/js/post.js	(revision )
@@ -515,7 +515,7 @@
 			if ( attemptedDate > currentDate && $('#original_post_status').val() != 'future' ) {
 				publishOn = postL10n.publishOnFuture;
 				$('#publish').val( postL10n.schedule );
-			} else if ( attemptedDate <= currentDate && $('#original_post_status').val() != 'publish' ) {
+			} else if ( attemptedDate <= currentDate && $('#original_post_status').val() != 'publish' && $('#unpublished_parent').val() != 1 ) {
 				publishOn = postL10n.publishOn;
 				$('#publish').val( postL10n.publish );
 			} else {
Index: wp-includes/js/autosave.js
===================================================================
--- wp-includes/js/autosave.js	(revision 24974)
+++ wp-includes/js/autosave.js	(revision )
@@ -176,6 +176,9 @@
 
 			if ( res.responses[0].data ) // update autosave message
 				jQuery('.autosave-message').text( res.responses[0].data );
+
+            if ( res.responses[0].supplemental.parent_status ) // update hidden unpublished_parent field
+                jQuery('#unpublished_parent').val( res.responses[0].supplemental.parent_status );
 		}
 	}
 
Index: wp-admin/includes/ajax-actions.php
===================================================================
--- wp-admin/includes/ajax-actions.php	(revision 24974)
+++ wp-admin/includes/ajax-actions.php	(revision )
@@ -1081,6 +1081,10 @@
 				$id = $post->ID;
 		}
 
+        $parent_status = get_post_status( $post->post_parent );
+        if ( $parent_status !== 'publish' )
+            $supplemental['replace-unpublished_parent'] = 1;
+
 		if ( ! is_wp_error($id) ) {
 			/* translators: draft saved date format, see http://php.net/date */
 			$draft_saved_date_format = __('g:i:s a');
