package main import ( "crypto/md5" "crypto/sha256" "crypto/subtle" "encoding/hex" "fmt" "io" "net/http" "os" ) type FileInfo struct { Name string Path string Size int64 FormattedSize string Type string Content string } type TemplateData struct { Files []FileInfo URL string } func CheckAuth(r *http.Request, key string) bool { return r.Header.Get("X-Auth") == key } func FormatFileSize(size int64) string { if size < 1024 { return fmt.Sprintf("%d B", size) } else if size < 1024*1024 { return fmt.Sprintf("%.2f KB", float64(size)/1024) } else if size < 1024*1024*1024 { return fmt.Sprintf("%.2f MB", float64(size)/(1024*1024)) } return fmt.Sprintf("%.2f GB", float64(size)/(1024*1024*1024)) } func HashFile(file io.Reader, extension string) (string, error) { hasher := md5.New() if _, err := io.Copy(hasher, file); err != nil { return "", err } sha1Hash := hex.EncodeToString(hasher.Sum(nil))[:8] filename := fmt.Sprintf("%s%s", sha1Hash, extension) return filename, nil } func SaveFile(name string, file io.Reader) error { dst, err := os.Create(name) if err != nil { return err } defer dst.Close() if _, err := io.Copy(dst, file); err != nil { return err } return nil } func BasicAuth(next http.HandlerFunc, app *Application) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { username, password, ok := r.BasicAuth() if ok { // hash password received usernameHash := sha256.Sum256([]byte(username)) passwordHash := sha256.Sum256([]byte(password)) // hash our password expectedUsernameHash := sha256.Sum256([]byte(app.auth.username)) expectedPasswordHash := sha256.Sum256([]byte(app.auth.password)) // compare hashes usernameMatch := (subtle.ConstantTimeCompare(usernameHash[:], expectedUsernameHash[:]) == 1) passwordMatch := (subtle.ConstantTimeCompare(passwordHash[:], expectedPasswordHash[:]) == 1) if usernameMatch && passwordMatch { next.ServeHTTP(w, r) return } } w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8`) http.Error(w, "Unauthorized", http.StatusUnauthorized) }) }