diff --git a/listener.go b/listener.go index b4c5623..2c15b40 100644 --- a/listener.go +++ b/listener.go @@ -8,7 +8,7 @@ type Listener interface { CheckHost(ip net.IP, domain, sender string) CheckHostResult(r Result, explanation string, extras *ResponseExtras, err error) SPFRecord(s string) - Directive(unused bool, qualifier, mechanism, value, effectiveValue string) + Directive(unused bool, qualifier, mechanism, key, value, effectiveValue string) NonMatch(qualifier, mechanism, value string, result Result, err error) Match(qualifier, mechanism, value string, result Result, explanation string, extras *ResponseExtras, err error) FirstMatch(r Result, err error) diff --git a/parser.go b/parser.go index b18ccc0..4f787d5 100644 --- a/parser.go +++ b/parser.go @@ -342,7 +342,7 @@ func (p *parser) fireDirective(t *token, effectiveValue string) { if p.listener == nil { return } - p.listener.Directive(false, t.qualifier.String(), t.mechanism.String(), t.value, effectiveValue) + p.listener.Directive(false, t.qualifier.String(), t.mechanism.String(), t.key, t.value, effectiveValue) } func (p *parser) fireMatchingIP(t *token, fqdn string, ipn net.IPNet, host string, ip net.IP) { @@ -356,7 +356,7 @@ func (p *parser) fireUnusedDirective(t *token) { if p.listener == nil || t == nil { return } - p.listener.Directive(true, t.qualifier.String(), t.mechanism.String(), t.value, "") + p.listener.Directive(true, t.qualifier.String(), t.mechanism.String(), t.key, t.value, "") } func (p *parser) fireNonMatch(t *token, r Result, e error) { diff --git a/printer/printer.go b/printer/printer.go index 337bb2f..3cc4c6a 100644 --- a/printer/printer.go +++ b/printer/printer.go @@ -48,7 +48,7 @@ func (p *Printer) CheckHostResult(r spf.Result, explanation string, extras *spf. fmt.Fprintf(p.w, "%s= %s, %v, %v, %v\n", strings.Repeat(" ", p.c), r, extras, explanation, err) } -func (p *Printer) Directive(unused bool, qualifier, mechanism, value, effectiveValue string) { +func (p *Printer) Directive(unused bool, qualifier, mechanism, key, value, effectiveValue string) { fmt.Fprintf(p.w, "%s", strings.Repeat(" ", p.c)) if qualifier == "+" { qualifier = "" @@ -61,6 +61,11 @@ func (p *Printer) Directive(unused bool, qualifier, mechanism, value, effectiveV if mechanism == "v" { delimiter = "=" } + + if mechanism[0] == ':' { + fmt.Fprintf(p.w, " (%s)", key) + } + if value != "" { fmt.Fprintf(p.w, "%s%s", delimiter, value) } diff --git a/token.go b/token.go index 3db179f..53f392b 100644 --- a/token.go +++ b/token.go @@ -6,6 +6,9 @@ import ( "strings" ) +// UnknownModifierMech constructed so we break policy if someone tries to create a policy out of mechanism string function instead of using actual key +const UnknownModifierMech = ":?" + type tokenType int const ( @@ -83,9 +86,9 @@ func (tok tokenType) String() string { case qTilde: return "~" case tUnknownModifier: - return "UNKNOWN_MODIFIER" + return UnknownModifierMech default: - return strconv.Itoa(int(tok)) + return ":" + strconv.Itoa(int(tok)) } } @@ -197,3 +200,7 @@ func (t *token) String() string { } return fmt.Sprintf("%s%s%s%s", q, k, d, t.value) } + +func IsKnownMechanism(s string) bool { + return tokenTypeFromString(s) != tErr +}