mirror of
https://github.com/bettercap/bettercap
synced 2025-07-05 20:42:09 -07:00
new: added removeEventListener builtin function (closes #1139)
This commit is contained in:
parent
a7e4572416
commit
169b0cb8c9
2 changed files with 85 additions and 26 deletions
|
@ -2,8 +2,10 @@ package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/v2/js"
|
"github.com/bettercap/bettercap/v2/js"
|
||||||
"github.com/evilsocket/islazy/fs"
|
"github.com/evilsocket/islazy/fs"
|
||||||
|
@ -14,6 +16,8 @@ import (
|
||||||
// see https://github.com/robertkrimen/otto/issues/213
|
// see https://github.com/robertkrimen/otto/issues/213
|
||||||
var jsRuntime = otto.New()
|
var jsRuntime = otto.New()
|
||||||
|
|
||||||
|
var jsListeners = sync.Map{}
|
||||||
|
|
||||||
func jsRunFunc(call otto.FunctionCall) otto.Value {
|
func jsRunFunc(call otto.FunctionCall) otto.Value {
|
||||||
argv := call.ArgumentList
|
argv := call.ArgumentList
|
||||||
argc := len(argv)
|
argc := len(argv)
|
||||||
|
@ -57,40 +61,94 @@ func jsOnEventFunc(call otto.FunctionCall) otto.Value {
|
||||||
cb = argv[1]
|
cb = argv[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listenerKey := fmt.Sprintf("%s:%s", filterExpr, cb.String())
|
||||||
|
|
||||||
|
if _, found := jsListeners.Load(listenerKey); found {
|
||||||
|
return js.ReportError("listener already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to listeners
|
||||||
|
closeChan := make(chan bool)
|
||||||
|
jsListeners.Store(listenerKey, closeChan)
|
||||||
|
|
||||||
// start a go routine for this event listener
|
// start a go routine for this event listener
|
||||||
go func(expr string, cb otto.Value) {
|
go func(expr string, cb otto.Value, closeChan chan bool) {
|
||||||
listener := I.Events.Listen()
|
listener := I.Events.Listen()
|
||||||
defer I.Events.Unlisten(listener)
|
defer I.Events.Unlisten(listener)
|
||||||
|
defer close(closeChan)
|
||||||
|
|
||||||
for event := range listener {
|
for {
|
||||||
if expr == "" || event.Tag == expr {
|
select {
|
||||||
// some objects don't do well with js, so convert them to a generic map
|
case event := <-listener:
|
||||||
// before passing them to the callback
|
if expr == "" || event.Tag == expr {
|
||||||
var opaque interface{}
|
// some objects don't do well with js, so convert them to a generic map
|
||||||
if raw, err := json.Marshal(event); err != nil {
|
// before passing them to the callback
|
||||||
I.Events.Log(log.ERROR, "error serializing event %s: %v", event.Tag, err)
|
var opaque interface{}
|
||||||
} else if err = json.Unmarshal(raw, &opaque); err != nil {
|
if raw, err := json.Marshal(event); err != nil {
|
||||||
I.Events.Log(log.ERROR, "error serializing event %s: %v", event.Tag, err)
|
I.Events.Log(log.ERROR, "error serializing event %s: %v", event.Tag, err)
|
||||||
|
} else if err = json.Unmarshal(raw, &opaque); err != nil {
|
||||||
|
I.Events.Log(log.ERROR, "error serializing event %s: %v", event.Tag, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// lock vm if ready and available
|
||||||
|
locked := false
|
||||||
|
if I.script != nil {
|
||||||
|
I.script.Lock()
|
||||||
|
locked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := cb.Call(otto.NullValue(), opaque); err != nil {
|
||||||
|
I.Events.Log(log.ERROR, "error dispatching event %s: %v", event.Tag, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlock vm if ready and available
|
||||||
|
if locked {
|
||||||
|
I.script.Unlock()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock vm if ready and available
|
case <-closeChan:
|
||||||
locked := false
|
return
|
||||||
if I.script != nil {
|
|
||||||
I.script.Lock()
|
|
||||||
locked = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := cb.Call(otto.NullValue(), opaque); err != nil {
|
|
||||||
I.Events.Log(log.ERROR, "error dispatching event %s: %v", event.Tag, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// unlock vm if ready and available
|
|
||||||
if locked {
|
|
||||||
I.script.Unlock()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}(filterExpr, cb)
|
}(filterExpr, cb, closeChan)
|
||||||
|
|
||||||
|
return js.NullValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsRemoveEventListenerFunc(call otto.FunctionCall) otto.Value {
|
||||||
|
argv := call.ArgumentList
|
||||||
|
argc := len(argv)
|
||||||
|
cb := otto.NullValue()
|
||||||
|
filterExpr := ""
|
||||||
|
|
||||||
|
// just one argument, a function to receive all events
|
||||||
|
if argc == 1 {
|
||||||
|
if argv[0].IsFunction() == false {
|
||||||
|
return js.ReportError("the single argument must be a function")
|
||||||
|
}
|
||||||
|
cb = argv[0]
|
||||||
|
} else {
|
||||||
|
if argc != 2 {
|
||||||
|
return js.ReportError("expected two arguments (event_name, callback), got %d", argc)
|
||||||
|
} else if argv[0].IsString() == false {
|
||||||
|
return js.ReportError("first argument must be a string")
|
||||||
|
} else if argv[1].IsFunction() == false {
|
||||||
|
return js.ReportError("second argument must be a function")
|
||||||
|
}
|
||||||
|
|
||||||
|
filterExpr = argv[0].String()
|
||||||
|
cb = argv[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
listenerKey := fmt.Sprintf("%s:%s", filterExpr, cb.String())
|
||||||
|
if closer, found := jsListeners.Load(listenerKey); found {
|
||||||
|
closer.(chan bool) <- true
|
||||||
|
jsListeners.Delete(listenerKey)
|
||||||
|
} else {
|
||||||
|
return js.ReportError("listener not found")
|
||||||
|
}
|
||||||
|
|
||||||
return js.NullValue
|
return js.NullValue
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,6 +330,7 @@ func (s *Session) Start() error {
|
||||||
plugin.Defines["saveJSON"] = jsSaveJSONFunc
|
plugin.Defines["saveJSON"] = jsSaveJSONFunc
|
||||||
plugin.Defines["saveToFile"] = jsSaveToFileFunc
|
plugin.Defines["saveToFile"] = jsSaveToFileFunc
|
||||||
plugin.Defines["onEvent"] = jsOnEventFunc
|
plugin.Defines["onEvent"] = jsOnEventFunc
|
||||||
|
plugin.Defines["removeEventListener"] = jsRemoveEventListenerFunc
|
||||||
plugin.Defines["session"] = s
|
plugin.Defines["session"] = s
|
||||||
|
|
||||||
// load the script here so the session and its internal objects are ready
|
// load the script here so the session and its internal objects are ready
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue