From f97bdecbc1c82fab8904e3634381f488669968d4 Mon Sep 17 00:00:00 2001 From: Timothy Allen Date: Fri, 25 Sep 2026 21:57:11 +0200 Subject: [PATCH] Log database errors instead of showing them. display_errors is off unless DISPLAY_ERRORS is set in .env. --- .env.example | 4 ++++ config.lib.php | 4 ++++ display.php | 2 +- feed.php | 2 +- get_data.lib.php | 5 ++--- open_db.lib.php | 21 +++++++++++++++++++-- publish/login.php | 2 +- publish/post.lib.php | 8 ++++---- session.lib.php | 8 ++++---- 9 files changed, 40 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index 65bf9f4..c0c54f4 100644 --- a/.env.example +++ b/.env.example @@ -17,3 +17,7 @@ GOOGLE_ANALYTICS_ID= # Directory for uploaded images waiting to be saved. Keep it outside the # web root. The default is xxx-uploads in the system temporary directory. UPLOAD_DIR= + +# Show PHP errors in the page (1) or on stderr (stderr). Leave it empty in +# production: errors always go to the PHP error log. +DISPLAY_ERRORS= diff --git a/config.lib.php b/config.lib.php index e553b49..db7d6e8 100644 --- a/config.lib.php +++ b/config.lib.php @@ -39,4 +39,8 @@ function config($key, $default = NULL) { return array_key_exists($key, $values) ? $values[$key] : $default; } + +// Always log PHP errors; show them only if DISPLAY_ERRORS is set (for development) +ini_set('log_errors', '1'); +ini_set('display_errors', (string)config('DISPLAY_ERRORS', '0')); ?> diff --git a/display.php b/display.php index 51d1dc6..beffd0f 100644 --- a/display.php +++ b/display.php @@ -60,7 +60,7 @@ function display_img($id) { } $query = "SELECT img, mime FROM $table WHERE 1 AND ID = ?".$hidden." LIMIT 0, 1"; - $result = $db->execute_query($query, array((int)$id)) or die("Query failed : ".$db->error); + $result = $db->execute_query($query, array((int)$id)) or db_fail(); $row = $result->fetch_assoc(); if ($row) { diff --git a/feed.php b/feed.php index a2d51b9..914ba36 100644 --- a/feed.php +++ b/feed.php @@ -13,7 +13,7 @@ header("Content-Type: application/rss+xml"); // Set up a RSS "header" $query = "SELECT MAX(`date`) FROM $table;"; -$result = $db->query($query) or die("Query failed : ".$db->error); +$result = $db->query($query) or db_fail(); $most_recent = $result->fetch_row(); $now = date("D, d M Y H:i:s O"); diff --git a/get_data.lib.php b/get_data.lib.php index 73ef889..c0a17d8 100644 --- a/get_data.lib.php +++ b/get_data.lib.php @@ -127,13 +127,12 @@ function get_count() { //echo $count_query."
"; $row_count = NULL; - echo $db->info; if ($count_query) { if ($result = $db->execute_query($count_query, $params)) { $row_count = $result->fetch_row(); $result->close(); } else { - die("Error in query: $db->error"); + db_fail(); } } return $row_count[0]; @@ -186,7 +185,7 @@ function get_query($id = NULL) { } $result->close(); } else { - die("Error in query: $db->error"); + db_fail(); } return $results; } diff --git a/open_db.lib.php b/open_db.lib.php index ef4641e..994af57 100644 --- a/open_db.lib.php +++ b/open_db.lib.php @@ -13,8 +13,9 @@ function open_db($state) { mysqli_report(MYSQLI_REPORT_OFF); $db = new mysqli($hostname, $view_user, $view_pass, $db_name); if ($db->connect_error) { - die ("Unable to connect to database"); - die ('Connect Error (' . $db->connect_errno . ') ' . $db->connect_error); + $detail = 'connect error (' . $db->connect_errno . ') ' . $db->connect_error; + $db = NULL; + db_fail($detail); } return TRUE; } else @@ -29,4 +30,20 @@ function open_db($state) { return FALSE; } } + +/* + * Stop the page after a database error. The details, with the file and + * line of the failed call, go to the PHP error log; the visitor only + * sees a short apology. + */ +function db_fail($detail = NULL) { + global $db; + if ($detail === NULL) + $detail = $db ? $db->error : 'no database connection'; + $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; + error_log('xxx: database error at ' . basename($caller['file']) . ':' . $caller['line'] . ': ' . $detail); + if (!headers_sent()) + header('HTTP/1.1 500 Internal Server Error'); + die('

Sorry, something went wrong. Please try again later.

'); +} ?> diff --git a/publish/login.php b/publish/login.php index 31fbe9f..aac4f82 100644 --- a/publish/login.php +++ b/publish/login.php @@ -27,7 +27,7 @@ if (isset($_SESSION['editor'])) { $username = (string)($_POST['username'] ?? ''); $query = "SELECT * FROM $table WHERE username = ? LIMIT 1"; - $getid = $db->execute_query($query, array($username)) or die("Query failed: ".$db->error); + $getid = $db->execute_query($query, array($username)) or db_fail(); $row = $getid->fetch_assoc(); $stored_password = ''; diff --git a/publish/post.lib.php b/publish/post.lib.php index 3addd41..9304b93 100644 --- a/publish/post.lib.php +++ b/publish/post.lib.php @@ -46,7 +46,7 @@ function save_data($id = NULL) { $mime = $row['mime']; $getimg->close(); } else { - die("Error in query: $db->error"); + db_fail(); } } else { $image_file = save_uploaded_file(); @@ -91,7 +91,7 @@ function save_data($id = NULL) { } //echo $query; - $result = $db->execute_query($query, $params) or die("Query failed: ".$db->error); + $result = $db->execute_query($query, $params) or db_fail(); if (is_numeric($id) && $move) { $queue_id = $id; @@ -100,7 +100,7 @@ function save_data($id = NULL) { // Get the (new) ID if we don't already have it. if (!is_numeric($id) || $move) { $query = "SELECT LAST_INSERT_ID();"; - $getid = $db->query($query) or die("Query failed: ".$db->error); + $getid = $db->query($query) or db_fail(); $row = $getid->fetch_row(); $id = $row[0]; } @@ -140,7 +140,7 @@ function delete_story($id, $move = FALSE) { $query = "DELETE FROM $table WHERE `id` = ? LIMIT 1"; //echo $query; - $result = $db->execute_query($query, array((int)$id)) or die("Query failed : ".$db->error); + $result = $db->execute_query($query, array((int)$id)) or db_fail(); $message = ''; if (!$move) diff --git a/session.lib.php b/session.lib.php index a56296e..bc4b644 100644 --- a/session.lib.php +++ b/session.lib.php @@ -55,7 +55,7 @@ function check_persistent_login() { open_db('open'); $query = "SELECT * FROM $table WHERE username = ? AND session = ? LIMIT 1"; - $getid = $db->execute_query($query, array($username, $key_hash)) or die("Query failed: ".$db->error); + $getid = $db->execute_query($query, array($username, $key_hash)) or db_fail(); $row = $getid->fetch_assoc(); open_db('close'); @@ -79,7 +79,7 @@ function create_persistent_login($username) { // Add the hash of the session key to the database $query = "INSERT INTO $table (username, session) VALUES (?, ?)"; - $db->execute_query($query, array($username, persistent_key_hash($key))) or die("Query failed: ".$db->error); + $db->execute_query($query, array($username, persistent_key_hash($key))) or db_fail(); open_db('close'); // Create cookie with key @@ -98,14 +98,14 @@ function delete_persistent_login() { // Remove this session key from the database if ($username !== '' && $key !== '') { $query = "DELETE FROM $table WHERE username = ? AND session = ?"; - $db->execute_query($query, array($username, persistent_key_hash($key))) or die("Query failed: ".$db->error); + $db->execute_query($query, array($username, persistent_key_hash($key))) or db_fail(); } // Reap old sessions, and keys stored before they were hashed $query = "DELETE FROM $table " . " WHERE created < DATE_SUB(now(), INTERVAL 1 YEAR)" . " OR CHAR_LENGTH(session) <> 64;"; - $db->query($query) or die("Query failed: ".$db->error); + $db->query($query) or db_fail(); open_db('close');