2020-02-09 23:02:19 +01:00
|
|
|
<?php
|
|
|
|
|
2021-04-07 13:09:50 +02:00
|
|
|
define("WEBBASE_VERSION", "1.2.4");
|
2020-06-22 19:09:02 +02:00
|
|
|
|
2021-04-06 16:34:12 +02:00
|
|
|
spl_autoload_extensions(".php");
|
|
|
|
spl_autoload_register(function($class) {
|
|
|
|
$full_path = getClassPath($class);
|
|
|
|
if(file_exists($full_path)) {
|
|
|
|
include_once $full_path;
|
|
|
|
} else {
|
|
|
|
include_once getClassPath($class, false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2021-04-03 10:39:13 +02:00
|
|
|
function getProtocol(): string {
|
2021-04-07 00:03:14 +02:00
|
|
|
$isSecure = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
|
|
|
|
(!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
|
|
|
|
(!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on');
|
|
|
|
|
|
|
|
return $isSecure ? 'https' : 'http';
|
2020-06-22 19:09:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function generateRandomString($length): string {
|
|
|
|
$randomString = '';
|
|
|
|
if ($length > 0) {
|
|
|
|
$numCharacters = 26 + 26 + 10; // a-z + A-Z + 0-9
|
|
|
|
for ($i = 0; $i < $length; $i++) {
|
|
|
|
try {
|
|
|
|
$num = random_int(0, $numCharacters - 1);
|
|
|
|
} catch (Exception $e) {
|
|
|
|
$num = rand(0, $numCharacters - 1);
|
|
|
|
}
|
2020-06-20 15:49:53 +02:00
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
if ($num < 26) $randomString .= chr(ord('a') + $num);
|
|
|
|
else if ($num - 26 < 26) $randomString .= chr(ord('A') + $num - 26);
|
|
|
|
else $randomString .= chr(ord('0') + $num - 26 - 26);
|
2020-02-09 23:02:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
return $randomString;
|
|
|
|
}
|
2020-02-10 00:52:25 +01:00
|
|
|
|
2021-04-03 11:07:56 +02:00
|
|
|
function startsWith($haystack, $needle, bool $ignoreCase = false): bool {
|
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
$length = strlen($needle);
|
2021-04-03 11:07:56 +02:00
|
|
|
if ($length === 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($ignoreCase) {
|
|
|
|
$haystack = strtolower($haystack);
|
2021-04-03 12:05:32 +02:00
|
|
|
$needle = strtolower($needle);
|
2021-04-03 11:07:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// PHP 8.0 support
|
|
|
|
if (function_exists("str_starts_with")) {
|
|
|
|
return str_starts_with($haystack, $needle);
|
|
|
|
} else {
|
|
|
|
return (substr($haystack, 0, $length) === $needle);
|
|
|
|
}
|
2020-06-22 19:09:02 +02:00
|
|
|
}
|
|
|
|
|
2021-04-03 11:07:56 +02:00
|
|
|
function endsWith($haystack, $needle, bool $ignoreCase = false): bool {
|
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
$length = strlen($needle);
|
2021-04-03 11:07:56 +02:00
|
|
|
if ($length === 0) {
|
2020-06-22 19:09:02 +02:00
|
|
|
return true;
|
2021-04-03 11:07:56 +02:00
|
|
|
}
|
2020-06-22 19:09:02 +02:00
|
|
|
|
2021-04-03 11:07:56 +02:00
|
|
|
if ($ignoreCase) {
|
|
|
|
$haystack = strtolower($haystack);
|
2021-04-03 12:05:32 +02:00
|
|
|
$needle = strtolower($needle);
|
2021-04-03 11:07:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// PHP 8.0 support
|
|
|
|
if (function_exists("str_ends_with")) {
|
|
|
|
return str_ends_with($haystack, $needle);
|
|
|
|
} else {
|
|
|
|
return (substr($haystack, -$length) === $needle);
|
|
|
|
}
|
2020-06-22 19:09:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function intendCode($code, $escape = true) {
|
|
|
|
$newCode = "";
|
|
|
|
$first = true;
|
|
|
|
$brackets = array();
|
|
|
|
$intend = 0;
|
|
|
|
|
|
|
|
foreach (explode("\n", $code) as $line) {
|
|
|
|
if (!$first) $newCode .= "\n";
|
|
|
|
if ($escape) $line = htmlspecialchars($line);
|
|
|
|
$line = trim($line);
|
|
|
|
|
|
|
|
if (count($brackets) > 0 && startsWith($line, current($brackets))) {
|
|
|
|
$intend = max(0, $intend - 2);
|
|
|
|
array_pop($brackets);
|
2020-02-09 23:02:19 +01:00
|
|
|
}
|
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
$newCode .= str_repeat(" ", $intend);
|
|
|
|
$newCode .= $line;
|
|
|
|
$first = false;
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
if (endsWith($line, "{")) {
|
|
|
|
$intend += 2;
|
|
|
|
array_push($brackets, "}");
|
|
|
|
} else if (endsWith($line, "(")) {
|
|
|
|
$intend += 2;
|
|
|
|
array_push($brackets, ")");
|
|
|
|
}
|
2020-02-09 23:02:19 +01:00
|
|
|
}
|
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
return $newCode;
|
|
|
|
}
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
function replaceCssSelector($sel) {
|
|
|
|
return preg_replace("~[.#<>]~", "_", preg_replace("~[:\-]~", "", $sel));
|
|
|
|
}
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2021-01-07 15:54:19 +01:00
|
|
|
function urlId($str) {
|
|
|
|
return urlencode(htmlspecialchars(preg_replace("[: ]","-", $str)));
|
|
|
|
}
|
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
function getClassPath($class, $suffix = true) {
|
|
|
|
$path = str_replace('\\', '/', $class);
|
|
|
|
$path = array_values(array_filter(explode("/", $path)));
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2021-04-06 15:55:13 +02:00
|
|
|
if (count($path) > 2 && strcasecmp($path[0], "api") === 0 && strcasecmp($path[1], "Parameter") !== 0) {
|
2020-06-22 19:09:02 +02:00
|
|
|
$path = "Api/" . $path[1] . "API";
|
|
|
|
} else {
|
|
|
|
$path = implode("/", $path);
|
|
|
|
}
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
$suffix = ($suffix ? ".class" : "");
|
|
|
|
return "core/$path$suffix.php";
|
|
|
|
}
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
function createError($msg) {
|
|
|
|
return json_encode(array("success" => false, "msg" => $msg));
|
|
|
|
}
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2021-04-03 10:39:13 +02:00
|
|
|
function serveStatic(string $webRoot, string $file): string {
|
2020-02-09 23:02:19 +01:00
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
$path = realpath($webRoot . "/" . $file);
|
|
|
|
if (!startsWith($path, $webRoot . "/")) {
|
|
|
|
http_response_code(406);
|
|
|
|
return "<b>Access restricted, requested file outside web root:</b> " . htmlspecialchars($path);
|
2020-02-09 23:02:19 +01:00
|
|
|
}
|
|
|
|
|
2020-06-22 19:09:02 +02:00
|
|
|
if (!file_exists($path) || !is_file($path) || !is_readable($path)) {
|
|
|
|
http_response_code(500);
|
|
|
|
return "<b>Unable to read file:</b> " . htmlspecialchars($path);
|
2020-02-09 23:02:19 +01:00
|
|
|
}
|
2020-04-03 15:56:04 +02:00
|
|
|
|
2020-06-22 19:12:14 +02:00
|
|
|
$pathInfo = pathinfo($path);
|
2020-06-20 20:13:51 +02:00
|
|
|
|
2021-04-03 13:05:20 +02:00
|
|
|
// TODO: add more file extensions here, probably add them to settings?
|
|
|
|
$allowedExtension = array("html", "htm", "pdf");
|
2020-06-22 19:09:02 +02:00
|
|
|
$ext = $pathInfo["extension"] ?? "";
|
|
|
|
if (!in_array($ext, $allowedExtension)) {
|
|
|
|
http_response_code(406);
|
|
|
|
return "<b>Access restricted:</b> Extension '" . htmlspecialchars($ext) . "' not allowed.";
|
2020-04-03 15:56:04 +02:00
|
|
|
}
|
|
|
|
|
2020-06-22 21:39:15 +02:00
|
|
|
$size = filesize($path);
|
2020-06-22 19:12:14 +02:00
|
|
|
$mimeType = mime_content_type($path);
|
2020-06-22 21:39:15 +02:00
|
|
|
header("Content-Type: $mimeType"); // TODO: do we need to check mime type?
|
|
|
|
header("Content-Length: $size");
|
|
|
|
header('Accept-Ranges: bytes');
|
|
|
|
|
|
|
|
if (strcasecmp($_SERVER["REQUEST_METHOD"], "HEAD") !== 0) {
|
|
|
|
$bufferSize = 1024*16;
|
|
|
|
$handle = fopen($path, "rb");
|
|
|
|
if($handle === false) {
|
|
|
|
http_response_code(500);
|
|
|
|
return "<b>Unable to read file:</b> " . htmlspecialchars($path);
|
|
|
|
}
|
|
|
|
|
|
|
|
$offset = 0;
|
|
|
|
$length = $size;
|
|
|
|
|
|
|
|
if (isset($_SERVER['HTTP_RANGE'])) {
|
|
|
|
preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
|
|
|
|
$offset = intval($matches[1]);
|
|
|
|
$length = intval($matches[2]) - $offset;
|
|
|
|
http_response_code(206);
|
|
|
|
header('Content-Range: bytes ' . $offset . '-' . ($offset + $length) . '/' . $size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($offset > 0) {
|
|
|
|
fseek($handle, $offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
$bytesRead = 0;
|
|
|
|
while (!feof($handle) && $bytesRead < $length) {
|
|
|
|
$chunkSize = min($length - $bytesRead, $bufferSize);
|
|
|
|
echo fread($handle, $chunkSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose($handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
2020-06-22 19:09:02 +02:00
|
|
|
}
|
2020-07-15 15:05:54 +02:00
|
|
|
|
|
|
|
function parseClass($class) {
|
|
|
|
if (!startsWith($class, "\\")) {
|
|
|
|
$class = "\\$class";
|
|
|
|
}
|
|
|
|
|
|
|
|
$parts = explode("\\", $class);
|
|
|
|
$parts = array_map('ucfirst', $parts);
|
|
|
|
return implode("\\", $parts);
|
2021-01-07 15:54:19 +01:00
|
|
|
}
|