'text/html; charset=utf-8', 'htm' => 'text/html; charset=utf-8', 'txt' => 'text/plain; charset=utf-8', 'xml' => 'application/xml; charset=utf-8', 'json' => 'application/json; charset=utf-8', 'css' => 'text/css; charset=utf-8', 'js' => 'text/javascript; charset=utf-8', 'mjs' => 'text/javascript; charset=utf-8', 'svg' => 'image/svg+xml', 'png' => 'image/png', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'webp' => 'image/webp', 'gif' => 'image/gif', 'ico' => 'image/x-icon', 'pdf' => 'application/pdf', 'mp4' => 'video/mp4', 'woff2' => 'font/woff2', 'otf' => 'font/otf', 'webmanifest' => 'application/manifest+json', ); if (function_exists('header_remove')) @header_remove('X-Powered-By'); $root = realpath(__DIR__); $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'; $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/'; $ua = isset($_SERVER['HTTP_USER_AGENT']) ? substr($_SERVER['HTTP_USER_AGENT'], 0, 300) : ''; $qpos = strpos($uri, '?'); $rawPath = $qpos === false ? $uri : substr($uri, 0, $qpos); $path = rawurldecode($rawPath); if ($path === '' || $path[0] !== '/') $path = '/' . $path; function sd_bot_name($ua, $bots) { $best = ''; foreach ($bots as $b) if (stripos($ua, $b) !== false && strlen($b) > strlen($best)) $best = $b; return $best; } /* The file Apache would serve: inside the docroot only, never a dotfile, never PHP source, * a directory's index.html, and a directory without its trailing slash redirects like * Apache's DirectorySlash does. Returns array(status, file or redirect target). */ function sd_resolve($root, $path) { if ($root === false || strpos($path, "\0") !== false || strpos($path, '\\') !== false) return array(404, null); foreach (explode('/', $path) as $seg) { if ($seg === '..' || ($seg !== '' && $seg[0] === '.' && $seg !== '.well-known')) return array(404, null); } $full = realpath($root . $path); if ($full === false) return array(404, null); if ($full !== $root && strpos($full, $root . DIRECTORY_SEPARATOR) !== 0) return array(404, null); if (is_dir($full)) { if (substr($path, -1) !== '/') return array(301, $path . '/'); $full = $full . DIRECTORY_SEPARATOR . 'index.html'; if (!is_file($full)) return array(404, null); } if (!is_file($full) || !is_readable($full)) return array(404, null); if (preg_match('/\.(php\d?|phtml|phar|inc|htaccess|htpasswd|env|ini|log|sql|bak|orig|swp)$/i', $full)) return array(404, null); return array(200, $full); } list($status, $target) = sd_resolve($root, $path); $head = ($method === 'HEAD'); if ($method !== 'GET' && $method !== 'HEAD') { $status = 405; header('Allow: GET, HEAD'); header('Content-Type: text/plain; charset=utf-8'); http_response_code(405); if (!$head) echo "Method not allowed\n"; } elseif ($status === 301) { $qs = $qpos === false ? '' : substr($uri, $qpos); http_response_code(301); header('Location: ' . str_replace('%2F', '/', rawurlencode($target)) . $qs); } elseif ($status === 200) { $ext = strtolower(pathinfo($target, PATHINFO_EXTENSION)); $type = isset($TYPES[$ext]) ? $TYPES[$ext] : 'application/octet-stream'; $mtime = filemtime($target); $size = filesize($target); $etag = '"' . dechex($mtime) . '-' . dechex($size) . '"'; header('Content-Type: ' . $type); header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $mtime) . ' GMT'); header('ETag: ' . $etag); header('Cache-Control: ' . (preg_match('/^(html|txt|xml)$/', $ext) ? 'no-cache, must-revalidate' : 'public, max-age=31536000, immutable')); $inm = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : ''; $ims = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false; if (($inm !== '' && $inm === $etag) || ($inm === '' && $ims !== false && $ims >= $mtime)) { $status = 304; http_response_code(304); } else { http_response_code(200); header('Content-Length: ' . $size); if (!$head) readfile($target); } } else { $status = 404; http_response_code(404); header('Content-Type: text/html; charset=utf-8'); $nf = $root === false ? false : $root . DIRECTORY_SEPARATOR . '404.html'; if (!$head) { if ($nf && is_file($nf)) readfile($nf); else echo "