| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 | package agiimport (	"encoding/csv"	"encoding/json"	"errors"	"io/ioutil"	"log"	"os/exec"	"path/filepath"	"strings"	"time"	"github.com/robertkrimen/otto")//Inject aroz online custom functions into the virtual machinefunc (g *Gateway) injectStandardLibs(vm *otto.Otto, scriptFile string, scriptScope string) {	//Define system core modules and definations	sysdb := g.Option.UserHandler.GetDatabase()	//Define VM global variables	vm.Set("BUILD_VERSION", g.Option.BuildVersion)	vm.Set("INTERNVAL_VERSION", g.Option.InternalVersion)	vm.Set("LOADED_MODULES", g.Option.LoadedModule)	vm.Set("LOADED_STORAGES", g.Option.UserHandler.GetStoragePool())	vm.Set("HTTP_RESP", "")	vm.Set("HTTP_HEADER", "text/plain")	//Response related	vm.Set("sendResp", func(call otto.FunctionCall) otto.Value {		argString, _ := call.Argument(0).ToString()		vm.Set("HTTP_RESP", argString)		return otto.Value{}	})	vm.Set("sendOK", func(call otto.FunctionCall) otto.Value {		vm.Set("HTTP_RESP", "ok")		return otto.Value{}	})	vm.Set("_sendJSONResp", func(call otto.FunctionCall) otto.Value {		argString, _ := call.Argument(0).ToString()		vm.Set("HTTP_HEADER", "application/json")		vm.Set("HTTP_RESP", argString)		return otto.Value{}	})	vm.Run(`		sendJSONResp = function(object){			if (typeof(object) === "object"){				_sendJSONResp(JSON.stringify(object));			}else{				_sendJSONResp(object);			}		}	`)	vm.Set("addNightlyTask", func(call otto.FunctionCall) otto.Value {		scriptPath, _ := call.Argument(0).ToString() //From web directory		if isValidAGIScript(scriptPath) {			g.NightlyScripts = append(g.NightlyScripts, scriptPath)		} else {			return otto.FalseValue()		}		return otto.TrueValue()	})	//Database related	//newDBTableIfNotExists(tableName)	vm.Set("newDBTableIfNotExists", func(call otto.FunctionCall) otto.Value {		tableName, err := call.Argument(0).ToString()		if err != nil {			g.raiseError(err)			reply, _ := vm.ToValue(false)			return reply		}		//Create the table with given tableName		if g.filterDBTable(tableName, false) {			sysdb.NewTable(tableName)			//Return true			reply, _ := vm.ToValue(true)			return reply		}		reply, _ := vm.ToValue(false)		return reply	})	vm.Set("DBTableExists", func(call otto.FunctionCall) otto.Value {		tableName, err := call.Argument(0).ToString()		if err != nil {			g.raiseError(err)			reply, _ := vm.ToValue(false)			return reply		}		//Create the table with given tableName		if sysdb.TableExists(tableName) {			return otto.TrueValue()		}		return otto.FalseValue()	})	//dropDBTable(tablename)	vm.Set("dropDBTable", func(call otto.FunctionCall) otto.Value {		tableName, err := call.Argument(0).ToString()		if err != nil {			g.raiseError(err)			reply, _ := vm.ToValue(false)			return reply		}		//Create the table with given tableName		if g.filterDBTable(tableName, true) {			sysdb.DropTable(tableName)			reply, _ := vm.ToValue(true)			return reply		}		//Return true		reply, _ := vm.ToValue(false)		return reply	})	//writeDBItem(tablename, key, value) => return true when suceed	vm.Set("writeDBItem", func(call otto.FunctionCall) otto.Value {		tableName, err := call.Argument(0).ToString()		if err != nil {			g.raiseError(err)			reply, _ := vm.ToValue(false)			return reply		}		//Check if the tablename is reserved		if g.filterDBTable(tableName, true) {			keyString, err := call.Argument(1).ToString()			if err != nil {				g.raiseError(err)				reply, _ := vm.ToValue(false)				return reply			}			valueString, err := call.Argument(2).ToString()			if err != nil {				g.raiseError(err)				reply, _ := vm.ToValue(false)				return reply			}			sysdb.Write(tableName, keyString, valueString)			reply, _ := vm.ToValue(true)			return reply		}		reply, _ := vm.ToValue(false)		return reply	})	//readDBItem(tablename, key) => return value	vm.Set("readDBItem", func(call otto.FunctionCall) otto.Value {		tableName, _ := call.Argument(0).ToString()		keyString, _ := call.Argument(1).ToString()		returnValue := ""		reply, _ := vm.ToValue(nil)		if g.filterDBTable(tableName, true) {			sysdb.Read(tableName, keyString, &returnValue)			r, _ := vm.ToValue(returnValue)			reply = r		} else {			reply = otto.FalseValue()		}		return reply	})	//listDBTable(tablename) => Return key values array	vm.Set("listDBTable", func(call otto.FunctionCall) otto.Value {		tableName, _ := call.Argument(0).ToString()		returnValue := map[string]string{}		reply, _ := vm.ToValue(nil)		if g.filterDBTable(tableName, true) {			entries, _ := sysdb.ListTable(tableName)			for _, keypairs := range entries {				//Decode the string				result := ""				json.Unmarshal(keypairs[1], &result)				returnValue[string(keypairs[0])] = result			}			r, err := vm.ToValue(returnValue)			if err != nil {				return otto.NullValue()			}			return r		} else {			reply = otto.FalseValue()		}		return reply	})	//deleteDBItem(tablename, key) => Return true if success, false if failed	vm.Set("deleteDBItem", func(call otto.FunctionCall) otto.Value {		tableName, _ := call.Argument(0).ToString()		keyString, _ := call.Argument(1).ToString()		if g.filterDBTable(tableName, true) {			err := sysdb.Delete(tableName, keyString)			if err != nil {				return otto.FalseValue()			}		} else {			//Permission denied			return otto.FalseValue()		}		return otto.TrueValue()	})	//Module registry	vm.Set("registerModule", func(call otto.FunctionCall) otto.Value {		jsonModuleConfig, err := call.Argument(0).ToString()		if err != nil {			g.raiseError(err)			reply, _ := vm.ToValue(false)			return reply		}		//Try to decode it to a module Info		g.Option.ModuleRegisterParser(jsonModuleConfig)		if err != nil {			g.raiseError(err)			reply, _ := vm.ToValue(false)			return reply		}		return otto.Value{}	})	//Package Executation. Only usable when called to a given script File.	if scriptFile != "" && scriptScope != "" {		//Package request --> Install linux package if not exists		vm.Set("requirepkg", func(call otto.FunctionCall) otto.Value {			packageName, err := call.Argument(0).ToString()			if err != nil {				g.raiseError(err)				return otto.FalseValue()			}			requireComply, err := call.Argument(1).ToBoolean()			if err != nil {				g.raiseError(err)				return otto.FalseValue()			}			scriptRoot := getScriptRoot(scriptFile, scriptScope)			//Check if this module already get registered.			alreadyRegistered := false			for _, pkgRequest := range g.AllowAccessPkgs[strings.ToLower(packageName)] {				if pkgRequest.InitRoot == scriptRoot {					alreadyRegistered = true					break				}			}			if !alreadyRegistered {				//Register this packge to this script and allow the module to call this package				g.AllowAccessPkgs[strings.ToLower(packageName)] = append(g.AllowAccessPkgs[strings.ToLower(packageName)], AgiPackage{					InitRoot: scriptRoot,				})			}			//Try to install the package via apt			err = g.Option.PackageManager.InstallIfNotExists(packageName, requireComply)			if err != nil {				g.raiseError(err)				return otto.FalseValue()			}			return otto.TrueValue()		})		//Exec required pkg with permission control		vm.Set("execpkg", func(call otto.FunctionCall) otto.Value {			//Check if the pkg is already registered			scriptRoot := getScriptRoot(scriptFile, scriptScope)			packageName, err := call.Argument(0).ToString()			if err != nil {				g.raiseError(err)				return otto.FalseValue()			}			if val, ok := g.AllowAccessPkgs[packageName]; ok {				//Package already registered by at least one module. Check if this script root registered				thisModuleRegistered := false				for _, registeredPkgInterface := range val {					if registeredPkgInterface.InitRoot == scriptRoot {						//This package registered this command. Allow access						thisModuleRegistered = true					}				}				if !thisModuleRegistered {					g.raiseError(errors.New("Package request not registered: " + packageName))					return otto.FalseValue()				}			} else {				g.raiseError(errors.New("Package request not registered: " + packageName))				return otto.FalseValue()			}			//Ok. Allow paramter to be loaded			execParamters, _ := call.Argument(1).ToString()			// Split input paramters into []string			r := csv.NewReader(strings.NewReader(execParamters))			r.Comma = ' ' // space			fields, err := r.Read()			if err != nil {				g.raiseError(err)				return otto.FalseValue()			}			//Run os.Exec on the given commands			cmd := exec.Command(packageName, fields...)			out, err := cmd.CombinedOutput()			if err != nil {				log.Println(string(out))				g.raiseError(err)				return otto.FalseValue()			}			reply, _ := vm.ToValue(string(out))			return reply		})		//Include another js in runtime		vm.Set("includes", func(call otto.FunctionCall) otto.Value {			//Check if the pkg is already registered			scriptName, err := call.Argument(0).ToString()			if err != nil {				g.raiseError(err)				return otto.FalseValue()			}			//Check if it is calling itself			if filepath.Base(scriptFile) == filepath.Base(scriptName) {				g.raiseError(errors.New("*AGI* Self calling is not allowed"))				return otto.FalseValue()			}			//Check if the script file exists			targetScriptPath := filepath.ToSlash(filepath.Join(filepath.Dir(scriptFile), scriptName))			if !fileExists(targetScriptPath) {				g.raiseError(errors.New("*AGI* Target path not exists!"))				return otto.FalseValue()			}			//Run the script			scriptContent, _ := ioutil.ReadFile(targetScriptPath)			_, err = vm.Run(string(scriptContent))			if err != nil {				//Script execution failed				log.Println("Script Execution Failed: ", err.Error())				g.raiseError(err)				return otto.FalseValue()			}			return otto.TrueValue()		})	}	//Delay, sleep given ms	vm.Set("delay", func(call otto.FunctionCall) otto.Value {		delayTime, err := call.Argument(0).ToInteger()		if err != nil {			g.raiseError(err)			return otto.FalseValue()		}		time.Sleep(time.Duration(delayTime) * time.Millisecond)		return otto.TrueValue()	})}
 |