package contextargs import ( "net/http/cookiejar" "sync/atomic" "github.com/projectdiscovery/gologger" mapsutil "github.com/projectdiscovery/utils/maps" ) // Context implements a shared context struct to share information across multiple templates within a workflow type Context struct { // Meta is the target for the executor MetaInput *MetaInput // CookieJar shared within workflow's http templates CookieJar *cookiejar.Jar // Args is a workflow shared key-value store args *mapsutil.SyncLockMap[string, interface{}] } // Create a new contextargs instance func New() *Context { return NewWithInput("") } // Create a new contextargs instance with input string func NewWithInput(input string) *Context { jar, err := cookiejar.New(nil) if err != nil { gologger.Error().Msgf("contextargs: could not create cookie jar: %s\n", err) } return &Context{ MetaInput: &MetaInput{Input: input}, CookieJar: jar, args: &mapsutil.SyncLockMap[string, interface{}]{ Map: make(map[string]interface{}), ReadOnly: atomic.Bool{}, }, } } // Set the specific key-value pair func (ctx *Context) Set(key string, value interface{}) { _ = ctx.args.Set(key, value) } func (ctx *Context) hasArgs() bool { return !ctx.args.IsEmpty() } // Get the value with specific key if exists func (ctx *Context) Get(key string) (interface{}, bool) { if !ctx.hasArgs() { return nil, false } return ctx.args.Get(key) } func (ctx *Context) GetAll() map[string]interface{} { if !ctx.hasArgs() { return nil } return ctx.args.Clone().Map } func (ctx *Context) ForEach(f func(string, interface{})) { _ = ctx.args.Iterate(func(k string, v interface{}) error { f(k, v) return nil }) } // Has check if the key exists func (ctx *Context) Has(key string) bool { return ctx.hasArgs() && ctx.args.Has(key) } func (ctx *Context) HasArgs() bool { return !ctx.args.IsEmpty() } func (ctx *Context) Clone() *Context { newCtx := &Context{ MetaInput: ctx.MetaInput.Clone(), args: ctx.args, CookieJar: ctx.CookieJar, } return newCtx }