ffuff/pkg/filter/filter.go
2023-02-06 11:20:28 +02:00

176 lines
4.3 KiB
Go

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
}