| @@ -150,8 +150,70 @@ | ||
| 150 | 150 | return true; |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | 153 | /** |
| 154 | + * Delete one canonical private key file with exact absence readback. | |
| 155 | + * | |
| 156 | + * @param string $file_key Name of key file. | |
| 157 | + * | |
| 158 | + * @return bool Whether exact absence was proved. | |
| 159 | + */ | |
| 160 | + public function delete_key_file_with_result( $file_key ) { | |
| 161 | + if ( ! is_string( $file_key ) || 1 !== preg_match( '/^[A-Za-z0-9][A-Za-z0-9_-]{0,254}$/D', $file_key ) ) { | |
| 162 | + return false; | |
| 163 | + } | |
| 164 | + | |
| 165 | + $key_dir = static::get_keys_dir(); | |
| 166 | + if ( ! is_string( $key_dir ) || '' === $key_dir ) { | |
| 167 | + return false; | |
| 168 | + } | |
| 169 | + | |
| 170 | + $file_path = trailingslashit( $key_dir ) . $file_key; | |
| 171 | + if ( ! $this->key_entry_present( $file_path ) ) { | |
| 172 | + return true; | |
| 173 | + } | |
| 174 | + | |
| 175 | + MainWP_Utility::delete_file( $file_path ); | |
| 176 | + clearstatcache( true, $file_path ); | |
| 177 | + | |
| 178 | + // A dangling symlink fails every exists() check, so the transport-aware helper skips it and leaves the entry behind. | |
| 179 | + if ( is_link( $file_path ) ) { | |
| 180 | + wp_delete_file( $file_path ); | |
| 181 | + clearstatcache( true, $file_path ); | |
| 182 | + } | |
| 183 | + | |
| 184 | + return ! $this->key_entry_present( $file_path ); | |
| 185 | + } | |
| 186 | + | |
| 187 | + /** | |
| 188 | + * Whether any directory entry, file or symlink, still occupies the key path. | |
| 189 | + * | |
| 190 | + * @param string $file_path Absolute key path. | |
| 191 | + * | |
| 192 | + * @return bool Whether an entry is present. | |
| 193 | + */ | |
| 194 | + private function key_entry_present( $file_path ) { | |
| 195 | + return $this->key_file_exists( $file_path ) || is_link( $file_path ); | |
| 196 | + } | |
| 197 | + | |
| 198 | + /** | |
| 199 | + * Check one exact private key path through the active filesystem boundary. | |
| 200 | + * | |
| 201 | + * @param string $file_path Absolute key path. | |
| 202 | + * | |
| 203 | + * @return bool Whether the path exists. | |
| 204 | + */ | |
| 205 | + private function key_file_exists( $file_path ) { | |
| 206 | + global $wp_filesystem; | |
| 207 | + | |
| 208 | + if ( is_object( $wp_filesystem ) && method_exists( $wp_filesystem, 'exists' ) ) { | |
| 209 | + return (bool) $wp_filesystem->exists( $file_path ); | |
| 210 | + } | |
| 211 | + | |
| 212 | + return file_exists( $file_path ); | |
| 213 | + } | |
| 214 | + | |
| 215 | + /** | |
| 154 | 216 | * Method get_decrypt_values() |
| 155 | 217 | * |
| 156 | 218 | * Get decrypt value. |
| 157 | 219 | * |
| @@ -453,8 +515,9 @@ | ||
| 453 | 515 | * |
| 454 | 516 | * @return void |
| 455 | 517 | */ |
| 456 | 518 | public static function migrate_private_filenames( $from_version, $to_version ) { |
| 519 | + unset( $to_version ); | |
| 457 | 520 | if ( ! version_compare( $from_version, '9.0.2.0', '<' ) ) { |
| 458 | 521 | return; |
| 459 | 522 | } |
| 460 | 523 | static::init_keys_dir(); |
| @@ -482,12 +545,12 @@ | ||
| 482 | 545 | $old_path = $key_dir . $entry; |
| 483 | 546 | $new_path = $key_dir . $new_name; |
| 484 | 547 | if ( file_exists( $new_path ) ) { |
| 485 | 548 | // New file already present (rare race); legacy is stale, remove it. |
| 486 | - @unlink( $old_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors -- cleanup of stale legacy. | |
| 549 | + wp_delete_file( $old_path ); | |
| 487 | 550 | continue; |
| 488 | 551 | } |
| 489 | - @rename( $old_path, $new_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors -- best-effort; lazy migration in get_key_file() handles failures. | |
| 552 | + @rename( $old_path, $new_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors, WordPress.WP.AlternativeFunctions.rename_rename -- best-effort direct rename inside the keys dir, before WP_Filesystem is initialized; lazy migration in get_key_file() handles failures. | |
| 490 | 553 | } |
| 491 | 554 | } |
| 492 | 555 | |
| 493 | 556 | /** |
| @@ -509,8 +572,9 @@ | ||
| 509 | 572 | * |
| 510 | 573 | * @return void |
| 511 | 574 | */ |
| 512 | 575 | public static function migrate_sibling_dir_perms( $from_version, $to_version ) { |
| 576 | + unset( $to_version ); | |
| 513 | 577 | if ( ! version_compare( $from_version, '9.0.2.1', '<' ) ) { |
| 514 | 578 | return; |
| 515 | 579 | } |
| 516 | 580 | $dirs = MainWP_System_Utility::get_mainwp_dir(); |
| @@ -591,8 +655,9 @@ | ||
| 591 | 655 | * |
| 592 | 656 | * @return void |
| 593 | 657 | */ |
| 594 | 658 | public static function fix_sibling_dir_perms_9023( $from_version, $to_version ) { |
| 659 | + unset( $to_version ); | |
| 595 | 660 | |
| 596 | 661 | if ( empty( $from_version ) || version_compare( $from_version, '9.0.2.1', '<' ) || version_compare( $from_version, '9.0.2.3', '>=' ) ) { |
| 597 | 662 | return; |
| 598 | 663 | } |