add path.Clean and other utilities.
use path.Clean in web server to sanitize URLs.
http://triv/go/../../../etc/passwd
no longer serves the password file.
it redirects to
http://triv/etc/passwd
which then gets a 404.
R=r
DELTA=288 (286 added, 0 deleted, 2 changed)
OCL=27142
CL=27152
diff --git a/src/lib/path_test.go b/src/lib/path_test.go
new file mode 100644
index 0000000..067b1d0
--- /dev/null
+++ b/src/lib/path_test.go
@@ -0,0 +1,119 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package path
+
+import (
+ "path";
+ "testing"
+)
+
+type CleanTest struct {
+ path, clean string
+}
+
+var cleantests = []CleanTest {
+ // Already clean
+ CleanTest{"", "."},
+ CleanTest{"abc", "abc"},
+ CleanTest{"abc/def", "abc/def"},
+ CleanTest{"a/b/c", "a/b/c"},
+ CleanTest{".", "."},
+ CleanTest{"..", ".."},
+ CleanTest{"../..", "../.."},
+ CleanTest{"../../abc", "../../abc"},
+ CleanTest{"/abc", "/abc"},
+ CleanTest{"/", "/"},
+
+ // Remove trailing slash
+ CleanTest{"abc/", "abc"},
+ CleanTest{"abc/def/", "abc/def"},
+ CleanTest{"a/b/c/", "a/b/c"},
+ CleanTest{"./", "."},
+ CleanTest{"../", ".."},
+ CleanTest{"../../", "../.."},
+ CleanTest{"/abc/", "/abc"},
+
+ // Remove doubled slash
+ CleanTest{"abc//def//ghi", "abc/def/ghi"},
+ CleanTest{"//abc", "/abc"},
+ CleanTest{"///abc", "/abc"},
+ CleanTest{"//abc//", "/abc"},
+ CleanTest{"abc//", "abc"},
+
+ // Remove . elements
+ CleanTest{"abc/./def", "abc/def"},
+ CleanTest{"/./abc/def", "/abc/def"},
+ CleanTest{"abc/.", "abc"},
+
+ // Remove .. elements
+ CleanTest{"abc/def/ghi/../jkl", "abc/def/jkl"},
+ CleanTest{"abc/def/../ghi/../jkl", "abc/jkl"},
+ CleanTest{"abc/def/..", "abc"},
+ CleanTest{"abc/def/../..", "."},
+ CleanTest{"/abc/def/../..", "/"},
+ CleanTest{"abc/def/../../..", ".."},
+ CleanTest{"/abc/def/../../..", "/"},
+ CleanTest{"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
+
+ // Combinations
+ CleanTest{"abc/./../def", "def"},
+ CleanTest{"abc//./../def", "def"},
+ CleanTest{"abc/../../././../def", "../../def"},
+}
+
+func TestClean(t *testing.T) {
+ for i, test := range cleantests {
+ if s := Clean(test.path); s != test.clean {
+ t.Errorf("Clean(%q) = %q, want %q", test.path, s, test.clean);
+ }
+ }
+}
+
+type SplitTest struct {
+ path, dir, file string
+}
+
+var splittests = []SplitTest {
+ SplitTest{"a/b", "a/", "b"},
+ SplitTest{"a/b/", "a/b/", ""},
+ SplitTest{"a/", "a/", ""},
+ SplitTest{"a", "", "a"},
+ SplitTest{"/", "/", ""},
+}
+
+func TestSplit(t *testing.T) {
+ for i, test := range splittests {
+ if d, f := Split(test.path); d != test.dir || f != test.file {
+ t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file);
+ }
+ }
+}
+
+type JoinTest struct {
+ dir, file, path string
+}
+
+var jointests = []JoinTest {
+ JoinTest{"a", "b", "a/b"},
+ JoinTest{"a", "", "a/"},
+ JoinTest{"", "b", "b"},
+ JoinTest{"/", "a", "/a"},
+ JoinTest{"/", "", "/"},
+ JoinTest{"a/", "b", "a/b"},
+ JoinTest{"a/", "", "a/"},
+}
+
+type ExtTest struct {
+ path, ext string
+}
+
+var exttests = []ExtTest {
+ ExtTest{"path.go", ".go"},
+ ExtTest{"path.pb.go", ".go"},
+ ExtTest{"path", ""},
+ ExtTest{"a.dir/b", ""},
+ ExtTest{"a.dir/b.go", ".go"},
+ ExtTest{"a.dir/", ""},
+}