agi.appdata.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package agi
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "github.com/robertkrimen/otto"
  9. "imuslab.com/arozos/mod/agi/static"
  10. "imuslab.com/arozos/mod/filesystem"
  11. "imuslab.com/arozos/mod/utils"
  12. )
  13. /*
  14. AGI Appdata Access Library
  15. Author: tobychui
  16. This library allow agi script to access files located in the web root
  17. *This library provide READ ONLY function*
  18. You cannot write to web folder due to security reasons. If you need to read write
  19. web root (which is not recommended), ask the user to mount it top web:/ manually
  20. */
  21. var webRoot string = "./web" //The web folder root
  22. func (g *Gateway) AppdataLibRegister() {
  23. err := g.RegisterLib("appdata", g.injectAppdataLibFunctions)
  24. if err != nil {
  25. log.Fatal(err)
  26. }
  27. }
  28. func (g *Gateway) injectAppdataLibFunctions(payload *static.AgiLibInjectionPayload) {
  29. vm := payload.VM
  30. //u := payload.User
  31. //scriptFsh := payload.ScriptFsh
  32. //scriptPath := payload.ScriptPath
  33. //w := payload.Writer
  34. //r := payload.Request
  35. vm.Set("_appdata_readfile", func(call otto.FunctionCall) otto.Value {
  36. relpath, err := call.Argument(0).ToString()
  37. if err != nil {
  38. g.RaiseError(err)
  39. return otto.FalseValue()
  40. }
  41. //Check if this is path escape
  42. escaped, err := static.CheckRootEscape(webRoot, filepath.Join(webRoot, relpath))
  43. if err != nil {
  44. g.RaiseError(err)
  45. return otto.FalseValue()
  46. }
  47. if escaped {
  48. g.RaiseError(errors.New("Path escape detected"))
  49. return otto.FalseValue()
  50. }
  51. //Check if file exists
  52. targetFile := filepath.Join(webRoot, relpath)
  53. if utils.FileExists(targetFile) && !filesystem.IsDir(targetFile) {
  54. content, err := os.ReadFile(targetFile)
  55. if err != nil {
  56. g.RaiseError(err)
  57. return otto.FalseValue()
  58. }
  59. //OK. Return the content of the file
  60. result, _ := vm.ToValue(string(content))
  61. return result
  62. } else if filesystem.IsDir(targetFile) {
  63. g.RaiseError(errors.New("Cannot read from directory"))
  64. return otto.FalseValue()
  65. } else {
  66. g.RaiseError(errors.New("File not exists"))
  67. return otto.FalseValue()
  68. }
  69. })
  70. vm.Set("_appdata_listdir", func(call otto.FunctionCall) otto.Value {
  71. relpath, err := call.Argument(0).ToString()
  72. if err != nil {
  73. g.RaiseError(err)
  74. return otto.FalseValue()
  75. }
  76. //Check if this is path escape
  77. escaped, err := static.CheckRootEscape(webRoot, filepath.Join(webRoot, relpath))
  78. if err != nil {
  79. g.RaiseError(err)
  80. return otto.FalseValue()
  81. }
  82. if escaped {
  83. g.RaiseError(errors.New("Path escape detected"))
  84. return otto.FalseValue()
  85. }
  86. //Check if file exists
  87. targetFolder := filepath.Join(webRoot, relpath)
  88. if utils.FileExists(targetFolder) && filesystem.IsDir(targetFolder) {
  89. //Glob the directory for filelist
  90. files, err := filepath.Glob(filepath.ToSlash(filepath.Clean(targetFolder)) + "/*")
  91. if err != nil {
  92. g.RaiseError(err)
  93. return otto.FalseValue()
  94. }
  95. results := []string{}
  96. for _, file := range files {
  97. rel, _ := filepath.Rel(webRoot, file)
  98. rel = filepath.ToSlash(rel)
  99. results = append(results, rel)
  100. }
  101. js, _ := json.Marshal(results)
  102. //OK. Return the content of the file
  103. result, _ := vm.ToValue(string(js))
  104. return result
  105. } else {
  106. g.RaiseError(errors.New("Directory not exists"))
  107. return otto.FalseValue()
  108. }
  109. })
  110. //Wrap all the native code function into an imagelib class
  111. vm.Run(`
  112. var appdata = {};
  113. appdata.readFile = _appdata_readfile;
  114. appdata.listDir = _appdata_listdir;
  115. `)
  116. }