backend filepicker GET

This commit is contained in:
Radon 2025-09-03 08:32:18 -05:00
parent 81b7746238
commit 739acadc9c
3 changed files with 118 additions and 0 deletions

63
hub.go
View File

@ -5,7 +5,10 @@ import (
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"radchat/server"
"strings"
)
func IsUsernameTaken(h *server.Hub, username string) bool {
@ -144,6 +147,66 @@ func HandleWebSocket(hub *server.Hub, w http.ResponseWriter, r *http.Request) {
go ReadPump(client)
}
func HandleUserFiles(h *server.Hub, uploadsDir string, w http.ResponseWriter, r *http.Request) {
// get will essentially serve the uploads folder as a static folder so someone can get something from it
// put/post will allow you to upload files to the uploads folder
_ = h
switch r.Method {
case "POST":
fallthrough
case "PUT":
// TODO: Implement uploading!
// upload files to the uploads folder
case "GET":
path := strings.TrimPrefix(r.URL.Path, "/")
segments := strings.Split(path, "/")
if len(segments) < 2 {
http.Error(w, "Filename required", http.StatusBadRequest)
return
}
filename := segments[len(segments)-1]
filename = SanitizeFilename(filename)
if filename == "" {
http.Error(w, "Invalid filename", http.StatusBadRequest)
return
}
filePath := filepath.Join(uploadsDir, filename)
fmt.Println(filePath)
absUploadsDir, err := filepath.Abs(uploadsDir)
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
absFilePath, err := filepath.Abs(filePath)
if err != nil {
http.Error(w, "Invalid file path", http.StatusBadRequest)
return
}
if !strings.HasPrefix(absFilePath, absUploadsDir) {
http.Error(w, "Access denied", http.StatusForbidden)
return
}
if _, err := os.Stat(filePath); os.IsNotExist(err) {
http.Error(w, "File not found", http.StatusNotFound)
return
}
http.ServeFile(w, r, filePath)
}
}
func Run(h *server.Hub) {
log.Println("Hub started and running...")
for {

13
main.go
View File

@ -5,6 +5,7 @@ import (
"fmt"
"log"
"net/http"
"path/filepath"
"radchat/server"
)
@ -14,6 +15,7 @@ func main() {
var bufSize = flag.Int("bufsize", 256, "Channel buffer size")
var gzipEnabled = flag.Bool("gzip-enable", false, "Enable gzip compression")
var cachingDisabled = flag.Bool("cache-disable", false, "Disable caching")
var filesDirectory = flag.String("files", "./files", "Directory to store upload files")
var origin = flag.String("origin", "", "Origin to allow (e.g. example.com), leave blank to allow all")
var help = flag.Bool("help", false, "Show help")
@ -24,6 +26,13 @@ func main() {
return
}
filesDir, err := filepath.Abs(*filesDirectory)
_ = DeleteDirContents(filesDir)
err = MakeDir(filesDir)
if err != nil {
log.Fatal(err)
}
address := fmt.Sprintf("%s:%d", *ip, *port)
hub := server.NewHub(*bufSize, server.Upgrader(*origin, *origin == ""))
@ -31,6 +40,10 @@ func main() {
mux := http.NewServeMux()
mux.HandleFunc("/files/", func(w http.ResponseWriter, r *http.Request) {
HandleUserFiles(hub, filesDir, w, r)
})
mux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
HandleWebSocket(hub, w, r)
})

View File

@ -4,10 +4,40 @@ import (
"crypto/sha256"
"encoding/hex"
"fmt"
"os"
"path/filepath"
"strings"
"time"
)
func MakeDir(dirname string) error {
if _, err := os.Stat(dirname); os.IsNotExist(err) {
return os.Mkdir(dirname, 0666)
}
return nil
}
func DeleteDirContents(dirname string) error {
entries, err := os.ReadDir(dirname)
if err != nil {
return err
}
for _, entry := range entries {
if entry.IsDir() {
err := os.RemoveAll(filepath.Join(dirname, entry.Name()))
if err != nil {
return err
}
} else {
err := os.Remove(filepath.Join(dirname, entry.Name()))
if err != nil {
return err
}
}
}
return nil
}
func IsUsernameValid(username string) bool {
minLength := 3
maxLength := 24
@ -45,3 +75,15 @@ func GenerateId() string {
hash := sha256.Sum256([]byte(data))
return hex.EncodeToString(hash[:])[:16]
}
func SanitizeFilename(filename string) string {
filename = strings.ReplaceAll(filename, "/", "")
filename = strings.ReplaceAll(filename, "\\", "")
filename = strings.ReplaceAll(filename, "..", "")
filename = strings.TrimSpace(filename)
if strings.HasPrefix(filename, ".") || filename == "" {
return ""
}
return filename
}