884 lines
26 KiB
PHP
884 lines
26 KiB
PHP
<?php
|
|
defined( 'ABSPATH' ) or die();
|
|
|
|
if ( ! class_exists( "cmplz_scan" ) ) {
|
|
class cmplz_scan {
|
|
private static $_this;
|
|
|
|
function __construct() {
|
|
if ( isset( self::$_this ) ) {
|
|
wp_die( sprintf( '%s is a singleton class and you cannot create a second instance.',
|
|
get_class( $this ) ) );
|
|
}
|
|
self::$_this = $this;
|
|
if ( cmplz_scan_in_progress() ) {
|
|
add_action( 'wp_print_footer_scripts', array( $this, 'test_cookies' ), PHP_INT_MAX, 2 );
|
|
}
|
|
|
|
add_action( 'cmplz_every_day_hook', array( $this, 'track_cookie_changes' ) );
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
|
|
add_action( 'admin_footer', array( $this, 'run_cookie_scan' ) );
|
|
add_filter( 'cmplz_do_action', array( $this, 'get_scan_progress' ), 10, 3 );
|
|
add_filter( 'cmplz_do_action', array( $this, 'reset_scan' ), 11, 3 );
|
|
add_filter( 'cmplz_every_five_minutes_hook', array( $this, 'background_remote_scan' ), 11, 3 );
|
|
}
|
|
|
|
static function this() {
|
|
return self::$_this;
|
|
}
|
|
|
|
/**
|
|
* If the remote scan is active, or has started, and we're not on a complianz page, run this on cron in the background
|
|
* @return void
|
|
*/
|
|
public function background_remote_scan(){
|
|
|
|
if ( !wp_doing_cron() ) {
|
|
return;
|
|
}
|
|
|
|
if ( isset($_GET['page'] ) && $_GET['page'] === 'complianz' ) {
|
|
return;
|
|
}
|
|
|
|
$url = $this->get_next_page_url();
|
|
if ( ! $url ) {
|
|
return;
|
|
}
|
|
|
|
if ( $url === 'remote' && !COMPLIANZ::$wsc_scanner->wsc_scan_completed() ) {
|
|
//as the wsc cookie scan has a wait of 10 seconds on each request, we do this on cron
|
|
do_action('cmplz_remote_cookie_scan');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if there are any new cookies added
|
|
*/
|
|
|
|
public function track_cookie_changes() {
|
|
if ( ! cmplz_user_can_manage() ) {
|
|
return;
|
|
}
|
|
|
|
//only run if all pages are scanned.
|
|
if ( ! $this->scan_complete() ) {
|
|
return;
|
|
}
|
|
//check if anything was changed
|
|
$new_cookies = COMPLIANZ::$banner_loader->get_cookies( array( 'new' => true ) );
|
|
if ( count( $new_cookies ) > 0 ) {
|
|
$this->set_cookies_changed();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the cookies as having been changed
|
|
*/
|
|
|
|
public function set_cookies_changed() {
|
|
update_option( 'cmplz_changed_cookies', 1 , false);
|
|
|
|
}
|
|
|
|
/**
|
|
* Check if cookies have been changed
|
|
*
|
|
* @return bool
|
|
*/
|
|
|
|
public function cookies_changed() {
|
|
return ( get_option( 'cmplz_changed_cookies' ) == 1 );
|
|
}
|
|
|
|
/**
|
|
* Delete the transient that contains the pages list
|
|
*
|
|
* @param int $post_id
|
|
* @param bool $post_after
|
|
* @param bool $post_before
|
|
*/
|
|
|
|
public function clear_pages_list( int $post_id, $post_after = false, $post_before = false ) {
|
|
delete_transient( 'cmplz_pages_list' );
|
|
}
|
|
|
|
/**
|
|
* Clean up duplicate cookie names
|
|
*
|
|
* @return void
|
|
*/
|
|
public function clear_double_cookienames() {
|
|
if ( ! cmplz_user_can_manage() ) {
|
|
return;
|
|
}
|
|
global $wpdb;
|
|
|
|
$languages = COMPLIANZ::$banner_loader->get_supported_languages();
|
|
//first, delete all cookies with a language not in the $languages array
|
|
$wpdb->query( "DELETE from {$wpdb->prefix}cmplz_cookies where language NOT IN ('" . implode( "','", $languages ) . "')" );
|
|
foreach ( $languages as $language ) {
|
|
$settings = array(
|
|
'language' => $language,
|
|
'isMembersOnly' => 'all',
|
|
);
|
|
$cookies = COMPLIANZ::$banner_loader->get_cookies( $settings );
|
|
foreach ( $cookies as $cookie ) {
|
|
$same_name_cookies
|
|
= $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_cookies where name = %s and language = %s and serviceID = %s ",
|
|
$cookie->name, $language, $cookie->serviceID ) );
|
|
if ( count( $same_name_cookies ) > 1 ) {
|
|
array_shift( $same_name_cookies );
|
|
$IDS = wp_list_pluck( $same_name_cookies, 'ID' );
|
|
$sql = implode( ' OR ID =', $IDS );
|
|
$sql = "DELETE from {$wpdb->prefix}cmplz_cookies where ID=" . $sql;
|
|
$wpdb->query( $sql );
|
|
}
|
|
}
|
|
$settings = array(
|
|
'language' => $language,
|
|
);
|
|
$services = COMPLIANZ::$banner_loader->get_services( $settings );
|
|
foreach ( $services as $service ) {
|
|
$same_name_services = $wpdb->get_results( $wpdb->prepare( "select * from {$wpdb->prefix}cmplz_services where name = %s and language = %s", $service->name, $language ) );
|
|
if ( count( $same_name_services ) > 1 ) {
|
|
array_shift( $same_name_services );
|
|
$IDS = wp_list_pluck( $same_name_services, 'ID' );
|
|
$sql = implode( ' OR ID =', $IDS );
|
|
$sql = "DELETE from {$wpdb->prefix}cmplz_services where ID=" . $sql;
|
|
$wpdb->query( $sql );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Here we add scripts and styles for the wysywig editor on the backend
|
|
* @param string $hook
|
|
*
|
|
* */
|
|
|
|
public function enqueue_admin_assets( $hook ) {
|
|
if ( isset( $_GET['page'] ) && $_GET['page'] === 'complianz' ) {
|
|
//script to check for ad blockers
|
|
wp_enqueue_script( 'cmplz-ad-checker', cmplz_url . "assets/js/ads.js", array(), cmplz_version, true );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all cookies, and post back to site with ajax.
|
|
* This script is only inserted when a valid token is passed, so will never run for other visitors than the site admin
|
|
*
|
|
* */
|
|
|
|
public function test_cookies() {
|
|
if ( $this->scan_complete() ) {
|
|
return;
|
|
}
|
|
|
|
if (!isset($_GET['complianz_scan_token']) || !isset($_GET['complianz_id'])){
|
|
return;
|
|
}
|
|
|
|
$token = sanitize_title( $_GET['complianz_scan_token'] );
|
|
$id = sanitize_title( $_GET['complianz_id'] );
|
|
$admin_url = esc_url_raw( rest_url('complianz/v1/') );
|
|
$nonce = wp_create_nonce( 'wp_rest' );
|
|
$javascript = cmplz_get_template( 'test-cookies.js' );
|
|
$javascript = str_replace( array(
|
|
'{admin_url}',
|
|
'{token}',
|
|
'{id}',
|
|
'{nonce}'
|
|
), array(
|
|
esc_url_raw( $admin_url ),
|
|
esc_attr( $token ),
|
|
esc_attr( $id ),
|
|
$nonce
|
|
), $javascript );
|
|
?>
|
|
<script>
|
|
<?php echo $javascript;?>
|
|
</script>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Insert an iframe to retrieve front-end cookies
|
|
*
|
|
*
|
|
* */
|
|
|
|
public function run_cookie_scan(): void {
|
|
if ( ! cmplz_admin_logged_in() ) {
|
|
return;
|
|
}
|
|
|
|
if ( get_option('cmplz_activation_time') > strtotime('-30 minutes') ) {
|
|
return;
|
|
}
|
|
|
|
if ( defined( 'CMPLZ_DO_NOT_SCAN' ) && CMPLZ_DO_NOT_SCAN ) {
|
|
return;
|
|
}
|
|
|
|
if ( isset( $_GET['complianz_scan_token'] ) ) {
|
|
return;
|
|
}
|
|
//if the last cookie scan date is more than a month ago, we re-scan.
|
|
$last_scan_date = COMPLIANZ::$banner_loader->get_last_cookie_scan_date( true );
|
|
$scan_interval = apply_filters( 'cmplz_scan_interval', 3 );
|
|
$one_month_ago = strtotime( "-".$scan_interval." month" );
|
|
if (
|
|
( $one_month_ago > $last_scan_date )
|
|
&& $this->scan_complete()
|
|
&& !$this->automatic_cookiescan_disabled()
|
|
) {
|
|
$this->reset_pages_list();
|
|
}
|
|
|
|
if ( ! $this->scan_complete() ) {
|
|
if ( ! get_option( 'cmplz_synced_cookiedatabase_once' ) ) {
|
|
update_option( 'cmplz_sync_cookies_complete', false );
|
|
update_option( 'cmplz_sync_cookies_after_services_complete', false );
|
|
update_option( 'cmplz_sync_services_complete', false );
|
|
update_option( 'cmplz_synced_cookiedatabase_once', true );
|
|
}
|
|
|
|
//store the date
|
|
$timezone_offset = get_option( 'gmt_offset' );
|
|
$time = time() + ( 60 * 60 * $timezone_offset );
|
|
update_option( 'cmplz_last_cookie_scan', $time );
|
|
|
|
$url = $this->get_next_page_url();
|
|
if ( ! $url ) {
|
|
return;
|
|
}
|
|
|
|
if ( $url === 'remote' ) {
|
|
//as the wsc cookie scan has a wait of 10 seconds on each request, we do this on cron instead
|
|
//do_action('cmplz_remote_cookie_scan');
|
|
} else if ( strpos( $url, 'complianz_id' ) !== false ) {
|
|
//get the html of this page.
|
|
$response = wp_remote_get( $url );
|
|
if ( ! is_wp_error( $response ) ) {
|
|
$html = $response['body'];
|
|
$this->parse_html($html);
|
|
}
|
|
}
|
|
//load in iframe so the scripts run.
|
|
echo '<iframe id="cmplz_cookie_scan_frame" class="hidden" src="' . $url . '"></iframe>';
|
|
}
|
|
}
|
|
|
|
private function parse_html($html){
|
|
$stored_social_media = cmplz_scan_detected_social_media();
|
|
if ( ! $stored_social_media ) {
|
|
$stored_social_media = array();
|
|
}
|
|
$social_media = COMPLIANZ::$banner_loader->parse_for_social_media( $html );
|
|
$social_media = array_unique( array_merge( $stored_social_media, $social_media ), SORT_REGULAR );
|
|
update_option( 'cmplz_detected_social_media', $social_media );
|
|
|
|
$stored_thirdparty_services = cmplz_scan_detected_thirdparty_services();
|
|
if ( ! $stored_thirdparty_services ) {
|
|
$stored_thirdparty_services = array();
|
|
}
|
|
$thirdparty = $this->parse_for_thirdparty_services( $html );
|
|
$thirdparty = array_unique( array_merge( $stored_thirdparty_services, $thirdparty ), SORT_REGULAR );
|
|
update_option( 'cmplz_detected_thirdparty_services', $thirdparty );
|
|
|
|
//parse for google analytics and tagmanager, but only if the wizard wasn't completed before.
|
|
//with this data we prefill the settings and give warnings when tracking is doubled
|
|
if ( ! COMPLIANZ::$banner_loader->wizard_completed_once() ) {
|
|
$this->parse_for_statistics_settings( $html );
|
|
}
|
|
|
|
if ( preg_match_all( '/ga\.js/', $html ) > 1
|
|
|| preg_match_all( '/analytics\.js/', $html ) > 1
|
|
|| preg_match_all( '/googletagmanager\.com\/gtm\.js/', $html ) > 1
|
|
|| preg_match_all( '/piwik\.js/', $html ) > 1
|
|
|| preg_match_all( '/matomo\.js/', $html ) > 1
|
|
|| preg_match_all( '/getclicky\.com\/js/', $html ) > 1
|
|
|| preg_match_all( '/mc\.yandex\.ru\/metrika\/watch\.js/', $html ) > 1
|
|
) {
|
|
update_option( 'cmplz_double_stats', true );
|
|
} else {
|
|
delete_option( 'cmplz_double_stats' );
|
|
}
|
|
|
|
$stored_stats = cmplz_scan_detected_stats();
|
|
if ( ! $stored_stats ) {
|
|
$stored_stats = array();
|
|
}
|
|
$stats = $this->parse_for_stats( $html );
|
|
$stats = array_unique( array_merge( $stored_stats, $stats ), SORT_REGULAR );
|
|
update_option( 'cmplz_detected_stats', $stats );
|
|
}
|
|
|
|
/**
|
|
* Check a string for statistics
|
|
*
|
|
* @param string $html
|
|
* @param bool $single_key //return a single string instead of array
|
|
*
|
|
* @return array|string $thirdparty
|
|
*
|
|
* */
|
|
|
|
public function parse_for_stats( $html, $single_key = false ) {
|
|
$stats = array();
|
|
$stats_markers = COMPLIANZ::$config->stats_markers;
|
|
foreach ( $stats_markers as $key => $markers ) {
|
|
foreach ( $markers as $marker ) {
|
|
if ( $single_key && strpos( $html, $marker ) !== false ) {
|
|
return $key;
|
|
}
|
|
|
|
if ( strpos( $html, $marker ) !== false && ! in_array( $key, $stats ) ) {
|
|
if ( $single_key ) {
|
|
return $key;
|
|
}
|
|
$stats[] = $key;
|
|
}
|
|
}
|
|
}
|
|
if ( $single_key ) {
|
|
return false;
|
|
}
|
|
|
|
return $stats;
|
|
}
|
|
|
|
/**
|
|
* Run once to retrieve the settings for most used stats tools
|
|
*
|
|
* @param $html
|
|
*/
|
|
|
|
private function parse_for_statistics_settings( $html ) {
|
|
|
|
if ( strpos( $html, 'gtm.js' ) !== false || strpos( $html, 'gtm.start' ) !== false
|
|
) {
|
|
update_option( 'cmplz_detected_stats_type', true );
|
|
|
|
$pattern = '/(\'|")(GTM-[A-Z]{7})(\'|")/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches && isset( $matches[2] ) ) {
|
|
cmplz_update_option_no_hooks('gtm_code', sanitize_text_field( $matches[2] ) );
|
|
update_option( 'cmplz_detected_stats_data', true );
|
|
cmplz_update_option('compile_statistics', 'google-tag-manager' );
|
|
}
|
|
}
|
|
|
|
if ( strpos( $html, 'analytics.js' ) !== false || strpos( $html, 'ga.js' ) !== false || strpos( $html, '_getTracker' ) !== false ) {
|
|
update_option( 'cmplz_detected_stats_type', true );
|
|
|
|
$pattern = '/(\'|")(UA-[0-9]{8}-[0-9]{1})(\'|")/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches && isset( $matches[2] ) ) {
|
|
cmplz_update_option('ua_code', sanitize_text_field( $matches[2] ) );
|
|
cmplz_update_option('compile_statistics', 'google-analytics' );
|
|
}
|
|
|
|
//gtag
|
|
$pattern = '/(\'|")(G-[0-9a-zA-Z]{10})(\'|")/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches && isset( $matches[2] ) ) {
|
|
cmplz_update_option('ua_code', sanitize_text_field( $matches[2] ) );
|
|
cmplz_update_option('compile_statistics', 'google-analytics' );
|
|
}
|
|
$pattern = '/\'anonymizeIp|anonymize_ip\'|:[ ]{0,1}true/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches ) {
|
|
$value = cmplz_get_option( 'compile_statistics_more_info' );
|
|
if ( ! is_array( $value ) ) {
|
|
$value = array();
|
|
}
|
|
if ( !in_array( 'ip-addresses-blocked', $value, true )) {
|
|
$value[] = 'ip-addresses-blocked';
|
|
}
|
|
cmplz_update_option('compile_statistics_more_info', $value );
|
|
}
|
|
}
|
|
|
|
if ( strpos( $html, 'piwik.js' ) !== false || strpos( $html, 'matomo.js' ) !== false ) {
|
|
update_option( 'cmplz_detected_stats_type', true );
|
|
$pattern = '/(var u=")((https|http):\/\/.*?)"/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches && isset( $matches[2] ) ) {
|
|
cmplz_update_option('matomo_url', sanitize_text_field( $matches[2] ) );
|
|
update_option( 'cmplz_detected_stats_data', true );
|
|
}
|
|
|
|
$pattern = '/\[\'setSiteId\', \'([0-9]){1,3}\'\]\)/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches && isset( $matches[1] ) ) {
|
|
cmplz_update_option('matomo_site_id', intval( $matches[1] ) );
|
|
update_option( 'cmplz_detected_stats_data', true );
|
|
}
|
|
|
|
cmplz_update_option('compile_statistics', 'matomo' );
|
|
}
|
|
|
|
if ( strpos( $html, 'static.getclicky.com/js' ) !== false ) {
|
|
update_option( 'cmplz_detected_stats_type', true );
|
|
|
|
$pattern = '/clicky_site_ids\.push\(([0-9]{1,3})\)/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches && isset( $matches[1] ) ) {
|
|
cmplz_update_option('clicky_site_id', intval( $matches[1] ) );
|
|
update_option( 'cmplz_detected_stats_data', true );
|
|
cmplz_update_option('compile_statistics', 'clicky' );
|
|
}
|
|
}
|
|
|
|
if ( strpos( $html, 'mc.yandex.ru/metrika/watch.js' ) !== false ) {
|
|
update_option( 'cmplz_detected_stats_type', true );
|
|
|
|
$pattern = '/w.yaCounter([0-9]{1,10}) = new/i';
|
|
preg_match( $pattern, $html, $matches );
|
|
if ( $matches && isset( $matches[1] ) ) {
|
|
cmplz_update_option('yandex_id', intval( $matches[1] ) );
|
|
update_option( 'cmplz_detected_stats_data', true );
|
|
cmplz_update_option('compile_statistics', 'yandex' );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Check a string for third party services
|
|
*
|
|
* @param string $html
|
|
* @param bool $single_key //return a single string instead of array
|
|
*
|
|
* @return array|string $thirdparty
|
|
*
|
|
* */
|
|
|
|
public function parse_for_thirdparty_services( $html, $single_key = false ) {
|
|
$thirdparty = array();
|
|
$thirdparty_markers = COMPLIANZ::$config->thirdparty_service_markers;
|
|
foreach ( $thirdparty_markers as $key => $markers ) {
|
|
foreach ( $markers as $marker ) {
|
|
if ( $single_key && strpos( $html, $marker ) !== false ) {
|
|
return $key;
|
|
}
|
|
|
|
if ( strpos( $html, $marker ) !== false && ! in_array( $key, $thirdparty ) ) {
|
|
$thirdparty[] = $key;
|
|
}
|
|
}
|
|
}
|
|
if ( $single_key ) {
|
|
return false;
|
|
}
|
|
|
|
return $thirdparty;
|
|
}
|
|
|
|
private function get_next_page_url() {
|
|
if ( ! cmplz_user_can_manage() ) {
|
|
return '';
|
|
}
|
|
$token = wp_create_nonce( 'complianz_scan_token' );
|
|
$pages = array_filter($this->pages_to_process());
|
|
if ( count( $pages ) === 0 ) {
|
|
return false;
|
|
}
|
|
$id_to_process = reset( $pages );
|
|
|
|
//in case of remote, we want to wait until the process has completed before moving on to the next.
|
|
if ( $id_to_process !== 'remote' ) {
|
|
$this->set_page_as_processed( $id_to_process );
|
|
} else if ( COMPLIANZ::$wsc_scanner->wsc_scan_completed() ) {
|
|
$this->set_page_as_processed( $id_to_process );
|
|
}
|
|
|
|
switch ( $id_to_process ) {
|
|
case 'remote':
|
|
return 'remote';
|
|
case 'home':
|
|
$url = site_url();
|
|
break;
|
|
case 'loginpage':
|
|
$url = wp_login_url();
|
|
break;
|
|
default:
|
|
$url = get_permalink( $id_to_process );
|
|
}
|
|
$url = add_query_arg( array(
|
|
"complianz_scan_token" => $token,
|
|
'complianz_id' => $id_to_process
|
|
), $url );
|
|
if ( is_ssl() ) {
|
|
$url = str_replace( "http://", "https://", $url );
|
|
}
|
|
|
|
return apply_filters("cmplz_next_page_url", $url);
|
|
}
|
|
|
|
/**
|
|
* Get the list of posttypes to process
|
|
* @return array
|
|
*/
|
|
|
|
public function get_scannable_post_types(){
|
|
$args = array(
|
|
'public' => true,
|
|
);
|
|
$post_types = get_post_types( $args );
|
|
unset(
|
|
$post_types['elementor_font'],
|
|
$post_types['attachment'],
|
|
$post_types['revision'],
|
|
$post_types['nav_menu_item'],
|
|
$post_types['custom_css'],
|
|
$post_types['customize_changeset'],
|
|
$post_types['cmplz-dataleak'],
|
|
$post_types['cmplz-processing'],
|
|
$post_types['user_request'],
|
|
$post_types['cookie'],
|
|
$post_types['product']
|
|
);
|
|
return apply_filters('cmplz_cookiescan_post_types',$post_types );
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Get list of page id's that we want to process this set of scan requests, which weren't included in the scan before
|
|
*
|
|
* @return array $pages
|
|
* *@since 1.0
|
|
*/
|
|
|
|
public function get_pages_list_single_run() {
|
|
if ( !cmplz_user_can_manage() ) {
|
|
return [];
|
|
}
|
|
$posts = get_transient( 'cmplz_pages_list' );
|
|
if ( ! $posts ) {
|
|
$posts = ['home', 'remote'];
|
|
$all_types_posts = [];
|
|
$post_types = $this->get_scannable_post_types();
|
|
//from each post type, get one, for faster results.
|
|
foreach ( $post_types as $post_type ) {
|
|
$args = array(
|
|
'post_type' => $post_type,
|
|
'posts_per_page' => 1,
|
|
'meta_query' => array(
|
|
array(
|
|
'key' => '_cmplz_scanned_post',
|
|
'compare' => 'NOT EXISTS'
|
|
),
|
|
)
|
|
);
|
|
$new_posts = get_posts( $args );
|
|
$all_types_posts = $all_types_posts + $new_posts;
|
|
}
|
|
|
|
$all_types_array = count($all_types_posts)>0 ? wp_list_pluck($all_types_posts, 'ID') : [];
|
|
$posts = array_merge( $posts, $all_types_array );
|
|
foreach ( $post_types as $post_type ) {
|
|
$args = array(
|
|
'post__not_in' => $all_types_array,
|
|
'post_type' => $post_type,
|
|
'posts_per_page' => 5,
|
|
'meta_query' => array(
|
|
array(
|
|
'key' => '_cmplz_scanned_post',
|
|
'compare' => 'NOT EXISTS'
|
|
),
|
|
)
|
|
);
|
|
$new_posts = get_posts( $args );
|
|
$new_posts_array = count($new_posts)>0 ? wp_list_pluck($new_posts, 'ID') : [];
|
|
$posts = $posts + $new_posts_array;
|
|
}
|
|
if ( count( $posts ) === 0 && ! $this->automatic_cookiescan_disabled() ) {
|
|
/*
|
|
* If we didn't find any posts, we reset the post meta that tracks if all posts have been scanned.
|
|
* This way we will find some posts on the next scan attempt
|
|
* */
|
|
$this->reset_scanned_post_batches();
|
|
|
|
//now we need to reset the scanned pages list too
|
|
$this->reset_pages_list();
|
|
} else {
|
|
foreach ( $posts as $post_id ) {
|
|
update_post_meta( $post_id, '_cmplz_scanned_post', true );
|
|
}
|
|
}
|
|
|
|
if ( cmplz_get_option( 'wp_admin_access_users' ) === 'yes' ) {
|
|
$posts[] = 'loginpage';
|
|
}
|
|
set_transient( 'cmplz_pages_list', $posts, MONTH_IN_SECONDS );
|
|
}
|
|
|
|
return array_filter($posts);
|
|
}
|
|
|
|
/**
|
|
* Reset the list of pages
|
|
*
|
|
* @param bool $delay
|
|
* @param bool $manual //if it's manual, we always reset. If automatic scan is disabled, we do not reset.
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 2.1.5
|
|
*/
|
|
|
|
public function reset_pages_list( $delay = false, $manual = false ) {
|
|
|
|
if ( ! $manual && $this->automatic_cookiescan_disabled() ) {
|
|
return;
|
|
}
|
|
|
|
if ( $manual ) {
|
|
$this->reset_scanned_post_batches();
|
|
}
|
|
|
|
if ( $delay ) {
|
|
$current_list = get_transient( 'cmplz_pages_list' );
|
|
$processed_pages = get_transient( 'cmplz_processed_pages_list' );
|
|
set_transient( 'cmplz_pages_list', $current_list, HOUR_IN_SECONDS );
|
|
set_transient( 'cmplz_processed_pages_list', $processed_pages, HOUR_IN_SECONDS );
|
|
|
|
} else {
|
|
delete_transient( 'cmplz_pages_list' );
|
|
delete_transient( 'cmplz_processed_pages_list' );
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* The scanned post meta is used to create batches of posts. A batch that is being processed is set to scanned.
|
|
* This is only reset when all posts have been processed, or if user has disabled automatic scanning, and the manual scan is fired.
|
|
* */
|
|
|
|
public function reset_scanned_post_batches() {
|
|
if ( ! function_exists( 'delete_post_meta_by_key' ) ) {
|
|
require_once ABSPATH . WPINC . '/post.php';
|
|
}
|
|
delete_post_meta_by_key( '_cmplz_scanned_post' );
|
|
}
|
|
|
|
/**
|
|
* Check if the automatic scan is disabled
|
|
*
|
|
* @return bool
|
|
*/
|
|
|
|
public function automatic_cookiescan_disabled() {
|
|
return cmplz_get_option( 'disable_automatic_cookiescan' ) == 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* Get list of pages that were processed before
|
|
*
|
|
* @return array $pages
|
|
*/
|
|
|
|
public function get_processed_pages_list() {
|
|
|
|
$pages = get_transient( 'cmplz_processed_pages_list' );
|
|
if ( ! is_array( $pages ) ) {
|
|
$pages = array();
|
|
}
|
|
|
|
return array_filter($pages);
|
|
}
|
|
|
|
/**
|
|
* Check if the scan is complete
|
|
*
|
|
* @param void
|
|
*
|
|
* @return bool
|
|
* @since 1.0
|
|
*
|
|
* */
|
|
|
|
public function scan_complete() {
|
|
$pages = array_filter($this->pages_to_process());
|
|
return count( $pages ) === 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Get list of pages that still have to be processed
|
|
*
|
|
* @param void
|
|
*
|
|
* @return array $pagåes
|
|
* @since 1.0
|
|
*/
|
|
|
|
private function pages_to_process(): array {
|
|
|
|
$pages_list = $this->get_pages_list_single_run();
|
|
$processed_pages_list = $this->get_processed_pages_list();
|
|
return array_diff( $pages_list, $processed_pages_list );
|
|
}
|
|
|
|
/**
|
|
* Set a page as being processed
|
|
*
|
|
* @param $id
|
|
*
|
|
* @return void
|
|
* @since 1.0
|
|
*/
|
|
|
|
public function set_page_as_processed( $id ): void {
|
|
if ( ! cmplz_user_can_manage() ) {
|
|
return;
|
|
}
|
|
|
|
if ( $id !== 'home' && $id !== 'loginpage' && $id !== 'remote' && ! is_numeric( $id ) ) {
|
|
return;
|
|
}
|
|
|
|
$pages = $this->get_processed_pages_list();
|
|
if ( ! in_array( $id, $pages, true ) ) {
|
|
$pages[] = $id;
|
|
$expiration = $this->automatic_cookiescan_disabled() ? 10 * YEAR_IN_SECONDS : MONTH_IN_SECONDS;
|
|
set_transient( 'cmplz_processed_pages_list', $pages, $expiration );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the cookie policy date
|
|
*/
|
|
|
|
public function update_cookie_policy_date() {
|
|
update_option( 'cmplz_publish_date', time() );
|
|
|
|
//also reset the email notification, so it will get sent next year.
|
|
update_option( 'cmplz_update_legal_documents_mail_sent', false );
|
|
}
|
|
|
|
/**
|
|
* Get progress of the current scan to output with ajax
|
|
*
|
|
* @param array $data
|
|
* @param string $action
|
|
* @param WP_REST_Request $request
|
|
*
|
|
* @return array
|
|
*/
|
|
|
|
public function get_scan_progress( array $data, string $action, WP_REST_Request $request): array {
|
|
if (!cmplz_user_can_manage()) {
|
|
return [];
|
|
}
|
|
|
|
if ( $action === 'get_scan_progress' ) {
|
|
$timezone_offset = get_option( 'gmt_offset' );
|
|
$time = time() + ( 60 * 60 * $timezone_offset );
|
|
update_option( 'cmplz_last_cookie_scan', $time );
|
|
|
|
$next_url = $this->get_next_page_url();
|
|
if ($next_url==='remote') {
|
|
do_action('cmplz_remote_cookie_scan');
|
|
//only proceed to next page if remote scan is complete
|
|
if ( COMPLIANZ::$wsc_scanner->wsc_scan_completed() ) {
|
|
$next_url = $this->get_next_page_url();
|
|
}
|
|
} else if ( strpos( $next_url, 'complianz_id' ) !== false ) {
|
|
$response = wp_remote_get( $next_url );
|
|
if ( ! is_wp_error( $response ) ) {
|
|
$html = $response['body'];
|
|
$this->parse_html($html);
|
|
}
|
|
}
|
|
$this->clear_double_cookienames();
|
|
$cookies = COMPLIANZ::$banner_loader->get_cookies();
|
|
$progress = $this->get_progress_count();
|
|
$total = count($cookies);
|
|
$current = (int) ( $progress / 100 * $total );
|
|
$cookies = array_slice( $cookies, 0, $current);
|
|
$cookies = count($cookies) > 0 ? wp_list_pluck( $cookies, 'name' ) : [];
|
|
$data = [
|
|
"progress" => $progress,
|
|
"next_page" => $next_url,
|
|
'cookies' => $cookies,
|
|
'token' => wp_create_nonce( 'complianz_scan_token' ),
|
|
];
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Rescan after a manual "rescan" command from the user
|
|
*/
|
|
|
|
public function reset_scan($data, $action, $request) {
|
|
if ( !cmplz_user_can_manage() ) {
|
|
return [];
|
|
}
|
|
|
|
if ( $action === 'scan' ) {
|
|
$scan_type = sanitize_title($request->get_param('scan_action'));
|
|
if ( $scan_type==='reset' ) {
|
|
global $wpdb;
|
|
$table_names = array( $wpdb->prefix . 'cmplz_cookies');
|
|
foreach ( $table_names as $table_name ) {
|
|
if ( $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) === $table_name ) {
|
|
$wpdb->query( "TRUNCATE TABLE $table_name" );
|
|
}
|
|
}
|
|
update_option( 'cmplz_detected_social_media', false );
|
|
update_option( 'cmplz_detected_thirdparty_services', false );
|
|
update_option( 'cmplz_detected_stats', false );
|
|
}
|
|
|
|
if ( $scan_type==='reset' || $scan_type==='restart' ) {
|
|
COMPLIANZ::$wsc_scanner->wsc_scan_reset();
|
|
$this->reset_pages_list( false, true );
|
|
COMPLIANZ::$sync->resync();
|
|
}
|
|
|
|
$data = [];
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Get progress of the scan in percentage
|
|
*
|
|
* @return float
|
|
*/
|
|
|
|
public function get_progress_count() {
|
|
|
|
$remote_scan_total = 100;
|
|
$remote_scan_progress = COMPLIANZ::$wsc_scanner->wsc_scan_progress();
|
|
|
|
$local_done = count($this->get_processed_pages_list());
|
|
$local_total = count($this->get_pages_list_single_run());
|
|
|
|
//convert local to a 100 scale
|
|
//prevent division by zero
|
|
$local_total = $local_total === 0 ? $local_done : $local_total;
|
|
$local_done = 100 * ( $local_done / $local_total);
|
|
|
|
$total = 200;
|
|
$done = $remote_scan_progress + $local_done;
|
|
|
|
$progress = 100 * ( $done / $total);
|
|
if ( $progress > 100 ) {
|
|
$progress = 100;
|
|
}
|
|
|
|
return $progress;
|
|
}
|
|
|
|
}
|
|
|
|
} //class closure
|