diff --git a/FUNCTIONS.md b/FUNCTIONS.md index 689cb99..fe09c22 100644 --- a/FUNCTIONS.md +++ b/FUNCTIONS.md @@ -184,6 +184,24 @@ Change the permissions on a path. +## `CopyFile(srcPath, dstPath, perms)` + +Reads the contents of one file and copies it to another with the given permissions. + +### Argument List + + * **srcPath** *string* + * **dstPath** *string* + * **perms** *int64* + +### Returned Object Fields + + * **fileError** *error* + +--- + + + ## `CreateDir(path)` Creates a directory at a given path or return an error @@ -585,6 +603,25 @@ Uninstalls a system service +## `ReplaceFileString(file, match, replacement)` + +Searches a file for a string and replaces each instance found of that string. Returns the amount of strings replaced + +### Argument List + + * **file** *string* + * **match** *string* + * **replacement** *string* + +### Returned Object Fields + + * **stringsReplaced** *int* + * **fileError** *error* + +--- + + + ## `RunningProcs()` Returns an array of int's representing active PIDs currently running diff --git a/engine/lib_file.go b/engine/lib_file.go index f68de21..46079bc 100644 --- a/engine/lib_file.go +++ b/engine/lib_file.go @@ -1,8 +1,10 @@ package engine import ( + "io" "io/ioutil" "os" + "strings" ) // WriteFile - Writes data from a byte array to a file with the given permissions. @@ -53,6 +55,120 @@ func (e *Engine) WriteFile(path string, fileData []byte, perms int64) (int, erro return len(fileData), nil } +// ReplaceFileString - Searches a file for a string and replaces each instance found of that string. Returns the amount of strings replaced +// +// Package +// +// file +// +// Author +// +// - ahhh (https://github.com/ahhh) +// +// Javascript +// +// Here is the Javascript method signature: +// ReplaceFileString(file, match, replacement) +// +// Arguments +// +// Here is a list of the arguments for the Javascript function: +// * file (string) +// * match (string) +// * replacement (string) +// +// Returns +// +// Here is a list of fields in the return object: +// * obj.stringsReplaced (int) +// * obj.fileError (error) +// +// Example +// +// Here is an example of how to use this function in gscript: +// var obj = ReplaceFileString(file, match, replacement); +// // obj.stringsReplaced +// // obj.fileError +// +func (e *Engine) ReplaceFileString(file, match, replacement string) (int, error) { + fileInfo, err := os.Stat(file) + if os.IsNotExist(err) { + e.Logger.WithField("trace", "true").Errorf("File error: %s", err.Error()) + return 0, err + } + contents, err := ioutil.ReadFile(file) + if err != nil { + e.Logger.WithField("trace", "true").Errorf("File error: %s", err.Error()) + return 0, err + } + var count int = 0 + lines := strings.Split(string(contents), "\n") + for index, line := range lines { + if strings.Contains(line, match) { + lines[index] = strings.Replace(line, match, replacement, 10) + count++ + } + } + ioutil.WriteFile(file, []byte(strings.Join(lines, "\n")), fileInfo.Mode()) + return count, nil +} + +// CopyFile - Reads the contents of one file and copies it to another with the given permissions. +// +// Package +// +// file +// +// Author +// +// - ahhh (https://github.com/ahhh) +// +// Javascript +// +// Here is the Javascript method signature: +// CopyFile(srcPath, dstPath, perms) +// +// Arguments +// +// Here is a list of the arguments for the Javascript function: +// * srcPath (string) +// * dstPath (string) +// * perms (int64) +// +// Returns +// +// Here is a list of fields in the return object: +// * obj.fileError (error) +// +// Example +// +// Here is an example of how to use this function in gscript: +// var obj = CopyFile(srcPath, dstPath, perms); +// // obj.fileError +// +func (e *Engine) CopyFile(srcPath, destPath string, perms int64) error { + from, err := os.Open(srcPath) + if err != nil { + e.Logger.WithField("trace", "true").Errorf("File error: %s", err.Error()) + return err + } + defer from.Close() + + to, err := os.OpenFile(destPath, os.O_RDWR|os.O_CREATE, os.FileMode(uint32(perms))) + if err != nil { + e.Logger.WithField("trace", "true").Errorf("File error: %s", err.Error()) + return err + } + defer to.Close() + + _, err = io.Copy(to, from) + if err != nil { + e.Logger.WithField("trace", "true").Errorf("File error: %s", err.Error()) + return err + } + return nil +} + // AppendFileBytes - Addes a given byte array to the end of a file // // Package diff --git a/engine/vm_functions.go b/engine/vm_functions.go index d2b4908..dd3913f 100644 --- a/engine/vm_functions.go +++ b/engine/vm_functions.go @@ -28,10 +28,12 @@ // Functions in file: // AppendFileBytes(path, fileData) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.AppendFileBytes // AppendFileString(path, addString) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.AppendFileString +// CopyFile(srcPath, dstPath, perms) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.CopyFile // CreateDir(path) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.CreateDir // DeleteFile(path) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.DeleteFile // FileExists(path) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.FileExists // ReadFile(path) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.ReadFile +// ReplaceFileString(file, match, replacement) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.ReplaceFileString // WriteFile(path, fileData, perms) - https://godoc.org/github.com/gen0cide/gscript/engine/#Engine.WriteFile // // Library os @@ -86,6 +88,7 @@ func (e *Engine) CreateVM() { e.VM.Set("AppendFileString", e.vmAppendFileString) e.VM.Set("Asset", e.vmAsset) e.VM.Set("Chmod", e.vmChmod) + e.VM.Set("CopyFile", e.vmCopyFile) e.VM.Set("CreateDir", e.vmCreateDir) e.VM.Set("DelRegKey", e.vmDelRegKey) e.VM.Set("DelRegKeyValue", e.vmDelRegKeyValue) @@ -110,6 +113,7 @@ func (e *Engine) CreateVM() { e.VM.Set("RandomString", e.vmRandomString) e.VM.Set("ReadFile", e.vmReadFile) e.VM.Set("RemoveServiceByName", e.vmRemoveServiceByName) + e.VM.Set("ReplaceFileString", e.vmReplaceFileString) e.VM.Set("RunningProcs", e.vmRunningProcs) e.VM.Set("SelfPath", e.vmSelfPath) e.VM.Set("Signal", e.vmSignal) @@ -798,6 +802,74 @@ func (e *Engine) vmChmod(call otto.FunctionCall) otto.Value { return vmRet } +func (e *Engine) vmCopyFile(call otto.FunctionCall) otto.Value { + if len(call.ArgumentList) > 3 { + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Error("Too many arguments in call.") + return otto.FalseValue() + } + if len(call.ArgumentList) < 3 { + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Error("Too few arguments in call.") + return otto.FalseValue() + } + + var srcPath string + rawArg0, err := call.Argument(0).Export() + if err != nil { + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf("Could not export field: %s", "srcPath") + return otto.FalseValue() + } + switch v := rawArg0.(type) { + case string: + srcPath = rawArg0.(string) + default: + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf("Argument type mismatch: expected %s, got %T", "string", v) + return otto.FalseValue() + } + + var dstPath string + rawArg1, err := call.Argument(1).Export() + if err != nil { + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf("Could not export field: %s", "dstPath") + return otto.FalseValue() + } + switch v := rawArg1.(type) { + case string: + dstPath = rawArg1.(string) + default: + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf("Argument type mismatch: expected %s, got %T", "string", v) + return otto.FalseValue() + } + + var perms int64 + rawArg2, err := call.Argument(2).Export() + if err != nil { + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf("Could not export field: %s", "perms") + return otto.FalseValue() + } + switch v := rawArg2.(type) { + case int64: + perms = rawArg2.(int64) + default: + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf("Argument type mismatch: expected %s, got %T", "int64", v) + return otto.FalseValue() + } + fileError := e.CopyFile(srcPath, dstPath, perms) + rawVMRet := VMResponse{} + + if fileError != nil { + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf(" %s", fileError.Error()) + rawVMRet["fileError"] = fileError.Error() + } else { + rawVMRet["fileError"] = nil + } + vmRet, vmRetError := e.VM.ToValue(rawVMRet) + if vmRetError != nil { + e.Logger.WithField("function", "CopyFile").WithField("trace", "true").Errorf("Return conversion failed: %s", vmRetError.Error()) + return otto.FalseValue() + } + return vmRet +} + func (e *Engine) vmCreateDir(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) > 1 { e.Logger.WithField("function", "CreateDir").WithField("trace", "true").Error("Too many arguments in call.") @@ -1850,6 +1922,76 @@ func (e *Engine) vmRemoveServiceByName(call otto.FunctionCall) otto.Value { return vmRet } +func (e *Engine) vmReplaceFileString(call otto.FunctionCall) otto.Value { + if len(call.ArgumentList) > 3 { + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Error("Too many arguments in call.") + return otto.FalseValue() + } + if len(call.ArgumentList) < 3 { + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Error("Too few arguments in call.") + return otto.FalseValue() + } + + var file string + rawArg0, err := call.Argument(0).Export() + if err != nil { + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf("Could not export field: %s", "file") + return otto.FalseValue() + } + switch v := rawArg0.(type) { + case string: + file = rawArg0.(string) + default: + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf("Argument type mismatch: expected %s, got %T", "string", v) + return otto.FalseValue() + } + + var match string + rawArg1, err := call.Argument(1).Export() + if err != nil { + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf("Could not export field: %s", "match") + return otto.FalseValue() + } + switch v := rawArg1.(type) { + case string: + match = rawArg1.(string) + default: + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf("Argument type mismatch: expected %s, got %T", "string", v) + return otto.FalseValue() + } + + var replacement string + rawArg2, err := call.Argument(2).Export() + if err != nil { + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf("Could not export field: %s", "replacement") + return otto.FalseValue() + } + switch v := rawArg2.(type) { + case string: + replacement = rawArg2.(string) + default: + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf("Argument type mismatch: expected %s, got %T", "string", v) + return otto.FalseValue() + } + stringsReplaced, fileError := e.ReplaceFileString(file, match, replacement) + rawVMRet := VMResponse{} + + rawVMRet["stringsReplaced"] = stringsReplaced + + if fileError != nil { + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf(" %s", fileError.Error()) + rawVMRet["fileError"] = fileError.Error() + } else { + rawVMRet["fileError"] = nil + } + vmRet, vmRetError := e.VM.ToValue(rawVMRet) + if vmRetError != nil { + e.Logger.WithField("function", "ReplaceFileString").WithField("trace", "true").Errorf("Return conversion failed: %s", vmRetError.Error()) + return otto.FalseValue() + } + return vmRet +} + func (e *Engine) vmRunningProcs(call otto.FunctionCall) otto.Value { if len(call.ArgumentList) > 0 { e.Logger.WithField("function", "RunningProcs").WithField("trace", "true").Error("Too many arguments in call.") diff --git a/functions.yml b/functions.yml index 4d3eea8..1cfb0fa 100644 --- a/functions.yml +++ b/functions.yml @@ -185,6 +185,39 @@ - label: fileError gotype: error return: true +- name: CopyFile + description: Reads the contents of one file and copies it to another with the given permissions. + author: ahhh (https://github.com/ahhh) + package: file + args: + - label: srcPath + gotype: string + - label: dstPath + gotype: string + - label: perms + gotype: int64 + returns: + - label: fileError + gotype: error + return: true +- name: ReplaceFileString + description: Searches a file for a string and replaces each instance found of that string. Returns the amount of strings replaced + author: ahhh (https://github.com/ahhh) + package: file + args: + - label: file + gotype: string + - label: match + gotype: string + - label: replacement + gotype: string + returns: + - label: stringsReplaced + gotype: int + return: true + - label: fileError + gotype: error + return: true - name: AppendFileBytes description: Addes a given byte array to the end of a file author: ahhh (https://github.com/ahhh)