2023-01-30 16:27:06 +03:00
|
|
|
package imapserver
|
|
|
|
|
|
|
|
import (
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
"bytes"
|
2023-01-30 16:27:06 +03:00
|
|
|
"encoding/base64"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
"unicode/utf16"
|
2023-01-30 16:27:06 +03:00
|
|
|
)
|
|
|
|
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
// IMAP4rev1 uses a modified version of UTF-7.
|
|
|
|
// ../rfc/3501:1050
|
|
|
|
// ../rfc/2152:69
|
|
|
|
|
2023-01-30 16:27:06 +03:00
|
|
|
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")
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
errUTF7BadSurrogate = errors.New("utf7: bad utf16 surrogates")
|
2023-01-30 16:27:06 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
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
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
trymerge := false
|
2023-01-30 16:27:06 +03:00
|
|
|
for i := 0; i < len(buf); i += 2 {
|
|
|
|
x[j] = rune(buf[i])<<8 | rune(buf[i+1])
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
if trymerge {
|
|
|
|
s0 := utf16.IsSurrogate(x[j-1])
|
|
|
|
s1 := utf16.IsSurrogate(x[j])
|
|
|
|
if s0 && s1 {
|
|
|
|
c := utf16.DecodeRune(x[j-1], x[j])
|
|
|
|
if c == 0xfffd {
|
|
|
|
return "", fmt.Errorf("%w: decoding %x %x", errUTF7BadSurrogate, x[j-1], x[j])
|
|
|
|
}
|
|
|
|
x[j-1] = c
|
|
|
|
trymerge = false
|
|
|
|
continue
|
|
|
|
} else if s0 != s1 {
|
|
|
|
return "", fmt.Errorf("%w: not both surrogate: %x %x", errUTF7BadSurrogate, x[j-1], x[j])
|
|
|
|
}
|
|
|
|
}
|
2023-01-30 16:27:06 +03:00
|
|
|
j++
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
trymerge = true
|
2023-01-30 16:27:06 +03:00
|
|
|
}
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
x = x[:j]
|
2023-01-30 16:27:06 +03:00
|
|
|
|
|
|
|
for _, c := range x {
|
|
|
|
if c < 0x20 || c > 0x7e || c == '&' {
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
r += string(c)
|
|
|
|
} else {
|
|
|
|
// ../rfc/3501:1057
|
|
|
|
return "", errUTF7UnneededShift
|
2023-01-30 16:27:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if shifted {
|
|
|
|
return "", errUTF7UnfinishedShift
|
|
|
|
}
|
|
|
|
return r, nil
|
|
|
|
}
|
imapserver: allow creating mailboxes with characters &#*%, and encode mailbox names in imap with imaputf7 when needed
the imapserver started with imap4rev2-only and utf8=only. to prevent potential
issues with imaputf7, which makes "&" special, we refused any mailbox with an
"&" in the name. we already tried decoding utf7, falling back to using a
mailbox name verbatim. that behaviour wasn't great. we now treat the enabled
extensions IMAP4rev2 and/or UTF8=ACCEPT as indication whether mailbox names are
in imaputf7. if they are, the encoding must be correct.
we now also send mailbox names in imaputf7 when imap4rev2/utf8=accept isn't
enabled.
and we now allow "*" and "%" (wildcard characters for matching) in mailbox
names. not ideal for IMAP LIST with patterns, but not enough reason to refuse
them in mailbox names. people that migrate may run into this, possibly as
blocker.
we also allow "#" in mailbox names, but not as first character, to prevent
potential clashes with IMAP namespaces in the future.
based on report from Damian Poddebniak using
https://github.com/duesee/imap-flow and issue #110, thanks for reporting!
2024-01-01 15:15:25 +03:00
|
|
|
|
|
|
|
func utf7encode(s string) string {
|
|
|
|
var r string
|
|
|
|
var code string
|
|
|
|
|
|
|
|
flushcode := func() {
|
|
|
|
if code == "" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
|
|
for _, c := range code {
|
|
|
|
high, low := utf16.EncodeRune(c)
|
|
|
|
if high == 0xfffd && low == 0xfffd {
|
|
|
|
b.WriteByte(byte(c >> 8))
|
|
|
|
b.WriteByte(byte(c >> 0))
|
|
|
|
} else {
|
|
|
|
b.WriteByte(byte(high >> 8))
|
|
|
|
b.WriteByte(byte(high >> 0))
|
|
|
|
b.WriteByte(byte(low >> 8))
|
|
|
|
b.WriteByte(byte(low >> 0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r += "&" + utf7encoding.EncodeToString(b.Bytes()) + "-"
|
|
|
|
code = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, c := range s {
|
|
|
|
if c == '&' {
|
|
|
|
flushcode()
|
|
|
|
r += "&-"
|
|
|
|
} else if c >= ' ' && c < 0x7f {
|
|
|
|
flushcode()
|
|
|
|
r += string(c)
|
|
|
|
} else {
|
|
|
|
code += string(c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
flushcode()
|
|
|
|
return r
|
|
|
|
}
|