mirror of https://github.com/veypi/OneAuth.git
webdav enable dir renader
parent
2766dd99bd
commit
a4bb05d60d
@ -0,0 +1,89 @@
|
|||||||
|
//
|
||||||
|
// dir_render.go
|
||||||
|
// Copyright (C) 2024 veypi <i@veypi.com>
|
||||||
|
// 2024-10-18 19:35
|
||||||
|
// Distributed under terms of the GPL license.
|
||||||
|
//
|
||||||
|
|
||||||
|
package webdav
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/veypi/utils/logv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type anyDirs interface {
|
||||||
|
len() int
|
||||||
|
name(i int) string
|
||||||
|
isDir(i int) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileInfoDirs []fs.FileInfo
|
||||||
|
|
||||||
|
func (d fileInfoDirs) len() int { return len(d) }
|
||||||
|
func (d fileInfoDirs) isDir(i int) bool { return d[i].IsDir() }
|
||||||
|
func (d fileInfoDirs) name(i int) string { return d[i].Name() }
|
||||||
|
|
||||||
|
type dirEntryDirs []fs.DirEntry
|
||||||
|
|
||||||
|
func (d dirEntryDirs) len() int { return len(d) }
|
||||||
|
func (d dirEntryDirs) isDir(i int) bool { return d[i].IsDir() }
|
||||||
|
func (d dirEntryDirs) name(i int) string { return d[i].Name() }
|
||||||
|
|
||||||
|
func dirList(w http.ResponseWriter, r *http.Request, f File) {
|
||||||
|
|
||||||
|
// Prefer to use ReadDir instead of Readdir,
|
||||||
|
// because the former doesn't require calling
|
||||||
|
// Stat on every entry of a directory on Unix.
|
||||||
|
var dirs anyDirs
|
||||||
|
var err error
|
||||||
|
if d, ok := f.(fs.ReadDirFile); ok {
|
||||||
|
var list dirEntryDirs
|
||||||
|
list, err = d.ReadDir(-1)
|
||||||
|
dirs = list
|
||||||
|
} else {
|
||||||
|
var list fileInfoDirs
|
||||||
|
list, err = f.Readdir(-1)
|
||||||
|
dirs = list
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logv.Warn().Msgf("http: error reading directory: %v", err)
|
||||||
|
http.Error(w, "Error reading directory", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sort.Slice(dirs, func(i, j int) bool { return dirs.name(i) < dirs.name(j) })
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
fmt.Fprintf(w, "<!doctype html>\n")
|
||||||
|
fmt.Fprintf(w, "<meta name=\"viewport\" content=\"width=device-width\">\n")
|
||||||
|
fmt.Fprintf(w, "<pre>\n")
|
||||||
|
for i, n := 0, dirs.len(); i < n; i++ {
|
||||||
|
name := dirs.name(i)
|
||||||
|
if dirs.isDir(i) {
|
||||||
|
name += "/"
|
||||||
|
}
|
||||||
|
// name may contain '?' or '#', which must be escaped to remain
|
||||||
|
// part of the URL path, and not indicate the start of a query
|
||||||
|
// string or fragment.
|
||||||
|
url := url.URL{Path: name}
|
||||||
|
fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "</pre>\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
var htmlReplacer = strings.NewReplacer(
|
||||||
|
"&", "&",
|
||||||
|
"<", "<",
|
||||||
|
">", ">",
|
||||||
|
// """ is shorter than """.
|
||||||
|
`"`, """,
|
||||||
|
// "'" is shorter than "'" and apos was not in HTML until HTML5.
|
||||||
|
"'", "'",
|
||||||
|
)
|
Loading…
Reference in New Issue