diff --git a/caddy/letsencrypt/letsencrypt.go b/caddy/letsencrypt/letsencrypt.go index 63eeaf7f..f6b55a5f 100644 --- a/caddy/letsencrypt/letsencrypt.go +++ b/caddy/letsencrypt/letsencrypt.go @@ -124,6 +124,19 @@ func Activate(configs []server.Config) ([]server.Config, error) { errMsg += "[" + domain + "] failed to get certificate: " + obtainErr.Error() + "\n" } + // Save the certs we did obtain, though, before leaving + if err := saveCertsAndKeys(certificates); err == nil { + if len(certificates) > 0 { + var certList []string + for _, cert := range certificates { + certList = append(certList, cert.Domain) + } + errMsg += "Saved certificates for: " + strings.Join(certList, ", ") + "\n" + } + } else { + errMsg += "Unable to save obtained certificates: " + err.Error() + "\n" + } + return configs, errors.New(errMsg) } diff --git a/caddy/setup/browse.go b/caddy/setup/browse.go index 4e5291a5..40d5746e 100644 --- a/caddy/setup/browse.go +++ b/caddy/setup/browse.go @@ -86,171 +86,282 @@ const defaultTemplate = ` {{.Name}} + -
- {{if .CanGoUp}} - - {{else}} -
 
- {{end}} + + + + + + + + + + + + + + + + + + + + + -

{{.Path}}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

{{.LinkedPath}}

- - - - - - - {{range .Items}} - - - - - - {{end}} -
- {{if and (eq .Sort "name") (ne .Order "desc")}} - Name ▲ - {{else if and (eq .Sort "name") (ne .Order "asc")}} - Name ▼ - {{else}} - Name - {{end}} - - {{if and (eq .Sort "size") (ne .Order "desc")}} - Size ▲ - {{else if and (eq .Sort "size") (ne .Order "asc")}} - Size ▼ - {{else}} - Size - {{end}} - - {{if and (eq .Sort "time") (ne .Order "desc")}} - Modified ▲ - {{else if and (eq .Sort "time") (ne .Order "asc")}} - Modified ▼ - {{else}} - Modified - {{end}} -
- {{if .IsDir}}📂{{else}}📄{{end}} - {{.Name}} - {{.HumanSize}}{{.HumanModTime "01/02/2006 3:04:05 PM -0700"}}
+
+
+ {{.NumDirs}} director{{if eq 1 .NumDirs}}y{{else}}ies{{end}} + {{.NumFiles}} file{{if ne 1 .NumFiles}}s{{end}} +
+
+
+ + + + + + + {{range .Items}} + + + + + + {{end}} +
+ {{if and (eq .Sort "name") (ne .Order "desc")}} + Name + {{else if and (eq .Sort "name") (ne .Order "asc")}} + Name + {{else}} + Name + {{end}} + + {{if and (eq .Sort "size") (ne .Order "desc")}} + Size + {{else if and (eq .Sort "size") (ne .Order "asc")}} + Size + {{else}} + Size + {{end}} + + {{if and (eq .Sort "time") (ne .Order "desc")}} + Modified + {{else if and (eq .Sort "time") (ne .Order "asc")}} + Modified + {{else}} + Modified + {{end}} +
+ + {{if .IsDir}} + + {{else}} + + {{end}} + {{.Name}} + + {{.HumanSize}}{{.HumanModTime "01/02/2006 03:04:05 PM"}}
+
+ ` diff --git a/middleware/browse/browse.go b/middleware/browse/browse.go index 5a8c229b..75a5b32c 100644 --- a/middleware/browse/browse.go +++ b/middleware/browse/browse.go @@ -6,6 +6,7 @@ import ( "bytes" "encoding/json" "errors" + "fmt" "net/http" "net/url" "os" @@ -36,7 +37,7 @@ type Config struct { Template *template.Template } -// A Listing is used to fill out a template. +// A Listing is the context used to fill out a template. type Listing struct { // The name of the directory (the last element of the path) Name string @@ -50,6 +51,12 @@ type Listing struct { // The items (files and folders) in the path Items []FileInfo + // The number of directories in the listing + NumDirs int + + // The number of files (items that aren't directories) in the listing + NumFiles int + // Which sorting order is used Sort string @@ -62,6 +69,33 @@ type Listing struct { middleware.Context } +// LinkedPath returns l.Path where every element is a clickable +// link to the path up to that point so far. +func (l Listing) LinkedPath() string { + if len(l.Path) == 0 { + return "" + } + + // skip trailing slash + lpath := l.Path + if lpath[len(lpath)-1] == '/' { + lpath = lpath[:len(lpath)-1] + } + + parts := strings.Split(lpath, "/") + var result string + for i, part := range parts { + if i == 0 && part == "" { + // Leading slash (root) + result += `/` + continue + } + result += fmt.Sprintf(`%s/`, strings.Join(parts[:i+1], "/"), part) + } + + return result +} + // FileInfo is the info about a particular file or directory type FileInfo struct { IsDir bool @@ -140,7 +174,9 @@ func (fi FileInfo) HumanModTime(format string) string { func directoryListing(files []os.FileInfo, r *http.Request, canGoUp bool, root string, ignoreIndexes bool, vars interface{}) (Listing, error) { var fileinfos []FileInfo + var dirCount, fileCount int var urlPath = r.URL.Path + for _, f := range files { name := f.Name() @@ -155,6 +191,9 @@ func directoryListing(files []os.FileInfo, r *http.Request, canGoUp bool, root s if f.IsDir() { name += "/" + dirCount++ + } else { + fileCount++ } url := url.URL{Path: name} @@ -170,10 +209,12 @@ func directoryListing(files []os.FileInfo, r *http.Request, canGoUp bool, root s } return Listing{ - Name: path.Base(urlPath), - Path: urlPath, - CanGoUp: canGoUp, - Items: fileinfos, + Name: path.Base(urlPath), + Path: urlPath, + CanGoUp: canGoUp, + Items: fileinfos, + NumDirs: dirCount, + NumFiles: fileCount, Context: middleware.Context{ Root: http.Dir(root), Req: r,