From bf93e9699f61cd781910ac08af29b1980f30e612 Mon Sep 17 00:00:00 2001 From: Jake Spurlock Date: Fri, 10 Jul 2020 06:06:46 +0000 Subject: [PATCH] Upgrade/Install: Ensure cleanup after canceled update. Ensure that the uploaded zip is hidden from the media library, where a task will remove failed installs after two hours. Fixes #50612. Props psykro, desrosj, joyously, azaozz, noisysocks, whyisjake. git-svn-id: https://develop.svn.wordpress.org/trunk@48417 602fd350-edb4-49c9-b593-d223f7449a82 --- src/js/_enqueues/admin/common.js | 29 +++++++++++++ .../includes/class-plugin-installer-skin.php | 12 ++++-- .../includes/class-theme-installer-skin.php | 12 ++++-- .../includes/class-wp-media-list-table.php | 23 ++++++++++ src/wp-admin/update.php | 42 +++++++++++++++++++ 5 files changed, 112 insertions(+), 6 deletions(-) diff --git a/src/js/_enqueues/admin/common.js b/src/js/_enqueues/admin/common.js index 8734ee72f4..7265ae4612 100644 --- a/src/js/_enqueues/admin/common.js +++ b/src/js/_enqueues/admin/common.js @@ -1606,6 +1606,35 @@ $document.ready( function() { }); }); +// On the "Update plugin/theme from uploaded zip" screen +// hide the "Replace current with uploaded" button and show a warning in 1 hour and 59 minutes. +$document.ready( function( $ ) { + var $overwrite, $warning; + + if ( ! $body.hasClass( 'update-php' ) ) { + return; + } + + $overwrite = $( 'a.update-from-upload-overwrite' ); + $warning = $( '.update-from-upload-expired' ); + + if ( ! $overwrite.length || ! $warning.length ) { + return; + } + + window.setTimeout( + function() { + $overwrite.hide(); + $warning.removeClass( 'hidden' ); + + if ( window.wp && window.wp.a11y ) { + window.wp.a11y.speak( $warning.text() ); + } + }, + 7140000 // 119 minutes. The uploaded file is deleted after 2 hours. + ); +} ); + // Fire a custom jQuery event at the end of window resize. ( function() { var timeout; diff --git a/src/wp-admin/includes/class-plugin-installer-skin.php b/src/wp-admin/includes/class-plugin-installer-skin.php index 9cc5646f0b..d2c038702a 100644 --- a/src/wp-admin/includes/class-plugin-installer-skin.php +++ b/src/wp-admin/includes/class-plugin-installer-skin.php @@ -292,17 +292,19 @@ class Plugin_Installer_Skin extends WP_Upgrader_Skin { $overwrite = $this->is_downgrading ? 'downgrade-plugin' : 'update-plugin'; $install_actions['ovewrite_plugin'] = sprintf( - '%s', + '%s', wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'plugin-upload' ), - esc_html( __( 'Replace current with uploaded' ) ) + __( 'Replace current with uploaded' ) ); } else { echo $blocked_message; } + $cancel_url = add_query_arg( 'action', 'upload-plugin-cancel-overwrite', $this->url ); + $install_actions['plugins_page'] = sprintf( '%s', - self_admin_url( 'plugin-install.php' ), + wp_nonce_url( $cancel_url, 'plugin-upload-cancel-overwrite' ), __( 'Cancel and go back' ) ); @@ -318,6 +320,10 @@ class Plugin_Installer_Skin extends WP_Upgrader_Skin { $install_actions = apply_filters( 'install_plugin_ovewrite_actions', $install_actions, $this->api, $this->upgrader->new_plugin_data ); if ( ! empty( $install_actions ) ) { + printf( + '', + __( 'The uploaded file has expired. Please go back and upload it again.' ) + ); echo '

' . implode( ' ', (array) $install_actions ) . '

'; } diff --git a/src/wp-admin/includes/class-theme-installer-skin.php b/src/wp-admin/includes/class-theme-installer-skin.php index 89835f287f..2cdc698909 100644 --- a/src/wp-admin/includes/class-theme-installer-skin.php +++ b/src/wp-admin/includes/class-theme-installer-skin.php @@ -321,17 +321,19 @@ class Theme_Installer_Skin extends WP_Upgrader_Skin { $overwrite = $this->is_downgrading ? 'downgrade-theme' : 'update-theme'; $install_actions['ovewrite_theme'] = sprintf( - '%s', + '%s', wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'theme-upload' ), - esc_html( __( 'Replace current with uploaded' ) ) + __( 'Replace current with uploaded' ) ); } else { echo $blocked_message; } + $cancel_url = add_query_arg( 'action', 'upload-theme-cancel-overwrite', $this->url ); + $install_actions['themes_page'] = sprintf( '%s', - self_admin_url( 'theme-install.php' ), + wp_nonce_url( $cancel_url, 'theme-upload-cancel-overwrite' ), __( 'Cancel and go back' ) ); @@ -347,6 +349,10 @@ class Theme_Installer_Skin extends WP_Upgrader_Skin { $install_actions = apply_filters( 'install_theme_ovewrite_actions', $install_actions, $this->api, $this->upgrader->new_theme_data ); if ( ! empty( $install_actions ) ) { + printf( + '', + __( 'The uploaded file has expired. Please go back and upload it again.' ) + ); echo '

' . implode( ' ', (array) $install_actions ) . '

'; } diff --git a/src/wp-admin/includes/class-wp-media-list-table.php b/src/wp-admin/includes/class-wp-media-list-table.php index 630553d63f..1724b96728 100644 --- a/src/wp-admin/includes/class-wp-media-list-table.php +++ b/src/wp-admin/includes/class-wp-media-list-table.php @@ -69,6 +69,29 @@ class WP_Media_List_Table extends WP_List_Table { public function prepare_items() { global $wp_query, $post_mime_types, $avail_post_mime_types, $mode; + // Exclude attachments scheduled for deletion in the next two hours + // if they are for zip packages for interrupted or failed updates. + // See File_Upload_Upgrader class. + $not_in = array(); + + foreach ( _get_cron_array() as $cron ) { + if ( isset( $cron['upgrader_scheduled_cleanup'] ) ) { + $details = reset( $cron['upgrader_scheduled_cleanup'] ); + + if ( ! empty( $details['args'][0] ) ) { + $not_in[] = (int) $details['args'][0]; + } + } + } + + if ( ! empty( $_REQUEST['post__not_in'] ) && is_array( $_REQUEST['post__not_in'] ) ) { + $not_in = array_merge( array_values( $_REQUEST['post__not_in'] ), $not_in ); + } + + if ( ! empty( $not_in ) ) { + $_REQUEST['post__not_in'] = $not_in; + } + list( $post_mime_types, $avail_post_mime_types ) = wp_edit_attachments_query( $_REQUEST ); $this->is_trash = isset( $_REQUEST['attachment-filter'] ) && 'trash' === $_REQUEST['attachment-filter']; diff --git a/src/wp-admin/update.php b/src/wp-admin/update.php index 700c0a779c..7980ea7a8b 100644 --- a/src/wp-admin/update.php +++ b/src/wp-admin/update.php @@ -17,6 +17,8 @@ require_once __DIR__ . '/admin.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; +wp_enqueue_script( 'wp-a11y' ); + if ( isset( $_GET['action'] ) ) { $plugin = isset( $_REQUEST['plugin'] ) ? trim( $_REQUEST['plugin'] ) : ''; $theme = isset( $_REQUEST['theme'] ) ? urldecode( $_REQUEST['theme'] ) : ''; @@ -174,6 +176,26 @@ if ( isset( $_GET['action'] ) ) { require_once ABSPATH . 'wp-admin/admin-footer.php'; + } elseif ( 'upload-plugin-cancel-overwrite' === $action ) { + if ( ! current_user_can( 'upload_plugins' ) ) { + wp_die( __( 'Sorry, you are not allowed to install plugins on this site.' ) ); + } + + check_admin_referer( 'plugin-upload-cancel-overwrite' ); + + // Make sure the attachment still exists, or File_Upload_Upgrader will call wp_die() + // that shows a generic "Please select a file" error. + if ( ! empty( $_GET['package'] ) ) { + $attachment_id = (int) $_GET['package']; + + if ( get_post( $attachment_id ) ) { + $file_upload = new File_Upload_Upgrader( 'pluginzip', 'package' ); + $file_upload->cleanup(); + } + } + + wp_redirect( self_admin_url( 'plugin-install.php' ) ); + exit; } elseif ( 'upgrade-theme' === $action ) { if ( ! current_user_can( 'update_themes' ) ) { @@ -297,6 +319,26 @@ if ( isset( $_GET['action'] ) ) { require_once ABSPATH . 'wp-admin/admin-footer.php'; + } elseif ( 'upload-theme-cancel-overwrite' === $action ) { + if ( ! current_user_can( 'upload_themes' ) ) { + wp_die( __( 'Sorry, you are not allowed to install themes on this site.' ) ); + } + + check_admin_referer( 'theme-upload-cancel-overwrite' ); + + // Make sure the attachment still exists, or File_Upload_Upgrader will call wp_die() + // that shows a generic "Please select a file" error. + if ( ! empty( $_GET['package'] ) ) { + $attachment_id = (int) $_GET['package']; + + if ( get_post( $attachment_id ) ) { + $file_upload = new File_Upload_Upgrader( 'themezip', 'package' ); + $file_upload->cleanup(); + } + } + + wp_redirect( self_admin_url( 'theme-install.php' ) ); + exit; } else { /** * Fires when a custom plugin or theme update request is received.