prepare("SELECT i.id, i.invoice_number, i.customer_id, c.id AS cust_exists FROM invoices i LEFT JOIN customers c ON c.id = i.customer_id WHERE i.id = :id"); $stmt->execute([':id' => $id]); $diag = $stmt->fetch(PDO::FETCH_ASSOC); if (!$diag) { die('Fehler: Rechnung nicht gefunden (ID: ' . $id . ')'); } if (!$diag['cust_exists']) { die('Fehler: Kunde zur Rechnung ' . htmlspecialchars($diag['invoice_number']) . ' existiert nicht mehr.'); } // Prüfe Verzeichnis-Berechtigungen $uploadBase = __DIR__ . '/uploads/invoices'; if (!is_dir($uploadBase)) { die('Fehler: Upload-Verzeichnis fehlt (' . $uploadBase . '). Bitte erstellen mit: mkdir -p ' . $uploadBase); } if (!is_writable($uploadBase)) { die('Fehler: Upload-Verzeichnis nicht beschreibbar (' . $uploadBase . ')'); } die('Fehler beim Generieren der PDF. Bitte Logs prüfen.'); } } // Vollständiger Dateipfad $fullPath = __DIR__ . '/' . $pdfPath; if (!file_exists($fullPath) || !is_readable($fullPath)) { die('PDF-Datei nicht gefunden.'); } // Integritätsprüfung $isValid = verify_invoice_pdf($id); if ($isValid === false) { // WARNUNG: PDF wurde möglicherweise manipuliert! error_log("WARNUNG: Integritätsprüfung fehlgeschlagen für Rechnung ID $id"); // Optional: Warnung anzeigen statt die PDF auszuliefern // die('PDF-Integritätsfehler! Die Datei wurde möglicherweise manipuliert.'); } // Rechnungsnummer für Dateinamen holen $pdo = get_db(); $stmt = $pdo->prepare("SELECT invoice_number FROM invoices WHERE id = :id"); $stmt->execute([':id' => $id]); $invoiceNumber = $stmt->fetchColumn() ?: 'Rechnung'; // PDF ausliefern header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="Rechnung-' . $invoiceNumber . '.pdf"'); header('Content-Length: ' . filesize($fullPath)); header('Cache-Control: private, max-age=0, must-revalidate'); readfile($fullPath); exit;