Fix utf8foldernames configuration option to work with Python3

The current code for supporting the utf8foldernames does not work with
Python3 due to changes in the 'codecs' module and related functions.

This fix adapts the existing code to work with Python3.

Signed-off-by: Amit Ramon <amit@riseup.net>
This commit is contained in:
Amit Ramon 2021-02-05 16:57:51 +02:00
parent 00d395b746
commit 910e194a99

View File

@ -18,6 +18,7 @@
import re import re
import binascii import binascii
import codecs import codecs
from typing import Tuple
from offlineimap.ui import getglobalui from offlineimap.ui import getglobalui
# Globals # Globals
@ -352,42 +353,45 @@ def decode_mailbox_name(name):
def IMAP_utf8(foldername): def IMAP_utf8(foldername):
"""Convert IMAP4_utf_7 encoded string to utf-8""" """Convert IMAP4_utf_7 encoded string to utf-8"""
return foldername.decode('imap4-utf-7').encode('utf-8') return codecs.decode(
foldername.encode(),
'imap4-utf-7'
).encode('utf-8').decode()
def utf8_IMAP(foldername): def utf8_IMAP(foldername):
"""Convert utf-8 encoded string to IMAP4_utf_7""" """Convert utf-8 encoded string to IMAP4_utf_7"""
return foldername.decode('utf-8').encode('imap4-utf-7') return codecs.decode(
foldername.encode(),
'utf-8'
).encode('imap4-utf-7').decode()
# Codec definition # Codec definition
def modified_base64(s): def modified_base64(s):
s = s.encode('utf-16be') s = s.encode('utf-16be')
return binascii.b2a_base64(s).rstrip('\n=').replace('/', ',') return binascii.b2a_base64(s).rstrip(b'\n=').replace(b'/', b',')
def doB64(_in, r): def doB64(_in, r):
if _in: if _in:
r.append('&%s-' % modified_base64(''.join(_in))) r.append(b'&%s-' % modified_base64(''.join(_in)))
del _in[:] del _in[:]
def encoder(s): def utf7m_encode(text: str) -> Tuple[bytes, int]:
r = [] r = []
_in = [] _in = []
for c in s:
ordC = ord(c) for c in text:
if 0x20 <= ordC <= 0x25 or 0x27 <= ordC <= 0x7e: if 0x20 <= ord(c) <= 0x7e:
doB64(_in, r) doB64(_in, r)
r.append(c) r.append(b'&-' if c == '&' else c.encode())
elif c == '&':
doB64(_in, r)
r.append('&-')
else: else:
_in.append(c) _in.append(c)
doB64(_in, r) doB64(_in, r)
return str(''.join(r)), len(s) return b''.join(r), len(text)
# decoding # decoding
@ -396,10 +400,10 @@ def modified_unbase64(s):
return str(b, 'utf-16be') return str(b, 'utf-16be')
def decoder(s): def utf7m_decode(binary: bytes) -> Tuple[str, int]:
r = [] r = []
decode = [] decode = []
for c in s: for c in binary.decode():
if c == '&' and not decode: if c == '&' and not decode:
decode.append('&') decode.append('&')
elif c == '-' and decode: elif c == '-' and decode:
@ -415,26 +419,31 @@ def decoder(s):
if decode: if decode:
r.append(modified_unbase64(''.join(decode[1:]))) r.append(modified_unbase64(''.join(decode[1:])))
bin_str = ''.join(r)
return bin_str, len(s) return ''.join(r), len(binary)
class StreamReader(codecs.StreamReader): class StreamReader(codecs.StreamReader):
def decode(self, s, errors='strict'): def decode(self, s, errors='strict'):
return decoder(s) return utf7m_decode(s)
class StreamWriter(codecs.StreamWriter): class StreamWriter(codecs.StreamWriter):
def decode(self, s, errors='strict'): def decode(self, s, errors='strict'):
return encoder(s) return utf7m_encode(s)
def imap4_utf_7(name): def utf7m_search_function(name):
if name == 'imap4-utf-7': return codecs.CodecInfo(
return encoder, decoder, StreamReader, StreamWriter utf7m_encode,
utf7m_decode,
StreamReader,
StreamWriter,
name='imap4-utf-7'
)
codecs.register(imap4_utf_7) codecs.register(utf7m_search_function)
def foldername_to_imapname(folder_name): def foldername_to_imapname(folder_name):
@ -454,4 +463,4 @@ def foldername_to_imapname(folder_name):
if any((c in atom_specials) for c in folder_name): if any((c in atom_specials) for c in folder_name):
folder_name = '"' + folder_name + '"' folder_name = '"' + folder_name + '"'
return folder_name return folder_name