123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655 |
- package agi
- import (
- "errors"
- "log"
- "os"
- "path/filepath"
- "github.com/robertkrimen/otto"
- "imuslab.com/arozos/mod/filesystem/fssort"
- "imuslab.com/arozos/mod/filesystem/hidden"
- user "imuslab.com/arozos/mod/user"
- )
- /*
- AJGI File Processing Library
- This is a library for handling image related functionalities in agi scripts.
- By Alanyueng 2020 <- This person write shitty code that need me to tidy up (by tobychui)
- Complete rewrite by tobychui in Sept 2020
- */
- func (g *Gateway) FileLibRegister() {
- err := g.RegisterLib("filelib", g.injectFileLibFunctions)
- if err != nil {
- log.Fatal(err)
- }
- }
- func (g *Gateway) injectFileLibFunctions(vm *otto.Otto, u *user.User) {
- //Legacy File system API
- //writeFile(virtualFilepath, content) => return true/false when succeed / failed
- vm.Set("_filelib_writeFile", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check for permission
- if !u.CanWrite(vpath) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
- }
- content, err := call.Argument(1).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check if there is quota for the given length
- if !u.StorageQuota.HaveSpace(int64(len(content))) {
- //User have no remaining storage quota
- g.raiseError(errors.New("Storage Quota Fulled"))
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Translate the virtual path to realpath
- fsh, rpath, err := virtualPathToRealPath(vpath, u)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check if file already exists.
- if fsh.FileSystemAbstraction.FileExists(rpath) {
- //Check if this user own this file
- isOwner := u.IsOwnerOfFile(fsh, vpath)
- if isOwner {
- //This user own this system. Remove this file from his quota
- u.RemoveOwnershipFromFile(fsh, vpath)
- }
- }
- //Create and write to file using ioutil
- err = fsh.FileSystemAbstraction.WriteFile(rpath, []byte(content), 0755)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Add the filesize to user quota
- u.SetOwnerOfFile(fsh, vpath)
- reply, _ := vm.ToValue(true)
- return reply
- })
- vm.Set("_filelib_deleteFile", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check for permission
- if !u.CanWrite(vpath) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
- }
- //Translate the virtual path to realpath
- fsh, rpath, err := virtualPathToRealPath(vpath, u)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check if file already exists.
- if fsh.FileSystemAbstraction.FileExists(rpath) {
- //Check if this user own this file
- isOwner := u.IsOwnerOfFile(fsh, vpath)
- if isOwner {
- //This user own this system. Remove this file from his quota
- u.RemoveOwnershipFromFile(fsh, vpath)
- }
- } else {
- g.raiseError(errors.New("File not exists"))
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Remove the file
- fsh.FileSystemAbstraction.Remove(rpath)
- reply, _ := vm.ToValue(true)
- return reply
- })
- //readFile(virtualFilepath) => return content in string
- vm.Set("_filelib_readFile", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check for permission
- if !u.CanRead(vpath) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
- }
- //Translate the virtual path to realpath
- fsh, rpath, err := virtualPathToRealPath(vpath, u)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Create and write to file using ioUtil
- content, err := fsh.FileSystemAbstraction.ReadFile(rpath)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- reply, _ := vm.ToValue(string(content))
- return reply
- })
- //Listdir
- //readdir("user:/Desktop") => return filelist in array
- vm.Set("_filelib_readdir", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Translate the virtual path to realpath
- fsh, rpath, err := virtualPathToRealPath(vpath, u)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- fshAbs := fsh.FileSystemAbstraction
- rpath = filepath.ToSlash(filepath.Clean(rpath)) + "/*"
- fileList, err := fshAbs.Glob(rpath)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Translate all paths to virtual paths
- results := []string{}
- for _, file := range fileList {
- isHidden, _ := hidden.IsHidden(file, true)
- if !isHidden {
- thisRpath, _ := fshAbs.RealPathToVirtualPath(file, u.Username)
- results = append(results, thisRpath)
- }
- }
- reply, _ := vm.ToValue(results)
- return reply
- })
- //Usage
- //filelib.walk("user:/") => list everything recursively
- //filelib.walk("user:/", "folder") => list all folder recursively
- //filelib.walk("user:/", "file") => list all files recursively
- vm.Set("_filelib_walk", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- mode, err := call.Argument(1).ToString()
- if err != nil {
- mode = "all"
- }
- fsh, rpath, err := virtualPathToRealPath(vpath, u)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- results := []string{}
- fsh.FileSystemAbstraction.Walk(rpath, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- //Ignore this error file and continue
- return nil
- }
- thisVpath, err := realpathToVirtualpath(fsh, path, u)
- if err != nil {
- return nil
- }
- if mode == "file" {
- if !info.IsDir() {
- results = append(results, thisVpath)
- }
- } else if mode == "folder" {
- if info.IsDir() {
- results = append(results, thisVpath)
- }
- } else {
- results = append(results, thisVpath)
- }
- return nil
- })
- reply, _ := vm.ToValue(results)
- return reply
- })
- //Glob
- //glob("user:/Desktop/*.mp3") => return fileList in array
- //glob("/") => return a list of root directories
- //glob("user:/Desktop/*", "mostRecent") => return fileList in mostRecent sorting mode
- //glob("user:/Desktop/*", "user") => return fileList in array in user prefered sorting method
- vm.Set("_filelib_glob", func(call otto.FunctionCall) otto.Value {
- regex, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- userSortMode, err := call.Argument(1).ToString()
- if err != nil || userSortMode == "" || userSortMode == "undefined" {
- userSortMode = "default"
- }
- //Handle when regex = "." or "./" (listroot)
- if filepath.ToSlash(filepath.Clean(regex)) == "/" || filepath.Clean(regex) == "." {
- //List Root
- rootDirs := []string{}
- fileHandlers := u.GetAllFileSystemHandler()
- for _, fsh := range fileHandlers {
- if fsh.Hierarchy == "backup" {
- } else {
- rootDirs = append(rootDirs, fsh.UUID+":/")
- }
- }
- reply, _ := vm.ToValue(rootDirs)
- return reply
- } else {
- //Check for permission
- if !u.CanRead(regex) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
- }
- //This function can only handle wildcard in filename but not in dir name
- vrootPath := filepath.Dir(regex)
- regexFilename := filepath.Base(regex)
- //Rewrite and validate the sort mode
- if userSortMode == "user" {
- //Use user sorting mode.
- if g.Option.UserHandler.GetDatabase().KeyExists("fs-sortpref", u.Username+"/"+filepath.ToSlash(vrootPath)) {
- g.Option.UserHandler.GetDatabase().Read("fs-sortpref", u.Username+"/"+filepath.ToSlash(vrootPath), &userSortMode)
- } else {
- userSortMode = "default"
- }
- }
- if !fssort.SortModeIsSupported(userSortMode) {
- log.Println("[AGI] Sort mode: " + userSortMode + " not supported. Using default")
- userSortMode = "default"
- }
- //Translate the virtual path to realpath
- fsh, rrootPath, err := virtualPathToRealPath(vrootPath, u)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- suitableFiles, err := fsh.FileSystemAbstraction.Glob(filepath.Join(rrootPath, regexFilename))
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Sort the files
- newFilelist := fssort.SortFileList(suitableFiles, userSortMode)
- //Return the results in virtual paths
- results := []string{}
- for _, file := range newFilelist {
- isHidden, _ := hidden.IsHidden(file, true)
- if isHidden {
- //Hidden file. Skip this
- continue
- }
- thisRpath, _ := realpathToVirtualpath(fsh, filepath.ToSlash(file), u)
- results = append(results, thisRpath)
- }
- reply, _ := vm.ToValue(results)
- return reply
- }
- })
- //Advance Glob using file system special Glob, cannot use to scan root dirs
- vm.Set("_filelib_aglob", func(call otto.FunctionCall) otto.Value {
- regex, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- userSortMode, err := call.Argument(1).ToString()
- if err != nil || userSortMode == "" || userSortMode == "undefined" {
- userSortMode = "default"
- }
- if regex != "/" && !u.CanRead(regex) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
- }
- //This function can only handle wildcard in filename but not in dir name
- vrootPath := filepath.Dir(regex)
- regexFilename := filepath.Base(regex)
- //Rewrite and validate the sort mode
- if userSortMode == "user" {
- //Use user sorting mode.
- if g.Option.UserHandler.GetDatabase().KeyExists("fs-sortpref", u.Username+"/"+filepath.ToSlash(vrootPath)) {
- g.Option.UserHandler.GetDatabase().Read("fs-sortpref", u.Username+"/"+filepath.ToSlash(vrootPath), &userSortMode)
- } else {
- userSortMode = "default"
- }
- }
- if !fssort.SortModeIsSupported(userSortMode) {
- log.Println("[AGI] Sort mode: " + userSortMode + " not supported. Using default")
- userSortMode = "default"
- }
- //Translate the virtual path to realpath
- fsh, err := u.GetFileSystemHandlerFromVirtualPath(vrootPath)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- fshAbs := fsh.FileSystemAbstraction
- rrootPath, _ := fshAbs.VirtualPathToRealPath(vrootPath, u.Username)
- suitableFiles, err := fshAbs.Glob(filepath.Join(rrootPath, regexFilename))
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Sort the files
- newFilelist := fssort.SortFileList(suitableFiles, userSortMode)
- //Parse the results (Only extract the filepath)
- results := []string{}
- for _, filename := range newFilelist {
- isHidden, _ := hidden.IsHidden(filename, true)
- if isHidden {
- //Hidden file. Skip this
- continue
- }
- thisVpath, _ := realpathToVirtualpath(fsh, filename, u)
- results = append(results, thisVpath)
- }
- reply, _ := vm.ToValue(results)
- return reply
- })
- //filesize("user:/Desktop/test.txt")
- vm.Set("_filelib_filesize", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check for permission
- if !u.CanRead(vpath) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
- }
- fsh, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- fshAbs := fsh.FileSystemAbstraction
- rpath, err := fshAbs.VirtualPathToRealPath(vpath, u.Username)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Get filesize of file
- rawsize := fshAbs.GetFileSize(rpath)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- reply, _ := vm.ToValue(rawsize)
- return reply
- })
- //fileExists("user:/Desktop/test.txt") => return true / false
- vm.Set("_filelib_fileExists", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check for permission
- if !u.CanRead(vpath) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
- }
- fsh, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- fshAbs := fsh.FileSystemAbstraction
- rpath, err := fshAbs.VirtualPathToRealPath(vpath, u.Username)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- if fshAbs.FileExists(rpath) {
- reply, _ := vm.ToValue(true)
- return reply
- } else {
- reply, _ := vm.ToValue(false)
- return reply
- }
- })
- //fileExists("user:/Desktop/test.txt") => return true / false
- vm.Set("_filelib_isDir", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check for permission
- if !u.CanRead(vpath) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied: "+vpath))
- }
- //Translate the virtual path to realpath
- fsh, rpath, err := virtualPathToRealPath(vpath, u)
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- if _, err := fsh.FileSystemAbstraction.Stat(rpath); os.IsNotExist(err) {
- //File not exists
- panic(vm.MakeCustomError("File Not Exists", "Required path not exists"))
- }
- if fsh.FileSystemAbstraction.IsDir(rpath) {
- reply, _ := vm.ToValue(true)
- return reply
- } else {
- reply, _ := vm.ToValue(false)
- return reply
- }
- })
- //Make directory command
- vm.Set("_filelib_mkdir", func(call otto.FunctionCall) otto.Value {
- vdir, err := call.Argument(0).ToString()
- if err != nil {
- return otto.FalseValue()
- }
- //Check for permission
- if !u.CanWrite(vdir) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
- }
- //Translate the path to realpath
- fsh, rdir, err := virtualPathToRealPath(vdir, u)
- if err != nil {
- log.Println(err.Error())
- return otto.FalseValue()
- }
- //Create the directory at rdir location
- err = fsh.FileSystemAbstraction.MkdirAll(rdir, 0755)
- if err != nil {
- log.Println(err.Error())
- return otto.FalseValue()
- }
- return otto.TrueValue()
- })
- //Get MD5 of the given filepath, not implemented
- vm.Set("_filelib_md5", func(call otto.FunctionCall) otto.Value {
- log.Println("Call to MD5 Functions!")
- return otto.FalseValue()
- })
- //Get the root name of the given virtual path root
- vm.Set("_filelib_rname", func(call otto.FunctionCall) otto.Value {
- //Get virtual path from the function input
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- return otto.FalseValue()
- }
- //Get fs handler from the vpath
- fsHandler, err := u.GetFileSystemHandlerFromVirtualPath(vpath)
- if err != nil {
- g.raiseError(err)
- return otto.FalseValue()
- }
- //Return the name of the fsHandler
- name, _ := vm.ToValue(fsHandler.Name)
- return name
- })
- vm.Set("_filelib_mtime", func(call otto.FunctionCall) otto.Value {
- vpath, err := call.Argument(0).ToString()
- if err != nil {
- g.raiseError(err)
- reply, _ := vm.ToValue(false)
- return reply
- }
- //Check for permission
- if !u.CanRead(vpath) {
- panic(vm.MakeCustomError("PermissionDenied", "Path access denied"))
- }
- parseToUnix, err := call.Argument(1).ToBoolean()
- if err != nil {
- parseToUnix = false
- }
- fsh, rpath, err := virtualPathToRealPath(vpath, u)
- if err != nil {
- log.Println(err.Error())
- return otto.FalseValue()
- }
- info, err := fsh.FileSystemAbstraction.Stat(rpath)
- if err != nil {
- log.Println(err.Error())
- return otto.FalseValue()
- }
- modTime := info.ModTime()
- if parseToUnix {
- result, _ := otto.ToValue(modTime.Unix())
- return result
- } else {
- result, _ := otto.ToValue(modTime.Format("2006-01-02 15:04:05"))
- return result
- }
- })
- //Other file operations, wip
- //Wrap all the native code function into an imagelib class
- vm.Run(`
- var filelib = {};
- filelib.writeFile = _filelib_writeFile;
- filelib.readFile = _filelib_readFile;
- filelib.deleteFile = _filelib_deleteFile;
- filelib.readdir = _filelib_readdir;
- filelib.walk = _filelib_walk;
- filelib.glob = _filelib_glob;
- filelib.aglob = _filelib_aglob;
- filelib.filesize = _filelib_filesize;
- filelib.fileExists = _filelib_fileExists;
- filelib.isDir = _filelib_isDir;
- filelib.md5 = _filelib_md5;
- filelib.mkdir = _filelib_mkdir;
- filelib.mtime = _filelib_mtime;
- filelib.rootName = _filelib_rname;
- `)
- }
|