summaryrefslogtreecommitdiff
path: root/vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2021-12-12 18:00:20 +0100
committerLibravatar GitHub <noreply@github.com>2021-12-12 18:00:20 +0100
commitc111b239f7d102ac24a79fbef420af46dfec66f9 (patch)
tree813f5c4501a6e5048fb2922e099ce92d35b33b14 /vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164
parentadd systemd service example to packaging (#342) (diff)
downloadgotosocial-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')
-rw-r--r--vendor/gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164/rfc3164.go292
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
+}