\n{\"beacon\":" ) ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local file. wp_delete_file( $pncp_file ); } } // The copy of the wrong-code counters next to the lock file. foreach ( (array) glob( $pncp_dir . '/fails-*.php' ) as $pncp_file ) { if ( is_string( $pncp_file ) && 0 === strpos( (string) file_get_contents( $pncp_file, false, null, 0, 64 ), "\n{\"rows\":" ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local file. wp_delete_file( $pncp_file ); } } foreach ( array( 'index.php' => " "# ScrapeLock Lockdown\n\n\tRequire all denied\n\n\n\tOrder allow,deny\n\tDeny from all\n\n", ) as $pncp_name => $pncp_content ) { if ( is_file( $pncp_dir . '/' . $pncp_name ) && file_get_contents( $pncp_dir . '/' . $pncp_name ) === $pncp_content ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local file. wp_delete_file( $pncp_dir . '/' . $pncp_name ); } } @rmdir( $pncp_dir ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- Only succeeds when empty. } unset( $pncp_dir, $pncp_file, $pncp_name, $pncp_content ); // The lock file of the code checks (in the must-use plugins folder, or in wp-content). foreach ( array( PNCP_Paths::mu_plugins(), PNCP_Paths::content() ) as $pncp_dir ) { if ( file_exists( $pncp_dir . '/scrapelock-lockdown.lock' ) ) { wp_delete_file( $pncp_dir . '/scrapelock-lockdown.lock' ); } } // The per-attachment "already watermarked" record (_pncp_wm) and pncp_backup_dir are kept on purpose: they // are the index of the clean image originals, which are intentionally not deleted (see the file header). // Without them a later reinstall could no longer tell which backup belongs to which file. // The country database folder (this site's uploads; on multisite each site has its own). Its files first, // then the now-empty folder. $pncp_geo = trailingslashit( wp_upload_dir( null, false )['basedir'] ) . 'scrapelock-geo'; foreach ( array( 'v4.bin', 'v6.bin', 'index.html', 'index.php', '.htaccess' ) as $pncp_geo_file ) { if ( file_exists( $pncp_geo . '/' . $pncp_geo_file ) ) { wp_delete_file( $pncp_geo . '/' . $pncp_geo_file ); } } if ( is_dir( $pncp_geo ) ) { @rmdir( $pncp_geo ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- Only succeeds when empty; harmless otherwise. } unset( $pncp_geo, $pncp_geo_file ); // "No PHP in the uploads folder": ScrapeLock's block in the .htaccess of the uploads folder (other content stays). $pncp_htaccess = trailingslashit( wp_upload_dir( null, false )['basedir'] ) . '.htaccess'; if ( file_exists( $pncp_htaccess ) ) { require_once __DIR__ . '/includes/class-pncp-rules.php'; PNCP_Rules::remove_marker_block( $pncp_htaccess ); // The whole block, markers included. } unset( $pncp_htaccess ); // phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Runs once, on uninstall. $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $wpdb->prefix . 'pncp_log' ) ); $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $wpdb->prefix . 'pncp_bans' ) ); $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like( '_transient_pncp_' ) . '%', $wpdb->esc_like( '_transient_timeout_pncp_' ) . '%', $wpdb->esc_like( '_site_transient_pncp_' ) . '%', $wpdb->esc_like( '_site_transient_timeout_pncp_' ) . '%', $wpdb->esc_like( 'pncp_dc_' ) . '%', $wpdb->esc_like( 'pncp_ip_lists_dc_' ) . '%' ) ); // phpcs:enable } // The pre-cache check (normally already removed on deactivation): its line in wp-config.php and its files. if ( ! is_multisite() ) { require_once __DIR__ . '/includes/class-pncp-precheck.php'; PNCP_Precheck::remove( false ); } // The early check (mu-plugin, shared by all sites of a network): removed only if ScrapeLock wrote it. $pncp_early = PNCP_Paths::mu_plugins() . '/scrapelock-early.php'; if ( is_readable( $pncp_early ) && false !== strpos( (string) file_get_contents( $pncp_early, false, null, 0, 200 ), 'Plugin Name: ScrapeLock early check' ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Local file. wp_delete_file( $pncp_early ); } unset( $pncp_early ); if ( is_multisite() ) { foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0, ) ) as $pncp_site_id ) { switch_to_blog( $pncp_site_id ); pncp_uninstall_site(); restore_current_blog(); } } else { pncp_uninstall_site(); } // Lockdown: on multisite its state is network-wide (site options); the pending app secret is user meta. delete_site_option( 'pncp_lockdown' ); delete_site_option( 'pncp_lockdown_log' ); delete_site_option( 'pncp_lockdown_mutex' ); delete_site_option( 'pncp_lockdown_mutex_pri' ); delete_site_option( 'pncp_lockdown_fails' ); delete_site_option( 'pncp_lockdown_dblock' ); delete_site_option( 'pncp_integrity' ); delete_site_option( 'pncp_integrity_report' ); delete_site_option( 'pncp_integrity_scan' ); delete_metadata( 'user', 0, 'pncp_lockdown_pending', '', true ); delete_site_option( 'pncp_lockdown_digests' ); // 3.4, multisite: the snapshot of the whole network, its fingerprints and the changes noted while unlocked for a while. delete_site_option( 'pncp_lockdown_net_snap' ); delete_site_option( 'pncp_lockdown_net_digests' ); delete_site_option( 'pncp_lockdown_net_window' ); // Network transients (Lockdown wrong-code counters, recovery codes shown once, cached checksums): on multisite // they live in the network's own table, which the per-site cleanup above does not reach. if ( is_multisite() ) { global $wpdb; // uninstall.php is included from inside a function: the global must be named. // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Runs once, on uninstall. $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->sitemeta} WHERE meta_key LIKE %s OR meta_key LIKE %s", $wpdb->esc_like( '_site_transient_pncp_' ) . '%', $wpdb->esc_like( '_site_transient_timeout_pncp_' ) . '%' ) ); }