summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/caddyhttp/fileserver/staticfiles.go39
-rw-r--r--modules/caddyhttp/fileserver/staticfiles_test.go73
2 files changed, 95 insertions, 17 deletions
diff --git a/modules/caddyhttp/fileserver/staticfiles.go b/modules/caddyhttp/fileserver/staticfiles.go
index d6cf4d6..735352b 100644
--- a/modules/caddyhttp/fileserver/staticfiles.go
+++ b/modules/caddyhttp/fileserver/staticfiles.go
@@ -329,28 +329,37 @@ func sanitizedPathJoin(root, reqPath string) string {
// fileHidden returns true if filename is hidden
// according to the hide list.
func fileHidden(filename string, hide []string) bool {
- nameOnly := filepath.Base(filename)
sep := string(filepath.Separator)
+ var components []string
for _, h := range hide {
- // assuming h is a glob/shell-like pattern,
- // use it to compare the whole file path;
- // but if there is no separator in h, then
- // just compare against the file's name
- compare := filename
if !strings.Contains(h, sep) {
- compare = nameOnly
- }
-
- hidden, err := filepath.Match(h, compare)
- if err != nil {
- // malformed pattern; fallback by checking prefix
- if strings.HasPrefix(filename, h) {
+ // if there is no separator in h, then we assume the user
+ // wants to hide any files or folders that match that
+ // name; thus we have to compare against each component
+ // of the filename, e.g. hiding "bar" would hide "/bar"
+ // as well as "/foo/bar/baz" but not "/barstool".
+ if len(components) == 0 {
+ components = strings.Split(filename, sep)
+ }
+ for _, c := range components {
+ if c == h {
+ return true
+ }
+ }
+ } else if strings.HasPrefix(filename, h) {
+ // otherwise, if there is a separator in h, and
+ // filename is exactly prefixed with h, then we
+ // can do a prefix match so that "/foo" matches
+ // "/foo/bar" but not "/foobar".
+ withoutPrefix := strings.TrimPrefix(filename, h)
+ if strings.HasPrefix(withoutPrefix, sep) {
return true
}
}
- if hidden {
- // file name or path matches hide pattern
+
+ // in the general case, a glob match will suffice
+ if hidden, _ := filepath.Match(h, filename); hidden {
return true
}
}
diff --git a/modules/caddyhttp/fileserver/staticfiles_test.go b/modules/caddyhttp/fileserver/staticfiles_test.go
index 73762c7..f074318 100644
--- a/modules/caddyhttp/fileserver/staticfiles_test.go
+++ b/modules/caddyhttp/fileserver/staticfiles_test.go
@@ -93,9 +93,78 @@ func TestSanitizedPathJoin(t *testing.T) {
}
actual := sanitizedPathJoin(tc.inputRoot, u.Path)
if actual != tc.expect {
- t.Errorf("Test %d: [%s %s] => %s (expected %s)", i, tc.inputRoot, tc.inputPath, actual, tc.expect)
+ t.Errorf("Test %d: [%s %s] => %s (expected %s)",
+ i, tc.inputRoot, tc.inputPath, actual, tc.expect)
}
}
}
-// TODO: test fileHidden
+func TestFileHidden(t *testing.T) {
+ for i, tc := range []struct {
+ inputHide []string
+ inputPath string
+ expect bool
+ }{
+ {
+ inputHide: nil,
+ inputPath: "",
+ expect: false,
+ },
+ {
+ inputHide: []string{".gitignore"},
+ inputPath: "/.gitignore",
+ expect: true,
+ },
+ {
+ inputHide: []string{".git"},
+ inputPath: "/.gitignore",
+ expect: false,
+ },
+ {
+ inputHide: []string{"/.git"},
+ inputPath: "/.gitignore",
+ expect: false,
+ },
+ {
+ inputHide: []string{".git"},
+ inputPath: "/.git",
+ expect: true,
+ },
+ {
+ inputHide: []string{".git"},
+ inputPath: "/.git/foo",
+ expect: true,
+ },
+ {
+ inputHide: []string{".git"},
+ inputPath: "/foo/.git/bar",
+ expect: true,
+ },
+ {
+ inputHide: []string{"/prefix"},
+ inputPath: "/prefix/foo",
+ expect: true,
+ },
+ {
+ inputHide: []string{"/foo/*/bar"},
+ inputPath: "/foo/asdf/bar",
+ expect: true,
+ },
+ {
+ inputHide: []string{"/foo"},
+ inputPath: "/foo",
+ expect: true,
+ },
+ {
+ inputHide: []string{"/foo"},
+ inputPath: "/foobar",
+ expect: false,
+ },
+ } {
+ actual := fileHidden(tc.inputPath, tc.inputHide)
+ if actual != tc.expect {
+ t.Errorf("Test %d: Is %s hidden in %v? Got %t but expected %t",
+ i, tc.inputPath, tc.inputHide, actual, tc.expect)
+ }
+ }
+}