diff --git a/caddy/filemanager/filemanager.go b/caddy/filemanager/filemanager.go index 35d5e06d..948de73d 100644 --- a/caddy/filemanager/filemanager.go +++ b/caddy/filemanager/filemanager.go @@ -13,7 +13,7 @@ import ( "strings" . "github.com/hacdias/filemanager" - "github.com/hacdias/filemanager/dir" + "github.com/hacdias/fileutils" "github.com/mholt/caddy" "github.com/mholt/caddy/caddyhttp/httpserver" ) @@ -136,7 +136,7 @@ func parse(c *caddy.Controller) ([]*config, error) { Regexp: &Regexp{Raw: "\\/\\..+"}, }}, CSS: "", - FileSystem: dir.Dir(baseScope), + FileSystem: fileutils.Dir(baseScope), }) if err != nil { diff --git a/caddy/hugo/setup.go b/caddy/hugo/setup.go index 3e8120f0..044e086a 100644 --- a/caddy/hugo/setup.go +++ b/caddy/hugo/setup.go @@ -12,7 +12,7 @@ import ( "strings" "github.com/hacdias/filemanager" - "github.com/hacdias/filemanager/dir" + "github.com/hacdias/fileutils" "github.com/mholt/caddy" "github.com/mholt/caddy/caddyhttp/httpserver" ) @@ -112,7 +112,7 @@ func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) { Regexp: &filemanager.Regexp{Raw: "\\/\\..+"}, }}, CSS: "", - FileSystem: dir.Dir(directory), + FileSystem: fileutils.Dir(directory), }) if err != nil { diff --git a/cmd/filemanager/main.go b/cmd/filemanager/main.go index b15e635b..b3b80da3 100644 --- a/cmd/filemanager/main.go +++ b/cmd/filemanager/main.go @@ -11,7 +11,7 @@ import ( "strings" "github.com/hacdias/filemanager" - "github.com/hacdias/filemanager/dir" + "github.com/hacdias/fileutils" ) // confFile contains the configuration file for this File Manager instance. @@ -65,7 +65,7 @@ func main() { Commands: strings.Split(strings.TrimSpace(commands), " "), Rules: []*filemanager.Rule{}, CSS: "", - FileSystem: dir.Dir(scope), + FileSystem: fileutils.Dir(scope), }) if err != nil { diff --git a/dir/dir.go b/dir/dir.go deleted file mode 100644 index 1e5ed0b1..00000000 --- a/dir/dir.go +++ /dev/null @@ -1,230 +0,0 @@ -// Package dir implements a FileSystem interface using the native -// file system restricted to a specific directory tree. Originally from -// https://github.com/golang/net/blob/master/webdav/file.go#L68 -package dir - -import ( - "errors" - "io" - "os" - "path" - "path/filepath" - "strings" -) - -// A Dir uses the native file system restricted to a specific directory tree. -// -// While the FileSystem.OpenFile method takes '/'-separated paths, a Dir's -// string value is a filename on the native file system, not a URL, so it is -// separated by filepath.Separator, which isn't necessarily '/'. -// -// An empty Dir is treated as ".". -type Dir string - -func (d Dir) resolve(name string) string { - // This implementation is based on Dir.Open's code in the standard net/http package. - if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || - strings.Contains(name, "\x00") { - return "" - } - - dir := string(d) - if dir == "" { - dir = "." - } - - return filepath.Join(dir, filepath.FromSlash(SlashClean(name))) -} - -// Mkdir implements os.Mkdir in this directory context. -func (d Dir) Mkdir(name string, perm os.FileMode) error { - if name = d.resolve(name); name == "" { - return os.ErrNotExist - } - return os.Mkdir(name, perm) -} - -// OpenFile implements os.OpenFile in this directory context. -func (d Dir) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { - if name = d.resolve(name); name == "" { - return nil, os.ErrNotExist - } - f, err := os.OpenFile(name, flag, perm) - if err != nil { - return nil, err - } - return f, nil -} - -// RemoveAll implements os.RemoveAll in this directory context. -func (d Dir) RemoveAll(name string) error { - if name = d.resolve(name); name == "" { - return os.ErrNotExist - } - - if name == filepath.Clean(string(d)) { - // Prohibit removing the virtual root directory. - return os.ErrInvalid - } - return os.RemoveAll(name) -} - -// Rename implements os.Rename in this directory context. -func (d Dir) Rename(oldName, newName string) error { - if oldName = d.resolve(oldName); oldName == "" { - return os.ErrNotExist - } - if newName = d.resolve(newName); newName == "" { - return os.ErrNotExist - } - if root := filepath.Clean(string(d)); root == oldName || root == newName { - // Prohibit renaming from or to the virtual root directory. - return os.ErrInvalid - } - return os.Rename(oldName, newName) -} - -// Stat implements os.Stat in this directory context. -func (d Dir) Stat(name string) (os.FileInfo, error) { - if name = d.resolve(name); name == "" { - return nil, os.ErrNotExist - } - - return os.Stat(name) -} - -// Copy copies a file or directory from src to dst. If it is -// a directory, all of the files and sub-directories will be copied. -func (d Dir) Copy(src, dst string) error { - if src = d.resolve(src); src == "" { - return os.ErrNotExist - } - - if dst = d.resolve(dst); dst == "" { - return os.ErrNotExist - } - - if root := filepath.Clean(string(d)); root == src || root == dst { - // Prohibit copying from or to the virtual root directory. - return os.ErrInvalid - } - - if dst == src { - return os.ErrInvalid - } - - info, err := os.Stat(src) - if err != nil { - return err - } - - if info.IsDir() { - return CopyDir(src, dst) - } - - return CopyFile(src, dst) -} - -// SlashClean is equivalent to but slightly more efficient than -// path.Clean("/" + name). -func SlashClean(name string) string { - if name == "" || name[0] != '/' { - name = "/" + name - } - return path.Clean(name) -} - -// CopyFile copies a file from source to dest and returns -// an error if any. -func CopyFile(source string, dest string) error { - // Open the source file. - src, err := os.Open(source) - if err != nil { - return err - } - defer src.Close() - - // Makes the directory needed to create the dst - // file. - err = os.MkdirAll(filepath.Dir(dest), 0666) - if err != nil { - return err - } - - // Create the destination file. - dst, err := os.Create(dest) - if err != nil { - return err - } - defer dst.Close() - - // Copy the contents of the file. - _, err = io.Copy(dst, src) - if err != nil { - return err - } - - // Copy the mode if the user can't - // open the file. - info, err := os.Stat(source) - if err != nil { - err = os.Chmod(dest, info.Mode()) - if err != nil { - return err - } - } - - return nil -} - -// CopyDir copies a directory from source to dest and all -// of its sub-directories. It doesn't stop if it finds an error -// during the copy. Returns an error if any. -func CopyDir(source string, dest string) error { - // Get properties of source. - srcinfo, err := os.Stat(source) - if err != nil { - return err - } - - // Create the destination directory. - err = os.MkdirAll(dest, srcinfo.Mode()) - if err != nil { - return err - } - - dir, _ := os.Open(source) - obs, err := dir.Readdir(-1) - - var errs []error - - for _, obj := range obs { - fsource := source + "/" + obj.Name() - fdest := dest + "/" + obj.Name() - - if obj.IsDir() { - // Create sub-directories, recursively. - err = CopyDir(fsource, fdest) - if err != nil { - errs = append(errs, err) - } - } else { - // Perform the file copy. - err = CopyFile(fsource, fdest) - if err != nil { - errs = append(errs, err) - } - } - } - - var errString string - for _, err := range errs { - errString += err.Error() + "\n" - } - - if errString != "" { - return errors.New(errString) - } - - return nil -} diff --git a/download.go b/download.go index 2d59ab48..5b6a5130 100644 --- a/download.go +++ b/download.go @@ -9,7 +9,7 @@ import ( "path/filepath" "strings" - "github.com/hacdias/filemanager/dir" + "github.com/hacdias/fileutils" "github.com/mholt/archiver" ) @@ -45,7 +45,7 @@ func downloadHandler(c *RequestContext, w http.ResponseWriter, r *http.Request) } // Clean the slashes. - name = dir.SlashClean(name) + name = fileutils.SlashClean(name) files = append(files, filepath.Join(c.FI.Path, name)) } } else { diff --git a/filemanager.go b/filemanager.go index c4b4e043..7d2d8d25 100644 --- a/filemanager.go +++ b/filemanager.go @@ -11,7 +11,7 @@ import ( rice "github.com/GeertJohan/go.rice" "github.com/asdine/storm" - "github.com/hacdias/filemanager/dir" + "github.com/hacdias/fileutils" "github.com/mholt/caddy" ) @@ -76,7 +76,7 @@ type User struct { Admin bool `json:"admin"` // FileSystem is the virtual file system the user has access. - FileSystem dir.Dir `json:"filesystem"` + FileSystem fileutils.Dir `json:"filesystem"` // Rules is an array of access and deny rules. Rules []*Rule `json:"rules"` @@ -136,7 +136,7 @@ var DefaultUser = User{ Rules: []*Rule{}, CSS: "", Admin: true, - FileSystem: dir.Dir("."), + FileSystem: fileutils.Dir("."), } // New creates a new File Manager instance. If 'database' file already diff --git a/filemanager_test.go b/filemanager_test.go index 2fa524df..cca8a1ce 100644 --- a/filemanager_test.go +++ b/filemanager_test.go @@ -6,7 +6,7 @@ import ( "path/filepath" "testing" - "github.com/hacdias/filemanager/dir" + "github.com/hacdias/fileutils" ) type test struct { @@ -28,13 +28,13 @@ func newTest(t *testing.T) *test { scope := filepath.Join(temp, "scope") database := filepath.Join(temp, "database.db") - err = dir.CopyDir("./testdata", scope) + err = fileutils.CopyDir("./testdata", scope) if err != nil { t.Fatalf("Error copying the test data: %v", err) } user := DefaultUser - user.FileSystem = dir.Dir(scope) + user.FileSystem = fileutils.Dir(scope) fm, err := New(database, user) diff --git a/resource.go b/resource.go index 8626aeda..1e1766d3 100644 --- a/resource.go +++ b/resource.go @@ -10,13 +10,13 @@ import ( "path/filepath" "strings" - "github.com/hacdias/filemanager/dir" + "github.com/hacdias/fileutils" ) // sanitizeURL sanitizes the URL to prevent path transversal -// using dir.SlashClean and adds the trailing slash bar. +// using fileutils.SlashClean and adds the trailing slash bar. func sanitizeURL(url string) string { - path := dir.SlashClean(url) + path := fileutils.SlashClean(url) if strings.HasSuffix(url, "/") && path != "/" { return path + "/" }