package api import ( "fmt" "github.com/gin-gonic/gin" "io" "os" "path/filepath" "strings" ) func verifyPath(path string) bool { path = filepath.Clean(path) for _, part := range strings.Split(path, string(filepath.Separator)) { if part == ".." || part == "." { return false } } return true } func verifyDir(c *gin.Context) bool { if !verifyPath(c.Params.ByName("dir")) { c.Fail(400, fmt.Errorf("wrong dir")) return false } return true } // GET /files func apiFilesListDirs(c *gin.Context) { list := []string{} err := filepath.Walk(context.UploadPath(), func(path string, info os.FileInfo, err error) error { if err != nil { return err } if path == context.UploadPath() { return nil } if info.IsDir() { list = append(list, filepath.Base(path)) return filepath.SkipDir } return nil }) if err != nil && !os.IsNotExist(err) { c.Fail(400, err) return } c.JSON(200, list) } // POST /files/:dir/ func apiFilesUpload(c *gin.Context) { if !verifyDir(c) { return } path := filepath.Join(context.UploadPath(), c.Params.ByName("dir")) err := os.MkdirAll(path, 0777) if err != nil { c.Fail(500, err) return } err = c.Request.ParseMultipartForm(10 * 1024 * 1024) if err != nil { c.Fail(400, err) return } stored := []string{} for _, files := range c.Request.MultipartForm.File { for _, file := range files { src, err := file.Open() if err != nil { c.Fail(500, err) return } defer src.Close() destPath := filepath.Join(path, filepath.Base(file.Filename)) dst, err := os.Create(destPath) if err != nil { c.Fail(500, err) return } defer dst.Close() _, err = io.Copy(dst, src) if err != nil { c.Fail(500, err) return } stored = append(stored, filepath.Join(c.Params.ByName("dir"), filepath.Base(file.Filename))) } } c.JSON(200, stored) } // GET /files/:dir func apiFilesListFiles(c *gin.Context) { if !verifyDir(c) { return } list := []string{} root := filepath.Join(context.UploadPath(), c.Params.ByName("dir")) err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if path == root { return nil } list = append(list, filepath.Base(path)) return nil }) if err != nil { if os.IsNotExist(err) { c.Fail(404, err) } else { c.Fail(500, err) } return } c.JSON(200, list) } // DELETE /files/:dir func apiFilesDeleteDir(c *gin.Context) { if !verifyDir(c) { return } err := os.RemoveAll(filepath.Join(context.UploadPath(), c.Params.ByName("dir"))) if err != nil { c.Fail(500, err) return } c.JSON(200, gin.H{}) } // DELETE /files/:dir/:name func apiFilesDeleteFile(c *gin.Context) { if !verifyDir(c) { return } if !verifyPath(c.Params.ByName("name")) { c.Fail(400, fmt.Errorf("wrong file")) return } err := os.Remove(filepath.Join(context.UploadPath(), c.Params.ByName("dir"), c.Params.ByName("name"))) if err != nil { if err1, ok := err.(*os.PathError); !ok || !os.IsNotExist(err1.Err) { c.Fail(500, err) return } } c.JSON(200, gin.H{}) }