dnscontrol/docs/flattener/js.go
2020-04-14 16:49:03 -04:00

158 lines
3.6 KiB
Go

// +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(`
<h3> %s flattened (length %d, %d lookups)</h3><code>%s</code>
`, mode, len(flat.TXT()), lookups, flat.TXT())
split := flat.TXTSplit("_spf%d." + domain)
if len(split) > 1 {
lookups += len(split) - 1
content += fmt.Sprintf("<h3>%s flattened split (%d lookups)</h3>", mode, lookups)
for k, v := range split {
content += fmt.Sprintf("<h4>%s</h4><code>%s</code>", 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 := "<h1>" + domain + "</h1>"
h += fmt.Sprintf("<h2>%d lookups</h2>", rec.Lookups())
return h + genRoot(rec)
}
// html based on https://codepen.io/khoama/pen/hpljA
func genRoot(rec *spflib.SPFRecord) string {
h := fmt.Sprintf(`
<ul>
<li class='root'>%s</li>
`, rec.TXT())
for _, p := range rec.Parts {
h += genPart(p)
}
h += "</ul>"
return h
}
func genPart(rec *spflib.SPFPart) string {
if !rec.IsLookup {
return fmt.Sprintf(`<li>%s</li>`, rec.Text)
}
h := fmt.Sprintf(`<li>
<input type="checkbox" class='cb' id="%s" name="%s" />
<label for="%s">%s(%d lookups)</label>`, rec.IncludeDomain, rec.IncludeDomain, rec.IncludeDomain, rec.Text, rec.IncludeRecord.Lookups()+1)
h += fmt.Sprintf("<ul>")
for _, p := range rec.IncludeRecord.Parts {
h += genPart(p)
}
h += "</ul>"
h += "</li>"
return h
}