//go:build js // +build js package main import ( "encoding/json" "fmt" "net/http" "strings" "github.com/StackExchange/dnscontrol/v3/pkg/spflib" "github.com/gopherjs/jquery" ) type gResolver struct{} type gResp struct { Status int Answer []struct { Data string `json:"data"` } } func (g gResolver) GetSPF(fqdn string) (string, error) { resp, err := http.Get("https://dns.google.com/resolve?type=txt&name=" + fqdn) if err != nil { return "", err } defer resp.Body.Close() dec := json.NewDecoder(resp.Body) dat := &gResp{} if err = dec.Decode(dat); err != nil { return "", err } for _, a := range dat.Answer { val := strings.Trim(a.Data, "\"") if strings.HasPrefix(val, "v=spf1 ") { return val, nil } } return "", fmt.Errorf("No spf records found") } var jq = jquery.NewJQuery var parsed *spflib.SPFRecord var domain string var resolver = gResolver{} func main() { jq(func() { jq("#lookup_btn").On(jquery.CLICK, func(e jquery.Event) { go func() { domain = jq("#domain").Val() text, err := resolver.GetSPF(domain) fmt.Println(text) if err != nil { panic(err) } parsed, err = spflib.Parse(text, resolver) if err != nil { panic(err) } jq("#results").SetHtml(buildHTML(parsed, domain)) jq(".cb").On(jquery.CHANGE, func(e jquery.Event) { updateDisabledChecks() renderResults() }) updateDisabledChecks() renderResults() }() }) }) } func updateDisabledChecks() { jq("input:checkbox").Each(func(i int, el interface{}) { fmt.Println(jq(el).Prop("disabled")) jq(el).SetProp("disabled", false) }) jq("input:checkbox:not(:checked)").Each(func(i int, el interface{}) { fmt.Println(jq(el).Attr("id")) jq(el).Next().Next().Find("input:checkbox").Each(func(i int, el interface{}) { fmt.Println("^^", jq(el).Attr("id")) jq(el).SetProp("disabled", true) }) }) } func renderResults() { content := "" addFlattened := func(mode string, filter string) { flat := parsed.Flatten(filter) lookups := 0 if filter != "*" { lookups = parsed.Lookups() - len(strings.Split(filter, ",")) } content += fmt.Sprintf(`

%s flattened (length %d, %d lookups)

%s `, mode, len(flat.TXT()), lookups, flat.TXT()) split := flat.TXTSplit("_spf%d."+domain, 0, 255) if len(split) > 1 { lookups += len(split) - 1 content += fmt.Sprintf("

%s flattened split (%d lookups)

", mode, lookups) for k, v := range split { content += fmt.Sprintf("

%s

%s", k, v) } } } addFlattened("Fully", "*") // look for selected divs filters := []string{} jq("input:checked").Each(func(i int, el interface{}) { filters = append(filters, jq(el).Attr("id")) }) if len(filters) > 0 { addFlattened("Selectively", strings.Join(filters, ",")) } jq("#flattened").SetHtml(content) } func buildHTML(rec *spflib.SPFRecord, domain string) string { h := "

" + domain + "

" h += fmt.Sprintf("

%d lookups

", rec.Lookups()) return h + genRoot(rec) } // html based on https://codepen.io/khoama/pen/hpljA func genRoot(rec *spflib.SPFRecord) string { h := fmt.Sprintf(` " return h } func genPart(rec *spflib.SPFPart) string { if !rec.IsLookup { return fmt.Sprintf(`
  • %s
  • `, rec.Text) } h := fmt.Sprintf(`
  • `, rec.IncludeDomain, rec.IncludeDomain, rec.IncludeDomain, rec.Text, rec.IncludeRecord.Lookups()+1) h += fmt.Sprintf("" h += "
  • " return h }