agi.appdata.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package agi
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "log"
  7. "path/filepath"
  8. "github.com/robertkrimen/otto"
  9. "imuslab.com/arozos/mod/filesystem"
  10. user "imuslab.com/arozos/mod/user"
  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(vm *otto.Otto, u *user.User, scriptFsh *filesystem.FileSystemHandler, scriptPath string) {
  29. vm.Set("_appdata_readfile", func(call otto.FunctionCall) otto.Value {
  30. relpath, err := call.Argument(0).ToString()
  31. if err != nil {
  32. g.raiseError(err)
  33. return otto.FalseValue()
  34. }
  35. //Check if this is path escape
  36. escaped, err := checkRootEscape(webRoot, filepath.Join(webRoot, relpath))
  37. if err != nil {
  38. g.raiseError(err)
  39. return otto.FalseValue()
  40. }
  41. if escaped {
  42. g.raiseError(errors.New("Path escape detected"))
  43. return otto.FalseValue()
  44. }
  45. //Check if file exists
  46. targetFile := filepath.Join(webRoot, relpath)
  47. if utils.FileExists(targetFile) && !filesystem.IsDir(targetFile) {
  48. content, err := ioutil.ReadFile(targetFile)
  49. if err != nil {
  50. g.raiseError(err)
  51. return otto.FalseValue()
  52. }
  53. //OK. Return the content of the file
  54. result, _ := vm.ToValue(string(content))
  55. return result
  56. } else if filesystem.IsDir(targetFile) {
  57. g.raiseError(errors.New("Cannot read from directory"))
  58. return otto.FalseValue()
  59. } else {
  60. g.raiseError(errors.New("File not exists"))
  61. return otto.FalseValue()
  62. }
  63. })
  64. vm.Set("_appdata_listdir", func(call otto.FunctionCall) otto.Value {
  65. relpath, err := call.Argument(0).ToString()
  66. if err != nil {
  67. g.raiseError(err)
  68. return otto.FalseValue()
  69. }
  70. //Check if this is path escape
  71. escaped, err := checkRootEscape(webRoot, filepath.Join(webRoot, relpath))
  72. if err != nil {
  73. g.raiseError(err)
  74. return otto.FalseValue()
  75. }
  76. if escaped {
  77. g.raiseError(errors.New("Path escape detected"))
  78. return otto.FalseValue()
  79. }
  80. //Check if file exists
  81. targetFolder := filepath.Join(webRoot, relpath)
  82. if utils.FileExists(targetFolder) && filesystem.IsDir(targetFolder) {
  83. //Glob the directory for filelist
  84. files, err := filepath.Glob(filepath.ToSlash(filepath.Clean(targetFolder)) + "/*")
  85. if err != nil {
  86. g.raiseError(err)
  87. return otto.FalseValue()
  88. }
  89. results := []string{}
  90. for _, file := range files {
  91. rel, _ := filepath.Rel(webRoot, file)
  92. rel = filepath.ToSlash(rel)
  93. results = append(results, rel)
  94. }
  95. js, _ := json.Marshal(results)
  96. //OK. Return the content of the file
  97. result, _ := vm.ToValue(string(js))
  98. return result
  99. } else {
  100. g.raiseError(errors.New("Directory not exists"))
  101. return otto.FalseValue()
  102. }
  103. })
  104. //Wrap all the native code function into an imagelib class
  105. vm.Run(`
  106. var appdata = {};
  107. appdata.readFile = _appdata_readfile;
  108. appdata.listDir = _appdata_listdir;
  109. `)
  110. }