forked from lug/matterbridge
		
	 04567c765e
			
		
	
	04567c765e
	
	
	
		
			
			This uses our own gomatrix lib with the SendHTML function which adds HTML to formatted_body in matrix. golang-commonmark is used to convert markdown into valid HTML.
		
			
				
	
	
		
			288 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 The Authors. All rights reserved.
 | ||
| // Use of this source code is governed by a BSD-style
 | ||
| // license that can be found in the LICENSE file.
 | ||
| 
 | ||
| // Package puny provides functions for encoding/decoding to/from punycode.
 | ||
| package puny
 | ||
| 
 | ||
| import (
 | ||
| 	"errors"
 | ||
| 	"strings"
 | ||
| 	"unicode/utf8"
 | ||
| )
 | ||
| 
 | ||
| const (
 | ||
| 	maxInt32      int32 = 2147483647
 | ||
| 	base          int32 = 36
 | ||
| 	tMin          int32 = 1
 | ||
| 	baseMinusTMin       = base - tMin
 | ||
| 	tMax          int32 = 26
 | ||
| 	skew          int32 = 38
 | ||
| 	damp          int32 = 700
 | ||
| 	initialBias   int32 = 72
 | ||
| 	initialN      int32 = 128
 | ||
| )
 | ||
| 
 | ||
| var (
 | ||
| 	ErrOverflow     = errors.New("overflow: input needs wider integers to process")
 | ||
| 	ErrNotBasic     = errors.New("illegal input >= 0x80 (not a basic code point)")
 | ||
| 	ErrInvalidInput = errors.New("invalid input")
 | ||
| )
 | ||
| 
 | ||
| func adapt(delta, numPoints int32, firstTime bool) int32 {
 | ||
| 	if firstTime {
 | ||
| 		delta /= damp
 | ||
| 	} else {
 | ||
| 		delta /= 2
 | ||
| 	}
 | ||
| 	delta += delta / numPoints
 | ||
| 	k := int32(0)
 | ||
| 	for delta > baseMinusTMin*tMax/2 {
 | ||
| 		delta = delta / baseMinusTMin
 | ||
| 		k += base
 | ||
| 	}
 | ||
| 	return k + (baseMinusTMin+1)*delta/(delta+skew)
 | ||
| }
 | ||
| 
 | ||
| func basicToDigit(b byte) int32 {
 | ||
| 	switch {
 | ||
| 	case b >= '0' && b <= '9':
 | ||
| 		return int32(b - 22)
 | ||
| 	case b >= 'A' && b <= 'Z':
 | ||
| 		return int32(b - 'A')
 | ||
| 	case b >= 'a' && b <= 'z':
 | ||
| 		return int32(b - 'a')
 | ||
| 	}
 | ||
| 	return base
 | ||
| }
 | ||
| 
 | ||
| func digitToBasic(digit int32) byte {
 | ||
| 	switch {
 | ||
| 	case digit >= 0 && digit <= 25:
 | ||
| 		return byte(digit) + 'a'
 | ||
| 	case digit >= 26 && digit <= 35:
 | ||
| 		return byte(digit) - 26 + '0'
 | ||
| 	}
 | ||
| 	panic("unreachable")
 | ||
| }
 | ||
| 
 | ||
| func lastIndex(s string, c byte) int {
 | ||
| 	for i := len(s) - 1; i >= 0; i-- {
 | ||
| 		if s[i] == c {
 | ||
| 			return i
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return -1
 | ||
| }
 | ||
| 
 | ||
| func ascii(s string) bool {
 | ||
| 	for _, r := range s {
 | ||
| 		if r > 0x7e {
 | ||
| 			return false
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return true
 | ||
| }
 | ||
| 
 | ||
| // Decode converts a Punycode string of ASCII-only symbols to a string of Unicode symbols.
 | ||
| func Decode(s string) (string, error) {
 | ||
| 	basic := lastIndex(s, '-')
 | ||
| 	output := make([]rune, 0, len(s))
 | ||
| 	for i := 0; i < basic; i++ {
 | ||
| 		b := s[i]
 | ||
| 		if b >= 0x80 {
 | ||
| 			return "", ErrNotBasic
 | ||
| 		}
 | ||
| 		output = append(output, rune(b))
 | ||
| 	}
 | ||
| 
 | ||
| 	i, n, bias, pos := int32(0), initialN, initialBias, basic+1
 | ||
| 
 | ||
| 	for pos < len(s) {
 | ||
| 		oldi, w, k := i, int32(1), base
 | ||
| 		for {
 | ||
| 			digit := basicToDigit(s[pos])
 | ||
| 			pos++
 | ||
| 
 | ||
| 			if digit >= base || digit > (maxInt32-i)/w {
 | ||
| 				return "", ErrOverflow
 | ||
| 			}
 | ||
| 
 | ||
| 			i += digit * w
 | ||
| 
 | ||
| 			t := k - bias
 | ||
| 			if t < tMin {
 | ||
| 				t = tMin
 | ||
| 			} else if t > tMax {
 | ||
| 				t = tMax
 | ||
| 			}
 | ||
| 
 | ||
| 			if digit < t {
 | ||
| 				break
 | ||
| 			}
 | ||
| 
 | ||
| 			if pos == len(s) {
 | ||
| 				return "", ErrInvalidInput
 | ||
| 			}
 | ||
| 
 | ||
| 			baseMinusT := base - t
 | ||
| 			if w > maxInt32/baseMinusT {
 | ||
| 				return "", ErrOverflow
 | ||
| 			}
 | ||
| 
 | ||
| 			w *= baseMinusT
 | ||
| 			k += base
 | ||
| 		}
 | ||
| 
 | ||
| 		out := int32(len(output) + 1)
 | ||
| 		bias = adapt(i-oldi, out, oldi == 0)
 | ||
| 
 | ||
| 		if i/out > maxInt32-n {
 | ||
| 			return "", ErrOverflow
 | ||
| 		}
 | ||
| 
 | ||
| 		n += i / out
 | ||
| 		i %= out
 | ||
| 
 | ||
| 		output = append(output, 0)
 | ||
| 		copy(output[i+1:], output[i:])
 | ||
| 		output[i] = rune(n)
 | ||
| 
 | ||
| 		i++
 | ||
| 	}
 | ||
| 
 | ||
| 	return string(output), nil
 | ||
| }
 | ||
| 
 | ||
| // Encode converts a string of Unicode symbols (e.g. a domain name label) to a
 | ||
| // Punycode string of ASCII-only symbols.
 | ||
| func Encode(input string) (string, error) {
 | ||
| 	n := initialN
 | ||
| 	delta := int32(0)
 | ||
| 	bias := initialBias
 | ||
| 
 | ||
| 	var output []byte
 | ||
| 	runes := 0
 | ||
| 	for _, r := range input {
 | ||
| 		if r >= 0x80 {
 | ||
| 			runes++
 | ||
| 			continue
 | ||
| 		}
 | ||
| 		output = append(output, byte(r))
 | ||
| 	}
 | ||
| 
 | ||
| 	basicLength := len(output)
 | ||
| 	handledCPCount := basicLength
 | ||
| 
 | ||
| 	if basicLength > 0 {
 | ||
| 		output = append(output, '-')
 | ||
| 	}
 | ||
| 
 | ||
| 	for runes > 0 {
 | ||
| 		m := maxInt32
 | ||
| 		for _, r := range input {
 | ||
| 			if r >= n && r < m {
 | ||
| 				m = r
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		handledCPCountPlusOne := int32(handledCPCount + 1)
 | ||
| 		if m-n > (maxInt32-delta)/handledCPCountPlusOne {
 | ||
| 			return "", ErrOverflow
 | ||
| 		}
 | ||
| 
 | ||
| 		delta += (m - n) * handledCPCountPlusOne
 | ||
| 		n = m
 | ||
| 
 | ||
| 		for _, r := range input {
 | ||
| 			if r < n {
 | ||
| 				delta++
 | ||
| 				if delta < 0 {
 | ||
| 					return "", ErrOverflow
 | ||
| 				}
 | ||
| 				continue
 | ||
| 			}
 | ||
| 			if r > n {
 | ||
| 				continue
 | ||
| 			}
 | ||
| 			q := delta
 | ||
| 			for k := base; ; k += base {
 | ||
| 				t := k - bias
 | ||
| 				if t < tMin {
 | ||
| 					t = tMin
 | ||
| 				} else if t > tMax {
 | ||
| 					t = tMax
 | ||
| 				}
 | ||
| 				if q < t {
 | ||
| 					break
 | ||
| 				}
 | ||
| 				qMinusT := q - t
 | ||
| 				baseMinusT := base - t
 | ||
| 				output = append(output, digitToBasic(t+qMinusT%baseMinusT))
 | ||
| 				q = qMinusT / baseMinusT
 | ||
| 			}
 | ||
| 
 | ||
| 			output = append(output, digitToBasic(q))
 | ||
| 			bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength)
 | ||
| 			delta = 0
 | ||
| 			handledCPCount++
 | ||
| 			runes--
 | ||
| 		}
 | ||
| 		delta++
 | ||
| 		n++
 | ||
| 	}
 | ||
| 	return string(output), nil
 | ||
| }
 | ||
| 
 | ||
| func sep(r rune) bool { return r == '.' || r == '。' || r == '.' || r == '。' }
 | ||
| 
 | ||
| func mapLabels(s string, fn func(string) string) string {
 | ||
| 	var result string
 | ||
| 	i := strings.IndexByte(s, '@')
 | ||
| 	if i != -1 {
 | ||
| 		result = s[:i+1]
 | ||
| 		s = s[i+1:]
 | ||
| 	}
 | ||
| 	var labels []string
 | ||
| 	start := 0
 | ||
| 	for i, r := range s {
 | ||
| 		if !sep(r) {
 | ||
| 			continue
 | ||
| 		}
 | ||
| 		labels = append(labels, fn(s[start:i]))
 | ||
| 		start = i + utf8.RuneLen(r)
 | ||
| 	}
 | ||
| 	labels = append(labels, fn(s[start:]))
 | ||
| 	return result + strings.Join(labels, ".")
 | ||
| }
 | ||
| 
 | ||
| // ToUnicode converts a Punycode string representing a domain name or an email address
 | ||
| // to Unicode. Only the Punycoded parts of the input will be converted.
 | ||
| func ToUnicode(s string) string {
 | ||
| 	return mapLabels(s, func(s string) string {
 | ||
| 		if !strings.HasPrefix(s, "xn--") {
 | ||
| 			return s
 | ||
| 		}
 | ||
| 		d, err := Decode(strings.ToLower(s[4:]))
 | ||
| 		if err != nil {
 | ||
| 			return s
 | ||
| 		}
 | ||
| 		return d
 | ||
| 	})
 | ||
| }
 | ||
| 
 | ||
| // ToASCII converts a Unicode string representing a domain name or an email address to
 | ||
| // Punycode. Only the non-ASCII parts of the domain name will be converted.
 | ||
| func ToASCII(s string) string {
 | ||
| 	return mapLabels(s, func(s string) string {
 | ||
| 		if ascii(s) {
 | ||
| 			return s
 | ||
| 		}
 | ||
| 		d, err := Encode(s)
 | ||
| 		if err != nil {
 | ||
| 			return s
 | ||
| 		}
 | ||
| 		return "xn--" + d
 | ||
| 	})
 | ||
| }
 |