/
decode.go
99 lines (90 loc) · 2.03 KB
/
decode.go
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
92
93
94
95
96
97
98
99
package rfc2047
import (
"bufio"
"bytes"
"errors"
"io"
"strings"
"strconv"
)
type Encoding int
type Charset int
// Represents encoding 'Q'
const Q Encoding = 0
// Represents charset UTF-8
const Utf8 Charset = 0
type Decoder struct {
e Encoding
c Charset
}
func (d *Decoder) Decode(in *bufio.Reader, out *bytes.Buffer) (err error) {
for {
b, err := in.ReadByte()
if err != nil { break }
switch b {
case '=':
char := make([]byte,2)
in.Read(char)
code, _ := strconv.ParseUint(string(char), 16, 8)
out.WriteByte(byte(code))
case '_':
err = out.WriteByte(' ')
case ' ':
return errors.New("Invalid char ` `")
case '?':
b, err = in.ReadByte()
if b == '=' {
return nil
}
return errors.New("Unexpected `?`")
default:
err = out.WriteByte(b)
}
}
return err
}
func DecodeString(in string) (string, error) {
return Decode(bufio.NewReader(bytes.NewBufferString(in)))
}
func Decode(input *bufio.Reader) (_ string, err error) {
buf := bytes.NewBufferString("")
for {
b, err := input.ReadByte()
if err != nil { break }
if b != '=' {
err = buf.WriteByte(b)
} else {
input.UnreadByte()
charset, err := readCharset(input)
if err != nil { return "", err }
encoding, err := readEncoding(input)
if err != nil { return "", err }
(&Decoder{encoding, charset}).Decode(input, buf)
}
}
if err == io.EOF {
return buf.String(), nil
}
return buf.String(), err
}
func readCharset(input *bufio.Reader) (Charset, error) {
start, err := input.ReadString('?')
if err != nil { return -1, err }
if start != "=?" {
return 0, errors.New("Invalid encoded string start")
}
charset, err := input.ReadString('?')
if err != nil { return -1, err }
if strings.EqualFold(charset, "UTF-8?") {
return Utf8, nil
}
return -1, errors.New("Unknown characterset")
}
func readEncoding(input *bufio.Reader) (Encoding, error) {
encoding, err := input.ReadString('?')
if err != nil { return -1, err }
if strings.EqualFold(encoding, "Q?") {
return Q, nil
}
return -1, errors.New("Unknown encoding")
}