agi.file.go 24 KB

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