mirror of
https://github.com/myronblair/tomtomgames-app
synced 2026-06-30 17:49:57 -05:00
v1.0.4 - Clean start
This commit is contained in:
+75
-17
@@ -1,37 +1,103 @@
|
||||
Options -Indexes
|
||||
# ══════════════════════════════════════════════════════════
|
||||
# TomTomGames Security Configuration
|
||||
# ══════════════════════════════════════════════════════════
|
||||
|
||||
Options -Indexes -Includes
|
||||
ServerSignature Off
|
||||
|
||||
# ── Block sensitive files ────────────────────────────────
|
||||
<FilesMatch "\.(sql|env|log|sh|md|git)$">
|
||||
# ── Block all sensitive file types ───────────────────────
|
||||
<FilesMatch "\.(sql|env|log|sh|md|git|bak|backup|old|orig|tmp|swp|cfg|ini|conf|yaml|yml|json.bak)$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
|
||||
# ── Block direct access to includes ──────────────────────
|
||||
# ── Block direct access to sensitive PHP files ───────────
|
||||
<FilesMatch "^(phpcheck|test|test_mail|test_login|sgtest|install|config|db|auth|mailer|square|smtp)\.php$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
|
||||
# ── Block access to includes and vendor folders ──────────
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteRule ^includes/ - [F,L]
|
||||
RewriteRule ^vendor/ - [F,L]
|
||||
RewriteRule ^mail_queue/ - [F,L]
|
||||
RewriteRule ^\.git/ - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Security headers ──────────────────────────────────────
|
||||
# ── Block common attack vectors ──────────────────────────
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
# Block SQL injection attempts in query strings
|
||||
RewriteCond %{QUERY_STRING} (union|select|insert|drop|delete|update|cast|exec|declare|char|convert|truncate).*= [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} \.\./\.\. [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} (javascript|vbscript|expression|applet|meta|xml|blink|link|iframe|input|embed|script|object|marquee) [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
|
||||
# Block base64 encoded attacks
|
||||
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
|
||||
# Block common exploit scanners and bad bots
|
||||
RewriteCond %{HTTP_USER_AGENT} (nikto|sqlmap|havij|nessus|masscan|zgrab|python-requests/2\.6|libwww-perl|wget|curl\/7\.[0-4]) [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Block access to WordPress paths (scanners look for these) ──
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteRule ^wp-admin - [F,L]
|
||||
RewriteRule ^wp-login - [F,L]
|
||||
RewriteRule ^xmlrpc - [F,L]
|
||||
RewriteRule ^\.env - [F,L]
|
||||
RewriteRule ^composer\. - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Security Headers ──────────────────────────────────────
|
||||
<IfModule mod_headers.c>
|
||||
# Prevent MIME type sniffing
|
||||
Header always set X-Content-Type-Options "nosniff"
|
||||
Header always set X-Frame-Options "SAMEORIGIN"
|
||||
|
||||
# Prevent clickjacking
|
||||
Header always set X-Frame-Options "DENY"
|
||||
|
||||
# XSS protection
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
|
||||
# Referrer policy
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
|
||||
|
||||
# Permissions policy — disable dangerous browser features
|
||||
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), magnetometer=(), gyroscope=()"
|
||||
|
||||
# Content Security Policy
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://web.squarecdn.com https://sandbox.web.squarecdn.com https://js.squareup.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' data: https://fonts.gstatic.com; img-src 'self' data: blob: https:; connect-src 'self' https: wss:; frame-src 'none'; object-src 'none'"
|
||||
|
||||
# Strict Transport Security — force HTTPS for 1 year
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
|
||||
# Remove server info headers
|
||||
Header unset Server
|
||||
Header unset X-Powered-By
|
||||
</IfModule>
|
||||
|
||||
# ── Canonical HTTPS redirect ──────────────────────────────
|
||||
# ── Canonical HTTPS + non-www redirect ───────────────────
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
||||
# Remove www (pick one: www or non-www, use non-www)
|
||||
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
|
||||
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Block PHP execution in uploads folder (if it exists) ─
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteRule ^uploads/.*\.php$ - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Gzip compression ──────────────────────────────────────
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/json image/svg+xml
|
||||
@@ -49,11 +115,3 @@ ServerSignature Off
|
||||
ExpiresByType image/webp "access plus 1 month"
|
||||
ExpiresByType application/json "access plus 1 day"
|
||||
</IfModule>
|
||||
|
||||
# ── LiteSpeed cache rules ─────────────────────────────────
|
||||
<IfModule LiteSpeed>
|
||||
CacheEnable public /assets/
|
||||
CacheEnable public /manifest.json
|
||||
CacheEnable public /sitemap.xml
|
||||
CacheEnable public /robots.txt
|
||||
</IfModule>
|
||||
|
||||
+327
-247
File diff suppressed because it is too large
Load Diff
@@ -310,14 +310,16 @@ switch ($action) {
|
||||
$stmt->execute([$uid]);
|
||||
$current = $stmt->fetchColumn();
|
||||
$new_val = $current ? 0 : 1;
|
||||
// If granting admin, also set email_verified=1
|
||||
if ($new_val) {
|
||||
db()->prepare("UPDATE users SET is_admin=1, email_verified=1 WHERE id=?")->execute([$uid]);
|
||||
} else {
|
||||
db()->prepare("UPDATE users SET is_admin=0 WHERE id=?")->execute([$uid]);
|
||||
}
|
||||
logActivity($new_val?'admin_granted':'admin_revoked', $uid, (int)$_SESSION['user_id'], 'user', $uid, 'Admin status changed to '.($new_val?'admin':'player'));
|
||||
echo json_encode(['success'=>true, 'is_admin'=>$new_val]);
|
||||
// Force the affected user to re-login by invalidating their sessions
|
||||
// Store a flag in DB that forces re-auth on next request
|
||||
db()->prepare("UPDATE users SET last_login=last_login WHERE id=?")->execute([$uid]);
|
||||
logActivity($new_val?'admin_granted':'admin_revoked', $uid, (int)$_SESSION['user_id'], 'user', $uid, 'Admin status changed to '.($new_val?'admin':'player'), '', 'admin', '', '', 'warning');
|
||||
echo json_encode(['success'=>true, 'is_admin'=>$new_val, 'needs_relogin'=>true, 'message'=>$new_val ? 'Admin access granted. User must log out and back in.' : 'Admin access removed. User must log out and back in.']);
|
||||
break;
|
||||
|
||||
// ─── TOGGLE SUSPEND ───────────────────────────────────────
|
||||
@@ -439,6 +441,24 @@ switch ($action) {
|
||||
echo json_encode(['success'=>true,'broadcasts'=>$rows]);
|
||||
break;
|
||||
|
||||
case 'broadcast_list':
|
||||
try {
|
||||
$sql = "SELECT b.id, b.subject, b.message, b.target, b.sent_at,
|
||||
u.username AS sender_name,
|
||||
(SELECT COUNT(*) FROM broadcast_reads WHERE broadcast_id=b.id) AS read_count,
|
||||
(SELECT COUNT(*) FROM broadcast_replies WHERE broadcast_id=b.id) AS reply_count,
|
||||
(SELECT COUNT(*) FROM users WHERE status='active' AND is_admin=0) AS total_players
|
||||
FROM broadcasts b
|
||||
JOIN users u ON b.admin_id=u.id
|
||||
ORDER BY b.sent_at DESC
|
||||
LIMIT 100";
|
||||
$stmt = db()->query($sql);
|
||||
echo json_encode(['success'=>true,'broadcasts'=>$stmt->fetchAll()]);
|
||||
} catch(Exception $e) {
|
||||
echo json_encode(['success'=>false,'error'=>$e->getMessage()]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'broadcast_send':
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['success'=>false]); exit; }
|
||||
$d = json_decode(file_get_contents('php://input'), true);
|
||||
@@ -468,6 +488,42 @@ switch ($action) {
|
||||
echo json_encode(['success'=>true]);
|
||||
break;
|
||||
|
||||
case 'broadcast_edit':
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['success'=>false]); exit; }
|
||||
$d = json_decode(file_get_contents('php://input'), true);
|
||||
$id = (int)($d['id'] ?? 0);
|
||||
$subject = substr(trim($d['subject'] ?? ''), 0, 200);
|
||||
$message = trim($d['message'] ?? '');
|
||||
$target = in_array($d['target']??'', ['all','verified','unverified','admins']) ? $d['target'] : 'all';
|
||||
if (!$id || !$subject || !$message) { echo json_encode(['success'=>false,'error'=>'Missing fields']); exit; }
|
||||
db()->prepare("UPDATE broadcasts SET subject=?, message=?, target=? WHERE id=?")->execute([$subject, $message, $target, $id]);
|
||||
logAdminAction('BROADCAST_EDITED', $adminId, 'broadcast', $id, 'Edited broadcast #'.$id, '', '', 'info');
|
||||
echo json_encode(['success'=>true]);
|
||||
break;
|
||||
|
||||
case 'broadcast_resend':
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['success'=>false]); exit; }
|
||||
$d = json_decode(file_get_contents('php://input'), true);
|
||||
$id = (int)($d['id'] ?? 0);
|
||||
if (!$id) { echo json_encode(['success'=>false,'error'=>'Missing ID']); exit; }
|
||||
$bc = db()->prepare("SELECT * FROM broadcasts WHERE id=?");
|
||||
$bc->execute([$id]);
|
||||
$orig = $bc->fetch();
|
||||
if (!$orig) { echo json_encode(['success'=>false,'error'=>'Broadcast not found']); exit; }
|
||||
// Count recipients
|
||||
$target = $orig['target'];
|
||||
$countSql = "SELECT COUNT(*) FROM users WHERE status='active' AND is_admin=0";
|
||||
if ($target === 'verified') $countSql .= " AND email_verified=1";
|
||||
if ($target === 'unverified') $countSql .= " AND email_verified=0";
|
||||
$recipientCount = (int)db()->query($countSql)->fetchColumn();
|
||||
// Delete old reads so everyone sees it again
|
||||
db()->prepare("DELETE FROM broadcast_reads WHERE broadcast_id=?")->execute([$id]);
|
||||
// Update sent_at to now
|
||||
db()->prepare("UPDATE broadcasts SET sent_at=NOW() WHERE id=?")->execute([$id]);
|
||||
logAdminAction('BROADCAST_RESENT', $adminId, 'broadcast', $id, 'Resent broadcast #'.$id.' to '.$recipientCount.' players', '', '', 'info');
|
||||
echo json_encode(['success'=>true,'recipient_count'=>$recipientCount]);
|
||||
break;
|
||||
|
||||
case 'broadcast_reads':
|
||||
$bid = (int)($_GET['broadcast_id']??0);
|
||||
$rows = db()->prepare("SELECT br.read_at, u.username, u.alias FROM broadcast_reads br JOIN users u ON br.user_id=u.id WHERE br.broadcast_id=? ORDER BY br.read_at ASC");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
ob_start(); // Buffer any accidental output (PHP errors, notices, etc.)
|
||||
ob_start();
|
||||
try {
|
||||
require_once __DIR__ . '/../../includes/auth.php';
|
||||
} catch (Throwable $e) {
|
||||
@@ -28,5 +28,8 @@ if (!$user) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Sync session is_admin with DB value — catches admin elevation/demotion
|
||||
$_SESSION['is_admin'] = (int)$user['is_admin'];
|
||||
|
||||
unset($user['password']);
|
||||
echo json_encode(['success' => true, 'user' => $user]);
|
||||
|
||||
@@ -20,6 +20,13 @@ if ($method === 'GET') {
|
||||
$user->execute([$userId]);
|
||||
$u = $user->fetch();
|
||||
|
||||
// Auto-generate code if missing
|
||||
if (empty($u['referral_code'])) {
|
||||
$code = strtoupper(substr(md5($userId.uniqid()),0,8));
|
||||
db()->prepare("UPDATE users SET referral_code=? WHERE id=?")->execute([$code, $userId]);
|
||||
$u['referral_code'] = $code;
|
||||
}
|
||||
|
||||
// Count verified referrals
|
||||
$countStmt = db()->prepare("SELECT COUNT(*) FROM referrals WHERE referrer_id=? AND status='verified'");
|
||||
$countStmt->execute([$userId]);
|
||||
@@ -175,7 +182,7 @@ if ($action === 'resolve_referral') {
|
||||
db()->prepare("UPDATE referrals SET status='verified', tier_id=?, tokens_awarded=?, admin_id=?, admin_note=?, resolved_at=NOW() WHERE id=?")
|
||||
->execute([$tier['id'] ?? null, $totalAward, (int)$_SESSION['user_id'], $note, $id]);
|
||||
db()->prepare("UPDATE users SET tokens=tokens+? WHERE id=?")->execute([$totalAward, $ref['referrer_id']]);
|
||||
logAdminAction('REFERRAL_VERIFIED', (int)\$_SESSION['user_id'], 'referral', \$id, 'Verified referral #'.\$id.' — awarded '.\$totalAward.' tokens to user #'.\$ref['referrer_id'], 'pending', 'verified', 'info');
|
||||
logAdminAction('REFERRAL_VERIFIED', (int)$_SESSION['user_id'], 'referral', $id, 'Verified referral #'.$id.' — awarded '.$totalAward.' tokens to user #'.$ref['referrer_id'], 'pending', 'verified', 'info');
|
||||
db()->commit();
|
||||
echo json_encode(['success'=>true,'tokens_awarded'=>$totalAward,'bonus'=>$bonusTokens,'tier'=>$tier['name']??'']);
|
||||
} catch(Exception $e) {
|
||||
@@ -199,7 +206,7 @@ if ($action === 'resolve_share') {
|
||||
db()->prepare("UPDATE referral_social_shares SET status=?,admin_id=?,resolved_at=NOW() WHERE id=?")->execute([$status,(int)$_SESSION['user_id'],$id]);
|
||||
if ($status === 'approved') {
|
||||
db()->prepare("UPDATE users SET tokens=tokens+? WHERE id=?")->execute([$share['bonus_tokens'],$share['user_id']]);
|
||||
logAdminAction('SOCIAL_SHARE_APPROVED', (int)\$_SESSION['user_id'], 'referral_share', \$id, 'Approved social share #'.\$id.' — awarded '.\$share['bonus_tokens'].' bonus tokens to user #'.\$share['user_id'], '', 'approved', 'info');
|
||||
logAdminAction('SOCIAL_SHARE_APPROVED', (int)$_SESSION['user_id'], 'referral_share', $id, 'Approved social share #'.$id.' — awarded '.$share['bonus_tokens'].' bonus tokens to user #'.$share['user_id'], '', 'approved', 'info');
|
||||
}
|
||||
echo json_encode(['success'=>true]);
|
||||
exit;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 136 B |
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="6" fill="#0a0a12"/>
|
||||
<circle cx="16" cy="16" r="13" fill="#f0c040"/>
|
||||
<text x="16" y="22" text-anchor="middle" font-family="Arial" font-weight="bold" font-size="18" fill="#000">T</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 290 B |
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* TomGames — Square Location ID Finder
|
||||
* Upload this file, visit it in your browser ONCE to get your Location ID.
|
||||
* Then paste the ID into includes/config.php and DELETE this file.
|
||||
*/
|
||||
|
||||
$token = 'EAAAl1ECweOVgNiwhC2SuA56QFjlfRLkYxo4xe4r2fMLvqwLT0IKGUZNNOYy1NXn';
|
||||
$locations = [];
|
||||
$error = '';
|
||||
|
||||
$ch = curl_init('https://connect.squareup.com/v2/locations');
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Authorization: Bearer ' . $token,
|
||||
'Square-Version: 2024-01-18',
|
||||
'Content-Type: application/json',
|
||||
],
|
||||
CURLOPT_TIMEOUT => 15,
|
||||
]);
|
||||
$resp = curl_exec($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($code === 200) {
|
||||
$data = json_decode($resp, true);
|
||||
$locations = $data['locations'] ?? [];
|
||||
} else {
|
||||
$error = "HTTP $code: " . htmlspecialchars($resp);
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Square Location ID Finder</title>
|
||||
<style>
|
||||
body{font-family:'Segoe UI',sans-serif;background:#0a0a12;color:#e8e8f0;max-width:600px;margin:40px auto;padding:20px}
|
||||
h1{font-size:22px;background:linear-gradient(135deg,#f0c040,#00e5ff);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:6px}
|
||||
.sub{color:#8888aa;font-size:13px;margin-bottom:28px}
|
||||
.loc{background:#1a1a2e;border:1px solid rgba(255,255,255,.1);border-radius:12px;padding:20px;margin-bottom:16px}
|
||||
.loc-name{font-size:18px;font-weight:700;color:#e8e8f0;margin-bottom:6px}
|
||||
.loc-id-wrap{display:flex;align-items:center;gap:10px;margin:10px 0}
|
||||
.loc-id{font-family:monospace;font-size:18px;font-weight:700;color:#f0c040;background:#0a0a12;border:1px solid rgba(240,192,64,.4);border-radius:8px;padding:10px 16px;flex:1;letter-spacing:1px}
|
||||
.copy-btn{padding:10px 16px;background:linear-gradient(135deg,#f0c040,#d4a017);border:none;border-radius:8px;color:#000;font-weight:700;font-size:13px;cursor:pointer}
|
||||
.copy-btn:hover{opacity:.9}
|
||||
.loc-meta{font-size:12px;color:#8888aa;margin-top:6px}
|
||||
.next{background:rgba(0,229,255,.08);border:1px solid rgba(0,229,255,.2);border-radius:12px;padding:18px;margin-top:24px}
|
||||
.next h2{color:#00e5ff;font-size:15px;margin-bottom:10px}
|
||||
.next ol{padding-left:18px;line-height:2;color:#c0c0d8;font-size:13px}
|
||||
.next code{background:#0a0a12;border:1px solid rgba(255,255,255,.15);border-radius:4px;padding:2px 7px;font-family:monospace;color:#f0c040}
|
||||
.err{background:rgba(255,68,68,.1);border:1px solid rgba(255,68,68,.3);border-radius:10px;padding:16px;color:#ff6666}
|
||||
.warn{background:rgba(255,214,10,.08);border:1px solid rgba(255,214,10,.2);border-radius:8px;padding:12px;margin-top:20px;font-size:12px;color:#ffd60a}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🔑 Square Location Finder</h1>
|
||||
<div class="sub">TomGames — Run once, then delete this file</div>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="err"><strong>Error fetching locations:</strong><br><?= $error ?></div>
|
||||
<?php elseif (empty($locations)): ?>
|
||||
<div class="err">No locations found on this Square account.</div>
|
||||
<?php else: ?>
|
||||
<p style="color:#8888aa;font-size:13px;margin-bottom:16px">Found <?= count($locations) ?> location(s). Copy the ID for your main location:</p>
|
||||
<?php foreach ($locations as $loc): ?>
|
||||
<div class="loc">
|
||||
<div class="loc-name"><?= htmlspecialchars($loc['name']) ?> <?= $loc['status'] === 'ACTIVE' ? '✅' : '⚠️ ' . $loc['status'] ?></div>
|
||||
<div class="loc-id-wrap">
|
||||
<div class="loc-id" id="id-<?= $loc['id'] ?>"><?= htmlspecialchars($loc['id']) ?></div>
|
||||
<button class="copy-btn" onclick="copyId('<?= $loc['id'] ?>', this)">COPY</button>
|
||||
</div>
|
||||
<div class="loc-meta">
|
||||
<?= htmlspecialchars($loc['address']['address_line_1'] ?? '') ?>
|
||||
<?= htmlspecialchars($loc['address']['city'] ?? '') ?> ·
|
||||
Currency: <?= htmlspecialchars($loc['currency'] ?? 'USD') ?> ·
|
||||
Country: <?= htmlspecialchars($loc['country'] ?? '—') ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<div class="next">
|
||||
<h2>📋 Next Steps</h2>
|
||||
<ol>
|
||||
<li>Copy your Location ID above</li>
|
||||
<li>Open <code>includes/config.php</code></li>
|
||||
<li>Replace <code>YOUR_LOCATION_ID</code> with your copied ID</li>
|
||||
<li>Also update <code>DB_PASS</code> with your MySQL password</li>
|
||||
<li><strong>Delete this file from your server!</strong></li>
|
||||
</ol>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="warn">⚠️ <strong>Security:</strong> Delete <code>get_location.php</code> from your server after use. It exposes your access token.</div>
|
||||
|
||||
<script>
|
||||
function copyId(id, btn) {
|
||||
navigator.clipboard.writeText(id).then(() => {
|
||||
btn.textContent = 'COPIED!';
|
||||
btn.style.background = '#00e676';
|
||||
setTimeout(() => { btn.textContent = 'COPY'; btn.style.background = ''; }, 2000);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+274
-229
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
// Admin only diagnostic - delete after use
|
||||
$files = [
|
||||
'../../includes/db.php',
|
||||
'../../includes/auth.php',
|
||||
'../api/admin.php',
|
||||
];
|
||||
foreach ($files as $f) {
|
||||
$full = __DIR__ . '/' . $f;
|
||||
$out = shell_exec("php -l " . escapeshellarg($full) . " 2>&1");
|
||||
echo $f . ": " . trim($out) . "\n";
|
||||
}
|
||||
|
||||
// Also test DB connection directly
|
||||
try {
|
||||
require_once __DIR__ . '/../../includes/config.php';
|
||||
require_once __DIR__ . '/../../includes/db.php';
|
||||
$v = db()->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
||||
echo "\nDB OK — users: $v\n";
|
||||
$v2 = db()->query("SELECT version FROM app_version ORDER BY id DESC LIMIT 1")->fetchColumn();
|
||||
echo "App version: $v2\n";
|
||||
} catch (Throwable $e) {
|
||||
echo "\nDB ERROR: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . " line " . $e->getLine() . "\n";
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
echo json_encode([
|
||||
'php' => PHP_VERSION,
|
||||
'time' => date('Y-m-d H:i:s'),
|
||||
'status' => 'ok'
|
||||
]);
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
// POST test - simulates exactly what the app does
|
||||
ob_start();
|
||||
try { require_once __DIR__ . '/../includes/auth.php'; } catch(Throwable $e) { ob_end_clean(); die(json_encode(['boot_error'=>$e->getMessage()])); }
|
||||
ob_end_clean();
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$result = loginUser($data['username'] ?? '', $data['password'] ?? '');
|
||||
if ($result['success']) unset($result['user']['password']);
|
||||
echo json_encode($result);
|
||||
exit;
|
||||
}
|
||||
|
||||
// GET - show users
|
||||
$users = db()->query("SELECT id,username,alias,is_admin,email_verified,status FROM users")->fetchAll();
|
||||
echo json_encode(['users'=>$users,'session_id'=>session_id()]);
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
// Standalone email test - no auth required for diagnosis
|
||||
// DELETE THIS FILE after confirming email works
|
||||
|
||||
$result = [];
|
||||
$result['php_version'] = PHP_VERSION;
|
||||
$result['mail_function_exists'] = function_exists('mail');
|
||||
$result['server_software'] = $_SERVER['SERVER_SOFTWARE'] ?? 'unknown';
|
||||
$result['hostname'] = gethostname();
|
||||
|
||||
// Check sendmail path
|
||||
$sendmail = ini_get('sendmail_path');
|
||||
$result['sendmail_path'] = $sendmail ?: 'not set';
|
||||
|
||||
// Check if we can detect SMTP settings
|
||||
$result['smtp_host'] = ini_get('SMTP') ?: 'not set';
|
||||
$result['smtp_port'] = ini_get('smtp_port') ?: 'not set';
|
||||
|
||||
$to = $_POST['to'] ?? '';
|
||||
$sent = false;
|
||||
$sendError = '';
|
||||
|
||||
if ($to && filter_var($to, FILTER_VALIDATE_EMAIL) && isset($_POST['send'])) {
|
||||
$subject = 'TomTomGames Email Test';
|
||||
$message = "This is a test email from TomTomGames.\n\nIf you received this, PHP mail() is working correctly on this server.";
|
||||
$headers = "From: noreply@tomtomgames.com\r\n";
|
||||
$headers .= "Reply-To: support@tomtomgames.com\r\n";
|
||||
$headers .= "X-Mailer: PHP/" . PHP_VERSION;
|
||||
|
||||
// Capture any mail errors
|
||||
set_error_handler(function($errno, $errstr) use (&$sendError) {
|
||||
$sendError = $errstr;
|
||||
});
|
||||
$sent = mail($to, $subject, $message, $headers, '-fnoreply@tomtomgames.com');
|
||||
restore_error_handler();
|
||||
$result['mail_return'] = $sent;
|
||||
$result['mail_error'] = $sendError ?: 'none';
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Email Test</title>
|
||||
<style>
|
||||
body{font-family:monospace;background:#0a0a12;color:#e8e8f0;padding:24px;max-width:600px;margin:0 auto}
|
||||
h2{color:#f0c040}
|
||||
.box{background:#1a1a2e;border:1px solid #333;border-radius:8px;padding:16px;margin:12px 0}
|
||||
.ok{color:#00e676}.err{color:#ff4444}.warn{color:#f0c040}
|
||||
input{background:#111;border:1px solid #444;color:#fff;padding:8px 12px;width:280px;border-radius:6px;font-size:14px}
|
||||
button{background:#f0c040;color:#000;border:none;padding:10px 20px;border-radius:6px;font-weight:700;cursor:pointer;margin-left:8px}
|
||||
label{display:block;margin-bottom:6px;color:#aaa;font-size:13px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>TomTomGames — Email Diagnostics</h2>
|
||||
|
||||
<div class="box">
|
||||
<b>Server Info:</b><br>
|
||||
PHP: <span class="ok"><?= $result['php_version'] ?></span><br>
|
||||
Server: <?= htmlspecialchars($result['server_software']) ?><br>
|
||||
Hostname: <?= htmlspecialchars($result['hostname']) ?><br>
|
||||
mail() function: <span class="<?= $result['mail_function_exists'] ? 'ok' : 'err' ?>"><?= $result['mail_function_exists'] ? 'EXISTS' : 'MISSING' ?></span><br>
|
||||
sendmail_path: <span class="warn"><?= htmlspecialchars($result['sendmail_path']) ?></span><br>
|
||||
SMTP: <span class="warn"><?= htmlspecialchars($result['smtp_host']) ?>:<?= htmlspecialchars($result['smtp_port']) ?></span>
|
||||
</div>
|
||||
|
||||
<?php if ($to): ?>
|
||||
<div class="box">
|
||||
<b>Send Result:</b><br>
|
||||
To: <?= htmlspecialchars($to) ?><br>
|
||||
mail() returned: <span class="<?= $sent ? 'ok' : 'err' ?>"><?= $sent ? 'TRUE (queued for delivery)' : 'FALSE (failed)' ?></span><br>
|
||||
Error: <span class="warn"><?= htmlspecialchars($result['mail_error']) ?></span><br>
|
||||
<?php if ($sent): ?>
|
||||
<br><span class="ok">Check your inbox (and spam folder). If nothing arrives in 5 minutes, the server is not sending outbound mail.</span>
|
||||
<?php else: ?>
|
||||
<br><span class="err">mail() returned false — server cannot send email. You need to configure SMTP (PHPMailer) or enable sendmail.</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="box">
|
||||
<form method="POST">
|
||||
<label>Send test email to:</label>
|
||||
<input type="email" name="to" value="<?= htmlspecialchars($to) ?>" placeholder="your@email.com" required>
|
||||
<button type="submit" name="send" value="1">Send Test</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p style="color:#555;font-size:11px">Delete test_mail.php after diagnosis is complete.</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user