|
@@ -0,0 +1,239 @@
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "io"
|
|
|
+ "net/http"
|
|
|
+ "os"
|
|
|
+ "path"
|
|
|
+ "strings"
|
|
|
+
|
|
|
+ "github.com/labstack/echo/v4"
|
|
|
+ "github.com/nyudlts/bytemath"
|
|
|
+)
|
|
|
+
|
|
|
+// GET /
|
|
|
+func MainHandle(c echo.Context) error {
|
|
|
+ m := map[string]any{
|
|
|
+ "cod": 200,
|
|
|
+ "id": "JGoServer",
|
|
|
+ "version": "1.0-dev",
|
|
|
+ }
|
|
|
+ ents, err := os.ReadDir("storage")
|
|
|
+ if errors.Is(err, os.ErrNotExist) {
|
|
|
+ err2 := os.Mkdir("storage", 0775)
|
|
|
+ if err2 != nil {
|
|
|
+ m["cod"] = 500
|
|
|
+ m["dirs"] = nil // This is what we were trying to populate
|
|
|
+ m["err"] = err2.Error()
|
|
|
+ m["cause"] = err.Error()
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+ }
|
|
|
+ } else if err != nil {
|
|
|
+ m["cod"] = 500
|
|
|
+ m["dirs"] = nil // This is what we were trying to populate
|
|
|
+ m["err"] = err.Error()
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+ }
|
|
|
+ dirs := []string{}
|
|
|
+ for _, e := range ents {
|
|
|
+ if e.IsDir() {
|
|
|
+ dirs = append(dirs, e.Name())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ m["dirs"] = dirs
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+}
|
|
|
+
|
|
|
+// Sanitizes directory name so it's a little safe
|
|
|
+func CleanDirName(raw string) string {
|
|
|
+ return strings.ToLower(strings.Trim(raw, " .\r\n\t"))
|
|
|
+}
|
|
|
+
|
|
|
+// GET /dir?q=<dir>
|
|
|
+func GetDirHandle(c echo.Context) error {
|
|
|
+ m := map[string]any{
|
|
|
+ "cod": 200,
|
|
|
+ }
|
|
|
+ target := CleanDirName(c.QueryParam("q")) // Directory to list
|
|
|
+ if len(target) == 0 || target == "" {
|
|
|
+ // Nothing todo?
|
|
|
+ m["cod"] = http.StatusBadRequest
|
|
|
+ m["q"] = c.QueryParam("q")
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+ }
|
|
|
+ // Verify the directory at least exists
|
|
|
+ _, err := os.Stat(path.Join("storage", target))
|
|
|
+ if errors.Is(err, os.ErrNotExist) {
|
|
|
+ err2 := os.MkdirAll(path.Join("storage", target), 0775)
|
|
|
+ if err2 != nil {
|
|
|
+ m["cod"] = 500
|
|
|
+ m["files"] = nil
|
|
|
+ m["dirs"] = nil
|
|
|
+ m["err"] = err2.Error()
|
|
|
+ m["cause"] = err.Error()
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+ }
|
|
|
+ } else if err != nil {
|
|
|
+ m["cod"] = 500
|
|
|
+ m["files"] = nil
|
|
|
+ m["dirs"] = nil
|
|
|
+ m["err"] = err.Error()
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+ }
|
|
|
+ // Scan the dirs looking for files (won't include ones that start with .)
|
|
|
+ var scanDir func(string) ([]string, []string, error)
|
|
|
+ scanDir = func(dir string) ([]string, []string, error) {
|
|
|
+ ents, err := os.ReadDir(dir)
|
|
|
+ if err != nil {
|
|
|
+ return nil, nil, err
|
|
|
+ }
|
|
|
+ fs := []string{}
|
|
|
+ ds := []string{}
|
|
|
+ for _, e := range ents {
|
|
|
+ if strings.HasPrefix(e.Name(), ".") { // Keep hidden files/dirs hidden
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if e.IsDir() {
|
|
|
+ ds = append(ds, path.Join(dir, e.Name()))
|
|
|
+ f, d, err := scanDir(path.Join(dir, e.Name()))
|
|
|
+ if err != nil {
|
|
|
+ return nil, nil, err
|
|
|
+ }
|
|
|
+ fs = append(fs, f...)
|
|
|
+ ds = append(ds, d...)
|
|
|
+ } else {
|
|
|
+ fs = append(fs, path.Join(dir, e.Name()))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return fs, ds, nil
|
|
|
+ }
|
|
|
+ files, dirs, err2 := scanDir(path.Join("storage", target))
|
|
|
+ if err2 != nil {
|
|
|
+ m["cod"] = 500
|
|
|
+ m["files"] = nil
|
|
|
+ m["dirs"] = nil
|
|
|
+ m["err"] = err.Error()
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+ }
|
|
|
+ m["files"] = files
|
|
|
+ m["dirs"] = dirs
|
|
|
+ return c.JSON(m["cod"].(int), m)
|
|
|
+}
|
|
|
+
|
|
|
+// POST/PUT /up?q=<filepath>
|
|
|
+func UploadJData(c echo.Context) error {
|
|
|
+ // e.g. test/dir1/pkt001.json
|
|
|
+ targetDir := CleanDirName(path.Dir(c.QueryParam("q"))) // e.g. test/dir1
|
|
|
+ targetName := path.Base(c.QueryParam("q")) // e.g. pkt001.json
|
|
|
+ _, err := os.Stat(path.Join("storage", targetDir))
|
|
|
+ if errors.Is(err, os.ErrNotExist) {
|
|
|
+ err2 := os.MkdirAll(path.Join("storage", targetDir), 0775)
|
|
|
+ if err2 != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err2.Error(),
|
|
|
+ "cause": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else if err != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ fh, err := os.Create(path.Join("storage", targetDir, targetName))
|
|
|
+ if err != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ body := c.Request().Body
|
|
|
+ defer body.Close()
|
|
|
+ written, err := io.Copy(fh, body)
|
|
|
+ fh.Close()
|
|
|
+ if err != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // Check that it is in fact really JSON
|
|
|
+ data, err := os.ReadFile(path.Join("storage", targetDir, targetName))
|
|
|
+ if err != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ var test any
|
|
|
+ err = json.Unmarshal(data, &test)
|
|
|
+ if err != nil {
|
|
|
+ // Not json!
|
|
|
+ err2 := os.Remove(path.Join("storage", targetDir, targetName))
|
|
|
+ if err2 != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err2.Error(),
|
|
|
+ "cause": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // Ok we're good
|
|
|
+ return c.JSON(200, map[string]any{
|
|
|
+ "cod": 200,
|
|
|
+ "size": bytemath.ConvertBytesToHumanReadable(written),
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+// GET /down?q=<filepath>
|
|
|
+func DownloadJData(c echo.Context) error {
|
|
|
+ // e.g. test/dir1/pkt001.json
|
|
|
+ targetDir := CleanDirName(path.Dir(c.QueryParam("q"))) // e.g. test/dir1
|
|
|
+ targetName := path.Base(c.QueryParam("q")) // e.g. pkt001.json
|
|
|
+ _, err := os.ReadDir(path.Join("storage", targetDir))
|
|
|
+ if errors.Is(err, os.ErrNotExist) {
|
|
|
+ err2 := os.MkdirAll(path.Join("storage", targetDir), 0775)
|
|
|
+ if err2 != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err2.Error(),
|
|
|
+ "cause": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else if err != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": err.Error(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // File contents must be JSON, we live in JSON so it must be JSON data
|
|
|
+ fh, err := os.ReadFile(path.Join("storage", targetDir, targetName))
|
|
|
+ if err != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": "ReadFile: " + err.Error(),
|
|
|
+ "data": nil,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ var data any
|
|
|
+ err = json.Unmarshal(fh, &data)
|
|
|
+ if err != nil {
|
|
|
+ return c.JSON(500, map[string]any{
|
|
|
+ "cod": 500,
|
|
|
+ "err": "json.Unmarshal: " + err.Error(),
|
|
|
+ "data": nil,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return c.JSON(200, map[string]any{
|
|
|
+ "cod": 200,
|
|
|
+ "data": data,
|
|
|
+ "size": bytemath.ConvertBytesToHumanReadable(int64(len(fh))),
|
|
|
+ })
|
|
|
+}
|