Spaces:
Build error
Build error
Create api/serve.php
Browse files- api/serve.php +95 -0
api/serve.php
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
// ── Parse the username from the URL ──────────────────────────────────────────
|
| 3 |
+
// Expected URL format: https://emalawi19-php-hosting.hf.space/site/username/
|
| 4 |
+
// e.g. /site/alice/index.php → serves /data/sites/alice/htdocs/index.php
|
| 5 |
+
|
| 6 |
+
$requestUri = $_SERVER['REQUEST_URI'];
|
| 7 |
+
|
| 8 |
+
// Strip query string
|
| 9 |
+
$path = parse_url($requestUri, PHP_URL_PATH);
|
| 10 |
+
|
| 11 |
+
// Match /site/{username}/{filepath}
|
| 12 |
+
if (!preg_match('#^/site/([a-z0-9]{3,32})(/.*)?$#', $path, $matches)) {
|
| 13 |
+
http_response_code(400);
|
| 14 |
+
echo '<h1>400 Bad Request</h1><p>Invalid site URL format.</p>';
|
| 15 |
+
echo '<p>Use: /site/username/filename.php</p>';
|
| 16 |
+
exit;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
$username = $matches[1];
|
| 20 |
+
$filePath = $matches[2] ?? '/index.php';
|
| 21 |
+
|
| 22 |
+
// Default to index.php if only directory requested
|
| 23 |
+
if (substr($filePath, -1) === '/') {
|
| 24 |
+
$filePath .= 'index.php';
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
// Sanitise — prevent directory traversal
|
| 28 |
+
$filePath = '/' . implode('/', array_filter(array_map(function($part) {
|
| 29 |
+
return ($part === '..' || $part === '.') ? '' : $part;
|
| 30 |
+
}, explode('/', $filePath))));
|
| 31 |
+
|
| 32 |
+
// Check user exists
|
| 33 |
+
$db = new PDO('sqlite:/data/db/platform.sqlite');
|
| 34 |
+
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
| 35 |
+
$stmt = $db->prepare('SELECT id FROM users WHERE username = ?');
|
| 36 |
+
$stmt->execute([$username]);
|
| 37 |
+
if (!$stmt->fetch()) {
|
| 38 |
+
http_response_code(404);
|
| 39 |
+
echo '<h1>404 Not Found</h1><p>No site found for user: ' . htmlspecialchars($username) . '</p>';
|
| 40 |
+
exit;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
$htdocs = "/data/sites/{$username}/htdocs";
|
| 44 |
+
$fullPath = $htdocs . $filePath;
|
| 45 |
+
|
| 46 |
+
if (!file_exists($fullPath)) {
|
| 47 |
+
http_response_code(404);
|
| 48 |
+
echo '<h1>404 Not Found</h1><p>File not found: ' . htmlspecialchars($filePath) . '</p>';
|
| 49 |
+
exit;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
// ── Serve static files directly ───────────────────────────────────────────────
|
| 53 |
+
$ext = strtolower(pathinfo($fullPath, PATHINFO_EXTENSION));
|
| 54 |
+
$mimeTypes = [
|
| 55 |
+
'html' => 'text/html',
|
| 56 |
+
'htm' => 'text/html',
|
| 57 |
+
'css' => 'text/css',
|
| 58 |
+
'js' => 'application/javascript',
|
| 59 |
+
'json' => 'application/json',
|
| 60 |
+
'png' => 'image/png',
|
| 61 |
+
'jpg' => 'image/jpeg',
|
| 62 |
+
'jpeg' => 'image/jpeg',
|
| 63 |
+
'gif' => 'image/gif',
|
| 64 |
+
'webp' => 'image/webp',
|
| 65 |
+
'svg' => 'image/svg+xml',
|
| 66 |
+
'ico' => 'image/x-icon',
|
| 67 |
+
'txt' => 'text/plain',
|
| 68 |
+
'pdf' => 'application/pdf',
|
| 69 |
+
'woff' => 'font/woff',
|
| 70 |
+
'woff2'=> 'font/woff2',
|
| 71 |
+
];
|
| 72 |
+
|
| 73 |
+
if ($ext !== 'php') {
|
| 74 |
+
$mime = $mimeTypes[$ext] ?? 'application/octet-stream';
|
| 75 |
+
header("Content-Type: {$mime}");
|
| 76 |
+
readfile($fullPath);
|
| 77 |
+
exit;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
// ── Execute PHP files ─────────────────────────────────────────────────────────
|
| 81 |
+
// Set environment so the included PHP file feels like it was requested directly
|
| 82 |
+
$_SERVER['DOCUMENT_ROOT'] = $htdocs;
|
| 83 |
+
$_SERVER['SCRIPT_FILENAME'] = $fullPath;
|
| 84 |
+
$_SERVER['SCRIPT_NAME'] = $filePath;
|
| 85 |
+
$_SERVER['PHP_SELF'] = $filePath;
|
| 86 |
+
|
| 87 |
+
// Change working directory so relative includes work
|
| 88 |
+
chdir($htdocs);
|
| 89 |
+
|
| 90 |
+
// Buffer and include the PHP file
|
| 91 |
+
ob_start();
|
| 92 |
+
include $fullPath;
|
| 93 |
+
$output = ob_get_clean();
|
| 94 |
+
|
| 95 |
+
echo $output;
|