mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-04 03:32:25 -06:00 
			
		
		
		
	
		
			
	
	
		
			214 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			214 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
							 | 
						||
| 
								 | 
							
								}
							 |