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