diff options
author | Runxi Yu <me@runxiyu.org> | 2025-04-05 18:26:51 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2025-04-05 18:26:51 +0800 |
commit | 4f4f6a25be2625b4bb2cb10e3520f52c4a35c243 (patch) | |
tree | 5458da1ee5efa5e46e831c34c1f39ebc67fb71b0 | |
parent | Remove renderReadmeAtTree (diff) | |
download | forge-4f4f6a25be2625b4bb2cb10e3520f52c4a35c243.tar.gz forge-4f4f6a25be2625b4bb2cb10e3520f52c4a35c243.tar.zst forge-4f4f6a25be2625b4bb2cb10e3520f52c4a35c243.zip |
Separate code/README rendering and unsafe to their own packages
-rw-r--r-- | git_hooks_handle_linux.go | 3 | ||||
-rw-r--r-- | git_hooks_handle_other.go | 3 | ||||
-rw-r--r-- | git_plumbing.go | 6 | ||||
-rw-r--r-- | http_handle_repo_index.go | 3 | ||||
-rw-r--r-- | http_handle_repo_tree.go | 3 | ||||
-rw-r--r-- | lmtp_handle_patch.go | 3 | ||||
-rw-r--r-- | misc/unsafe.go (renamed from unsafe.go) | 10 | ||||
-rw-r--r-- | render/chroma.go (renamed from chroma.go) | 4 | ||||
-rw-r--r-- | render/escape.go | 11 | ||||
-rw-r--r-- | render/readme.go (renamed from readme_to_html.go) | 20 | ||||
-rw-r--r-- | resources.go | 3 | ||||
-rw-r--r-- | ssh_server.go | 5 |
12 files changed, 45 insertions, 29 deletions
diff --git a/git_hooks_handle_linux.go b/git_hooks_handle_linux.go index e316bb7..3c556c3 100644 --- a/git_hooks_handle_linux.go +++ b/git_hooks_handle_linux.go @@ -22,6 +22,7 @@ import ( "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "github.com/jackc/pgx/v5" + "go.lindenii.runxiyu.org/forge/misc" "go.lindenii.runxiyu.org/lindenii-common/ansiec" "go.lindenii.runxiyu.org/lindenii-common/clog" ) @@ -76,7 +77,7 @@ func hooksHandler(conn net.Conn) { { var ok bool - packPass, ok = packPasses.Load(bytesToString(cookie)) + packPass, ok = packPasses.Load(misc.BytesToString(cookie)) if !ok { if _, err = conn.Write([]byte{1}); err != nil { return diff --git a/git_hooks_handle_other.go b/git_hooks_handle_other.go index 4285784..89a4193 100644 --- a/git_hooks_handle_other.go +++ b/git_hooks_handle_other.go @@ -20,6 +20,7 @@ import ( "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "github.com/jackc/pgx/v5" + "go.lindenii.runxiyu.org/forge/misc" "go.lindenii.runxiyu.org/lindenii-common/ansiec" "go.lindenii.runxiyu.org/lindenii-common/clog" ) @@ -54,7 +55,7 @@ func hooksHandler(conn net.Conn) { { var ok bool - packPass, ok = packPasses.Load(bytesToString(cookie)) + packPass, ok = packPasses.Load(misc.BytesToString(cookie)) if !ok { if _, err = conn.Write([]byte{1}); err != nil { return diff --git a/git_plumbing.go b/git_plumbing.go index 15329ad..74c80ac 100644 --- a/git_plumbing.go +++ b/git_plumbing.go @@ -13,6 +13,8 @@ import ( "path" "sort" "strings" + + "go.lindenii.runxiyu.org/forge/misc" ) func writeTree(ctx context.Context, repoPath string, entries []treeEntry) (string, error) { @@ -76,14 +78,14 @@ func buildTreeRecursive(ctx context.Context, repoPath, baseTree string, updates if modeEnd < 0 { return errors.New("invalid tree format") } - mode := bytesToString(data[i : i+modeEnd]) + mode := misc.BytesToString(data[i : i+modeEnd]) i += modeEnd + 1 nameEnd := bytes.IndexByte(data[i:], 0) if nameEnd < 0 { return errors.New("missing null after filename") } - name := bytesToString(data[i : i+nameEnd]) + name := misc.BytesToString(data[i : i+nameEnd]) i += nameEnd + 1 if i+20 > len(data) { diff --git a/http_handle_repo_index.go b/http_handle_repo_index.go index 182b5df..ef1b76e 100644 --- a/http_handle_repo_index.go +++ b/http_handle_repo_index.go @@ -8,6 +8,7 @@ import ( "strings" "go.lindenii.runxiyu.org/forge/git2c" + "go.lindenii.runxiyu.org/forge/render" ) type commitDisplay struct { @@ -45,7 +46,7 @@ func httpHandleRepoIndex(w http.ResponseWriter, req *http.Request, params map[st params["commits"] = commits params["readme_filename"] = readme.Filename - _, params["readme"] = renderReadme(readme.Content, readme.Filename) + _, params["readme"] = render.Readme(readme.Content, readme.Filename) params["notes"] = notes renderTemplate(w, "repo_index", params) diff --git a/http_handle_repo_tree.go b/http_handle_repo_tree.go index 889406b..9cdd9cd 100644 --- a/http_handle_repo_tree.go +++ b/http_handle_repo_tree.go @@ -9,6 +9,7 @@ import ( "strings" "go.lindenii.runxiyu.org/forge/git2c" + "go.lindenii.runxiyu.org/forge/render" ) // httpHandleRepoTree provides a friendly, syntax-highlighted view of @@ -44,7 +45,7 @@ func httpHandleRepoTree(writer http.ResponseWriter, request *http.Request, param params["readme"] = template.HTML("<p>README rendering here is WIP again</p>") // TODO renderTemplate(writer, "repo_tree_dir", params) case content != "": - rendered := renderHighlightedFile(pathSpec, content) + rendered := render.Highlight(pathSpec, content) params["file_contents"] = rendered renderTemplate(writer, "repo_tree_file", params) default: diff --git a/lmtp_handle_patch.go b/lmtp_handle_patch.go index 6bcb272..45d146a 100644 --- a/lmtp_handle_patch.go +++ b/lmtp_handle_patch.go @@ -16,6 +16,7 @@ import ( "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/go-git/go-git/v5" + "go.lindenii.runxiyu.org/forge/misc" ) func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string, mbox io.Reader) (err error) { @@ -63,7 +64,7 @@ func lmtpHandlePatch(session *lmtpSession, groupPath []string, repoName string, return fmt.Errorf("failed to get contents: %w", err) } - sourceBuf := bytes.NewReader(stringToBytes(sourceString)) + sourceBuf := bytes.NewReader(misc.StringToBytes(sourceString)) var patchedBuf bytes.Buffer if err := gitdiff.Apply(&patchedBuf, sourceBuf, diffFile); err != nil { return fmt.Errorf("failed to apply patch: %w", err) diff --git a/unsafe.go b/misc/unsafe.go index a4e9ac8..6c2192f 100644 --- a/unsafe.go +++ b/misc/unsafe.go @@ -1,20 +1,20 @@ // SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> -package main +package misc import "unsafe" -// stringToBytes converts a string to a byte slice without copying the string. +// StringToBytes converts a string to a byte slice without copying the string. // Memory is borrowed from the string. // The resulting byte slice must not be modified in any form. -func stringToBytes(s string) (bytes []byte) { +func StringToBytes(s string) (bytes []byte) { return unsafe.Slice(unsafe.StringData(s), len(s)) } -// bytesToString converts a byte slice to a string without copying the bytes. +// BytesToString converts a byte slice to a string without copying the bytes. // Memory is borrowed from the byte slice. // The source byte slice must not be modified. -func bytesToString(b []byte) string { +func BytesToString(b []byte) string { return unsafe.String(unsafe.SliceData(b), len(b)) } diff --git a/chroma.go b/render/chroma.go index 0d904b7..c7d64ec 100644 --- a/chroma.go +++ b/render/chroma.go @@ -1,4 +1,4 @@ -package main +package render import ( "bytes" @@ -9,7 +9,7 @@ import ( chromaStyles "github.com/alecthomas/chroma/v2/styles" ) -func renderHighlightedFile(filename, content string) template.HTML { +func Highlight(filename, content string) template.HTML { lexer := chromaLexers.Match(filename) if lexer == nil { lexer = chromaLexers.Fallback diff --git a/render/escape.go b/render/escape.go new file mode 100644 index 0000000..44c56f3 --- /dev/null +++ b/render/escape.go @@ -0,0 +1,11 @@ +package render + +import ( + "html" + "html/template" +) + +// EscapeHTML just escapes a string and wraps it in [template.HTML]. +func EscapeHTML(s string) template.HTML { + return template.HTML(html.EscapeString(s)) //#nosec G203 +} diff --git a/readme_to_html.go b/render/readme.go index 6d3f6f3..1a153fb 100644 --- a/readme_to_html.go +++ b/render/readme.go @@ -1,7 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu <https://runxiyu.org> -package main +package render import ( "bytes" @@ -13,33 +13,29 @@ import ( "github.com/niklasfasching/go-org/org" "github.com/yuin/goldmark" "github.com/yuin/goldmark/extension" + "go.lindenii.runxiyu.org/forge/misc" ) var markdownConverter = goldmark.New(goldmark.WithExtensions(extension.GFM)) -// escapeHTML just escapes a string and wraps it in [template.HTML]. -func escapeHTML(s string) template.HTML { - return template.HTML(html.EscapeString(s)) //#nosec G203 -} - // renderReadme renders and sanitizes README content from a byte slice and filename. -func renderReadme(data []byte, filename string) (string, template.HTML) { +func Readme(data []byte, filename string) (string, template.HTML) { switch strings.ToLower(filename) { case "readme": - return "README", template.HTML("<pre>" + html.EscapeString(bytesToString(data)) + "</pre>") //#nosec G203 + return "README", template.HTML("<pre>" + html.EscapeString(misc.BytesToString(data)) + "</pre>") //#nosec G203 case "readme.md": var buf bytes.Buffer if err := markdownConverter.Convert(data, &buf); err != nil { - return "Error fetching README", escapeHTML("Unable to render README: " + err.Error()) + return "Error fetching README", EscapeHTML("Unable to render README: " + err.Error()) } return "README.md", template.HTML(bluemonday.UGCPolicy().SanitizeBytes(buf.Bytes())) //#nosec G203 case "readme.org": - htmlStr, err := org.New().Parse(strings.NewReader(bytesToString(data)), filename).Write(org.NewHTMLWriter()) + htmlStr, err := org.New().Parse(strings.NewReader(misc.BytesToString(data)), filename).Write(org.NewHTMLWriter()) if err != nil { - return "Error fetching README", escapeHTML("Unable to render README: " + err.Error()) + return "Error fetching README", EscapeHTML("Unable to render README: " + err.Error()) } return "README.org", template.HTML(bluemonday.UGCPolicy().Sanitize(htmlStr)) //#nosec G203 default: - return filename, template.HTML("<pre>" + html.EscapeString(bytesToString(data)) + "</pre>") //#nosec G203 + return filename, template.HTML("<pre>" + html.EscapeString(misc.BytesToString(data)) + "</pre>") //#nosec G203 } } diff --git a/resources.go b/resources.go index 0bb033a..00d7b66 100644 --- a/resources.go +++ b/resources.go @@ -11,6 +11,7 @@ import ( "github.com/tdewolff/minify/v2" "github.com/tdewolff/minify/v2/html" + "go.lindenii.runxiyu.org/forge/misc" ) //go:embed LICENSE source.tar.gz @@ -59,7 +60,7 @@ func loadTemplates() (err error) { return err } - _, err = templates.Parse(bytesToString(minified)) + _, err = templates.Parse(misc.BytesToString(minified)) if err != nil { return err } diff --git a/ssh_server.go b/ssh_server.go index a3b69e4..1408a2a 100644 --- a/ssh_server.go +++ b/ssh_server.go @@ -10,6 +10,7 @@ import ( "strings" gliderSSH "github.com/gliderlabs/ssh" + "go.lindenii.runxiyu.org/forge/misc" "go.lindenii.runxiyu.org/lindenii-common/ansiec" "go.lindenii.runxiyu.org/lindenii-common/clog" goSSH "golang.org/x/crypto/ssh" @@ -39,7 +40,7 @@ func serveSSH(listener net.Listener) error { } serverPubkey = hostKey.PublicKey() - serverPubkeyString = bytesToString(goSSH.MarshalAuthorizedKey(serverPubkey)) + serverPubkeyString = misc.BytesToString(goSSH.MarshalAuthorizedKey(serverPubkey)) serverPubkeyFP = goSSH.FingerprintSHA256(serverPubkey) server = &gliderSSH.Server{ @@ -47,7 +48,7 @@ func serveSSH(listener net.Listener) error { clientPubkey := session.PublicKey() var clientPubkeyStr string if clientPubkey != nil { - clientPubkeyStr = strings.TrimSuffix(bytesToString(goSSH.MarshalAuthorizedKey(clientPubkey)), "\n") + clientPubkeyStr = strings.TrimSuffix(misc.BytesToString(goSSH.MarshalAuthorizedKey(clientPubkey)), "\n") } clog.Info("Incoming SSH: " + session.RemoteAddr().String() + " " + clientPubkeyStr + " " + session.RawCommand()) |