|
|
@ -21,6 +21,16 @@ type Browse struct { |
|
|
|
} |
|
|
|
|
|
|
|
func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *http.Request) error { |
|
|
|
// navigation on the client-side gets messed up if the
|
|
|
|
// URL doesn't end in a trailing slash because hrefs like
|
|
|
|
// "/b/c" on a path like "/a" end up going to "/b/c" instead
|
|
|
|
// of "/a/b/c" - so we have to redirect in this case
|
|
|
|
if !strings.HasSuffix(r.URL.Path, "/") { |
|
|
|
r.URL.Path += "/" |
|
|
|
http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently) |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
dir, err := fsrv.openFile(dirPath, w) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
@ -29,7 +39,8 @@ func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *ht |
|
|
|
|
|
|
|
repl := r.Context().Value(caddy2.ReplacerCtxKey).(caddy2.Replacer) |
|
|
|
|
|
|
|
listing, err := fsrv.loadDirectoryContents(dir, r.URL.Path, repl) |
|
|
|
// calling path.Clean here prevents weird breadcrumbs when URL paths are sketchy like /%2e%2e%2f
|
|
|
|
listing, err := fsrv.loadDirectoryContents(dir, path.Clean(r.URL.Path), repl) |
|
|
|
switch { |
|
|
|
case os.IsPermission(err): |
|
|
|
return caddyhttp.Error(http.StatusForbidden, err) |
|
|
@ -58,21 +69,6 @@ func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *ht |
|
|
|
buf.WriteTo(w) |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
// TODO: Sigh... do we have to put this here?
|
|
|
|
// // Browsing navigation gets messed up if browsing a directory
|
|
|
|
// // that doesn't end in "/" (which it should, anyway)
|
|
|
|
// u := *r.URL
|
|
|
|
// if u.Path == "" {
|
|
|
|
// u.Path = "/"
|
|
|
|
// }
|
|
|
|
// if u.Path[len(u.Path)-1] != '/' {
|
|
|
|
// u.Path += "/"
|
|
|
|
// http.Redirect(w, r, u.String(), http.StatusMovedPermanently)
|
|
|
|
// return http.StatusMovedPermanently, nil
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return b.ServeListing(w, r, requestedFilepath, bc)
|
|
|
|
} |
|
|
|
|
|
|
|
func (fsrv *FileServer) loadDirectoryContents(dir *os.File, urlPath string, repl caddy2.Replacer) (browseListing, error) { |
|
|
@ -138,20 +134,16 @@ func isSymlink(f os.FileInfo) bool { |
|
|
|
return f.Mode()&os.ModeSymlink != 0 |
|
|
|
} |
|
|
|
|
|
|
|
// isSymlinkTargetDir return true if f's symbolic link target
|
|
|
|
// is a directory. Return false if not a symbolic link.
|
|
|
|
// TODO: Re-implement
|
|
|
|
func isSymlinkTargetDir(f os.FileInfo, urlPath string) bool { |
|
|
|
// if !isSymlink(f) {
|
|
|
|
// return false
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // TODO: Ensure path is sanitized
|
|
|
|
// target:= path.Join(root, urlPath, f.Name()))
|
|
|
|
// targetInfo, err := os.Stat(target)
|
|
|
|
// if err != nil {
|
|
|
|
// return false
|
|
|
|
// }
|
|
|
|
// return targetInfo.IsDir()
|
|
|
|
return false |
|
|
|
// isSymlinkTargetDir returns true if f's symbolic link target
|
|
|
|
// is a directory.
|
|
|
|
func isSymlinkTargetDir(f os.FileInfo, root, urlPath string) bool { |
|
|
|
if !isSymlink(f) { |
|
|
|
return false |
|
|
|
} |
|
|
|
target := sanitizedPathJoin(root, path.Join(urlPath, f.Name())) |
|
|
|
targetInfo, err := os.Stat(target) |
|
|
|
if err != nil { |
|
|
|
return false |
|
|
|
} |
|
|
|
return targetInfo.IsDir() |
|
|
|
} |
|
|
|