diff options
Diffstat (limited to 'vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/syslogparser.go')
-rw-r--r-- | vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/syslogparser.go | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/syslogparser.go b/vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/syslogparser.go new file mode 100644 index 000000000..7a10820c7 --- /dev/null +++ b/vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/syslogparser.go @@ -0,0 +1,213 @@ +package syslogparser + +import ( + "fmt" + "strconv" + "strings" + "time" +) + +const ( + PRI_PART_START = '<' + PRI_PART_END = '>' + + NO_VERSION = -1 +) + +var ( + ErrEOL = &ParserError{"End of log line"} + ErrNoSpace = &ParserError{"No space found"} + + ErrPriorityNoStart = &ParserError{"No start char found for priority"} + ErrPriorityEmpty = &ParserError{"Priority field empty"} + ErrPriorityNoEnd = &ParserError{"No end char found for priority"} + ErrPriorityTooShort = &ParserError{"Priority field too short"} + ErrPriorityTooLong = &ParserError{"Priority field too long"} + ErrPriorityNonDigit = &ParserError{"Non digit found in priority"} + + ErrVersionNotFound = &ParserError{"Can not find version"} + + ErrTimestampUnknownFormat = &ParserError{"Timestamp format unknown"} + + ErrHostnameTooShort = &ParserError{"Hostname field too short"} +) + +type LogParser interface { + Parse() error + Dump() LogParts + Location(*time.Location) +} + +type ParserError struct { + ErrorString string +} + +type Priority struct { + P int + F Facility + S Severity +} + +type Facility struct { + Value int +} + +type Severity struct { + Value int +} + +type LogParts map[string]interface{} + +// https://tools.ietf.org/html/rfc3164#section-4.1 +func ParsePriority(buff []byte, cursor *int, l int) (Priority, error) { + pri := newPriority(0) + + if l <= 0 { + return pri, ErrPriorityEmpty + } + + if buff[*cursor] != PRI_PART_START { + return pri, ErrPriorityNoStart + } + + i := 1 + priDigit := 0 + + for i < l { + if i >= 5 { + return pri, ErrPriorityTooLong + } + + c := buff[i] + + if c == PRI_PART_END { + if i == 1 { + return pri, ErrPriorityTooShort + } + + *cursor = i + 1 + return newPriority(priDigit), nil + } + + if IsDigit(c) { + v, e := strconv.Atoi(string(c)) + if e != nil { + return pri, e + } + + priDigit = (priDigit * 10) + v + } else { + return pri, ErrPriorityNonDigit + } + + i++ + } + + return pri, ErrPriorityNoEnd +} + +// https://tools.ietf.org/html/rfc5424#section-6.2.2 +func ParseVersion(buff []byte, cursor *int, l int) (int, error) { + if *cursor >= l { + return NO_VERSION, ErrVersionNotFound + } + + c := buff[*cursor] + *cursor++ + + // XXX : not a version, not an error though as RFC 3164 does not support it + if !IsDigit(c) { + return NO_VERSION, nil + } + + v, e := strconv.Atoi(string(c)) + if e != nil { + *cursor-- + return NO_VERSION, e + } + + return v, nil +} + +func IsDigit(c byte) bool { + return c >= '0' && c <= '9' +} + +func newPriority(p int) Priority { + // The Priority value is calculated by first multiplying the Facility + // number by 8 and then adding the numerical value of the Severity. + + return Priority{ + P: p, + F: Facility{Value: p / 8}, + S: Severity{Value: p % 8}, + } +} + +func FindNextSpace(buff []byte, from int, l int) (int, error) { + var to int + + for to = from; to < l; to++ { + if buff[to] == ' ' { + to++ + return to, nil + } + } + + return 0, ErrNoSpace +} + +func Parse2Digits(buff []byte, cursor *int, l int, min int, max int, e error) (int, error) { + digitLen := 2 + + if *cursor+digitLen > l { + return 0, ErrEOL + } + + sub := string(buff[*cursor : *cursor+digitLen]) + + *cursor += digitLen + + i, err := strconv.Atoi(sub) + if err != nil { + return 0, e + } + + if i >= min && i <= max { + return i, nil + } + + return 0, e +} + +func ParseHostname(buff []byte, cursor *int, l int) (string, error) { + from := *cursor + + if from >= l { + return "", ErrHostnameTooShort + } + + var to int + + for to = from; to < l; to++ { + if buff[to] == ' ' { + break + } + } + + hostname := buff[from:to] + + *cursor = to + + return string(hostname), nil +} + +func ShowCursorPos(buff []byte, cursor int) { + fmt.Println(string(buff)) + padding := strings.Repeat("-", cursor) + fmt.Println(padding + "↑\n") +} + +func (err *ParserError) Error() string { + return err.ErrorString +} |