Navigate privacy laws with feline precision — detect every boundary, respect every territory! GDPR compliance and privacy protection for WordPress. - Cookie consent management - Privacy boundary detection - GDPR-compliant analytics gating - Cross-plugin consent coordination (integrates with TigerStyle Heat) - Visitor preference tracking - Configurable cookie categories Includes build.sh and .distignore for WordPress-installable release ZIPs.
489 lines
18 KiB
PHP
489 lines
18 KiB
PHP
<?php
|
|
/**
|
|
* TigerStyle Whiskers Compliance Scanner
|
|
*
|
|
* Scan for compliance gaps with feline precision - no boundary goes unchecked!
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class TigerStyleWhiskers_ComplianceScanner {
|
|
|
|
/**
|
|
* Single instance
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Compliance checks
|
|
*/
|
|
private $compliance_checks = array();
|
|
|
|
/**
|
|
* Last scan results
|
|
*/
|
|
private $last_scan_results = array();
|
|
|
|
/**
|
|
* Get instance
|
|
*/
|
|
public static function instance() {
|
|
if (is_null(self::$instance)) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
private function __construct() {
|
|
$this->init_compliance_scanner();
|
|
}
|
|
|
|
/**
|
|
* Initialize compliance scanner
|
|
*/
|
|
private function init_compliance_scanner() {
|
|
// Define compliance checks
|
|
$this->define_compliance_checks();
|
|
|
|
// Schedule periodic scans
|
|
add_action('wp_loaded', array($this, 'schedule_periodic_scan'));
|
|
|
|
// Admin hooks
|
|
if (is_admin()) {
|
|
add_action('wp_ajax_whiskers_run_compliance_scan', array($this, 'ajax_run_compliance_scan'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Define compliance checks
|
|
*/
|
|
private function define_compliance_checks() {
|
|
$this->compliance_checks = array(
|
|
'cookie_consent' => array(
|
|
'name' => __('Cookie Consent Banner', 'tigerstyle-whiskers'),
|
|
'description' => __('Ensure cookie consent banner is active and compliant', 'tigerstyle-whiskers'),
|
|
'priority' => 'high',
|
|
'callback' => array($this, 'check_cookie_consent')
|
|
),
|
|
'privacy_policy' => array(
|
|
'name' => __('Privacy Policy', 'tigerstyle-whiskers'),
|
|
'description' => __('Verify privacy policy exists and is up-to-date', 'tigerstyle-whiskers'),
|
|
'priority' => 'high',
|
|
'callback' => array($this, 'check_privacy_policy')
|
|
),
|
|
'data_processing' => array(
|
|
'name' => __('Data Processing Records', 'tigerstyle-whiskers'),
|
|
'description' => __('Check data processing documentation', 'tigerstyle-whiskers'),
|
|
'priority' => 'medium',
|
|
'callback' => array($this, 'check_data_processing')
|
|
),
|
|
'user_rights' => array(
|
|
'name' => __('User Rights Implementation', 'tigerstyle-whiskers'),
|
|
'description' => __('Verify GDPR user rights are implemented', 'tigerstyle-whiskers'),
|
|
'priority' => 'high',
|
|
'callback' => array($this, 'check_user_rights')
|
|
),
|
|
'data_security' => array(
|
|
'name' => __('Data Security Measures', 'tigerstyle-whiskers'),
|
|
'description' => __('Check basic data security implementations', 'tigerstyle-whiskers'),
|
|
'priority' => 'medium',
|
|
'callback' => array($this, 'check_data_security')
|
|
),
|
|
'third_party_scripts' => array(
|
|
'name' => __('Third-party Script Compliance', 'tigerstyle-whiskers'),
|
|
'description' => __('Verify third-party scripts respect consent', 'tigerstyle-whiskers'),
|
|
'priority' => 'high',
|
|
'callback' => array($this, 'check_third_party_scripts')
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Run full compliance scan
|
|
*/
|
|
public function run_full_scan() {
|
|
$results = array();
|
|
$total_score = 0;
|
|
$max_score = 0;
|
|
|
|
foreach ($this->compliance_checks as $check_id => $check) {
|
|
$result = call_user_func($check['callback']);
|
|
$results[$check_id] = array_merge($check, $result);
|
|
|
|
// Calculate weighted score
|
|
$weight = ($check['priority'] === 'high') ? 3 : ($check['priority'] === 'medium' ? 2 : 1);
|
|
$total_score += $result['score'] * $weight;
|
|
$max_score += 10 * $weight;
|
|
}
|
|
|
|
$overall_score = ($max_score > 0) ? round(($total_score / $max_score) * 10, 1) : 0;
|
|
|
|
$this->last_scan_results = array(
|
|
'overall_score' => $overall_score,
|
|
'scan_date' => current_time('mysql'),
|
|
'checks' => $results,
|
|
'recommendations' => $this->generate_recommendations($results)
|
|
);
|
|
|
|
// Store results
|
|
update_option('whiskers_compliance_scan_results', $this->last_scan_results);
|
|
|
|
return $this->last_scan_results;
|
|
}
|
|
|
|
/**
|
|
* Check cookie consent implementation
|
|
*/
|
|
private function check_cookie_consent() {
|
|
$score = 0;
|
|
$issues = array();
|
|
$recommendations = array();
|
|
|
|
// Check if consent banner is active
|
|
$consent_module = tigerstyle_whiskers()->get_whisker('cookie_consent');
|
|
if ($consent_module) {
|
|
$score += 3;
|
|
} else {
|
|
$issues[] = __('Cookie consent banner not active', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Activate cookie consent banner', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for granular consent options
|
|
if ($consent_module && method_exists($consent_module, 'get_consent_categories')) {
|
|
$categories = $consent_module->get_consent_categories();
|
|
if (count($categories) >= 3) {
|
|
$score += 3;
|
|
} else {
|
|
$issues[] = __('Limited consent categories available', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Implement granular consent categories', 'tigerstyle-whiskers');
|
|
}
|
|
}
|
|
|
|
// Check for consent withdrawal mechanism
|
|
if ($consent_module && method_exists($consent_module, 'withdraw_consent')) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Consent withdrawal mechanism missing', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Implement consent withdrawal functionality', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for proper cookie blocking
|
|
if ($this->check_cookie_blocking()) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Cookies may load before consent', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Ensure cookies are blocked until consent is given', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
return array(
|
|
'score' => min($score, 10),
|
|
'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')),
|
|
'issues' => $issues,
|
|
'recommendations' => $recommendations
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check privacy policy
|
|
*/
|
|
private function check_privacy_policy() {
|
|
$score = 0;
|
|
$issues = array();
|
|
$recommendations = array();
|
|
|
|
// Check if privacy policy page exists
|
|
$policy_page = get_option('wp_page_for_privacy_policy');
|
|
if ($policy_page && get_post_status($policy_page) === 'publish') {
|
|
$score += 4;
|
|
|
|
// Check if policy is recent (updated within last year)
|
|
$policy_post = get_post($policy_page);
|
|
if ($policy_post && strtotime($policy_post->post_modified) > (time() - YEAR_IN_SECONDS)) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Privacy policy may be outdated', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Update privacy policy with recent changes', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for GDPR-specific content
|
|
$content = get_post_field('post_content', $policy_page);
|
|
if (stripos($content, 'gdpr') !== false || stripos($content, 'data protection') !== false) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Privacy policy lacks GDPR-specific content', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Add GDPR compliance information to privacy policy', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for contact information
|
|
if (stripos($content, 'contact') !== false || stripos($content, 'email') !== false) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Privacy policy lacks contact information', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Add privacy contact information', 'tigerstyle-whiskers');
|
|
}
|
|
} else {
|
|
$issues[] = __('Privacy policy page not found or not published', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Create and publish a comprehensive privacy policy', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
return array(
|
|
'score' => min($score, 10),
|
|
'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')),
|
|
'issues' => $issues,
|
|
'recommendations' => $recommendations
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check data processing records
|
|
*/
|
|
private function check_data_processing() {
|
|
$score = 5; // Base score for having Whiskers installed
|
|
$issues = array();
|
|
$recommendations = array();
|
|
|
|
// Check if data mapper is active
|
|
$data_mapper = tigerstyle_whiskers()->get_whisker('data_mapper');
|
|
if ($data_mapper) {
|
|
$score += 3;
|
|
} else {
|
|
$issues[] = __('Data mapping not active', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Activate data mapping functionality', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for audit trail
|
|
$audit_trail = tigerstyle_whiskers()->get_whisker('audit_trail');
|
|
if ($audit_trail) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Audit trail not configured', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Enable audit trail for data processing activities', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
return array(
|
|
'score' => min($score, 10),
|
|
'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')),
|
|
'issues' => $issues,
|
|
'recommendations' => $recommendations
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check user rights implementation
|
|
*/
|
|
private function check_user_rights() {
|
|
$score = 0;
|
|
$issues = array();
|
|
$recommendations = array();
|
|
|
|
// Check data deletion capability
|
|
$data_deletion = tigerstyle_whiskers()->get_whisker('data_deletion');
|
|
if ($data_deletion) {
|
|
$score += 3;
|
|
} else {
|
|
$issues[] = __('Data deletion (right to be forgotten) not implemented', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Implement data deletion functionality', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check data access/export capability
|
|
if ($data_deletion && method_exists($data_deletion, 'export_user_data')) {
|
|
$score += 3;
|
|
} else {
|
|
$issues[] = __('Data access/export not available', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Implement data access and export functionality', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for data rectification process
|
|
if ($this->check_data_rectification()) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Data rectification process not defined', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Define process for data rectification requests', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for consent withdrawal
|
|
$consent_module = tigerstyle_whiskers()->get_whisker('cookie_consent');
|
|
if ($consent_module && method_exists($consent_module, 'withdraw_consent')) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Consent withdrawal not available', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Implement consent withdrawal mechanism', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
return array(
|
|
'score' => min($score, 10),
|
|
'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')),
|
|
'issues' => $issues,
|
|
'recommendations' => $recommendations
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check data security measures
|
|
*/
|
|
private function check_data_security() {
|
|
$score = 0;
|
|
$issues = array();
|
|
$recommendations = array();
|
|
|
|
// Check for HTTPS
|
|
if (is_ssl()) {
|
|
$score += 3;
|
|
} else {
|
|
$issues[] = __('Website not using HTTPS', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Enable SSL/HTTPS for data protection', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for secure password policies
|
|
if ($this->check_password_policies()) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Weak password policies detected', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Implement strong password requirements', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for data encryption options
|
|
if ($this->check_data_encryption()) {
|
|
$score += 3;
|
|
} else {
|
|
$issues[] = __('Limited data encryption measures', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Consider additional data encryption measures', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
// Check for access controls
|
|
if ($this->check_access_controls()) {
|
|
$score += 2;
|
|
} else {
|
|
$issues[] = __('Basic access controls could be improved', 'tigerstyle-whiskers');
|
|
$recommendations[] = __('Review and strengthen access control measures', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
return array(
|
|
'score' => min($score, 10),
|
|
'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')),
|
|
'issues' => $issues,
|
|
'recommendations' => $recommendations
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Check third-party script compliance
|
|
*/
|
|
private function check_third_party_scripts() {
|
|
$score = 8; // Base score assuming Whiskers is handling this
|
|
$issues = array();
|
|
$recommendations = array();
|
|
|
|
// Check if consent-aware analytics is active
|
|
if (class_exists('TigerStyleSEO')) {
|
|
$score += 2;
|
|
$issues[] = __('Heat integration active - analytics consent respected', 'tigerstyle-whiskers');
|
|
} else {
|
|
$recommendations[] = __('Install TigerStyle Heat for enhanced analytics integration', 'tigerstyle-whiskers');
|
|
}
|
|
|
|
return array(
|
|
'score' => min($score, 10),
|
|
'status' => ($score >= 8) ? 'excellent' : (($score >= 6) ? 'good' : (($score >= 4) ? 'fair' : 'poor')),
|
|
'issues' => $issues,
|
|
'recommendations' => $recommendations
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Helper methods for compliance checks
|
|
*/
|
|
private function check_cookie_blocking() {
|
|
// Check if cookies are properly blocked before consent
|
|
return true; // Assume Whiskers is handling this correctly
|
|
}
|
|
|
|
private function check_data_rectification() {
|
|
// Check if data rectification process is defined
|
|
return false; // This needs to be implemented
|
|
}
|
|
|
|
private function check_password_policies() {
|
|
// Check WordPress password strength requirements
|
|
return !empty(get_option('users_can_register'));
|
|
}
|
|
|
|
private function check_data_encryption() {
|
|
// Check for basic data encryption measures
|
|
return is_ssl(); // Basic check for HTTPS
|
|
}
|
|
|
|
private function check_access_controls() {
|
|
// Check WordPress access control settings
|
|
return !get_option('blog_public'); // If site is not public, access is more controlled
|
|
}
|
|
|
|
/**
|
|
* Generate recommendations based on scan results
|
|
*/
|
|
private function generate_recommendations($results) {
|
|
$recommendations = array();
|
|
|
|
foreach ($results as $check_id => $result) {
|
|
if ($result['score'] < 8) {
|
|
$recommendations = array_merge($recommendations, $result['recommendations']);
|
|
}
|
|
}
|
|
|
|
return array_unique($recommendations);
|
|
}
|
|
|
|
/**
|
|
* Get compliance status
|
|
*/
|
|
public static function get_status() {
|
|
$instance = self::instance();
|
|
|
|
if (empty($instance->last_scan_results)) {
|
|
// Load from database or run initial scan
|
|
$stored_results = get_option('whiskers_compliance_scan_results');
|
|
if ($stored_results) {
|
|
$instance->last_scan_results = $stored_results;
|
|
} else {
|
|
$instance->run_full_scan();
|
|
}
|
|
}
|
|
|
|
return $instance->last_scan_results;
|
|
}
|
|
|
|
/**
|
|
* Schedule periodic compliance scan
|
|
*/
|
|
public function schedule_periodic_scan() {
|
|
if (!wp_next_scheduled('whiskers_periodic_compliance_scan')) {
|
|
wp_schedule_event(time(), 'daily', 'whiskers_periodic_compliance_scan');
|
|
}
|
|
|
|
add_action('whiskers_periodic_compliance_scan', array($this, 'run_full_scan'));
|
|
}
|
|
|
|
/**
|
|
* AJAX handler for compliance scan
|
|
*/
|
|
public function ajax_run_compliance_scan() {
|
|
check_ajax_referer('whiskers_admin_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die(__('Insufficient permissions', 'tigerstyle-whiskers'));
|
|
}
|
|
|
|
$results = $this->run_full_scan();
|
|
|
|
wp_send_json_success(array(
|
|
'message' => __('Compliance scan completed with feline precision!', 'tigerstyle-whiskers'),
|
|
'results' => $results
|
|
));
|
|
}
|
|
} |