commit 34caa6914a83e1f6192f35b37fa6202a22ec8002
parent 062c073b84705a9cf8449739355508fda1c30415
Author: n0tr1v <n0tr1v@protonmail.com>
Date: Fri, 3 Feb 2023 19:49:46 -0800
1 endpoint for dkfupload
Diffstat:
3 files changed, 125 insertions(+), 104 deletions(-)
diff --git a/cmd/dkfupload/main.go b/cmd/dkfupload/main.go
@@ -111,12 +111,13 @@ func main() {
logrus.Debug("sending metadata")
client := doGetClient(isLocal, httpTimeout)
body := url.Values{}
+ body.Set("init", "1")
body.Set("fileName", fs.Name())
body.Set("fileSize", strconv.FormatInt(fileSize, 10))
body.Set("fileSha256", fileSha256)
body.Set("chunkSize", strconv.FormatInt(maxChunkSize, 10))
body.Set("nbChunks", strconv.FormatInt(nbChunks, 10))
- req, _ := http.NewRequest(http.MethodPost, baseUrl+"/file-drop/"+filedropUUID+"/dkfupload-init", strings.NewReader(body.Encode()))
+ req, _ := http.NewRequest(http.MethodPost, baseUrl+"/file-drop/"+filedropUUID+"/dkfupload", strings.NewReader(body.Encode()))
req.Header.Set("User-Agent", userAgent)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
@@ -151,6 +152,24 @@ func main() {
// Wait for all workers to have completed
wg.Wait()
+
+ if !dry {
+ client := doGetClient(isLocal, httpTimeout)
+ body := url.Values{}
+ body.Set("completed", "1")
+ req, _ := http.NewRequest(http.MethodPost, baseUrl+"/file-drop/"+filedropUUID+"/dkfupload", strings.NewReader(body.Encode()))
+ req.Header.Set("User-Agent", userAgent)
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ resp, err := client.Do(req)
+ if err != nil {
+ logrus.Fatal(err)
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ logrus.Fatal(fmt.Errorf("invalid status code %s", resp.Status))
+ }
+ }
+
logrus.Infof("All done in %s\n", ShortDur(time.Since(start)))
}
@@ -170,7 +189,7 @@ func work(i int, wg *sync.WaitGroup, chunksCh chan int64, isLocal, dry bool, max
// Ask server if he already has the chunk
{
body := url.Values{}
- body.Set("fileName", partFileName)
+ body.Set("chunkFileName", partFileName)
req, _ := http.NewRequest(http.MethodPost, baseUrl+"/file-drop/"+filedropUUID+"/dkfupload", strings.NewReader(body.Encode()))
req.Header.Set("User-Agent", userAgent)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
diff --git a/pkg/web/handlers/handlers.go b/pkg/web/handlers/handlers.go
@@ -4318,136 +4318,140 @@ func FileDropHandler(c echo.Context) error {
return c.Render(http.StatusOK, filedropTmplName, data)
}
-func FileDropDkfUploadReconstructHandler(c echo.Context) error {
- filedropUUID := c.Param("uuid")
+func FileDropDkfUploadHandler(c echo.Context) error {
+ // Init
+ if c.Request().PostFormValue("init") != "" {
+ filedropUUID := c.Param("uuid")
+ _, err := database.GetFiledropByUUID(filedropUUID)
+ if err != nil {
+ return c.Redirect(http.StatusFound, "/")
+ }
- filedrop, err := database.GetFiledropByUUID(filedropUUID)
- if err != nil {
- return c.Redirect(http.StatusFound, "/")
- }
+ _ = os.Mkdir(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID), 0755)
+ metadataPath := filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, "metadata")
- dirEntries, _ := os.ReadDir(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID))
- fileNames := make([]string, 0)
- for _, dirEntry := range dirEntries {
- if !strings.HasPrefix(dirEntry.Name(), "part_") {
- continue
+ fileName := c.Request().PostFormValue("fileName")
+ fileSize := c.Request().PostFormValue("fileSize")
+ fileSha256 := c.Request().PostFormValue("fileSha256")
+ chunkSize := c.Request().PostFormValue("chunkSize")
+ nbChunks := c.Request().PostFormValue("nbChunks")
+ data := []byte(fileName + "\n" + fileSize + "\n" + fileSha256 + "\n" + chunkSize + "\n" + nbChunks + "\n")
+
+ if _, err := os.Stat(metadataPath); err != nil {
+ if err := os.WriteFile(metadataPath, data, 0644); err != nil {
+ logrus.Error(err)
+ return c.String(http.StatusInternalServerError, err.Error())
+ }
+ } else {
+ by, err := os.ReadFile(metadataPath)
+ if err != nil {
+ logrus.Error(err)
+ return c.String(http.StatusInternalServerError, err.Error())
+ }
+ if bytes.Compare(by, data) != 0 {
+ err := errors.New("metadata file already exists with different configuration")
+ logrus.Error(err)
+ return c.String(http.StatusInternalServerError, err.Error())
+ }
}
- fileNames = append(fileNames, dirEntry.Name())
- }
- sort.Slice(fileNames, func(i, j int) bool {
- a := strings.Split(fileNames[i], "_")[1]
- b := strings.Split(fileNames[j], "_")[1]
- numA, _ := strconv.Atoi(a)
- numB, _ := strconv.Atoi(b)
- return numA < numB
- })
- metadata, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, "metadata"))
- if err != nil {
- logrus.Error(err)
- return c.NoContent(http.StatusInternalServerError)
+ return c.NoContent(http.StatusOK)
}
- lines := strings.Split(string(metadata), "\n")
- origFileName := lines[0]
- fileSha256 := lines[2]
- f, err := os.OpenFile(filepath.Join(config.Global.ProjectFiledropPath(), filedrop.FileName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- logrus.Error(err)
- return c.NoContent(http.StatusInternalServerError)
- }
- defer f.Close()
- h := sha256.New()
+ // completed
+ if c.Request().PostFormValue("completed") != "" {
+ filedropUUID := c.Param("uuid")
- password := make([]byte, 16)
- _, _ = cryptoRand.Read(password)
+ filedrop, err := database.GetFiledropByUUID(filedropUUID)
+ if err != nil {
+ return c.Redirect(http.StatusFound, "/")
+ }
- stream, _, iv, err := crypto.NewCtrStram(password)
- if err != nil {
- logrus.Error(err)
- return c.NoContent(http.StatusInternalServerError)
- }
- written := int64(0)
- for _, fileName := range fileNames {
- by, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, fileName))
+ dirEntries, _ := os.ReadDir(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID))
+ fileNames := make([]string, 0)
+ for _, dirEntry := range dirEntries {
+ if !strings.HasPrefix(dirEntry.Name(), "part_") {
+ continue
+ }
+ fileNames = append(fileNames, dirEntry.Name())
+ }
+ sort.Slice(fileNames, func(i, j int) bool {
+ a := strings.Split(fileNames[i], "_")[1]
+ b := strings.Split(fileNames[j], "_")[1]
+ numA, _ := strconv.Atoi(a)
+ numB, _ := strconv.Atoi(b)
+ return numA < numB
+ })
+
+ metadata, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, "metadata"))
if err != nil {
logrus.Error(err)
return c.NoContent(http.StatusInternalServerError)
}
+ lines := strings.Split(string(metadata), "\n")
+ origFileName := lines[0]
+ fileSha256 := lines[2]
- dst := make([]byte, len(by))
- _, _ = h.Write(by)
- stream.XORKeyStream(dst, by)
- _, err = f.Write(dst)
+ f, err := os.OpenFile(filepath.Join(config.Global.ProjectFiledropPath(), filedrop.FileName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
logrus.Error(err)
return c.NoContent(http.StatusInternalServerError)
}
- written += int64(len(by))
- }
-
- newFileSha256 := hex.EncodeToString(h.Sum(nil))
+ defer f.Close()
+ h := sha256.New()
- if newFileSha256 != fileSha256 {
- logrus.Errorf("%s != %s", newFileSha256, fileSha256)
- return c.NoContent(http.StatusInternalServerError)
- }
+ password := make([]byte, 16)
+ _, _ = cryptoRand.Read(password)
- filedrop.Password = database.EncryptedString(password)
- filedrop.IV = iv
- filedrop.OrigFileName = origFileName
- filedrop.FileSize = written
- filedrop.DoSave()
+ stream, _, iv, err := crypto.NewCtrStram(password)
+ if err != nil {
+ logrus.Error(err)
+ return c.NoContent(http.StatusInternalServerError)
+ }
+ written := int64(0)
+ for _, fileName := range fileNames {
+ by, err := os.ReadFile(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, fileName))
+ if err != nil {
+ logrus.Error(err)
+ return c.NoContent(http.StatusInternalServerError)
+ }
- return c.NoContent(http.StatusOK)
-}
+ dst := make([]byte, len(by))
+ _, _ = h.Write(by)
+ stream.XORKeyStream(dst, by)
+ _, err = f.Write(dst)
+ if err != nil {
+ logrus.Error(err)
+ return c.NoContent(http.StatusInternalServerError)
+ }
+ written += int64(len(by))
+ }
-func FileDropDkfUploadInitHandler(c echo.Context) error {
- filedropUUID := c.Param("uuid")
+ newFileSha256 := hex.EncodeToString(h.Sum(nil))
- _, err := database.GetFiledropByUUID(filedropUUID)
- if err != nil {
- return c.Redirect(http.StatusFound, "/")
- }
+ if newFileSha256 != fileSha256 {
+ logrus.Errorf("%s != %s", newFileSha256, fileSha256)
+ return c.NoContent(http.StatusInternalServerError)
+ }
- _ = os.Mkdir(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID), 0755)
- metadataPath := filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, "metadata")
+ // Cleanup
+ _ = os.RemoveAll(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID))
- fileName := c.Request().PostFormValue("fileName")
- fileSize := c.Request().PostFormValue("fileSize")
- fileSha256 := c.Request().PostFormValue("fileSha256")
- chunkSize := c.Request().PostFormValue("chunkSize")
- nbChunks := c.Request().PostFormValue("nbChunks")
- data := []byte(fileName + "\n" + fileSize + "\n" + fileSha256 + "\n" + chunkSize + "\n" + nbChunks + "\n")
+ filedrop.Password = database.EncryptedString(password)
+ filedrop.IV = iv
+ filedrop.OrigFileName = origFileName
+ filedrop.FileSize = written
+ filedrop.DoSave()
- if _, err := os.Stat(metadataPath); err != nil {
- if err := os.WriteFile(metadataPath, data, 0644); err != nil {
- logrus.Error(err)
- return c.String(http.StatusInternalServerError, err.Error())
- }
- } else {
- by, err := os.ReadFile(metadataPath)
- if err != nil {
- logrus.Error(err)
- return c.String(http.StatusInternalServerError, err.Error())
- }
- if bytes.Compare(by, data) != 0 {
- err := errors.New("metadata file already exists with different configuration")
- logrus.Error(err)
- return c.String(http.StatusInternalServerError, err.Error())
- }
+ return c.NoContent(http.StatusOK)
}
- return c.NoContent(http.StatusOK)
-}
-
-func FileDropDkfUploadHandler(c echo.Context) error {
filedropUUID := c.Param("uuid")
{
- fileName := c.Request().PostFormValue("fileName")
- if fileName != "" {
- if _, err := os.Stat(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, fileName)); err != nil {
+ chunkFileName := c.Request().PostFormValue("chunkFileName")
+ if chunkFileName != "" {
+ if _, err := os.Stat(filepath.Join(config.Global.ProjectFiledropPath(), filedropUUID, chunkFileName)); err != nil {
return c.NoContent(http.StatusOK)
}
// Let's use the teapot response (because why not) to say that we already have the file
diff --git a/pkg/web/web.go b/pkg/web/web.go
@@ -248,7 +248,6 @@ func getMainServer(i18nBundle *i18n.Bundle, renderer *tmp.Templates) echo.Handle
adminGroup.POST("/admin/uploads", handlers.AdminUploadsHandler)
adminGroup.GET("/admin/filedrops", handlers.AdminFiledropsHandler)
adminGroup.POST("/admin/filedrops", handlers.AdminFiledropsHandler)
- adminGroup.GET("/file-drop/:uuid/dkfupload-reconstruct", handlers.FileDropDkfUploadReconstructHandler)
adminGroup.GET("/admin/file-drop/:filename", handlers.FiledropDownloadHandler)
adminGroup.GET("/admin/downloads", handlers.AdminDownloadsHandler)
adminGroup.POST("/admin/downloads/:downloadID/delete", handlers.AdminDeleteDownloadHandler)
@@ -302,7 +301,6 @@ func getBaseServer() *echo.Echo {
e.Use(middlewares.I18nMiddleware(i18nBundle, "en"))
e.GET("/file-drop/:uuid", handlers.FileDropHandler)
e.POST("/file-drop/:uuid", handlers.FileDropHandler)
- e.POST("/file-drop/:uuid/dkfupload-init", handlers.FileDropDkfUploadInitHandler)
e.POST("/file-drop/:uuid/dkfupload", handlers.FileDropDkfUploadHandler)
e.POST("/file-drop/:uuid/dkfdownload", handlers.FileDropDkfDownloadHandler)
e.GET("/downloads/:fileName", handlers.FileDropDownloadHandler)