diff --git a/modules/billing/admin_coupons.php b/modules/billing/admin_coupons.php
index 233180cb..e1d7678e 100644
--- a/modules/billing/admin_coupons.php
+++ b/modules/billing/admin_coupons.php
@@ -36,7 +36,7 @@ function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
$db = false;
try {
// suppress direct output; we'll log errors and show a friendly message
- $db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+ $db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
} catch (Throwable $e) {
error_log('[admin_coupons] mysqli_connect exception: ' . $e->getMessage());
$db = false;
diff --git a/modules/billing/admin_invoices.php b/modules/billing/admin_invoices.php
index 87cdf778..adf3425e 100644
--- a/modules/billing/admin_invoices.php
+++ b/modules/billing/admin_invoices.php
@@ -12,7 +12,7 @@ require_once __DIR__ . '/classes/GatewayFactory.php';
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) die('DB connection failed');
mysqli_set_charset($db, 'utf8mb4');
$prefix = $table_prefix ?? 'gsp_';
diff --git a/modules/billing/admin_payments.php b/modules/billing/admin_payments.php
index da4c6839..d53be759 100644
--- a/modules/billing/admin_payments.php
+++ b/modules/billing/admin_payments.php
@@ -10,7 +10,7 @@ require_once __DIR__ . '/classes/BillingRepository.php';
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
$transactions = [];
$errorMsg = '';
if (!$db) {
diff --git a/modules/billing/adminserverlist.php b/modules/billing/adminserverlist.php
index 5d8d7a2a..d7b38b74 100644
--- a/modules/billing/adminserverlist.php
+++ b/modules/billing/adminserverlist.php
@@ -18,8 +18,8 @@ $siteBaseUrl = isset($SITE_BASE_URL) ? trim((string)$SITE_BASE_URL) : '';
// Protect this page: require admin
require_once(__DIR__ . '/includes/admin_auth.php');
-// Create database connection (admin_auth already validated DB but we need connection for UI ops)
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+// Create database connection
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
@@ -29,7 +29,7 @@ include(__DIR__ . '/includes/top.php');
include(__DIR__ . '/includes/menu.php');
echo "
";
/* show errors during setup */
diff --git a/modules/billing/bootstrap.php b/modules/billing/bootstrap.php
index 0750d843..49c9b637 100644
--- a/modules/billing/bootstrap.php
+++ b/modules/billing/bootstrap.php
@@ -28,7 +28,7 @@ $billing_db_opened_by_bootstrap = false;
*/
function billing_get_db()
{
- global $billing_db, $db, $db_host, $db_user, $db_pass, $db_name, $billing_db_opened_by_bootstrap;
+ global $billing_db, $db, $db_host, $db_user, $db_pass, $db_name, $db_port, $billing_db_opened_by_bootstrap;
if (!empty($billing_db) && ($billing_db instanceof mysqli)) {
return $billing_db;
}
@@ -36,8 +36,9 @@ function billing_get_db()
$billing_db = $db;
return $billing_db;
}
+ $port = isset($db_port) ? (int)$db_port : null;
// Try to connect (suppress warnings; caller may check return value)
- $conn = @mysqli_connect($db_host ?? null, $db_user ?? null, $db_pass ?? null, $db_name ?? null);
+ $conn = @mysqli_connect($db_host ?? null, $db_user ?? null, $db_pass ?? null, $db_name ?? null, $port);
if ($conn) {
// Set charset when available
if (function_exists('mysqli_set_charset')) {
diff --git a/modules/billing/diag_remote.php b/modules/billing/diag_remote.php
index 57da2096..8b9c5b41 100644
--- a/modules/billing/diag_remote.php
+++ b/modules/billing/diag_remote.php
@@ -37,7 +37,7 @@ if (defined('BILLING_CONFIG_PATH') && is_readable(BILLING_CONFIG_PATH)) {
echo "Trying DB connection...\n";
$ok = false;
if (isset($db_host)) {
- $db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+ $db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if ($db) {
echo "DB connect: OK (host=$db_host db=$db_name)\n";
$ok = true;
diff --git a/modules/billing/forgot_password.php b/modules/billing/forgot_password.php
index 4bb7eb37..3c8ae32f 100644
--- a/modules/billing/forgot_password.php
+++ b/modules/billing/forgot_password.php
@@ -14,7 +14,7 @@ require_once(__DIR__ . '/bootstrap.php');
/** @var string $table_prefix Table prefix for database tables */
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/includes/admin_auth.php b/modules/billing/includes/admin_auth.php
index 5cbec4ad..2d988224 100644
--- a/modules/billing/includes/admin_auth.php
+++ b/modules/billing/includes/admin_auth.php
@@ -4,17 +4,8 @@ require_once(__DIR__ . '/session_bridge.php');
// If not logged in, redirect to login
if (empty($_SESSION['website_user_id'])) {
- // Build absolute login URL to avoid browser-relative resolution issues
- $script = $_SERVER['SCRIPT_NAME'] ?? '';
- $siteRoot = '/';
- $pos = strpos($script, '/_website');
- if ($pos !== false) {
- $siteRoot = substr($script, 0, $pos + strlen('/_website'));
- } else {
- $siteRoot = rtrim(dirname($script), '/\\');
- }
- $loginUrl = $siteRoot . '/login.php';
- $returnTo = $siteRoot . '/' . basename($_SERVER['PHP_SELF']);
+ $loginUrl = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? '/'), '/\\') . '/login.php';
+ $returnTo = $_SERVER['SCRIPT_NAME'] ?? '/';
header('Location: ' . $loginUrl . '?return_to=' . urlencode($returnTo));
exit();
}
@@ -29,15 +20,13 @@ require_once(__DIR__ . '/config_loader.php');
/** @var string $db_name Database name */
/** @var string $table_prefix Table prefix for database tables */
+$auth_db_port = isset($db_port) ? (int)$db_port : null;
// Use a local connection variable so we don't clash with pages that also use $db
-$auth_db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$auth_db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name, $auth_db_port);
if (!$auth_db) {
// If DB unavailable, deny access gracefully
- // Redirect to absolute login URL
- $script = $_SERVER['SCRIPT_NAME'] ?? '';
- $pos = strpos($script, '/_website');
- $siteRoot = $pos !== false ? substr($script, 0, $pos + strlen('/_website')) : rtrim(dirname($script), '/\\');
- header('Location: ' . $siteRoot . '/login.php');
+ $loginUrl = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? '/'), '/\\') . '/login.php';
+ header('Location: ' . $loginUrl);
exit();
}
@@ -52,15 +41,10 @@ mysqli_close($auth_db);
if (strtolower($role) !== 'admin') {
// Not an admin — redirect to login or home
- // Redirect to absolute login URL
- $script = $_SERVER['SCRIPT_NAME'] ?? '';
- $pos = strpos($script, '/_website');
- $siteRoot = $pos !== false ? substr($script, 0, $pos + strlen('/_website')) : rtrim(dirname($script), '/\\');
- header('Location: ' . $siteRoot . '/login.php');
+ $loginUrl = rtrim(dirname($_SERVER['SCRIPT_NAME'] ?? '/'), '/\\') . '/login.php';
+ header('Location: ' . $loginUrl);
exit();
}
// If we reach here, user is an admin
?>
-
-
diff --git a/modules/billing/includes/config.example.php b/modules/billing/includes/config.example.php
new file mode 100644
index 00000000..a675b925
--- /dev/null
+++ b/modules/billing/includes/config.example.php
@@ -0,0 +1,43 @@
+/includes/config.inc.php (panel config — fallback when no local config)
+ *
+ * This ensures that copying modules/billing/ to any web root works correctly
+ * after editing its own config.inc.php, without being overridden by a parent
+ * panel installation that may have a different database name.
*/
if (defined('BILLING_CONFIG_LOADED')) {
return;
}
+$localConfig = __DIR__ . '/config.inc.php';
+$attempted = [];
+
+// Always prefer the local billing config so the module is self-contained.
+if (is_readable($localConfig)) {
+ $attempted[] = $localConfig;
+ require_once $localConfig;
+ if (!defined('BILLING_CONFIG_PATH')) {
+ define('BILLING_CONFIG_PATH', $localConfig);
+ }
+ define('BILLING_CONFIG_LOADED', true);
+ return;
+}
+
+$attempted[] = $localConfig;
+
+// Fallback: try to load the panel's config (useful when running embedded inside the panel
+// and no local copy has been made yet).
$panelConfig = null;
$projectRoot = realpath(__DIR__ . '/../../..');
if ($projectRoot !== false) {
$panelConfig = $projectRoot . '/includes/config.inc.php';
} else {
- // Fallback relative path without resolving symlinks
$panelConfig = __DIR__ . '/../../..' . '/includes/config.inc.php';
}
-$localConfig = __DIR__ . '/config.inc.php';
-$attempted = [];
-
if ($panelConfig && is_readable($panelConfig)) {
$attempted[] = $panelConfig;
require_once $panelConfig;
@@ -34,17 +51,6 @@ if ($panelConfig && is_readable($panelConfig)) {
}
$attempted[] = $panelConfig;
-if (is_readable($localConfig)) {
- $attempted[] = $localConfig;
- require_once $localConfig;
- if (!defined('BILLING_CONFIG_PATH')) {
- define('BILLING_CONFIG_PATH', $localConfig);
- }
- define('BILLING_CONFIG_LOADED', true);
- return;
-}
-
-$attempted[] = $localConfig;
$message = "GSP Billing module cannot find config.inc.php.\n";
$message .= "Looked in:\n";
diff --git a/modules/billing/includes/menu.php b/modules/billing/includes/menu.php
index 74c4b873..5908f399 100644
--- a/modules/billing/includes/menu.php
+++ b/modules/billing/includes/menu.php
@@ -58,7 +58,8 @@ if ($is_logged_in) {
if (isset($db) && $db instanceof mysqli) {
$menu_db = $db;
} else {
- $menu_db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+ $menu_db_port = isset($db_port) ? (int)$db_port : null;
+ $menu_db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name, $menu_db_port);
$menu_db_opened = true;
}
diff --git a/modules/billing/login.php b/modules/billing/login.php
index 2653a12b..ab4d791d 100644
--- a/modules/billing/login.php
+++ b/modules/billing/login.php
@@ -20,10 +20,9 @@ require_once(__DIR__ . '/includes/log.php');
/** @var string $db_name Database name */
/** @var string $table_prefix Table prefix for database tables */
-// Determine site root up to /_website so we can enforce absolute redirects within this site
+// Determine site root (directory of this script) for building absolute redirects within this site
$script = $_SERVER['SCRIPT_NAME'] ?? '';
-$pos = strpos($script, '/_website');
-$SITE_ROOT_PATH = $pos !== false ? substr($script, 0, $pos + strlen('/_website')) : rtrim(dirname($script), '/\\');
+$SITE_ROOT_PATH = rtrim(dirname($script), '/\\');
// Strict sanitizer that returns an absolute path under $SITE_ROOT_PATH or empty string on invalid
$sanitize_return_path = function($p) use ($SITE_ROOT_PATH) {
@@ -50,7 +49,7 @@ $sanitize_return_path = function($p) use ($SITE_ROOT_PATH) {
};
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/my_account.php b/modules/billing/my_account.php
index 71ad7ab5..6d1ac48b 100644
--- a/modules/billing/my_account.php
+++ b/modules/billing/my_account.php
@@ -38,7 +38,7 @@ require_once(__DIR__ . '/bootstrap.php');
/** @var string $table_prefix Table prefix for database tables */
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/my_servers.php b/modules/billing/my_servers.php
index 62ca9e25..fe351378 100644
--- a/modules/billing/my_servers.php
+++ b/modules/billing/my_servers.php
@@ -21,7 +21,7 @@ require_once(__DIR__ . '/bootstrap.php');
/** @var string $table_prefix Table prefix for database tables */
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/order.php b/modules/billing/order.php
index 2955a84d..45a11270 100644
--- a/modules/billing/order.php
+++ b/modules/billing/order.php
@@ -34,7 +34,7 @@ require_once(__DIR__ . '/bootstrap.php');
/** @var string $table_prefix Table prefix for database tables */
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/payment_success.php b/modules/billing/payment_success.php
index 1743008d..63db78a8 100644
--- a/modules/billing/payment_success.php
+++ b/modules/billing/payment_success.php
@@ -22,7 +22,7 @@ $user_id = isset($_SESSION['website_user_id']) ? intval($_SESSION['website_user_
(isset($_SESSION['user_id']) ? intval($_SESSION['user_id']) : 0);
// Connect to database
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
$orders = [];
$total_paid = 0;
diff --git a/modules/billing/register.php b/modules/billing/register.php
index a4971334..c1a1ad46 100644
--- a/modules/billing/register.php
+++ b/modules/billing/register.php
@@ -12,7 +12,7 @@ require_once(__DIR__ . '/bootstrap.php');
// Simple registration form (creates a user in {table_prefix}users with MD5 password)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['username']) && !empty($_POST['password'])) {
- $db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+ $db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if ($db) {
$username = trim($_POST['username']);
$password = $_POST['password'];
diff --git a/modules/billing/renew_server.php b/modules/billing/renew_server.php
index a2d98694..e2cb61c7 100644
--- a/modules/billing/renew_server.php
+++ b/modules/billing/renew_server.php
@@ -19,7 +19,7 @@ require_once(__DIR__ . '/includes/log.php');
/** @var string $table_prefix Table prefix for database tables */
// Connect to DB (use mysqli like other website modules)
-$db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = @mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
// fail silently and redirect back
$back = $_SERVER['HTTP_REFERER'] ?? 'my_account.php';
diff --git a/modules/billing/reset_password.php b/modules/billing/reset_password.php
index 163222d0..00d2188f 100644
--- a/modules/billing/reset_password.php
+++ b/modules/billing/reset_password.php
@@ -14,7 +14,7 @@ require_once(__DIR__ . '/bootstrap.php');
/** @var string $table_prefix Table prefix for database tables */
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/server_status.php b/modules/billing/server_status.php
index 96fced3a..d40778ef 100644
--- a/modules/billing/server_status.php
+++ b/modules/billing/server_status.php
@@ -11,7 +11,7 @@
require_once(__DIR__ . '/bootstrap.php');
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/serverlist.php b/modules/billing/serverlist.php
index 6393cb23..8962d33f 100644
--- a/modules/billing/serverlist.php
+++ b/modules/billing/serverlist.php
@@ -22,7 +22,7 @@ require_once(__DIR__ . '/bootstrap.php');
/** @var string $table_prefix Table prefix for database tables */
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/test_db_connection.php b/modules/billing/test_db_connection.php
index 3df5c66a..3c222e73 100644
--- a/modules/billing/test_db_connection.php
+++ b/modules/billing/test_db_connection.php
@@ -14,7 +14,7 @@
require_once(__DIR__ . '/bootstrap.php');
// Create database connection
-$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
+$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name, isset($db_port) ? (int)$db_port : null);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
diff --git a/modules/billing/timestamp.txt b/modules/billing/timestamp.txt
index a207b112..4fdf6d43 100644
--- a/modules/billing/timestamp.txt
+++ b/modules/billing/timestamp.txt
@@ -1 +1 @@
-Last Updated at 12:49pm on 2026-02-05
+Last Updated at 1:15pm on 2026-02-05
diff --git a/modules/billing/tools/check_db_user.php b/modules/billing/tools/check_db_user.php
index 7c579605..d6fc3ea7 100644
--- a/modules/billing/tools/check_db_user.php
+++ b/modules/billing/tools/check_db_user.php
@@ -1,6 +1,6 @@