@@ -6,13 +6,45 @@ import (
66 "net/url"
77 "os"
88 "path"
9+ "strings"
910)
1011
1112type archiveCallback func (f * os.File , fInfo os.FileInfo , relPath string ) error
1213
13- func (h * handler ) visitFs (
14+ func matchSelection (name string , selections []string ) (matchName , matchPrefix bool , childSelections []string ) {
15+ if len (selections ) == 0 {
16+ return true , false , nil
17+ }
18+
19+ for _ , sel := range selections {
20+ if sel == name {
21+ matchName = true
22+ continue
23+ }
24+
25+ slashIndex := strings .IndexByte (sel , '/' )
26+ if slashIndex <= 0 {
27+ continue
28+ }
29+
30+ prefix := sel [:slashIndex ]
31+ if prefix == name {
32+ childSel := sel [slashIndex + 1 :]
33+ if len (childSel ) > 0 {
34+ matchPrefix = true
35+ childSelections = append (childSelections , childSel )
36+ }
37+ continue
38+ }
39+ }
40+
41+ return
42+ }
43+
44+ func (h * handler ) visitTreeNode (
1445 fsPath , rawReqPath , relPath string ,
15- statFs bool ,
46+ statNode bool ,
47+ childSelections []string ,
1648 archiveCallback archiveCallback ,
1749) {
1850 var fInfo os.FileInfo
@@ -21,14 +53,13 @@ func (h *handler) visitFs(
2153 err := func () error {
2254 var f * os.File
2355 var err error
24- if statFs {
56+ if statNode {
2557 f , err = os .Open (fsPath )
2658 if f != nil {
2759 defer f .Close ()
2860 }
29- h .errHandler .LogError (err )
3061
31- if err != nil {
62+ if h . errHandler . LogError ( err ) {
3263 if os .IsExist (err ) {
3364 return err
3465 }
@@ -68,15 +99,21 @@ func (h *handler) visitFs(
6899
69100 // childInfo can be regular dir/file, or aliased item that shadows regular dir/file
70101 for _ , childInfo := range childInfos {
71- childPath := "/" + childInfo .Name ()
102+ childName := childInfo .Name ()
103+ matchChildName , matchChildPrefix , childChildSelections := matchSelection (childName , childSelections )
104+ if ! matchChildName && ! matchChildPrefix {
105+ continue
106+ }
107+
108+ childPath := "/" + childName
72109 childFsPath := fsPath + childPath
73110 childRawReqPath := util .CleanUrlPath (rawReqPath + childPath )
74111 childRelPath := relPath + childPath
75112
76113 if childAlias , hasChildAlias := h .aliases .byUrlPath (childRawReqPath ); hasChildAlias {
77- h .visitFs (childAlias .fsPath , childRawReqPath , childRelPath , true , archiveCallback )
114+ h .visitTreeNode (childAlias .fsPath , childRawReqPath , childRelPath , true , childChildSelections , archiveCallback )
78115 } else {
79- h .visitFs (childFsPath , childRawReqPath , childRelPath , statFs , archiveCallback )
116+ h .visitTreeNode (childFsPath , childRawReqPath , childRelPath , statNode , childChildSelections , archiveCallback )
80117 }
81118 }
82119 }
@@ -86,6 +123,7 @@ func (h *handler) archive(
86123 w http.ResponseWriter ,
87124 r * http.Request ,
88125 pageData * responseData ,
126+ selections []string ,
89127 fileSuffix string ,
90128 contentType string ,
91129 cbWriteFile archiveCallback ,
@@ -106,11 +144,12 @@ func (h *handler) archive(
106144 return
107145 }
108146
109- h .visitFs (
147+ h .visitTreeNode (
110148 path .Clean (h .root + pageData .handlerReqPath ),
111149 pageData .rawReqPath ,
112150 "" ,
113- ! h .emptyRoot ,
151+ pageData .Item != nil , // not empty root
152+ selections ,
114153 func (f * os.File , fInfo os.FileInfo , relPath string ) error {
115154 go h .logArchive (targetFilename , relPath , r )
116155 err := cbWriteFile (f , fInfo , relPath )
@@ -129,3 +168,26 @@ func writeArchiveHeader(w http.ResponseWriter, contentType, filename string) {
129168 header .Set ("Cache-Control" , "public, max-age=0" )
130169 w .WriteHeader (http .StatusOK )
131170}
171+
172+ func (h * handler ) getArchiveSelections (r * http.Request ) ([]string , bool ) {
173+ if h .errHandler .LogError (r .ParseForm ()) {
174+ return nil , false
175+ }
176+ inputs := r .Form ["name" ]
177+ if len (inputs ) == 0 {
178+ return nil , true
179+ }
180+
181+ count := len (inputs )
182+ selections := make ([]string , count )
183+ for i := 0 ; i < count ; i ++ {
184+ var ok bool
185+ selections [i ], ok = getCleanDirFilePath (inputs [i ])
186+ if ! ok {
187+ h .logger .LogErrorString ("archive: illegal path " + inputs [i ])
188+ return nil , false
189+ }
190+ }
191+
192+ return selections , true
193+ }
0 commit comments