inspect( $target ); if ( 'foreign' === $status || 'unreadable' === $status ) { update_option( 'nbh_performance_dropin_conflict', 1, false ); return false; } // A previously reported conflict may have been removed manually. delete_option( 'nbh_performance_dropin_conflict' ); if ( 'owned' === $status ) { $source_hash = hash_file( 'sha256', $source ); $target_hash = hash_file( 'sha256', $target ); if ( is_string( $source_hash ) && is_string( $target_hash ) && hash_equals( $source_hash, $target_hash ) ) { delete_option( 'nbh_performance_dropin_error' ); update_option( 'nbh_performance_dropin_installed', 1, false ); return true; } } $temp = tempnam( WP_CONTENT_DIR, '.nbh-performance-dropin-' ); if ( false === $temp ) { update_option( 'nbh_performance_dropin_error', 'temp_unavailable', false ); return false; } // The temporary file must be removed after every unsuccessful install. if ( ! \NBH\Performance\Modules\Core\Filesystem::copy( $source, $temp ) ) { \NBH\Performance\Modules\Core\Filesystem::unlink( $temp ); update_option( 'nbh_performance_dropin_error', 'copy_failed', false ); return false; } $source_hash = hash_file( 'sha256', $source ); $temp_hash = hash_file( 'sha256', $temp ); if ( ! is_string( $source_hash ) || ! is_string( $temp_hash ) || ! hash_equals( $source_hash, $temp_hash ) ) { \NBH\Performance\Modules\Core\Filesystem::unlink( $temp ); update_option( 'nbh_performance_dropin_error', 'integrity_failed', false ); return false; } // Reject a newly created foreign drop-in before the final move. if ( $status !== $this->inspect( $target ) ) { \NBH\Performance\Modules\Core\Filesystem::unlink( $temp ); update_option( 'nbh_performance_dropin_conflict', 1, false ); update_option( 'nbh_performance_dropin_error', 'target_changed', false ); return false; } \NBH\Performance\Modules\Core\Filesystem::chmod( $temp, 0644 ); // Use an atomic same-directory replacement for the verified wp-content // drop-in; WP_Filesystem_Direct::move() deletes before renaming. $installed = \NBH\Performance\Modules\Core\Filesystem::atomic_replace( $temp, $target ); if ( ! $installed ) { \NBH\Performance\Modules\Core\Filesystem::unlink( $temp ); update_option( 'nbh_performance_dropin_error', 'rename_failed', false ); } else { delete_option( 'nbh_performance_dropin_error' ); delete_option( 'nbh_performance_dropin_conflict' ); } update_option( 'nbh_performance_dropin_installed', (int) $installed, false ); return $installed; } /** * Reconcile the stored conflict flag with the actual filesystem state. * * @return string missing|owned|foreign|unreadable */ public function reconcile() { $target = WP_CONTENT_DIR . '/advanced-cache.php'; $status = $this->inspect( $target ); if ( 'foreign' === $status || 'unreadable' === $status ) { update_option( 'nbh_performance_dropin_conflict', 1, false ); } else { delete_option( 'nbh_performance_dropin_conflict' ); } return $status; } /** * Inspect a drop-in without generating filesystem warnings. * * @param string $file Drop-in path. * @return string */ public function inspect( $file ) { // A dangling symlink does not satisfy file_exists(), but is not a safe target. if ( is_link( $file ) ) { return 'unreadable'; } if ( ! file_exists( $file ) ) { return 'missing'; } if ( ! is_readable( $file ) || ! is_file( $file ) ) { return 'unreadable'; } return $this->is_ours( $file ) ? 'owned' : 'foreign'; } /** * Determine whether a readable drop-in belongs to NBH Performance. * * @param string $file Drop-in path. * @return bool */ public function is_ours( $file ) { if ( is_link( $file ) || ! is_readable( $file ) || ! is_file( $file ) ) { return false; } $header = \NBH\Performance\Modules\Core\Filesystem::get_contents( $file ); if ( ! is_string( $header ) ) { return false; } return false !== strpos( substr( $header, 0, 1024 ), self::MARKER ); } }