diff --git a/src/wp-admin/includes/class-wp-filesystem-direct.php b/src/wp-admin/includes/class-wp-filesystem-direct.php
index 887ad4e715..b95d04ae94 100644
a
|
b
|
class WP_Filesystem_Direct extends WP_Filesystem_Base { |
365 | 365 | |
366 | 366 | $file = str_replace( '\\', '/', $file ); // For Win32, occasional problems deleting files otherwise. |
367 | 367 | |
368 | | if ( 'f' === $type || $this->is_file( $file ) ) { |
369 | | return @unlink( $file ); |
| 368 | if ( 'f' === $type || $this->is_file( $file ) || $this->is_link( $file ) ) { |
| 369 | if ( |
| 370 | 'WIN' === strtoupper( substr( PHP_OS, 0, 3 ) ) && |
| 371 | $this->is_link( $file ) && |
| 372 | $this->is_dir( $file ) |
| 373 | ) { |
| 374 | // on windows unlink()'ing a symlink that points to a directory fails. |
| 375 | // @link https://bugs.php.net/bug.php?id=52176 |
| 376 | return @rmdir( $file ); |
| 377 | } else { |
| 378 | // untrailingslashit() needed to remove symlinks successfully. |
| 379 | return @unlink( untrailingslashit( $file ) ); |
| 380 | } |
370 | 381 | } |
371 | 382 | |
372 | 383 | if ( ! $recursive && $this->is_dir( $file ) ) { |
… |
… |
class WP_Filesystem_Direct extends WP_Filesystem_Base { |
454 | 465 | return @is_writable( $file ); |
455 | 466 | } |
456 | 467 | |
| 468 | /** |
| 469 | * Checks if a file or directory is a symbolic link. |
| 470 | * |
| 471 | * @since 5.8.0 |
| 472 | * |
| 473 | * @param string $file Path to file or directory. |
| 474 | * @return bool Whether $file is a symbolic link. |
| 475 | */ |
| 476 | public function is_link( $file ) { |
| 477 | // Strip trailing slashes, to avoid directory symlinks resolving. |
| 478 | return @is_link( untrailingslashit( $file ) ); |
| 479 | } |
| 480 | |
457 | 481 | /** |
458 | 482 | * Gets the file's last access time. |
459 | 483 | * |
… |
… |
class WP_Filesystem_Direct extends WP_Filesystem_Base { |
599 | 623 | * } |
600 | 624 | */ |
601 | 625 | public function dirlist( $path, $include_hidden = true, $recursive = false ) { |
602 | | if ( $this->is_file( $path ) ) { |
| 626 | if ( $this->is_dir( $path ) && $this->is_link( $path ) ) { |
| 627 | // Directory is symlink, therefore return no listing. |
| 628 | return array(); |
| 629 | } elseif ( $this->is_file( $path ) || $this->is_link( $path ) ) { |
603 | 630 | $limit_file = basename( $path ); |
604 | 631 | $path = dirname( $path ); |
605 | 632 | } else { |
… |
… |
class WP_Filesystem_Direct extends WP_Filesystem_Base { |
645 | 672 | $struc['time'] = gmdate( 'h:i:s', $struc['lastmodunix'] ); |
646 | 673 | $struc['type'] = $this->is_dir( $path . '/' . $entry ) ? 'd' : 'f'; |
647 | 674 | |
648 | | if ( 'd' === $struc['type'] ) { |
| 675 | if ( 'd' === $struc['type'] && ! $this->is_link( $path . '/' . $struc['name'] ) ) { |
649 | 676 | if ( $recursive ) { |
650 | 677 | $struc['files'] = $this->dirlist( $path . '/' . $struc['name'], $include_hidden, $recursive ); |
651 | 678 | } else { |
diff --git a/src/wp-admin/includes/class-wp-upgrader.php b/src/wp-admin/includes/class-wp-upgrader.php
index 9fa6c808a8..7fc26b9eca 100644
a
|
b
|
class WP_Upgrader { |
403 | 403 | if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { |
404 | 404 | // Attempt to alter permissions to allow writes and try again. |
405 | 405 | $wp_filesystem->chmod( $remote_destination . $filename, ( 'd' === $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) ); |
406 | | if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) { |
| 406 | // is_writable() returns false on symlinks for some reason. |
| 407 | if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) |
| 408 | && ! $wp_filesystem->is_link( $remote_destination . $filename ) ) { |
407 | 409 | $unwritable_files[] = $filename; |
408 | 410 | } |
409 | 411 | } |