aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-03-22 11:44:59 +0800
committerRunxi Yu <me@runxiyu.org>2025-03-22 11:44:59 +0800
commitc7440c2c3366e516ef9b0f4c34093e0c7f5c23d4 (patch)
tree4695fba3ffb65a2abbadda90bac2c7511ffcaaf7
parentFix HTTPS cloning (diff)
downloadforge-c7440c2c3366e516ef9b0f4c34093e0c7f5c23d4.tar.gz
forge-c7440c2c3366e516ef9b0f4c34093e0c7f5c23d4.tar.zst
forge-c7440c2c3366e516ef9b0f4c34093e0c7f5c23d4.zip
Fix tree/raw redirection and disallow slashes in their path segments
-rw-r--r--http_error_page.go6
-rw-r--r--http_handle_repo_raw.go7
-rw-r--r--http_handle_repo_tree.go3
-rw-r--r--http_server.go9
-rw-r--r--templates/400.tmpl25
-rw-r--r--url.go9
6 files changed, 51 insertions, 8 deletions
diff --git a/http_error_page.go b/http_error_page.go
index aabc9bd..3980797 100644
--- a/http_error_page.go
+++ b/http_error_page.go
@@ -11,3 +11,9 @@ func errorPage404(w http.ResponseWriter, params map[string]any) {
w.WriteHeader(404)
_ = templates.ExecuteTemplate(w, "404", params)
}
+
+func errorPage400(w http.ResponseWriter, params map[string]any, msg string) {
+ w.WriteHeader(400)
+ params["bad_request_msg"] = msg
+ _ = templates.ExecuteTemplate(w, "400", params)
+}
diff --git a/http_handle_repo_raw.go b/http_handle_repo_raw.go
index e398856..8664ceb 100644
--- a/http_handle_repo_raw.go
+++ b/http_handle_repo_raw.go
@@ -6,7 +6,6 @@ package main
import (
"fmt"
"net/http"
- "path"
"strings"
"github.com/go-git/go-git/v5"
@@ -51,8 +50,7 @@ func httpHandleRepoRaw(w http.ResponseWriter, r *http.Request, params map[string
http.Error(w, "Error retrieving path: "+err.Error(), http.StatusInternalServerError)
return
}
- if len(rawPathSpec) != 0 && rawPathSpec[len(rawPathSpec)-1] == '/' {
- http.Redirect(w, r, "../"+pathSpec, http.StatusSeeOther)
+ if redirectNoDir(w, r) {
return
}
if fileContent, err = file.Contents(); err != nil {
@@ -64,8 +62,7 @@ func httpHandleRepoRaw(w http.ResponseWriter, r *http.Request, params map[string
}
}
- if len(rawPathSpec) != 0 && rawPathSpec[len(rawPathSpec)-1] != '/' {
- http.Redirect(w, r, path.Base(pathSpec)+"/", http.StatusSeeOther)
+ if redirectDir(w, r) {
return
}
diff --git a/http_handle_repo_tree.go b/http_handle_repo_tree.go
index a1a3ca4..36eefc0 100644
--- a/http_handle_repo_tree.go
+++ b/http_handle_repo_tree.go
@@ -61,8 +61,7 @@ func httpHandleRepoTree(w http.ResponseWriter, r *http.Request, params map[strin
http.Error(w, "Error retrieving path: "+err.Error(), http.StatusInternalServerError)
return
}
- if len(rawPathSpec) != 0 && rawPathSpec[len(rawPathSpec)-1] == '/' {
- http.Redirect(w, r, "../"+pathSpec, http.StatusSeeOther)
+ if redirectNoDir(w, r) {
return
}
if fileContent, err = file.Contents(); err != nil {
diff --git a/http_server.go b/http_server.go
index c883cdf..584c48d 100644
--- a/http_server.go
+++ b/http_server.go
@@ -28,7 +28,6 @@ func (router *forgeHTTPRouter) ServeHTTP(w http.ResponseWriter, r *http.Request)
return
}
if segments[len(segments)-1] == "" {
- // Might assign a trailing bool here
segments = segments[:len(segments)-1]
}
@@ -172,12 +171,20 @@ func (router *forgeHTTPRouter) ServeHTTP(w http.ResponseWriter, r *http.Request)
repoFeature := segments[sepIndex+3]
switch repoFeature {
case "tree":
+ if anyContain(segments[sepIndex+4:], "/") {
+ errorPage400(w, params, "Repo tree paths may not contain slashes in any segments")
+ return
+ }
params["rest"] = strings.Join(segments[sepIndex+4:], "/")
if len(segments) < sepIndex+5 && redirectDir(w, r) {
return
}
httpHandleRepoTree(w, r, params)
case "raw":
+ if anyContain(segments[sepIndex+4:], "/") {
+ errorPage400(w, params, "Repo tree paths may not contain slashes in any segments")
+ return
+ }
params["rest"] = strings.Join(segments[sepIndex+4:], "/")
if len(segments) < sepIndex+5 && redirectDir(w, r) {
return
diff --git a/templates/400.tmpl b/templates/400.tmpl
new file mode 100644
index 0000000..1fcd5d9
--- /dev/null
+++ b/templates/400.tmpl
@@ -0,0 +1,25 @@
+{{/*
+ SPDX-License-Identifier: AGPL-3.0-only
+ SPDX-FileContributor: Runxi Yu <https://runxiyu.org>
+*/}}
+{{- define "400" -}}
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ {{- template "head_common" . -}}
+ <title>400 Bad Request &ndash; {{ .global.forge_title }}</title>
+ </head>
+ <body class="400">
+ {{- template "header" . -}}
+ <div class="padding-wrapper complete-error-page">
+ <h1>400 Bad Request</h1>
+ <p>{{- .bad_request_msg -}}</p>
+ <hr />
+ <address>Lindenii Forge</address>
+ </div>
+ <footer>
+ {{- template "footer" . -}}
+ </footer>
+ </body>
+</html>
+{{- end -}}
diff --git a/url.go b/url.go
index 3978c6e..57cb196 100644
--- a/url.go
+++ b/url.go
@@ -119,3 +119,12 @@ func segmentsToURL(segments []string) string {
}
return strings.Join(segments, "/")
}
+
+func anyContain(ss []string, c string) bool {
+ for _, s := range ss {
+ if strings.Contains(s, c) {
+ return true
+ }
+ }
+ return false
+}