package site import "testing" func TestSplitTilde(t *testing.T) { tests := []struct { path string project string rest string ok bool }{ {"/~proj", "proj", "", true}, {"/~proj/", "proj", "/", true}, {"/~proj/a/b", "proj", "/a/b", true}, {"/~proj/a/b/", "proj", "/a/b/", true}, {"/~proj//a", "proj", "//a", true}, {"/~p", "p", "", true}, {"/~proj/~other/x", "proj", "/~other/x", true}, // A percent-encoded traversal arrives here already decoded; the project // still ends at the first slash, and Resolve cleans the remainder. {"/~proj/../../etc/passwd", "proj", "/../../etc/passwd", true}, // Not a site request at all. {"", "", "", false}, {"/", "", "", false}, {"/x", "", "", false}, {"/~", "", "", false}, {"/~/", "", "", false}, {"~proj/", "", "", false}, {"//~proj/", "", "", false}, {"/favicon.ico", "", "", false}, {"/api/v1/projects", "", "", false}, } for _, tc := range tests { project, rest, ok := splitTilde(tc.path) if project != tc.project || rest != tc.rest || ok != tc.ok { t.Errorf("splitTilde(%q) = (%q, %q, %v), want (%q, %q, %v)", tc.path, project, rest, ok, tc.project, tc.rest, tc.ok) } } } // The project name never contains a slash, which is what makes "~" + name a // single entry inside the webroot and keeps a redirect built from it inside the // project's own prefix. func TestSplitTildeProjectIsOneSegment(t *testing.T) { for _, p := range []string{"/~a/b", "/~a//b", "/~a/../b", "/~a/b/c/d"} { project, _, ok := splitTilde(p) if !ok { t.Fatalf("splitTilde(%q) refused a site path", p) } if project != "a" { t.Errorf("splitTilde(%q) project = %q, want %q", p, project, "a") } } }