Skip to content

Commit d07680e

Browse files
committed
feat(serverHandler): ensure all sub items shadowed by case-insensitive alias are fake FileInfo
This ensures that shadowed directory could not be deleted or mkdired.
1 parent 0a7c2c0 commit d07680e

File tree

8 files changed

+106
-19
lines changed

8 files changed

+106
-19
lines changed

src/serverHandler/alias.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
type alias interface {
99
urlPath() string
1010
fsPath() string
11+
caseSensitive() bool
1112
isMatch(rawReqPath string) bool
1213
isSuccessorOf(rawReqPath string) bool
1314
isPredecessorOf(rawReqPath string) bool

src/serverHandler/aliasAccurate.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ func (alias aliasAccurate) fsPath() string {
2121
return alias.fs
2222
}
2323

24+
func (alias aliasAccurate) caseSensitive() bool {
25+
return true
26+
}
27+
2428
func (alias aliasAccurate) isMatch(rawReqPath string) bool {
2529
return alias.url == rawReqPath
2630
}

src/serverHandler/aliasAccurate_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ func TestAliasAccurate(t *testing.T) {
1515
}
1616

1717
// isSuccessorOf
18+
if !alias.isSuccessorOf("/") {
19+
t.Error()
20+
}
21+
1822
if !alias.isSuccessorOf("/hello") {
1923
t.Error()
2024
}
@@ -51,6 +55,18 @@ func TestAliasAccurate(t *testing.T) {
5155
t.Error()
5256
}
5357

58+
if alias.isSuccessorOf("/hi") {
59+
t.Error()
60+
}
61+
62+
if alias.isSuccessorOf("/hi/") {
63+
t.Error()
64+
}
65+
66+
if alias.isSuccessorOf("/hi/there") {
67+
t.Error()
68+
}
69+
5470
// isPredecessorOf
5571
if !alias.isPredecessorOf("/hello/world/foo/bar") {
5672
t.Error()
@@ -59,4 +75,8 @@ func TestAliasAccurate(t *testing.T) {
5975
if !alias.isPredecessorOf("/hello/world/foo/bar/") {
6076
t.Error()
6177
}
78+
79+
if alias.isPredecessorOf("/hi/world/foo/bar") {
80+
t.Error()
81+
}
6282
}

src/serverHandler/aliasNoCase.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ func (alias aliasNoCase) fsPath() string {
2222
return alias.fs
2323
}
2424

25+
func (alias aliasNoCase) caseSensitive() bool {
26+
return false
27+
}
28+
2529
func (alias aliasNoCase) isMatch(rawReqPath string) bool {
2630
return strings.EqualFold(alias.url, rawReqPath)
2731
}

src/serverHandler/aliasNoCase_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ func TestAliasNoCase(t *testing.T) {
1515
}
1616

1717
// isSuccessorOf
18+
if !alias.isSuccessorOf("/") {
19+
t.Error()
20+
}
21+
1822
if !alias.isSuccessorOf("/hello") {
1923
t.Error()
2024
}
@@ -58,6 +62,18 @@ func TestAliasNoCase(t *testing.T) {
5862
t.Error()
5963
}
6064

65+
if alias.isSuccessorOf("/hi") {
66+
t.Error()
67+
}
68+
69+
if alias.isSuccessorOf("/Hi/") {
70+
t.Error()
71+
}
72+
73+
if alias.isSuccessorOf("/hi/There") {
74+
t.Error()
75+
}
76+
6177
// isPredecessorOf
6278
if !alias.isPredecessorOf("/Hello/world/foo/bar") {
6379
t.Error()
@@ -66,4 +82,8 @@ func TestAliasNoCase(t *testing.T) {
6682
if !alias.isPredecessorOf("/hello/world/FOO/BAR/") {
6783
t.Error()
6884
}
85+
86+
if alias.isPredecessorOf("/Hi/world/foo/bar") {
87+
t.Error()
88+
}
6989
}

src/serverHandler/alias_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ func TestGetAliasSubPartAccurate(t *testing.T) {
88

99
aliasAccurate := createAliasAccurate("/hello/world/foo", "/tmp")
1010

11+
subName, isLastPart, ok = getAliasSubPart(aliasAccurate, "/")
12+
if !ok {
13+
t.Error()
14+
}
15+
if subName != "hello" {
16+
t.Error()
17+
}
18+
if isLastPart {
19+
t.Error()
20+
}
21+
1122
_, _, ok = getAliasSubPart(aliasAccurate, "/test")
1223
if ok {
1324
t.Error()
@@ -81,7 +92,6 @@ func TestGetAliasSubPartAccurate(t *testing.T) {
8192
if ok {
8293
t.Error()
8394
}
84-
8595
}
8696

8797
func TestGetAliasSubPartNoCase(t *testing.T) {
@@ -90,6 +100,17 @@ func TestGetAliasSubPartNoCase(t *testing.T) {
90100

91101
aliasNoCase := createAliasNoCase("/hello/world/foo", "/tmp")
92102

103+
subName, isLastPart, ok = getAliasSubPart(aliasNoCase, "/")
104+
if !ok {
105+
t.Error()
106+
}
107+
if subName != "hello" {
108+
t.Error()
109+
}
110+
if isLastPart {
111+
t.Error()
112+
}
113+
93114
_, _, ok = getAliasSubPart(aliasNoCase, "/test")
94115
if ok {
95116
t.Error()
@@ -200,5 +221,4 @@ func TestGetAliasSubPartNoCase(t *testing.T) {
200221
if ok {
201222
t.Error()
202223
}
203-
204224
}

src/serverHandler/responseData.go

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -143,39 +143,45 @@ func (h *handler) mergeAlias(
143143
continue
144144
}
145145

146-
var aliasSubItem os.FileInfo
147-
matchExisted := false
146+
var fsItem os.FileInfo
148147
if isChildAlias { // reached second-deepest path of alias
149148
var err error
150-
aliasSubItem, err = os.Stat(alias.fsPath())
151-
if err == nil {
152-
aliasSubItem = newRenamedFileInfo(subName, aliasSubItem)
153-
} else {
149+
fsItem, err = os.Stat(alias.fsPath())
150+
if err != nil {
154151
errs = append(errs, err)
155-
aliasSubItem = newFakeFileInfo(subName, true)
156152
}
157153
}
158154

155+
matchExisted := false
159156
for i, subItem := range subItems {
160157
if !alias.namesEqual(subItem.Name(), subName) {
161158
continue
162159
}
160+
if isVirtual(subItem) {
161+
continue
162+
}
163163
matchExisted = true
164-
if aliasSubItem == nil {
165-
// use aliased item instead of original item
166-
// to mark it as an alias, which results non-deletable
167-
aliasSubItem = newRenamedFileInfo(subName, subItems[i])
164+
var aliasSubItem os.FileInfo
165+
if fsItem != nil {
166+
aliasSubItem = newRenamedFileInfo(subItem.Name(), fsItem)
167+
} else {
168+
aliasSubItem = newRenamedFileInfo(subItem.Name(), subItem)
168169
}
170+
aliasSubItems = append(aliasSubItems, aliasSubItem)
169171
subItems[i] = aliasSubItem
170-
break
171-
}
172-
173-
if aliasSubItem == nil {
174-
aliasSubItem = newFakeFileInfo(subName, true)
172+
if alias.caseSensitive() {
173+
break
174+
}
175175
}
176-
aliasSubItems = append(aliasSubItems, aliasSubItem)
177176

178177
if !matchExisted {
178+
var aliasSubItem os.FileInfo
179+
if fsItem != nil {
180+
aliasSubItem = newRenamedFileInfo(subName, fsItem)
181+
} else {
182+
aliasSubItem = newFakeFileInfo(subName, true)
183+
}
184+
aliasSubItems = append(aliasSubItems, aliasSubItem)
179185
subItems = append(subItems, aliasSubItem)
180186
}
181187
}

src/util/path_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import "testing"
55
func TestHasUrlPrefixDir(t *testing.T) {
66
var full, prefix string
77

8+
full = "/hello"
9+
prefix = "/"
10+
if !HasUrlPrefixDir(full, prefix) {
11+
t.Error(full, prefix)
12+
}
13+
814
full = "/a/b/c"
915
prefix = "/a/b"
1016
if !HasUrlPrefixDir(full, prefix) {
@@ -63,6 +69,12 @@ func TestHasUrlPrefixDir(t *testing.T) {
6369
func TestHasUrlPrefixDirNoCase(t *testing.T) {
6470
var full, prefix string
6571

72+
full = "/hello"
73+
prefix = "/"
74+
if !HasUrlPrefixDirNoCase(full, prefix) {
75+
t.Error(full, prefix)
76+
}
77+
6678
full = "/a/b/c"
6779
prefix = "/a/b"
6880
if !HasUrlPrefixDirNoCase(full, prefix) {

0 commit comments

Comments
 (0)