nirvash/archetype/fileManager.go

172 lines
3.3 KiB
Go
Raw Normal View History

package archetype
import (
2022-06-13 06:32:14 +00:00
"errors"
"io/ioutil"
2022-06-13 06:32:14 +00:00
"net/http"
"os"
"path/filepath"
"strings"
)
type SimpleFileManager struct {
Root string
ShowHtml bool
ShowHidden bool
}
type FileData struct {
Error string
Path string
Name string
IsDir bool
}
type FileListing struct {
Error string
Root string
Up string
SubDirs []string
Files []string
}
type FileManager interface {
Init(cfg *Config) error
// ListTree() FileListing
ListSubTree(root string) FileListing
GetFileData(slug string) FileData
2022-06-13 06:32:14 +00:00
AddFile(path string, req *http.Request) error
// MkDir(path string) error
2022-06-13 06:32:14 +00:00
Remove(path string) error
// Rename(old, new string) error
}
func (self *SimpleFileManager) Init(cfg *Config) error {
self.Root = filepath.Clean(cfg.StaticRoot)
self.ShowHtml = cfg.StaticShowHtml
self.ShowHidden = cfg.StaticShowHidden
return nil
}
func (self *SimpleFileManager) ListSubTree(root string) FileListing {
list := FileListing{}
if strings.Contains(root, "../") || strings.Contains(root, "..\\") {
list.Error = "You cannot escape!"
return list
}
fullPath := filepath.Join(self.Root, root)
files, err := ioutil.ReadDir(fullPath)
if err != nil {
list.Error = err.Error()
return list
}
list.Root = root
if !strings.HasSuffix(list.Root, "/") {
list.Root += "/"
}
if !strings.HasPrefix(list.Root, "/") {
list.Root = "/" + list.Root
}
levels := strings.Split(root, "/")
if list.Root != "/" {
list.Up = "/"
}
if len(levels) >= 2 {
list.Up = "/" + strings.Join(levels[:len(levels)-1], "/")
}
for _, file := range files {
if !self.ShowHidden && strings.HasPrefix(file.Name(), ".") {
continue
}
if file.IsDir() {
list.SubDirs = append(list.SubDirs, file.Name())
} else {
if !self.ShowHtml && strings.HasSuffix(file.Name(), ".html") {
continue
}
list.Files = append(list.Files, file.Name())
}
}
return list
}
func (self *SimpleFileManager) GetFileData(slug string) FileData {
fullPath := filepath.Join(self.Root, slug)
fileInfo, err := os.Stat(fullPath)
if err != nil {
return FileData{
Error: err.Error(),
}
}
if !strings.HasPrefix(fullPath, self.Root) {
return FileData{
Error: "You cannot escape!",
}
}
cleanedSlug := filepath.Clean(slug)
fileBase := filepath.Base(cleanedSlug)
return FileData{
Path: filepath.Clean(slug),
Name: fileBase,
IsDir: fileInfo.IsDir(),
}
}
2022-06-13 06:32:14 +00:00
func (self *SimpleFileManager) Remove(slug string) error {
fullPath := filepath.Join(self.Root, slug)
_, err := os.Stat(fullPath)
if err != nil {
return err
}
if !strings.HasPrefix(fullPath, self.Root) {
return errors.New("You cannot escape!")
}
return os.RemoveAll(fullPath)
}
func (self *SimpleFileManager) AddFile(path string, req *http.Request) error {
fullPath := filepath.Join(self.Root, path)
_, err := os.Stat(fullPath)
if err != nil {
return err
}
if !strings.HasPrefix(fullPath, filepath.Clean(self.Root)) {
return errors.New("You cannot escape!")
}
req.ParseMultipartForm(250 << 20)
file, header, err := req.FormFile("file")
if err != nil {
return err
}
fileData, err := ioutil.ReadAll(file)
if err != nil {
return err
}
destPath := filepath.Join(fullPath, header.Filename)
dest, err := os.Create(destPath)
if err != nil {
return err
}
defer dest.Close()
dest.Write(fileData)
return nil
}