63 lines
1.2 KiB
Go
63 lines
1.2 KiB
Go
package adapters
|
|
|
|
import (
|
|
"errors"
|
|
"mime"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func SafeRel(root, requested string) (string, error) {
|
|
s := requested
|
|
if after, ok := strings.CutPrefix(s, "/"); ok {
|
|
s = after
|
|
}
|
|
full := filepath.Join(root, filepath.FromSlash(s))
|
|
rel, err := filepath.Rel(root, full)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if rel == "." {
|
|
return "/", nil
|
|
}
|
|
sep := string(filepath.Separator)
|
|
if strings.HasPrefix(rel, "..") || strings.Contains(rel, ".."+sep) {
|
|
return "", errors.New("path escapes root")
|
|
}
|
|
return "/" + filepath.ToSlash(rel), nil
|
|
}
|
|
|
|
func ResponsePath(root, full string) string {
|
|
rel, err := filepath.Rel(root, full)
|
|
if err != nil || rel == "." {
|
|
return "/"
|
|
}
|
|
return "/" + filepath.ToSlash(rel)
|
|
}
|
|
|
|
var textPlainExtensions = map[string]bool{
|
|
".txt": true,
|
|
".log": true,
|
|
".json": true,
|
|
".yaml": true,
|
|
".yml": true,
|
|
".toml": true,
|
|
".xml": true,
|
|
".csv": true,
|
|
}
|
|
|
|
func contentTypeFor(name string) string {
|
|
ext := strings.ToLower(filepath.Ext(name))
|
|
switch ext {
|
|
case ".md", ".markdown", ".mdown":
|
|
return "application/markdown"
|
|
}
|
|
if ct := mime.TypeByExtension(ext); ct != "" {
|
|
return ct
|
|
}
|
|
if textPlainExtensions[ext] {
|
|
return "text/plain; charset=utf-8"
|
|
}
|
|
return "application/octet-stream"
|
|
}
|