func headerVal(hdrs, hdr string) string {
	var hdrSIdx, hdrEIdx int
	if hdrSIdx = strings.Index(hdrs, hdr); hdrSIdx == -1 {
		return ""
	} else if hdrEIdx = strings.Index(hdrs[hdrSIdx:], "\n"); hdrEIdx == -1 {
		hdrEIdx = len(hdrs[hdrSIdx:])
	}
	splt := strings.SplitN(hdrs[hdrSIdx:hdrSIdx+hdrEIdx], ": ", 2)
	if len(splt) != 2 {
		return ""
	}
	return strings.TrimSpace(strings.TrimRight(splt[1], "\n"))
}
Extracts value of a header from anywhere in content string
package fsock
import (
	"crypto/rand"
	"encoding/json"
	"fmt"
	"io"
	"net/url"
	"regexp"
	"sort"
	"strings"
)
const EventBodyTag = "EvBody"
type logger interface {
	Alert(string) error
	Close() error
	Crit(string) error
	Debug(string) error
	Emerg(string) error
	Err(string) error
	Info(string) error
	Notice(string) error
	Warning(string) error
}
type nopLogger struct{}
func (nopLogger) Alert(string) error   { return nil }
func (nopLogger) Close() error         { return nil }
func (nopLogger) Crit(string) error    { return nil }
func (nopLogger) Debug(string) error   { return nil }
func (nopLogger) Emerg(string) error   { return nil }
func (nopLogger) Err(string) error     { return nil }
func (nopLogger) Info(string) error    { return nil }
func (nopLogger) Notice(string) error  { return nil }
func (nopLogger) Warning(string) error { return nil }
func FSEventStrToMap(fsevstr string, headers []string) map[string]string {
	fsevent := make(map[string]string)
	filtered := (len(headers) != 0)
	for _, strLn := range strings.Split(fsevstr, "\n") {
		if hdrVal := strings.SplitN(strLn, ": ", 2); len(hdrVal) == 2 {
			if filtered && isSliceMember(headers, hdrVal[0]) {
				continue  
			}
			fsevent[hdrVal[0]] = urlDecode(strings.TrimSpace(strings.TrimRight(hdrVal[1], "\n")))
		}
	}
	return fsevent
}
func MapChanData(chanInfoStr string) (chansInfoMap []map[string]string) {
	chansInfoMap = make([]map[string]string, 0)
	spltChanInfo := strings.Split(chanInfoStr, "\n")
	if len(spltChanInfo) <= 4 {
		return
	}
	hdrs := strings.Split(spltChanInfo[0], ",")
	for _, chanInfoLn := range spltChanInfo[1 : len(spltChanInfo)-3] {
		chanInfo := splitIgnoreGroups(chanInfoLn, ",")
		if len(hdrs) != len(chanInfo) {
			continue
		}
		chnMp := make(map[string]string)
		for iHdr, hdr := range hdrs {
			chnMp[hdr] = chanInfo[iHdr]
		}
		chansInfoMap = append(chansInfoMap, chnMp)
	}
	return
}
func EventToMap(event string) (result map[string]string) {
	result = make(map[string]string)
	body := false
	spltevent := strings.Split(event, "\n")
	for i := 0; i < len(spltevent); i++ {
		if len(spltevent[i]) == 0 {
			body = true
			continue
		}
		if body {
			result[EventBodyTag] = strings.Join(spltevent[i:], "\n")
			return
		}
		if val := strings.SplitN(spltevent[i], ": ", 2); len(val) == 2 {
			result[val[0]] = urlDecode(strings.TrimSpace(val[1]))
		}
	}
	return
}
func genUUID() string {
	b := make([]byte, 16)
	io.ReadFull(rand.Reader, b)
	b[6] = (b[6] & 0x0F) | 0x40
	b[8] = (b[8] &^ 0x40) | 0x80
	return fmt.Sprintf("%x-%x-%x-%x-%x", b[:4], b[4:6], b[6:8], b[8:10],
		b[10:])
}
func toJSON(v interface{}) string {
	b, _ := json.Marshal(v)
	return string(b)
}
func indexStringAll(origStr, srchd string) []int {
	foundIdxs := make([]int, 0)
	lenSearched := len(srchd)
	startIdx := 0
	for {
		idxFound := strings.Index(origStr[startIdx:], srchd)
		if idxFound == -1 {
			break
		}
		idxFound += startIdx
		foundIdxs = append(foundIdxs, idxFound)
		startIdx = idxFound + lenSearched  
	}
	return foundIdxs
}
func splitIgnoreGroups(origStr, sep string) []string {
	if len(origStr) == 0 {
		return []string{}
	} else if len(sep) == 0 {
		return []string{origStr}
	}
	retSplit := make([]string, 0)
	cmIdxs := indexStringAll(origStr, ",")  
	if len(cmIdxs) == 0 {
		return []string{origStr}
	}
	oCrlyIdxs := indexStringAll(origStr, "{")  
	cCrlyIdxs := indexStringAll(origStr, "}")  
	oBrktIdxs := indexStringAll(origStr, "[")  
	cBrktIdxs := indexStringAll(origStr, "]")  
	lastNonexcludedIdx := 0
	for i, cmdIdx := range cmIdxs {
		if len(oCrlyIdxs) == len(cCrlyIdxs) && len(oBrktIdxs) == len(cBrktIdxs) {  
			exceptFound := false
			for iCrlyIdx := range oCrlyIdxs {
				if oCrlyIdxs[iCrlyIdx] < cmdIdx && cCrlyIdxs[iCrlyIdx] > cmdIdx {  
					exceptFound = true
					break
				}
			}
			for oBrktIdx := range oBrktIdxs {
				if oBrktIdxs[oBrktIdx] < cmdIdx && cBrktIdxs[oBrktIdx] > cmdIdx {  
					exceptFound = true
					break
				}
			}
			if exceptFound {
				continue
			}
		}
		switch i {
		case 0:  
			retSplit = append(retSplit, origStr[:cmIdxs[i]])
		case len(cmIdxs) - 1:  
			postpendStr := ""
			if len(origStr) > cmIdxs[i]+1 {  
				postpendStr = origStr[cmIdxs[i]+1:]
			}
			retSplit = append(retSplit, origStr[cmIdxs[lastNonexcludedIdx]+1:cmIdxs[i]], postpendStr)
		default:
			retSplit = append(retSplit, origStr[cmIdxs[lastNonexcludedIdx]+1:cmIdxs[i]])  
		}
		lastNonexcludedIdx = i
	}
	groupedSplt := make([]string, 0)
	for idx, spltData := range retSplit {
		if idx == 0 {
			groupedSplt = append(groupedSplt, spltData)
			continue  
		}
		isGroup, _ := regexp.MatchString("{.*}|[.*]", spltData)
		if !isGroup {
			groupedSplt = append(groupedSplt, spltData)
			continue
		}
		isPrevGroup, _ := regexp.MatchString("{.*}|[.*]", retSplit[idx-1])
		if !isPrevGroup {
			groupedSplt = append(groupedSplt, spltData)
			continue
		}
		groupedSplt[len(groupedSplt)-1] = groupedSplt[len(groupedSplt)-1] + sep + spltData  
	}
	return groupedSplt
}