Path: blob/dev/pkg/operators/matchers/compile.go
2070 views
package matchers12import (3"encoding/hex"4"fmt"5"regexp"6"strings"78"github.com/Knetic/govaluate"910"github.com/projectdiscovery/nuclei/v3/pkg/operators/common/dsl"11)1213// CompileMatchers performs the initial setup operation on a matcher14func (matcher *Matcher) CompileMatchers() error {15var ok bool1617// Support hexadecimal encoding for matchers too.18if matcher.Encoding == "hex" {19for i, word := range matcher.Words {20if decoded, err := hex.DecodeString(word); err == nil && len(decoded) > 0 {21matcher.Words[i] = string(decoded)22}23}24}2526// Set up the matcher type27computedType, err := toMatcherTypes(matcher.GetType().String())28if err != nil {29return fmt.Errorf("unknown matcher type specified: %s", matcher.Type)30}3132matcher.matcherType = computedType3334// Validate the matcher structure35if err := matcher.Validate(); err != nil {36return err37}3839// By default, match on body if user hasn't provided any specific items40if matcher.Part == "" && matcher.GetType() != DSLMatcher {41matcher.Part = "body"42}4344// Compile the regexes45for _, regex := range matcher.Regex {46compiled, err := regexp.Compile(regex)47if err != nil {48return fmt.Errorf("could not compile regex: %s", regex)49}50matcher.regexCompiled = append(matcher.regexCompiled, compiled)51}5253// Compile and validate binary Values in matcher54for _, value := range matcher.Binary {55if decoded, err := hex.DecodeString(value); err != nil {56return fmt.Errorf("could not hex decode binary: %s", value)57} else {58matcher.binaryDecoded = append(matcher.binaryDecoded, string(decoded))59}60}6162// Compile the dsl expressions63for _, dslExpression := range matcher.DSL {64compiledExpression, err := govaluate.NewEvaluableExpressionWithFunctions(dslExpression, dsl.HelperFunctions)65if err != nil {66return &dsl.CompilationError{DslSignature: dslExpression, WrappedError: err}67}68matcher.dslCompiled = append(matcher.dslCompiled, compiledExpression)69}7071// Set up the condition type, if any.72if matcher.Condition != "" {73matcher.condition, ok = ConditionTypes[matcher.Condition]74if !ok {75return fmt.Errorf("unknown condition specified: %s", matcher.Condition)76}77} else {78matcher.condition = ORCondition79}8081if matcher.CaseInsensitive {82if matcher.GetType() != WordsMatcher {83return fmt.Errorf("case-insensitive flag is supported only for 'word' matchers (not '%s')", matcher.Type)84}85for i := range matcher.Words {86matcher.Words[i] = strings.ToLower(matcher.Words[i])87}88}89return nil90}9192// GetType returns the condition type of the matcher93// todo: the field should be exposed natively94func (matcher *Matcher) GetCondition() ConditionType {95return matcher.condition96}979899