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');