/
parser.go
80 lines (65 loc) · 1.52 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package core
import (
"fmt"
"regexp"
"strings"
"time"
"github.com/evilsocket/islazy/log"
)
type Tokens map[string]string
var mandatoryTokens = []string{
"address",
"datetime",
}
var (
currYear = time.Now().Year()
)
type Parser struct {
DatetimeFormat string `yaml:"datetime_format"`
Expression string `yaml:"expression"`
Tokens map[string]int `yaml:"tokens"`
compiled *regexp.Regexp
maxIndex int
}
func (p *Parser) Compile() (err error) {
for _, t := range mandatoryTokens {
if _, found := p.Tokens[t]; !found {
return fmt.Errorf("mandatory token %s not found in parser", t)
}
}
for _, index := range p.Tokens {
if index > p.maxIndex {
p.maxIndex = index
}
}
expr := p.Expression
if !strings.HasPrefix(expr, "(?i)") {
expr = "(?i)" + expr
}
log.Debug("compiling parser '%s'", expr)
p.compiled, err = regexp.Compile(expr)
return
}
func hasYear(value string) bool {
for year := currYear - 5; year <= currYear; year++ {
if strings.Contains(value, fmt.Sprintf("%d", year)) {
return true
}
}
return false
}
func (p *Parser) Parse(line string) (matched bool, tokens Tokens) {
if m := p.compiled.FindStringSubmatch(line); len(m) >= p.maxIndex {
matched = true
tokens = make(map[string]string)
for token, index := range p.Tokens {
value := m[index]
// ugly hack to handle formats withtout the year like sshd
if token == "datetime" && !hasYear(value) {
value = fmt.Sprintf("%d %s", currYear, value)
}
tokens[token] = value
}
}
return
}