clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

title browse pages and harden the file viewer

Dami committed 4115672
Browse pages carry the repository or file in the title, file hashes are
URL encoded in links, raw downloads bypass in-page navigation, empty
files say so, and hosted site URLs keep the relay port.
commit
411567228bc1d930b30bcd3cfc4d95ef1a49aa1c
parent
789c96dc188d999ff4e67486387d97e9df2e6299
author
Dami <dami.etoile@gmail.com>
7 files changed, +77 -13
Minternal/webui/browse.html22+++++++++++-----------
Minternal/webui/browse_test.go26++++++++++++++++++++++++++
Minternal/webui/public_pages.go2+-
Minternal/webui/repo.html2+-
Minternal/webui/shell_test.go17+++++++++++++++++
Minternal/webui/style.css1+
Minternal/webui/webui.go20++++++++++++++++++++
M internal/webui/browse.html +11 -11
@@ -18,7 +18,7 @@
1818 {{else if .Feed}}<table id="rows">1919 <thead><tr><th>hash</th><th>type</th><th>uploaded</th></tr></thead>2020 <tbody>21-{{range .Feed}}{{$f := asMap .}}<tr><td><a href="/file?sha={{str (index $f "sha256")}}">{{shortID (index $f "sha256")}}</a></td><td>{{str (index $f "type")}} <small>{{str (index $f "size")}} B</small></td><td>{{when (index $f "uploaded")}}</td></tr>21+{{range .Feed}}{{$f := asMap .}}<tr><td><a href="/file?sha={{urlquery (str (index $f "sha256"))}}">{{shortID (index $f "sha256")}}</a></td><td>{{str (index $f "type")}} <small>{{str (index $f "size")}} B</small></td><td>{{when (index $f "uploaded")}}</td></tr>2222 {{end}}</tbody>2323 </table>2424 {{else}}<p>No files were reported.</p>
@@ -27,23 +27,23 @@
2727 {{end}}2828 2929 {{define "file"}}{{if .Error}}<section><h1>File</h1>{{template "alert" .Error}}</section>30-{{else}}{{$file := asMap .Event}}{{$hash := or (.Query.Get "hash") (.Query.Get "sha")}}<section>30+{{else}}{{$file := asMap .Event}}{{$hash := or (.Query.Get "hash") (.Query.Get "sha")}}<section id="file-view">3131 <h1>File</h1>3232 <table id="facts">3333 <tr><th>sha256</th><td><code>{{str (index $file "sha256")}}</code></td></tr>3434 <tr><th>type</th><td>{{str (index $file "type")}}</td></tr>3535 <tr><th>size</th><td>{{str (index $file "size")}} bytes</td></tr>3636 {{with index $file "blossom_uri"}}<tr><th>blossom</th><td><code>{{.}}</code></td></tr>{{end}}37-<tr><th>download</th><td><a href="/files/raw?hash={{str (index $file "sha256")}}">raw</a></td></tr>37+<tr><th>download</th><td><a fx-ignore href="/files/raw?hash={{urlquery (str (index $file "sha256"))}}">raw</a></td></tr>3838 </table>39-</section>40-{{$type := str (index $file "type")}}{{$raw := printf "/files/raw?hash=%s" (str (index $file "sha256"))}}{{if hasPrefix $type "image/"}}<section id="media"><img src="{{$raw}}" alt=""></section>41-{{else if hasPrefix $type "video/"}}<section id="media"><video controls src="{{$raw}}"></video></section>42-{{else if hasPrefix $type "audio/"}}<section id="media"><audio controls src="{{$raw}}"></audio></section>43-{{else if eq $type "application/pdf"}}<section id="media"><a href="{{$raw}}">Open the PDF</a></section>44-{{else if index $file "binary"}}<section><p>This is a binary file. Download it to view its contents.</p></section>45-{{else}}{{sourceHTML .Event}}46-{{end}}{{if .Actor}}<section><details><summary>Manage file</summary><rpc-form method="deleteblob"><input type="hidden" name="param" value="{{$hash}}"><button>Delete file</button></rpc-form></details></section>{{end}}39+{{$type := str (index $file "type")}}{{$raw := printf "/files/raw?hash=%s" (urlquery (str (index $file "sha256")))}}{{if hasPrefix $type "image/"}}<div id="media"><img src="{{$raw}}" alt=""></div>40+{{else if hasPrefix $type "video/"}}<div id="media"><video controls src="{{$raw}}"></video></div>41+{{else if hasPrefix $type "audio/"}}<div id="media"><audio controls src="{{$raw}}"></audio></div>42+{{else if eq $type "application/pdf"}}<div id="media"><a fx-ignore href="{{$raw}}">Open the PDF</a></div>43+{{else if index $file "binary"}}<p id="media">This is a binary file. Download it to view its contents.</p>44+{{else if index $file "content"}}{{sourceHTML .Event}}45+{{else}}<p id="media">This file is empty.</p>46+{{end}}{{if .Actor}}<details id="manage-file"><summary>Manage file</summary><rpc-form method="deleteblob"><input type="hidden" name="param" value="{{$hash}}"><button>Delete file</button></rpc-form></details>{{end}}</section>4747 {{end}}{{end}}4848 4949 {{define "sites"}}<section>
M internal/webui/browse_test.go +26 -0
M internal/webui/public_pages.go +1 -1
M internal/webui/repo.html +1 -1
M internal/webui/shell_test.go +17 -0
M internal/webui/style.css +1 -0
M internal/webui/webui.go +20 -0
@@ -445,6 +445,7 @@ func (a *App) eventPage(writer http.ResponseWriter, request *http.Request) {
445445 return446446 }447447 data := PageData{Event: result, View: identifier, Tab: "event"}448+ data.Title = "Event " + shortID(identifier) + " | " + a.backend.Slug()448449 if address {449450 data.Feed = browseRows(result)450451 }
@@ -535,6 +536,7 @@ func (a *App) browse(writer http.ResponseWriter, request *http.Request) {
535536 pageQuery.Set("view", "tree")536537 }537538 data := PageData{Tab: browseTab(path), Feed: browseRows(result), Event: result, Query: pageQuery}539+ data.Title = browseTitle(path, pageQuery, result, a.backend.Slug())538540 if method == "browserepo" && pageQuery.Get("view") == "home" {539541 data.Readme = a.readme(request.Context(), actor, pageQuery)540542 }
@@ -542,6 +544,24 @@ func (a *App) browse(writer http.ResponseWriter, request *http.Request) {
542544 a.render(writer, request, data)543545 }544546 547+func browseTitle(path string, query url.Values, result any, slug string) string {548+ label := map[string]string{"/repos": "Repositories", "/files": "Files", "/file": "File"}[path]549+ if path == "/repo" {550+ label = query.Get("repo")551+ if label == "" {552+ label = plainString(valueMap(result)["identifier"])553+ }554+ if label == "" {555+ label = "Repository"556+ }557+ label += " | " + repoView(query)558+ }559+ if label == "" {560+ label = "Browse"561+ }562+ return label + " | " + slug563+}564+545565 // readme renders README.md from the requested ref for the repository entry546566 // page. A missing or binary README simply yields no content.547567 func (a *App) readme(ctx context.Context, actor string, query url.Values) template.HTML {