From 369907392e181e801a447372005e04595ec815b4 Mon Sep 17 00:00:00 2001 From: Codeberg Date: Wed, 23 Oct 2019 23:50:06 +0200 Subject: [PATCH] fix path if incomplete, more mime-types, security work --- var/www/pages/index.php | 95 +++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 27 deletions(-) diff --git a/var/www/pages/index.php b/var/www/pages/index.php index ddba4a6..9afecdb 100644 --- a/var/www/pages/index.php +++ b/var/www/pages/index.php @@ -1,57 +1,98 @@ + + Codeberg Pages + + +

Codeberg Pages. Static Pages for your Project.

+

+ Create a repo called 'pages' to your user account or org, push static content including HTML+CSS styles, fonts, images. + +

+

+ Access your rendered pages via: +

+			https://" . $_SERVER["HTTP_HOST"] . "/<username>/
+		
+

+ + +"); } -if (preg_match("/\/[a-zA-Z0-9_ +\-\/\.]+\z/", $request_url) != 1) { - error(404, "invalid request URL '$request_url'"); +if (preg_match("/^\/[a-zA-Z0-9_ +\-\/\.]+\$/", $request_url) != 1) { + send_response(404, "invalid request URL"); } +$git_prefix = "/data/git/gitea-repositories"; $parts = explode("/", $request_url); array_shift($parts); # remove empty first $owner = strtolower(array_shift($parts)); -$git_root = "/data/git/gitea-repositories/$owner/pages.git"; -$file_url = implode("/", $parts); +$git_root = realpath("$git_prefix/$owner/pages.git"); -if (!is_dir($git_root)) { - error(404, "this user/organization does not have codeberg pages"); +if (substr($git_root, 0, strlen($git_prefix)) !== $git_prefix) { + send_response(404, "this user/organization does not have codeberg pages"); } +if (end($parts) === '') { + array_shift($parts); +} + +if (sizeof($parts) === 0 || strpos(end($parts), ".") === false) { + $h = "Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; + if (substr($h, -1) != "/") { + $h .= "/"; + } + $h .= "index.html"; + header($h); + exit(); +} + +$file_url = implode("/", $parts); + $command = "sh -c \"cd '$git_root' && /usr/bin/git show 'master:$file_url'\""; -## We are executing command twice (first for error-checking, then for actual raw output to stream), +## We are executing command twice (first for send_response-checking, then for actual raw output to stream), ## which seems wasteful, but it seems exec+echo cannot do raw binary output? Is this true? exec($command, $output, $retval); if ($retval != 0) { - error(404 , "no such file in repo: '$file_url'"); + send_response(404 , "no such file in repo: '" . htmlspecialchars($file_url) . "'"); } +$mime_types = array( + "svg" => "image/svg+xml", + "png" => "image/png", + "jpg" => "image/jpeg", + "jpeg" => "image/jpeg", + "gif" => "image/gif", + "js" => "application/javascript", + "html" => "text/html", + "css" => "text/css", + "ico" => "image/x-icon" +); + $ext = pathinfo($file_url, PATHINFO_EXTENSION); $ext = strtolower($ext); -if ($ext == "svg") { - header("Content-Type: image/svg+xml"); -} elseif ($ext == "jpg") { - header("Content-Type: image/jpeg"); -} elseif ($ext == "png") { - header("Content-Type: image/png"); -} elseif ($ext == "gif") { - header("Content-Type: image/gif"); -} elseif ($ext == "js") { - header("Content-Type: application/javascript"); -} elseif ($ext == "css") { - header("Content-Type: text/css"); +if (array_key_exists($ext, $mime_types)) { + $mime_type = $mime_types[$ext]; +} else { + $mime_type = "text/plain"; } +header("Content-Type: " . $mime_type); + ## If we could directly implode+echo raw output from above, we wouldn't need to execute command twice: passthru($command);