validate_download_token($certificate_token); if (!$certificate_data) { wp_die(__('Invalid or expired certificate download link.', 'hvac-community-events')); } // Get file path $file_path = $this->get_certificate_file_path($certificate_data); if (!$file_path || !file_exists($file_path)) { wp_die(__('Certificate file not found.', 'hvac-community-events')); } // Serve the file $this->serve_certificate_file($file_path, $certificate_data); exit; } /** * Parse certificate requests directly without relying on rewrite rules. * This is a fallback method that works even if rewrite rules fail. */ public function parse_certificate_request($wp) { // Only process if we haven't already handled via template_redirect if (did_action('template_redirect')) { return; } $request_uri = $_SERVER['REQUEST_URI']; // Only match exact certificate download URLs - be very specific if (preg_match('#^/hvac-certificate/([a-zA-Z0-9]{32})/?$#', $request_uri, $matches)) { $certificate_token = $matches[1]; // Validate the token exists (don't delete it yet - let the normal handler do that) $certificate_data = get_transient('hvac_certificate_token_' . $certificate_token); if (!$certificate_data) { // Return 404 instead of wp_die to avoid interfering with other pages status_header(404); return; } // If we have valid certificate data, let the normal template_redirect handler take over // Set the query var so the normal handler can pick it up set_query_var('certificate_token', $certificate_token); return; } } /** * Validate a certificate download token. * * @param string $token The token to validate. * * @return array|false Certificate data if valid, false otherwise. */ protected function validate_download_token($token) { // Check if token exists in transients $certificate_data = get_transient('hvac_certificate_token_' . $token); if (!$certificate_data) { return false; } // Delete the transient to prevent reuse delete_transient('hvac_certificate_token_' . $token); return $certificate_data; } /** * Get the full file path for a certificate. * * @param array $certificate_data Certificate data. * * @return string|false Full file path or false if not found. */ protected function get_certificate_file_path($certificate_data) { if (empty($certificate_data['file_path'])) { return false; } $upload_dir = wp_upload_dir(); $file_path = $upload_dir['basedir'] . '/' . $certificate_data['file_path']; if (file_exists($file_path)) { return $file_path; } return false; } /** * Serve a certificate file for download. * * @param string $file_path Full path to certificate file. * @param array $certificate_data Certificate data. */ protected function serve_certificate_file($file_path, $certificate_data) { // Get file information $file_name = basename($file_path); $file_size = filesize($file_path); $file_ext = pathinfo($file_path, PATHINFO_EXTENSION); // Set download filename $event_name = sanitize_title($certificate_data['event_name'] ?? 'event'); $attendee_name = sanitize_title($certificate_data['attendee_name'] ?? 'attendee'); $download_filename = "certificate-{$event_name}-{$attendee_name}.{$file_ext}"; // Send headers nocache_headers(); header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="' . $download_filename . '"'); header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . $file_size); // Disable output buffering if (ob_get_level()) { ob_end_clean(); } // Output the file readfile($file_path); } /** * Generate a secure download token for a certificate. * * @param int $certificate_id The certificate ID. * @param array $certificate_data Additional certificate data. * @param int $expiry Token expiry time in seconds (default 1 hour). * * @return string|false The download URL or false on failure. */ public function generate_download_token($certificate_id, $certificate_data, $expiry = 3600) { if (!$certificate_id || empty($certificate_data['file_path'])) { return false; } // Generate a unique token $token = wp_generate_password(32, false); // Store in transient set_transient('hvac_certificate_token_' . $token, $certificate_data, $expiry); // Generate URL return home_url('hvac-certificate/' . $token); } /** * Create a secure storage directory for certificates. * * @param string $dir_path The directory path to secure. * * @return bool True if successful, false otherwise. */ public function create_secure_directory($dir_path) { // Check if directory exists if (!file_exists($dir_path)) { // Create directory if (!wp_mkdir_p($dir_path)) { return false; } } // Create/update .htaccess file $htaccess_content = "# Prevent direct access to files\n"; $htaccess_content .= "\n"; $htaccess_content .= " Order Allow,Deny\n"; $htaccess_content .= " Deny from all\n"; $htaccess_content .= "\n"; $htaccess_content .= "# Prevent directory listing\n"; $htaccess_content .= "Options -Indexes\n"; $htaccess_file = $dir_path . '/.htaccess'; if (!@file_put_contents($htaccess_file, $htaccess_content)) { return false; } // Create empty index.php $index_content = "init_secure_download(); // Flush the rules flush_rewrite_rules(); // Log the action if (class_exists('HVAC_Logger')) { HVAC_Logger::info('Rewrite rules flushed manually via admin parameter', 'Certificate Security'); } // Redirect to remove the parameter wp_redirect(remove_query_arg('hvac_flush_rewrite_rules')); exit; } } }