PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /home/trave494/rfstoolsupply.com/wp-content/plugins/complianz-gdpr/cookie/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //home/trave494/rfstoolsupply.com/wp-content/plugins/complianz-gdpr/cookie/class-cookie-admin.php |
<?php defined( 'ABSPATH' ) or die( "you do not have access to this page!" ); if ( ! class_exists( "cmplz_cookie_admin" ) ) { class cmplz_cookie_admin { private static $_this; public $position; public $cookies = array(); public $cookie_settings = array(); 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; $scan_in_progress = isset( $_GET['complianz_scan_token'] ) && ( sanitize_title( $_GET['complianz_scan_token'] ) == get_option( 'complianz_scan_token' ) ); if ( $scan_in_progress ) { add_action( 'wp_print_footer_scripts', array( $this, 'test_cookies' ), PHP_INT_MAX, 2 ); } else { add_action( 'admin_init', array( $this, 'track_cookie_changes' ) ); } if ( ! is_admin() ) { if ( $this->site_needs_cookie_warning() ) { add_action( 'wp_print_footer_scripts', array( $this, 'inline_cookie_script' ), PHP_INT_MAX - 50 ); add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ), PHP_INT_MAX - 50 ); add_filter( 'script_loader_tag', array( $this, 'add_asyncdefer_attribute' ), 10, 2 ); add_action( 'wp_head', array( $this, 'cookiebanner_css') ); add_action( 'wp_footer', array( $this, 'cookiebanner_html') ); } else { add_action( 'wp_print_footer_scripts', array( $this, 'inline_cookie_script_no_warning' ), 10, 2 ); } } else if (isset( $_GET['page'] ) && $_GET['page'] === 'cmplz-cookiebanner' ) { if ( isset( $_GET['id'] ) || ( isset( $_GET['action'] ) && $_GET['action'] == 'new' ) ) { add_action( 'admin_footer', array( $this, 'cookiebanner_css' ) ); add_action( 'admin_footer', array( $this, 'cookiebanner_html' ) ); } } add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) ); add_action( 'admin_footer', array( $this, 'run_cookie_scan' ) ); if ( defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ) { add_action( 'wp_footer', array( $this, 'detect_conflicts' ), PHP_INT_MAX ); add_action( 'wp_ajax_cmplz_store_console_errors', array( $this, 'store_console_errors' ) ); } add_action( 'wp_ajax_load_detected_cookies', array( $this, 'load_detected_cookies' ) ); add_action( 'wp_ajax_cmplz_get_scan_progress', array( $this, 'get_scan_progress' ) ); add_action( 'wp_ajax_cmplz_run_sync', array( $this, 'run_sync' ) ); add_action( 'admin_init', array( $this, 'run_sync_on_update' ) ); add_action( 'admin_init', array( $this, 'ensure_cookies_in_all_languages' ) ); add_action( 'plugins_loaded', array( $this, 'rescan' ), 20, 2 ); add_action( 'plugins_loaded', array( $this, 'clear_cookies' ), 20, 2 ); //callback from settings add_action( 'cmplz_cookie_scan', array( $this, 'scan_progress' ), 10, 1 ); add_action( 'cmplz_cookiedatabase_sync', array( $this, 'sync_progress' ), 10, 1 ); add_action( 'cmplz_statistics_script', array( $this, 'get_statistics_script' ), 10 ); add_action( 'cmplz_tagmanager_script', array( $this, 'get_tagmanager_script' ), 10 ); add_action( 'cmplz_before_statistics_script', array( $this, 'add_gtag_js' ), 10 ); add_action( 'cmplz_before_statistics_script', array( $this, 'add_clicky_js' ), 10 ); add_action( 'wp_ajax_cmplz_edit_item', array( $this, 'ajax_edit_item' ) ); add_action( 'wp_ajax_cmplz_get_list', array( $this, 'ajax_get_list' ) ); add_filter( 'cmplz_consenttype', array( $this, 'maybe_filter_consenttype' ), 10, 2 ); // add_filter( 'admin_init', array( $this, 'scan_cookies' ), 10, 1 ); } static function this() { return self::$_this; } /** * Run our remote cookie scan for third party cookies * * @return void */ /** * Front end javascript error detection. * Only for site admins */ public function detect_conflicts() { if ( ! cmplz_user_can_manage() ) { return; } if ( !cmplz_can_run_cookie_blocker() ) { return; } $checked_count = intval( get_transient( 'cmplz_checked_for_js_count' ) ); if ( $checked_count > 5 ) { return; } $nonce = wp_create_nonce( 'cmplz-detect-errors' ); ?> <script> var request = new XMLHttpRequest(); var error_ocurred = false; window.onerror = function (msg, url, lineNo, columnNo, error) { error_ocurred = true; var request = new XMLHttpRequest(); request.open('POST', '<?php echo add_query_arg( array( 'type' => 'errors', 'nonce' => $nonce, 'action' => 'cmplz_store_console_errors' ), admin_url( 'admin-ajax.php' ) ) ?>', true); var data = []; data.push(msg); data.push(lineNo); data.push(url.substring(0, url.indexOf('?'))); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); request.send(data); }; //if no error occurred after 3 seconds, send a reset signal setTimeout(function () { if (!error_ocurred) { var request = new XMLHttpRequest(); request.open('POST', '<?php echo add_query_arg( array( 'type' => 'errors', 'nonce' => $nonce, 'action' => 'cmplz_store_console_errors' ), admin_url( 'admin-ajax.php' ) ) ?>', true); var data = []; data.push('no-errors'); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); request.send(data); } }, 3000); </script> <?php } /** * Store detected errors * Only for site admins */ public function store_console_errors() { if ( ! cmplz_user_can_manage() ) { return; } if ( ! $this->site_needs_cookie_warning() ) { return; } /** * limit to one request each two minutes. */ $checked_count = intval( get_transient( 'cmplz_checked_for_js_count' ) ); if ( $checked_count > 5 ) { return; } set_transient( 'cmplz_checked_for_js_count' , $checked_count + 1, 5 * MINUTE_IN_SECONDS ); $success = false; if ( isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'], 'cmplz-detect-errors' ) ) { if ( isset( $_POST['no-errors'] ) ) { update_option( 'cmplz_detected_console_errors', false ); $success = true; } else { $errors = array_keys( array_map( 'sanitize_text_field', $_POST ) ); if ( count( $errors ) > 0 && strpos($errors[0], 'runReadyTrigger') === false) { $errors = explode( ',', str_replace( site_url(), '', $errors[0] ) ); if ( isset( $errors[1] ) && $errors[1] > 1 ) { update_option( 'cmplz_detected_console_errors', $errors ); } $success = true; } } } $response = json_encode( array( 'success' => $success, ) ); header( "Content-Type: application/json" ); echo $response; exit; } /** * When special data is processed, Canada requires optin consenttype * * @param string $consenttype * @param string $region * * @return string $consenttype */ public function maybe_filter_consenttype( $consenttype, $region ) { if ( $region === 'ca' && cmplz_site_shares_data() && cmplz_get_value( 'sensitive_information_processed' ) === 'yes' ) { $consenttype = 'optin'; } elseif ( $region === 'ca' && cmplz_get_value('ca_targets_quebec') === 'yes' ) { $consenttype = 'optin'; } if ( $region === 'au' && cmplz_site_shares_data() && cmplz_get_value( 'sensitive_information_processed' ) === 'yes' && cmplz_uses_marketing_cookies() ) { $consenttype = 'optin'; } return $consenttype; } /** * create select html for services * * @param string $selected_value * @param string $language * * @return string */ public function get_services_options( $selected_value, $language ) { if ( ! cmplz_user_can_manage() ) { return ''; } $services = $this->get_services( array( 'language' => $language ) ); $html = '<option value="" >' . esc_html( __( 'Select or add a service', 'complianz-gdpr' ) ) . '</option>'; foreach ( $services as $service ) { if ( empty( $service->name ) ) { continue; } $sel = ( $selected_value == $service->name ) ? 'selected="selected"' : ''; $html .= '<option value="' . esc_html( $service->name ) . '" ' . $sel . '>' . esc_html( $service->name ) . '</option>'; } if ( empty( $html ) ) { $html = '<option value="">' . esc_html( __( 'No services listed', 'complianz-gdpr' ) ) . '</option>'; } return $html; } /** * create select html for service types * * @param string $selected_value * @param string $language * * @return string */ public function get_serviceTypes_options( $selected_value, $language ) { if ( ! cmplz_user_can_manage() ) { return ''; } $html = '<option value="0" >' . esc_html( __( 'Select a service type', 'complianz-gdpr' ) ) . '</option>'; $serviceTypes = get_transient( 'cmplz_serviceTypes_' . $language ); if ( ! $serviceTypes ) { $endpoint = trailingslashit( CMPLZ_COOKIEDATABASE_URL ) . 'v1/servicetypes/' . $language; $response = wp_remote_get( $endpoint ); $status = wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); if ( $status == 200 ) { $body = json_decode( $body ); $serviceTypes = $body->data; if ( $language === 'en' ) { foreach ( $serviceTypes as $serviceType ) { if ( empty( $serviceType ) ) { continue; } cmplz_register_translation( $serviceType, $serviceType ); } } set_transient( 'cmplz_serviceTypes_' . $language, $serviceTypes, MONTH_IN_SECONDS ); } } if ( $serviceTypes ) { foreach ( $serviceTypes as $serviceType ) { if ( empty( $serviceType ) ) { continue; } $sel = ( $selected_value == $serviceType ) ? 'selected="selected"' : ''; $html .= '<option value="' . esc_html( $serviceType ) . '" ' . $sel . '>' . esc_html( $serviceType ) . '</option>'; } } if ( empty( $html ) ) { $html = '<option value="">' . esc_html( __( 'No service types listed', 'complianz-gdpr' ) ) . '</option>'; } return $html; } /** * create select html for purposes * * @param string $selected_value * @param string $language * * @return string */ public function get_cookiePurpose_options( $selected_value, $language ) { if ( ! cmplz_user_can_manage() ) { return ''; } $html = '<option value="" >' . esc_html( __( 'Select a purpose', 'complianz-gdpr' ) ) . '</option>'; $cookiePurposes = get_transient( 'cmplz_purposes_' . $language ); if ( ! $cookiePurposes ) { $endpoint = trailingslashit( CMPLZ_COOKIEDATABASE_URL ) . 'v1/cookiepurposes/' . $language; $response = wp_remote_get( $endpoint ); $status = wp_remote_retrieve_response_code( $response ); $body = wp_remote_retrieve_body( $response ); if ( $status == 200 ) { $body = json_decode( $body ); $cookiePurposes = $body->data; if ( $language === 'en' ) { foreach ( $cookiePurposes as $cookiePurpose ) { if ( empty( $cookiePurpose ) ) { continue; } cmplz_register_translation( $cookiePurpose, $cookiePurpose ); } } set_transient( 'cmplz_purposes_' . $language, $cookiePurposes, MONTH_IN_SECONDS ); } } if ( $cookiePurposes ) { foreach ( $cookiePurposes as $cookiePurpose ) { if ( empty( $cookiePurpose ) ) { continue; } $sel = ( $selected_value == $cookiePurpose ) ? 'selected="selected"' : ''; $html .= '<option value="' . esc_html( $cookiePurpose ) . '" ' . $sel . '>' . esc_html( $cookiePurpose ) . '</option>'; } } if ( empty( $html ) ) { $html = '<option value="">' . esc_html( __( 'No purposes listed', 'complianz-gdpr' ) ) . '</option>'; } return $html; } /** * get list item html for one cookie setting form * * @param $tmpl * @param CMPLZ_COOKIE * * @return string */ public function get_cookie_list_item_html( $tmpl, $cookie ) { if ( ! cmplz_user_can_manage() ) { return ''; } $sync = COMPLIANZ::$cookie_admin->use_cdb_api() ? $cookie->sync : false; $syncDisabled = ''; if ( ! COMPLIANZ::$cookie_admin->use_cdb_api() ) { $syncDisabled = 'cmplz-disabled'; } $disabled = $sync ? 'disabled="disabled"' : false; $disabledClass = $sync ? 'cmplz-disabled' : false; $sync = $sync ? 'checked="checked"' : ''; $isPersonalData = $cookie->isPersonalData == 1 ? 'checked="checked"' : ''; $showOnPolicy = $cookie->showOnPolicy == 1 ? 'checked="checked"' : ''; $services = $this->get_services_options( $cookie->service, $cookie->language ); $cookiePurposes = $this->get_cookiePurpose_options( $cookie->purpose, $cookie->language ); $link = ''; if ( cmplz_get_value( 'use_cdb_links' ) === 'yes' && !empty( $cookie->slug ) ) { $service_slug = ( empty( $cookie->service ) ) ? 'unknown-service' : $cookie->service; $link = '<a target="_blank" href="https://cookiedatabase.org/cookie/' . $service_slug . '/' . $cookie->slug . '/">' . __( "View cookie on cookiedatabase.org", "complianz-gdpr" ) . '</a>'; } $cookie_html = str_replace( array( '{cookie_id}', '{name}', '{disabled}', '{disabledClass}', '{services}', '{retention}', '{sync}', '{cookieFunction}', '{purposes}', '{isPersonalData}', '{collectedPersonalData}', '{showOnPolicy}', '{syncDisabled}', "{link}", ), array( $cookie->ID, $cookie->name, $disabled, $disabledClass, $services, esc_html( $cookie->retention ), $sync, $cookie->cookieFunction, $cookiePurposes, $isPersonalData, $cookie->collectedPersonalData, $showOnPolicy, $syncDisabled, $link, ), $tmpl ); $icons = ''; $membersOnly = ( !$cookie->ignored && cmplz_get_value( 'wp_admin_access_users' ) === 'no' && $cookie->isMembersOnly ); if ( $cookie->complete || $cookie->ignored || $membersOnly) { $icons .= cmplz_icon( 'check', 'success', __( "The data for this cookie is complete", "complianz-gdpr" )); } else { $icons .= cmplz_icon( 'times', 'error', __( "This cookie has missing fields", "complianz-gdpr" )); } if ( ! $cookie->sync ) { $icons .= cmplz_icon( 'sync', 'disabled', __( "Synchronization with cookiedatabase.org is not enabled for this cookie", "complianz-gdpr" ) ); } elseif ( $cookie->synced ) { $icons .= cmplz_icon( 'sync', 'success', __( "This cookie has been synchronized with cookiedatabase.org.",'complianz-gdpr').' '.__( "Our moderators will keep the cookies up-to-date.", "complianz-gdpr" ) ); } else { $icons .= cmplz_icon( 'sync-error', 'error', __( "This cookie is not yet synchronized with cookiedatabase.org.",'complianz-gdpr').' '.__( "Either try again, or if this fails; our moderators will investigate further and automatically update the descriptions.", "complianz-gdpr" ) ); } if ( $cookie->showOnPolicy && ! $cookie->ignored ) { $icons .= cmplz_icon( 'file', 'success', __( "This cookie will be on your Cookie Policy", "complianz-gdpr" ) ); } else { $icons .= cmplz_icon( 'file-disabled', 'disabled', __( "This cookie is not shown on the Cookie Policy", "complianz-gdpr" ) ); } if ( ! $cookie->old ) { $icons .= cmplz_icon( 'calendar', 'success', __( "This cookie has recently been detected", "complianz-gdpr" ) ); } else { $icons .= cmplz_icon( 'calendar-error', 'error', __( "This cookie has not been detected on your site in the last three months", "complianz-gdpr" ) ); } $notice = ( $cookie->old ) ? cmplz_notice( __( 'This cookie has not been found in the scan for three months. Please check if you are still using this cookie', 'complianz-gdpr' ), 'warning', false ) : ''; $cookie_html = $notice . $cookie_html; $ignored = ( $cookie->ignored ) ? ' <i>' . __( '(Administrator cookie, will be ignored)', 'complianz-gdpr' ) . '</i>' : ''; $membersOnly = $membersOnly ? ' <i>' . __( '(Logged in users only, will be ignored)', 'complianz-gdpr' ) . '</i>' : ''; $html = cmplz_panel( cmplz_sprintf( __( 'Cookie "%s"%s%s', 'complianz-gdpr' ), $cookie->name, $ignored, $membersOnly ), $cookie_html, $icons, false, false ); if ( $cookie->deleted ) { $html = str_replace( array( 'cmplz-toggle-active' ), array( 'cmplz-toggle-active cmplz-deleted' ), $html ); } if ( $cookie->ignored ) { $html = str_replace( array( 'cmplz-toggle-active' ), array( 'cmplz-toggle-disabled' ), $html ); } return $html; } /** * Get html for service list item * * @param $tmpl * @param $name * @param $language * * @return string */ public function get_service_list_item_html( $tmpl, $name, $language ) { if ( ! cmplz_user_can_manage() ) { return ''; } $service = new CMPLZ_SERVICE( $name, $language ); if ( ! $service->ID ) { return ''; } $sync = COMPLIANZ::$cookie_admin->use_cdb_api() ? $service->sync : false; $syncDisabled = ''; if ( ! COMPLIANZ::$cookie_admin->use_cdb_api() ) { $syncDisabled = 'cmplz-disabled'; } $serviceTypes = $this->get_serviceTypes_options( $service->serviceType, $language ); $disabled = $sync ? 'disabled="disabled"' : false; $disabledClass = $sync ? 'cmplz-disabled' : false; $sync = $sync ? 'checked="checked"' : ''; $link = ''; if ( cmplz_get_value( 'use_cdb_links' ) === 'yes' && strlen( $service->slug ) !== 0 && $service->slug !== 'unknown-service' ) { $link = '<a target="_blank" href="https://cookiedatabase.org/service/' . $service->slug . '/">' . __( "View service on cookiedatabase.org", "complianz-gdpr" ) . '</a>'; } $sharesData = $service->sharesData == 1 ? 'checked="checked"' : ''; $service_html = str_replace( array( '{service_id}', '{name}', '{disabled}', '{disabledClass}', '{sync}', '{serviceTypes}', '{privacyStatementURL}', '{sharesData}', '{showOnPolicy}', '{syncDisabled}', "{link}", ), array( $service->ID, $service->name, $disabled, $disabledClass, $sync, $serviceTypes, $service->privacyStatementURL, $sharesData, $service->showOnPolicy, $syncDisabled, $link, ), $tmpl ); $icons = ''; if ( $service->complete ) { $icons .= cmplz_icon( 'check', 'success', __( "The data for this service is complete", "complianz-gdpr" ) ); } else { $icons .= cmplz_icon( 'times', 'error', __( "This service has missing fields", "complianz-gdpr" ) ); } if ( ! $service->sync ) { $icons .= cmplz_icon( 'sync', 'disabled', __( "Synchronization with cookiedatabase.org is not enabled for this service", "complianz-gdpr" ) ); } elseif ( $service->synced ) { $icons .= cmplz_icon( 'sync', 'success', __( "This service has been synchronized with cookiedatabase.org", "complianz-gdpr" ) ); } else { $icons .= cmplz_icon( 'sync', 'error', __( "This service is not synchronized with cookiedatabase.org", "complianz-gdpr" ) ); } return cmplz_panel( cmplz_sprintf( __( 'Service "%s"', 'complianz-gdpr' ), $service->name ), $service_html, $icons, false, false ); } /** * Get a list of cookies or services, in a specific language */ public function ajax_get_list() { if ( ! cmplz_user_can_manage() ) { return; } $msg = 'success'; $language = 'en'; $deleted = false; $type = 'cookie'; if ( isset( $_GET['language'] ) ) { $language = cmplz_sanitize_language( $_GET['language'] ); } if ( isset( $_GET['type'] ) && in_array( $_GET['type'], array( 'service', 'cookie' ) ) ) { $type = $_GET['type']; } if ( isset( $_GET['deleted'] ) && $_GET["deleted"] == 'true' ) { $deleted = true; } $args = array( 'language' => $language, 'deleted' => $deleted, 'isMembersOnly' => 'all', ); if ( $type == 'cookie' ) { $this->reset_cookies_changed(); $items = $this->get_cookies( $args ); //group by service $grouped_by_service = array(); foreach ( $items as $cookie ) { $service = !empty( $cookie->service ) ? $cookie->service : 'no-service'; $grouped_by_service[ $service ][] = $cookie; } $html = ''; $tmpl = cmplz_get_template( $type . '_settings.php' ); if ( $grouped_by_service ) { foreach ( $grouped_by_service as $service_name => $cookies ) { $class = ''; if ( $service_name === 'no-service' ) { $service = __( 'Cookies without selected service', 'complianz-gdpr' ); $class = 'no-service'; } else { $service = $service_name; } $html .= '<div class="cmplz-service-cookie-list">'; $html .= '<div class="cmplz-service-divider ' . $class . '">' . $service . '</div>'; foreach ( $cookies as $cookie ) { $html .= $this->get_cookie_list_item_html( $tmpl, $cookie ); } $html .= '</div>'; } } } else { $items = $this->get_services( $args ); $html = ''; $tmpl = cmplz_get_template( $type . '_settings.php' ); if ( $items ) { foreach ( $items as $service => $item ) { $html .= $this->get_service_list_item_html( $tmpl, $item->name, $language ); } } } $data = array( 'success' => true, 'message' => $msg, 'html' => $html, ); $response = json_encode( $data ); header( "Content-Type: application/json" ); echo $response; exit; } /** * Callback for editing an item */ public function ajax_edit_item() { if (!isset($_POST['nonce'])) { return; } if (!wp_verify_nonce($_POST['nonce'], 'complianz_save')) { return; } if ( ! cmplz_user_can_manage() ) { return; } $error = false; $action = ""; $html = ''; $divider = ''; $msg = 'success'; $item_id = false; $type = 'cookie'; if ( isset( $_POST['type'] ) && in_array( $_POST['type'], array( 'service', 'cookie' ) ) ) { $type = $_POST['type']; } if ( isset( $_POST['item_id'] ) ) { $item_id = intval( $_POST['item_id'] ); } if ( ! $error && isset( $_POST["cmplz_action"] ) ) { $action = sanitize_title( $_POST["cmplz_action"] ); } if ( ! $error && $action === 'save' && $item_id ) { if ( ! $item_id || ! isset( $_POST['data'] ) ) { $error = true; $msg = 'no data sent'; } if ( ! $error ) { $item = ( $type === 'cookie' ) ? new CMPLZ_COOKIE( $item_id ) : new CMPLZ_SERVICE( $item_id ); $data = json_decode( stripslashes( $_POST['data'] ), true ); foreach ( $data as $key => $value ) { if ( ! strpos( $key, 'cmplz_' ) === false ) { continue; } $fieldname = str_replace( 'cmplz_', '', $key ); //test if property exists if ( ! property_exists( $item, $fieldname ) ) { continue; } $item->{$fieldname} = $value; } $item->save( $updateAllLanguages = true ); } } if ( ! $error && $item_id && $action === 'delete' ) { $item = ( $type === 'cookie' ) ? new CMPLZ_COOKIE( $item_id ) : new CMPLZ_SERVICE( $item_id ); $item->delete(); } if ( ! $error && $item_id && $action === 'restore' ) { $item = new CMPLZ_COOKIE( $item_id ); $item->restore(); } if ( ! $error && $action === 'add' ) { $language = cmplz_sanitize_language( $_POST['language'] ); $item = ( $type === 'cookie' ) ? new CMPLZ_COOKIE() : new CMPLZ_SERVICE(); $name = $type . '-' . time(); $new_id = $item->add( $name, $this->get_supported_languages(), $language, false, false ); $tmpl = cmplz_get_template( $type . '_settings.php' ); //create empty set, to use for ajax $services = $this->get_services_options( '', $language ); $purposes = $this->get_cookiePurpose_options( '', $language ); $serviceTypes = $this->get_serviceTypes_options( '', $language ); if ( $type === 'cookie' ) { $title = 'Cookie "' . $name . '"'; $divider = '<div class="cmplz-service-divider no-service">' . __( 'Cookies without selected service', 'complianz-gdpr' ) . '</div>'; $html = str_replace( array( '{' . $type . '_id}', '{disabled}', '{name}', '{services}', '{retention}', '{sync}', '{syncDisabled}', '{showOnPolicy}', '{cookieFunction}', '{purposes}', '{collectedPersonalData}', '{link}', ), array( $new_id, '', $name, $services, '', '', '', 'checked="checked"', '', $purposes, '', '', ), $tmpl ); } else { $title = 'Service "' . $name . '"'; $syncDisabled = ! COMPLIANZ::$cookie_admin->use_cdb_api() ? 'cmplz-disabled' : ''; $html = str_replace( array( '{' . $type . '_id}', '{disabled}', '{name}', '{serviceTypes}', '{privacyStatementURL}', '{sync}', '{syncDisabled}', '{showOnPolicy}', '{link}', ), array( $new_id, '', $name, $serviceTypes, '', '', $syncDisabled, 'checked="checked"', '', ), $tmpl ); } $html = cmplz_panel( __( $title, 'complianz-gdpr' ), $html, '', '', false, true ); } $data = array( 'success' => true, 'message' => $msg, 'action' => $action, 'html' => $html, 'divider' => $divider, ); $response = json_encode( $data ); header( "Content-Type: application/json" ); echo $response; exit; } /** * Delete the transient that contains the pages list * * @param $post_id * @param bool $post_after * @param bool $post_before */ public function clear_pages_list( $post_id, $post_after = false, $post_before = false ) { delete_transient( 'cmplz_pages_list' ); } /** * Runs each used cookies overview pageload to check if any new languages were added in the meantime. * * @hooked admin_init */ public function ensure_cookies_in_all_languages() { if ( ! cmplz_user_can_manage() ) { return; } $step = isset($_REQUEST['step']) ? $_REQUEST['step'] : '1'; if ( $step != STEP_COOKIES ) { return; } $data = $this->get_syncable_cookies( true, true ); if ( ! isset( $data['en'] ) ) { return; } //if no syncable cookies are found, exit. if ( $data['count'] == 0 ) { return; } //get english cookies $cookie_data = $data['en']; $languages = $this->get_supported_languages(); foreach ( $languages as $language ) { if ( $language === 'en' ) { continue; } //make sure each cookie is available in all languages foreach ( $cookie_data as $cookie ) { $translated_cookie = new CMPLZ_COOKIE( $cookie->name, $language ); if ( ! $translated_cookie->ID ) { $translated_cookie->isTranslationFrom = $cookie->ID; $translated_cookie->sync = $cookie->sync; $translated_cookie->showOnPolicy = $cookie->showOnPolicy; $translated_cookie->name = $cookie->name; $translated_cookie->isPersonalData = $cookie->isPersonalData; $translated_cookie->isMembersOnly = $cookie->isMembersOnly; $translated_cookie->serviceID = $cookie->serviceID; $translated_cookie->service = $cookie->service; $translated_cookie->slug = $cookie->slug; $translated_cookie->ignored = $cookie->ignored; $translated_cookie->lastAddDate = time(); $translated_cookie->save(); } } } } /** * Runs once a week to check if the CDB should be synced * * @param bool $running_after_services * * @hooked cmplz_every_week_hook */ public function maybe_sync_cookies( $running_after_services = false ) { if ( ! wp_doing_cron() && ! cmplz_user_can_manage() ) { return 'No permissions'; } $msg = ''; $error = false; $result = false; $data = $this->get_syncable_cookies(); if ( ! $this->use_cdb_api() ) { $error = true; $msg = __( 'You haven\'t accepted the usage of the cookiedatabase.org API. To automatically complete your cookie descriptions, please choose yes.', 'complianz-gdpr' ); } //if no syncable cookies are found, exit. if ( $data['count'] == 0 ) { update_option( 'cmplz_sync_cookies_complete', true ); $msg = "No cookies"; $error = true; } if ( get_transient( 'cmplz_cookiedatabase_request_active' ) ) { $error = true; $msg = __( "A request is already running. Please be patient until the current request finishes", "complianz-gdpr" ); } if ( ! $error ) { set_transient( 'cmplz_cookiedatabase_request_active', true, MINUTE_IN_SECONDS ); //add the plugins list to the data $plugins = get_option( 'active_plugins' ); $data['plugins'] = "<pre>" . implode( "<br />", $plugins ) . "</pre>"; $data['website'] = '<a href="' . esc_url_raw( site_url() ) . '">' . esc_url_raw( site_url() ) . '</a>'; $data = apply_filters( 'cmplz_api_data', $data ); $json = json_encode( $data ); $endpoint = trailingslashit( CMPLZ_COOKIEDATABASE_URL ) . 'v3/cookies/'; $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $endpoint ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" ); curl_setopt( $ch, CURLOPT_POST, 1 ); #in case of local SSL issues, allow for skipping $ssl_verification = apply_filters('cmplz_ssl_verify', get_site_option('cmplz_ssl_verify', 'true' )==='true' ); if ( !$ssl_verification ) { curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false); } curl_setopt( $ch, CURLOPT_POSTFIELDS, $json ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen( $json ) ) ); $result = curl_exec( $ch ); if (curl_errno($ch)) { $error_msg = curl_error($ch); update_option('cmplz_curl_error', $error_msg, false ); // if ( strpos($error_msg, 'SSL certificate problem' )!==false ){ // update_site_option('cmplz_ssl_verify', 'false'); // } } if ( $result === false ) { $error = true; } if ( strpos( $result, '<title>502 Bad Gateway</title>' ) !== false ) { $error = true; } if ( $error ) { $msg = __( "Could not connect to cookiedatabase.org", "complianz-gdpr" ); } curl_close( $ch ); delete_transient( 'cmplz_cookiedatabase_request_active' ); } if ( ! $error ) { $result = json_decode( $result ); //cookie creation also searches fuzzy, so we can now change the cookie name to an asterisk value //on updates it will still match. if ( isset( $result->data->error ) ) { $msg = $result->data->error; $error = true; } else { $result = $result->data; } } if ( ! $error && isset( $result->status ) && $result->status !== 200 ) { $error = true; } if ( ! $error ) { //make sure we have an 'en' cookie if ( is_object( $result ) && property_exists($result, 'en') ) { //first, add "en" as base cookie, and get ID $cookies = $result->en; $isTranslationFrom = []; foreach ( $cookies as $cookie_object ) { if ( !is_object( $cookie_object ) || !property_exists($cookie_object, 'name') ) { continue; } $cookie = new CMPLZ_COOKIE( $cookie_object->original_name, 'en', $cookie_object->service ); $cookie->name = $cookie_object->name; $cookie->retention = $cookie_object->retention; $cookie->type = $cookie_object->type; $cookie->collectedPersonalData = $cookie_object->collectedPersonalData; $cookie->cookieFunction = $cookie_object->cookieFunction; $cookie->purpose = $cookie_object->purpose; $cookie->isPersonalData = $cookie_object->isPersonalData; $cookie->isMembersOnly = $cookie_object->isMembersOnly; $cookie->service = $cookie_object->service; $cookie->ignored = $cookie_object->ignore; $cookie->slug = $cookie_object->slug; $cookie->lastUpdatedDate = time(); $cookie->save(); $isTranslationFrom[ $cookie->name ] = $cookie->ID; } foreach ( $result as $language => $cookies ) { if ($language === 'en') { continue; } foreach ( $cookies as $cookie_object ) { if ( !is_object( $cookie_object ) || !property_exists($cookie_object, 'name') ) { continue; } $cookie = new CMPLZ_COOKIE( $cookie_object->original_name, $language, $cookie_object->service); $cookie->name = $cookie_object->name; $cookie->retention = $cookie_object->retention; $cookie->collectedPersonalData = $cookie_object->collectedPersonalData; $cookie->cookieFunction = $cookie_object->cookieFunction; $cookie->purpose = $cookie_object->purpose; $cookie->isPersonalData = $cookie_object->isPersonalData; $cookie->isMembersOnly = $cookie_object->isMembersOnly; $cookie->service = $cookie_object->service; $cookie->slug = $cookie_object->slug; $cookie->ignored = $cookie_object->ignore; $cookie->lastUpdatedDate = time(); //when there's no en cookie, create one. if ( ! isset( $isTranslationFrom[ $cookie->name ] ) ) { $parent_cookie = new CMPLZ_COOKIE( $cookie->name, 'en' ); $parent_cookie->save(); $isTranslationFrom[ $cookie->name ] = $parent_cookie->ID; } $cookie->isTranslationFrom = $isTranslationFrom[ $cookie->name ]; $cookie->save(); } } } $this->update_sync_date(); } if ( $running_after_services ) { update_option( 'cmplz_sync_cookies_after_services_complete', true ); } else { update_option( 'cmplz_sync_cookies_complete', true ); } return $msg; } /** * Get list of services to be synced * * @return array */ public function get_syncable_services() { if ( ! wp_doing_cron() && ! cmplz_user_can_manage() ) { return []; } $languages = $this->get_supported_languages(); $data = array(); $count_all = 0; $scan_interval = apply_filters('cmplz_sync_interval', 3); $one_week_ago = strtotime( "-".$scan_interval." month" ); foreach ( $languages as $language ) { $args = array( 'sync' => true, 'language' => $language, 'includeServicesWithoutCookies' => true ); if ( ! wp_doing_cron() && ! defined( 'CMPLZ_SKIP_MONTH_CHECK' ) ) { $args['lastUpdatedDate'] = $one_week_ago; } $services = $this->get_services( $args ); $services = wp_list_pluck( $services, 'name' ); $data[ $language ] = $services; $count_all += count( $services ); } $data['count'] = $count_all; return $data; } /** * Get cookies to be synced * * @param false $ignore_time_limit * @param false $include_ignored_cookies * * @return array */ public function get_syncable_cookies( bool $ignore_time_limit = false, bool $include_ignored_cookies = false ): array { if ( ! wp_doing_cron() && ! cmplz_user_can_manage() ) { return []; } $languages = $this->get_supported_languages(); $data = []; $count_all = 0; $scan_interval = apply_filters('cmplz_sync_interval', 3); $one_week_ago = strtotime( "-".$scan_interval." month" ); foreach ( $languages as $language ) { $args = [ 'sync' => true, 'language' => $language, 'ignored' => false, ]; //ignored/admin cookies if ($include_ignored_cookies) unset($args['ignored']); if ( ! $ignore_time_limit && ! wp_doing_cron() && ! defined( 'CMPLZ_SKIP_MONTH_CHECK' ) ) { $args['lastUpdatedDate'] = $one_week_ago; } $cookies = $this->get_cookies( $args ); foreach ( $cookies as $cookie ) { $data[ $language ][] = new CMPLZ_COOKIE( $cookie->name, $language, $cookie->service ); } $count_all += count( $cookies ); } $data['count'] = $count_all; return $data; } /** * Get the cookie domain, without https or end slash * * @return string */ public function get_cookie_domain() { $domain = str_replace( array( 'http://', 'https://' ), '', cmplz_get_value( 'cookie_domain' ) ); if ( substr( $domain, - 1 ) == '/' ) { $domain = substr( $domain, 0, - 1 ); } return apply_filters('cmplz_cookie_domain', $domain); } /** * Get prefix for our Complianz cookies * * @return string */ public function get_cookie_prefix(){ if ( is_multisite() && is_main_site() && !cmplz_get_value( 'set_cookies_on_root' ) ) { return 'cmplz_rt_'; } else { return 'cmplz_'; } } /** * Sync all services */ public function maybe_sync_services() { if ( ! wp_doing_cron() && ! cmplz_user_can_manage() ) { return; } /** * get cookies by service name */ $msg = ''; $error = false; $data = $this->get_syncable_services(); if ( ! $this->use_cdb_api() ) { $error = true; $msg = __( 'You haven\'t accepted the usage of the cookiedatabase.org API. To automatically complete your cookie descriptions, please choose yes.', 'complianz-gdpr' ); } //if no syncable services found, exit. if ( $data['count'] == 0 ) { update_option( 'cmplz_sync_services_complete', true ); $msg = ''; $error = true; } unset( $data['count'] ); if ( get_transient( 'cmplz_cookiedatabase_request_active' ) ) { $error = true; $msg = __( "A request is already running. Please be patient until the current request finishes", "complianz-gdpr" ); } if ( ! $error ) { set_transient( 'cmplz_cookiedatabase_request_active', true, MINUTE_IN_SECONDS ); //clear, for further use of this variable. $data = apply_filters( 'cmplz_api_data', $data ); $json = json_encode( $data ); $endpoint = trailingslashit( CMPLZ_COOKIEDATABASE_URL ) . 'v1/services/'; $ch = curl_init(); curl_setopt( $ch, CURLOPT_URL, $endpoint ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" ); curl_setopt( $ch, CURLOPT_POST, 1 ); $ssl_verification = apply_filters('cmplz_ssl_verify', get_site_option('cmplz_ssl_verify', 'true' )==='true' ); if ( !$ssl_verification ) { curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false); } curl_setopt( $ch, CURLOPT_POSTFIELDS, $json ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen( $json ) ) ); $result = curl_exec( $ch ); if ( $result === false ) { $error = true; } if ( strpos( $result, '<title>502 Bad Gateway</title>' ) !== false ) { $error = true; } if ( $error ) { $msg = __( "Could not connect to cookiedatabase.org", "complianz-gdpr" ); } curl_close( $ch ); delete_transient( 'cmplz_cookiedatabase_request_active' ); } if ( ! $error ) { $result = json_decode( $result ); //cookie creation also searches fuzzy, so we can now change the cookie name to an asterisk value //on updates it will still match. if ( isset( $result->error ) ) { $msg = $result->error; $error = true; } else { $result = $result->data; } } if ( ! $error ) { if ( is_object( $result) && property_exists($result, 'en') ) { $services = $result->en; $isTranslationFrom = array(); foreach ( $services as $original_service_name => $service_and_cookies ) { if ( !is_object( $service_and_cookies) || !property_exists( $service_and_cookies, 'service') ){ continue; } $service_object = $service_and_cookies->service; //sync service data if ( !is_object( $service_object) || !property_exists( $service_object, 'name') ) { continue; } $service = new CMPLZ_SERVICE( $original_service_name, 'en' ); $service->name = $service_object->name; $service->privacyStatementURL = $service_object->privacyStatementURL; $service->sharesData = $service_object->sharesData; $service->secondParty = $service_object->secondParty; $service->thirdParty = $service_object->sharesData && ! $service_object->secondParty; $service->serviceType = $service_object->serviceType; $service->slug = $service_object->slug; $service->lastUpdatedDate = time(); $service->save( true, false ); $isTranslationFrom[ $service->name ] = $service->ID; //get the cookies only if it's third party service. Otherwise, just sync the service itself. if ( ($service->thirdParty || $service->secondParty) && property_exists( $service_and_cookies, 'cookies' ) ) { $cookies = $service_and_cookies->cookies; if ( ! is_array( $cookies ) ) { continue; } foreach ( $cookies as $cookie_name ) { $cookie = new CMPLZ_COOKIE( $cookie_name, 'en', $service->name ); $cookie->add( $cookie_name, $this->get_supported_languages(), false, $service->name ); } } } } foreach ( $result as $language => $services ) { if ( $language === 'en' ) { continue; } foreach ( $services as $original_service_name => $service_and_cookies ) { if ( !is_object( $service_and_cookies) || !property_exists( $service_and_cookies, 'service') ){ continue; } $service_object = $service_and_cookies->service; if ( !is_object( $service_object) || !property_exists( $service_object, 'name') ){ continue; } $service = new CMPLZ_SERVICE( $original_service_name, $language ); $service->name = $service_object->name; $service->privacyStatementURL = $service_object->privacyStatementURL; $service->sharesData = $service_object->sharesData; $service->secondParty = $service_object->secondParty; $service->serviceType = $service_object->serviceType; $service->slug = $service_object->slug; //when there's no 'en' service, create one. if ( ! isset( $isTranslationFrom[ $service->name ] ) ) { $parent_service = new CMPLZ_SERVICE( $service->name, 'en' ); $parent_service->save( false, false ); $isTranslationFrom[ $service->name ] = $parent_service->ID; } $service->isTranslationFrom = $isTranslationFrom[ $service->name ]; $service->save( false, false ); } } $this->update_sync_date(); } update_option( 'cmplz_sync_services_complete', true ); return $msg; } /** * Save the last sync date */ public function update_sync_date() { $timezone_offset = get_option( 'gmt_offset' ); $time = time() + ( 60 * 60 * $timezone_offset ); update_option( 'cmplz_last_cookie_sync', $time ); } public function clear_double_cookienames() { if ( ! wp_doing_cron() && ! cmplz_user_can_manage() ) { return; } $languages = $this->get_supported_languages(); global $wpdb; foreach ( $languages as $language ) { $settings = array( 'language' => $language, 'isMembersOnly' => 'all', ); $cookies = $this->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 ); } } } } /** * Helper function to check if a service exists, and if not, add it. * * @param $services * @param $service_to_add * @param $type * * @return array */ public function maybe_add_service_to_list( $services, $service_to_add, $type ) { if ( ! cmplz_user_can_manage() ) { return; } $added = false; if ( ! is_array( $services ) ) { $services = array(); } foreach ( $services as $service ) { if ( $service->name === $service_to_add ) { $added = true; } } if ( ! $added ) { $service = new CMPLZ_SERVICE(); $service->add( $service_to_add, COMPLIANZ::$cookie_admin->get_supported_languages(), false, $type ); $services[] = $service; } return $services; } public function processing_agreements() { ob_start(); //include( cmplz_path . '/class-processing-table.php' ); $processing_agreements_table = new WP_List_Table(); $processing_agreements_table->prepare_items(); ?> <div id="processing_agreements" class="wrap processing_agreements"> <h1><?php _e( "Processing Agreements", 'complianz-gdpr' ) ?></h1> <?php cmplz_notice( __( 'A Processor or Service Provider is the party that processes personal data on behalf of a responsible organization or person. ' . 'If you are this organization or person, you should probably sign a Processing Agreement with them. ' . 'You can use a Processing Agreement outside of Complianz, or generate one here.', 'complianz-gdpr' ) ) ?> <form id="cmplz-processing-agreements-create" method="POST" action=""> <?php echo wp_nonce_field( 'cmplz_processing_agreements', 'cmplz_nonce' ); ?> <select> <option id="eu">EU</option> </select> <input type="submit" class="button button-primary" name="cmplz_create_processing_agreement" value="<?php _e( "Create", "complianz-gdpr" ) ?>"/> </form> <form id="cmplz-processing-agreements-filter" method="get" action=""> <?php $processing_agreements_table->display(); ?> <input type="hidden" name="page" value="cmplz-processing-agreements"/> </form> <?php do_action( 'cmplz_after_cookiesnapshot_list' ); ?> </div> <?php $content = ob_get_clean(); $args = array( 'page' => 'processing-agreements', 'content' => $content, ); echo cmplz_get_template( 'admin_wrap.php', $args ); } /** * Keep services in sync with selected answers in wizard * * **/ public function update_services() { if ( !cmplz_user_can_manage() ) { return; } $social_media = ( cmplz_get_value( 'uses_social_media' ) === 'yes' ) ? true : false; if ( $social_media ) { $social_media_types = cmplz_get_value( 'socialmedia_on_site' ); foreach ( $social_media_types as $slug => $active ) { if ( $active == 1 ) { $service = new CMPLZ_SERVICE(); //add for all languages $service_name = $thirdparty_services = COMPLIANZ::$config->thirdparty_socialmedia[ $slug ]; $service->add( $service_name, $this->get_supported_languages(), false, 'social' ); } else { $service = new CMPLZ_SERVICE( $slug ); $service->delete(); } } } $thirdparty = ( cmplz_get_value( 'uses_thirdparty_services' ) === 'yes' ) ? true : false; if ( $thirdparty ) { $thirdparty_types = cmplz_get_value( 'thirdparty_services_on_site' ); foreach ( $thirdparty_types as $slug => $active ) { if ( $active == 1 ) { $service = new CMPLZ_SERVICE(); //add for all languages $service_name = $thirdparty_services = COMPLIANZ::$config->thirdparty_services[ $slug ]; $service->add( $service_name, $this->get_supported_languages(), false, 'service' ); } else { $service = new CMPLZ_SERVICE( $slug ); $service->delete(); } } } } /** * Rescan after a manual "rescan" command from the user */ public function rescan() { if ( !cmplz_user_can_manage() ) { return; } if ( isset( $_POST['rescan'] ) ) { if ( ! isset( $_POST['cmplz_nonce'] ) || ! wp_verify_nonce( $_POST['cmplz_nonce'], 'complianz_save' ) ) { return; } update_option( 'cmplz_detected_social_media', false ); update_option( 'cmplz_detected_thirdparty_services', false ); update_option( 'cmplz_detected_stats', false ); $this->reset_pages_list( false, true ); } } /** * Clear the cookies table */ public function clear_cookies() { if ( !cmplz_user_can_manage() ) { return; } if ( isset( $_POST['clear'] ) ) { if ( ! isset( $_POST['cmplz_nonce'] ) || ! wp_verify_nonce( $_POST['cmplz_nonce'], 'complianz_save' ) ) { return; } 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" ); } } $this->resync(); } } /** * Start a new sync * * @param bool $force */ public function resync() { if ( !cmplz_user_can_manage() ) { return; } update_option( 'cmplz_sync_cookies_complete', false ); update_option( 'cmplz_sync_cookies_after_services_complete', false ); update_option( 'cmplz_sync_services_complete', false ); } /** * On activation or deactivation of plugins, we clear the cookie list so it will be scanned anew. * * * */ public function plugin_changes( $plugin, $network_activation ) { if ( !cmplz_user_can_manage() ) { return; } update_option( 'cmplz_plugins_changed', 1 ); //we don't delete this transient, but just reschedule it. Otherwise the scan would start right away, which might cause a memory overload. $this->reset_pages_list( true ); } /** * Check if plugins were changed recently * * @return bool */ public function plugins_changed() { return ( get_option( 'cmplz_plugins_changed' ) == 1 ); } /** * Set plugins as having updated * * @param $upgrader_object * @param $options */ public function plugins_updating( $upgrader_object, $options ) { update_option( 'cmplz_plugins_updated', 1 ); } public function plugins_updated() { return ( get_option( 'cmplz_plugins_updated' ) == 1 ); } public function reset_plugins_updated() { update_option( 'cmplz_plugins_updated', - 1 ); } public function reset_plugins_changed() { update_option( 'cmplz_plugins_changed', - 1 ); } /** * Defer complianz.js * @param string $tag * @param string $handle * * @return string */ public function add_asyncdefer_attribute($tag, $handle) { if ( $handle === 'cmplz-cookiebanner' || $handle === 'cmplz-tcf' ) { return preg_replace( '/^<script /', '<script defer ', $tag ); } return $tag; } /** * Enqueue cookie banner javascript * * @return void */ public function enqueue_assets( ) { $minified = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; $banner = new CMPLZ_COOKIEBANNER( apply_filters( 'cmplz_user_banner_id', cmplz_get_default_banner_id() ) ); $cookiesettings = $banner->get_front_end_settings(); $deps = array(); if ( cmplz_tcf_active() ) { $deps[] = 'cmplz-tcf'; } if ( get_option('cmplz_post_scribe_required') ) { $deps[] = 'cmplz-postscribe'; wp_enqueue_script( 'cmplz-postscribe', cmplz_url . "assets/js/postscribe.min.js", array( 'jquery' ), cmplz_version, true ); } wp_enqueue_script( 'cmplz-cookiebanner', cmplz_url . "cookiebanner/js/complianz$minified.js", $deps, cmplz_version, true ); wp_localize_script( 'cmplz-cookiebanner', 'complianz', $cookiesettings ); if ( cmplz_get_value( 'enable_migrate_js' ) ) { wp_enqueue_script( 'cmplz-migrate', cmplz_url . "cookiebanner/js/migrate$minified.js", array('cmplz-cookiebanner'), cmplz_version, true ); } } /** * Inline css to default hide the banner until fully loaded * @return void */ public function cookiebanner_css(){ ?><style>.cmplz-hidden{display:none!important;}</style><?php } /** * Load the cookie banner html for each consenttype */ public function cookiebanner_html(){ global $post; $type = ''; if ( $post && ( $post->ID ?? false ) ) { if ( preg_match( COMPLIANZ::$document->get_shortcode_pattern( "gutenberg" ), $post->post_content, $matches ) ) { $type = $matches[1]; $region = cmplz_get_region_from_legacy_type( $type ); $type = str_replace( '-' . $region, '', $type ); } elseif ( preg_match( COMPLIANZ::$document->get_shortcode_pattern(), $post->post_content, $matches ) ) { $type = $matches[1]; } elseif ( preg_match( COMPLIANZ::$document->get_shortcode_pattern( "classic", true ), $post->post_content, $matches ) ) { $type = $matches[1]; $region = cmplz_get_region_from_legacy_type( $type ); $type = str_replace( '-' . $region, '', $type ); } } //to prevent WCAG errors, we skip banner html on the cookie statement. But not if TCF enabled, because TCF requires it. if ( $type ==='cookie-statement' && !cmplz_tcf_active() ){ return; } $editor = $new = false; if ( isset($_GET['page'] ) && $_GET['page'] === 'cmplz-cookiebanner' && is_admin() && cmplz_user_can_manage() ) { $editor = isset( $_GET['id'] ) || ( isset( $_GET['action'] ) && $_GET['action'] === 'new' ); $new = isset( $_GET['action'] ) && $_GET['action'] === 'new' ; } $consent_types = cmplz_get_used_consenttypes(); $path = trailingslashit( cmplz_path ).'cookiebanner/templates/'; $manage_consent_template = cmplz_get_template( "manage-consent.php", false, $path); $banner_html=''; $manage_consent_html = ''; global $consent_type; foreach ( $consent_types as $consent_type ) { $banner_template = cmplz_get_template( "cookiebanner.php", array( 'consent_type' => $consent_type ), $path); if ( $editor ) { if ($new) { $banner_ids = array(false); } else { $banner_ids = array( (int) $_GET['id'] ); } } else { if ( cmplz_ab_testing_enabled() ) { $banner_ids = wp_list_pluck(cmplz_get_cookiebanners(), 'ID'); } else { $banner_ids = array(cmplz_get_default_banner_id()); } } foreach ( $banner_ids as $banner_id ) { $temp_banner_html = $banner_template; $temp_manage_consent_html = $manage_consent_template; $banner = new CMPLZ_COOKIEBANNER( $banner_id ); $cookie_settings = $banner->get_html_settings(); foreach($cookie_settings as $fieldname => $value ) { if ( isset($value['text']) ) $value = $value['text']; if ( is_array($value) ) continue; if ( $fieldname !== 'logo') $value = nl2br($value); $temp_banner_html = str_replace( '{'.$fieldname.'}', $value, $temp_banner_html ); $temp_manage_consent_html = str_replace( '{'.$fieldname.'}', $value, $temp_manage_consent_html ); } $banner_html .= $temp_banner_html; $manage_consent_html .= $temp_manage_consent_html; } } $comment = apply_filters('cmplz_document_comment', "\n" . "<!-- Consent Management powered by Complianz | GDPR/CCPA Cookie Consent https://wordpress.org/plugins/complianz-gdpr -->" . "\n"); echo $comment . '<div id="cmplz-cookiebanner-container">'.apply_filters("cmplz_banner_html", $banner_html).'</div> <div id="cmplz-manage-consent" data-nosnippet="true">'.apply_filters("cmplz_manage_consent_html", $manage_consent_html).'</div>'; } /** * 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'] === 'cmplz-wizard' ) { wp_register_style( 'select2', cmplz_url . 'assets/select2/css/select2.min.css', false, cmplz_version ); wp_enqueue_style( 'select2' ); wp_enqueue_script( 'select2', cmplz_url . "assets/select2/js/select2.min.js", array( 'jquery' ), cmplz_version, true ); //script to check for ad blockers wp_enqueue_script( 'cmplz-ad-checker', cmplz_url . "assets/js/ads.js", array( 'cmplz-admin' ), cmplz_version, true ); } } /** * On multisite, we want to get the policy consistent across sites * * @return int */ public function get_active_policy_id() { return get_site_option( 'complianz_active_policy_id', 1 ); } /** * Upgrade the activate policy id with one * The active policy id is used to track if the user has consented to the latest policy changes. * If changes were made, the policy is increased, and user should consent again. * * On multisite, we want to get the policy consistent across sites */ public function upgrade_active_policy_id() { $policy_id = get_site_option( 'complianz_active_policy_id', 1 ); $policy_id++; update_site_option( 'complianz_active_policy_id', $policy_id ); } /** * Check if we're in a subfolder setup (home_url consists of domain+path, e.g. domain.com/sub) * * @return string $path //$path should at least contain a '/', for root application. */ public function get_cookie_path() { //if cookies are to be set on the root, don't send a path if ( cmplz_get_value( 'set_cookies_on_root' ) || function_exists( 'pll__' ) || function_exists( 'icl_translate' ) || class_exists( 'TRP_Translate_Press', false ) ) { return apply_filters( 'cmplz_cookie_path', '/' ); } $domain = home_url(); $parse = parse_url( $domain ); $root_domain = $parse['host']; $path = str_replace( array( 'http://', 'https://', $root_domain ), '', $domain ); return apply_filters( 'cmplz_cookie_path', trailingslashit( $path ) ); } /** * The category that is passed to the statistics script determine if these are executed immediately or not. * * @return string **/ public function get_statistics_category() { //if a cookie warning is needed for the stats we don't add a native class, so it will be disabled by the cookie blocker by default $category = 'statistics'; $uses_tagmanager = cmplz_get_value( 'compile_statistics' ) === 'google-tag-manager' ? true : false; $matomo = cmplz_get_value( 'compile_statistics' ) === 'matomo' ? true : false; //without tag manager, set as functional if no cookie warning required for stats if ( !$uses_tagmanager && ! $this->cookie_warning_required_stats() ) { $category = 'functional'; } //tag manager always fires as functional if ( $uses_tagmanager ){ $category = 'functional'; } if ( $matomo && cmplz_get_value('matomo_anonymized')==='yes' ) { $category = 'functional'; } /* * Run Tag Manager or gtag by default if consent mode is enabled */ if ( cmplz_consent_mode() ) { $category = 'functional'; } return apply_filters( 'cmplz_statistics_category', $category ); } public function inline_cookie_script() { //based on the script classes, the statistics will get added on consent, or without consent $category = $this->get_statistics_category(); $statistics = cmplz_get_value( 'compile_statistics' ); $fields = COMPLIANZ::$config->fields(); $aw_code = cmplz_get_value( 'AW_code' ); $configured_by_complianz = isset( $fields['configuration_by_complianz'] ) && cmplz_get_value( 'configuration_by_complianz' ) !== 'no'; do_action( 'cmplz_before_statistics_script' ); /** * Tag manager needs to be included as text/javascript (omitted as it's default), as it always needs to fire. * All other scripts will be included with the appropriate tags, and fired when possible */ $stats_comment = '<!-- Statistics script Complianz GDPR/CCPA -->' . "\n"; if ( $configured_by_complianz && $statistics !== 'no' ) { if ( $statistics === 'google-tag-manager' || $statistics === 'matomo-tag-manager' ) { ob_start(); do_action( 'cmplz_tagmanager_script' ); $statistics_script = ob_get_clean(); if ( !empty($statistics_script) ) { echo $stats_comment; ?> <script data-category="<?php echo esc_attr($category) ?>"> <?php echo $statistics_script; ?> </script><?php } } else { ob_start(); do_action( 'cmplz_statistics_script' ); $statistics_script = ob_get_clean(); if ( !empty($statistics_script) ) { echo $stats_comment; ?> <script <?php echo $category==='functional' ? '' : 'type="text/plain"' ?> data-category="<?php echo esc_attr($category) ?>"><?php echo $statistics_script; ?></script><?php } } if ( !empty($aw_code ) && $statistics === 'google-analytics' ) { $script = str_replace( '{AW_code}', $aw_code, cmplz_get_template( "statistics/gtag-remarketing.js" ) ); //remarketing with consent mode should be executed without consent, as consent mode handles the consent if ( cmplz_consent_mode() ) { ?> <script data-category="functional"><?php echo $script; ?></script><?php } else { ?> <script type="text/plain" data-category="marketing"><?php echo $script; ?></script><?php } } } if ( cmplz_get_value( 'safe_mode' ) == 1 ) { return; } $scripts = get_option("complianz_options_custom-scripts"); if ( !is_array($scripts) || !isset($scripts['add_script']) || !is_array( $scripts['add_script'] ) ) { return; } $added_scripts = array_filter( $scripts['add_script'], function($script) { return $script['enable'] == 1; }); $added_scripts = apply_filters('cmplz_added_scripts', $added_scripts ); foreach ( $added_scripts as $script ) { if ( !isset($script['editor']) || empty( $script['editor']) ) continue; echo "<!-- Script Center {$script['category']} script Complianz GDPR/CCPA -->\n"; $async = $script['async']== 1 ? 'async' : ''; ?> <script <?php echo $async?> type="text/plain" data-category="<?php echo esc_attr($script['category'])?>"> <?php echo ($script['editor']) ?> </script> <?php } } /** * Insert the gtag.js script required if gtag.js is used * * @hooked cmplz_before_statistics_script * @since 4.7.8 */ public function add_gtag_js() { if ( cmplz_get_value( 'configuration_by_complianz' ) === 'no' ) { return; } $statistics = cmplz_get_value( 'compile_statistics' ); $gtag_code = esc_attr( cmplz_get_value( "UA_code" ) ); if ( $statistics === 'google-analytics' && !empty($gtag_code) ) { $category = $this->get_statistics_category(); ?> <script async data-category="<?php echo $category ?>" src="https://www.googletagmanager.com/gtag/js?id=<?php echo $gtag_code ?>"></script><?php } } /** * Add generic clicky js script */ public function add_clicky_js(){ $statistics = cmplz_get_value( 'compile_statistics' ); if ( $statistics === 'clicky' ) { $category = $this->get_statistics_category(); ?> <script async <?php echo $category==='functional' ? '' : 'type="text/plain"' ?> data-category="<?php echo $category ?>" src="//static.getclicky.com/js"></script> <?php } } /** * Inline scripts which do not require a warning */ public function inline_cookie_script_no_warning() { do_action( 'cmplz_before_statistics_script' ); ?> <script data-category="functional"> <?php do_action( 'cmplz_statistics_script' );?> <?php do_action( 'cmplz_tagmanager_script' );?> </script> <?php } /** * * @hooked cmplz_tagmanager_script * * */ public function get_tagmanager_script() { if ( cmplz_get_value( 'configuration_by_complianz' ) !== 'yes' ) { return; } $script = ''; $statistics = cmplz_get_value( 'compile_statistics' ); if ( $statistics === 'google-tag-manager' ) { $consent_mode = cmplz_consent_mode() ? '-consent-mode' : ''; $script = cmplz_get_template( "statistics/google-tag-manager$consent_mode.js" ); $script = str_replace( '{GTM_code}', esc_attr( cmplz_get_value( "GTM_code" ) ), $script ); } elseif ( $statistics === 'matomo-tag-manager' ) { $script = cmplz_get_template( 'statistics/matomo-tag-manager.js' ); $script = str_replace( array( '{container_id}', '{matomo_url}' ), array( esc_attr( cmplz_get_value( 'matomo_container_id' ) ), esc_url_raw( trailingslashit( cmplz_get_value( 'matomo_tag_url' ) ) ) ), $script ); } echo apply_filters( 'cmplz_script_filter', $script ); } /** * * @hooked cmplz_statistics_script * * * */ public function get_statistics_script() { if ( cmplz_get_value( 'configuration_by_complianz' ) === 'no' ) { return; } $statistics = cmplz_get_value( 'compile_statistics' ); $script = ''; if ( $statistics === 'google-analytics' ) { $consent_mode = cmplz_consent_mode() ? '-consent-mode' : ''; $code = esc_attr( cmplz_get_value( "UA_code" ) ); $anonymize_ip = $this->google_analytics_always_block_ip() ? "'anonymize_ip': true" : ""; if ( substr( strtoupper($code), 0, 2) === 'G-' ) { $anonymize_ip = ''; } $enable_tcf_support = cmplz_tcf_active() ? 'true' : 'false'; $script = cmplz_get_template( "statistics/gtag$consent_mode.js" ); $script = str_replace( array('{G_code}', '{anonymize_ip}', '{enable_tcf_support}'), array($code, $anonymize_ip, $enable_tcf_support), $script ); } elseif ( $statistics === 'matomo' ) { $cookieless = ( cmplz_get_value( 'matomo_anonymized' ) === 'yes' ) ? '-cookieless' : ''; $script = cmplz_get_template( "statistics/matomo$cookieless.js" ); $script = str_replace( array( '{site_id}', '{matomo_url}' ), array( esc_attr( cmplz_get_value( 'matomo_site_id' ) ), esc_url_raw( trailingslashit( cmplz_get_value( 'matomo_url' ) ) ) ), $script ); } elseif ( $statistics === 'clicky' ) { $script = cmplz_get_template( 'statistics/clicky.js' ); $script = str_replace( '{site_ID}', esc_attr( cmplz_get_value( 'clicky_site_id' ) ), $script ); } elseif ( $statistics === 'clarity' ) { $script = cmplz_get_template( 'statistics/clarity.js' ); $script = str_replace( '{site_ID}', esc_attr( cmplz_get_value( 'clarity_id' ) ), $script ); } elseif ( $statistics === 'yandex' ) { $script = cmplz_get_template( 'statistics/yandex.js' ); $data_layer = cmplz_get_value('yandex_ecommerce') === 'yes'; $data_layer_str = ''; if ( $data_layer ) { $data_layer_str = 'ecommerce:"dataLayer"'; } $script = str_replace( array('{yandex_id}','{ecommerce}'), array(cmplz_get_value( 'yandex_id' ), $data_layer_str ), $script ); } echo apply_filters( 'cmplz_script_filter', $script ); } /** * * Get the domain from the current site url * * @return bool|string $domain */ public function get_domain() { $url = site_url(); $parse = parse_url( $url ); if ( ! isset( $parse['host'] ) ) { return false; } return $parse['host']; } /** * 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 ( !cmplz_user_can_manage() ) { 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 } /** * 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 = $this->get_cookies( array( 'new' => true ) ); if ( count( $new_cookies ) > 0 ) { $this->set_cookies_changed(); } } /** * get boolean string for database purposes * * @param bool $boolean * * @return string */ private function bool_string( $boolean ) { $bool = boolval( $boolean ); return $bool ? 'TRUE' : 'FALSE'; } /** * Insert an iframe to retrieve front-end cookies * * * */ public function run_cookie_scan() { if ( ! cmplz_user_can_manage() ) { 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 = $this->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; } //first, get the html of this page. if ( strpos( $url, 'complianz_id' ) !== false ) { $response = wp_remote_get( $url ); if ( ! is_wp_error( $response ) ) { $html = $response['body']; $stored_social_media = cmplz_scan_detected_social_media(); if ( ! $stored_social_media ) { $stored_social_media = array(); } $social_media = $this->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::$wizard->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 ); } } //load in iframe so the scripts run. echo '<iframe id="cmplz_cookie_scan_frame" class="hidden" src="' . $url . '"></iframe>'; } } /** * 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 ) { if ( !cmplz_user_can_manage() ) { return 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 ( !cmplz_user_can_manage() ) { return; } 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( 'wizard', 'GTM_code', sanitize_text_field( $matches[2] ) ); update_option( 'cmplz_detected_stats_data', true ); cmplz_update_option( 'wizard', '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( 'wizard', 'UA_code', sanitize_text_field( $matches[2] ) ); cmplz_update_option( 'wizard', '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( 'wizard', 'UA_code', sanitize_text_field( $matches[2] ) ); cmplz_update_option( 'wizard', 'compile_statistics', 'google-analytics' ); } $pattern = '/\'anonymizeIp|anonymize_ip\'|:[ ]{0,1}true/i'; preg_match( $pattern, $html, $matches ); if ( $matches ) { $value = cmplz_get_value( 'compile_statistics_more_info' ); if ( ! is_array( $value ) ) { $value = array(); } $value['ip-addresses-blocked'] = 1; cmplz_update_option( 'wizard', '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( 'wizard', '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( 'wizard', 'matomo_site_id', intval( $matches[1] ) ); update_option( 'cmplz_detected_stats_data', true ); } cmplz_update_option( 'wizard', '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( 'wizard', 'clicky_site_id', intval( $matches[1] ) ); update_option( 'cmplz_detected_stats_data', true ); cmplz_update_option( 'wizard', '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( 'wizard', 'yandex_id', intval( $matches[1] ) ); update_option( 'cmplz_detected_stats_data', true ); cmplz_update_option( 'wizard', 'compile_statistics', 'yandex' ); } } } /** * Check the webpage html output for social media markers. * * @param string $html * @param bool $single_key * * @return array|bool|string $social_media_key */ public function parse_for_social_media( $html, $single_key = false ) { if ( !cmplz_user_can_manage() ) { return false; } $social_media = array(); $social_media_markers = COMPLIANZ::$config->social_media_markers; foreach ( $social_media_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, $social_media ) ) { $social_media[] = $key; } } } if ( $single_key ) { return false; } return $social_media; } /** * 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 ) { if ( !cmplz_user_can_manage() ) { return 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 = time(); update_option( 'complianz_scan_token', $token ); $pages = $this->pages_to_process(); if ( count( $pages ) == 0 ) { return false; } //run our remote scan for this batch, only on the third request, when processed pages is 2. $processed_pages_list = $this->get_processed_pages_list(); if ( count($processed_pages_list)==2 ) { do_action('cmplz_remote_cookie_scan'); } $id_to_process = reset( $pages ); $this->set_page_as_processed( $id_to_process ); switch ( $id_to_process ) { 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 string $url * *@since 1.0 */ public function get_remote_scan_url() { if ( !cmplz_user_can_manage() ) { return false; } //homepage is not always a post. if ( !get_option('cmplz_remote_homepage_scanned') ) { update_option('cmplz_remote_homepage_scanned', true, false); return site_url(); } //from each post type, get one, for faster results. $post_types = $this->get_scannable_post_types(); $args = array( 'post_type' => $post_types, 'posts_per_page' => 1, 'meta_query' => array( array( 'key' => '_cmplz_remote_scanned_post', 'compare' => 'NOT EXISTS' ), ) ); $posts = get_posts( $args ); if ( count( $posts ) > 0 ) { $post = reset( $posts ); update_post_meta( $post->ID, '_cmplz_remote_scanned_post', true ); return get_permalink( $post->ID ); } //reset all posts, so we can start over. delete_post_meta_by_key( '_cmplz_remote_scanned_post' ); return site_url(); } /** * * 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 ) { $post_types = $this->get_scannable_post_types(); //from each post type, get one, for faster results. $all_types_posts = array(); 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 = array_merge( $all_types_posts, $new_posts ); } $all_types_array = wp_list_pluck($all_types_posts, 'ID'); $posts = 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 ); $posts = array_merge( $posts, $new_posts ); } $posts = array_merge( $posts, $all_types_posts ); 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 { $posts = wp_list_pluck( $posts, 'ID' ); foreach ( $posts as $post_id ) { update_post_meta( $post_id, '_cmplz_scanned_post', true ); } } $posts[] = 'home'; if ( cmplz_get_value( 'wp_admin_access_users' ) === 'yes' ) { $posts[] = 'loginpage'; } set_transient( 'cmplz_pages_list', $posts, MONTH_IN_SECONDS ); } return $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 ( !cmplz_user_can_manage() ) { return; } if ( ! $manual && $this->automatic_cookiescan_disabled() ) { return; } if ( $manual && $this->automatic_cookiescan_disabled() ) { $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 ( !cmplz_user_can_manage() ) { return; } 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_value( '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 $pages; } /** * Check if the scan is complete * * @param void * * @return bool * @since 1.0 * * */ public function scan_complete() { $pages = $this->pages_to_process(); return count( $pages ) == 0; } /** * * Get list of pages that still have to be processed * * @param void * * @return array $pages * @since 1.0 */ private function pages_to_process() { $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 ) { if ( !cmplz_user_can_manage() ) { return; } if ( $id !== 'home' && $id !== 'loginpage' && ! is_numeric( $id ) ) { return; } $pages = $this->get_processed_pages_list(); if ( ! in_array( $id, $pages ) ) { $pages[] = $id; $expiration = $this->automatic_cookiescan_disabled() ? 10 * YEAR_IN_SECONDS : MONTH_IN_SECONDS; set_transient( 'cmplz_processed_pages_list', $pages, $expiration ); } } /** * Check if we want to notify about Google Fonts * @return bool */ public function show_google_fonts_notice(): bool { if ( !cmplz_uses_thirdparty('google-fonts') ) { return false; } return !defined( "CMPLZ_SELF_HOSTED_PLUGIN_ACTIVE" ) && strpos( get_locale(), 'de_' ) !== false; } /** * Get cookies by service * * @param array $settings * * @return array */ public function get_cookies_by_service( array $settings = [] ): array { $cookies = COMPLIANZ::$cookie_admin->get_cookies( $settings ); $grouped_by_service = array(); $topServiceID = 0; foreach ( $cookies as $cookie ) { $serviceID = $cookie->serviceID ?: 999999999; $topServiceID = $serviceID > $topServiceID ? $serviceID : $topServiceID; $purpose = $cookie->purpose === 0 || strlen( $cookie->purpose ) == 0 ? __( 'Purpose pending investigation', 'complianz-gdpr' ) : $cookie->purpose; $grouped_by_service[ $serviceID ][ $purpose ][] = $cookie; } //move misc to end of array $misc = $grouped_by_service[999999999] ?? false; unset( $grouped_by_service[999999999] ); if ( $misc ) { $grouped_by_service[ $topServiceID + 1 ] = $misc; } return $grouped_by_service; } /** * Get list of active cookies on site * * @return array|object|null */ public function get_cookies( $settings = array() ) { global $wpdb; $defaults = array( 'ignored' => 'all', 'new' => false, 'language' => false, 'isPersonalData' => 'all', 'isMembersOnly' => false, 'hideEmpty' => false, 'showOnPolicy' => 'all', 'lastUpdatedDate' => false, 'deleted' => false, 'isOwnDomainCookie' => 'all', ); $settings = wp_parse_args( $settings, $defaults ); $sql = ' 1=1 '; if ( $settings['isPersonalData'] !== 'all' ) { $sql .= ' AND isPersonalData = ' . $this->bool_string( $settings['isPersonalData'] ); } if ( $settings['isMembersOnly'] !== 'all' ) { $sql .= ' AND isMembersOnly = ' . $this->bool_string( $settings['isMembersOnly'] ); } if ( $settings['showOnPolicy'] !== 'all' ) { $sql .= ' AND showOnPolicy = ' . $this->bool_string( $settings['showOnPolicy'] ); } if ( $settings['ignored'] !== 'all' ) { $sql .= ' AND ignored = ' . $this->bool_string( $settings['ignored'] ); } if ( $settings['isOwnDomainCookie'] !== 'all' ) { if ( $settings['isOwnDomainCookie']) { //legacy support for owndomain cookie value $sql .= " AND (domain = 'self' OR isOwnDomainCookie = true) "; } else { $sql .= " AND (domain != 'self') "; } } if ( ! $settings['language'] ) { $sql .= ' and isTranslationFrom = false '; } else { $sql .= $wpdb->prepare( ' and language = %s', $settings['language'] ); } if ( $settings['hideEmpty'] ) { $sql .= " AND name <>'' "; } if ( ! $settings['deleted'] ) { $sql .= " AND deleted != true "; } if ( isset( $settings['sync'] ) ) { $sql .= ' AND sync = ' . $this->bool_string( $settings['sync'] ); } if ( $settings['new'] ) { $sql .= $wpdb->prepare( ' AND firstAddDate > %s ', get_option( 'cmplz_cookie_data_verified_date' ) ); } if ( $settings['lastUpdatedDate'] ) { $sql .= $wpdb->prepare( ' AND (lastUpdatedDate < %s OR lastUpdatedDate=FALSE OR lastUpdatedDate=0)', (int) $settings['lastUpdatedDate'] ); } //stringyfy select args. $settings_args = sanitize_title(json_encode($settings)); $cookies = get_transient('cmplz_cookies_'.$settings_args); if ( !$cookies || cmplz_user_can_manage() ){ $table_exists = get_transient('cmplz_cookie_table_exists'); if ( !$table_exists ){ $table_exists = $wpdb->query( "SHOW TABLES LIKE '{$wpdb->prefix}cmplz_cookies'" ); set_transient('cmplz_cookie_table_exists', $table_exists ); } if ( empty( $table_exists ) ) { return array(); } $cookies = $wpdb->get_results( "select * from {$wpdb->prefix}cmplz_cookies where " . $sql ); //make sure service data is added foreach ( $cookies as $index => $cookie ) { $cookie = new CMPLZ_COOKIE( $cookie->ID ); $cookies[ $index ] = $cookie; } set_transient('cmplz_cookies_'.$settings_args, $cookies, HOUR_IN_SECONDS); } return $cookies; } /** * convert a slug to a normal readable name, without -, and with uppercase start of each word * * @param $slug * * @return string */ public function convert_slug_to_name( $slug ) { $a = explode( '-', $slug ); $a = array_map( 'ucfirst', $a ); return implode( ' ', $a ); } /** * Get list of detected services * * @param array $settings * * @return array $services * @since 1.0 * */ public function get_services( array $settings = array() ): array { global $wpdb; $result = $wpdb->query( "SHOW TABLES LIKE '{$wpdb->prefix}cmplz_cookies'" ); if ( empty( $result ) ) { return array(); } $defaults = array( 'language' => false, 'hideEmpty' => false, 'category' => 'all', 'lastUpdatedDate' => false, 'includeServicesWithoutCookies' => false, ); $settings = wp_parse_args( $settings, $defaults ); $sql = ' 1=1 '; if ( $settings['language'] ) { $lang = cmplz_sanitize_language( $settings['language'] ); $sql .= " AND language = '$lang' "; } if ( $settings['hideEmpty'] ) { $sql .= " AND name <>'' "; } if ( isset( $settings['sync'] ) ) { $sql .= ' AND sync = ' . $this->bool_string( $settings['sync'] ); } if ( $settings['category'] !== 'all' ) { $sql .= $wpdb->prepare( " AND category = %s", $settings['category'] ); } if ( ! $settings['language'] ) { $sql .= ' and isTranslationFrom = false '; } else { $sql .= $wpdb->prepare( ' and language = %s', $settings['language'] ); } $no_cookies_where = $sql; if ( $settings['lastUpdatedDate'] ) { $sql .= $wpdb->prepare( ' AND (lastUpdatedDate < %s OR lastUpdatedDate=FALSE OR lastUpdatedDate = 0 )', (int) $settings['lastUpdatedDate'] ); } $sql = "select * from {$wpdb->prefix}cmplz_services where " . $sql; $services = $wpdb->get_results( $sql ); if ( $settings['includeServicesWithoutCookies'] ) { $sql = "select * from ( select * from {$wpdb->prefix}cmplz_services where NOT ID in (select DISTINCT services.ID from {$wpdb->prefix}cmplz_services as services inner join {$wpdb->prefix}cmplz_cookies on services.ID = {$wpdb->prefix}cmplz_cookies.serviceID)) as services where $no_cookies_where"; $services_no_cookies = $wpdb->get_results( $sql ); $service_ids = wp_list_pluck($services, 'ID'); foreach ( $services_no_cookies as $service_no_cookies ) { if ( !in_array( $service_no_cookies->ID ,$service_ids) ){ $services[] = $service_no_cookies; } } } return $services; } /** * Get an array of languages used on this site in format array('en' => 'en') * * @param bool $count * * @return int|array */ public function get_supported_languages( bool $count = false ) { $site_locale = cmplz_sanitize_language( get_locale() ); $languages = array( $site_locale => $site_locale ); //QTranslate if ( defined('QTX_VERSION') ) { $enabled_languages = get_option( 'qtranslate_enabled_languages' ); if (is_array($enabled_languages)) { foreach ( $enabled_languages as $language_code ) { if ( ! in_array( $language_code, $languages ) ) { $languages[ $language_code ] = $language_code; } } } } if ( function_exists( 'icl_register_string' ) ) { $wpml = apply_filters( 'wpml_active_languages', null, array( 'skip_missing' => 0 ) ); if ( !is_array($wpml) ){ $wpml = []; } /** * WPML has changed the index from 'language_code' to 'code' so * we check for both. */ $wpml_test_index = reset( $wpml ); if ( isset( $wpml_test_index['language_code'] ) ) { $wpml = wp_list_pluck( $wpml, 'language_code' ); } elseif ( isset( $wpml_test_index['code'] ) ) { $wpml = wp_list_pluck( $wpml, 'code' ); } else { $wpml = array(); } $languages = array_merge( $wpml, $languages ); } /** * TranslatePress support * There does not seem to be an easy accessible API to get the languages, so we retrieve from the settings directly */ if ( class_exists( 'TRP_Translate_Press' ) ) { $trp_settings = get_option( 'trp_settings', array() ); if ( isset( $trp_settings['translation-languages'] ) ) { $trp_languages = $trp_settings['translation-languages']; foreach ( $trp_languages as $language_code ) { $key = substr( $language_code, 0, 2 ); $languages[ $key ] = $key; } } } if ( $count ) { return count( $languages ); } //make sure the en is always available. if ( ! in_array( 'en', $languages ) ) { $languages['en'] = 'en'; } return $languages; } /** * Get the last cookie scan date in unix or human time format * * @param bool $unix * * @return bool|int|string */ public function get_last_cookie_scan_date( $unix = false ) { $last_scan_date = get_option( 'cmplz_last_cookie_scan' ); if ( $unix ) { return $last_scan_date; } if ( $last_scan_date ) { $date = cmplz_localize_date( $last_scan_date ); $time = date( get_option( 'time_format' ), $last_scan_date ); $date = cmplz_sprintf( __( "%s at %s", 'complianz-gdpr' ), $date, $time ); } else { $date = false; } return $date; } /** * Get the last cookie sync date in unix or human time format * * @return string */ public function get_last_cookie_sync_date(): string { $last_sync_date = get_option( 'cmplz_last_cookie_sync' ); if ( $last_sync_date ) { $date = cmplz_localize_date( $last_sync_date ); } else { $date = __( '(not synced yet)', 'complianz-gdpr' ); } return $date; } /** * Set the cookies as having been changed */ public function set_cookies_changed() { update_option( 'cmplz_changed_cookies', 1 ); } /** * Check if cookies have been changed * * @return bool */ public function cookies_changed() { return ( get_option( 'cmplz_changed_cookies' ) == 1 ); } /** * Reset the cookies changed value */ public function reset_cookies_changed() { update_option( 'cmplz_cookie_data_verified_date', time() ); delete_transient( 'cmplz_cookie_settings_cache' ); update_option( 'cmplz_changed_cookies', - 1 ); } /** * 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 ); } /** * Hooked into ajax call to load detected cookies * * @hooked wp_ajax_load_detected_cookies */ public function load_detected_cookies() { $error = false; $cookies=array(); if ( ! cmplz_user_can_manage() ) { $error = true; } if ( ! $error ) { $args = array( 'isTranslationFrom' => false, ); $cookies = $this->get_cookies( $args ); $cookies = wp_list_pluck($cookies, 'name'); } $out = array( 'success' => true, 'cookies' => $cookies, ); echo json_encode( $out ); wp_die(); } /** * Get html for list of detected cookies * * @return string */ public function get_detected_cookies_table() { $list_html = ''; $args = array( 'isTranslationFrom' => false, ); $cookies = $this->get_cookies( $args ); if ( ! $cookies && $this->scan_complete() ) { $detected = __( "No cookies detected", 'complianz-gdpr' ); } else { $cookie_count = $this->scan_complete() ? count($cookies) : 0; $detected = cmplz_sprintf( _n( 'The scan found %s cookie on your domain.', 'The scan found %s cookies on your domain.', $cookie_count, 'complianz-gdpr' ), '<span class="cmplz-scan-count">'.number_format_i18n( $cookie_count ).'</span>' ) ; $detected .= ' '.__('Continue the wizard to categorize cookies and configure consent.', 'complianz-gdpr'); /** * Create list */ $cookies = wp_list_pluck( $cookies, 'name' ); $list_html .= '<div class="cmplz-cookies-table">'; if ( $cookies ) { foreach ( $cookies as $name ) { $list_html .= '<div>' . $name . '</div>'; } } else { $list_html .= '<span>' . __("Nothing found yet.", "complianz-gdpr") . '</span>'; } $list_html .= '</div>'; } return cmplz_panel( $detected, $list_html, false, false); } /** * Check if there's a cookie which is not filled out entirely * * @return bool */ public function has_empty_cookie_descriptions() { $cookies = COMPLIANZ::$cookie_admin->get_cookies( array( 'showOnPolicy' => true, 'ignored' => false ) ); if ( is_array( $cookies ) ) { foreach ( $cookies as $cookie_name ) { $cookie = new CMPLZ_COOKIE( $cookie_name ); if ( $cookie->showOnPolicy && ! $cookie->complete ) { return true; } } } return false; } /** * Get progress of the current scan to output with ajax */ public function get_scan_progress() { $next_url = $this->get_next_page_url(); $args = array( 'isTranslationFrom' => false, ); $cookies = $this->get_cookies( $args ); $progress = $this->get_progress_count(); $total = count($cookies); $current = intval($progress/100 * $total); $cookies = array_slice( $cookies, 0, $current); $cookies = wp_list_pluck( $cookies, 'name' ); $output = array( "progress" => $progress, "next_page" => $next_url, 'cookies' => $cookies, ); echo json_encode( $output ); wp_die(); } /** * force sync on update to new CDB versions */ public function run_sync_on_update() { if ( ! $this->use_cdb_api() ) { return; } if ( ! get_option( 'cmplz_run_cdb_sync_once' ) ) { return; } //make sure this is only attempted max 3 times. $attempts = get_transient( 'cmplz_sync_attempts' ); if ( ! $attempts ) { $attempts = 0; } if ( $attempts < 5 ) { $progress = $this->get_sync_progress(); if ( $progress < 50 ) { $this->maybe_sync_cookies(); } if ( $progress >= 50 && $progress < 75 ) { $this->maybe_sync_services(); } //after adding the cookies, do one more cookies sync if ( $progress >= 75 && $progress < 100 ) { $this->maybe_sync_cookies( true ); $this->clear_double_cookienames(); //clean up cache delete_transient('cmplz_cookie_shredder_list' ); } $attempts = $attempts + 1; set_transient( 'cmplz_sync_attempts', $attempts, DAY_IN_SECONDS ); } } /** * Run a sync * */ public function run_sync() { if ( !cmplz_user_can_manage() ) { return; } if (!isset($_GET['nonce'])) { return; } if (!wp_verify_nonce($_GET['nonce'], 'complianz_save')) { return; } if ( isset( $_GET['restart'] ) && $_GET['restart'] == 'true' ) { $this->resync(); } $msg = ""; $progress = $this->get_sync_progress(); if ( $progress < 50 ) { $msg = $this->maybe_sync_cookies(); } if ( $progress >= 50 && $progress < 75 ) { $msg = $this->maybe_sync_services(); } //after adding the cookies, do one more cookies sync if ( $progress >= 75 && $progress < 100 ) { $this->maybe_sync_cookies( true ); $this->clear_double_cookienames(); } $output = array( "message" => $msg, "progress" => $progress, ); echo json_encode( $output ); wp_die(); } /** * Get syn progress * @return int */ public function get_sync_progress() { $progress = 10; if ( get_option( 'cmplz_sync_cookies_complete' ) ) { $progress = 50; } if ( get_option( 'cmplz_sync_cookies_complete' ) && get_option( 'cmplz_sync_services_complete' ) ) { $progress = 75; } if ( get_option( 'cmplz_sync_cookies_complete' ) && get_option( 'cmplz_sync_services_complete' ) && get_option( 'cmplz_sync_cookies_after_services_complete' ) ) { //if sync was started after update, stop it now update_option( 'cmplz_run_cdb_sync_once', false ); $progress = 100; } return $progress; } /** * Get scan progress html */ public function scan_progress() { $disabled = ""; if ( ! function_exists( 'curl_version' ) ) { $disabled = "disabled"; } ?> <div class="cmplz-field"> <div class="cmplz-buttons-row-left"> <input <?php echo $disabled ?> type="submit" class="button cmplz-rescan" value="<?php _e( 'Scan', 'complianz-gdpr' ) ?>" name="rescan" > <input <?php echo $disabled ?> type="submit" class="button button-red cmplz-reset" onclick="return confirm('<?php _e( 'Are you sure? This will permanently delete the list of cookies.', 'complianz-gdpr' ) ?>');" value="<?php _e( 'Clear cookies', 'complianz-gdpr' ) ?>" name="clear" > </div> <br /> <div class="cmplz-label"><label><?php _e( "Cookie scan", "complianz-gdpr" ) ?></label></div> <div id="cmplz-scan-progress"> <div class="cmplz-progress-bar"></div> </div> <br /> <div class="detected-cookies"> <?php echo $this->get_detected_cookies_table(); ?> </div> </div> <?php } /** * Get sync progress html * @return void */ public function sync_progress() { $explanation = ''; $data_cookies = $this->get_syncable_cookies(); $data_services = $this->get_syncable_services(); $disabled = $this->use_cdb_api() ? '' : 'disabled'; if ( ! function_exists( 'curl_version' ) ) { $disabled = "disabled"; } if ( $data_cookies['count'] == 0 && $data_services['count'] == 0 ) { $disabled = "disabled"; } $default_language = substr( get_locale(), 0, 2 ); $languages = COMPLIANZ::$cookie_admin->get_supported_languages(); ?> <div class="field-group sync_progress"> <div class="cmplz-field"> <div class="cmplz-buttons-row-left"> <input type="button" <?php echo $disabled ?> class="button cmplz-resync" value="<?php _e( 'Sync', 'complianz-gdpr' ) ?>" name="resync"> <?php if ( count( $languages ) > 1 ) { ?> <select id="cmplz_language" class="cmplz_cookie_language_selector" data-type="cookie"> <?php foreach ( $languages as $language ) { ?> <option value="<?php echo $language ?>" <?php if ( $default_language === $language ) echo "selected" ?>> <?php echo $this->get_language_descriptor( $language ); ?> </option> <?php } ?> </select> <?php } else { ?> <input type="hidden" id="cmplz_language" data-type="cookie" value="<?php echo reset( $languages ) ?>"> <?php } ?> <label tabindex="0" role="button" aria-pressed="false" class="cmplz-switch"> <input name="cmplz_show_deleted" size="40" type="checkbox" value="1"/> <span class="cmplz-slider cmplz-round"></span> </label> <span><?php _e( "Show deleted cookies", "complianz-gdpr" ) ?></span> </div> <div class="cmplz-label cmplz-sync-status"> <label class=""><span><?php _e( "Syncing...", 'complianz-gdpr' ) ?></span> </label> </div> <div id="cmplz-sync-progress"> <div class="cmplz-sync-progress-bar"></div> </div> </div> <div class="cmplz-help-warning-wrap"> <?php echo $explanation ?> <div id="cmplz-warning cmplz_action_error" class="cmplz-hidden"> <?php echo cmplz_notice( '<!-- error msg-->', 'warning' ) ?> </div> </div> </div> <?php } /** * @param string $language * @param string $type * * @return string */ private function get_language_descriptor( string $language, string $type = 'cookie' ): string { $string = $type === 'cookie' ? __( 'Cookies in %s', 'complianz-gdpr' ) : __( 'Services in %s', 'complianz-gdpr' ); if ( isset( COMPLIANZ::$config->language_codes[ $language ] ) ) { $string = cmplz_sprintf( $string, COMPLIANZ::$config->language_codes[ $language ] ); } else { $string = cmplz_sprintf( $string, strtoupper( $language ) ); } return $string; } /** * Check if the api should be used * * @return bool */ public function use_cdb_api() { $use_api = cmplz_get_value( 'use_cdb_api' ) === 'yes'; return apply_filters( 'cmplz_use_cdb_api', $use_api ); } /** * Check if site uses Google Analytics * * @return bool * */ public function uses_google_analytics(): bool { $statistics = cmplz_get_value( 'compile_statistics' ); return $statistics === 'google-analytics'; } /** * Check if tm is used * * @return bool */ public function uses_google_tagmanager(): bool { $statistics = cmplz_get_value( 'compile_statistics' ); return $statistics === 'google-tag-manager'; } /** * Check if matomo is used * * @return bool */ public function uses_matomo() { $statistics = cmplz_get_value( 'compile_statistics' ); return $statistics === 'matomo'; } public function analytics_configured() { //if the user has chosen to configure it himself, we consider it to be configured. if ( cmplz_get_value( 'configuration_by_complianz' ) === 'no' ) { return true; } $UA_code = COMPLIANZ::$field->get_value( 'UA_code' ); return $UA_code != ''; } public function tagmanager_configured() { //if the user has chosen to configure it himself, we consider it to be configured. if ( cmplz_get_value( 'configuration_by_complianz' ) === 'no' ) { return true; } $GTM_code = COMPLIANZ::$field->get_value( 'GTM_code' ); return strlen( $GTM_code ) != 0; } public function matomo_configured() { //if the user has chosen to configure it himself, we consider it to be configured. if ( cmplz_get_value( 'configuration_by_complianz' ) === 'no' ) { return true; } $matomo_url = COMPLIANZ::$field->get_value( 'matomo_url' ); $site_id = COMPLIANZ::$field->get_value( 'matomo_site_id' ); return strlen( $matomo_url ) != 0 && strlen( $site_id ) !== 0; } /** * Check if the site needs a cookie banner. Pass a region to check cookie banner requirement for a specific region * * @@param string|bool $region * * @return bool * *@since 1.2 * */ public function site_needs_cookie_warning( $region = false ) { /** * default is false */ $needs_warning = false; if ( $region && ! cmplz_has_region( $region ) ) { /** * if we do not target this region, we don't show a banner for that region */ $needs_warning = false; } else if ( ( ! $region || $region === 'us' ) && cmplz_has_region( 'us' ) ) { /** * for the US, a cookie warning is always required * if a region other than US is passed, we check the region's requirements * if US is passed, we always need a banner */ $needs_warning = true; } else if ( $this->site_shares_data() ) { /** * site shares data */ $needs_warning = true; } else if ( $this->cookie_warning_required_stats() ) { /** * does the config of the statistics require a cookie warning? */ $needs_warning = true; } $url = $_SERVER['REQUEST_URI']; $excluded_posts_array = get_option( 'cmplz_excluded_posts_array', array() ); if ( ! empty( $excluded_posts_array ) ) { foreach ( $excluded_posts_array as $excluded_slug ) { if ( strpos( $url, $excluded_slug ) !== false ) { return false; } } } return apply_filters( 'cmplz_site_needs_cookiewarning', $needs_warning ); } /** * Check if the site needs a cookie banner considering statistics only * * @param $region bool|string * * @return bool * @since 1.0 * */ public function cookie_warning_required_stats( $region = false ) { if ( cmplz_get_value('consent_for_anonymous_stats')==='yes' ) { return apply_filters( 'cmplz_cookie_warning_required_stats', true ); } if ( $region ) { if ( COMPLIANZ::$config->regions[$region]['statistics_consent'] === 'no' ) { return apply_filters( 'cmplz_cookie_warning_required_stats', false ); } if ( COMPLIANZ::$config->regions[$region]['statistics_consent'] === 'always' ) { return apply_filters( 'cmplz_cookie_warning_required_stats', true ); } if ( COMPLIANZ::$config->regions[$region]['statistics_consent'] === 'when_not_anonymous' ) { if ( cmplz_get_value( 'eu_consent_regions' ) === 'yes' ) { return apply_filters( 'cmplz_cookie_warning_required_stats', true ); } if ( $this->statistics_privacy_friendly() ) { return apply_filters( 'cmplz_cookie_warning_required_stats', false ); } return apply_filters( 'cmplz_cookie_warning_required_stats', true ); } return apply_filters( 'cmplz_cookie_warning_required_stats', false ); } /** * if region is not provided. Generic check */ if ( $this->statistics_privacy_friendly() && $this->consent_required_for_anonymous_stats() ) { return apply_filters( 'cmplz_cookie_warning_required_stats', true ); } //if we're here, we don't need stats if they're set up privacy friendly return apply_filters( 'cmplz_cookie_warning_required_stats', ! $this->statistics_privacy_friendly() ); } /** * Check if consent is required for anonymous statistics * * @return bool */ public function consent_required_for_anonymous_stats() { $active_regions = COMPLIANZ::$config->active_regions(); if ( array_search('always', array_column( $active_regions, 'statistics_consent') ) ) { return true; } $when_not_anonymous = array_search('when_not_anonymous', array_column( $active_regions, 'statistics_consent') ); $uses_google = $this->uses_google_analytics() || $this->uses_google_tagmanager(); return $when_not_anonymous && $uses_google && cmplz_get_value( 'consent_for_anonymous_stats' ) === 'yes'; } /** * Add the selected statistics service as a service, and check for doubles */ public function maybe_add_statistics_service() { if ( !cmplz_user_can_manage() ) { return; } $selected_stat_service = cmplz_get_value( 'compile_statistics' ); if ( $selected_stat_service === 'google-analytics' || $selected_stat_service === 'matomo' || $selected_stat_service === 'google-tag-manager' ) { $service_name = COMPLIANZ::$cookie_admin->convert_slug_to_name( $selected_stat_service ); $service = new CMPLZ_SERVICE( $service_name ); if ( ! $service->ID ) { //Add new service $service = new CMPLZ_SERVICE(); $service->add( $service_name, COMPLIANZ::$cookie_admin->get_supported_languages(), false ); } } } /** * Determine if statistics are used in a privacy friendly way * * @return bool */ public function statistics_privacy_friendly() { $statistics = cmplz_get_value( 'compile_statistics' ); //no statistics at all, it's privacy friendly if ( $statistics === 'no' ) { return apply_filters('cmplz_statistics_privacy_friendly', true); } //not anonymous stats. if ( $statistics === 'yes' ) { return apply_filters('cmplz_statistics_privacy_friendly', false); } $tagmanager = $statistics === 'google-tag-manager'; $matomo = $statistics === 'matomo'; $google_analytics = $statistics === 'google-analytics'; $clicky = $statistics === 'clicky'; $accepted_google_data_processing_agreement = false; $ip_anonymous = false; $no_sharing = false; if ( $clicky ) { return apply_filters('cmplz_statistics_privacy_friendly', false); } if ( $matomo ) { return apply_filters('cmplz_statistics_privacy_friendly', false); } if ( $google_analytics || $tagmanager ) { $thirdparty = $google_analytics ? cmplz_get_value( 'compile_statistics_more_info' ) : cmplz_get_value( 'compile_statistics_more_info_tag_manager' ); $accepted_google_data_processing_agreement = ( isset( $thirdparty['accepted'] ) && ( $thirdparty['accepted'] == 1 ) ) ? true : false; $ip_anonymous = ( isset( $thirdparty['ip-addresses-blocked'] ) && ( $thirdparty['ip-addresses-blocked'] == 1 ) ) ? true : false; $no_sharing = ( isset( $thirdparty['no-sharing'] ) && ( $thirdparty['no-sharing'] == 1 ) ) ? true : false; } if ( ( $tagmanager || $google_analytics ) && ( ! $accepted_google_data_processing_agreement || ! $ip_anonymous || ! $no_sharing ) ) { return apply_filters('cmplz_statistics_privacy_friendly', false); } //everything set up privacy friendly! return apply_filters('cmplz_statistics_privacy_friendly', true); } /** * Check if ip is always blocked * @return bool */ public function google_analytics_always_block_ip() { $statistics = cmplz_get_value( 'compile_statistics' ); $google_analytics = $statistics === 'google-analytics'; if ( $google_analytics ) { $thirdparty = cmplz_get_value( 'compile_statistics_more_info' ); $always_block_ip = isset( $thirdparty['ip-addresses-blocked'] ) && ( $thirdparty['ip-addresses-blocked'] == 1 ); if ( $always_block_ip ) { return true; } } return false; } /** * Check if this website shares data with third parties, used for recommendations, cookiebanner check and canada policies * * @return bool */ public function site_shares_data() { //TCF always shares data if ( cmplz_tcf_active() ) { return true; } if ( $this->uses_google_tagmanager() ) { return true; } if ( cmplz_uses_marketing_cookies() ) { return true; } /** * Script Center */ $blocked_scripts = get_transient('cmplz_blocked_scripts'); $blocked_scripts = $blocked_scripts ?: COMPLIANZ::$cookie_blocker->blocked_scripts(); $thirdparty_scripts = is_array($blocked_scripts) && count( $blocked_scripts ) > 0; $ad_cookies = ( cmplz_get_value( 'uses_ad_cookies' ) === 'yes' ) ? true : false; $social_media = ( cmplz_get_value( 'uses_social_media' ) === 'yes' ) ? true : false; $thirdparty_services = ( cmplz_get_value( 'uses_thirdparty_services' ) === 'yes' ) ? true : false; if ( $thirdparty_scripts || $ad_cookies || $social_media || $thirdparty_services ) { return true; } //get all used cookies $args = array( 'isTranslationFrom' => false, 'ignored' => false, ); if ( !$this->statistics_privacy_friendly() ) { return true; } $cookies = $this->get_cookies( $args ); if ( empty( $cookies ) ) { return false; } foreach ( $cookies as $cookie ) { $service = new CMPLZ_SERVICE( $cookie->serviceID ); if ( $service->secondParty || $service->thirdParty ) { return true; } } return false; } /** * Check if non functional cookies are used on this site * @return bool */ public function uses_non_functional_cookies() { if ( $this->uses_google_tagmanager() ) { return true; } //get all used cookies $args = array( 'isTranslationFrom' => false, 'ignored' => false, ); $cookies = $this->get_cookies( $args ); if ( empty( $cookies ) ) { return false; } foreach ( $cookies as $cookie ) { $cookie_service = !empty($cookie->service) ? sanitize_title( $cookie->service ) : false; $has_optinstats = cmplz_uses_consenttype( 'optinstats' ); if ( $cookie_service === 'google-analytics' || $cookie_service === 'matomo' ) { if ( $has_optinstats ) { return true; } if ( ! $this->statistics_privacy_friendly() ) { return true; } } if ( strpos( strtolower( $cookie->purpose ), 'functional' ) === false ) { return true; } } return false; } public function uses_only_functional_cookies() { return ! $this->uses_non_functional_cookies(); } /** * Get progress of the scan in percentage * * @return float */ public function get_progress_count() { $done = $this->get_processed_pages_list(); $total = $this->get_pages_list_single_run(); $progress = 100 * ( count( $done ) / count( $total ) ); if ( $progress > 100 ) { $progress = 100; } return $progress; } /** * Check if this website uses cookies from a specific service * * @param $service * * @return bool */ public function site_uses_cookie_from_service( $service ) { $args = array( 'isTranslationFrom' => false, 'ignored' => false, ); $cookies = $this->get_cookies( $args ); if ( ! empty( $cookies ) ) { foreach ( $cookies as $cookie_name => $label ) { //get identifier for this cookie name $cookie = new CMPLZ_COOKIE( $cookie_name ); $cookie_service = sanitize_title( $cookie->service ); if ( $service == $cookie_service ) { return true; } } } return false; } } } //class closure