mirror of
https://github.com/mjl-/mox.git
synced 2025-07-12 12:24:38 +03:00
mox!
This commit is contained in:
83
imapserver/utf7.go
Normal file
83
imapserver/utf7.go
Normal file
@ -0,0 +1,83 @@
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user