No changes

This commit is contained in:
Frank Harris 2025-09-11 13:29:15 -04:00
parent 8680a02b13
commit b6b398f5bf
17374 changed files with 2475441 additions and 0 deletions

View file

@ -0,0 +1,320 @@
<?php
// gameservers.world admin — mysqli only, bulk + per-row update, image base URL + small button
global $db;
/* === Configure your site base URL for image previews (MUST end with or without slash; we'll normalize) === */
$SITE_BASE_URL = 'http://gameservers.world/';
/* include DB (must provide $db as mysqli) */
$try = [
__DIR__ . "db.php",
(defined('ABSPATH') ? ABSPATH : $_SERVER['DOCUMENT_ROOT']) . "db.php",
"db.php"
];
foreach ($try as $p) { if (empty($db) && is_readable($p)) include_once $p; }
/* show errors to WP admins during setup */
if (function_exists('current_user_can') && current_user_can('manage_options')) { @ini_set('display_errors','1'); error_reporting(E_ALL); }
/* guards & helpers */
if (!($db instanceof mysqli)) {
echo '<div style="border:1px solid #c00;padding:10px;margin:10px 0;">
<b>Admin panel error:</b> <code>$db</code> must be a <code>mysqli</code> connection (check panel/_db.php).
</div>';
return;
}
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
function esc_mysqli($db, $v){ return $db->real_escape_string($v); }
function fetch_all_assoc($db, $sql){
$res = $db->query($sql);
return $res ? $res->fetch_all(MYSQLI_ASSOC) : [];
}
function col_exists($db, $table, $col){
$res = $db->query("SHOW COLUMNS FROM `$table` LIKE '".$db->real_escape_string($col)."'");
return ($res && $res->num_rows > 0);
}
function parse_id_list($s){
$tokens = preg_split('/\s+/', trim((string)$s));
$out = [];
foreach ($tokens as $t) {
if ($t === '') continue;
if (preg_match('/^\d+$/', $t)) $out[] = (int)$t;
}
return array_values(array_unique($out));
}
/* URL helpers for image preview */
function is_abs_url($u){ return (bool)preg_match('~^(?:https?:)?//|^data:~i', (string)$u); }
function join_base($base, $path){
$base = rtrim((string)$base, '/');
$path = ltrim((string)$path, '/');
return $base !== '' ? $base.'/'.$path : $path;
}
/* which column holds space-separated locations */
$locationCol = col_exists($db, 'ogp_billing_services', 'remote_server_id') ? 'remote_server_id' :
(col_exists($db, 'ogp_billing_services', 'remote_server') ? 'remote_server' : 'remote_server_id');
$flash = [];
/* A) Update global server location enable flags */
if (isset($_POST['update_remote_servers'])) {
$enabledIds = array_map('intval', $_POST['rs'] ?? []);
$enabledSet = array_flip($enabledIds);
$allIds = fetch_all_assoc($db, "SELECT remote_server_id FROM ogp_remote_servers");
foreach ($allIds as $row) {
$id = (int)$row['remote_server_id'];
$e = isset($enabledSet[$id]) ? 1 : 0;
$db->query("UPDATE ogp_remote_servers SET enabled={$e} WHERE remote_server_id={$id}");
}
$flash[] = "Server locations updated.";
}
/* helper: update one service row from posted array */
function update_service_row(mysqli $db, string $locationCol, int $sid, array $svc){
$name = esc_mysqli($db, trim($svc['service_name'] ?? ''));
$price = esc_mysqli($db, trim($svc['price_monthly'] ?? '0.00'));
$img = esc_mysqli($db, trim($svc['img_url'] ?? ''));
$en = !empty($svc['enabled']) ? 1 : 0;
$minSlots = max(1, (int)($svc['slot_min_qty'] ?? 1));
$maxSlots = max($minSlots, (int)($svc['slot_max_qty'] ?? $minSlots));
$selected = [];
if (!empty($svc['locations']) && is_array($svc['locations'])) {
$selected = array_map('intval', $svc['locations']);
$selected = array_values(array_unique($selected));
}
$primary = isset($svc['primary_location']) ? (int)$svc['primary_location'] : 0;
if ($primary && in_array($primary, $selected, true)) {
$selected = array_values(array_diff($selected, [$primary]));
array_unshift($selected, $primary);
}
$locList = implode(' ', $selected);
$locListEsc = esc_mysqli($db, $locList);
$sql = "UPDATE ogp_billing_services
SET service_name='{$name}',
`{$locationCol}`='{$locListEsc}',
slot_min_qty={$minSlots},
slot_max_qty={$maxSlots},
price_monthly='{$price}',
img_url='{$img}',
enabled={$en}
WHERE service_id={$sid}";
$db->query($sql);
}
/* B1) PER-ROW UPDATE */
if (isset($_POST['update_single']) && isset($_POST['service']) && is_array($_POST['service'])) {
$sid = (int)$_POST['update_single'];
if (isset($_POST['service'][$sid])) {
update_service_row($db, $locationCol, $sid, $_POST['service'][$sid]);
$flash[] = "Service #{$sid} updated.";
}
}
/* B2) BULK UPDATE (single button at bottom) */
if (isset($_POST['bulk_update']) && !empty($_POST['service']) && is_array($_POST['service'])) {
foreach ($_POST['service'] as $sid => $svc) {
update_service_row($db, $locationCol, (int)$sid, (array)$svc);
}
$flash[] = "All edited services have been updated.";
}
/* C) Remove a service (separate small form) */
if (isset($_POST['remove_service'], $_POST['service_id_remove'])) {
$sid = (int)$_POST['service_id_remove'];
$db->query("DELETE FROM ogp_billing_services WHERE service_id={$sid}");
$flash[] = "Service #{$sid} removed.";
}
/* fetch data for UI */
$remoteServers = fetch_all_assoc($db, "SELECT remote_server_id, remote_server_name, enabled FROM ogp_remote_servers ORDER BY remote_server_name");
$services = fetch_all_assoc($db, "SELECT service_id, service_name, `{$locationCol}` AS locs, slot_min_qty, slot_max_qty, price_monthly, img_url, enabled FROM ogp_billing_services ORDER BY service_name");
?>
<?php if ($flash): ?>
<div style="padding:8px;border:1px solid #ccc;margin:10px 0;"><?php foreach($flash as $m) echo "<div>".h($m)."</div>"; ?></div>
<?php endif; ?>
<h2>Enable/Disable Server Locations (Global)</h2>
<form method="post" action="">
<input type="hidden" name="update_remote_servers" value="1">
<div style="display:flex;flex-wrap:wrap;gap:10px;">
<?php foreach ($remoteServers as $rs): ?>
<label style="border:1px solid #ddd;border-radius:6px;padding:6px 10px;min-width:240px;">
<input type="checkbox" name="rs[]" value="<?php echo (int)$rs['remote_server_id']; ?>" <?php echo ((int)$rs['enabled']===1?'checked':''); ?>>
<b><?php echo h($rs['remote_server_name']); ?></b>
<small style="color:#666;">(ID: <?php echo (int)$rs['remote_server_id']; ?>)</small>
</label>
<?php endforeach; ?>
</div>
<div style="margin-top:10px;"><button type="submit">Update Enabled Servers</button></div>
</form>
<hr style="margin:20px 0;">
<h2>Current Services</h2>
<?php if (!$services): ?>
<p>No services found.</p>
<?php else: ?>
<!-- SINGLE BULK FORM FOR ALL SERVICES -->
<form method="post" action="">
<table class="center" style="text-align:center;width:100%;border-collapse:collapse;">
<thead>
<tr>
<th style="border-bottom:1px solid #ddd;padding:6px;">Enabled</th>
<th style="border-bottom:1px solid #ddd;padding:6px;">Service Name <small style="color:#777;">(ID below)</small></th>
<th style="border-bottom:1px solid #ddd;padding:6px;">Min Slots</th>
<th style="border-bottom:1px solid #ddd;padding:6px;">Max Slots</th>
<th style="border-bottom:1px solid #ddd;padding:6px;">Price (Monthly)</th>
<th style="border-bottom:1px solid #ddd;padding:6px;">Thumbnail URL</th>
<th style="border-bottom:1px solid #ddd;padding:6px;">Preview</th>
<th style="border-bottom:1px solid #ddd;padding:6px;">Update Row</th>
</tr>
</thead>
<tbody>
<?php foreach ($services as $row): ?>
<?php
$sid = (int)$row['service_id'];
$selected = parse_id_list($row['locs'] ?? '');
$primary = $selected[0] ?? 0; // first ID is "primary"
$selSet = array_flip($selected);
$imgUrl = trim((string)$row['img_url']);
$displayUrl = '';
if ($imgUrl !== '') {
$displayUrl = is_abs_url($imgUrl) ? $imgUrl : join_base($SITE_BASE_URL, $imgUrl);
}
?>
<!-- MAIN ROW (no bottom border) -->
<tr>
<!-- Enabled first -->
<td style="padding:6px;">
<input type="hidden" name="service[<?php echo $sid; ?>][enabled]" value="0">
<input type="checkbox" name="service[<?php echo $sid; ?>][enabled]" value="1" <?php echo ((int)$row['enabled']===1?'checked':''); ?>>
</td>
<!-- Service name (with tiny ID under it) -->
<td style="padding:6px; text-align:left;">
<input type="text" name="service[<?php echo $sid; ?>][service_name]" value="<?php echo h($row['service_name']); ?>" style="min-width:260px;">
<div style="color:#777; font-size:12px; margin-top:2px;">ID: <?php echo $sid; ?></div>
</td>
<td style="padding:6px;">
<input type="number" name="service[<?php echo $sid; ?>][slot_min_qty]" value="<?php echo (int)$row['slot_min_qty']; ?>" min="1" step="1" style="width:90px;">
</td>
<td style="padding:6px;">
<input type="number" name="service[<?php echo $sid; ?>][slot_max_qty]" value="<?php echo (int)$row['slot_max_qty']; ?>" min="1" step="1" style="width:90px;">
</td>
<td style="padding:6px;">
<input type="text" name="service[<?php echo $sid; ?>][price_monthly]" value="<?php echo h($row['price_monthly']); ?>" size="8">
</td>
<!-- Thumbnail URL input -->
<td style="padding:6px; vertical-align:top;">
<input type="text" name="service[<?php echo $sid; ?>][img_url]" value="<?php echo h($row['img_url']); ?>" style="min-width:240px;">
</td>
<!-- Preview (uses BASE + relative path) -->
<td style="padding:6px; vertical-align:top;">
<?php if ($displayUrl !== ''): ?>
<img src="<?php echo h($displayUrl); ?>" alt="preview" loading="lazy"
style="max-height:48px; max-width:120px; border:1px solid #eee; display:block;"
onerror="this.style.display='none'">
<?php else: ?>
<span style="color:#aaa;">(no image)</span>
<?php endif; ?>
</td>
<!-- Per-row Update (smaller) -->
<td style="padding:6px;">
<button type="submit" name="update_single" value="<?php echo $sid; ?>"
style="padding:3px 8px; font-size:12px;">Update Row</button>
</td>
</tr>
<!-- LOCATIONS ROW (single bottom divider) -->
<tr>
<td colspan="8" style="border-bottom:1px solid #f0f0f0; padding:8px 6px; text-align:left;">
<div class="locs-box" data-sid="<?php echo $sid; ?>" style="display:flex; flex-wrap:wrap; gap:8px;">
<?php foreach ($remoteServers as $rs): ?>
<?php
$rid = (int)$rs['remote_server_id'];
$isChecked = isset($selSet[$rid]);
$isPrimary = ($primary === $rid);
?>
<label style="border:1px solid #eee;border-radius:6px;padding:6px 8px; display:inline-flex; align-items:center;">
<input type="checkbox" class="locchk" data-sid="<?php echo $sid; ?>"
name="service[<?php echo $sid; ?>][locations][]" value="<?php echo $rid; ?>"
<?php echo $isChecked ? 'checked' : ''; ?> style="margin-right:6px;">
<?php echo h($rs['remote_server_name']); ?> (<?php echo $rid; ?>)
<span style="margin-left:10px;">
<input type="radio" class="locprim" data-sid="<?php echo $sid; ?>"
name="service[<?php echo $sid; ?>][primary_location]" value="<?php echo $rid; ?>"
<?php echo $isPrimary ? 'checked' : ''; ?> <?php echo $isChecked ? '' : 'disabled'; ?>>
<small>Primary</small>
</span>
<?php if ((int)$rs['enabled'] === 0): ?>
<small style="color:#a00; margin-left:8px;">[Globally disabled]</small>
<?php endif; ?>
</label>
<?php endforeach; ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div style="margin-top:14px; text-align:right;">
<button type="submit" name="bulk_update" value="1">Update All</button>
</div>
</form>
<h3 style="margin-top:20px;">Remove a Service</h3>
<form method="post" action="" style="display:flex;gap:8px;align-items:center;">
<input type="hidden" name="remove_service" value="1">
<select name="service_id_remove">
<?php foreach ($services as $s): ?>
<option value="<?php echo (int)$s['service_id']; ?>">
<?php echo h($s['service_name']); ?> (ID: <?php echo (int)$s['service_id']; ?>)
</option>
<?php endforeach; ?>
</select>
<button type="submit" onclick="return confirm('Remove this service? This cannot be undone.')">Remove</button>
</form>
<?php endif; ?>
<!-- JS: Per-row: enable/disable Primary radios based on whether that location is checked -->
<script>
document.querySelectorAll('.locs-box').forEach(function(box){
const sid = box.getAttribute('data-sid');
const checks = box.querySelectorAll('input.locchk[data-sid="'+sid+'"]');
function refreshRadios() {
checks.forEach(function(chk){
const rid = chk.value;
const rad = box.querySelector('input.locprim[data-sid="'+sid+'"][value="'+rid+'"]');
if (!rad) return;
if (chk.checked) {
rad.disabled = false;
} else {
if (rad.checked) rad.checked = false;
rad.disabled = true;
}
});
}
checks.forEach(chk => chk.addEventListener('change', refreshRadios));
refreshRadios();
});
</script>

View file

@ -0,0 +1,321 @@
<?php
/***********************
* Assistant Chat (Full History) PHP + cURL
* - Persistent thread in session
* - Full history render with Question / Answer labels
* - SSL verification disabled (your hosting constraint)
* - Citations: filename + page (when available)
***********************/
// Debug (disable on production)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
/* ------------------- CONFIG ------------------- */
$OPENAI_API_KEY = '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';
$ASSISTANT_ID = 'asst_RAhtGzcy6higJeMwomZSqVjM'; // <-- set to your existing assistant
$OPENAI_BASE_URL = 'https://api.openai.com/v1';
$OPENAI_BETA_HDR = 'assistants=v2'; // required for Assistants v2
$REQUEST_TIMEOUT = 30; // seconds for cURL calls
$RUN_POLL_DELAY = 500000; // microseconds between run polls (0.5s)
$RUN_POLL_MAX = 40; // max polls (~20s total); adjust as needed
/* ---------------------------------------------- */
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (!isset($_SESSION['thread_id'])) {
$_SESSION['thread_id'] = null;
}
/** HTML escape helper */
function h($v) { return htmlspecialchars((string)$v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); }
/** Low-level OpenAI request helper */
function openai_request($method, $endpoint, $payload = null, $query = []) {
global $OPENAI_API_KEY;
$url = "https://api.openai.com/v1" . $endpoint;
if (!empty($query)) $url .= '?' . http_build_query($query);
$headers = [
"Content-Type: application/json",
"Authorization: Bearer {$OPENAI_API_KEY}",
"OpenAI-Beta: assistants=v2"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Host requires SSL verification disabled
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
if (!is_null($payload)) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
$resp = curl_exec($ch);
if ($resp === false) {
$err = curl_error($ch);
curl_close($ch);
throw new RuntimeException("cURL error: {$err}");
}
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($resp, true);
if ($code >= 400) {
$msg = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown API error';
throw new RuntimeException("OpenAI API error ({$code}): {$msg}");
}
return is_array($data) ? $data : [];
}
/** Create or reuse a per-visitor thread */
function ensure_thread_id() {
if (!empty($_SESSION['thread_id'])) return $_SESSION['thread_id'];
$created = openai_request('POST', '/threads', ['metadata' => ['site' => $_SERVER['HTTP_HOST'] ?? 'unknown']]);
$tid = $created['id'] ?? null;
if (!$tid) throw new RuntimeException('Failed to create thread.');
$_SESSION['thread_id'] = $tid;
return $tid;
}
/** Add a user message */
function add_user_message($thread_id, $text) {
openai_request('POST', "/threads/{$thread_id}/messages", [
'role' => 'user',
'content' => $text,
]);
}
/** Start a run */
function start_run($thread_id, $assistant_id) {
$run = openai_request('POST', "/threads/{$thread_id}/runs", [
'assistant_id' => $assistant_id,
]);
$run_id = $run['id'] ?? null;
if (!$run_id) throw new RuntimeException('Failed to start run.');
return $run_id;
}
/** Wait for completion (or fail/timeout) */
function wait_for_run($thread_id, $run_id, $max_tries, $delay_us) {
$terminal = ['completed', 'failed', 'requires_action', 'cancelled', 'expired'];
for ($i = 0; $i < $max_tries; $i++) {
usleep($delay_us);
$run = openai_request('GET', "/threads/{$thread_id}/runs/{$run_id}");
$status = $run['status'] ?? '';
if (in_array($status, $terminal, true)) return $run;
}
return ['status' => 'timeout'];
}
/** Cache of file_id => filename (per request) */
$_FILE_NAME_CACHE = [];
/** Resolve file name from file_id (API returns "filename" or sometimes "display_name") */
function get_file_name_by_id($file_id) {
global $_FILE_NAME_CACHE;
if (isset($_FILE_NAME_CACHE[$file_id])) return $_FILE_NAME_CACHE[$file_id];
$file = openai_request('GET', "/files/{$file_id}");
$name = $file['filename'] ?? ($file['display_name'] ?? ($file['name'] ?? $file_id));
$_FILE_NAME_CACHE[$file_id] = $name;
return $name;
}
/**
* Extract message text + citations (filename + page if available).
* Returns an array of entries: ['role' => 'user|assistant', 'text' => '...', 'refs' => [['filename'=>'','page'=>'','file_id'=>'']]]
*/
function normalize_messages($messages) {
$out = [];
if (empty($messages['data']) || !is_array($messages['data'])) return $out;
// The API returns newest first by default if not specifying; we request 'asc' in fetch.
foreach ($messages['data'] as $m) {
$role = $m['role'] ?? '';
if (!in_array($role, ['user', 'assistant', 'system'], true)) continue;
if (empty($m['content']) || !is_array($m['content'])) continue;
$all_text = [];
$refs = [];
foreach ($m['content'] as $part) {
if (($part['type'] ?? '') === 'text' && !empty($part['text']['value'])) {
$all_text[] = $part['text']['value'];
// Parse annotations for citations (file_citation)
$anns = $part['text']['annotations'] ?? [];
if (is_array($anns)) {
foreach ($anns as $ann) {
if (($ann['type'] ?? '') === 'file_citation' && !empty($ann['file_citation']['file_id'])) {
$fid = $ann['file_citation']['file_id'];
$page = null;
// Page can appear under different shapes depending on backend. Try common keys:
if (isset($ann['file_citation']['page'])) {
$page = $ann['file_citation']['page'];
} elseif (isset($ann['file_citation']['page_range']) && is_array($ann['file_citation']['page_range'])) {
// Example: ['start' => 5, 'end' => 6]
$start = $ann['file_citation']['page_range']['start'] ?? null;
$end = $ann['file_citation']['page_range']['end'] ?? null;
if ($start && $end && $start !== $end) $page = "{$start}-{$end}";
elseif ($start) $page = (string)$start;
}
// Fetch filename
try {
$filename = get_file_name_by_id($fid);
} catch (Throwable $e) {
$filename = $fid;
}
$refs[] = [
'file_id' => $fid,
'filename' => $filename,
'page' => $page ?? 'n/a',
];
}
}
}
}
}
if (!empty($all_text)) {
$out[] = [
'role' => $role,
'text' => implode("\n", $all_text),
'refs' => $refs,
];
}
}
return $out;
}
/** Fetch conversation (ascending) */
function fetch_history($thread_id) {
$messages = openai_request('GET', "/threads/{$thread_id}/messages", null, ['order' => 'asc', 'limit' => 50]);
return normalize_messages($messages);
}
/* ------------------- HANDLE POST ------------------- */
$error = null;
$history = [];
try {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['reset_thread'])) {
$_SESSION['thread_id'] = null;
} elseif (isset($_POST['user_input'])) {
$user_text = trim((string)$_POST['user_input']);
if ($user_text !== '') {
$thread_id = ensure_thread_id();
add_user_message($thread_id, $user_text);
$run_id = start_run($thread_id, $ASSISTANT_ID);
$run = wait_for_run($thread_id, $run_id, $POLL_MAX_TRIES, $POLL_DELAY_US);
if (($run['status'] ?? '') === 'failed') {
$error = 'Assistant run failed.';
} elseif (($run['status'] ?? '') === 'requires_action') {
// If you later support tool calls, handle them here then submit outputs.
} elseif (($run['status'] ?? '') === 'timeout') {
$error = 'Assistant timed out. Please try again.';
}
}
}
}
if (!empty($_SESSION['thread_id'])) {
$history = fetch_history($_SESSION['thread_id']);
}
} catch (Throwable $e) {
$error = $e->getMessage();
}
?>
<!-- UI -->
<div style="max-width:760px; margin:20px auto; font-family:Arial, sans-serif;">
<h3>Site Assistant</h3>
<p>Type a question below. Press <b>Enter</b> to send, <b>Shift+Enter</b> for a new line.</p>
<?php if ($error): ?>
<div style="margin:10px 0; padding:8px; border:1px solid #c00; border-radius:6px;">
<strong>Error:</strong> <?php echo h($error); ?>
</div>
<?php endif; ?>
<?php if (!empty($_SESSION['thread_id'])): ?>
<div style="margin:4px 0; font-size:12px;">Thread: <?php echo h($_SESSION['thread_id']); ?></div>
<?php endif; ?>
<form id="chat-form" method="post" style="margin:12px 0;">
<textarea id="chat-input" name="user_input" rows="3" style="width:100%; padding:6px;" placeholder="Ask your question..."></textarea>
<div style="margin-top:8px; display:flex; gap:8px;">
<button type="submit">Send</button>
<button type="submit" name="reset_thread" value="1">Reset Conversation</button>
</div>
</form>
<?php if (!empty($history) && is_array($history)): ?>
<div style="margin-top:16px; padding:10px; border:1px solid #ccc; border-radius:8px;">
<?php foreach ($history as $msg):
// Label mapping: user => Question, assistant => Answer, system => (optional)
$role = $msg['role'] ?? 'assistant';
if ($role === 'user') $label = 'Question';
elseif ($role === 'assistant') $label = 'Answer';
else $label = ucfirst($role); // e.g., System
$text = str_replace("\r\n", "\n", $msg['text'] ?? '');
$refs = $msg['refs'] ?? [];
?>
<div style="margin-bottom:14px;">
<div style="font-weight:bold;"><?php echo h($label); ?></div>
<div style="white-space:pre-wrap;"><?php echo nl2br(h($text)); ?></div>
<?php if (!empty($refs)): ?>
<div style="margin-top:6px; font-size:12px;">
<em>References:</em>
<ul style="margin:6px 0 0 18px; padding:0;">
<?php foreach ($refs as $r):
$fname = $r['filename'] ?? 'file';
$page = $r['page'] ?? 'n/a';
// If you have your own document links, replace '#' with a real URL.
?>
<li>
<a href="#" title="file_id: <?php echo h($r['file_id']); ?>">
<?php echo h($fname); ?> — page <?php echo h($page); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<div style="margin-top:10px; color:#666;">No messages yet.</div>
<?php endif; ?>
<div style="margin-top:10px; font-size:12px; color:#555;">
Conversation persists until you click “Reset Conversation”.
</div>
</div>
<!-- Submit on Enter (Shift+Enter = newline) -->
<script>
(function(){
var form = document.getElementById('chat-form');
var input = document.getElementById('chat-input');
input.addEventListener('keydown', function(e){
if (e.key === 'Enter') {
if (!e.shiftKey) {
e.preventDefault();
form.submit();
}
// if Shift+Enter, allow newline
}
});
})();
</script>

View file

@ -0,0 +1,258 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
global $db, $view, $settings;
include "panel/_db.php";
$user_id=$_SESSION['user_id'] ?? 0;
$user_id = 186; // For testing purposes, set a default user ID
if ($user_id <= 0) {
echo "<center><h4>Please login to view your cart</h4></center>";
return;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_single'])) {
$order_id = intval($_POST['delete_single']);
if ($order_id > 0) {
// First, check if the status is 'renew'
$stmt = $db->prepare("SELECT status FROM ogp_billing_orders WHERE order_id = ? AND user_id = ?");
$stmt->bind_param("ii", $order_id, $user_id);
$stmt->execute();
$stmt->bind_result($status);
if ($stmt->fetch() && strtolower($status) === 'renew') {
$stmt->close();
// Set status to 'expired' if currently 'renew'
$update = $db->prepare("UPDATE ogp_billing_orders SET status = 'expired' WHERE order_id = ? AND user_id = ?");
$update->bind_param("ii", $order_id, $user_id);
$update->execute();
$update->close();
} else {
$stmt->close();
// Otherwise, delete the order
$delete = $db->prepare("DELETE FROM ogp_billing_orders WHERE order_id = ? AND user_id = ?");
$delete->bind_param("ii", $order_id, $user_id);
$delete->execute();
$delete->close();
}
}
}
if ($db){
$carts = $db->query("SELECT * FROM ogp_billing_orders AS cart
WHERE (status = 'in-cart' OR status = 'renew') AND user_id = " . $user_id . " ORDER BY order_id ASC");
}
?>
<div style="width:100%; max-width:1000px; margin:auto; padding:1rem; background-color:#ffffff; border-radius:0.75rem; box-shadow:0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05);">
<h2 style="font-size:1.5rem; font-weight:bold; color:#1f2937; margin-bottom:1.5rem; text-align:center;">Your Cart</h2>
<!--
This is our cart form just for display and deletion. There is a different form below that has the paypal button and fills in all the hidden fields
-->
<table style="border-collapse:separate; border-spacing:0; width:100%; color:#000000;">
<thead style="background-color:#f9fafb;">
<tr>
<th style="padding:1rem 1.5rem; text-align:center; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;"></th>
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Server ID</th>
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Game Name</th>
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Location</th>
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Max Players</th>
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Price per Player</th>
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Months</th>
<th style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb; font-weight:600; text-transform:uppercase; font-size:0.75rem; letter-spacing:0.05em;">Total</th>
</tr>
</thead>
<tbody style="background-color:#ffffff;">
<?php
$grandTotal = 0; // Initialize grand total variable
if (isset($carts) && $carts instanceof mysqli_result && $carts->num_rows > 0) {
while ($row = $carts->fetch_assoc()) {
?>
<tr data-cart-id="<?php echo htmlspecialchars($row['order_id']); ?>" style="color:#000000;">
<td style="padding:1rem 1.5rem; text-align:center; border-bottom:1px solid #e5e7eb;">
<form method="post" action="" style="margin:0; display:inline;">
<button type="submit" name="delete_single" value="<?php echo htmlspecialchars($row['order_id']); ?>" style="background-color:#ef4444; color:#fff; border:none; border-radius:0.25rem; width:2rem; height:2rem; font-weight:bold; cursor:pointer; display:flex; align-items:center; justify-content:center;">
</button>
</form>
</td>
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['home_id']); ?></td>
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['home_name']); ?></td>
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['ip']); ?></td>
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['max_players']); ?></td>
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;">$<?php echo number_format($row['price'], 2); ?></td>
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;"><?php echo htmlspecialchars($row['qty']); ?></td>
<?php $rowtotal = $row['price'] * $row['qty'] * $row['max_players'];?>
<?php $grandTotal += $rowtotal; // Add to grand total ?>
<td style="padding:1rem 1.5rem; text-align:left; border-bottom:1px solid #e5e7eb;">$<?php echo number_format($rowtotal, 2); ?></td>
</tr>
<?php
}
// Add total row
?>
<tr style="background-color:#f9fafb; font-weight:bold;">
<td colspan="7" style="padding:1rem 1.5rem; text-align:right; border-top:2px solid #374151; font-weight:600; color:#374151;">
Cart Total:
</td>
<td style="padding:1rem 1.5rem; text-align:left; border-top:2px solid #374151; font-weight:600; color:#374151; font-size:1.1rem;">
$<?php echo number_format($grandTotal, 2); ?>
</td>
</tr>
<?php
} else {
// Display a message if no cart items are found
?>
<tr>
<td colspan="7" style="text-align:center; padding:1rem; color:#6b7280;">No items in your cart.</td>
</tr>
<?php
}
?>
</tbody>
</table>
<?php
// These must already exist earlier in your cart page:
// $grandTotal (number) e.g., 24.49
// $invoice (array) e.g., [['serverID'=>'srv123','amount'=>9.99], ['serverID'=>'srv999','amount'=>14.50]]
// --- Sanity + normalization ---
if (!isset($grandTotal) || !is_numeric($grandTotal)) {
$grandTotal = 0.00;
}
if (!isset($invoice) || !is_array($invoice)) {
$invoice = [];
}
$currency = 'USD';
$amount = number_format((float)$grandTotal, 2, '.', '');
$lineItems = [];
// Build PayPal-friendly items array (name, unit_amount, quantity, sku)
foreach ($invoice as $i) {
$sid = isset($i['serverID']) ? (string)$i['serverID'] : 'unknown';
$amt = isset($i['amount']) && is_numeric($i['amount']) ? number_format((float)$i['amount'], 2, '.', '') : '0.00';
$lineItems[] = [
'name' => "Server $sid",
'quantity' => '1',
'unit_amount' => ['currency_code' => $currency, 'value' => $amt],
'sku' => $sid
];
}
// Single overall invoice id for the order
$invoiceId = 'INV-' . date('Ymd-His') . '-' . bin2hex(random_bytes(3));
// A short custom reference derived from your line items (<= 127 chars for PayPal)
$customHash = substr(strtoupper(sha1(json_encode($invoice))), 0, 16);
$customId = "INVREF-$customHash";
// Text on the PayPal side
$description = 'Game server order (' . count($lineItems) . ' item' . (count($lineItems)===1?'': 's') . ')';
// URLs
$siteBase = 'https://panel.iaregamer.com';
$returnUrl = $siteBase . '/paypal/return.php?invoice=' . urlencode($invoiceId);
$cancelUrl = $siteBase . '/paypal/return.php?invoice=' . urlencode($invoiceId) . '&cancel=1';
// API base (relative)
$apiBase = '/paypal/api';
?>
<!-- PayPal JS SDK (Sandbox). Use LIVE client-id when going live. -->
<script src="https://www.paypal.com/sdk/js?client-id=AfvY_C2zA_hTHxHq7TIhtOeub4xBdySYrt_Hjj3d_WYQwjWI9NfOAVOTeResx2rgZ_nP5tOoxQSAHw8c&currency=USD&intent=capture"></script>
<div id="paypal-button-container"></div>
<div id="pp-status" style="margin-top:12px;font:14px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;"></div>
<script>
(function(){
const statusEl = document.getElementById('pp-status');
// Values from PHP
const amount = "<?= $amount ?>";
const currency = "<?= $currency ?>";
const invoice_id = "<?= $invoiceId ?>";
const custom_id = "<?= $customId ?>";
const description = "<?= htmlspecialchars($description, ENT_QUOTES) ?>";
const return_url = "<?= $returnUrl ?>";
const cancel_url = "<?= $cancelUrl ?>";
// Line items (serverID + per-item amount) for your records and webhook correlation
const line_invoices = <?php echo json_encode($invoice, JSON_UNESCAPED_SLASHES); ?>;
// PayPal "items" for purchase_units (shows on PayPal + returns in webhook under purchase_units)
const items = <?php echo json_encode($lineItems, JSON_UNESCAPED_SLASHES); ?>;
function setStatus(msg){ if(statusEl) statusEl.textContent = msg; }
paypal.Buttons({
createOrder: function() {
setStatus('Creating order…');
return fetch("<?= $apiBase ?>/create_order.php", {
method: "POST",
headers: {"Content-Type":"application/json"},
body: JSON.stringify({
amount, currency, invoice_id, custom_id, description,
return_url, cancel_url,
// The next two are for your server to include:
items, // PayPal purchase_units[0].items
line_invoices // your raw cart detail, persisted in your DB if you choose
})
})
.then(res => res.json())
.then(data => {
if (!data.id) { throw new Error(data.error || 'No order id'); }
setStatus('Order created.');
return data.id;
});
},
onApprove: function(data) {
setStatus('Capturing payment…');
return fetch("<?= $apiBase ?>/capture_order.php", {
method: "POST",
headers: {"Content-Type":"application/json"},
body: JSON.stringify({ order_id: data.orderID })
})
.then(res => res.json())
.then(capture => {
if (capture.status === 'COMPLETED') {
// go to your return page; webhook will fill data/<invoice_id>.json
window.location.href = return_url;
} else {
setStatus('Capture status: ' + capture.status);
}
})
.catch(err => setStatus('Error: ' + err.message));
},
onCancel: function() {
window.location.href = cancel_url;
},
onError: function(err){
setStatus('PayPal error: ' + (err && err.message ? err.message : err));
}
}).render('#paypal-button-container');
})();
</script>
</div>

View file

@ -0,0 +1,35 @@
text/x-generic _db.php ( PHP script, ASCII text, with CRLF line terminators )
<?php
$servername = "panel.iaregamer.com";
$username = "remoteuser";
$password = "Pkloyn7yvpht!";
$dbname = "panel";
// Create connection
$db = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if (!$db) {
echo "failed";
die("Connection failed: " . mysqli_connect_error());
}
//This gets the current users role , Admin, User or other
//returning true/false
//$isAdmin = isAdmin(186);
function isAdmin($userID){
$adminField = $db->query("SELECT 'users_role' FROM ogp_users WHERE userID = $userID");
if($adminField == "admin"){
$adminStatus = true;
}else{
$adminStatus = false;
}
return $adminStatus;
}
function logger($logtext){
file_put_contents("logfile.txt",$logtext . PHP_EOL,FILE_APPEND);
}
?>

View file

@ -0,0 +1,82 @@
<?php
echo <<<'HTML'
<style>
.gsw-outer-full{box-sizing:border-box;width:100vw!important;margin-left:calc(50% - 50vw)!important;margin-right:calc(50% - 50vw)!important}
.gsw-page-center{display:flex;justify-content:center;padding:24px 12px}
.gsw-wrap{width:min(95vw,1100px);margin:0 auto;line-height:1.55}
.gsw-hero{display:grid;gap:10px;margin-bottom:18px;text-align:center;justify-items:center}
.gsw-hero h1{margin:0;font-size:2rem;letter-spacing:.2px}
.gsw-hero p{margin:0;font-size:1.05rem}
.gsw-badge{display:inline-block;margin-top:6px;padding:6px 10px;border:1px solid;border-radius:999px;font-weight:600;font-size:.92rem}
.gsw-callout{margin:14px 0 4px;padding:12px 14px;border:1px dashed;border-radius:10px;text-align:center;font-size:1rem}
.gsw-locations{margin:12px 0 20px}
.gsw-locations h2{margin:0 0 10px;font-size:1.15rem;text-transform:uppercase;letter-spacing:.6px}
.gsw-locations-list{display:grid;gap:8px;grid-template-columns:1fr;list-style:disc;margin:0;padding-left:22px}
@media(min-width:680px){.gsw-locations-list{grid-template-columns:repeat(2,1fr)}}
.gsw-grid{display:grid;gap:14px;grid-template-columns:1fr}
@media(min-width:720px){.gsw-grid{grid-template-columns:repeat(3,1fr)}}
.gsw-card{padding:16px;border:1px solid;border-radius:10px}
.gsw-card h3{margin:0 0 6px;font-size:1.1rem}
.gsw-card p{margin:0}
.gsw-cta{display:flex;gap:12px;flex-wrap:wrap;margin-top:16px;justify-content:center}
.gsw-btn{border:1px solid;border-radius:8px;padding:10px 14px;text-decoration:none;display:inline-block;font-weight:600}
.gsw-fine{font-size:.92rem;opacity:.9;text-align:center;margin-top:10px}
</style>
<div class="gsw-outer-full">
<div class="gsw-page-center">
<section class="gsw-wrap" aria-label="GameServers.World">
<header class="gsw-hero">
<h1>Virtual Private Gameservers</h1>
<p>Just like running on your own dedicated box <strong>full configurability</strong> with <strong>help when you need it</strong>.</p>
<span class="gsw-badge" aria-label="Never oversold">Never Oversold Capacity</span>
<p style="margin-top:6px;">We also specialize in classics <strong>50+ older/community-favorite games</strong> hosted right.</p>
</header>
<div class="gsw-callout" role="note">
Your server gets the resources its promised. No cramming, no noisy neighbors predictable performance for your game and mods.
</div>
<section class="gsw-locations" aria-label="Current locations">
<h2>Current Locations</h2>
<ul class="gsw-locations-list">
<li><strong>East USA</strong></li>
<li><strong>Central USA</strong></li>
<li><strong>West USA</strong></li>
<li><strong>Western Europe</strong></li>
</ul>
</section>
<section class="gsw-grid" aria-label="Highlights">
<article class="gsw-card">
<h3>Built for the classics</h3>
<p>Low-latency routing and high-clock CPUs keep legacy engines smooth. We support favorites like CS&nbsp;1.6, Urban Terror, DayZ Mod and dozens more.</p>
</article>
<article class="gsw-card">
<h3>Simple, affordable plans</h3>
<p>Clear options, month-to-month flexibility, and room to scale as your community grows.</p>
</article>
<article class="gsw-card">
<h3>Real humans, fast setup</h3>
<p>Well help with configs, common mods, and a clean starter rotation so you can go live quickly.</p>
</article>
</section>
<nav class="gsw-cta" aria-label="Primary actions">
<a class="gsw-btn" href="/server-list/">Browse Game Servers</a>
<a class="gsw-btn" href="/contact/">Talk to Support</a>
</nav>
<p class="gsw-fine">Looking for a specific title or region? Tell us what you need we add games and locations regularly.</p>
</section>
</div>
</div>
HTML;
?>

View file

@ -0,0 +1,289 @@
<?php
/*
This is the actual "order gameserver" page. There is a page that displays all the possible game servers we can rent. This page displays the options
for a single specific game server and has the "Add to Cart" button.
The gameserver selected is passed from the gameserverss page by a Post of the ServiceID
When the user clicks the "Add to Cart" button, the next page to load is "add_to_cart.php" which creates all the DB entries.
All the configuration info is passed to the add_to_cart.php in hidden fields
In our website, we are setting "post" pages with a "Tag". The first tag in our post should be the service ID from the services table
There are other methods that might be better to get the info. But all we need is the "service_ID" in the "ogp_billing_services" table
This method means we can use one code block in every game page and fill in the data dynamically.
*/
include "panel/_db.php";
if (isset($_POST['save']) AND !empty($_POST['description']))
{
$new_description = str_replace("\\r\\n", "<br>", $_POST['description']);
$service = $_POST['service_id'];
$change_description = "UPDATE opg_billing_services
SET description ='".$new_description."'
WHERE service_id=".$service;
$save = $db->query($change_description);
}
?>
<!-- ------------------------------------------------------------------------------
THIS IS WHAT WE DISPLAY ON THE SHOP PAGE AT THE TOP
-->
<?php
// Shop Form
if(intval($_REQUEST['service_id']) !==0) $where_service_id = " WHERE enabled = 1 and service_id=".intval($_REQUEST['service_id']); else $where_service_id = " where enabled = 1";
$qry_services = "SELECT * FROM ogp_billing_services ".$where_service_id ." ORDER BY service_name";
$services = $db->query($qry_services);
if (isset($_REQUEST['service_id']) && $services === false) {
echo "<meta http-equiv='refresh' content='1'>";
return;
}
foreach ($services as $key => $row) {
$service_id[$key] = $row['service_id'];
$home_cfg_id[$key] = $row['home_cfg_id'];
$mod_cfg_id[$key] = $row['mod_cfg_id'];
$service_name[$key] = $row['service_name'];
$remote_server_id[$key] = $row['remote_server_id'];
$slot_max_qty[$key] = $row['slot_max_qty'];
$slot_min_qty[$key] = $row['slot_min_qty'];
$price_daily[$key] = $row['price_daily'];
$price_monthly[$key] = $row['price_monthly'];
$price_year[$key] = $row['price_year'];
$description[$key] = $row['description'];
$img_url[$key] = $row['img_url'];
$ftp[$key] = $row['ftp'];
$install_method[$key] = $row['install_method'];
$manual_url[$key] = $row['manual_url'];
$access_rights[$key] = $row['access_rights'];
}
?>
<div style="border-left:10px solid transparent;">
<?php
foreach($services as $row)
{
if(!isset($_REQUEST['service_id']))
{
?>
<div style="
float:left;
padding-top: 30px;
padding-right: 20px;
padding-bottom: 30px;
padding-left: 20px;">
<img src="<?php echo $row['img_url'] ;?>" width="460" height="225" >
<br>
<?php echo $row['service_name'];?>
<br>
<?php
if ($row['price_monthly'] == 0.0) {
echo "FREE";
} else {
echo "$" . number_format(floatval($row['price_monthly']),2). " Monthly";
}
?>
<br>
<form action="<?php echo $row['description'];?>" method="POST">
<input name="service_id" type="hidden" value="<?php echo $row['service_id'];?>" />
<input name="order_server" type="submit" value="Server Info">
</form>
<form action="" method="POST">
<input name="service_id" type="hidden" value="<?php echo $row['service_id'];?>" />
<input name="order_server" type="submit" value="Order Server">
</form>
</div>
</div>
</>
<?php
} else
//THIS IS THE SERVER WE WANT TO ORDER
{
?>
<div style="float:left; border: 4px solid transparent;border-bottom: 25px solid transparent;">
<img src="<?php echo $row['img_url'];?>" width=230 height=112 border=0 ">
<center><b> <?php echo $row['service_name'];?></b></center>
<?php
//$isAdmin = if( current_user_can('administrator')){
//$isAdmin = true;
//$isAdmin = $db->isAdmin($_SESSION['user_id'] );
$isAdmin = false;
if($isAdmin)
{
if(!isset($_POST['edit']))
{
echo "<p style='color:gray;width:230px;' >$row[description]<p>";
echo "<form action='' method='post'>".
"<input type='hidden' name='service_id' value='$row[service_id]' />".
"<input type='submit' name='edit' value='Edit' />".
"</form>";
}
else
{
echo "<form action='' method='post'>".
"<textarea style='resize:none;width:230px;height:132px;' name='description' >".str_replace("<br>", "\r\n", $row['description'])."</textarea><br>".
"<input type='hidden' name='service_id' value='$row[service_id]' />".
"<input type='submit' name='save' value='Save' />".
"</form>";
}
}
else
echo "<p style='color:gray;width:280px;' >$row[description]<p>";
?>
</div>
<table style="float:left;">
<form method="post" action="panel/_add_to_cart.php">
<input type="hidden" name="service_id" size="15" value="<?php if(isset($_POST['service_id'])) echo $_POST['service_id'];?>">
<input type="hidden" name="remote_control_password" size="15" value="ChangeMe">
<input type="hidden" name="ftp_password" size="15" value="ChangeMe">
<tr>
<td align="right"><b>Game Server Name</b> </td>
<td align="left">
<input type="text" name="home_name" size="40" value="<?php echo $row['service_name'];?>">
</td>
<tr>
<td align="right"><b>Location</b></td>
<td align="left">
<?php
//loop through multiple remote server ID stored in services 'remote_server_ip' as text
//change WHERE clause to IS IN clause
$rsiArray = explode(" ", $row['remote_server_id']);
$rsi = implode(",",$rsiArray);
//get the out of stock into an array and see if the rsID is in that array
$available_server = false;
//loop through each of the assigned servers and see if its disabled
foreach($rsiArray as $rsi)
{
$query = "SELECT * FROM ogp_remote_servers WHERE remote_server_id = ".$rsi;
$result = $db->query($query);
foreach($result as $rs)
{
$rsID =$rs['remote_server_id'];
$rsNAME = $rs['remote_server_name'];
//echo "<option value='$rsID'>$rsNAME</option>";
// add disabled to lable and input if $rsID is in out_of_stock
$is_unavailable = "";
$service_text_color = "";
if($rs['enabled']==0)
{
$is_unavailable = "disabled";
$service_text_color = "red";
}
if($is_unavailable == "")
{
$available_server = true;
}
//default radio button
// //<input type='radio' $is_unavailable name='ip_id' id='$rsID' value='$rsID' >
echo "<div>
<input type='radio' $is_unavailable name='ip_id' id='$rsID' value='$rsID' required>
<label for '$rsID' $is_unavailable ><span style='color:$service_text_color'>$rsNAME </span></label>
</div>";
}
}
?>
</td>
</tr>
<tr>
<td align="right"><b>Configure</b></td>
<td align="left">
<div class="slidecontainer">
<center><b>Player Slots</b> </center>
<input type="range" name="max_players" min="<?php echo $row['slot_min_qty']?>" max="<?php echo $row['slot_max_qty']?>" value="<?php echo $row['slot_min_qty']?>" class="slider" id="playerRange">
<center><b>Months</b></center>
<input type="range" name="qty" min="1" max="24" value="1" class="slider" id="invoiceRange">
<p>Player Slots: <span id="playerSlots"></span><br>
<span>Price: $<?php echo number_format(floatval($row['price_monthly']),2 );?> USD</span><br>
<span id="invoiceDuration"></span><br>
<span id="totalPrice"></span></p>
</div>
<script>
var slider = document.getElementById("playerRange");
var invoiceslider = document.getElementById("invoiceRange");
var output = document.getElementById("playerSlots");
var price = document.getElementById("totalPrice");
var invoiceDuration = document.getElementById("invoiceDuration");
var totalvalue = 0;
output.innerHTML = slider.value;
invoiceDuration.innerHTML = "Duration: "+invoiceslider.value+" months";
totalvalue = slider.value * invoiceslider.value * <?php echo number_format($row['price_monthly'],2);?>;
price.innerHTML = "Total Price: $"+totalvalue.toFixed(2) ;
slider.oninput = function() {
output.innerHTML = this.value;
invoiceDuration.innerHTML = "Duration: "+invoiceslider.value+" months";
totalvalue = invoiceslider.value * <?php echo number_format($row['price_monthly'],2);?>;
price.innerHTML = "Total Price: $"+totalvalue.toFixed(2) ;
}
invoiceslider.oninput = function() {
invoiceDuration.innerHTML = "Duration: "+invoiceslider.value+" months";
totalvalue = slider.value * invoiceslider.value * <?php echo number_format($row['price_monthly'],2);?>;
price.innerHTML = "Total Price: $"+totalvalue.toFixed(2) ;
}
</script>
<input type="hidden" name="invoice_duration" value="month" />
</td>
</tr>
<tr>
<td align="left" colspan="2">
<input name="service_id" type="hidden" value="<?php echo $row['service_id'];?>"/>
<?php
if ($available_server)
{
?>
<input type="submit" name="add_to_cart" value="Add to Cart"/>
<?php
}
?>
</form>
</td>
</tr>
<tr>
<td align="left" colspan="2">
<form action ="https://gameservers.world/server-list/" method="POST">
<button >Back to List</button>
</form>
</td>
</tr>
</table>
<?php
}
}
?>
</div>

View file

@ -0,0 +1,99 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
include "db.php";
// Save new description if admin
if (isset($_POST['save']) && !empty($_POST['description'])) {
$new_description = str_replace("\\r\\n", "<br>", $_POST['description']);
$service = intval($_POST['service_id']);
$stmt = $db->prepare("UPDATE ogp_billing_services SET description = ? WHERE service_id = ?");
$stmt->bind_param("si", $new_description, $service);
$stmt->execute();
$stmt->close();
}
// Fetch services
$service_id = isset($_REQUEST['service_id']) ? intval($_REQUEST['service_id']) : 0;
$where_service_id = $service_id !== 0 ? "WHERE enabled = 1 AND service_id = $service_id" : "WHERE enabled = 1";
$qry_services = "SELECT * FROM ogp_billing_services $where_service_id ORDER BY service_name";
$services = $db->query($qry_services);
if (!$services) {
echo "<meta http-equiv='refresh' content='1'>";
return;
}
?>
<div style="border-left:10px solid transparent;">
<?php foreach ($services as $row): ?>
<?php if (!isset($_REQUEST['service_id'])): ?>
<!-- Service listing (all) -->
<div style="float:left; padding:30px 20px;">
<img src="../<?php echo $row['img_url']; ?>" width="460" height="225"><br>
<strong><?php echo $row['service_name']; ?></strong><br>
<?php
echo ($row['price_monthly'] == 0.0) ? "FREE" : "$" . number_format(floatval($row['price_monthly']), 2) . " Monthly";
?>
<br>
<form action="https://gameservers.world/order-server" method="POST">
<input type="hidden" name="service_id" value="<?php echo $row['service_id']; ?>">
<input type="submit" name="order" value="Order Server" >
</form>
</div>
<?php else: ?>
<!-- Single service detail view -->
<div style="float:left; border: 4px solid transparent; border-bottom: 25px solid transparent;">
<img src="<?php echo $row['img_url']; ?>" width="230" height="112"><br>
<center><b><?php echo $row['service_name']; ?></b></center>
<?php
$isAdmin = false; // change to actual check, e.g. current_user_can('administrator')
if ($isAdmin) {
if (!isset($_POST['edit'])) {
echo "<p style='color:gray;width:230px;'>{$row['description']}</p>";
echo "<form method='post'>
<input type='hidden' name='service_id' value='{$row['servioce_id']}'>
<input type='submit' name='edit' value='Edit'>
</form>";
} else {
$desc = str_replace("<br>", "\r\n", $row['description']);
echo "<form method='post'>
<textarea style='resize:none;width:230px;height:132px;' name='description'>$desc</textarea><br>
<input type='hidden' name='service_id' value='{$row['service_id']}'>
<input type='submit' name='save' value='Save'>
</form>";
}
} else {
echo "<p style='color:gray;width:280px;'>{$row['description']}</p>";
}
?>
</div>
<!-- Order Form -->
<form method="post" action="order_server.php">
<input type="hidden" name="service_id" value="<?php echo $row['service_id']; ?>">
<input type="hidden" name="remote_control_password" value="ChangeMe">
<input type="hidden" name="ftp_password" value="ChangeMe">
<table style="float:left;">
<tr>
<td align="right"><b>Game Server Name</b></td>
<td><input type="text" name="home_name" size="40" value="<?php echo $row['service_name']; ?>"></td>
</tr>
<!-- Add other form fields as needed -->
<tr>
<td colspan="2"><input type="submit" value="Add to Cart"></td>
</tr>
</table>
</form>
<?php endif; ?>
<?php endforeach; ?>
</div>