// Tool to rewrite mod_security2 logs (very difficult to parse
// although they are in semi-structured format) to JSON.
//
package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"regexp"
)

var (
	outerRx = regexp.MustCompile(`\[[^\]]+]`)
	innerRx = regexp.MustCompile(`\[([^ ]+) \"?(.*)\"\]$`)
	needle  = []byte("ModSecurity: ")
)

func parseModSec(w io.Writer, line []byte) bool {
	if !bytes.Contains(line, needle) {
		return false
	}

	fields := make(map[string]interface{})
	var tags []string
	for _, inner := range outerRx.FindAll(line, -1) {
		for _, matches := range innerRx.FindAllSubmatch(inner, -1) {
			field := string(matches[1])
			value := string(matches[2])
			switch field {
			case "tag":
				tags = append(tags, value)
			case "client", "unique_id", "file", "line":
				// Suppress these tags.
			default:
				fields[field] = value
			}
		}
	}
	if len(fields) == 0 {
		return false
	}
	if len(tags) > 0 {
		fields["tag"] = tags
	}

	data, _ := json.Marshal(fields)
	fmt.Fprintf(w, "@cee:{\"modsec\":%s}\n", data)
	return true
}

func main() {
	outw := os.Stdout

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := scanner.Bytes()
		if !parseModSec(outw, line) {
			outw.Write(line)
			io.WriteString(outw, "\n")
		}
	}
}