handles.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io"
  6. "net/http"
  7. "os"
  8. "path"
  9. "strings"
  10. "github.com/labstack/echo/v4"
  11. "github.com/nyudlts/bytemath"
  12. )
  13. // GET /
  14. func MainHandle(c echo.Context) error {
  15. m := map[string]any{
  16. "cod": 200,
  17. "id": "JGoServer",
  18. "version": "1.0-dev",
  19. }
  20. ents, err := os.ReadDir("storage")
  21. if errors.Is(err, os.ErrNotExist) {
  22. err2 := os.Mkdir("storage", 0775)
  23. if err2 != nil {
  24. m["cod"] = 500
  25. m["dirs"] = nil // This is what we were trying to populate
  26. m["err"] = err2.Error()
  27. m["cause"] = err.Error()
  28. return c.JSON(m["cod"].(int), m)
  29. }
  30. } else if err != nil {
  31. m["cod"] = 500
  32. m["dirs"] = nil // This is what we were trying to populate
  33. m["err"] = err.Error()
  34. return c.JSON(m["cod"].(int), m)
  35. }
  36. dirs := []string{}
  37. for _, e := range ents {
  38. if e.IsDir() {
  39. dirs = append(dirs, e.Name())
  40. }
  41. }
  42. m["dirs"] = dirs
  43. return c.JSON(m["cod"].(int), m)
  44. }
  45. // Sanitizes directory name so it's a little safe
  46. func CleanDirName(raw string) string {
  47. return strings.ToLower(strings.Trim(raw, " .\r\n\t"))
  48. }
  49. // GET /dir?q=<dir>
  50. func GetDirHandle(c echo.Context) error {
  51. m := map[string]any{
  52. "cod": 200,
  53. }
  54. target := CleanDirName(c.QueryParam("q")) // Directory to list
  55. if len(target) == 0 || target == "" {
  56. // Nothing todo?
  57. m["cod"] = http.StatusBadRequest
  58. m["q"] = c.QueryParam("q")
  59. return c.JSON(m["cod"].(int), m)
  60. }
  61. // Verify the directory at least exists
  62. _, err := os.Stat(path.Join("storage", target))
  63. if errors.Is(err, os.ErrNotExist) {
  64. err2 := os.MkdirAll(path.Join("storage", target), 0775)
  65. if err2 != nil {
  66. m["cod"] = 500
  67. m["files"] = nil
  68. m["dirs"] = nil
  69. m["err"] = err2.Error()
  70. m["cause"] = err.Error()
  71. return c.JSON(m["cod"].(int), m)
  72. }
  73. } else if err != nil {
  74. m["cod"] = 500
  75. m["files"] = nil
  76. m["dirs"] = nil
  77. m["err"] = err.Error()
  78. return c.JSON(m["cod"].(int), m)
  79. }
  80. // Scan the dirs looking for files (won't include ones that start with .)
  81. var scanDir func(string) ([]string, []string, error)
  82. scanDir = func(dir string) ([]string, []string, error) {
  83. ents, err := os.ReadDir(dir)
  84. if err != nil {
  85. return nil, nil, err
  86. }
  87. fs := []string{}
  88. ds := []string{}
  89. for _, e := range ents {
  90. if strings.HasPrefix(e.Name(), ".") { // Keep hidden files/dirs hidden
  91. continue
  92. }
  93. if e.IsDir() {
  94. ds = append(ds, path.Join(dir, e.Name()))
  95. f, d, err := scanDir(path.Join(dir, e.Name()))
  96. if err != nil {
  97. return nil, nil, err
  98. }
  99. fs = append(fs, f...)
  100. ds = append(ds, d...)
  101. } else {
  102. fs = append(fs, path.Join(dir, e.Name()))
  103. }
  104. }
  105. return fs, ds, nil
  106. }
  107. files, dirs, err2 := scanDir(path.Join("storage", target))
  108. if err2 != nil {
  109. m["cod"] = 500
  110. m["files"] = nil
  111. m["dirs"] = nil
  112. m["err"] = err.Error()
  113. return c.JSON(m["cod"].(int), m)
  114. }
  115. m["files"] = files
  116. m["dirs"] = dirs
  117. return c.JSON(m["cod"].(int), m)
  118. }
  119. // POST/PUT /up?q=<filepath>
  120. func UploadJData(c echo.Context) error {
  121. // e.g. test/dir1/pkt001.json
  122. targetDir := CleanDirName(path.Dir(c.QueryParam("q"))) // e.g. test/dir1
  123. targetName := path.Base(c.QueryParam("q")) // e.g. pkt001.json
  124. _, err := os.Stat(path.Join("storage", targetDir))
  125. if errors.Is(err, os.ErrNotExist) {
  126. err2 := os.MkdirAll(path.Join("storage", targetDir), 0775)
  127. if err2 != nil {
  128. return c.JSON(500, map[string]any{
  129. "cod": 500,
  130. "err": err2.Error(),
  131. "cause": err.Error(),
  132. })
  133. }
  134. } else if err != nil {
  135. return c.JSON(500, map[string]any{
  136. "cod": 500,
  137. "err": err.Error(),
  138. })
  139. }
  140. fh, err := os.Create(path.Join("storage", targetDir, targetName))
  141. if err != nil {
  142. return c.JSON(500, map[string]any{
  143. "cod": 500,
  144. "err": err.Error(),
  145. })
  146. }
  147. body := c.Request().Body
  148. defer body.Close()
  149. written, err := io.Copy(fh, body)
  150. fh.Close()
  151. if err != nil {
  152. return c.JSON(500, map[string]any{
  153. "cod": 500,
  154. "err": err.Error(),
  155. })
  156. }
  157. // Check that it is in fact really JSON
  158. data, err := os.ReadFile(path.Join("storage", targetDir, targetName))
  159. if err != nil {
  160. return c.JSON(500, map[string]any{
  161. "cod": 500,
  162. "err": err.Error(),
  163. })
  164. }
  165. var test any
  166. err = json.Unmarshal(data, &test)
  167. if err != nil {
  168. // Not json!
  169. err2 := os.Remove(path.Join("storage", targetDir, targetName))
  170. if err2 != nil {
  171. return c.JSON(500, map[string]any{
  172. "cod": 500,
  173. "err": err2.Error(),
  174. "cause": err.Error(),
  175. })
  176. }
  177. return c.JSON(500, map[string]any{
  178. "cod": 500,
  179. "err": err.Error(),
  180. })
  181. }
  182. // Ok we're good
  183. return c.JSON(200, map[string]any{
  184. "cod": 200,
  185. "size": bytemath.ConvertBytesToHumanReadable(written),
  186. })
  187. }
  188. // GET /down?q=<filepath>
  189. func DownloadJData(c echo.Context) error {
  190. // e.g. test/dir1/pkt001.json
  191. targetDir := CleanDirName(path.Dir(c.QueryParam("q"))) // e.g. test/dir1
  192. targetName := path.Base(c.QueryParam("q")) // e.g. pkt001.json
  193. _, err := os.ReadDir(path.Join("storage", targetDir))
  194. if errors.Is(err, os.ErrNotExist) {
  195. err2 := os.MkdirAll(path.Join("storage", targetDir), 0775)
  196. if err2 != nil {
  197. return c.JSON(500, map[string]any{
  198. "cod": 500,
  199. "err": err2.Error(),
  200. "cause": err.Error(),
  201. })
  202. }
  203. } else if err != nil {
  204. return c.JSON(500, map[string]any{
  205. "cod": 500,
  206. "err": err.Error(),
  207. })
  208. }
  209. // File contents must be JSON, we live in JSON so it must be JSON data
  210. fh, err := os.ReadFile(path.Join("storage", targetDir, targetName))
  211. if err != nil {
  212. return c.JSON(500, map[string]any{
  213. "cod": 500,
  214. "err": "ReadFile: " + err.Error(),
  215. "data": nil,
  216. })
  217. }
  218. var data any
  219. err = json.Unmarshal(fh, &data)
  220. if err != nil {
  221. return c.JSON(500, map[string]any{
  222. "cod": 500,
  223. "err": "json.Unmarshal: " + err.Error(),
  224. "data": nil,
  225. })
  226. }
  227. return c.JSON(200, map[string]any{
  228. "cod": 200,
  229. "data": data,
  230. "size": bytemath.ConvertBytesToHumanReadable(int64(len(fh))),
  231. })
  232. }