WP_REST_Server::CREATABLE, 'callback' => array($this, 'initiate_scan'), 'permission_callback' => array($this, 'edit_permission'), )); // Register the scan status endpoint register_rest_route($namespace, '/scan/status', array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array($this, 'check_scan_status'), 'permission_callback' => array($this, 'edit_permission'), )); } /** * Permission check for the scanner routes. * The cookie scanner is only used from the notification builder, * which requires the edit_notificationx capability. * * @return bool */ public function edit_permission() { return current_user_can('edit_notificationx'); } /** * Initiates a scan process for the provided URL. * * Validates the URL parameter and triggers the scan if it's valid. * Responds with the scan status. * * @param WP_REST_Request $request The REST request object containing the URL. * * @return WP_REST_Response The response indicating the status of the scan initiation. */ public function initiate_scan(WP_REST_Request $request) { $url = $request->get_param('url'); // Check if the URL parameter is provided if (empty($url)) { return new WP_REST_Response(['error' => 'URL parameter is required'], 200); } // Trigger the scan process (implement this function as needed) $this->trigger_scan($url); return new WP_REST_Response(['status' => 'Scan started.'], 200); } /** * Retrieves the current status of a scan based on the provided scan ID. * * Queries the status from an external service and returns the results. * If the scan is completed, it processes the result and inserts cookie and stats entries into the database. * * @param WP_REST_Request $request The REST request object containing the scan ID. * * @return WP_REST_Response The response with the scan status or an error message. */ public function check_scan_status(WP_REST_Request $request) { $scanId = $request->get_param('scan_id'); // Retrieve the scan status from the database (implement this function as needed) $status = $this->get_scan_status($scanId); // Handle invalid scan ID if ($status === null && empty( $scanId )) { $data = [ 'status' => 'failed', 'message' => __('Invalid scan ID','notificationx') ]; return new WP_REST_Response(['data' => $data ], 404); } // Process the scan result if the status is 'completed' if ( is_array($status) && !empty($status['status']) && $status['status'] === 'completed') { // Update scan count to the options $pre_count = get_option('nx_scan_count', 0); update_option('nx_scan_count', $pre_count + 1); update_option('nx_scan_date', Helper::nx_get_current_datetime() ); $cookies = $status['result']; // Extract scanned cookies $stats = $status['stats']; // Extract scan statistics // Use the helper function to categorize cookies and get the category count $cookieData = $this->categorizeCookiesAndCount($cookies); $categoryCount = $cookieData['category_count']; $categorized = $cookieData['categorized']; $data = [ 'last_scan_date' => Helper::nx_get_current_datetime(), 'status' => 'completed', 'stats' => $stats, 'cookies' => $cookies, 'category_count' => $categoryCount, 'categorized' => $categorized ]; return new WP_REST_Response(['data' => $data], 200); } return new WP_REST_Response(['data' => $status], 200); } /** * Triggers a scan process by making an HTTP GET request to an external API. * * Sends the provided URL to the external scan API and handles the response. * * @param string $url The URL to be scanned. * * @return WP_REST_Response The response containing the result of the scan. */ private function trigger_scan($url) { // API endpoint that will process the scan if( self::$is_pro ) { $apiEndpoint = self::$_apiBase . "?nxpro=active&url=" . urlencode($url); }else{ $apiEndpoint = self::$_apiBase . "?url=" . urlencode($url); } // Make an HTTP GET request $response = wp_remote_get($apiEndpoint, [ 'timeout' => 200, // Set timeout (adjust as needed) 'sslverify' => false, // Bypass SSL verification temporarily (for local dev) ]); // Check for errors in the response if (is_wp_error($response)) { return new WP_REST_Response(['error' => $response->get_error_message()], 500); } // Decode response body $responseBody = json_decode(wp_remote_retrieve_body($response), true); return wp_send_json_success($responseBody); } /** * Retrieves the current status of a scan from the external scan API using the scan ID. * * Makes an HTTP GET request to the scan API to fetch the status of the scan. * * @param string $scanId The scan ID to check the status of. * * @return array The scan status data from the external API. */ private function get_scan_status($scanId) { // API endpoint to check the scan status $apiEndpoint = self::$_apiBase . "/status.php?scan_id=" . urlencode($scanId); // Make an HTTP GET request $response = wp_remote_get($apiEndpoint, [ 'timeout' => 200, // Set timeout (adjust as needed) 'sslverify' => false, // Bypass SSL verification temporarily (for local dev) ]); // Check for errors in the response if (is_wp_error($response)) { return new WP_REST_Response(['error' => $response->get_error_message()], 500); } // Decode response body $responseBody = json_decode(wp_remote_retrieve_body($response), true); return $responseBody; } // Helper function to categorize cookies and calculate category count public function categorizeCookiesAndCount($cookies) { // Define cookie categories $cookieCategoryPrefix = [ 'necessary' => ['PHPSESSID', 'wordpress_logged_in', 'wp-settings', 'wp-settings-time', 'wpEmojiSettingsSupports', 'cookieyes-consent', 'elementor', 'csrftoken', 'auth', 'session', 'secure', 'cart', 'checkout', 'wp_woocommerce'], 'functional' => ['lang', 'preferences', 'remember_me', 'theme', 'consent', 'locale', 'user_settings', 'cookie_preference'], 'analytics' => ['_ga', '_gid', '_gat', 'fbp', 'utm', 'amplitude', 'mixpanel', 'hotjar', 'segment', 'ahoy', 'kissmetrics', 'analytics', 'visitor_id', 'sbjs_udata', 'sbjs_current', 'sbjs_first', 'sbjs_first_add', 'sbjs_current_add'], 'performance' => ['_hj', 'cf_use_ob', 'cf_clearance', 'AWSALB', 'load_balancer', 'page_speed', 'cdn_cache', 'pingdom', 'new_relic'], 'advertisement' => ['ads', '_fbp', '_gcl', '_dc_gtm', 'doubleclick', 'IDE', 'adroll', 'criteo', 'twitter_ads', 'bing_ads', 'remarketing', 'test_cookie'], ]; // Initialize category counts $categorized = [ 'necessary' => 0, 'functional' => 0, 'analytics' => 0, 'performance' => 0, 'advertisement' => 0, ]; // Categorize cookies based on partial matching of cookie names (prefixes) if (!empty($cookies) && is_array($cookies)) { foreach ($cookies as $cookie) { foreach ($cookieCategoryPrefix as $category => $cookieNames) { foreach ($cookieNames as $cookieName) { if (isset($cookie['name']) && strpos($cookie['name'], $cookieName) !== false) { // Check if cookie contains the prefix $categorized[$category]++; break; // No need to check other prefixes for this cookie } } } } } // Calculate the category count (only categories with count > 0) $categoryCount = count(array_filter($categorized, function($count) { return $count > 0; })); return [ 'category_count' => $categoryCount, 'categorized' => $categorized ]; } } ?>