mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
Normalize domains
We should ignore the domains' case, and treat them uniformly, specially when it comes to local domains. This patch extends the existing normalization (IDNA, keeping domains as UTF8 internally) to include case conversion and NFC form for consistency.
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
// Package normalize contains functions to normalize usernames and addresses.
|
||||
// Package normalize contains functions to normalize usernames, domains and
|
||||
// addresses.
|
||||
package normalize
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"blitiri.com.ar/go/chasquid/internal/envelope"
|
||||
"golang.org/x/net/idna"
|
||||
"golang.org/x/text/secure/precis"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
// User normalices an username using PRECIS.
|
||||
// User normalizes an username using PRECIS.
|
||||
// On error, it will also return the original username to simplify callers.
|
||||
func User(user string) (string, error) {
|
||||
norm, err := precis.UsernameCaseMapped.String(user)
|
||||
@@ -17,7 +22,27 @@ func User(user string) (string, error) {
|
||||
return norm, nil
|
||||
}
|
||||
|
||||
// Name normalices an email address using PRECIS.
|
||||
// Domain normalizes a DNS domain into a cleaned UTF-8 form.
|
||||
// On error, it will also return the original domain to simplify callers.
|
||||
func Domain(domain string) (string, error) {
|
||||
// For now, we just convert them to lower case and make sure it's in NFC
|
||||
// form for consistency.
|
||||
// There are other possible transformations (like nameprep) but for our
|
||||
// purposes these should be enough.
|
||||
// https://tools.ietf.org/html/rfc5891#section-5.2
|
||||
// https://blog.golang.org/normalization
|
||||
d, err := idna.ToUnicode(domain)
|
||||
if err != nil {
|
||||
return domain, err
|
||||
}
|
||||
|
||||
d = norm.NFC.String(d)
|
||||
d = strings.ToLower(d)
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// Name normalizes an email address, applying User and Domain to its
|
||||
// respective components.
|
||||
// On error, it will also return the original address to simplify callers.
|
||||
func Addr(addr string) (string, error) {
|
||||
user, domain := envelope.Split(addr)
|
||||
@@ -27,5 +52,23 @@ func Addr(addr string) (string, error) {
|
||||
return addr, err
|
||||
}
|
||||
|
||||
domain, err = Domain(domain)
|
||||
if err != nil {
|
||||
return addr, err
|
||||
}
|
||||
|
||||
return user + "@" + domain, nil
|
||||
}
|
||||
|
||||
// Take an address with an ASCII domain, and convert it to Unicode as per
|
||||
// IDNA, including basic normalization.
|
||||
// The user part is unchanged.
|
||||
func DomainToUnicode(addr string) (string, error) {
|
||||
if addr == "<>" {
|
||||
return addr, nil
|
||||
}
|
||||
user, domain := envelope.Split(addr)
|
||||
|
||||
domain, err := Domain(domain)
|
||||
return user + "@" + domain, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user