aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/emersion/go-imap/utf7/encoder.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/emersion/go-imap/utf7/encoder.go')
-rw-r--r--vendor/github.com/emersion/go-imap/utf7/encoder.go91
1 files changed, 91 insertions, 0 deletions
diff --git a/vendor/github.com/emersion/go-imap/utf7/encoder.go b/vendor/github.com/emersion/go-imap/utf7/encoder.go
new file mode 100644
index 0000000..8414d10
--- /dev/null
+++ b/vendor/github.com/emersion/go-imap/utf7/encoder.go
@@ -0,0 +1,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
+}