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 | |
| 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')
| -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 +} | 
