about summary refs log tree commit diff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/soju-upload.patch222
1 files changed, 222 insertions, 0 deletions
diff --git a/packages/soju-upload.patch b/packages/soju-upload.patch
new file mode 100644
index 0000000..03efe76
--- /dev/null
+++ b/packages/soju-upload.patch
@@ -0,0 +1,222 @@
+diff --git i/fileupload/fileupload.go w/fileupload/fileupload.go
+index 07fccf1..55104f8 100644
+--- i/fileupload/fileupload.go
++++ w/fileupload/fileupload.go
+@@ -7,6 +7,7 @@ import (
+ 	"errors"
+ 	"fmt"
+ 	"io"
++	"log"
+ 	"mime"
+ 	"net/http"
+ 	"net/url"
+@@ -153,30 +154,35 @@ func (h *Handler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
+ 		return
+ 	}
+ 
++	var err error
+ 	switch req.Method {
+ 	case http.MethodOptions:
+ 		resp.WriteHeader(http.StatusNoContent)
+ 	case http.MethodHead, http.MethodGet:
+-		h.fetch(resp, req)
++		err = h.fetch(resp, req)
+ 	case http.MethodPost:
+-		h.store(resp, req)
++		err = h.store(resp, req)
+ 	default:
+ 		http.Error(resp, "only OPTIONS, HEAD, GET and POST are allowed", http.StatusMethodNotAllowed)
++		err = errors.New(http.StatusText(http.StatusMethodNotAllowed))
++	}
++	if err != nil {
++		log.Printf("upload: %s", err.Error())
+ 	}
+ }
+ 
+-func (h *Handler) fetch(resp http.ResponseWriter, req *http.Request) {
++func (h *Handler) fetch(resp http.ResponseWriter, req *http.Request) error {
+ 	prefix := "/uploads/"
+ 	if !strings.HasPrefix(req.URL.Path, prefix) {
+ 		http.Error(resp, "invalid path", http.StatusNotFound)
+-		return
++		return fmt.Errorf("invalid path")
+ 	}
+ 
+ 	filename := strings.TrimPrefix(req.URL.Path, prefix)
+ 	filename = path.Join("/", filename)[1:] // prevent directory traversal
+ 	if filename == "" {
+ 		http.Error(resp, "invalid path", http.StatusNotFound)
+-		return
++		return fmt.Errorf("invalid path")
+ 	}
+ 
+ 	basename, modTime, content, err := h.Uploader.load(req.Context(), filename)
+@@ -184,10 +190,10 @@ func (h *Handler) fetch(resp http.ResponseWriter, req *http.Request) {
+ 		var httpErr *httpError
+ 		if errors.As(err, &httpErr) {
+ 			httpErr.Write(resp)
+-			return
++			return err
+ 		}
+ 		http.Error(resp, "failed to open file", http.StatusNotFound)
+-		return
++		return fmt.Errorf("failed to open file: %v", err)
+ 	}
+ 	defer content.Close()
+ 
+@@ -200,7 +206,7 @@ func (h *Handler) fetch(resp http.ResponseWriter, req *http.Request) {
+ 		_, err := content.Seek(0, io.SeekStart) // rewind to output whole file
+ 		if err != nil {
+ 			http.Error(resp, "failed to seek file", http.StatusInternalServerError)
+-			return
++			return fmt.Errorf("failed to seek file: %v", err)
+ 		}
+ 	}
+ 
+@@ -219,18 +225,20 @@ func (h *Handler) fetch(resp http.ResponseWriter, req *http.Request) {
+ 	resp.Header().Set("Content-Disposition", contentDisp)
+ 
+ 	http.ServeContent(resp, req, basename, modTime, content)
++
++	return nil
+ }
+ 
+-func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
++func (h *Handler) store(resp http.ResponseWriter, req *http.Request) error {
+ 	if req.URL.Path != "/uploads" {
+ 		http.Error(resp, "invalid path", http.StatusNotFound)
+-		return
++		return fmt.Errorf("invalid path")
+ 	}
+ 
+ 	authz := req.Header.Get("Authorization")
+ 	if authz == "" {
+ 		http.Error(resp, "missing Authorization header", http.StatusUnauthorized)
+-		return
++		return fmt.Errorf("missing Authorization header")
+ 	}
+ 
+ 	var (
+@@ -243,26 +251,26 @@ func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
+ 		plainAuth := h.Auth.Plain
+ 		if plainAuth == nil {
+ 			http.Error(resp, "Basic scheme in Authorization header not supported", http.StatusBadRequest)
+-			return
++			return fmt.Errorf("Basic scheme in Authorization header not supported")
+ 		}
+ 		var password string
+ 		var ok bool
+ 		username, password, ok = req.BasicAuth()
+ 		if !ok {
+ 			http.Error(resp, "invalid Authorization header", http.StatusBadRequest)
+-			return
++			return fmt.Errorf("invalid Authorization header")
+ 		}
+ 		err = plainAuth.AuthPlain(req.Context(), h.DB, username, password)
+ 	case "bearer":
+ 		oauthAuth := h.Auth.OAuthBearer
+ 		if oauthAuth == nil {
+ 			http.Error(resp, "Bearer scheme in Authorization header not supported", http.StatusBadRequest)
+-			return
++			return fmt.Errorf("Bearer scheme in Authorization header not supported")
+ 		}
+ 		username, err = oauthAuth.AuthOAuthBearer(req.Context(), h.DB, param)
+ 	default:
+ 		http.Error(resp, "unsupported Authorization header scheme", http.StatusBadRequest)
+-		return
++		return fmt.Errorf("unsupported Authorization header scheme")
+ 	}
+ 	if err != nil {
+ 		var msg string
+@@ -272,7 +280,7 @@ func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
+ 			msg = "authentication failed"
+ 		}
+ 		http.Error(resp, msg, http.StatusForbidden)
+-		return
++		return fmt.Errorf("%s: %v", msg, err)
+ 	}
+ 
+ 	var mimeType string
+@@ -284,7 +292,7 @@ func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
+ 		mimeType, params, err = mime.ParseMediaType(contentType)
+ 		if err != nil {
+ 			http.Error(resp, "failed to parse Content-Type", http.StatusBadRequest)
+-			return
++			return fmt.Errorf("failed to parse Content-Type: %v", err)
+ 		}
+ 		if mimeType == "application/octet-stream" {
+ 			mimeType = ""
+@@ -295,7 +303,7 @@ func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
+ 			// OK
+ 		default:
+ 			http.Error(resp, "unsupported charset", http.StatusUnsupportedMediaType)
+-			return
++			return fmt.Errorf("unsupported charset")
+ 		}
+ 	}
+ 
+@@ -304,7 +312,7 @@ func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
+ 		_, params, err := mime.ParseMediaType(contentDisp)
+ 		if err != nil {
+ 			http.Error(resp, "failed to parse Content-Disposition", http.StatusBadRequest)
+-			return
++			return fmt.Errorf("failed to parse Content-Disposition: %v", err)
+ 		}
+ 		basename = path.Base(params["filename"])
+ 	}
+@@ -325,7 +333,7 @@ func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
+ 		var httpErr *httpError
+ 		if errors.As(err, &httpErr) {
+ 			httpErr.Write(resp)
+-			return
++			return err
+ 		}
+ 		status := http.StatusInternalServerError
+ 		var maxBytesErr *http.MaxBytesError
+@@ -335,19 +343,21 @@ func (h *Handler) store(resp http.ResponseWriter, req *http.Request) {
+ 			resp.Header().Set("Upload-Limit", fmt.Sprintf("maxsize=%v", maxBytesErr.Limit))
+ 		}
+ 		http.Error(resp, "failed to write file", status)
+-		return
++		return fmt.Errorf("failed to write file: %v", err)
+ 	}
+ 
+ 	u, err := url.Parse(out)
+ 	if err != nil {
+ 		http.Error(resp, "failed to write file", http.StatusInternalServerError)
+-		return
++		return fmt.Errorf("failed to write file: %v", err)
+ 	}
+-	baseURL := url.URL{Path: "/uploads/"}
++	baseURL := url.URL{Path: "/_irc/uploads/"}
+ 	out = baseURL.ResolveReference(u).String()
+ 
+ 	resp.Header().Set("Location", out)
+ 	resp.WriteHeader(http.StatusCreated)
++
++	return nil
+ }
+ 
+ func generateToken(n int) (string, error) {
+diff --git i/fileupload/fs.go w/fileupload/fs.go
+index c0c401d..66337a1 100644
+--- i/fileupload/fs.go
++++ w/fileupload/fs.go
+@@ -56,7 +56,7 @@ func (fs *fileuploadFS) store(ctx context.Context, r io.Reader, username, mimeTy
+ 	}
+ 
+ 	dir := filepath.Join(fs.dir, username)
+-	if err := os.MkdirAll(dir, 0700); err != nil {
++	if err := os.MkdirAll(dir, 0755); err != nil {
+ 		return "", fmt.Errorf("failed to create user upload directory: %w", err)
+ 	}
+ 
+@@ -77,7 +77,7 @@ func (fs *fileuploadFS) store(ctx context.Context, r io.Reader, username, mimeTy
+ 		}
+ 		basename += suffix
+ 
+-		f, err = os.OpenFile(filepath.Join(dir, basename), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
++		f, err = os.OpenFile(filepath.Join(dir, basename), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
+ 		if err == nil {
+ 			break
+ 		} else if !os.IsExist(err) {

Consider giving Nix/NixOS a try! <3