1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package idna implements IDNA2008 (Internationalized Domain Names for 6 // Applications), defined in RFC 5890, RFC 5891, RFC 5892, RFC 5893 and 7 // RFC 5894. 8 package idna // import "golang.org/x/net/idna" 9 10 import ( 11 "strings" 12 "unicode/utf8" 13 ) 14 15 // TODO(nigeltao): specify when errors occur. For example, is ToASCII(".") or 16 // ToASCII("foo\x00") an error? See also http://www.unicode.org/faq/idn.html#11 17 18 // acePrefix is the ASCII Compatible Encoding prefix. 19 const acePrefix = "xn--" 20 21 // ToASCII converts a domain or domain label to its ASCII form. For example, 22 // ToASCII("bcher.example.com") is "xn--bcher-kva.example.com", and 23 // ToASCII("golang") is "golang". 24 func ToASCII(s string) (string, error) { 25 if ascii(s) { 26 return s, nil 27 } 28 labels := strings.Split(s, ".") 29 for i, label := range labels { 30 if !ascii(label) { 31 a, err := encode(acePrefix, label) 32 if err != nil { 33 return "", err 34 } 35 labels[i] = a 36 } 37 } 38 return strings.Join(labels, "."), nil 39 } 40 41 // ToUnicode converts a domain or domain label to its Unicode form. For example, 42 // ToUnicode("xn--bcher-kva.example.com") is "bcher.example.com", and 43 // ToUnicode("golang") is "golang". 44 func ToUnicode(s string) (string, error) { 45 if !strings.Contains(s, acePrefix) { 46 return s, nil 47 } 48 labels := strings.Split(s, ".") 49 for i, label := range labels { 50 if strings.HasPrefix(label, acePrefix) { 51 u, err := decode(label[len(acePrefix):]) 52 if err != nil { 53 return "", err 54 } 55 labels[i] = u 56 } 57 } 58 return strings.Join(labels, "."), nil 59 } 60 61 func ascii(s string) bool { 62 for i := 0; i < len(s); i++ { 63 if s[i] >= utf8.RuneSelf { 64 return false 65 } 66 } 67 return true 68 } 69