1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
package utf7
import (
"unicode/utf16"
"unicode/utf8"
"golang.org/x/text/transform"
)
type encoder struct{}
func (e *encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for i := 0; i < len(src); {
ch := src[i]
var b []byte
if min <= ch && ch <= max {
b = []byte{ch}
if ch == '&' {
b = append(b, '-')
}
i++
} else {
start := i
// Find the next printable ASCII code point
i++
for i < len(src) && (src[i] < min || src[i] > max) {
i++
}
if !atEOF && i == len(src) {
err = transform.ErrShortSrc
return
}
b = encode(src[start:i])
}
if nDst+len(b) > len(dst) {
err = transform.ErrShortDst
return
}
nSrc = i
for _, ch := range b {
dst[nDst] = ch
nDst++
}
}
return
}
func (e *encoder) Reset() {}
// Converts string s from UTF-8 to UTF-16-BE, encodes the result as base64,
// removes the padding, and adds UTF-7 shifts.
func encode(s []byte) []byte {
// len(s) is sufficient for UTF-8 to UTF-16 conversion if there are no
// control code points (see table below).
b := make([]byte, 0, len(s)+4)
for len(s) > 0 {
r, size := utf8.DecodeRune(s)
if r > utf8.MaxRune {
r, size = utf8.RuneError, 1 // Bug fix (issue 3785)
}
s = s[size:]
if r1, r2 := utf16.EncodeRune(r); r1 != repl {
b = append(b, byte(r1>>8), byte(r1))
r = r2
}
b = append(b, byte(r>>8), byte(r))
}
// Encode as base64
n := b64Enc.EncodedLen(len(b)) + 2
b64 := make([]byte, n)
b64Enc.Encode(b64[1:], b)
// Strip padding
n -= 2 - (len(b)+2)%3
b64 = b64[:n]
// Add UTF-7 shifts
b64[0] = '&'
b64[n-1] = '-'
return b64
}
|