@@ -11,6 +11,10 @@ import (
1111 "strings"
1212)
1313
14+ const file = "file"
15+ const dirFile = "dirfile"
16+ const innerDirFile = "innerdirfile"
17+
1418func getAvailableFilename (fsPrefix , filename string , mustAppendSuffix bool ) string {
1519 if len (fsPrefix ) == 0 {
1620 fsPrefix = "/"
@@ -36,7 +40,7 @@ func getAvailableFilename(fsPrefix, filename string, mustAppendSuffix bool) stri
3640 return ""
3741}
3842
39- func (h * handler ) saveUploadFiles (fsPrefix string , overwriteExists bool , aliasSubItems []os.FileInfo , r * http.Request ) bool {
43+ func (h * handler ) saveUploadFiles (fsPrefix string , createDir , overwriteExists bool , aliasSubItems []os.FileInfo , r * http.Request ) bool {
4044 errs := []error {}
4145
4246 reader , err := r .MultipartReader ()
@@ -54,8 +58,50 @@ func (h *handler) saveUploadFiles(fsPrefix string, overwriteExists bool, aliasSu
5458 break
5559 }
5660
57- filename := part .FileName ()
58- slashIndex := strings .LastIndexAny (filename , "/\\ " )
61+ partFilename := path .Clean (strings .ReplaceAll (part .FileName (), "\\ " , "/" ))
62+ if partFilename [0 ] == '/' {
63+ partFilename = partFilename [1 :]
64+ }
65+ if len (partFilename ) == 0 {
66+ continue
67+ }
68+
69+ slashIndex := strings .LastIndexByte (partFilename , '/' )
70+
71+ fsInfix := ""
72+ formname := part .FormName ()
73+ if formname == dirFile {
74+ if slashIndex <= 0 {
75+ continue
76+ }
77+ fsInfix = partFilename [0 :slashIndex ]
78+ } else if formname == innerDirFile { // get file path, strip first level of dir
79+ if slashIndex <= 0 {
80+ continue
81+ }
82+ filepath := partFilename [0 :slashIndex ]
83+ prefixSlashIndex := strings .IndexByte (filepath , '/' )
84+ if prefixSlashIndex > 0 {
85+ fsInfix = filepath [prefixSlashIndex + 1 :]
86+ }
87+ }
88+
89+ filePrefix := fsPrefix
90+ if len (fsInfix ) > 0 {
91+ if ! createDir {
92+ errs = append (errs , errors .New ("Upload failed: mkdir is not enabled for " + fsPrefix ))
93+ continue
94+ }
95+
96+ filePrefix = fsPrefix + "/" + fsInfix
97+ err := os .MkdirAll (filePrefix , 0755 )
98+ if err != nil {
99+ errs = append (errs , err )
100+ continue
101+ }
102+ }
103+
104+ filename := partFilename
59105 if slashIndex >= 0 {
60106 filename = filename [slashIndex + 1 :]
61107 }
@@ -66,7 +112,7 @@ func (h *handler) saveUploadFiles(fsPrefix string, overwriteExists bool, aliasSu
66112 isFilenameAliased := containsItem (aliasSubItems , filename )
67113 var fsFilename string
68114 if overwriteExists && ! isFilenameAliased {
69- tryPath := fsPrefix + "/" + filename
115+ tryPath := filePrefix + "/" + filename
70116 var info os.FileInfo
71117 info , err = os .Lstat (tryPath )
72118 if info != nil && ! info .IsDir () {
@@ -79,15 +125,15 @@ func (h *handler) saveUploadFiles(fsPrefix string, overwriteExists bool, aliasSu
79125 }
80126 }
81127 if len (fsFilename ) == 0 {
82- fsFilename = getAvailableFilename (fsPrefix , filename , isFilenameAliased )
128+ fsFilename = getAvailableFilename (filePrefix , filename , isFilenameAliased )
83129 }
84130 if len (fsFilename ) == 0 {
85131 err := errors .New ("no available filename for " + filename )
86132 errs = append (errs , err )
87133 continue
88134 }
89135
90- fsPath := path .Clean (fsPrefix + "/" + fsFilename )
136+ fsPath := path .Clean (filePrefix + "/" + fsFilename )
91137 go h .logUpload (filename , fsPath , r )
92138 file , err := os .OpenFile (fsPath , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , 0666 )
93139 if err != nil {
0 commit comments