package filter import ( "fmt" "sync" "github.com/ffuf/ffuf/v2/pkg/ffuf" ) // MatcherManager handles both filters and matchers. type MatcherManager struct { IsCalibrated bool Mutex sync.Mutex Matchers map[string]ffuf.FilterProvider Filters map[string]ffuf.FilterProvider PerDomainFilters map[string]*PerDomainFilter } type PerDomainFilter struct { IsCalibrated bool Filters map[string]ffuf.FilterProvider } func NewPerDomainFilter(globfilters map[string]ffuf.FilterProvider) *PerDomainFilter { return &PerDomainFilter{IsCalibrated: false, Filters: globfilters} } func (p *PerDomainFilter) SetCalibrated(value bool) { p.IsCalibrated = value } func NewMatcherManager() ffuf.MatcherManager { return &MatcherManager{ IsCalibrated: false, Matchers: make(map[string]ffuf.FilterProvider), Filters: make(map[string]ffuf.FilterProvider), PerDomainFilters: make(map[string]*PerDomainFilter), } } func (f *MatcherManager) SetCalibrated(value bool) { f.IsCalibrated = value } func (f *MatcherManager) SetCalibratedForHost(host string, value bool) { if f.PerDomainFilters[host] != nil { f.PerDomainFilters[host].IsCalibrated = value } else { newFilter := NewPerDomainFilter(f.Filters) newFilter.IsCalibrated = true f.PerDomainFilters[host] = newFilter } } func NewFilterByName(name string, value string) (ffuf.FilterProvider, error) { if name == "status" { return NewStatusFilter(value) } if name == "size" { return NewSizeFilter(value) } if name == "word" { return NewWordFilter(value) } if name == "line" { return NewLineFilter(value) } if name == "regexp" { return NewRegexpFilter(value) } if name == "time" { return NewTimeFilter(value) } return nil, fmt.Errorf("Could not create filter with name %s", name) } //AddFilter adds a new filter to MatcherManager func (f *MatcherManager) AddFilter(name string, option string, replace bool) error { f.Mutex.Lock() defer f.Mutex.Unlock() newf, err := NewFilterByName(name, option) if err == nil { // valid filter create or append if f.Filters[name] == nil || replace { f.Filters[name] = newf } else { newoption := f.Filters[name].Repr() + "," + option newerf, err := NewFilterByName(name, newoption) if err == nil { f.Filters[name] = newerf } } } return err } //AddPerDomainFilter adds a new filter to PerDomainFilter configuration func (f *MatcherManager) AddPerDomainFilter(domain string, name string, option string) error { f.Mutex.Lock() defer f.Mutex.Unlock() var pdFilters *PerDomainFilter if filter, ok := f.PerDomainFilters[domain]; ok { pdFilters = filter } else { pdFilters = NewPerDomainFilter(f.Filters) } newf, err := NewFilterByName(name, option) if err == nil { // valid filter create or append if pdFilters.Filters[name] == nil { pdFilters.Filters[name] = newf } else { newoption := pdFilters.Filters[name].Repr() + "," + option newerf, err := NewFilterByName(name, newoption) if err == nil { pdFilters.Filters[name] = newerf } } } f.PerDomainFilters[domain] = pdFilters return err } //RemoveFilter removes a filter of a given type func (f *MatcherManager) RemoveFilter(name string) { f.Mutex.Lock() defer f.Mutex.Unlock() delete(f.Filters, name) } //AddMatcher adds a new matcher to Config func (f *MatcherManager) AddMatcher(name string, option string) error { f.Mutex.Lock() defer f.Mutex.Unlock() newf, err := NewFilterByName(name, option) if err == nil { // valid filter create or append if f.Matchers[name] == nil { f.Matchers[name] = newf } else { newoption := f.Matchers[name].Repr() + "," + option newerf, err := NewFilterByName(name, newoption) if err == nil { f.Matchers[name] = newerf } } } return err } func (f *MatcherManager) GetFilters() map[string]ffuf.FilterProvider { return f.Filters } func (f *MatcherManager) GetMatchers() map[string]ffuf.FilterProvider { return f.Matchers } func (f *MatcherManager) FiltersForDomain(domain string) map[string]ffuf.FilterProvider { if f.PerDomainFilters[domain] == nil { return f.Filters } return f.PerDomainFilters[domain].Filters } func (f *MatcherManager) CalibratedForDomain(domain string) bool { if f.PerDomainFilters[domain] != nil { return f.PerDomainFilters[domain].IsCalibrated } return false } func (f *MatcherManager) Calibrated() bool { return f.IsCalibrated }