diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-community-events.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-community-events.php index 5219d275..6db32114 100644 --- a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-community-events.php +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/hvac-community-events.php @@ -466,6 +466,25 @@ function hvac_community_events_init() { } add_action('plugins_loaded', 'hvac_community_events_init'); +// Initialize certificate URL handler very early to catch URLs before 404 +function hvac_init_certificate_url_handler() { + // Load the certificate URL handler class if not already loaded + if (!class_exists('HVAC_Certificate_URL_Handler')) { + $handler_file = HVAC_CE_PLUGIN_DIR . 'includes/certificates/class-certificate-url-handler.php'; + if (file_exists($handler_file)) { + require_once $handler_file; + } + } + + // Initialize the handler if class exists + if (class_exists('HVAC_Certificate_URL_Handler')) { + HVAC_Certificate_URL_Handler::instance(); + } +} +// Hook very early - before WordPress decides it's a 404 +add_action('muplugins_loaded', 'hvac_init_certificate_url_handler', 1); +add_action('plugins_loaded', 'hvac_init_certificate_url_handler', 1); + /** * Include custom template for single event summary page. diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-url-handler.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-url-handler.php new file mode 100644 index 00000000..13f3b9d2 --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/certificates/class-certificate-url-handler.php @@ -0,0 +1,213 @@ +handle_certificate_download($token); + exit; // Stop WordPress from processing further + } + } + + /** + * Handle certificate download + */ + protected function handle_certificate_download($token) { + // Validate the token + $certificate_data = $this->validate_download_token($token); + + if (!$certificate_data) { + if (class_exists('HVAC_Logger')) { + HVAC_Logger::error("Invalid or expired certificate token: $token", 'Certificates'); + } + wp_die(__('Invalid or expired certificate download link.', 'hvac-community-events'), 'Certificate Error', array('response' => 404)); + } + + // Get file path + $file_path = $this->get_certificate_file_path($certificate_data); + + if (!$file_path || !file_exists($file_path)) { + if (class_exists('HVAC_Logger')) { + HVAC_Logger::error("Certificate file not found for token: $token", 'Certificates'); + } + wp_die(__('Certificate file not found.', 'hvac-community-events'), 'Certificate Error', array('response' => 404)); + } + + // Log successful access + if (class_exists('HVAC_Logger')) { + HVAC_Logger::info("Serving certificate file: $file_path", 'Certificates'); + } + + // Serve the file + $this->serve_certificate_file($file_path, $certificate_data); + } + + /** + * Validate a certificate download token. + */ + 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. + */ + 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. + */ + 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); + } + + /** + * Parse request fallback method + */ + public function parse_certificate_request($wp) { + // Get the request URI + $request_uri = $_SERVER['REQUEST_URI']; + $parsed_url = parse_url($request_uri); + $path = $parsed_url['path'] ?? ''; + + // Remove any trailing slash for consistency + $path = rtrim($path, '/'); + + // Check if this is a certificate URL + if (preg_match('#^/hvac-certificate/([a-zA-Z0-9]{32})$#', $path, $matches)) { + $token = $matches[1]; + + // Log the request + if (class_exists('HVAC_Logger')) { + HVAC_Logger::info("Certificate URL detected via parse_request - Token: $token", 'Certificates'); + } + + // Handle the certificate download + $this->handle_certificate_download($token); + exit; // Stop WordPress from processing further + } + } +} \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php index 6160c5a4..89b73572 100644 --- a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php @@ -64,6 +64,7 @@ class HVAC_Community_Events { 'certificates/class-certificate-settings.php', // Certificate settings 'certificates/class-certificate-template.php', // Certificate template 'certificates/class-certificate-security.php', // Certificate security + 'certificates/class-certificate-url-handler.php', // Certificate URL handler 'certificates/class-certificate-ajax-handler.php', // Certificate AJAX handling 'certificates/class-certificate-fix.php', // Certificate diagnostic/fix tool 'community/class-email-debug.php', // Email debugging tools @@ -209,6 +210,11 @@ class HVAC_Community_Events { HVAC_Certificate_Security::instance(); } + // Initialize certificate URL handler + if (class_exists('HVAC_Certificate_URL_Handler')) { + HVAC_Certificate_URL_Handler::instance(); + } + // Add manual flush rewrite rules for admins (debugging) if (is_admin() && current_user_can('manage_options') && isset($_GET['hvac_flush_rewrite']) && $_GET['hvac_flush_rewrite'] === '1') { flush_rewrite_rules(); diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/test-certificate-url.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/test-certificate-url.php new file mode 100644 index 00000000..34e757f2 --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/test-certificate-url.php @@ -0,0 +1,167 @@ +Certificate URL System Test"; +echo "
";
+
+// 1. Check if URL handler is loaded
+echo "=== URL HANDLER CHECK ===\n";
+if (class_exists('HVAC_Certificate_URL_Handler')) {
+    echo "✅ HVAC_Certificate_URL_Handler class exists\n";
+    $handler = HVAC_Certificate_URL_Handler::instance();
+    echo "✅ URL Handler instance created\n";
+} else {
+    echo "❌ HVAC_Certificate_URL_Handler class NOT found!\n";
+}
+
+// 2. Check if security class is loaded
+echo "\n=== SECURITY CLASS CHECK ===\n";
+if (class_exists('HVAC_Certificate_Security')) {
+    echo "✅ HVAC_Certificate_Security class exists\n";
+    $security = HVAC_Certificate_Security::instance();
+    echo "✅ Security instance created\n";
+} else {
+    echo "❌ HVAC_Certificate_Security class NOT found!\n";
+}
+
+// 3. Create a test token
+echo "\n=== TOKEN GENERATION TEST ===\n";
+if (isset($security)) {
+    $test_data = array(
+        'file_path' => 'test/certificate.pdf',
+        'event_name' => 'Test Event',
+        'attendee_name' => 'Test Attendee',
+        'certificate_id' => 999
+    );
+    
+    $test_url = $security->generate_download_token(999, $test_data, 300); // 5 minute expiry
+    echo "Generated test URL: $test_url\n";
+    
+    // Extract token
+    if (preg_match('/hvac-certificate\/([^\/]+)/', $test_url, $matches)) {
+        $token = $matches[1];
+        echo "Token: $token\n";
+        
+        // Verify token exists in database
+        $transient = get_transient('hvac_certificate_token_' . $token);
+        if ($transient) {
+            echo "✅ Token transient exists\n";
+            echo "Token data:\n";
+            print_r($transient);
+            
+            // Test direct access URL
+            echo "\n=== DIRECT ACCESS TEST ===\n";
+            echo "Test this URL in your browser: $test_url\n";
+            echo "(Should show 'Certificate file not found' since we're using a test file path)\n";
+        } else {
+            echo "❌ Token transient NOT found!\n";
+        }
+    }
+}
+
+// 4. Check hooks
+echo "\n=== HOOK REGISTRATION CHECK ===\n";
+$init_callbacks = $GLOBALS['wp_filter']['init'] ?? array();
+$found_url_handler = false;
+
+foreach ($init_callbacks as $priority => $callbacks) {
+    foreach ($callbacks as $callback) {
+        if (is_array($callback['function']) && 
+            is_object($callback['function'][0]) && 
+            get_class($callback['function'][0]) === 'HVAC_Certificate_URL_Handler') {
+            $found_url_handler = true;
+            echo "✅ URL Handler init hook found at priority: $priority\n";
+        }
+    }
+}
+
+if (!$found_url_handler) {
+    echo "❌ URL Handler init hook NOT found!\n";
+}
+
+// 5. List recent certificate tokens
+echo "\n=== RECENT CERTIFICATE TOKENS ===\n";
+global $wpdb;
+$recent_tokens = $wpdb->get_results(
+    "SELECT option_name, option_value 
+     FROM {$wpdb->options} 
+     WHERE option_name LIKE '_transient_hvac_certificate_token_%' 
+     ORDER BY option_id DESC 
+     LIMIT 5"
+);
+
+if (empty($recent_tokens)) {
+    echo "No recent certificate tokens found\n";
+} else {
+    foreach ($recent_tokens as $token_row) {
+        $token_key = str_replace('_transient_hvac_certificate_token_', '', $token_row->option_name);
+        echo "\nToken: $token_key\n";
+        $data = maybe_unserialize($token_row->option_value);
+        if (is_array($data)) {
+            echo "  URL: " . home_url('hvac-certificate/' . $token_key) . "\n";
+            echo "  Event: " . ($data['event_name'] ?? 'N/A') . "\n";
+            echo "  Attendee: " . ($data['attendee_name'] ?? 'N/A') . "\n";
+        }
+    }
+}
+
+// 6. Test a real certificate if available
+echo "\n=== REAL CERTIFICATE TEST ===\n";
+require_once HVAC_CE_PLUGIN_DIR . 'includes/certificates/class-certificate-manager.php';
+$cert_manager = HVAC_Certificate_Manager::instance();
+
+// Get a recent certificate
+$recent_cert = $wpdb->get_row(
+    "SELECT * FROM {$wpdb->prefix}hvac_certificates 
+     WHERE file_path IS NOT NULL AND file_path != '' 
+     ORDER BY certificate_id DESC 
+     LIMIT 1"
+);
+
+if ($recent_cert) {
+    echo "Found certificate ID: {$recent_cert->certificate_id}\n";
+    echo "File path: {$recent_cert->file_path}\n";
+    
+    // Check if file exists
+    $upload_dir = wp_upload_dir();
+    $full_path = $upload_dir['basedir'] . '/' . $recent_cert->file_path;
+    
+    if (file_exists($full_path)) {
+        echo "✅ Certificate file exists at: $full_path\n";
+        
+        // Generate download URL
+        $cert_data = array(
+            'certificate_id' => $recent_cert->certificate_id,
+            'file_path' => $recent_cert->file_path,
+            'event_name' => 'Test Event',
+            'attendee_name' => 'Test Attendee'
+        );
+        
+        $download_url = $security->generate_download_token($recent_cert->certificate_id, $cert_data, 300);
+        echo "\nGenerated download URL: $download_url\n";
+        echo "✅ Test this URL in your browser - it should download the certificate!\n";
+    } else {
+        echo "❌ Certificate file NOT found at: $full_path\n";
+    }
+} else {
+    echo "No certificates with file paths found in database\n";
+}
+
+echo "\n=== SUMMARY ===\n";
+echo "Certificate URL system should now be working.\n";
+echo "URLs in format: " . home_url('hvac-certificate/[token]') . " will be handled directly.\n";
+echo "No rewrite rules needed!\n";
+
+echo "
"; \ No newline at end of file