55 "io"
66 "net/http"
77 "os"
8- "path/filepath"
98
109 "github.com/caddyserver/caddy/v2"
1110 "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
@@ -29,6 +28,7 @@ func init() {
2928// uploaded file to a file on the disk.
3029type Upload struct {
3130 DestDir string `json:"dest_dir,omitempty"`
31+ RootDir string `json:"root_dir,omitempty"`
3232 FileFieldName string `json:"file_field_name,omitempty"`
3333 MaxFilesize int64 `json:"max_filesize_int,omitempty"`
3434 MaxFilesizeH string `json:"max_filesize,omitempty"`
@@ -71,6 +71,11 @@ func (u *Upload) Provision(ctx caddy.Context) error {
7171 return fmt .Errorf ("no Destination Directory specified (dest_dir)" )
7272 }
7373
74+ if u .RootDir == "" {
75+ u .logger .Info ("Provision" ,
76+ zap .String ("msg" , "no Root Directory specified (root_dir), will use {http.vars.root}" ))
77+ }
78+
7479 mdall_err := os .MkdirAll (u .DestDir , 0755 )
7580 if mdall_err != nil {
7681 u .logger .Error ("Provision" ,
@@ -156,6 +161,7 @@ func (u *Upload) Provision(ctx caddy.Context) error {
156161 u .logger .Info ("Current Config" ,
157162 zap .String ("Version" , Version ),
158163 zap .String ("dest_dir" , u .DestDir ),
164+ zap .String ("root_dir" , u .RootDir ),
159165 zap .Int64 ("max_filesize_int" , u .MaxFilesize ),
160166 zap .String ("max_filesize" , u .MaxFilesizeH ),
161167 zap .Int64 ("max_form_buffer_int" , u .MaxFormBuffer ),
@@ -216,21 +222,34 @@ func (u Upload) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp
216222 }
217223 defer file .Close ()
218224
219- concatDir := u .DestDir
225+ if u .RootDir == "" {
226+ var rootDirErr bool
227+ u .RootDir , rootDirErr = repl .GetString ("http.vars.root" )
228+
229+ if ! rootDirErr {
230+ u .logger .Error ("Provision" ,
231+ zap .Bool ("rootDirErr" , rootDirErr ),
232+ zap .String ("rootDir" , u .RootDir ),
233+ zap .String ("message" , "Variable {http.vars.root} not defined" ))
234+ return caddyhttp .Error (http .StatusInternalServerError , fmt .Errorf ("can't find root dir" ))
235+ }
236+ }
237+
238+ concatDir := caddyhttp .SanitizedPathJoin (u .RootDir , u .DestDir )
220239
221240 if u .CreateUuidDir {
222241 uuidDir := uuid .New ()
223242
224243 // It's very unlikely that the uuidDir already exists, but just in case
225244 for {
226- if _ , err := os .Stat (concatDir + "/" + uuidDir .String ()); os .IsNotExist (err ) {
245+ if _ , err := os .Stat (caddyhttp . SanitizedPathJoin ( concatDir , uuidDir .String () )); os .IsNotExist (err ) {
227246 break
228247 } else {
229248 uuidDir = uuid .New ()
230249 }
231250 }
232251
233- concatDir = concatDir + "/" + uuidDir .String ()
252+ concatDir = caddyhttp . SanitizedPathJoin ( concatDir , uuidDir .String () )
234253 }
235254
236255 if err := os .MkdirAll (concatDir , 0755 ); err != nil {
@@ -244,7 +263,7 @@ func (u Upload) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp
244263
245264 // Create the file within the DestDir directory
246265
247- tempFile , tmpf_err := os .OpenFile (concatDir + "/" + handler .Filename , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0755 )
266+ tempFile , tmpf_err := os .OpenFile (caddyhttp . SanitizedPathJoin ( concatDir , handler .Filename ) , os .O_RDWR | os .O_CREATE | os .O_TRUNC , 0755 )
248267
249268 if tmpf_err != nil {
250269 u .logger .Error ("TempFile Error" ,
@@ -296,33 +315,11 @@ func (u Upload) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp
296315
297316 if u .ResponseTemplate != "" {
298317
299- rootDir , rootDirErr := repl .GetString ("http.vars.root" )
300-
301- if ! rootDirErr {
302- u .logger .Error ("http.root" ,
303- zap .Bool ("rootDirErr" , rootDirErr ),
304- zap .String ("rootDir" , rootDir ),
305- zap .String ("message" , "Can't find root dir" ),
306- zap .Object ("request" , caddyhttp.LoggableHTTPRequest {Request : r }))
307- return caddyhttp .Error (http .StatusInternalServerError , fmt .Errorf ("can't find root dir" ))
308- }
309-
310- fpAbs , fpErr := filepath .Abs (rootDir )
311- if fpErr != nil {
312- u .logger .Error ("filepath Abs Error" ,
313- zap .String ("requuid" , requuid ),
314- zap .String ("rootDir" , rootDir ),
315- zap .String ("message" , "Error at Copy" ),
316- zap .Error (fpErr ),
317- zap .Object ("request" , caddyhttp.LoggableHTTPRequest {Request : r }))
318- return caddyhttp .Error (http .StatusInternalServerError , fpErr )
319- }
320-
321- fileRespTemplate , fRTErr := os .Open (fpAbs + "/" + u .ResponseTemplate )
318+ fileRespTemplate , fRTErr := os .Open (caddyhttp .SanitizedPathJoin (u .RootDir , u .ResponseTemplate ))
322319 if fRTErr != nil {
323320 u .logger .Error ("File Response Template open Error" ,
324321 zap .String ("requuid" , requuid ),
325- zap .String ( "rootDir " , rootDir ),
322+ zap .Any ( "fileRespTemplate " , fileRespTemplate ),
326323 zap .String ("message" , "Error at os.Open" ),
327324 zap .Error (fRTErr ),
328325 zap .Object ("request" , caddyhttp.LoggableHTTPRequest {Request : r }))
@@ -335,7 +332,7 @@ func (u Upload) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp
335332 if fRTSTErr != nil {
336333 u .logger .Error ("File Response Template Stat Error" ,
337334 zap .String ("requuid" , requuid ),
338- zap .String ( "rootDir " , rootDir ),
335+ zap .Any ( "fileRespTemplate " , fileRespTemplate ),
339336 zap .String ("message" , "Error at fileRespTemplate.Stat" ),
340337 zap .Error (fRTSTErr ),
341338 zap .Object ("request" , caddyhttp.LoggableHTTPRequest {Request : r }))
0 commit comments