Home | History | Annotate | Download | only in idna
      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