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

230
APACHE_SETUP.md Normal file
View file

@ -0,0 +1,230 @@
# Apache Configuration Files for GSP
This directory contains Apache virtual host configuration files for deploying the GameServerPanel and its associated services.
## Configuration Files
### 1. panel.conf
Configuration for the main Open Game Panel dashboard.
- **Domain**: panel.yourdomain.com
- **Document Root**: /var/www/GSP
- **Purpose**: Main panel interface for server management
### 2. website.conf
Configuration for the GameServers.World storefront website.
- **Domain**: gameservers.world
- **Document Root**: /var/www/GSP/_website
- **Purpose**: Customer-facing storefront for ordering game servers
- **Features**:
- Separate session handling
- Protected includes and data directories
- Static asset caching
- Security headers
### 3. fileserver.conf
Configuration for the file server for game downloads.
- **Domain**: files.yourdomain.com
- **Document Root**: /var/www/fileserver
- **Purpose**: File distribution for game server installations
- **Features**:
- Directory browsing enabled
- Large file support
- Script execution disabled in upload directories
## Installation Instructions
### 1. Copy Configuration Files
Copy the configuration files to Apache's sites-available directory:
```bash
# For Ubuntu/Debian
sudo cp panel.conf /etc/apache2/sites-available/
sudo cp website.conf /etc/apache2/sites-available/
sudo cp fileserver.conf /etc/apache2/sites-available/
# For CentOS/RHEL
sudo cp panel.conf /etc/httpd/conf.d/
sudo cp website.conf /etc/httpd/conf.d/
sudo cp fileserver.conf /etc/httpd/conf.d/
```
### 2. Update Configuration
Edit each configuration file to match your environment:
1. Replace `yourdomain.com` with your actual domain
2. Verify document root paths match your installation
3. Update SSL certificate paths (if using HTTPS)
```bash
sudo nano /etc/apache2/sites-available/panel.conf
sudo nano /etc/apache2/sites-available/website.conf
sudo nano /etc/apache2/sites-available/fileserver.conf
```
### 3. Enable Sites (Ubuntu/Debian)
```bash
sudo a2ensite panel.conf
sudo a2ensite website.conf
sudo a2ensite fileserver.conf
```
### 4. Enable Required Apache Modules
```bash
# Ubuntu/Debian
sudo a2enmod rewrite
sudo a2enmod headers
sudo a2enmod expires
sudo a2enmod deflate
sudo a2enmod ssl # if using HTTPS
# CentOS/RHEL - most modules are enabled by default
# Check /etc/httpd/conf.modules.d/ for module configuration
```
### 5. Create File Server Directory
```bash
sudo mkdir -p /var/www/fileserver
sudo chown -R www-data:www-data /var/www/fileserver # Ubuntu/Debian
# OR
sudo chown -R apache:apache /var/www/fileserver # CentOS/RHEL
```
### 6. Test Configuration
```bash
# Ubuntu/Debian
sudo apache2ctl configtest
# CentOS/RHEL
sudo apachectl configtest
```
### 7. Restart Apache
```bash
# Ubuntu/Debian
sudo systemctl restart apache2
# CentOS/RHEL
sudo systemctl restart httpd
```
## SSL/HTTPS Configuration
Each configuration file includes commented-out HTTPS sections. To enable SSL:
1. Obtain SSL certificates (using Let's Encrypt, purchased certificates, etc.)
2. Uncomment the HTTPS VirtualHost sections
3. Update certificate paths
4. Enable SSL module (see step 4 above)
5. Restart Apache
### Using Let's Encrypt
```bash
# Install Certbot
sudo apt-get install certbot python3-certbot-apache # Ubuntu/Debian
sudo yum install certbot python3-certbot-apache # CentOS/RHEL
# Obtain certificates
sudo certbot --apache -d panel.yourdomain.com
sudo certbot --apache -d gameservers.world -d www.gameservers.world
sudo certbot --apache -d files.yourdomain.com
# Certbot will automatically update your Apache configuration
```
## DNS Configuration
Make sure your DNS records point to your server:
```
panel.yourdomain.com A YOUR_SERVER_IP
gameservers.world A YOUR_SERVER_IP
www.gameservers.world A YOUR_SERVER_IP
files.yourdomain.com A YOUR_SERVER_IP
```
## Firewall Configuration
Ensure ports 80 and 443 are open:
```bash
# UFW (Ubuntu)
sudo ufw allow 'Apache Full'
# firewalld (CentOS/RHEL)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
# iptables
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
```
## Troubleshooting
### Permission Issues
```bash
# Fix ownership
sudo chown -R www-data:www-data /var/www/GSP # Ubuntu/Debian
sudo chown -R apache:apache /var/www/GSP # CentOS/RHEL
# Fix permissions
sudo find /var/www/GSP -type d -exec chmod 755 {} \;
sudo find /var/www/GSP -type f -exec chmod 644 {} \;
```
### Check Logs
```bash
# Apache error logs
sudo tail -f /var/log/apache2/error.log # Ubuntu/Debian
sudo tail -f /var/log/httpd/error_log # CentOS/RHEL
# Site-specific logs
sudo tail -f /var/log/apache2/ogp-panel-error.log
sudo tail -f /var/log/apache2/gameservers-website-error.log
sudo tail -f /var/log/apache2/fileserver-error.log
```
### Test PHP
Create a test file:
```bash
echo "<?php phpinfo(); ?>" | sudo tee /var/www/GSP/info.php
```
Visit http://panel.yourdomain.com/info.php
**Important**: Delete this file after testing!
## Security Recommendations
1. **Always use HTTPS in production**
2. **Keep Apache and PHP updated**
3. **Configure firewall properly**
4. **Use strong passwords in database configurations**
5. **Regularly backup your data**
6. **Monitor logs for suspicious activity**
7. **Consider using fail2ban to prevent brute force attacks**
8. **Restrict access to sensitive directories**
## Support
For issues specific to:
- **Panel**: Check the main GSP documentation
- **Website**: Review _website/README.md and related documentation
- **Apache**: Consult Apache documentation at https://httpd.apache.org/docs/
## License
These configuration files are part of the Open Game Panel project and follow the same license as the main project.

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 -->

118
fileserver.conf Normal file
View file

@ -0,0 +1,118 @@
<VirtualHost *:80>
# File server configuration for game server file downloads
ServerName files.yourdomain.com
ServerAlias files.*
# Document root points to the file server directory
# Change this path to your actual file server location
DocumentRoot /var/www/fileserver
# Directory configuration
<Directory /var/www/fileserver>
Options +Indexes +FollowSymLinks
AllowOverride None
Require all granted
# Enable directory browsing with custom index
DirectoryIndex index.html index.php
# Fancy indexing for better file browsing
IndexOptions FancyIndexing HTMLTable VersionSort NameWidth=* DescriptionWidth=*
IndexOrderDefault Descending Date
# Add descriptions for common file types
AddDescription "Game Server Files" *.zip *.tar.gz *.rar
AddDescription "Configuration File" *.cfg *.ini *.conf
AddDescription "Script File" *.sh *.bat
AddDescription "Text Document" *.txt *.md
# Set icons for file types
AddIconByType (TXT,/icons/text.png) text/*
AddIconByType (IMG,/icons/image2.png) image/*
AddIcon /icons/compressed.png .zip .tar .gz .rar .7z
AddIcon /icons/script.png .sh .bat .ps1
</Directory>
# Prevent execution of scripts in upload directories
<Directory /var/www/fileserver/uploads>
<FilesMatch "\.(php|php3|php4|php5|phtml|pl|py|jsp|asp|sh|cgi)$">
Require all denied
</FilesMatch>
</Directory>
# Set proper MIME types
<IfModule mod_mime.c>
AddType application/octet-stream .zip .tar .gz .rar .7z
AddType text/plain .txt .log .cfg .ini .conf
</IfModule>
# Enable large file downloads
LimitRequestBody 0
# Error and access logs
ErrorLog ${APACHE_LOG_DIR}/fileserver-error.log
CustomLog ${APACHE_LOG_DIR}/fileserver-access.log combined
# Security headers
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>
# Compression for text files
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
</IfModule>
# Cache static files
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 week"
</IfModule>
# Optional: Bandwidth limiting (requires mod_bw or similar)
# Uncomment and adjust as needed
#<IfModule mod_bw.c>
# BandWidthModule On
# ForceBandWidthModule On
# BandWidth all 512000
# MinBandWidth all 50000
#</IfModule>
</VirtualHost>
# SSL/HTTPS configuration (uncomment and configure after obtaining SSL certificate)
#<VirtualHost *:443>
# ServerName files.yourdomain.com
# ServerAlias files.*
#
# DocumentRoot /var/www/fileserver
#
# SSLEngine on
# SSLCertificateFile /etc/ssl/certs/files.yourdomain.com.crt
# SSLCertificateKeyFile /etc/ssl/private/files.yourdomain.com.key
# SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt
#
# <Directory /var/www/fileserver>
# Options +Indexes +FollowSymLinks
# AllowOverride None
# Require all granted
# DirectoryIndex index.html index.php
# IndexOptions FancyIndexing HTMLTable VersionSort NameWidth=* DescriptionWidth=*
# IndexOrderDefault Descending Date
# </Directory>
#
# <Directory /var/www/fileserver/uploads>
# <FilesMatch "\.(php|php3|php4|php5|phtml|pl|py|jsp|asp|sh|cgi)$">
# Require all denied
# </FilesMatch>
# </Directory>
#
# ErrorLog ${APACHE_LOG_DIR}/fileserver-ssl-error.log
# CustomLog ${APACHE_LOG_DIR}/fileserver-ssl-access.log combined
#
# <IfModule mod_headers.c>
# Header always set X-Content-Type-Options "nosniff"
# Header always set X-Frame-Options "SAMEORIGIN"
# Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# </IfModule>
#</VirtualHost>

61
panel.conf Normal file
View file

@ -0,0 +1,61 @@
<VirtualHost *:80>
# Panel domain configuration for Open Game Panel
ServerName panel.yourdomain.com
ServerAlias panel.*
# Document root points to the GSP panel installation
DocumentRoot /var/www/GSP
# Directory configuration
<Directory /var/www/GSP>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# PHP configuration
<IfModule mod_php7.c>
php_value upload_max_filesize 100M
php_value post_max_size 100M
php_value max_execution_time 300
php_value max_input_time 300
</IfModule>
</Directory>
# Error and access logs
ErrorLog ${APACHE_LOG_DIR}/ogp-panel-error.log
CustomLog ${APACHE_LOG_DIR}/ogp-panel-access.log combined
# Security headers
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
</IfModule>
# Disable directory listing
<Directory /var/www/GSP>
Options -Indexes
</Directory>
</VirtualHost>
# SSL/HTTPS configuration (uncomment and configure after obtaining SSL certificate)
#<VirtualHost *:443>
# ServerName panel.yourdomain.com
# ServerAlias panel.*
#
# DocumentRoot /var/www/GSP
#
# SSLEngine on
# SSLCertificateFile /etc/ssl/certs/panel.yourdomain.com.crt
# SSLCertificateKeyFile /etc/ssl/private/panel.yourdomain.com.key
# SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt
#
# <Directory /var/www/GSP>
# Options -Indexes +FollowSymLinks
# AllowOverride All
# Require all granted
# </Directory>
#
# ErrorLog ${APACHE_LOG_DIR}/ogp-panel-ssl-error.log
# CustomLog ${APACHE_LOG_DIR}/ogp-panel-ssl-access.log combined
#</VirtualHost>

109
website.conf Normal file
View file

@ -0,0 +1,109 @@
<VirtualHost *:80>
# Website domain configuration for GameServers.World storefront
ServerName gameservers.world
ServerAlias www.gameservers.world
# Document root points to the _website directory
DocumentRoot /var/www/GSP/_website
# Directory configuration
<Directory /var/www/GSP/_website>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
DirectoryIndex index.php index.html
# PHP configuration
<IfModule mod_php7.c>
php_value upload_max_filesize 50M
php_value post_max_size 50M
php_value max_execution_time 180
php_value max_input_time 180
php_value session.name "gameservers_website"
</IfModule>
</Directory>
# Restrict access to sensitive files and directories
<DirectoryMatch "^/var/www/GSP/_website/(includes|data|tools)">
Require all denied
</DirectoryMatch>
# Protect sensitive files
<FilesMatch "^(config\.inc\.php|.*\.log|.*\.md)$">
Require all denied
</FilesMatch>
# Error and access logs
ErrorLog ${APACHE_LOG_DIR}/gameservers-website-error.log
CustomLog ${APACHE_LOG_DIR}/gameservers-website-access.log combined
# Security headers
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
# Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
# Cache static assets
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 week"
ExpiresByType application/javascript "access plus 1 week"
</IfModule>
</VirtualHost>
# SSL/HTTPS configuration (uncomment and configure after obtaining SSL certificate)
#<VirtualHost *:443>
# ServerName gameservers.world
# ServerAlias www.gameservers.world
#
# DocumentRoot /var/www/GSP/_website
#
# SSLEngine on
# SSLCertificateFile /etc/ssl/certs/gameservers.world.crt
# SSLCertificateKeyFile /etc/ssl/private/gameservers.world.key
# SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt
#
# <Directory /var/www/GSP/_website>
# Options -Indexes +FollowSymLinks
# AllowOverride All
# Require all granted
# DirectoryIndex index.php index.html
# </Directory>
#
# <DirectoryMatch "^/var/www/GSP/_website/(includes|data|tools)">
# Require all denied
# </DirectoryMatch>
#
# <FilesMatch "^(config\.inc\.php|.*\.log|.*\.md)$">
# Require all denied
# </FilesMatch>
#
# ErrorLog ${APACHE_LOG_DIR}/gameservers-website-ssl-error.log
# CustomLog ${APACHE_LOG_DIR}/gameservers-website-ssl-access.log combined
#
# # Security headers
# <IfModule mod_headers.c>
# Header always set X-Content-Type-Options "nosniff"
# Header always set X-Frame-Options "SAMEORIGIN"
# Header always set X-XSS-Protection "1; mode=block"
# Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# </IfModule>
#</VirtualHost>
# Redirect www to non-www (optional, uncomment if desired)
#<VirtualHost *:80>
# ServerName www.gameservers.world
# Redirect permanent / http://gameservers.world/
#</VirtualHost>