1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
package fs
import (
"bytes"
"io"
"os"
"sort"
"strings"
"text/template"
sr "tildegit.org/tjp/sliderule"
)
// RenderDirectoryListing provides an io.Reader with the output of a directory listing template.
//
// The template is provided the following namespace:
// - .FullPath: the complete path to the listed directory
// - .DirName: the name of the directory itself
// - .Entries: the []fs.DirEntry of the directory contents
// - .Hostname: the hostname of the server hosting the file
// - .Port: the port on which the server is listening
//
// Each entry in .Entries has the following fields:
// - .Name the string name of the item within the directory
// - .IsDir is a boolean
// - .Type is the FileMode bits
// - .Info is a method returning (fs.FileInfo, error)
func RenderDirectoryListing(
path string,
requestpath string,
template *template.Template,
server sr.Server,
) (io.Reader, error) {
buf := &bytes.Buffer{}
environ, err := dirlistNamespace(path, requestpath, server)
if err != nil {
return nil, err
}
if err := template.Execute(buf, environ); err != nil {
return nil, err
}
return buf, nil
}
func dirlistNamespace(path, requestpath string, server sr.Server) (map[string]any, error) {
entries, err := os.ReadDir(path)
if err != nil {
return nil, err
}
for i := len(entries) - 1; i >= 0; i-- {
if strings.HasPrefix(entries[i].Name(), ".") {
copy(entries[i:], entries[i+1:])
entries = entries[:len(entries)-1]
}
}
sort.Slice(entries, func(i, j int) bool {
return entries[i].Name() < entries[j].Name()
})
var dirname string
if requestpath == "" {
dirname = "(root)"
} else {
dirname = path[strings.LastIndex(path, "/")+1:]
}
hostname := "none"
port := "0"
if server != nil {
hostname = server.Hostname()
port = server.Port()
}
m := map[string]any{
"FullPath": path,
"DirName": dirname,
"Entries": entries,
"Hostname": hostname,
"Port": port,
}
return m, nil
}
|