implemented http server
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SharedLocation struct {
|
||||
// relative to config path at first,
|
||||
// then [normalize] makes it absolute
|
||||
Path string `toml:"path"`
|
||||
// [normalize] removes trailing '/'
|
||||
// so "/" becomes ""
|
||||
Url string `toml:"url"`
|
||||
ReadPassword string `toml:"read_password"`
|
||||
WritePassword string `toml:"write_password"`
|
||||
}
|
||||
|
||||
func (sh *SharedLocation) normalize(configDir string) error {
|
||||
if sh.Path == "" {
|
||||
return errors.New("share.path is empty")
|
||||
}
|
||||
// get absolute path for configDir
|
||||
configDirAbs, err := filepath.Abs(configDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// resolve symlinks
|
||||
configDirAbs, err = filepath.EvalSymlinks(configDirAbs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// fix separators
|
||||
shPathOsSep, err := filepath.Localize(sh.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// join configDir with sh.Path
|
||||
sh.Path = filepath.Join(configDirAbs, shPathOsSep)
|
||||
|
||||
if sh.Url == "" {
|
||||
return errors.New("share.url is empty")
|
||||
}
|
||||
if sh.Url[0] != '/' {
|
||||
return errors.New("share.url doesn't start with slash: '" + sh.Url + "'")
|
||||
}
|
||||
// remove trailing slash
|
||||
sh.Url = strings.TrimRight(sh.Url, "/")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sh *SharedLocation) String() string {
|
||||
var r, w string
|
||||
if sh.ReadPassword == "" {
|
||||
r = "public"
|
||||
} else {
|
||||
r = "password"
|
||||
}
|
||||
if sh.WritePassword == "" {
|
||||
w = "no"
|
||||
} else {
|
||||
w = "password"
|
||||
}
|
||||
url := sh.Url
|
||||
if url == "" {
|
||||
url = "/"
|
||||
}
|
||||
return "share '" + url + "' r:" + r + " w:" + w +
|
||||
" -> '" + sh.Path + "'"
|
||||
}
|
||||
|
||||
func (sh *SharedLocation) mkdir() error {
|
||||
return os.MkdirAll(sh.Path, 0o755)
|
||||
}
|
||||
|
||||
type UrlStatus uint32
|
||||
|
||||
const (
|
||||
UrlFile = UrlStatus(iota)
|
||||
UrlDir
|
||||
UrlNotFound
|
||||
UrlForbidden
|
||||
UrlIncorrect
|
||||
)
|
||||
|
||||
// returns calculated path, or input url if it doesn't belong to any share
|
||||
func (shares Shares) MapUrl(url string) (string, *SharedLocation, UrlStatus) {
|
||||
if url == "" || url[0] != '/' {
|
||||
return "", nil, UrlIncorrect
|
||||
}
|
||||
for _, sh := range shares {
|
||||
pathInShare, ok := strings.CutPrefix(url, sh.Url)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if pathInShare != "" && pathInShare[0] != '/' {
|
||||
// url is not sh.Url or child of it
|
||||
continue
|
||||
}
|
||||
pathAbs := filepath.Join(sh.Path, filepath.FromSlash(pathInShare))
|
||||
|
||||
fi, err := os.Stat(pathAbs)
|
||||
switch {
|
||||
case errors.Is(err, fs.ErrNotExist):
|
||||
return pathAbs, sh, UrlNotFound
|
||||
case err != nil:
|
||||
return pathAbs, sh, UrlForbidden
|
||||
case fi.IsDir():
|
||||
return pathAbs, sh, UrlDir
|
||||
default:
|
||||
return pathAbs, sh, UrlFile
|
||||
}
|
||||
}
|
||||
return url, nil, UrlNotFound
|
||||
}
|
||||
Reference in New Issue
Block a user