From 2b89a40a01cd6ca520a58cf0ea4e148794a5da14 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:41:24 +0000 Subject: [PATCH 01/42] Initial plan From 825590b8c970d338f79f7b472ce9aafcf7a8dd52 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:44:16 +0000 Subject: [PATCH 02/42] Remove deprecated get_magic_quotes_gpc() function calls Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- accessories.php | 4 +--- inc/functions.inc.php | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/accessories.php b/accessories.php index 16540eb..7e95f24 100644 --- a/accessories.php +++ b/accessories.php @@ -506,9 +506,7 @@ // modify the View if (isset($_POST['acc_modview_doit'])) { - $viewdefs['source'] = get_magic_quotes_gpc() - ? stripslashes(trim($_POST['def_view_source'])) - : $_POST['def_view_source']; + $viewdefs['source'] = $_POST['def_view_source']; $viewdefs['check'] = (isset($_POST['def_view_check'])) ? 'yes' : 'no'; if (drop_view($s_viewdefs['name'])) { diff --git a/inc/functions.inc.php b/inc/functions.inc.php index eb71013..53f1c99 100644 --- a/inc/functions.inc.php +++ b/inc/functions.inc.php @@ -1328,10 +1328,7 @@ function get_request_data($name, $source = 'POST') if ($source == 'GET') { $data = urldecode($data); } - if (get_magic_quotes_gpc() || - ini_get('magic_quotes_sybase') == 1 - ) { - + if (ini_get('magic_quotes_sybase') == 1) { $data = stripslashes($data); } From 484005c24be37de43b2149c0a88b6e3adc40a52c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:47:00 +0000 Subject: [PATCH 03/42] Initial plan From fd62e26fc5913858b3bf31476e0f2cb9b9738785 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:50:17 +0000 Subject: [PATCH 04/42] Initial plan From c1511331febaf565cb5e7c0b8ad3dbe880192779 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:50:54 +0000 Subject: [PATCH 05/42] Fix fb_lock_print to use mandatory -d parameter for Firebird 3+ Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- admin.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/admin.php b/admin.php index 8cf7946..d181c6d 100644 --- a/admin.php +++ b/admin.php @@ -163,9 +163,12 @@ // if (have_panel_permissions($s_login['user'], 'adm_server')) { $exe = 'fb_lock_print'; + + // Construct database path with host if needed (required for Firebird 3+) + $db_path = !empty($s_login['host']) ? $s_login['host'].':'.$s_login['database'] : $s_login['database']; // get the LOCK_HEADER BLOCK - list($iblockpr_output, $binary_error) = exec_command($exe, ' -o'); + list($iblockpr_output, $binary_error) = exec_command($exe, ' -d ' . escapeshellarg($db_path) . ' -o'); $lock_header = ''; unset($iblockpr_output[0]); @@ -177,7 +180,7 @@ } // get the server statistics - list($iblockpr_output, $binray_error) = exec_command($exe, ' -i'); + list($iblockpr_output, $binray_error) = exec_command($exe, ' -d ' . escapeshellarg($db_path) . ' -i'); if (count($iblockpr_output) > 3) { $iblock['names'] = preg_split('/[\s,]+/', $iblockpr_output[0]); From 1fbdc36822d3b6e2b580351343ec096a740a8600 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:52:39 +0000 Subject: [PATCH 06/42] Apply code review feedback: use ibwa_escapeshellarg and fix typo Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- admin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin.php b/admin.php index d181c6d..ae44ee2 100644 --- a/admin.php +++ b/admin.php @@ -168,7 +168,7 @@ $db_path = !empty($s_login['host']) ? $s_login['host'].':'.$s_login['database'] : $s_login['database']; // get the LOCK_HEADER BLOCK - list($iblockpr_output, $binary_error) = exec_command($exe, ' -d ' . escapeshellarg($db_path) . ' -o'); + list($iblockpr_output, $binary_error) = exec_command($exe, ' -d ' . ibwa_escapeshellarg($db_path) . ' -o'); $lock_header = ''; unset($iblockpr_output[0]); @@ -180,7 +180,7 @@ } // get the server statistics - list($iblockpr_output, $binray_error) = exec_command($exe, ' -d ' . escapeshellarg($db_path) . ' -i'); + list($iblockpr_output, $binary_error) = exec_command($exe, ' -d ' . ibwa_escapeshellarg($db_path) . ' -i'); if (count($iblockpr_output) > 3) { $iblock['names'] = preg_split('/[\s,]+/', $iblockpr_output[0]); From 07a744a4c751def964a2accb16873c39b944d610 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:52:56 +0000 Subject: [PATCH 07/42] Fix XSS vulnerabilities with htmlspecialchars sanitization Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- panels/tb_dropfields.php | 6 +++--- panels/tb_droptables.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/panels/tb_dropfields.php b/panels/tb_dropfields.php index 4eaa84a..f50700a 100644 --- a/panels/tb_dropfields.php +++ b/panels/tb_dropfields.php @@ -18,18 +18,18 @@ } else { ?>
-

+

- +
-
+
diff --git a/panels/tb_droptables.php b/panels/tb_droptables.php index 6f2a92a..de68877 100644 --- a/panels/tb_droptables.php +++ b/panels/tb_droptables.php @@ -23,11 +23,11 @@ - + -
+
@@ -35,7 +35,7 @@

 
-
+
 
         
From 778248828471c33308c3dac97d83643b168e68fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:00:12 +0000 Subject: [PATCH 08/42] Initial plan From 0a977026bcfd29d4fd5bd2bc10abbf96057319dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:15:38 +0000 Subject: [PATCH 09/42] Initial plan From bc983c0bb07fabc7b4a9c533a64afcf9265288f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:20:31 +0000 Subject: [PATCH 10/42] Fix XSS vulnerabilities in showblob.php and showimage.php Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- showblob.php | 16 +++++++++------- showimage.php | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/showblob.php b/showblob.php index d6910ce..d38af13 100644 --- a/showblob.php +++ b/showblob.php @@ -15,13 +15,13 @@ require './inc/script_start.inc.php'; if ($_SERVER['REQUEST_METHOD'] == 'GET') { - $table = get_request_data('table', 'GET'); - $col = get_request_data('col', 'GET'); - $where = get_request_data('where', 'GET'); + $table = htmlspecialchars(get_request_data('table', 'GET'), ENT_QUOTES, 'UTF-8'); + $col = htmlspecialchars(get_request_data('col', 'GET'), ENT_QUOTES, 'UTF-8'); + $where = htmlspecialchars(get_request_data('where', 'GET'), ENT_QUOTES, 'UTF-8'); } else { - $table = get_request_data('table'); - $col = get_request_data('col'); - $where = get_request_data('where'); + $table = htmlspecialchars(get_request_data('table'), ENT_QUOTES, 'UTF-8'); + $col = htmlspecialchars(get_request_data('col'), ENT_QUOTES, 'UTF-8'); + $where = htmlspecialchars(get_request_data('where'), ENT_QUOTES, 'UTF-8'); $s_wt['blob_as'][$col] = get_request_data('blobtype'); } @@ -61,7 +61,9 @@ echo '
'.htmlspecialchars($blob)."
\n"; break; case 'html': - echo $blob; + // Note: HTML blob display is intentionally unescaped to allow rendering of HTML content. + // This should only be used with trusted blob data. For untrusted data, use 'text' mode instead. + echo htmlspecialchars($blob, ENT_QUOTES, 'UTF-8'); break; case 'hex': echo hex_view($blob); diff --git a/showimage.php b/showimage.php index 3884e01..508f75f 100644 --- a/showimage.php +++ b/showimage.php @@ -24,9 +24,9 @@ $dbhandle = db_connect() or fb_error(); -$table = $_GET['table']; -$col = $_GET['col']; -$where = $_GET['where']; +$table = htmlspecialchars($_GET['table'], ENT_QUOTES, 'UTF-8'); +$col = htmlspecialchars($_GET['col'], ENT_QUOTES, 'UTF-8'); +$where = htmlspecialchars($_GET['where'], ENT_QUOTES, 'UTF-8'); $sql = sprintf('SELECT %s FROM %s %s', $col, $table, $where); $blob = get_blob_content($sql); From 3d28a4e158c2f59add5066d163c874804510560a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:24:21 +0000 Subject: [PATCH 11/42] Fix header injection vulnerability in settings.php Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- settings.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/settings.php b/settings.php index 6eb52c6..6188f66 100644 --- a/settings.php +++ b/settings.php @@ -34,7 +34,16 @@ $s_stylesheet_etag = ''; } -header("Location: " . $_SERVER["HTTP_REFERER"]); +// Redirect back to referer, but validate it first to prevent header injection +$referer = isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : 'index.php'; +// Validate referer to prevent header injection - only allow same-origin URLs +if (filter_var($referer, FILTER_VALIDATE_URL) && + (parse_url($referer, PHP_URL_HOST) === $_SERVER['HTTP_HOST'] || + parse_url($referer, PHP_URL_HOST) === null)) { + header("Location: " . $referer); +} else { + header("Location: index.php"); +} require('./inc/script_end.inc.php'); From 7474a15492fb4afe58db84c5de742df33e4f3f6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:27:09 +0000 Subject: [PATCH 12/42] Address code review feedback - improve SQL injection prevention and URL validation Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- settings.php | 17 +++++++++++++---- showblob.php | 30 +++++++++++++++++++++--------- showimage.php | 18 +++++++++++++++--- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/settings.php b/settings.php index 6188f66..4e0087c 100644 --- a/settings.php +++ b/settings.php @@ -37,11 +37,20 @@ // Redirect back to referer, but validate it first to prevent header injection $referer = isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : 'index.php'; // Validate referer to prevent header injection - only allow same-origin URLs -if (filter_var($referer, FILTER_VALIDATE_URL) && - (parse_url($referer, PHP_URL_HOST) === $_SERVER['HTTP_HOST'] || - parse_url($referer, PHP_URL_HOST) === null)) { - header("Location: " . $referer); +$referer_host = parse_url($referer, PHP_URL_HOST); +$current_host = $_SERVER['HTTP_HOST']; + +// Allow only same-origin URLs (when host matches) or relative URLs (when host is null) +// Reject external URLs and malformed URLs +if (filter_var($referer, FILTER_VALIDATE_URL)) { + // Absolute URL - must be same origin + if ($referer_host === $current_host) { + header("Location: " . $referer); + } else { + header("Location: index.php"); + } } else { + // Not a valid absolute URL - use default header("Location: index.php"); } diff --git a/showblob.php b/showblob.php index d38af13..2f0b937 100644 --- a/showblob.php +++ b/showblob.php @@ -15,18 +15,29 @@ require './inc/script_start.inc.php'; if ($_SERVER['REQUEST_METHOD'] == 'GET') { - $table = htmlspecialchars(get_request_data('table', 'GET'), ENT_QUOTES, 'UTF-8'); - $col = htmlspecialchars(get_request_data('col', 'GET'), ENT_QUOTES, 'UTF-8'); - $where = htmlspecialchars(get_request_data('where', 'GET'), ENT_QUOTES, 'UTF-8'); + $table = get_request_data('table', 'GET'); + $col = get_request_data('col', 'GET'); + $where = get_request_data('where', 'GET'); } else { - $table = htmlspecialchars(get_request_data('table'), ENT_QUOTES, 'UTF-8'); - $col = htmlspecialchars(get_request_data('col'), ENT_QUOTES, 'UTF-8'); - $where = htmlspecialchars(get_request_data('where'), ENT_QUOTES, 'UTF-8'); + $table = get_request_data('table'); + $col = get_request_data('col'); + $where = get_request_data('where'); $s_wt['blob_as'][$col] = get_request_data('blobtype'); } -$imageurl = 'showimage.php?where='.urlencode($where).'&table='.$table.'&col='.$col; +// Validate SQL identifiers to prevent SQL injection +// Table and column names should only contain alphanumeric characters and underscores +if (!preg_match('/^[a-zA-Z0-9_$]+$/', $table)) { + die('Invalid table name'); +} +if (!preg_match('/^[a-zA-Z0-9_$]+$/', $col)) { + die('Invalid column name'); +} +// Where clause validation is complex, so we trust it comes from internal app logic +// In production, this should use parameterized queries + +$imageurl = 'showimage.php?where='.urlencode($where).'&table='.urlencode($table).'&col='.urlencode($col); $imageurl .= '&'.uniqid('UNIQ_'); $blob = get_blob_content(sprintf('SELECT %s FROM %s %s', $col, $table, $where)); @@ -61,8 +72,9 @@ echo '
'.htmlspecialchars($blob)."
\n"; break; case 'html': - // Note: HTML blob display is intentionally unescaped to allow rendering of HTML content. - // This should only be used with trusted blob data. For untrusted data, use 'text' mode instead. + // Note: Displaying HTML blob content with escaping to prevent XSS attacks. + // The HTML will be shown as plain text. To render actual HTML, this feature + // should only be used with trusted blob data in a controlled environment. echo htmlspecialchars($blob, ENT_QUOTES, 'UTF-8'); break; case 'hex': diff --git a/showimage.php b/showimage.php index 508f75f..4fa7e14 100644 --- a/showimage.php +++ b/showimage.php @@ -24,9 +24,21 @@ $dbhandle = db_connect() or fb_error(); -$table = htmlspecialchars($_GET['table'], ENT_QUOTES, 'UTF-8'); -$col = htmlspecialchars($_GET['col'], ENT_QUOTES, 'UTF-8'); -$where = htmlspecialchars($_GET['where'], ENT_QUOTES, 'UTF-8'); +$table = $_GET['table']; +$col = $_GET['col']; +$where = $_GET['where']; + +// Validate SQL identifiers to prevent SQL injection +// Table and column names should only contain alphanumeric characters and underscores +if (!preg_match('/^[a-zA-Z0-9_$]+$/', $table)) { + die('Invalid table name'); +} +if (!preg_match('/^[a-zA-Z0-9_$]+$/', $col)) { + die('Invalid column name'); +} +// Where clause validation is complex, so we trust it comes from internal app logic +// In production, this should use parameterized queries + $sql = sprintf('SELECT %s FROM %s %s', $col, $table, $where); $blob = get_blob_content($sql); From 76a57f327ccfbc15798ad694b1d743eea5362256 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 11:28:22 +0000 Subject: [PATCH 13/42] Add warning comments for WHERE clause and support relative URLs in referer validation Co-authored-by: mariuz <18359+mariuz@users.noreply.github.com> --- settings.php | 8 +++++--- showblob.php | 5 +++-- showimage.php | 5 +++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/settings.php b/settings.php index 4e0087c..9089fe3 100644 --- a/settings.php +++ b/settings.php @@ -40,8 +40,7 @@ $referer_host = parse_url($referer, PHP_URL_HOST); $current_host = $_SERVER['HTTP_HOST']; -// Allow only same-origin URLs (when host matches) or relative URLs (when host is null) -// Reject external URLs and malformed URLs +// Allow same-origin absolute URLs or relative URLs if (filter_var($referer, FILTER_VALIDATE_URL)) { // Absolute URL - must be same origin if ($referer_host === $current_host) { @@ -49,8 +48,11 @@ } else { header("Location: index.php"); } +} elseif (strpos($referer, '/') === 0) { + // Relative URL starting with / - safe to use + header("Location: " . $referer); } else { - // Not a valid absolute URL - use default + // Not a valid URL - use default header("Location: index.php"); } diff --git a/showblob.php b/showblob.php index 2f0b937..1041fa1 100644 --- a/showblob.php +++ b/showblob.php @@ -34,8 +34,9 @@ if (!preg_match('/^[a-zA-Z0-9_$]+$/', $col)) { die('Invalid column name'); } -// Where clause validation is complex, so we trust it comes from internal app logic -// In production, this should use parameterized queries +// WARNING: WHERE clause validation is complex and not implemented here +// The WHERE parameter remains a potential SQL injection vector +// This should use parameterized queries in production $imageurl = 'showimage.php?where='.urlencode($where).'&table='.urlencode($table).'&col='.urlencode($col); $imageurl .= '&'.uniqid('UNIQ_'); diff --git a/showimage.php b/showimage.php index 4fa7e14..5242e03 100644 --- a/showimage.php +++ b/showimage.php @@ -36,8 +36,9 @@ if (!preg_match('/^[a-zA-Z0-9_$]+$/', $col)) { die('Invalid column name'); } -// Where clause validation is complex, so we trust it comes from internal app logic -// In production, this should use parameterized queries +// WARNING: WHERE clause validation is complex and not implemented here +// The WHERE parameter remains a potential SQL injection vector +// This should use parameterized queries in production $sql = sprintf('SELECT %s FROM %s %s', $col, $table, $where); $blob = get_blob_content($sql); From 72174b695b18a58d97bcac7dc33e73ece35caac6 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 15:43:09 +0200 Subject: [PATCH 14/42] docs: improve README structure and content --- README.md | 127 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 70 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 4ce82de..3084a7a 100644 --- a/README.md +++ b/README.md @@ -1,85 +1,98 @@ -# FirebirdWebAdmin is a web frontend for the Firebird database server +# FirebirdWebAdmin + +**FirebirdWebAdmin** is a lightweight, powerful web-based administration tool for the Firebird database server. It provides an intuitive interface for managing databases, tables, and other database objects directly from your browser. [![Crowdin](https://d322cqt584bo4o.cloudfront.net/firebirdwebadmin/localized.svg)](https://crowdin.com/project/firebirdwebadmin) [![Code Climate](https://codeclimate.com/github/mariuz/firebirdwebadmin/badges/gpa.svg)](https://codeclimate.com/github/mariuz/firebirdwebadmin) +[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://opensource.org/licenses/GPL-2.0) +[![PHP Version](https://img.shields.io/badge/php-%3E%3D%205.5-8892bf.svg)](https://php.net) + +--- + +## ๐Ÿš€ Features -By now it has the functionalities for - -* creating, deleting, modifying databases, tables, generators, views, triggers, domains, indices, stored procedures, udf's, exceptions, roles and database users -* performing sql expressions on databases and display the results -* import and export of data through files in the csv format -* browsing through the contents of tables and views, watching them growing while typing in data -* selecting data for deleting and editing while browsing tables -* inserting, deleting, displaying the contents of blob fields -* diplaying database metadata, browsing the firebird system tables -* database backup and restore, database maintenance +### ๐Ÿ›  Database & Object Management +* **Database Operations:** Create, delete, and modify databases. +* **Schema Management:** Manage tables, views, triggers, domains, indices, and generators. +* **Business Logic:** Create and edit stored procedures and User Defined Functions (UDFs). +* **Security:** Manage database users and roles. +* **Exceptions:** Define and manage database exceptions. -Some of the features are only available if the database- and the web-server are running on the same machine. The reason is that php have to call the Firebird tools (isql, gsec, gstat, etc.) to perform certain actions. +### ๐Ÿ” Data Manipulation +* **SQL Console:** Execute SQL expressions and scripts with result display. +* **Data Browsing:** Browse table and view contents with real-time updates. +* **Editing:** Insert, edit, and delete data rows while browsing. +* **Blob Support:** Handle BLOB fields (display and edit contents). +* **Import/Export:** Seamlessly import and export data using CSV format. -## Overview +### ๐Ÿ“ˆ Administration & Maintenance +* **Maintenance:** Database backup and restore capabilities. +* **Monitoring:** Display database metadata and browse system tables. +* **Statistics:** Access database and server statistics (requires local access). +* **Maintenance Tools:** Integrated database maintenance functions. -1. [Documentation](#documentation) -2. [Requirements](#requirements) -3. [ChangeLog](#requirements) -4. [Contributing](#contributing) -5. [Copyright notice](#copyright-notice) +> **Note:** Some administrative features (like backup/restore and statistics) require PHP to have access to Firebird command-line tools (`isql`, `gsec`, `gstat`, etc.) and may require the web server to run on the same machine as the database server. -## Documentation +--- -There is no documentation available yet, but if you are familiar with Firebird you will have no troubles using FirebirdWebAdmin. +## ๐Ÿ“‹ Requirements -For some basic configuration settings have a look to the file `./inc/configuration.inc.php` before you start the programm. +* **PHP:** Version 5.5 or higher (PHP 7.x and 8.x recommended). + * Must be compiled with `pdo_firebird` or `interbase` support. + * `pcre` support enabled. +* **Database:** Firebird 2.x, 3.x, or 4.x. +* **Web Server:** Apache 2.x, Nginx, or any server with PHP support. +* **Operating System:** Linux (tested), Windows (compatible). -Here is how to use and install on Ubuntu +--- -Firebird documentation is located on this page +## โš™๏ธ Installation & Configuration -## Requirements +1. **Download:** Clone this repository or download the source code. + ```bash + git clone https://github.com/mariuz/firebirdwebadmin.git + ``` +2. **Web Server Setup:** Place the directory in your web server's document root (e.g., `/var/www/html/`). +3. **Configuration:** + * Open `inc/configuration.inc.php`. + * Configure the `BINPATH` to point to your Firebird binaries (e.g., `/usr/bin/`). + * Set `TMPPATH` to a directory writable by the web server. + * Adjust default connection settings if necessary. +4. **Access:** Navigate to the directory in your browser (e.g., `http://localhost/firebirdwebadmin/`). -This is the environment I'm using for the development. Other components are not or less tested. So if you got problems make sure you are not using older software components. +--- -PHP with compiled in support for Firebird/InterBase and pcre (but any version >= 5.5 should work) +## ๐Ÿ“– Documentation -Firebird 2.x.x for Linux, -Apache 2.x or any server with php support +While there is no exhaustive manual, users familiar with Firebird will find the interface intuitive. -## ChangeLog +* **Configuration:** Check `inc/configuration.inc.php` for advanced settings. +* **Ubuntu Guide:** [How to install Firebird on Ubuntu](https://help.ubuntu.com/community/Firebird3.0) +* **Firebird Official Docs:** [Firebird Documentation](https://www.firebirdsql.org/en/documentation/) -### Version 3.4.1 (27.02.2020) +--- -* [enhancement:] Adjust "Accessories" page UI. -* [enhancement:] Remove Crowdin badge from footer. -* [enhancement:] Update debug_funcs.inc.php -* [bugfix:] Don't warn if "isql" is "isql-fb" on Linux -* [typo:] Correct typo: firebirid -> firebird -* [bugfix] fix sql create database -* [enhancement:] Add Character Sets -* [enhancement:] Quiet PHP7.2 deprecation warning โ€ฆ -* [enhancement:] Further create_function refactor -* [enhancement:] Remove unused/outdated markableFbwaTable. -* [enhancement:] cosmetics +## ๐Ÿ“„ ChangeLog -#### Further informations +See [CHANGELOG.md](CHANGELOG.md) for the full history of changes. -* See [CHANGELOG.md][changelog] to get the full changelog. +--- -## Contributing +## ๐Ÿค Contributing -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request +We welcome contributions! To contribute: -## Copyright notice +1. Fork the repository. +2. Create a feature branch (`git checkout -b feature/amazing-feature`). +3. Commit your changes (`git commit -m 'Add amazing feature'`). +4. Push to the branch (`git push origin feature/amazing-feature`). +5. Open a Pull Request. - (C) 2000,2001,2002,2003,2004 Lutz Brueckner - Kapellenstr. 1A - 22117 Hamburg, Germany +--- -FirebirdWebAdmin is published under the terms of the [GNU GPL v.2][gnu_gpl_v2_license], please read the file LICENCE for details. +## โš–๏ธ License -This software is provided 'as-is', without any expressed or implied warranty. In no event will the author be held liable for any damages arising from the use of this software. +**FirebirdWebAdmin** is published under the terms of the [GNU GPL v.2](https://opensource.org/licenses/GPL-2.0). +See the `LICENSE` file for details. -[gnu_gpl_v2_license]: https://opensource.org/licenses/GPL-2.0 -[changelog]: CHANGELOG.md +ยฉ 2000-2026 Lutz Brueckner and contributors. From 90c6c9f7b7b152b8229c1c69be90f48f9134edc2 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 15:59:52 +0200 Subject: [PATCH 15/42] refactor: Replace XMLHttpRequestClient with fetch API --- CHANGELOG.md | 5 ++ inc/javascript.inc.php | 54 +++++--------------- js/XMLHttpRequestClient.js | 69 ------------------------- js/miscellaneous.js | 101 +++++++++++++++++++++++++++++++++++-- 4 files changed, 116 insertions(+), 113 deletions(-) delete mode 100644 js/XMLHttpRequestClient.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a9539c..a6d16e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # ChangeLog +## Version 3.4.2 (24.02.2026) + +* [enhancement:] Refactored all AJAX calls to use the modern `fetch` API. +* [enhancement:] Removed the outdated and insecure `XMLHttpRequestClient.js` library. + ## Version 3.4.1 (27.02.2020) * [enhancement:] Adjust "Accessories" page UI. diff --git a/inc/javascript.inc.php b/inc/javascript.inc.php index 0205179..b255c69 100644 --- a/inc/javascript.inc.php +++ b/inc/javascript.inc.php @@ -152,21 +152,6 @@ function adjustCollation(source, target) { return $js; } -// -// include the XMLHttpRequestClient library -// -function js_xml_http_request_client() -{ - static $done = false; - - if ($done == true) { - return ''; - } - $done = true; - - return js_javascript_file('js/XMLHttpRequestClient.js'); -} - // // return the URL of the server-script for the XMLHttpRequests // @@ -195,8 +180,7 @@ function js_request_column_config_form() $js = << function requestColumnConfigForm(fk_table, table, column, divId) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("column_config_form", new Array(fk_table, table, column), "setInnerHtml", new Array(divId)); + doRequest("column_config_form", [fk_table, table, column], "setInnerHtml", [divId]); } @@ -215,8 +199,7 @@ function js_request_close_panel() $js = << function requestClosedPanel(idx, active) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("closed_panel", new Array(idx, active), "setInnerHtml", new Array("p" + idx)); + doRequest("closed_panel", [idx, active], "setInnerHtml", ["p" + idx]); } @@ -241,12 +224,10 @@ function js_request_details() $js = << function requestDetail(type, name, title) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("detail_view", new Array(type, name, title), "setInnerHtml", new Array(detailPrefix(type) + '_' + name)); + doRequest("detail_view", [type, name, title], "setInnerHtml", [detailPrefix(type) + '_' + name]); } function closeDetail(type, id, name, title) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("detail_close", new Array(type, name, title), "setInnerHtml", new Array(id)); + doRequest("detail_close", [type, name, title], "setInnerHtml", [id]); } @@ -267,8 +248,7 @@ function js_request_fk() $js = << function requestFKValues(table, column, value) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("fk_values", new Array(table, column, value), "setInnerHtml", new Array("fk")); + doRequest("fk_values", [table, column, value], "setInnerHtml", ["fk"]); } @@ -287,12 +267,10 @@ function js_request_filter_fields() $js = << function getFilterFields(table) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("systable_filter_fields", new Array(table), "setInnerHtml", new Array("systable_field")); + doRequest("systable_filter_fields", [table], "setInnerHtml", ["systable_field"]); } function getFilterValues(table, field) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("systable_filter_values", new Array(table, field), "setInnerHtml", new Array("systable_value")); + doRequest("systable_filter_values", [table, field], "setInnerHtml", ["systable_value"]); } @@ -311,8 +289,7 @@ function js_request_table_columns() $js = << function requestTableColumns(table, id, restriction) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("table_columns_selectlist", new Array(table, id, restriction), "setInnerHtml", new Array(id)); + doRequest("table_columns_selectlist", [table, id, restriction], "setInnerHtml", [id]); } @@ -332,8 +309,7 @@ function js_request_sql_buffer() $js = << function requestSqlBuffer(idx) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("sql_buffer", new Array(idx), "putSqlBuffer", new Array(idx)); + doRequest("sql_buffer", [idx], "putSqlBuffer", [idx]); } function putSqlBuffer(sql, idx) { @@ -356,8 +332,7 @@ function js_data_export() $js = << function replaceExportFormatOptions(format) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("data_export_format_options", new Array(format), "setInnerHtml", new Array("dt_export_format_options")); + doRequest("data_export_format_options", [format], "setInnerHtml", ["dt_export_format_options"]); hide("dt_export_iframe"); @@ -371,13 +346,11 @@ function replaceExportFormatOptions(format) { } function setExportTarget(target) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("set_export_target", new Array(target), "", new Array()); + doRequest("set_export_target", [target], "", []); } function setExportSource(source) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("set_export_source", new Array(source), "", new Array()); + doRequest("set_export_source", [source], "", []); hide("dt_export_iframe"); @@ -414,8 +387,7 @@ function js_request_comment_area() $js = << function requestCommentArea(type, name) { - var req = new XMLHttpRequestClient("$server_url"); - req.Request("comment_area", new Array(type, name), "setInnerHtml", new Array(detailPrefix(type) + 'c_' + name)); + doRequest("comment_area", [type, name], "setInnerHtml", [detailPrefix(type) + 'c_' + name]); } diff --git a/js/XMLHttpRequestClient.js b/js/XMLHttpRequestClient.js deleted file mode 100644 index b9b36e5..0000000 --- a/js/XMLHttpRequestClient.js +++ /dev/null @@ -1,69 +0,0 @@ -// Purpose javascript implementation of a client class for XMLHttpRequests -// Author Lutz Brueckner -// Copyright (c) 2000-2006 by Lutz Brueckner, -// published under the terms of the GNU General Public Licence v.2, -// see file LICENCE for details - - -/* - by defining the request object in the global scope - it is reusable for multiple calls on mozilla browsers -*/ -var xmlreq = false; - -function XMLHttpRequestClient(server_url) { - - var method = 'GET'; - var serverUrl = server_url; - var response = null; - var jsCallback = null; - var jsCallbackParameters = null; - var debug = false; - - this.Request = doRequest; - - xmlreq = new XMLHttpRequest(); - return; - - function doRequest(handler, handler_parameters, callback, callback_parameters) { - - jsCallback = callback; - jsCallbackParameters = callback_parameters; - - var sep = serverUrl.search(/\?/) == -1 ? '?' : '&'; - xmlreq.onreadystatechange = ProcessReqChange; - xmlreq.open(method, serverUrl + sep + 'f=' + handler + _getUrlParameters(handler_parameters), true); - xmlreq.setRequestHeader('Content-Type', 'text/xml; charset=' + php_charset); - xmlreq.send(null); - } - - function ProcessReqChange() { - - if (xmlreq.readyState == 4) { - if (jsCallback != null) { - response = xmlreq.responseText; - eval(jsCallback + "(response" + _getParametersList(jsCallbackParameters) + ")"); - } - } - } - - function _getUrlParameters(parameters) { - - var str = ''; - for (var i=0; i { + url.searchParams.append(`p${i}`, param); + }); + + fetch(url) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.text(); + }) + .then(html => { + displayFKValues(html); + }) + .catch(error => { + console.error('There has been a problem with your fetch operation:', error); + }); } function displayFKValues(html) { @@ -35,20 +53,97 @@ function displayFKValues(html) { } function detailPrefix(type) { + switch (type) { + case 'table': + return 't'; + break; + case 'view': + return 'v'; + break; + case 'trigger': + return 'r'; + break; + case 'procedure': + return 'p'; + break; + default: + return ''; + } -} \ No newline at end of file + +} + + + +// A modern fetch-based replacement for the old XMLHttpRequestClient.Request + +function doRequest(handler, handler_parameters, callback, callback_parameters) { + + const url = new URL(php_xml_http_request_server_url); + + url.searchParams.append('f', handler); + + handler_parameters.forEach((param, i) => { + + url.searchParams.append(`p${i}`, param); + + }); + + + + fetch(url) + + .then(response => { + + if (!response.ok) { + + throw new Error(`Network response was not ok for handler: ${handler}`); + + } + + return response.text(); + + }) + + .then(textResponse => { + + // Get the callback function from the window object + + const callbackFn = window[callback]; + + if (typeof callbackFn === 'function') { + + // Call the function with the response and any extra parameters + + callbackFn(textResponse, ...callback_parameters); + + } else { + + console.error(`Callback function "${callback}" not found.`); + + } + + }) + + .catch(error => { + + console.error('There has been a problem with your fetch operation:', error); + + }); + +} From f573e73ac63875dbc72fd0b6012a815ee9832ef5 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 16:43:19 +0200 Subject: [PATCH 16/42] feat(testing): Add Playwright E2E tests with GitHub Actions --- .github/docker/php-apache-firebird/Dockerfile | 2 + .github/workflows/playwright.yml | 72 +++++++++++++++++ .gitignore | 9 ++- docker-compose.yml | 31 ++++++++ package-lock.json | 79 +++++++++++++++++++ package.json | 7 +- playwright.config.js | 45 +++++++++++ tests/e2e/example.spec.js | 18 +++++ 8 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 .github/docker/php-apache-firebird/Dockerfile create mode 100644 .github/workflows/playwright.yml create mode 100644 docker-compose.yml create mode 100644 package-lock.json create mode 100644 playwright.config.js create mode 100644 tests/e2e/example.spec.js diff --git a/.github/docker/php-apache-firebird/Dockerfile b/.github/docker/php-apache-firebird/Dockerfile new file mode 100644 index 0000000..ab82819 --- /dev/null +++ b/.github/docker/php-apache-firebird/Dockerfile @@ -0,0 +1,2 @@ +FROM php:8.1-apache +RUN docker-php-ext-install pdo_firebird && a2enmod rewrite diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..c038513 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,72 @@ +name: Playwright Tests + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Install dependencies + run: npm ci + + - name: Install Playwright browsers + run: npx playwright install --with-deps + + - name: Configure application for testing + run: | + cp inc/configuration.inc.php inc/configuration.inc.php.bak + sed -i "s/define('DB_USER', 'SYSDBA');/define('DB_USER', 'SYSDBA');/" inc/configuration.inc.php + sed -i "s/define('DB_PASS', '');/define('DB_PASS', 'test');/" inc/configuration.inc.php + sed -i "s/define('DB_HOST', 'localhost');/define('DB_HOST', 'firebird');/" inc/configuration.inc.php + sed -i "s|define('DB_PATH', '/var/lib/firebird/3.0/data/employee.fdb');|define('DB_PATH', 'test.fdb');|" inc/configuration.inc.php + + - name: Start services + run: docker-compose up -d + + - name: Wait for services to be healthy + run: | + echo "Waiting for services to become healthy..." + # This command will wait for the healthchecks defined in docker-compose.yml to pass. + # It will exit with an error if the services do not become healthy within the timeout. + docker-compose ps + max_wait=300 + current_wait=0 + while [ $current_wait -lt $max_wait ]; do + if [ "$(docker-compose ps -q web | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ] && + [ "$(docker-compose ps -q firebird | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ]; then + echo "Services are healthy!" + docker-compose logs + exit 0 + fi + echo -n "." + sleep 5 + current_wait=$((current_wait + 5)) + done + echo "Services did not become healthy in time." + docker-compose logs + exit 1 + + - name: Run Playwright tests + run: npx playwright test + env: + BASE_URL: http://localhost:8080 + + - name: Stop services + if: always() + run: docker-compose down + + - name: Restore config file + if: always() + run: | + mv inc/configuration.inc.php.bak inc/configuration.inc.php diff --git a/.gitignore b/.gitignore index 4037493..a06a842 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,11 @@ # git config --global core.excludesfile '~/.gitignore_global' # PhpStorm -.idea/**/* \ No newline at end of file + +.idea/**/* + + + +# Node dependencies + +node_modules/ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..67463b0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +version: '3.8' +services: + firebird: + image: firebird/firebird:3.0 + ports: + - "3050:3050" + environment: + FIREBIRD_PASSWORD: test + FIREBIRD_DB: test.fdb + healthcheck: + test: ["CMD", "gbak", "-user", "sysdba", "-password", "test", "localhost:/firebird/data/test.fdb", "/dev/null"] + interval: 10s + timeout: 5s + retries: 5 + + web: + build: + context: . + dockerfile: .github/docker/php-apache-firebird/Dockerfile + ports: + - "8080:80" + volumes: + - .:/var/www/html + depends_on: + firebird: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost/database.php"] + interval: 10s + timeout: 5s + retries: 5 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c4d90c1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,79 @@ +{ + "name": "firebird-web-admin", + "version": "3.4.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "firebird-web-admin", + "version": "3.4.1", + "license": "GPL-2.0", + "devDependencies": { + "@playwright/test": "^1.58.2" + } + }, + "node_modules/@playwright/test": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/playwright": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.58.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + } + } +} diff --git a/package.json b/package.json index a70e74a..1abcf43 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "FirebirdWebAdmin is a web frontend for the Firebird database server.", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "npx playwright test" }, "repository": { "type": "git", @@ -34,5 +34,8 @@ "bugs": { "url": "https://github.com/mariuz/firebirdwebadmin/issues" }, - "homepage": "https://github.com/mariuz/firebirdwebadmin#readme" + "homepage": "https://github.com/mariuz/firebirdwebadmin#readme", + "devDependencies": { + "@playwright/test": "^1.58.2" + } } diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 0000000..4872824 --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,45 @@ +// @ts-check +const { defineConfig, devices } = require('@playwright/test'); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +module.exports = defineConfig({ + testDir: './tests/e2e', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: process.env.BASE_URL || 'http://localhost:8080', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + ], +}); diff --git a/tests/e2e/example.spec.js b/tests/e2e/example.spec.js new file mode 100644 index 0000000..5067a96 --- /dev/null +++ b/tests/e2e/example.spec.js @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('/database.php'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Firebird Web Admin \/ Database/); +}); + +test('login form is visible', async ({ page }) => { + await page.goto('/database.php'); + + // Expect the login form to be visible + await expect(page.locator('form[action="database.php"]')).toBeVisible(); + await expect(page.getByLabel('Username')).toBeVisible(); + await expect(page.getByLabel('Password')).toBeVisible(); + await expect(page.getByRole('button', { name: 'Login' })).toBeVisible(); +}); From 2d8e0c34f8e6f9cf54f9cea18e203812918e1f4b Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 17:04:57 +0200 Subject: [PATCH 17/42] fix docker-compose command not found --- .github/workflows/playwright.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index c038513..647a5ff 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -32,21 +32,21 @@ jobs: sed -i "s|define('DB_PATH', '/var/lib/firebird/3.0/data/employee.fdb');|define('DB_PATH', 'test.fdb');|" inc/configuration.inc.php - name: Start services - run: docker-compose up -d + run: docker compose up -d - name: Wait for services to be healthy run: | echo "Waiting for services to become healthy..." # This command will wait for the healthchecks defined in docker-compose.yml to pass. # It will exit with an error if the services do not become healthy within the timeout. - docker-compose ps + docker compose ps max_wait=300 current_wait=0 while [ $current_wait -lt $max_wait ]; do if [ "$(docker-compose ps -q web | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ] && [ "$(docker-compose ps -q firebird | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ]; then echo "Services are healthy!" - docker-compose logs + docker compose logs exit 0 fi echo -n "." @@ -54,7 +54,7 @@ jobs: current_wait=$((current_wait + 5)) done echo "Services did not become healthy in time." - docker-compose logs + docker compose logs exit 1 - name: Run Playwright tests @@ -64,7 +64,7 @@ jobs: - name: Stop services if: always() - run: docker-compose down + run: docker compose down - name: Restore config file if: always() From 30eb78e5fd4cabedc9a33eed8b2a0bc57e7e9523 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 17:12:21 +0200 Subject: [PATCH 18/42] fix(ci): address obsolete docker-compose version and incorrect Firebird image name --- .github/docker/php-apache-firebird/Dockerfile | 3 ++- .github/workflows/playwright.yml | 11 +++++------ docker-compose.yml | 5 ++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/docker/php-apache-firebird/Dockerfile b/.github/docker/php-apache-firebird/Dockerfile index ab82819..5ecab89 100644 --- a/.github/docker/php-apache-firebird/Dockerfile +++ b/.github/docker/php-apache-firebird/Dockerfile @@ -1,2 +1,3 @@ FROM php:8.1-apache -RUN docker-php-ext-install pdo_firebird && a2enmod rewrite +RUN apt-get update && apt-get install -y firebird-dev && \ + docker-php-ext-install pdo_firebird && a2enmod rewrite diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 647a5ff..2d2592b 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -26,10 +26,9 @@ jobs: - name: Configure application for testing run: | cp inc/configuration.inc.php inc/configuration.inc.php.bak - sed -i "s/define('DB_USER', 'SYSDBA');/define('DB_USER', 'SYSDBA');/" inc/configuration.inc.php - sed -i "s/define('DB_PASS', '');/define('DB_PASS', 'test');/" inc/configuration.inc.php - sed -i "s/define('DB_HOST', 'localhost');/define('DB_HOST', 'firebird');/" inc/configuration.inc.php - sed -i "s|define('DB_PATH', '/var/lib/firebird/3.0/data/employee.fdb');|define('DB_PATH', 'test.fdb');|" inc/configuration.inc.php + sed -i "s/define('DEFAULT_HOST', 'localhost');/define('DEFAULT_HOST', 'firebird');/" inc/configuration.inc.php + sed -i "s/define('DEFAULT_DB', 'employee.fdb');/define('DEFAULT_DB', 'test.fdb');/" inc/configuration.inc.php + sed -i "s|define('DEFAULT_PATH', '/var/lib/firebird/2.5/data/');|define('DEFAULT_PATH', '/firebird/data/');|" inc/configuration.inc.php - name: Start services run: docker compose up -d @@ -43,8 +42,8 @@ jobs: max_wait=300 current_wait=0 while [ $current_wait -lt $max_wait ]; do - if [ "$(docker-compose ps -q web | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ] && - [ "$(docker-compose ps -q firebird | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ]; then + if [ "$(docker compose ps -q web | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ] && + [ "$(docker compose ps -q firebird | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ]; then echo "Services are healthy!" docker compose logs exit 0 diff --git a/docker-compose.yml b/docker-compose.yml index 67463b0..cbb43a7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,11 @@ -version: '3.8' services: firebird: - image: firebird/firebird:3.0 + image: firebirdsql/firebird:3.0 ports: - "3050:3050" environment: FIREBIRD_PASSWORD: test - FIREBIRD_DB: test.fdb + FIREBIRD_DATABASE: test.fdb healthcheck: test: ["CMD", "gbak", "-user", "sysdba", "-password", "test", "localhost:/firebird/data/test.fdb", "/dev/null"] interval: 10s From 87d211e7ee7a9b06373cd66e8f902397419ea1e0 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 17:14:57 +0200 Subject: [PATCH 19/42] fix(ci): install firebird extension from PECL for fbird_* functions --- .github/docker/php-apache-firebird/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/docker/php-apache-firebird/Dockerfile b/.github/docker/php-apache-firebird/Dockerfile index 5ecab89..41443fe 100644 --- a/.github/docker/php-apache-firebird/Dockerfile +++ b/.github/docker/php-apache-firebird/Dockerfile @@ -1,3 +1,6 @@ FROM php:8.1-apache RUN apt-get update && apt-get install -y firebird-dev && \ - docker-php-ext-install pdo_firebird && a2enmod rewrite + pecl install firebird && \ + docker-php-ext-install pdo_firebird && \ + docker-php-ext-enable firebird && \ + a2enmod rewrite From 7656acf52f697fd74016e1e3f9e0d91998a71c2b Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 17:17:06 +0200 Subject: [PATCH 20/42] fix(ci): compile firebird extension from source (GitHub) --- .github/docker/php-apache-firebird/Dockerfile | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/docker/php-apache-firebird/Dockerfile b/.github/docker/php-apache-firebird/Dockerfile index 41443fe..8731da5 100644 --- a/.github/docker/php-apache-firebird/Dockerfile +++ b/.github/docker/php-apache-firebird/Dockerfile @@ -1,6 +1,19 @@ FROM php:8.1-apache -RUN apt-get update && apt-get install -y firebird-dev && \ - pecl install firebird && \ - docker-php-ext-install pdo_firebird && \ - docker-php-ext-enable firebird && \ - a2enmod rewrite + +RUN apt-get update && apt-get install -y \ + firebird-dev \ + git \ + autoconf \ + build-essential \ + && git clone https://github.com/FirebirdSQL/php-firebird.git /tmp/php-firebird \ + && cd /tmp/php-firebird \ + && phpize \ + && ./configure \ + && make \ + && make install \ + && docker-php-ext-install pdo_firebird \ + && docker-php-ext-enable firebird \ + && a2enmod rewrite \ + && rm -rf /tmp/php-firebird \ + && apt-get purge -y --auto-remove git autoconf build-essential \ + && rm -rf /var/lib/apt/lists/* From d89ffffd27f783dd0270cca71057e09da7e5e18e Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Tue, 24 Feb 2026 18:46:41 +0200 Subject: [PATCH 21/42] fix(ci): use firebirdsql/firebird:v3.0 as tag 3.0 is missing --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index cbb43a7..eafad8c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: firebird: - image: firebirdsql/firebird:3.0 + image: firebirdsql/firebird:v3.0 ports: - "3050:3050" environment: From 49f3d029830d97385a97a78ab9ecd05d77c9538b Mon Sep 17 00:00:00 2001 From: Popa Marius Adrian Date: Tue, 24 Feb 2026 20:37:13 +0200 Subject: [PATCH 22/42] Update Firebird image version to 3 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index eafad8c..a144a50 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: firebird: - image: firebirdsql/firebird:v3.0 + image: firebirdsql/firebird:3 ports: - "3050:3050" environment: From 0fdf647528d19dcf9051ff94474f65fcb5a389ec Mon Sep 17 00:00:00 2001 From: Popa Marius Adrian Date: Tue, 24 Feb 2026 21:27:33 +0200 Subject: [PATCH 23/42] Replace firebird extension with interbase --- .github/docker/php-apache-firebird/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/docker/php-apache-firebird/Dockerfile b/.github/docker/php-apache-firebird/Dockerfile index 8731da5..531e2af 100644 --- a/.github/docker/php-apache-firebird/Dockerfile +++ b/.github/docker/php-apache-firebird/Dockerfile @@ -12,7 +12,7 @@ RUN apt-get update && apt-get install -y \ && make \ && make install \ && docker-php-ext-install pdo_firebird \ - && docker-php-ext-enable firebird \ + && docker-php-ext-enable interbase \ && a2enmod rewrite \ && rm -rf /tmp/php-firebird \ && apt-get purge -y --auto-remove git autoconf build-essential \ From 388cb968ae866108c085999f5348111543747ee4 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 04:43:42 +0200 Subject: [PATCH 24/42] fix(ci): use FIREBIRD_ROOT_PASSWORD and improve healthcheck --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a144a50..99625e8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,13 +4,13 @@ services: ports: - "3050:3050" environment: - FIREBIRD_PASSWORD: test + FIREBIRD_ROOT_PASSWORD: test FIREBIRD_DATABASE: test.fdb healthcheck: - test: ["CMD", "gbak", "-user", "sysdba", "-password", "test", "localhost:/firebird/data/test.fdb", "/dev/null"] + test: ["CMD", "/opt/firebird/bin/isql", "-user", "sysdba", "-password", "test", "localhost:/firebird/data/test.fdb", "-q", "-e", "show database; quit;"] interval: 10s timeout: 5s - retries: 5 + retries: 10 web: build: From 9db881cb15aed9904728e53a618d89326adaab50 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 04:44:19 +0200 Subject: [PATCH 25/42] fix(ci): simplify firebird healthcheck --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 99625e8..d30a44f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: FIREBIRD_ROOT_PASSWORD: test FIREBIRD_DATABASE: test.fdb healthcheck: - test: ["CMD", "/opt/firebird/bin/isql", "-user", "sysdba", "-password", "test", "localhost:/firebird/data/test.fdb", "-q", "-e", "show database; quit;"] + test: ["CMD-SHELL", "isql -user sysdba -password test /firebird/data/test.fdb -q -e 'quit;'"] interval: 10s timeout: 5s retries: 10 From 055e31c587c0147d5f863a2621682fea02b713b0 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 04:53:19 +0200 Subject: [PATCH 26/42] fix(ci): use simpler port-based healthcheck for firebird --- docker-compose.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d30a44f..05ed5ea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,10 +7,11 @@ services: FIREBIRD_ROOT_PASSWORD: test FIREBIRD_DATABASE: test.fdb healthcheck: - test: ["CMD-SHELL", "isql -user sysdba -password test /firebird/data/test.fdb -q -e 'quit;'"] + test: ["CMD", "nc", "-z", "localhost", "3050"] interval: 10s timeout: 5s - retries: 10 + retries: 20 + start_period: 30s web: build: From dd12f1afc31ba6b48ba78138db441fd65d45f355 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 10:06:32 +0200 Subject: [PATCH 27/42] fix(ci): improve healthcheck robustness and add debug info --- .github/workflows/playwright.yml | 8 +++++++- docker-compose.yml | 9 +++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 2d2592b..b2d4a38 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -31,7 +31,13 @@ jobs: sed -i "s|define('DEFAULT_PATH', '/var/lib/firebird/2.5/data/');|define('DEFAULT_PATH', '/firebird/data/');|" inc/configuration.inc.php - name: Start services - run: docker compose up -d + run: | + docker compose up -d || { + echo "Docker compose up failed!" + docker compose ps + docker compose logs + exit 1 + } - name: Wait for services to be healthy run: | diff --git a/docker-compose.yml b/docker-compose.yml index 05ed5ea..bbf8ebf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,11 +7,11 @@ services: FIREBIRD_ROOT_PASSWORD: test FIREBIRD_DATABASE: test.fdb healthcheck: - test: ["CMD", "nc", "-z", "localhost", "3050"] + test: ["CMD-SHELL", "/opt/firebird/bin/isql -user sysdba -password test localhost:test.fdb -q -e 'quit;'"] interval: 10s - timeout: 5s - retries: 20 - start_period: 30s + timeout: 10s + retries: 30 + start_period: 60s web: build: @@ -29,3 +29,4 @@ services: interval: 10s timeout: 5s retries: 5 + start_period: 30s From b8c9269a74a93da2af812386a81de7db78fd698e Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 10:25:07 +0200 Subject: [PATCH 28/42] fix(ci): use correct database path for healthcheck and config --- .github/workflows/playwright.yml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index b2d4a38..8603c8d 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -28,7 +28,7 @@ jobs: cp inc/configuration.inc.php inc/configuration.inc.php.bak sed -i "s/define('DEFAULT_HOST', 'localhost');/define('DEFAULT_HOST', 'firebird');/" inc/configuration.inc.php sed -i "s/define('DEFAULT_DB', 'employee.fdb');/define('DEFAULT_DB', 'test.fdb');/" inc/configuration.inc.php - sed -i "s|define('DEFAULT_PATH', '/var/lib/firebird/2.5/data/');|define('DEFAULT_PATH', '/firebird/data/');|" inc/configuration.inc.php + sed -i "s|define('DEFAULT_PATH', '/var/lib/firebird/2.5/data/');|define('DEFAULT_PATH', '/var/lib/firebird/data/');|" inc/configuration.inc.php - name: Start services run: | diff --git a/docker-compose.yml b/docker-compose.yml index bbf8ebf..96f2a89 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: FIREBIRD_ROOT_PASSWORD: test FIREBIRD_DATABASE: test.fdb healthcheck: - test: ["CMD-SHELL", "/opt/firebird/bin/isql -user sysdba -password test localhost:test.fdb -q -e 'quit;'"] + test: ["CMD-SHELL", "isql -user sysdba -password test localhost:/var/lib/firebird/data/test.fdb -q -e 'quit;'"] interval: 10s timeout: 10s retries: 30 From 93aa57c7a83131b2645b953883ba84435cbe6f68 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 10:46:07 +0200 Subject: [PATCH 29/42] fix(ci): use absolute isql path, 127.0.0.1, and add healthcheck debug info --- .github/workflows/playwright.yml | 17 +++++++++++------ docker-compose.yml | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 8603c8d..3d68c38 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -48,17 +48,22 @@ jobs: max_wait=300 current_wait=0 while [ $current_wait -lt $max_wait ]; do - if [ "$(docker compose ps -q web | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ] && - [ "$(docker compose ps -q firebird | xargs docker inspect -f '{{.State.Health.Status}}')" = "healthy" ]; then + web_status=$(docker compose ps --format json web | jq -r '.[0].Health' 2>/dev/null || docker inspect -f '{{.State.Health.Status}}' $(docker compose ps -q web)) + firebird_status=$(docker compose ps --format json firebird | jq -r '.[0].Health' 2>/dev/null || docker inspect -f '{{.State.Health.Status}}' $(docker compose ps -q firebird)) + + if [ "$web_status" = "healthy" ] && [ "$firebird_status" = "healthy" ]; then echo "Services are healthy!" - docker compose logs exit 0 fi - echo -n "." - sleep 5 - current_wait=$((current_wait + 5)) + echo "Waiting... Web: $web_status, Firebird: $firebird_status" + sleep 10 + current_wait=$((current_wait + 10)) done echo "Services did not become healthy in time." + echo "--- Firebird Healthcheck Logs ---" + docker inspect --format='{{json .State.Health}}' $(docker compose ps -q firebird) + echo "--- Web Healthcheck Logs ---" + docker inspect --format='{{json .State.Health}}' $(docker compose ps -q web) docker compose logs exit 1 diff --git a/docker-compose.yml b/docker-compose.yml index 96f2a89..3fe98ce 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: FIREBIRD_ROOT_PASSWORD: test FIREBIRD_DATABASE: test.fdb healthcheck: - test: ["CMD-SHELL", "isql -user sysdba -password test localhost:/var/lib/firebird/data/test.fdb -q -e 'quit;'"] + test: ["CMD-SHELL", "/opt/firebird/bin/isql -user sysdba -password test 127.0.0.1:/var/lib/firebird/data/test.fdb -q -e 'quit;'"] interval: 10s timeout: 10s retries: 30 From b48d23d312e547bf43101b2c4ceb94252354d9b9 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 10:55:20 +0200 Subject: [PATCH 30/42] fix(ci): decouple startup and improve healthcheck visibility --- .github/workflows/playwright.yml | 27 ++++++++++++++------------- docker-compose.yml | 9 ++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 3d68c38..adbd677 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -42,28 +42,29 @@ jobs: - name: Wait for services to be healthy run: | echo "Waiting for services to become healthy..." - # This command will wait for the healthchecks defined in docker-compose.yml to pass. - # It will exit with an error if the services do not become healthy within the timeout. - docker compose ps max_wait=300 current_wait=0 while [ $current_wait -lt $max_wait ]; do - web_status=$(docker compose ps --format json web | jq -r '.[0].Health' 2>/dev/null || docker inspect -f '{{.State.Health.Status}}' $(docker compose ps -q web)) - firebird_status=$(docker compose ps --format json firebird | jq -r '.[0].Health' 2>/dev/null || docker inspect -f '{{.State.Health.Status}}' $(docker compose ps -q firebird)) + firebird_status=$(docker inspect --format='{{.State.Health.Status}}' $(docker compose ps -q firebird) 2>/dev/null || echo "starting") + web_status=$(docker inspect --format='{{.State.Health.Status}}' $(docker compose ps -q web) 2>/dev/null || echo "starting") - if [ "$web_status" = "healthy" ] && [ "$firebird_status" = "healthy" ]; then - echo "Services are healthy!" + echo "Status: Firebird=$firebird_status, Web=$web_status (${current_wait}s)" + + if [ "$firebird_status" = "healthy" ] && [ "$web_status" = "healthy" ]; then + echo "All services are healthy!" exit 0 fi - echo "Waiting... Web: $web_status, Firebird: $firebird_status" + sleep 10 current_wait=$((current_wait + 10)) done - echo "Services did not become healthy in time." - echo "--- Firebird Healthcheck Logs ---" - docker inspect --format='{{json .State.Health}}' $(docker compose ps -q firebird) - echo "--- Web Healthcheck Logs ---" - docker inspect --format='{{json .State.Health}}' $(docker compose ps -q web) + + echo "ERROR: Services did not become healthy in time." + echo "--- Firebird Detailed Status ---" + docker inspect $(docker compose ps -q firebird) + echo "--- Web Detailed Status ---" + docker inspect $(docker compose ps -q web) + echo "--- Container Logs ---" docker compose logs exit 1 diff --git a/docker-compose.yml b/docker-compose.yml index 3fe98ce..68d0568 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,11 +7,11 @@ services: FIREBIRD_ROOT_PASSWORD: test FIREBIRD_DATABASE: test.fdb healthcheck: - test: ["CMD-SHELL", "/opt/firebird/bin/isql -user sysdba -password test 127.0.0.1:/var/lib/firebird/data/test.fdb -q -e 'quit;'"] + test: ["CMD-SHELL", "timeout 1s bash -c ':> /dev/tcp/127.0.0.1/3050' || exit 1"] interval: 10s - timeout: 10s + timeout: 5s retries: 30 - start_period: 60s + start_period: 30s web: build: @@ -22,8 +22,7 @@ services: volumes: - .:/var/www/html depends_on: - firebird: - condition: service_healthy + - firebird healthcheck: test: ["CMD", "curl", "-f", "http://localhost/database.php"] interval: 10s From c483df60bda02b79f7e81087671b5314c2ebb9db Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 11:04:23 +0200 Subject: [PATCH 31/42] fix(ci): fix PHP extension loading and title mismatch --- .github/docker/php-apache-firebird/Dockerfile | 2 +- inc/functions.inc.php | 2 +- inc/script_start.inc.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/docker/php-apache-firebird/Dockerfile b/.github/docker/php-apache-firebird/Dockerfile index 531e2af..8731da5 100644 --- a/.github/docker/php-apache-firebird/Dockerfile +++ b/.github/docker/php-apache-firebird/Dockerfile @@ -12,7 +12,7 @@ RUN apt-get update && apt-get install -y \ && make \ && make install \ && docker-php-ext-install pdo_firebird \ - && docker-php-ext-enable interbase \ + && docker-php-ext-enable firebird \ && a2enmod rewrite \ && rm -rf /tmp/php-firebird \ && apt-get purge -y --auto-remove git autoconf build-essential \ diff --git a/inc/functions.inc.php b/inc/functions.inc.php index 53f1c99..d499d8c 100644 --- a/inc/functions.inc.php +++ b/inc/functions.inc.php @@ -40,7 +40,7 @@ function build_title($str, $showdb = true) { global $s_connected, $s_login; - $title = 'FirebirdWebAdmin ' . VERSION . ' *** ' . $str; + $title = 'Firebird Web Admin / ' . $str; if ($s_connected == true && $showdb) { $title .= ': ' . $s_login['database']; } diff --git a/inc/script_start.inc.php b/inc/script_start.inc.php index c066243..b0b2e38 100644 --- a/inc/script_start.inc.php +++ b/inc/script_start.inc.php @@ -26,7 +26,7 @@ include './inc/debug_funcs.inc.php'; } -if (!extension_loaded('interbase')) { +if (!extension_loaded('interbase') && !extension_loaded('firebird')) { die($ERRORS['NO_IBASE_MODULE']); } From 314ebb21ebea0d10c0312155eed2d0709f37a7d4 Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 11:23:36 +0200 Subject: [PATCH 32/42] fix(ci): enable interbase extension (filename produced by build) --- .github/docker/php-apache-firebird/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/docker/php-apache-firebird/Dockerfile b/.github/docker/php-apache-firebird/Dockerfile index 8731da5..531e2af 100644 --- a/.github/docker/php-apache-firebird/Dockerfile +++ b/.github/docker/php-apache-firebird/Dockerfile @@ -12,7 +12,7 @@ RUN apt-get update && apt-get install -y \ && make \ && make install \ && docker-php-ext-install pdo_firebird \ - && docker-php-ext-enable firebird \ + && docker-php-ext-enable interbase \ && a2enmod rewrite \ && rm -rf /tmp/php-firebird \ && apt-get purge -y --auto-remove git autoconf build-essential \ From 64de2a4e09b85f9d5b29ffed25a69486ed93e13c Mon Sep 17 00:00:00 2001 From: Popa Adrian Marius Date: Wed, 25 Feb 2026 11:34:43 +0200 Subject: [PATCH 33/42] fix(ci): fix TypeError in get_customize_defaults and modernize PHP tags --- inc/functions.inc.php | 3 ++- views/footer.php | 6 +++--- views/header.php | 4 ++-- views/menu.php | 5 ++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/inc/functions.inc.php b/inc/functions.inc.php index d499d8c..10136a5 100644 --- a/inc/functions.inc.php +++ b/inc/functions.inc.php @@ -1249,6 +1249,7 @@ function get_customize_cookie_name() // function get_customize_defaults($useragent) { + $ie = (isset($useragent) && is_array($useragent) && isset($useragent['ie'])) ? $useragent['ie'] : false; return array('color' => array('background' => COLOR_BACKGROUND, 'panel' => COLOR_PANEL, @@ -1264,7 +1265,7 @@ function get_customize_defaults($useragent) 'firstrow' => COLOR_FIRSTROW, 'secondrow' => COLOR_SECONDROW), 'language' => LANGUAGE, - 'fontsize' => ($useragent['ie'] ? 8 : 11), + 'fontsize' => ($ie ? 8 : 11), 'textarea' => array('cols' => SQL_AREA_COLS, 'rows' => SQL_AREA_ROWS), 'iframeheight' => IFRAME_HEIGHT, diff --git a/views/footer.php b/views/footer.php index e478655..c4f63e6 100644 --- a/views/footer.php +++ b/views/footer.php @@ -10,7 +10,7 @@

- + - FirebirdWebAdmin @@ -120,10 +120,10 @@ class="col-sm-4 control-label"> - diff --git a/views/header.php b/views/header.php index 97e8a95..e226cf7 100644 --- a/views/header.php +++ b/views/header.php @@ -1,10 +1,10 @@ - + - <?= $title ?> + <?php echo $title; ?> diff --git a/views/menu.php b/views/menu.php index 30bcf1d..1a66d67 100644 --- a/views/menu.php +++ b/views/menu.php @@ -14,7 +14,7 @@ FirebirdWebAdmin