From 76791cefc7ab80a770e3ff45e3395130a7bde499 Mon Sep 17 00:00:00 2001 From: Thomas Limoncelli Date: Tue, 25 Nov 2025 17:54:44 -0500 Subject: [PATCH] wip! --- pkg/domaintags/idn.go | 29 +++++++++++++ pkg/rtypecontrol/import.go | 89 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 pkg/domaintags/idn.go create mode 100644 pkg/rtypecontrol/import.go diff --git a/pkg/domaintags/idn.go b/pkg/domaintags/idn.go new file mode 100644 index 000000000..28cbcfde5 --- /dev/null +++ b/pkg/domaintags/idn.go @@ -0,0 +1,29 @@ +package domaintags + +import "golang.org/x/net/idna" + +func EfficientToASCII(name string) string { + nameIDN, err := idna.ToASCII(name) + if err != nil { + return name // Fallback to raw name on error. + } else { + // Avoid pointless duplication. + if nameIDN == name { + return name + } + } + return nameIDN +} + +func EfficientToUnicode(name string) string { + nameUnicode, err := idna.ToUnicode(name) + if err != nil { + return name // Fallback to raw name on error. + } else { + // Avoid pointless duplication. + if nameUnicode == name { + return name + } + } + return nameUnicode +} diff --git a/pkg/rtypecontrol/import.go b/pkg/rtypecontrol/import.go new file mode 100644 index 000000000..65efd3688 --- /dev/null +++ b/pkg/rtypecontrol/import.go @@ -0,0 +1,89 @@ +package rtypecontrol + +import ( + "fmt" + + "github.com/StackExchange/dnscontrol/v4/models" + "github.com/StackExchange/dnscontrol/v4/pkg/domaintags" + "github.com/miekg/dns/dnsutil" +) + +// ImportRawRecords imports the RawRecordConfigs into RecordConfigs. +func ImportRawRecords(domains []*models.DomainConfig) error { + + for _, dc := range domains { + for _, rawRec := range dc.RawRecords { + + // Create as much of the RecordConfig as we can now. Allow New() to fill in the reset. + rec := &models.RecordConfig{ + Type: rawRec.Type, + TTL: rawRec.TTL, + Metadata: stringifyMetas(rawRec.Metas), + //FilePos: models.FixPosition(rawRec.FilePos), + } + + setRecordNames(rec, dc, rawRec.Args[0].(string)) + + // Fill in the .F/.Fields* fields. + err := Func[rawRec.Type].FromArgs(rec, rawRec.Args) + if err != nil { + return err + } + + // Free memeory: + clear(rawRec.Args) + rawRec.Args = nil + + dc.Records = append(dc.Records, rec) + } + dc.RawRecords = nil + } + + return nil +} + +func stringifyMetas(metas []map[string]any) map[string]string { + result := make(map[string]string) + for _, m := range metas { + for mk, mv := range m { + if v, ok := mv.(string); ok { + result[mk] = v // Already a string. No new malloc. + } else { + result[mk] = fmt.Sprintf("%v", mv) + } + } + } + return result +} + +func setRecordNames(rec *models.RecordConfig, dc *models.DomainConfig, n string) { + + if rec.SubDomain == "" { + // Not _EXTEND() mode: + if rec.Name == "@" { + rec.NameRaw = rec.Name + rec.Name = rec.Name + } else { + rec.Name = domaintags.EfficientToASCII(n) + rec.NameRaw = n + rec.Name = domaintags.EfficientToUnicode(n) + } + rec.NameFQDN = dnsutil.AddOrigin(rec.Name, dc.Name) + rec.NameFQDNRaw = dnsutil.AddOrigin(rec.NameRaw, dc.NameRaw) + rec.NameFQDNUnicode = dnsutil.AddOrigin(rec.NameUnicode, dc.NameUnicode) + } else { + // _EXTEND() mode: + // FIXME(tlim): Not implemented. + if rec.Name == "@" { + rec.NameRaw = rec.Name + rec.Name = rec.Name + } else { + rec.Name = domaintags.EfficientToASCII(n) + rec.NameRaw = n + rec.Name = domaintags.EfficientToUnicode(n) + } + rec.NameFQDN = dnsutil.AddOrigin(rec.Name, dc.Name) + rec.NameFQDNRaw = dnsutil.AddOrigin(rec.NameRaw, dc.NameRaw) + rec.NameFQDNUnicode = dnsutil.AddOrigin(rec.NameUnicode, dc.NameUnicode) + } +}