[], 'screenshots' => [], 'eras' => [], 'links_section' => ['title' => 'Server Lists', 'disclaimer' => '', 'items' => []], ]; if (!is_file($path)) { return $empty; } $raw = file_get_contents($path); if ($raw === false || trim($raw) === '') { return $empty; } $data = json_decode($raw, true); if (!is_array($data)) { return $empty; } $welcome = []; foreach (($data['welcome'] ?? []) as $line) { $line = trim((string)$line); if ($line !== '') $welcome[] = $line; } $screenshots = []; foreach (($data['screenshots'] ?? []) as $shot) { if (!is_array($shot)) continue; $filename = trim((string)($shot['filename'] ?? '')); if ($filename === '' || str_contains($filename, '..') || str_contains($filename, '/')) continue; $screenshots[] = [ 'filename' => $filename, 'caption' => (string)($shot['caption'] ?? ''), ]; } $eras = []; foreach (($data['eras'] ?? []) as $era) { if (!is_array($era)) continue; $title = trim((string)($era['title'] ?? '')); if ($title === '') continue; $servers = []; foreach (($era['servers'] ?? []) as $srv) { if (!is_array($srv)) continue; $name = trim((string)($srv['name'] ?? '')); if ($name === '') continue; $url = trim((string)($srv['url'] ?? '')); if ($url !== '' && !runescape_valid_url_or_path($url)) $url = ''; $highlights = []; foreach (($srv['highlights'] ?? []) as $hl) { $hl = trim((string)$hl); if ($hl !== '') $highlights[] = $hl; } $links = []; foreach (($srv['links'] ?? []) as $lk) { if (!is_array($lk)) continue; $label = trim((string)($lk['label'] ?? '')); $lurl = trim((string)($lk['url'] ?? '')); if ($label === '' || $lurl === '' || !runescape_valid_url_or_path($lurl)) continue; $links[] = ['label' => $label, 'url' => $lurl]; } $srvImage = trim((string)($srv['image'] ?? '')); if ($srvImage !== '' && str_contains($srvImage, '..')) $srvImage = ''; $servers[] = [ 'id' => (string)($srv['id'] ?? ''), 'name' => $name, 'url' => $url, 'featured' => !empty($srv['featured']), 'desc' => (string)($srv['desc'] ?? ''), 'highlights' => $highlights, 'links' => $links, 'image' => $srvImage, ]; } $eraImage = trim((string)($era['image'] ?? '')); if ($eraImage !== '' && str_contains($eraImage, '..')) $eraImage = ''; $eras[] = [ 'id' => (string)($era['id'] ?? ''), 'title' => $title, 'subtitle' => (string)($era['subtitle'] ?? ''), 'image' => $eraImage, 'servers' => $servers, ]; } $linksSection = ['title' => 'Server Lists', 'disclaimer' => '', 'items' => []]; if (is_array($data['links_section'] ?? null)) { $ls = $data['links_section']; $linksSection['title'] = trim((string)($ls['title'] ?? '')) ?: 'Server Lists'; $linksSection['disclaimer'] = (string)($ls['disclaimer'] ?? ''); foreach (($ls['items'] ?? []) as $item) { if (!is_array($item)) continue; $label = trim((string)($item['label'] ?? '')); $lurl = trim((string)($item['url'] ?? '')); if ($label === '' || $lurl === '' || !runescape_valid_url_or_path($lurl)) continue; $linksSection['items'][] = ['label' => $label, 'url' => $lurl, 'desc' => (string)($item['desc'] ?? '')]; } } return ['welcome' => $welcome, 'screenshots' => $screenshots, 'eras' => $eras, 'links_section' => $linksSection]; } function runescape_screenshot_src(string $filename): string { $filename = trim($filename); if ($filename === '' || str_contains($filename, '..') || str_contains($filename, '/')) return ''; return '/gaming/runescape/images/' . rawurlencode($filename); } /** Public URL for an era/server image (uploaded filename, site path, or absolute URL). */ function runescape_image_src(string $image): string { $image = trim($image); if ($image === '') return ''; if (str_starts_with($image, 'http://') || str_starts_with($image, 'https://') || str_starts_with($image, '/')) { return $image; } if (str_contains($image, '..') || str_contains($image, "\0")) return ''; return '/gaming/runescape/images/' . rawurlencode(basename($image)); } /** Render the Welcome list — lines like "::Label::" become bold headings, everything else is a bullet. */ function runescape_render_welcome(array $lines): void { $he = fn($s) => htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); $inList = false; foreach ($lines as $line) { if (preg_match('/^::(.+)::$/', trim($line), $m)) { if ($inList) { echo ''; $inList = false; } echo '
' . $he(trim($m[1])) . '
'; continue; } if (!$inList) { echo '$lk): ?> = $i > 0 ? ' · ' : '' ?>= $he($lk['label']) ?>