agi.file.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. package agi
  2. import (
  3. "crypto/md5"
  4. "encoding/hex"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "io/fs"
  10. "os"
  11. "path/filepath"
  12. "github.com/robertkrimen/otto"
  13. "imuslab.com/arozos/mod/agi/static"
  14. "imuslab.com/arozos/mod/filesystem/fssort"
  15. "imuslab.com/arozos/mod/filesystem/hidden"
  16. "imuslab.com/arozos/mod/info/logger"
  17. )
  18. /*
  19. AJGI File Processing Library
  20. This is a library for handling image related functionalities in agi scripts.
  21. By Alanyueng 2020 <- This person write shitty code that need me to tidy up (by tobychui)
  22. Complete rewrite by tobychui in Sept 2020
  23. */
  24. func (g *Gateway) FileLibRegister() {
  25. err := g.RegisterLib("filelib", g.injectFileLibFunctions)
  26. if err != nil {
  27. logger.PrintAndLog("Agi", fmt.Sprint(err), nil)
  28. os.Exit(1)
  29. }
  30. }
  31. func (g *Gateway) injectFileLibFunctions(payload *static.AgiLibInjectionPayload) {
  32. vm := payload.VM
  33. u := payload.User
  34. scriptFsh := payload.ScriptFsh
  35. //scriptPath := payload.ScriptPath
  36. //w := payload.Writer
  37. //r := payload.Request
  38. //writeFile(virtualFilepath, content) => return true/false when succeed / failed
  39. vm.Set("_filelib_writeFile", func(call otto.FunctionCall) otto.Value {
  40. vpath, err := call.Argument(0).ToString()
  41. if err != nil {
  42. g.RaiseError(err)
  43. return otto.FalseValue()
  44. }
  45. //Rewrite the vpath if it is relative
  46. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  47. //Check for permission
  48. if !u.CanWrite(vpath) {
  49. panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
  50. }
  51. content, err := call.Argument(1).ToString()
  52. if err != nil {
  53. g.RaiseError(err)
  54. return otto.FalseValue()
  55. }
  56. //Check if there is quota for the given length
  57. if !u.StorageQuota.HaveSpace(int64(len(content))) {
  58. //User have no remaining storage quota
  59. g.RaiseError(errors.New("Storage Quota Fulled"))
  60. return otto.FalseValue()
  61. }
  62. //Translate the virtual path to realpath
  63. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  64. if err != nil {
  65. g.RaiseError(err)
  66. return otto.FalseValue()
  67. }
  68. //Check if file already exists.
  69. if fsh.FileSystemAbstraction.FileExists(rpath) {
  70. //Check if this user own this file
  71. isOwner := u.IsOwnerOfFile(fsh, vpath)
  72. if isOwner {
  73. //This user own this system. Remove this file from his quota
  74. u.RemoveOwnershipFromFile(fsh, vpath)
  75. }
  76. }
  77. //Create and write to file using ioutil
  78. err = fsh.FileSystemAbstraction.WriteFile(rpath, []byte(content), 0755)
  79. if err != nil {
  80. g.RaiseError(err)
  81. return otto.FalseValue()
  82. }
  83. //Add the filesize to user quota
  84. u.SetOwnerOfFile(fsh, vpath)
  85. reply, _ := vm.ToValue(true)
  86. return reply
  87. })
  88. vm.Set("_filelib_deleteFile", func(call otto.FunctionCall) otto.Value {
  89. vpath, err := call.Argument(0).ToString()
  90. if err != nil {
  91. g.RaiseError(err)
  92. return otto.FalseValue()
  93. }
  94. //Rewrite the vpath if it is relative
  95. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  96. //Check for permission
  97. if !u.CanWrite(vpath) {
  98. panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
  99. }
  100. //Translate the virtual path to realpath
  101. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  102. if err != nil {
  103. g.RaiseError(err)
  104. return otto.FalseValue()
  105. }
  106. //Check if file already exists.
  107. if fsh.FileSystemAbstraction.FileExists(rpath) {
  108. //Check if this user own this file
  109. isOwner := u.IsOwnerOfFile(fsh, vpath)
  110. if isOwner {
  111. //This user own this system. Remove this file from his quota
  112. u.RemoveOwnershipFromFile(fsh, vpath)
  113. }
  114. } else {
  115. g.RaiseError(errors.New("File not exists"))
  116. return otto.FalseValue()
  117. }
  118. //Remove the file
  119. fsh.FileSystemAbstraction.Remove(rpath)
  120. reply, _ := vm.ToValue(true)
  121. return reply
  122. })
  123. //readFile(virtualFilepath) => return content in string
  124. vm.Set("_filelib_readFile", func(call otto.FunctionCall) otto.Value {
  125. vpath, err := call.Argument(0).ToString()
  126. if err != nil {
  127. g.RaiseError(err)
  128. return otto.FalseValue()
  129. }
  130. //Rewrite the vpath if it is relative
  131. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  132. //Check for permission
  133. if !u.CanRead(vpath) {
  134. panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
  135. }
  136. //Translate the virtual path to realpath
  137. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  138. if err != nil {
  139. g.RaiseError(err)
  140. return otto.FalseValue()
  141. }
  142. //Create and write to file using ioUtil
  143. content, err := fsh.FileSystemAbstraction.ReadFile(rpath)
  144. if err != nil {
  145. g.RaiseError(err)
  146. return otto.FalseValue()
  147. }
  148. reply, _ := vm.ToValue(string(content))
  149. return reply
  150. })
  151. //Usage
  152. //filelib.walk("user:/") => list everything recursively
  153. //filelib.walk("user:/", "folder") => list all folder recursively
  154. //filelib.walk("user:/", "file") => list all files recursively
  155. vm.Set("_filelib_walk", func(call otto.FunctionCall) otto.Value {
  156. vpath, err := call.Argument(0).ToString()
  157. if err != nil {
  158. g.RaiseError(err)
  159. return otto.FalseValue()
  160. }
  161. mode, err := call.Argument(1).ToString()
  162. if err != nil {
  163. mode = "all"
  164. }
  165. //Rewrite the vpath if it is relative
  166. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  167. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  168. if err != nil {
  169. g.RaiseError(err)
  170. return otto.FalseValue()
  171. }
  172. results := []string{}
  173. fsh.FileSystemAbstraction.Walk(rpath, func(path string, info os.FileInfo, err error) error {
  174. if err != nil {
  175. //Ignore this error file and continue
  176. return nil
  177. }
  178. thisVpath, err := static.RealpathToVirtualpath(fsh, path, u)
  179. if err != nil {
  180. return nil
  181. }
  182. if mode == "file" {
  183. if !info.IsDir() {
  184. results = append(results, thisVpath)
  185. }
  186. } else if mode == "folder" {
  187. if info.IsDir() {
  188. results = append(results, thisVpath)
  189. }
  190. } else {
  191. results = append(results, thisVpath)
  192. }
  193. return nil
  194. })
  195. reply, _ := vm.ToValue(results)
  196. return reply
  197. })
  198. //Glob
  199. //glob("user:/Desktop/*.mp3") => return fileList in array
  200. //glob("/") => return a list of root directories
  201. //glob("user:/Desktop/*", "mostRecent") => return fileList in mostRecent sorting mode
  202. //glob("user:/Desktop/*", "user") => return fileList in array in user prefered sorting method
  203. vm.Set("_filelib_glob", func(call otto.FunctionCall) otto.Value {
  204. regex, err := call.Argument(0).ToString()
  205. if err != nil {
  206. g.RaiseError(err)
  207. return otto.FalseValue()
  208. }
  209. userSortMode, err := call.Argument(1).ToString()
  210. if err != nil || userSortMode == "" || userSortMode == "undefined" {
  211. userSortMode = "default"
  212. }
  213. //Handle when regex = "." or "./" (listroot)
  214. if filepath.ToSlash(filepath.Clean(regex)) == "/" || filepath.Clean(regex) == "." {
  215. //List Root
  216. rootDirs := []string{}
  217. fileHandlers := u.GetAllFileSystemHandler()
  218. for _, fsh := range fileHandlers {
  219. if fsh.Hierarchy == "backup" {
  220. } else {
  221. rootDirs = append(rootDirs, fsh.UUID+":/")
  222. }
  223. }
  224. reply, _ := vm.ToValue(rootDirs)
  225. return reply
  226. } else {
  227. //Check for permission
  228. if !u.CanRead(regex) {
  229. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  230. }
  231. //This function can only handle wildcard in filename but not in dir name
  232. vrootPath := filepath.Dir(regex)
  233. regexFilename := filepath.Base(regex)
  234. //Rewrite and validate the sort mode
  235. if userSortMode == "user" {
  236. //Use user sorting mode.
  237. if g.Option.UserHandler.GetDatabase().KeyExists("fs-sortpref", u.Username+"/"+filepath.ToSlash(filepath.Clean(vrootPath))) {
  238. g.Option.UserHandler.GetDatabase().Read("fs-sortpref", u.Username+"/"+filepath.ToSlash(filepath.Clean(vrootPath)), &userSortMode)
  239. } else {
  240. userSortMode = "default"
  241. }
  242. }
  243. if !fssort.SortModeIsSupported(userSortMode) {
  244. logger.PrintAndLog("Agi", "[AGI] Sort mode: "+userSortMode+" not supported. Using default", nil)
  245. userSortMode = "default"
  246. }
  247. //Translate the virtual path to realpath
  248. fsh, rrootPath, err := static.VirtualPathToRealPath(vrootPath, u)
  249. if err != nil {
  250. g.RaiseError(err)
  251. return otto.FalseValue()
  252. }
  253. suitableFiles, err := fsh.FileSystemAbstraction.Glob(filepath.Join(rrootPath, regexFilename))
  254. if err != nil {
  255. g.RaiseError(err)
  256. return otto.FalseValue()
  257. }
  258. fileList := []string{}
  259. fis := []fs.FileInfo{}
  260. for _, thisFile := range suitableFiles {
  261. fi, err := fsh.FileSystemAbstraction.Stat(thisFile)
  262. if err == nil {
  263. fileList = append(fileList, thisFile)
  264. fis = append(fis, fi)
  265. }
  266. }
  267. //Sort the files
  268. newFilelist := fssort.SortFileList(fileList, fis, userSortMode)
  269. //Return the results in virtual paths
  270. results := []string{}
  271. for _, file := range newFilelist {
  272. isHidden, _ := hidden.IsHidden(file, true)
  273. if isHidden {
  274. //Hidden file. Skip this
  275. continue
  276. }
  277. thisVpath, _ := static.RealpathToVirtualpath(fsh, file, u)
  278. results = append(results, thisVpath)
  279. }
  280. reply, _ := vm.ToValue(results)
  281. return reply
  282. }
  283. })
  284. //Advance Glob using file system special Glob, cannot use to scan root dirs
  285. vm.Set("_filelib_aglob", func(call otto.FunctionCall) otto.Value {
  286. regex, err := call.Argument(0).ToString()
  287. if err != nil {
  288. g.RaiseError(err)
  289. return otto.FalseValue()
  290. }
  291. userSortMode, err := call.Argument(1).ToString()
  292. if err != nil || userSortMode == "" || userSortMode == "undefined" {
  293. userSortMode = "default"
  294. }
  295. if regex != "/" && !u.CanRead(regex) {
  296. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  297. }
  298. //This function can only handle wildcard in filename but not in dir name
  299. vrootPath := filepath.Dir(regex)
  300. regexFilename := filepath.Base(regex)
  301. //Rewrite and validate the sort mode
  302. if userSortMode == "user" {
  303. //Use user sorting mode.
  304. if g.Option.UserHandler.GetDatabase().KeyExists("fs-sortpref", u.Username+"/"+filepath.ToSlash(filepath.Clean(vrootPath))) {
  305. g.Option.UserHandler.GetDatabase().Read("fs-sortpref", u.Username+"/"+filepath.ToSlash(filepath.Clean(vrootPath)), &userSortMode)
  306. } else {
  307. userSortMode = "default"
  308. }
  309. }
  310. if !fssort.SortModeIsSupported(userSortMode) {
  311. logger.PrintAndLog("Agi", "[AGI] Sort mode: "+userSortMode+" not supported. Using default", nil)
  312. userSortMode = "default"
  313. }
  314. //Translate the virtual path to realpath
  315. fsh, err := u.GetFileSystemHandlerFromVirtualPath(vrootPath)
  316. if err != nil {
  317. g.RaiseError(err)
  318. return otto.FalseValue()
  319. }
  320. fshAbs := fsh.FileSystemAbstraction
  321. rrootPath, _ := fshAbs.VirtualPathToRealPath(vrootPath, u.Username)
  322. suitableFiles, err := fshAbs.Glob(filepath.Join(rrootPath, regexFilename))
  323. if err != nil {
  324. g.RaiseError(err)
  325. return otto.FalseValue()
  326. }
  327. fileList := []string{}
  328. fis := []fs.FileInfo{}
  329. for _, thisFile := range suitableFiles {
  330. fi, err := fsh.FileSystemAbstraction.Stat(thisFile)
  331. if err == nil {
  332. fileList = append(fileList, thisFile)
  333. fis = append(fis, fi)
  334. }
  335. }
  336. //Sort the files
  337. newFilelist := fssort.SortFileList(fileList, fis, userSortMode)
  338. //Parse the results (Only extract the filepath)
  339. results := []string{}
  340. for _, filename := range newFilelist {
  341. isHidden, _ := hidden.IsHidden(filename, true)
  342. if isHidden {
  343. //Hidden file. Skip this
  344. continue
  345. }
  346. thisVpath, _ := static.RealpathToVirtualpath(fsh, filename, u)
  347. results = append(results, thisVpath)
  348. }
  349. reply, _ := vm.ToValue(results)
  350. return reply
  351. })
  352. vm.Set("_filelib_readdir", func(call otto.FunctionCall) otto.Value {
  353. vpath, err := call.Argument(0).ToString()
  354. if err != nil {
  355. g.RaiseError(err)
  356. return otto.FalseValue()
  357. }
  358. //Rewrite the vpath if it is relative
  359. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  360. //Check for permission
  361. if !u.CanRead(vpath) {
  362. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  363. }
  364. userSortMode, err := call.Argument(1).ToString()
  365. if err != nil || userSortMode == "" || userSortMode == "undefined" {
  366. userSortMode = "default"
  367. }
  368. //Rewrite and validate the sort mode
  369. if userSortMode == "user" {
  370. //Use user sorting mode.
  371. if g.Option.UserHandler.GetDatabase().KeyExists("fs-sortpref", u.Username+"/"+filepath.ToSlash(filepath.Clean(vpath))) {
  372. g.Option.UserHandler.GetDatabase().Read("fs-sortpref", u.Username+"/"+filepath.ToSlash(filepath.Clean(vpath)), &userSortMode)
  373. } else {
  374. userSortMode = "default"
  375. }
  376. }
  377. if !fssort.SortModeIsSupported(userSortMode) {
  378. logger.PrintAndLog("Agi", "[AGI] Sort mode: "+userSortMode+" not supported. Using default", nil)
  379. userSortMode = "default"
  380. }
  381. fsh, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
  382. if err != nil {
  383. g.RaiseError(err)
  384. return otto.FalseValue()
  385. }
  386. fshAbs := fsh.FileSystemAbstraction
  387. rpath, err := fshAbs.VirtualPathToRealPath(vpath, u.Username)
  388. if err != nil {
  389. g.RaiseError(err)
  390. return otto.FalseValue()
  391. }
  392. dirEntry, err := fshAbs.ReadDir(rpath)
  393. if err != nil {
  394. g.RaiseError(err)
  395. return otto.FalseValue()
  396. }
  397. type fileInfo struct {
  398. Filename string
  399. Filepath string
  400. Ext string
  401. Filesize int64
  402. Modtime int64
  403. IsDir bool
  404. }
  405. //Sort the dirEntry by file info, a bit slow :(
  406. if userSortMode != "default" {
  407. //Prepare the data structure for sorting
  408. newDirEntry := fssort.SortDirEntryList(dirEntry, userSortMode)
  409. dirEntry = newDirEntry
  410. }
  411. results := []fileInfo{}
  412. for _, de := range dirEntry {
  413. isHidden, _ := hidden.IsHidden(de.Name(), false)
  414. if isHidden {
  415. continue
  416. }
  417. fstat, _ := de.Info()
  418. vpath, _ := static.RealpathToVirtualpath(fsh, filepath.ToSlash(filepath.Join(rpath, de.Name())), u)
  419. thisInfo := fileInfo{
  420. Filename: de.Name(),
  421. Filepath: vpath,
  422. Ext: filepath.Ext(de.Name()),
  423. Filesize: fstat.Size(),
  424. Modtime: fstat.ModTime().Unix(),
  425. IsDir: de.IsDir(),
  426. }
  427. results = append(results, thisInfo)
  428. }
  429. js, _ := json.Marshal(results)
  430. r, _ := vm.ToValue(string(js))
  431. return r
  432. })
  433. //filesize("user:/Desktop/test.txt")
  434. vm.Set("_filelib_filesize", func(call otto.FunctionCall) otto.Value {
  435. vpath, err := call.Argument(0).ToString()
  436. if err != nil {
  437. g.RaiseError(err)
  438. return otto.FalseValue()
  439. }
  440. //Rewrite the vpath if it is relative
  441. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  442. //Check for permission
  443. if !u.CanRead(vpath) {
  444. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  445. }
  446. fsh, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
  447. if err != nil {
  448. g.RaiseError(err)
  449. return otto.FalseValue()
  450. }
  451. fshAbs := fsh.FileSystemAbstraction
  452. rpath, err := fshAbs.VirtualPathToRealPath(vpath, u.Username)
  453. if err != nil {
  454. g.RaiseError(err)
  455. return otto.FalseValue()
  456. }
  457. //Get filesize of file
  458. rawsize := fshAbs.GetFileSize(rpath)
  459. if err != nil {
  460. g.RaiseError(err)
  461. return otto.FalseValue()
  462. }
  463. reply, _ := vm.ToValue(rawsize)
  464. return reply
  465. })
  466. //fileExists("user:/Desktop/test.txt") => return true / false
  467. vm.Set("_filelib_fileExists", func(call otto.FunctionCall) otto.Value {
  468. vpath, err := call.Argument(0).ToString()
  469. if err != nil {
  470. g.RaiseError(err)
  471. return otto.FalseValue()
  472. }
  473. //Rewrite the vpath if it is relative
  474. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  475. //Check for permission
  476. if !u.CanRead(vpath) {
  477. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  478. }
  479. fsh, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
  480. if err != nil {
  481. g.RaiseError(err)
  482. return otto.FalseValue()
  483. }
  484. fshAbs := fsh.FileSystemAbstraction
  485. rpath, err := fshAbs.VirtualPathToRealPath(vpath, u.Username)
  486. if err != nil {
  487. g.RaiseError(err)
  488. return otto.FalseValue()
  489. }
  490. if fshAbs.FileExists(rpath) {
  491. return otto.TrueValue()
  492. } else {
  493. return otto.FalseValue()
  494. }
  495. })
  496. //fileExists("user:/Desktop/test.txt") => return true / false
  497. vm.Set("_filelib_isDir", func(call otto.FunctionCall) otto.Value {
  498. vpath, err := call.Argument(0).ToString()
  499. if err != nil {
  500. g.RaiseError(err)
  501. return otto.FalseValue()
  502. }
  503. //Rewrite the vpath if it is relative
  504. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  505. //Check for permission
  506. if !u.CanRead(vpath) {
  507. panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
  508. }
  509. //Translate the virtual path to realpath
  510. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  511. if err != nil {
  512. g.RaiseError(err)
  513. return otto.FalseValue()
  514. }
  515. if _, err := fsh.FileSystemAbstraction.Stat(rpath); os.IsNotExist(err) {
  516. //File not exists
  517. panic(vm.MakeCustomError("File Not Exists", "Required path not exists"))
  518. }
  519. if fsh.FileSystemAbstraction.IsDir(rpath) {
  520. return otto.TrueValue()
  521. } else {
  522. return otto.FalseValue()
  523. }
  524. })
  525. //Make directory command
  526. vm.Set("_filelib_mkdir", func(call otto.FunctionCall) otto.Value {
  527. vdir, err := call.Argument(0).ToString()
  528. if err != nil {
  529. return otto.FalseValue()
  530. }
  531. //Check for permission
  532. if !u.CanWrite(vdir) {
  533. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  534. }
  535. //Translate the path to realpath
  536. fsh, rdir, err := static.VirtualPathToRealPath(vdir, u)
  537. if err != nil {
  538. logger.PrintAndLog("Agi", err.Error(), nil)
  539. return otto.FalseValue()
  540. }
  541. //Create the directory at rdir location
  542. err = fsh.FileSystemAbstraction.MkdirAll(rdir, 0755)
  543. if err != nil {
  544. logger.PrintAndLog("Agi", err.Error(), nil)
  545. return otto.FalseValue()
  546. }
  547. return otto.TrueValue()
  548. })
  549. //Get MD5 of the given filepath, not implemented
  550. vm.Set("_filelib_md5", func(call otto.FunctionCall) otto.Value {
  551. vpath, err := call.Argument(0).ToString()
  552. if err != nil {
  553. g.RaiseError(err)
  554. return otto.FalseValue()
  555. }
  556. //Rewrite the vpath if it is relative
  557. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  558. //Check for permission
  559. if !u.CanRead(vpath) {
  560. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  561. }
  562. fsh, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
  563. if err != nil {
  564. g.RaiseError(err)
  565. return otto.FalseValue()
  566. }
  567. fshAbs := fsh.FileSystemAbstraction
  568. rpath, err := fshAbs.VirtualPathToRealPath(vpath, u.Username)
  569. if err != nil {
  570. g.RaiseError(err)
  571. return otto.FalseValue()
  572. }
  573. f, err := fshAbs.ReadStream(rpath)
  574. if err != nil {
  575. g.RaiseError(err)
  576. return otto.FalseValue()
  577. }
  578. defer f.Close()
  579. h := md5.New()
  580. if _, err := io.Copy(h, f); err != nil {
  581. g.RaiseError(err)
  582. return otto.FalseValue()
  583. }
  584. md5Sum := hex.EncodeToString(h.Sum(nil))
  585. result, _ := vm.ToValue(md5Sum)
  586. return result
  587. })
  588. //Get the root name of the given virtual path root
  589. vm.Set("_filelib_rname", func(call otto.FunctionCall) otto.Value {
  590. //Get virtual path from the function input
  591. vpath, err := call.Argument(0).ToString()
  592. if err != nil {
  593. g.RaiseError(err)
  594. return otto.FalseValue()
  595. }
  596. //Rewrite the vpath if it is relative
  597. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  598. //Get fs handler from the vpath
  599. fsHandler, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
  600. if err != nil {
  601. g.RaiseError(err)
  602. return otto.FalseValue()
  603. }
  604. //Return the name of the fsHandler
  605. name, _ := vm.ToValue(fsHandler.Name)
  606. return name
  607. })
  608. vm.Set("_filelib_mtime", func(call otto.FunctionCall) otto.Value {
  609. vpath, err := call.Argument(0).ToString()
  610. if err != nil {
  611. g.RaiseError(err)
  612. return otto.FalseValue()
  613. }
  614. //Rewrite the vpath if it is relative
  615. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  616. //Check for permission
  617. if !u.CanRead(vpath) {
  618. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  619. }
  620. parseToUnix, err := call.Argument(1).ToBoolean()
  621. if err != nil {
  622. parseToUnix = false
  623. }
  624. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  625. if err != nil {
  626. logger.PrintAndLog("Agi", err.Error(), nil)
  627. return otto.FalseValue()
  628. }
  629. info, err := fsh.FileSystemAbstraction.Stat(rpath)
  630. if err != nil {
  631. logger.PrintAndLog("Agi", err.Error(), nil)
  632. return otto.FalseValue()
  633. }
  634. modTime := info.ModTime()
  635. if parseToUnix {
  636. result, _ := otto.ToValue(modTime.Unix())
  637. return result
  638. } else {
  639. result, _ := otto.ToValue(modTime.Format("2006-01-02 15:04:05"))
  640. return result
  641. }
  642. })
  643. //ArozOS v2.0 New features
  644. //Reading or writing from hex to target virtual filepath
  645. //Write binary from hex string
  646. vm.Set("_filelib_writeBinaryFile", func(call otto.FunctionCall) otto.Value {
  647. vpath, err := call.Argument(0).ToString()
  648. if err != nil {
  649. g.RaiseError(err)
  650. return otto.FalseValue()
  651. }
  652. //Rewrite the vpath if it is relative
  653. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  654. //Check for permission
  655. if !u.CanWrite(vpath) {
  656. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  657. }
  658. hexContent, err := call.Argument(1).ToString()
  659. if err != nil {
  660. g.RaiseError(err)
  661. return otto.FalseValue()
  662. }
  663. //Get the target vpath
  664. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  665. if err != nil {
  666. logger.PrintAndLog("Agi", err.Error(), nil)
  667. return otto.FalseValue()
  668. }
  669. //Decode the hex content to bytes
  670. hexContentInByte, err := hex.DecodeString(hexContent)
  671. if err != nil {
  672. g.RaiseError(err)
  673. return otto.FalseValue()
  674. }
  675. //Write the file to target file
  676. err = fsh.FileSystemAbstraction.WriteFile(rpath, hexContentInByte, 0775)
  677. if err != nil {
  678. g.RaiseError(err)
  679. return otto.FalseValue()
  680. }
  681. return otto.TrueValue()
  682. })
  683. //Read file from external fsh. Small file only
  684. vm.Set("_filelib_readBinaryFile", func(call otto.FunctionCall) otto.Value {
  685. vpath, err := call.Argument(0).ToString()
  686. if err != nil {
  687. g.RaiseError(err)
  688. return otto.NullValue()
  689. }
  690. //Rewrite the vpath if it is relative
  691. vpath = static.RelativeVpathRewrite(scriptFsh, vpath, vm, u)
  692. //Check for permission
  693. if !u.CanRead(vpath) {
  694. panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
  695. }
  696. //Get the target vpath
  697. fsh, rpath, err := static.VirtualPathToRealPath(vpath, u)
  698. if err != nil {
  699. g.RaiseError(err)
  700. return otto.NullValue()
  701. }
  702. if !fsh.FileSystemAbstraction.FileExists(rpath) {
  703. //Check if the target file exists
  704. g.RaiseError(err)
  705. return otto.NullValue()
  706. }
  707. content, err := fsh.FileSystemAbstraction.ReadFile(rpath)
  708. if err != nil {
  709. g.RaiseError(err)
  710. return otto.NullValue()
  711. }
  712. hexifiedContent := hex.EncodeToString(content)
  713. val, _ := vm.ToValue(hexifiedContent)
  714. return val
  715. })
  716. //Other file operations, wip
  717. //Wrap all the native code function into an imagelib class
  718. vm.Run(`
  719. var filelib = {};
  720. filelib.writeFile = _filelib_writeFile;
  721. filelib.readFile = _filelib_readFile;
  722. filelib.deleteFile = _filelib_deleteFile;
  723. filelib.walk = _filelib_walk;
  724. filelib.glob = _filelib_glob;
  725. filelib.aglob = _filelib_aglob;
  726. filelib.filesize = _filelib_filesize;
  727. filelib.fileExists = _filelib_fileExists;
  728. filelib.isDir = _filelib_isDir;
  729. filelib.md5 = _filelib_md5;
  730. filelib.mkdir = _filelib_mkdir;
  731. filelib.mtime = _filelib_mtime;
  732. filelib.rootName = _filelib_rname;
  733. filelib.readdir = function(path, sortmode){
  734. var s = _filelib_readdir(path, sortmode);
  735. return JSON.parse(s);
  736. };
  737. `)
  738. }