\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_' ) . '%'
)
);
}