diff options
author | 2021-12-12 18:00:20 +0100 | |
---|---|---|
committer | 2021-12-12 18:00:20 +0100 | |
commit | c111b239f7d102ac24a79fbef420af46dfec66f9 (patch) | |
tree | 813f5c4501a6e5048fb2922e099ce92d35b33b14 /vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164/rfc3164.go | |
parent | add systemd service example to packaging (#342) (diff) | |
download | gotosocial-c111b239f7d102ac24a79fbef420af46dfec66f9.tar.xz |
Add optional syslog logrus hook (#343)
* add optional syslog logrus hook
* document syslog
Diffstat (limited to 'vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164/rfc3164.go')
-rw-r--r-- | vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164/rfc3164.go | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164/rfc3164.go b/vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164/rfc3164.go new file mode 100644 index 000000000..486a0cb54 --- /dev/null +++ b/vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164/rfc3164.go @@ -0,0 +1,292 @@ +package rfc3164 + +import ( + "bytes" + "os" + "time" + + "gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser" +) + +type Parser struct { + buff []byte + cursor int + l int + priority syslogparser.Priority + version int + header header + message rfc3164message + location *time.Location + skipTag bool +} + +type header struct { + timestamp time.Time + hostname string +} + +type rfc3164message struct { + tag string + content string +} + +func NewParser(buff []byte) *Parser { + return &Parser{ + buff: buff, + cursor: 0, + l: len(buff), + location: time.UTC, + } +} + +func (p *Parser) Location(location *time.Location) { + p.location = location +} + +func (p *Parser) Parse() error { + tcursor := p.cursor + pri, err := p.parsePriority() + if err != nil { + // RFC3164 sec 4.3.3 + p.priority = syslogparser.Priority{13, syslogparser.Facility{Value: 1}, syslogparser.Severity{Value: 5}} + p.cursor = tcursor + content, err := p.parseContent() + p.header.timestamp = time.Now().Round(time.Second) + if err != syslogparser.ErrEOL { + return err + } + p.message = rfc3164message{content: content} + return nil + } + + tcursor = p.cursor + hdr, err := p.parseHeader() + if err == syslogparser.ErrTimestampUnknownFormat { + // RFC3164 sec 4.3.2. + hdr.timestamp = time.Now().Round(time.Second) + // No tag processing should be done + p.skipTag = true + // Reset cursor for content read + p.cursor = tcursor + } else if err != nil { + return err + } else { + p.cursor++ + } + + msg, err := p.parsemessage() + if err != syslogparser.ErrEOL { + return err + } + + p.priority = pri + p.version = syslogparser.NO_VERSION + p.header = hdr + p.message = msg + + return nil +} + +func (p *Parser) Dump() syslogparser.LogParts { + return syslogparser.LogParts{ + "timestamp": p.header.timestamp, + "hostname": p.header.hostname, + "tag": p.message.tag, + "content": p.message.content, + "priority": p.priority.P, + "facility": p.priority.F.Value, + "severity": p.priority.S.Value, + } +} + +func (p *Parser) parsePriority() (syslogparser.Priority, error) { + return syslogparser.ParsePriority(p.buff, &p.cursor, p.l) +} + +func (p *Parser) parseHeader() (header, error) { + hdr := header{} + var err error + + ts, err := p.parseTimestamp() + if err != nil { + return hdr, err + } + + hostname, err := p.parseHostname() + if err != nil { + return hdr, err + } + + hdr.timestamp = ts + hdr.hostname = hostname + + return hdr, nil +} + +func (p *Parser) parsemessage() (rfc3164message, error) { + msg := rfc3164message{} + var err error + + if !p.skipTag { + tag, err := p.parseTag() + if err != nil { + return msg, err + } + msg.tag = tag + } + + content, err := p.parseContent() + if err != syslogparser.ErrEOL { + return msg, err + } + + msg.content = content + + return msg, err +} + +// https://tools.ietf.org/html/rfc3164#section-4.1.2 +func (p *Parser) parseTimestamp() (time.Time, error) { + var ts time.Time + var err error + var tsFmtLen int + var sub []byte + + tsFmts := []string{ + time.Stamp, + time.RFC3339, + } + // if timestamps starts with numeric try formats with different order + // it is more likely that timestamp is in RFC3339 format then + if c := p.buff[p.cursor]; c > '0' && c < '9' { + tsFmts = []string{ + time.RFC3339, + time.Stamp, + } + } + + found := false + for _, tsFmt := range tsFmts { + tsFmtLen = len(tsFmt) + + if p.cursor+tsFmtLen > p.l { + continue + } + + sub = p.buff[p.cursor : tsFmtLen+p.cursor] + ts, err = time.ParseInLocation(tsFmt, string(sub), p.location) + if err == nil { + found = true + break + } + } + + if !found { + p.cursor = len(time.Stamp) + + // XXX : If the timestamp is invalid we try to push the cursor one byte + // XXX : further, in case it is a space + if (p.cursor < p.l) && (p.buff[p.cursor] == ' ') { + p.cursor++ + } + + return ts, syslogparser.ErrTimestampUnknownFormat + } + + fixTimestampIfNeeded(&ts) + + p.cursor += tsFmtLen + + if (p.cursor < p.l) && (p.buff[p.cursor] == ' ') { + p.cursor++ + } + + return ts, nil +} + +func (p *Parser) parseHostname() (string, error) { + oldcursor := p.cursor + hostname, err := syslogparser.ParseHostname(p.buff, &p.cursor, p.l) + if err == nil && len(hostname) > 0 && string(hostname[len(hostname)-1]) == ":" { // not an hostname! we found a GNU implementation of syslog() + p.cursor = oldcursor - 1 + myhostname, err := os.Hostname() + if err == nil { + return myhostname, nil + } + return "", nil + } + return hostname, err +} + +// http://tools.ietf.org/html/rfc3164#section-4.1.3 +func (p *Parser) parseTag() (string, error) { + var b byte + var endOfTag bool + var bracketOpen bool + var tag []byte + var err error + var found bool + + from := p.cursor + + for { + if p.cursor == p.l { + // no tag found, reset cursor for content + p.cursor = from + return "", nil + } + + b = p.buff[p.cursor] + bracketOpen = (b == '[') + endOfTag = (b == ':' || b == ' ') + + // XXX : parse PID ? + if bracketOpen { + tag = p.buff[from:p.cursor] + found = true + } + + if endOfTag { + if !found { + tag = p.buff[from:p.cursor] + found = true + } + + p.cursor++ + break + } + + p.cursor++ + } + + if (p.cursor < p.l) && (p.buff[p.cursor] == ' ') { + p.cursor++ + } + + return string(tag), err +} + +func (p *Parser) parseContent() (string, error) { + if p.cursor > p.l { + return "", syslogparser.ErrEOL + } + + content := bytes.Trim(p.buff[p.cursor:p.l], " ") + p.cursor += len(content) + + return string(content), syslogparser.ErrEOL +} + +func fixTimestampIfNeeded(ts *time.Time) { + now := time.Now() + y := ts.Year() + + if ts.Year() == 0 { + y = now.Year() + } + + newTs := time.Date(y, ts.Month(), ts.Day(), ts.Hour(), ts.Minute(), + ts.Second(), ts.Nanosecond(), ts.Location()) + + *ts = newTs +} |