mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 21:02:24 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			213 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
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
 | 
						|
}
 |