mirror of
https://github.com/mjl-/mox.git
synced 2024-12-26 16:33:47 +03:00
83 lines
1.5 KiB
Go
83 lines
1.5 KiB
Go
package imapserver
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
const utf7chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"
|
|
|
|
var utf7encoding = base64.NewEncoding(utf7chars).WithPadding(base64.NoPadding)
|
|
|
|
var (
|
|
errUTF7SuperfluousShift = errors.New("utf7: superfluous unshift+shift")
|
|
errUTF7Base64 = errors.New("utf7: bad base64")
|
|
errUTF7OddSized = errors.New("utf7: odd-sized data")
|
|
errUTF7UnneededShift = errors.New("utf7: unneeded shift")
|
|
errUTF7UnfinishedShift = errors.New("utf7: unfinished shift")
|
|
)
|
|
|
|
func utf7decode(s string) (string, error) {
|
|
var r string
|
|
var shifted bool
|
|
var b string
|
|
lastunshift := -2
|
|
|
|
for i, c := range s {
|
|
if !shifted {
|
|
if c == '&' {
|
|
if lastunshift == i-1 {
|
|
return "", errUTF7SuperfluousShift
|
|
}
|
|
shifted = true
|
|
} else {
|
|
r += string(c)
|
|
}
|
|
continue
|
|
}
|
|
|
|
if c != '-' {
|
|
b += string(c)
|
|
continue
|
|
}
|
|
|
|
shifted = false
|
|
lastunshift = i
|
|
if b == "" {
|
|
r += "&"
|
|
continue
|
|
}
|
|
buf, err := utf7encoding.DecodeString(b)
|
|
if err != nil {
|
|
return "", fmt.Errorf("%w: %q: %v", errUTF7Base64, b, err)
|
|
}
|
|
b = ""
|
|
|
|
if len(buf)%2 != 0 {
|
|
return "", errUTF7OddSized
|
|
}
|
|
|
|
x := make([]rune, len(buf)/2)
|
|
j := 0
|
|
for i := 0; i < len(buf); i += 2 {
|
|
x[j] = rune(buf[i])<<8 | rune(buf[i+1])
|
|
j++
|
|
}
|
|
|
|
need := false
|
|
for _, c := range x {
|
|
if c < 0x20 || c > 0x7e || c == '&' {
|
|
need = true
|
|
}
|
|
r += string(c)
|
|
}
|
|
if !need {
|
|
return "", errUTF7UnneededShift
|
|
}
|
|
}
|
|
if shifted {
|
|
return "", errUTF7UnfinishedShift
|
|
}
|
|
return r, nil
|
|
}
|