From 6586a557ed87480298a533a2db41c6b03e2354e0 Mon Sep 17 00:00:00 2001 From: johnnyq Date: Fri, 28 Aug 2026 15:04:43 -0400 Subject: [PATCH] Fix Send Client Account Statement Bug --- agent/post/invoice.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/agent/post/invoice.php b/agent/post/invoice.php index 14020c387..c22cfa22e 100644 --- a/agent/post/invoice.php +++ b/agent/post/invoice.php @@ -786,6 +786,17 @@ if (isset($_POST['send_statement'])) { // Build the table once - it is identical for every recipient, only the // greeting differs. Everything interpolated here is already escaped: // addToMailQueue() writes the body into the queue raw. + // + // KEEP EVERY ATTRIBUTE IN THIS MARKUP DOUBLE-QUOTED. The body is spliced + // into a single-quoted SQL literal, so a bare ' ends the statement and the + // INSERT dies; a " is just a character there and needs nothing. The older + // bodies above solve the same problem the other way, writing \' inside a + // double-quoted PHP string so the backslash itself reaches MySQL - do not + // copy that here, because \' inside a SINGLE-quoted PHP string collapses to + // a bare quote and puts the crash straight back. + // + // escapeSql() is not an option on assembled markup: it strip_tags() first, + // which would empty the table. $statement_rows = ''; $statement_total = 0; $statement_line_count = 0; @@ -814,7 +825,7 @@ if (isset($_POST['send_statement'])) { } $statement_rows .= '' - . '' . "$invoice_prefix$invoice_number" . '' + . '' . "$invoice_prefix$invoice_number" . '' . '' . $invoice_scope . '' . '' . $invoice_date . '' . '' . $invoice_due . $overdue_flag . ''