| Server IP : 10.200.247.200 / Your IP : 216.73.217.19 Web Server : Apache System : Linux synergy-usa-sites 6.8.0-138-generic #138-Ubuntu SMP PREEMPT_DYNAMIC Fri Jul 31 22:41:49 UTC 2026 x86_64 User : jeremy ( 1001) PHP Version : 8.4.25 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/development/callings.lvsaints.com/ |
Upload File : |
<?php
// ---------------------------------------------------------------------------
// Serves the live uploaded site, but only to signed-in users.
//
// The browser hits site.php/ (and site.php/css/style.css, site.php/img/x.png,
// …). We read the matching file out of the live release folder and stream it
// with the right content-type. Because every request goes through PHP, the
// login check applies to the whole site — the release folders themselves are
// blocked from direct web access (see data/.htaccess).
//
// Editors can preview a not-yet-live version: admin links to
// site.php?preview=<version>, which pins that version for their session so its
// assets resolve too. site.php?preview= (empty) clears it.
// ---------------------------------------------------------------------------
require __DIR__ . '/lib.php';
require __DIR__ . '/releases.php';
$user = require_login();
$is_editor = in_array($user['role'], ['admin', 'super_admin'], true);
// --- Editor preview controls (set/clear, then redirect to a clean URL) ------
if (isset($_GET['preview'])) {
if ($is_editor) {
$v = basename((string) $_GET['preview']);
if ($v !== '' && is_dir(releases_dir() . '/' . $v)) {
$_SESSION['preview_version'] = $v;
} else {
unset($_SESSION['preview_version']);
}
}
header('Location: site.php/');
exit;
}
// --- Pick which release folder to serve from --------------------------------
$base = null;
if ($is_editor && !empty($_SESSION['preview_version'])) {
$p = releases_dir() . '/' . $_SESSION['preview_version'];
if (is_dir($p)) {
$base = $p;
} else {
unset($_SESSION['preview_version']);
}
}
if ($base === null) {
$base = active_dir();
}
if ($base === null) {
http_response_code(404);
exit('No version has been published yet.');
}
// --- Resolve the requested file inside that folder --------------------------
$rel = ltrim((string) ($_SERVER['PATH_INFO'] ?? ''), '/');
if ($rel === '' || str_ends_with($rel, '/')) {
$rel .= 'index.html';
}
// Block traversal and hidden files.
if (preg_match('#(^|/)\.\.?(/|$)#', $rel) || str_contains(basename($rel), "\0")) {
http_response_code(404);
exit('Not found.');
}
$baseReal = realpath($base);
$full = realpath($base . '/' . $rel);
if ($full === false || $baseReal === false || !str_starts_with($full, $baseReal . DIRECTORY_SEPARATOR)) {
http_response_code(404);
exit('Not found.');
}
if (is_dir($full)) {
$full = realpath($full . '/index.html');
if ($full === false || !str_starts_with($full, $baseReal . DIRECTORY_SEPARATOR)) {
http_response_code(404);
exit('Not found.');
}
}
if (str_starts_with(basename($full), '.')) {
http_response_code(404);
exit('Not found.');
}
// --- Stream it with a sensible content-type ---------------------------------
$types = [
'html' => 'text/html; charset=utf-8', 'htm' => 'text/html; charset=utf-8',
'css' => 'text/css; charset=utf-8',
'js' => 'text/javascript; charset=utf-8', 'mjs' => 'text/javascript; charset=utf-8',
'json' => 'application/json', 'xml' => 'application/xml', 'txt' => 'text/plain; charset=utf-8',
'svg' => 'image/svg+xml', 'png' => 'image/png', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg',
'gif' => 'image/gif', 'webp' => 'image/webp', 'ico' => 'image/x-icon', 'avif' => 'image/avif',
'woff' => 'font/woff', 'woff2' => 'font/woff2', 'ttf' => 'font/ttf', 'otf' => 'font/otf', 'eot' => 'application/vnd.ms-fontobject',
'mp4' => 'video/mp4', 'webm' => 'video/webm', 'mp3' => 'audio/mpeg', 'ogg' => 'audio/ogg',
'pdf' => 'application/pdf', 'map' => 'application/json',
];
$ext = strtolower(pathinfo($full, PATHINFO_EXTENSION));
$ct = $types[$ext] ?? (function_exists('mime_content_type') ? (mime_content_type($full) ?: 'application/octet-stream') : 'application/octet-stream');
header('Content-Type: ' . $ct);
header('Content-Length: ' . filesize($full));
header('Cache-Control: private, no-cache'); // content is behind login; don't let shared caches keep it
header('X-Content-Type-Options: nosniff');
readfile($full);