Make WordPress Core

Ticket #30921: 30921.diff

File 30921.diff, 2.9 KB (added by dd32, 10 years ago)
  • src/wp-admin/includes/class-wp-upgrader.php

    class WP_Upgrader { 
    405405                 * destination directory (WP_PLUGIN_DIR / wp-content/themes) intending
    406406                 * to copy the directory into the directory, whilst they pass the source
    407407                 * as the actual files to copy.
    408408                 */
    409409                $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );
    410410
    411411                if ( is_array( $wp_theme_directories ) ) {
    412412                        $protected_directories = array_merge( $protected_directories, $wp_theme_directories );
    413413                }
    414414                if ( in_array( $destination, $protected_directories ) ) {
    415415                        $remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
    416416                        $destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
    417417                }
    418418
    419419                if ( $clear_destination ) {
    420                         //We're going to clear the destination if there's something there
     420                        // We're going to clear the destination if there's something there
    421421                        $this->skin->feedback('remove_old');
     422
    422423                        $removed = true;
    423424                        if ( $wp_filesystem->exists( $remote_destination ) ) {
    424                                 $removed = $wp_filesystem->delete( $remote_destination, true );
     425                                // Check all files are writable before attempting to clear the destination
     426                                $unwritable_files = array();
     427
     428                                $_files = $wp_filesystem->dirlist( $remote_destination, true, true );
     429                                // Flatten the resulting array
     430                                while ( $f = each( $_files ) ) {
     431                                        $file = $f['value'];
     432                                        $name = $f['key'];
     433
     434                                        if ( ! isset( $file['files'] ) ) {
     435                                                continue;
     436                                        }
     437
     438                                        foreach ( $file['files'] as $filename => $details ) {
     439                                                $_files[ $name . '/' . $filename ] = $details;
     440                                        }
     441                                }
     442
     443                                // Check writability
     444                                foreach ( $_files as $filename => $file_details ) {
     445                                        if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
     446                                                $unwritable_files[] = $filename;
     447                                        }
     448                                }
     449
     450                                if ( empty( $unwritable_files ) ) {
     451                                        $removed = $wp_filesystem->delete( $remote_destination, true );
     452                                } else {
     453                                        $removed = new WP_Error( 'unwritable_files', 'Some files are unwritable, abort abort!', $unwritable_files );
     454                                }
    425455                        }
    426456
    427457                        /**
    428458                         * Filter whether the upgrader cleared the destination.
    429459                         *
    430460                         * @since 2.8.0
    431461                         *
    432462                         * @param bool   $removed            Whether the destination was cleared.
    433463                         * @param string $local_destination  The local package destination.
    434464                         * @param string $remote_destination The remote package destination.
    435465                         * @param array  $hook_extra         Extra arguments passed to hooked filters.
    436466                         */
    437467                        $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );
    438468
    439469                        if ( is_wp_error($removed) ) {