shithub: img

Download patch

ref: d6fc20a67e1128c101617581bba6a17592699876
parent: f17f591d30d890670005da4e262ddd7f6e755841
author: Alex Musolino <alex@musolino.id.au>
date: Fri Jan 9 08:16:45 EST 2026

imgsrv.go: allow images tagged "public" to be accessed without auth

--- a/imgsrv.go
+++ b/imgsrv.go
@@ -7,6 +7,7 @@
 	"net/http"
 	"os"
 	"path"
+	"slices"
 	"sort"
 	"strings"
 	"sync"
@@ -26,6 +27,9 @@
 }
 
 func (h *YearIndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if !checkauth(w, r) {
+		return
+	}
 	if r.URL.Path == "montage.jpg" {
 		http.ServeFile(w, r, fmt.Sprintf("%s/montage.jpg", h.Idx.Path))
 		return
@@ -66,12 +70,20 @@
 	Tags *Tags
 }
 
+func imageNameFromJpeg(jpeg string) string {
+	name, _ := strings.CutSuffix(strings.ToLower(jpeg), ".jpg")
+	for _, suffix := range []string{".big", ".medium", ".full", ".small", ".thumb"} {
+		name, _ = strings.CutSuffix(name, suffix)
+	}
+	return name
+}
+
 func (h *AlbumIndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	relpath := strings.TrimPrefix(r.URL.Path, "/")
-	switch relpath {
-	case "":
-		fallthrough
-	case "index.html":
+	if relpath == "" || relpath == "index.html" {
+		if !checkauth(w, r) {
+			return
+		}
 		type TplImgData struct {
 			ID string
 			Prefix string
@@ -115,6 +127,9 @@
 		return
 	}
 	if strings.HasSuffix(relpath, ".html") {
+		if !checkauth(w, r) {
+			return
+		}
 		type TplData struct {
 			Title string
 			UpText string
@@ -147,6 +162,12 @@
 		return
 	}
 	if strings.HasSuffix(strings.ToLower(relpath), ".jpg") {
+		image := imageNameFromJpeg(relpath)
+		if !slices.Contains(h.Tags.TagsForImage(image), "public") {
+			if !checkauth(w, r) {
+				return
+			}
+		}
 		w.Header().Add("cache-control", "private, max-age=3600")
 		http.ServeFile(w, r, fmt.Sprintf("%s/%s", h.Idx.Path, r.URL.Path))
 		return
@@ -161,6 +182,9 @@
 }
 
 func (h *MainIndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if !checkauth(w, r) {
+		return
+	}
 	type TplData struct {
 		Title string
 		Years sort.StringSlice
@@ -280,11 +304,6 @@
 	Images map[string]struct{}
 }
 
-func (db *ImgDB) imageExists(img string) bool {
-	_, exists := db.Images[img]
-	return exists
-}
-
 func (db *ImgDB) nextMonth(y0 string, m0, step int) *AlbumIdx {
 	var years []string
 	for y := range db.Years {
@@ -614,12 +633,15 @@
 }
 
 func (h *TagApiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if !checkauth(w, r) {
+		return
+	}
 	if err := r.ParseForm(); err != nil {
 		http.Error(w, "bad request", 400)
 		return
 	}
 	img := r.FormValue("image")
-	if !h.DB.imageExists(img) {
+	if _, exists := h.DB.Images[img]; !exists {
 		http.Error(w, "not found", 404)
 		return
 	}
@@ -657,6 +679,9 @@
 }
 
 func (h *TagIndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	if !checkauth(w, r) {
+		return
+	}
 	parts := strings.Split(r.URL.Path, "/")
 	if len(parts) == 1 && !strings.HasSuffix(r.URL.Path, "/") {
 		http.Redirect(w, r, fmt.Sprintf("/tags/%s/", parts[0]), http.StatusSeeOther)
@@ -705,25 +730,15 @@
 	To uint
 }
 
-type BasicAuthMux struct {
-	serveMux *http.ServeMux
-}
-
-func NewBasicAuthMux(serveMux *http.ServeMux) *BasicAuthMux {
-	return &BasicAuthMux{
-		serveMux: serveMux,
-	}
-}
-
-func (basicAuthMux *BasicAuthMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+func checkauth(w http.ResponseWriter, r *http.Request) bool {
 	user, pass, ok := r.BasicAuth()
 	if !ok || user != "alex" || pass != "holyidentitytheftbatman!" {
 		w.Header().Set("WWW-Authenticate", "Basic realm=PAIN")
 		status := http.StatusUnauthorized
 		http.Error(w, http.StatusText(status), status)
-		return
+		return false
 	}
-	basicAuthMux.serveMux.ServeHTTP(w, r)
+	return true
 }
 
 func main() {
@@ -763,5 +778,5 @@
 		mux.Handle(prefix, http.StripPrefix(prefix, &AlbumIndexHandler{idx, templates.Album, templates.Image, tags}))
 	}
 	mux.Handle("/", &MainIndexHandler{db, templates.Main, tags})
-	log.Fatal(http.ListenAndServeTLS(":8080", "imgsrv.cert.pem", "imgsrv.key.pem", NewBasicAuthMux(mux)))
+	log.Fatal(http.ListenAndServeTLS(":8080", "imgsrv.cert.pem", "imgsrv.key.pem", mux))
 }
--