Add password reset feature and server management pages

Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-10-22 14:38:22 +00:00
parent 0a573145d3
commit 5f93c6728e
14 changed files with 1580 additions and 5 deletions

View file

@ -0,0 +1,286 @@
<?php
// Start a separate session for the website
session_name("gameservers_website");
session_start();
// Include database configuration
require_once(__DIR__ . '/includes/config.inc.php');
// Create database connection
$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
// Logger function
function logger($logtext){
file_put_contents(__DIR__ . "/logfile.txt", $logtext . PHP_EOL, FILE_APPEND);
}
$message = '';
$error = '';
// Process password reset request
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['request_reset'])) {
$identifier = trim($_POST['identifier'] ?? '');
if (empty($identifier)) {
$error = 'Please enter your username or email address.';
} else {
// Sanitize input
$identifier = mysqli_real_escape_string($db, $identifier);
// Check if it's an email or username
$query = "SELECT user_id, users_login, users_email FROM ogp_users
WHERE users_login = '$identifier' OR users_email = '$identifier' LIMIT 1";
$result = mysqli_query($db, $query);
if ($result && mysqli_num_rows($result) === 1) {
$user = mysqli_fetch_assoc($result);
// Generate reset token
$token = bin2hex(random_bytes(32));
$expires = date('Y-m-d H:i:s', strtotime('+1 hour'));
// Check if password_reset_tokens table exists
$table_check = mysqli_query($db, "SHOW TABLES LIKE 'ogp_password_reset_tokens'");
if (!$table_check || mysqli_num_rows($table_check) === 0) {
// Create table if it doesn't exist
$create_table = "CREATE TABLE IF NOT EXISTS ogp_password_reset_tokens (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
token VARCHAR(64) NOT NULL,
expires DATETIME NOT NULL,
used TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_token (token),
INDEX idx_user_id (user_id)
)";
mysqli_query($db, $create_table);
}
// Delete any existing tokens for this user
$stmt = $db->prepare("DELETE FROM ogp_password_reset_tokens WHERE user_id = ?");
$stmt->bind_param('i', $user['user_id']);
$stmt->execute();
$stmt->close();
// Insert new token
$stmt = $db->prepare("INSERT INTO ogp_password_reset_tokens (user_id, token, expires) VALUES (?, ?, ?)");
$stmt->bind_param('iss', $user['user_id'], $token, $expires);
$stmt->execute();
$stmt->close();
// Build reset link
$reset_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http")
. "://{$_SERVER['HTTP_HOST']}"
. dirname($_SERVER['SCRIPT_NAME'])
. "/reset_password.php?token=" . urlencode($token);
// Send email (for now, just show the link - actual email sending requires mail configuration)
$email_body = "Hello {$user['users_login']},\n\n"
. "You requested a password reset. Click the link below to reset your password:\n\n"
. "{$reset_link}\n\n"
. "This link will expire in 1 hour.\n\n"
. "If you did not request this reset, please ignore this email.";
// Attempt to send email
$headers = "From: noreply@" . $_SERVER['HTTP_HOST'] . "\r\n"
. "Reply-To: noreply@" . $_SERVER['HTTP_HOST'] . "\r\n"
. "X-Mailer: PHP/" . phpversion();
$email_sent = @mail($user['users_email'], "Password Reset Request", $email_body, $headers);
logger("Password reset requested for user: {$user['users_login']} (email sent: " . ($email_sent ? 'yes' : 'no') . ")");
if ($email_sent) {
$message = "Password reset instructions have been sent to your email address.";
} else {
// If email fails, show the link directly (development mode)
$message = "Password reset link generated. In production, this would be emailed to you.<br><br>"
. "For testing, use this link: <a href='$reset_link'>Reset Password</a>";
}
} else {
// For security, don't reveal if user exists or not
$message = "If an account exists with that username or email, password reset instructions have been sent.";
logger("Password reset requested for unknown identifier: $identifier");
}
}
}
// Close database connection
mysqli_close($db);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Forgot Password - GameServers.World</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: block;
padding: 0;
}
.content{
display:flex;
align-items:center;
justify-content:center;
min-height: calc(100vh - 140px);
padding:20px;
}
.reset-container {
background: white;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
width: 100%;
max-width: 420px;
padding: 40px;
}
.reset-header {
text-align: center;
margin-bottom: 30px;
}
.reset-header h1 {
font-size: 1.8rem;
color: #333;
margin-bottom: 8px;
}
.reset-header p {
color: #666;
font-size: 0.95rem;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
color: #333;
font-weight: 500;
font-size: 0.95rem;
}
.form-group input {
width: 100%;
padding: 12px 16px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.3s;
}
.form-group input:focus {
outline: none;
border-color: #667eea;
}
.btn-submit {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.btn-submit:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.btn-submit:active {
transform: translateY(0);
}
.alert {
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
font-size: 0.95rem;
}
.alert-error {
background-color: #fee;
border: 1px solid #fcc;
color: #c33;
}
.alert-success {
background-color: #efe;
border: 1px solid #cfc;
color: #3c3;
}
.footer-links {
margin-top: 24px;
text-align: center;
}
.footer-links a {
color: #667eea;
text-decoration: none;
font-size: 0.9rem;
}
.footer-links a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<?php include(__DIR__ . '/includes/top.php'); ?>
<?php include(__DIR__ . '/includes/menu.php'); ?>
<div class="content">
<div class="reset-container">
<div class="reset-header">
<h1>Forgot Password</h1>
<p>Enter your username or email to reset your password</p>
</div>
<?php if (!empty($error)): ?>
<div class="alert alert-error"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<?php if (!empty($message)): ?>
<div class="alert alert-success"><?php echo $message; ?></div>
<?php endif; ?>
<form method="POST" action="forgot_password.php">
<div class="form-group">
<label for="identifier">Username or Email</label>
<input type="text" id="identifier" name="identifier" required autofocus>
</div>
<button type="submit" name="request_reset" class="btn-submit">Request Password Reset</button>
</form>
<div class="footer-links">
<a href="login.php">Back to Login</a> |
<a href="index.php">Home</a>
</div>
</div>
</div>
</body>
<?php include(__DIR__ . '/includes/footer.php'); ?>
</html>

View file

@ -3,6 +3,6 @@
?>
<footer class="gsw-footer">
<div class="container-wide">
<a href="privacy.php">Privacy</a> | <a href="tos.php">TOS</a> | <a href="https://worlddomination.dev" target="_blank" rel="noopener">Worlddomination.dev</a>
<a href="privacy.php">Privacy</a> | <a href="tos.php">TOS</a> | <a href="server_status.php">Server Status</a> | <a href="https://worlddomination.dev" target="_blank" rel="noopener">Worlddomination.dev</a>
</div>
</footer>

View file

@ -51,6 +51,9 @@ if ($is_logged_in) {
<nav class="gsw-header-nav">
<a href="index.php" class="gsw-nav-link">Home</a>
<a href="serverlist.php" class="gsw-nav-link">Game Servers</a>
<?php if ($is_logged_in): ?>
<a href="my_servers.php" class="gsw-nav-link">My Servers</a>
<?php endif; ?>
<li>
<a href="cart.php">Cart
<?php

View file

@ -338,7 +338,8 @@ mysqli_close($db);
<button type="submit" name="login" class="btn-login">Sign In</button>
</form>
<div class="center mt-12">
<a href="register.php">Register</a>
<a href="register.php">Register</a> |
<a href="forgot_password.php">Forgot Password?</a>
</div>
<div class="divider">or</div>

138
_website/my_servers.php Normal file
View file

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Servers - GameServers.World</title>
</head>
<body>
<?php
// Require login for this page
require_once(__DIR__ . '/includes/login_required.php');
// Include database configuration
require_once(__DIR__ . '/includes/config.inc.php');
// Create database connection
$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
// Include top bar and menu
include(__DIR__ . '/includes/top.php');
include(__DIR__ . '/includes/menu.php');
// Get user ID from session
$user_id = intval($_SESSION['website_user_id']);
// Fetch user's active servers
// We'll look for homes assigned to this user
// The relationship is: ogp_billing_orders -> user_id and contains home_id references
// We need to join with ogp_home to get server details
$query = "SELECT
h.home_id,
h.home_name,
h.enabled,
rs.remote_server_name,
gc.game_name,
o.order_id,
o.status,
o.created_at,
o.invoice_duration,
DATE_ADD(o.created_at, INTERVAL
CASE
WHEN o.invoice_duration = 'month' THEN 30
WHEN o.invoice_duration = 'year' THEN 365
ELSE 30
END DAY
) as expiration_date,
bs.service_name,
bs.price_monthly
FROM ogp_home h
LEFT JOIN ogp_remote_servers rs ON h.remote_server_id = rs.remote_server_id
LEFT JOIN ogp_game_configs gc ON h.home_cfg_id = gc.home_cfg_id
LEFT JOIN ogp_billing_orders o ON h.user_id = o.user_id
LEFT JOIN ogp_billing_services bs ON o.service_id = bs.service_id
WHERE h.user_id = $user_id
ORDER BY h.home_id DESC";
$result = mysqli_query($db, $query);
?>
<div class="site-panel">
<div class="site-panel-title">My Game Servers</div>
<?php if ($result && mysqli_num_rows($result) > 0): ?>
<table class="cart-table">
<thead>
<tr>
<th>Server Name</th>
<th>Game</th>
<th>Location</th>
<th>Status</th>
<th>Expiration Date</th>
<th>Monthly Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php while ($server = mysqli_fetch_assoc($result)): ?>
<?php
$is_active = $server['enabled'] == 1;
$is_expired = strtotime($server['expiration_date']) < time();
$status_class = $is_active ? 'text-success' : 'text-danger';
$status_text = $is_active ? 'Active' : 'Inactive';
if ($is_expired) {
$status_text = 'Expired';
$status_class = 'text-danger';
}
?>
<tr>
<td><?php echo htmlspecialchars($server['home_name'] ?? 'Unknown'); ?></td>
<td><?php echo htmlspecialchars($server['game_name'] ?? $server['service_name'] ?? 'Unknown'); ?></td>
<td><?php echo htmlspecialchars($server['remote_server_name'] ?? 'Unknown'); ?></td>
<td class="<?php echo $status_class; ?>"><?php echo $status_text; ?></td>
<td><?php echo $server['expiration_date'] ? date('M d, Y', strtotime($server['expiration_date'])) : 'N/A'; ?></td>
<td><?php echo $server['price_monthly'] ? '$' . number_format($server['price_monthly'], 2) : 'N/A'; ?></td>
<td>
<?php if ($server['order_id']): ?>
<a href="renew_server.php?order_id=<?php echo urlencode($server['order_id']); ?>" class="btn-primary" style="padding:8px 16px;text-decoration:none;display:inline-block;border-radius:6px;">Renew</a>
<?php else: ?>
<span class="muted">N/A</span>
<?php endif; ?>
</td>
</tr>
<?php endwhile; ?>
</tbody>
</table>
<?php else: ?>
<div class="panel" style="text-align:center;padding:40px;">
<p style="font-size:1.2rem;margin-bottom:20px;">You don't have any game servers yet.</p>
<a href="serverlist.php" class="btn-primary" style="padding:12px 24px;text-decoration:none;display:inline-block;border-radius:8px;">Browse Game Servers</a>
</div>
<?php endif; ?>
</div>
<?php
// Close database connection
mysqli_close($db);
?>
<style>
.text-success {
color: #10b981;
font-weight: 600;
}
.text-danger {
color: #ef4444;
font-weight: 600;
}
</style>
</body>
<?php include(__DIR__ . '/includes/footer.php'); ?>
</html>

View file

@ -99,7 +99,7 @@ THIS IS WHAT WE DISPLAY ON THE SHOP PAGE AT THE TOP
<img src="<?php echo $row['img_url'] ;?>" width="460" height="225" >
<img src="../<?php echo $row['img_url'];?>" width="460" height="225" >
<br>
<?php echo $row['service_name'];?>
<br>
@ -136,7 +136,7 @@ if ($row['price_monthly'] == 0.0) {
?>
<div class="float-left decorative-bottom">
<img src="<?php echo $row['img_url'];?>" width=230 height=112 border=0 ">
<img src="../<?php echo $row['img_url'];?>" width=230 height=112 border=0 ">
<center><b> <?php echo $row['service_name'];?></b></center>
<?php

129
_website/renew_server.php Normal file
View file

@ -0,0 +1,129 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Renew Server - GameServers.World</title>
</head>
<body>
<?php
// Require login for this page
require_once(__DIR__ . '/includes/login_required.php');
// Include database configuration
require_once(__DIR__ . '/includes/config.inc.php');
// Create database connection
$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
// Include top bar and menu
include(__DIR__ . '/includes/top.php');
include(__DIR__ . '/includes/menu.php');
// Get order ID from URL
$order_id = isset($_GET['order_id']) ? intval($_GET['order_id']) : 0;
$user_id = intval($_SESSION['website_user_id']);
if ($order_id === 0) {
echo '<div class="site-panel"><p class="text-danger">Invalid order ID.</p></div>';
include(__DIR__ . '/includes/footer.php');
exit;
}
// Fetch order details
$query = "SELECT o.*, bs.service_name, bs.price_monthly, bs.price_year
FROM ogp_billing_orders o
LEFT JOIN ogp_billing_services bs ON o.service_id = bs.service_id
WHERE o.order_id = $order_id AND o.user_id = $user_id
LIMIT 1";
$result = mysqli_query($db, $query);
if (!$result || mysqli_num_rows($result) === 0) {
echo '<div class="site-panel"><p class="text-danger">Order not found or you do not have permission to renew this server.</p></div>';
mysqli_close($db);
include(__DIR__ . '/includes/footer.php');
exit;
}
$order = mysqli_fetch_assoc($result);
// Process renewal
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm_renewal'])) {
$duration = isset($_POST['duration']) ? $_POST['duration'] : 'month';
$price = ($duration === 'year') ? $order['price_year'] : $order['price_monthly'];
// Create a new order for renewal
// In a real system, this would redirect to payment gateway
// For now, we'll just show a message
$message = "Renewal initiated for " . htmlspecialchars($order['service_name']) . ". ";
$message .= "Duration: " . ($duration === 'year' ? '1 year' : '1 month') . ". ";
$message .= "Total: $" . number_format($price, 2) . ". ";
$message .= "In a production system, you would be redirected to payment processing.";
echo '<div class="site-panel"><div class="alert alert-success">' . $message . '</div></div>';
}
?>
<div class="site-panel">
<div class="site-panel-title">Renew Server</div>
<div class="panel" style="max-width:600px;margin:20px auto;">
<h3 style="margin-bottom:20px;"><?php echo htmlspecialchars($order['service_name']); ?></h3>
<form method="POST" action="">
<div class="form-group" style="margin-bottom:20px;">
<label style="display:block;margin-bottom:10px;">
<input type="radio" name="duration" value="month" checked>
1 Month - $<?php echo number_format($order['price_monthly'], 2); ?>
</label>
<?php if ($order['price_year'] > 0): ?>
<label style="display:block;">
<input type="radio" name="duration" value="year">
1 Year - $<?php echo number_format($order['price_year'], 2); ?>
</label>
<?php endif; ?>
</div>
<button type="submit" name="confirm_renewal" class="btn-primary" style="padding:12px 24px;border-radius:8px;">
Proceed to Payment
</button>
<a href="my_servers.php" style="margin-left:20px;color:#667eea;">Cancel</a>
</form>
</div>
</div>
<?php
// Close database connection
mysqli_close($db);
?>
<style>
.alert-success {
background-color: #d1fae5;
border: 1px solid #6ee7b7;
color: #065f46;
padding: 16px;
border-radius: 8px;
margin-bottom: 20px;
}
.form-group label {
cursor: pointer;
padding: 12px;
border: 2px solid #e1e8ed;
border-radius: 8px;
background: rgba(255,255,255,0.05);
}
.form-group label:hover {
background: rgba(255,255,255,0.1);
}
</style>
</body>
<?php include(__DIR__ . '/includes/footer.php'); ?>
</html>

296
_website/reset_password.php Normal file
View file

@ -0,0 +1,296 @@
<?php
// Start a separate session for the website
session_name("gameservers_website");
session_start();
// Include database configuration
require_once(__DIR__ . '/includes/config.inc.php');
// Create database connection
$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
// Logger function
function logger($logtext){
file_put_contents(__DIR__ . "/logfile.txt", $logtext . PHP_EOL, FILE_APPEND);
}
$message = '';
$error = '';
$token_valid = false;
$user_id = null;
// Get token from URL
$token = isset($_GET['token']) ? trim($_GET['token']) : '';
if (empty($token)) {
$error = 'Invalid or missing reset token.';
} else {
// Sanitize token
$token = mysqli_real_escape_string($db, $token);
// Verify token
$query = "SELECT user_id, expires, used FROM ogp_password_reset_tokens
WHERE token = '$token' LIMIT 1";
$result = mysqli_query($db, $query);
if ($result && mysqli_num_rows($result) === 1) {
$token_data = mysqli_fetch_assoc($result);
// Check if token is expired or used
if ($token_data['used'] == 1) {
$error = 'This password reset link has already been used.';
} elseif (strtotime($token_data['expires']) < time()) {
$error = 'This password reset link has expired. Please request a new one.';
} else {
$token_valid = true;
$user_id = $token_data['user_id'];
}
} else {
$error = 'Invalid password reset token.';
}
}
// Process password reset
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['reset_password']) && $token_valid) {
$new_password = $_POST['new_password'] ?? '';
$confirm_password = $_POST['confirm_password'] ?? '';
if (empty($new_password) || empty($confirm_password)) {
$error = 'Please enter and confirm your new password.';
} elseif ($new_password !== $confirm_password) {
$error = 'Passwords do not match.';
} elseif (strlen($new_password) < 8) {
$error = 'Password must be at least 8 characters long.';
} else {
// Hash the password (MD5 for panel compatibility, with modern hash shadow if column exists)
$md5_password = md5($new_password);
// Check if shadow column exists
$has_shadow = false;
$res_cols = mysqli_query($db, "SHOW COLUMNS FROM ogp_users LIKE 'users_pass_hash'");
if ($res_cols && mysqli_num_rows($res_cols) > 0) {
$has_shadow = true;
}
// Update password
if ($has_shadow) {
$modern_hash = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $db->prepare("UPDATE ogp_users SET users_passwd = ?, users_pass_hash = ? WHERE user_id = ?");
$stmt->bind_param('ssi', $md5_password, $modern_hash, $user_id);
} else {
$stmt = $db->prepare("UPDATE ogp_users SET users_passwd = ? WHERE user_id = ?");
$stmt->bind_param('si', $md5_password, $user_id);
}
if ($stmt->execute()) {
// Mark token as used
$stmt2 = $db->prepare("UPDATE ogp_password_reset_tokens SET used = 1 WHERE token = ?");
$stmt2->bind_param('s', $token);
$stmt2->execute();
$stmt2->close();
logger("Password reset completed for user_id: $user_id");
$message = 'Password has been reset successfully. You can now login with your new password.';
$token_valid = false; // Prevent form from showing again
} else {
$error = 'Failed to reset password. Please try again.';
}
$stmt->close();
}
}
// Close database connection
mysqli_close($db);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reset Password - GameServers.World</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: block;
padding: 0;
}
.content{
display:flex;
align-items:center;
justify-content:center;
min-height: calc(100vh - 140px);
padding:20px;
}
.reset-container {
background: white;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
width: 100%;
max-width: 420px;
padding: 40px;
}
.reset-header {
text-align: center;
margin-bottom: 30px;
}
.reset-header h1 {
font-size: 1.8rem;
color: #333;
margin-bottom: 8px;
}
.reset-header p {
color: #666;
font-size: 0.95rem;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
color: #333;
font-weight: 500;
font-size: 0.95rem;
}
.form-group input {
width: 100%;
padding: 12px 16px;
border: 2px solid #e1e8ed;
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.3s;
}
.form-group input:focus {
outline: none;
border-color: #667eea;
}
.btn-submit {
width: 100%;
padding: 14px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.btn-submit:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.btn-submit:active {
transform: translateY(0);
}
.alert {
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
font-size: 0.95rem;
}
.alert-error {
background-color: #fee;
border: 1px solid #fcc;
color: #c33;
}
.alert-success {
background-color: #efe;
border: 1px solid #cfc;
color: #3c3;
}
.footer-links {
margin-top: 24px;
text-align: center;
}
.footer-links a {
color: #667eea;
text-decoration: none;
font-size: 0.9rem;
}
.footer-links a:hover {
text-decoration: underline;
}
.password-requirements {
font-size: 0.85rem;
color: #666;
margin-top: 8px;
}
</style>
</head>
<body>
<?php include(__DIR__ . '/includes/top.php'); ?>
<?php include(__DIR__ . '/includes/menu.php'); ?>
<div class="content">
<div class="reset-container">
<div class="reset-header">
<h1>Reset Password</h1>
<p>Enter your new password</p>
</div>
<?php if (!empty($error)): ?>
<div class="alert alert-error"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<?php if (!empty($message)): ?>
<div class="alert alert-success"><?php echo $message; ?></div>
<?php endif; ?>
<?php if ($token_valid): ?>
<form method="POST" action="reset_password.php?token=<?php echo urlencode($token); ?>">
<div class="form-group">
<label for="new_password">New Password</label>
<input type="password" id="new_password" name="new_password" required autofocus>
<div class="password-requirements">Must be at least 8 characters long</div>
</div>
<div class="form-group">
<label for="confirm_password">Confirm Password</label>
<input type="password" id="confirm_password" name="confirm_password" required>
</div>
<button type="submit" name="reset_password" class="btn-submit">Reset Password</button>
</form>
<?php endif; ?>
<div class="footer-links">
<a href="login.php">Back to Login</a> |
<a href="index.php">Home</a>
</div>
</div>
</div>
</body>
<?php include(__DIR__ . '/includes/footer.php'); ?>
</html>

204
_website/server_status.php Normal file
View file

@ -0,0 +1,204 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Server Status - GameServers.World</title>
</head>
<body>
<?php
// Include database configuration
require_once(__DIR__ . '/includes/config.inc.php');
// Create database connection
$db = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
if (!$db) {
die("Connection failed: " . mysqli_connect_error());
}
// Include top bar and menu
include(__DIR__ . '/includes/top.php');
include(__DIR__ . '/includes/menu.php');
// Check if server status table exists, if not create it
$table_check = mysqli_query($db, "SHOW TABLES LIKE 'ogp_server_status'");
if (!$table_check || mysqli_num_rows($table_check) === 0) {
// Create table for server status updates
$create_table = "CREATE TABLE IF NOT EXISTS ogp_server_status (
status_id INT AUTO_INCREMENT PRIMARY KEY,
remote_server_id INT NOT NULL,
server_name VARCHAR(255) NOT NULL,
ip_address VARCHAR(45),
status ENUM('online', 'offline', 'maintenance') DEFAULT 'offline',
cpu_usage DECIMAL(5,2),
memory_usage DECIMAL(5,2),
disk_usage DECIMAL(5,2),
uptime VARCHAR(50),
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
notes TEXT,
INDEX idx_remote_server (remote_server_id),
UNIQUE KEY unique_server (remote_server_id)
)";
mysqli_query($db, $create_table);
}
// Fetch all remote servers and their status
$query = "SELECT
rs.remote_server_id,
rs.remote_server_name,
rs.agent_ip,
rs.enabled,
ss.status,
ss.cpu_usage,
ss.memory_usage,
ss.disk_usage,
ss.uptime,
ss.last_updated,
ss.notes
FROM ogp_remote_servers rs
LEFT JOIN ogp_server_status ss ON rs.remote_server_id = ss.remote_server_id
ORDER BY rs.remote_server_name";
$result = mysqli_query($db, $query);
?>
<div class="site-panel">
<div class="site-panel-title">Server Status</div>
<div style="margin-bottom:20px;text-align:center;">
<p style="color:rgba(255,255,255,0.7);">Real-time status of our game server infrastructure</p>
</div>
<?php if ($result && mysqli_num_rows($result) > 0): ?>
<table class="cart-table">
<thead>
<tr>
<th>Server Name</th>
<th>Location/IP</th>
<th>Status</th>
<th>CPU Usage</th>
<th>Memory Usage</th>
<th>Disk Usage</th>
<th>Uptime</th>
<th>Last Updated</th>
</tr>
</thead>
<tbody>
<?php while ($server = mysqli_fetch_assoc($result)): ?>
<?php
// Determine status
$status = $server['status'] ?? 'unknown';
if ($server['enabled'] == 0) {
$status = 'maintenance';
}
// Status styling
$status_class = '';
$status_display = ucfirst($status);
switch ($status) {
case 'online':
$status_class = 'status-online';
break;
case 'offline':
$status_class = 'status-offline';
break;
case 'maintenance':
$status_class = 'status-maintenance';
break;
default:
$status_class = 'status-unknown';
$status_display = 'Unknown';
}
// Format last updated
$last_updated = 'Never';
if ($server['last_updated']) {
$timestamp = strtotime($server['last_updated']);
$diff = time() - $timestamp;
if ($diff < 60) {
$last_updated = 'Just now';
} elseif ($diff < 3600) {
$last_updated = floor($diff / 60) . ' min ago';
} elseif ($diff < 86400) {
$last_updated = floor($diff / 3600) . ' hours ago';
} else {
$last_updated = date('M d, Y', $timestamp);
}
}
?>
<tr>
<td><strong><?php echo htmlspecialchars($server['remote_server_name']); ?></strong></td>
<td><?php echo htmlspecialchars($server['agent_ip'] ?? 'N/A'); ?></td>
<td>
<span class="status-badge <?php echo $status_class; ?>">
<?php echo $status_display; ?>
</span>
</td>
<td><?php echo $server['cpu_usage'] ? number_format($server['cpu_usage'], 1) . '%' : 'N/A'; ?></td>
<td><?php echo $server['memory_usage'] ? number_format($server['memory_usage'], 1) . '%' : 'N/A'; ?></td>
<td><?php echo $server['disk_usage'] ? number_format($server['disk_usage'], 1) . '%' : 'N/A'; ?></td>
<td><?php echo htmlspecialchars($server['uptime'] ?? 'N/A'); ?></td>
<td><?php echo $last_updated; ?></td>
</tr>
<?php if (!empty($server['notes'])): ?>
<tr>
<td colspan="8" style="padding-left:40px;font-size:0.9rem;color:rgba(255,255,255,0.7);">
<em><?php echo htmlspecialchars($server['notes']); ?></em>
</td>
</tr>
<?php endif; ?>
<?php endwhile; ?>
</tbody>
</table>
<?php else: ?>
<div class="panel" style="text-align:center;padding:40px;">
<p style="font-size:1.2rem;">No server status information available.</p>
</div>
<?php endif; ?>
<div style="margin-top:30px;text-align:center;color:rgba(255,255,255,0.6);font-size:0.9rem;">
<p>Server status is updated automatically every 5 minutes.</p>
<p style="margin-top:10px;">If you experience any issues, please contact support.</p>
</div>
</div>
<?php
// Close database connection
mysqli_close($db);
?>
<style>
.status-badge {
display: inline-block;
padding: 4px 12px;
border-radius: 12px;
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
}
.status-online {
background-color: #10b981;
color: white;
}
.status-offline {
background-color: #ef4444;
color: white;
}
.status-maintenance {
background-color: #f59e0b;
color: white;
}
.status-unknown {
background-color: #6b7280;
color: white;
}
</style>
</body>
<?php include(__DIR__ . '/includes/footer.php'); ?>
</html>

View file

@ -59,7 +59,7 @@ include(__DIR__ . '/includes/menu.php');
?>
<br>
<a href="order.php?service_id=<?php echo urlencode($row['service_id']); ?>" class="gsw-btn">Order Server</a>
<a href="order.php?service_id=<?php echo urlencode($row['service_id']); ?>" class="gsw-btn" style="display:inline-block;padding:12px 24px;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:white;text-decoration:none;border-radius:8px;font-weight:600;transition:transform 0.2s;">Order Now</a>
</div>
<?php else: ?>
<!-- Single service detail view -->