161 lines
4.3 KiB
Go
161 lines
4.3 KiB
Go
package interceptor
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"path/filepath"
|
||
|
||
"github.com/mattn/anko/env"
|
||
"github.com/mattn/anko/vm"
|
||
)
|
||
|
||
type Ankointerceptor struct {
|
||
importMap map[string]interface{}
|
||
libMap map[string]interface{}
|
||
libhabdles []uintptr
|
||
ankoEnv *env.Env
|
||
}
|
||
|
||
func NewAnkointerceptor(ankoEnv *env.Env) *Ankointerceptor {
|
||
if ankoEnv == nil {
|
||
ankoEnv = env.NewEnv()
|
||
}
|
||
a := &Ankointerceptor{
|
||
importMap: make(map[string]interface{}),
|
||
libMap: make(map[string]interface{}),
|
||
libhabdles: make([]uintptr, 0),
|
||
ankoEnv: ankoEnv,
|
||
}
|
||
a.ankoEnv.Define("println", fmt.Println)
|
||
a.ankoEnv.Define("loadLibrary", func(libPath string, libFuncMap map[string]funcType) interface{} {
|
||
return a.loadLibrary(libPath, libFuncMap)
|
||
})
|
||
a.importMap["fs"] = &FileModule{}
|
||
a.importMap["net"] = &NetModule{}
|
||
a.importMap["process"] = &ProcessModule{}
|
||
a.importMap["shell"] = &ShellModule{}
|
||
return a
|
||
}
|
||
|
||
// Exec executes the specified script within the Anko environment.
|
||
// It sets up the environment with necessary variables and methods,
|
||
// reads the script file, and executes it, returning the result or an error.
|
||
//
|
||
// Parameters:
|
||
// - script: Path to the script file to be executed.
|
||
//
|
||
// Returns:
|
||
// - interface{}: The result of the script execution.
|
||
// - error: An error if the script file cannot be read or execution fails.
|
||
func (a *Ankointerceptor) Exec(script string) (interface{}, error) {
|
||
st, err := os.Stat(script)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if st.IsDir() {
|
||
toExec := filepath.Join(script, "index.ank")
|
||
return a.exec(toExec, script)
|
||
}
|
||
if !filepath.IsAbs(script) {
|
||
script = filepath.Join(os.Getenv("PWD"), script)
|
||
}
|
||
content, err := os.ReadFile(script)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
scriptContent := string(content)
|
||
result, err := a.exec(scriptContent, script)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
// ExecContent executes the specified script content within the Anko environment.
|
||
// It sets up the environment with necessary variables and methods,
|
||
// executes the script content, and returns the result or an error.
|
||
//
|
||
// Parameters:
|
||
// - scriptContent: The script content to be executed.
|
||
//
|
||
// Returns:
|
||
// - interface{}: The result of the script execution.
|
||
// - error: An error if the script execution fails.
|
||
func (a *Ankointerceptor) ExecContent(scriptContent string) (interface{}, error) {
|
||
result, err := a.exec(scriptContent, "")
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func (a *Ankointerceptor) exec(scriptContent string, scriptPath string) (interface{}, error) {
|
||
e := a.ankoEnv.Copy()
|
||
// Configure the Anko environment with required variables and methods
|
||
if scriptPath == "" {
|
||
cdir, _ := os.Getwd()
|
||
scriptPath = filepath.Join(cdir, "tmp")
|
||
}
|
||
e.Define("Require", a.genRequireMethod(scriptPath))
|
||
e.Define("__filename", scriptPath)
|
||
e.Define("__dirname", filepath.Dir(scriptPath))
|
||
|
||
// Execute the script code in the prepared environment
|
||
result, err := vm.Execute(e, nil, scriptContent)
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
return nil, err
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
// genRequireMethod 创建模块解析闭包函数
|
||
// 该函数用于处理模块路径解析和缓存机制:
|
||
// 1. 优先从importMap缓存中查找已加载模块
|
||
// 2. 对相对路径自动转换为基于basePath的绝对路径
|
||
// 3. 执行模块加载后自动缓存结果
|
||
// 参数:
|
||
//
|
||
// basePath - 模块基础路径,用于解析相对路径
|
||
//
|
||
// 返回:
|
||
//
|
||
// 闭包函数,接收模块路径s,返回解析后的模块对象
|
||
func (a *Ankointerceptor) genRequireMethod(basePath string) interface{} {
|
||
return func(s string) interface{} {
|
||
if r, ok := a.importMap[s]; ok {
|
||
return r
|
||
}
|
||
// 将相对路径转换为基于basePath的绝对路径
|
||
if !filepath.IsAbs(s) {
|
||
s = filepath.Join(filepath.Dir(basePath), s)
|
||
}
|
||
if _, ok := a.importMap[s]; ok {
|
||
return a.importMap[s]
|
||
}
|
||
// 执行模块加载并将结果缓存
|
||
result, err := a.Exec(s)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
a.importMap[s] = result
|
||
return result
|
||
}
|
||
}
|
||
|
||
func (a *Ankointerceptor) RegistModule(name string, m map[string]interface{}) {
|
||
_, ok := a.importMap[name]
|
||
if ok {
|
||
panic("Module already exists")
|
||
}
|
||
a.importMap[name] = m
|
||
}
|
||
|
||
func (a *Ankointerceptor) RegistStructAsModule(name string, s interface{}) {
|
||
_, ok := a.importMap[name]
|
||
if ok {
|
||
panic("Module already exists")
|
||
}
|
||
a.importMap[name] = s
|
||
}
|