From 910e194a999430b78d481bcca6e9ac9991056284 Mon Sep 17 00:00:00 2001 From: Amit Ramon Date: Fri, 5 Feb 2021 16:57:51 +0200 Subject: [PATCH] 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 --- offlineimap/imaputil.py | 59 ++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/offlineimap/imaputil.py b/offlineimap/imaputil.py index 4083d34..758e78c 100644 --- a/offlineimap/imaputil.py +++ b/offlineimap/imaputil.py @@ -18,6 +18,7 @@ import re import binascii import codecs +from typing import Tuple from offlineimap.ui import getglobalui # Globals @@ -352,42 +353,45 @@ def decode_mailbox_name(name): def IMAP_utf8(foldername): """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): """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 - def modified_base64(s): 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): if _in: - r.append('&%s-' % modified_base64(''.join(_in))) + r.append(b'&%s-' % modified_base64(''.join(_in))) del _in[:] -def encoder(s): +def utf7m_encode(text: str) -> Tuple[bytes, int]: r = [] _in = [] - for c in s: - ordC = ord(c) - if 0x20 <= ordC <= 0x25 or 0x27 <= ordC <= 0x7e: + + for c in text: + if 0x20 <= ord(c) <= 0x7e: doB64(_in, r) - r.append(c) - elif c == '&': - doB64(_in, r) - r.append('&-') + r.append(b'&-' if c == '&' else c.encode()) else: _in.append(c) + doB64(_in, r) - return str(''.join(r)), len(s) + return b''.join(r), len(text) # decoding @@ -396,10 +400,10 @@ def modified_unbase64(s): return str(b, 'utf-16be') -def decoder(s): +def utf7m_decode(binary: bytes) -> Tuple[str, int]: r = [] decode = [] - for c in s: + for c in binary.decode(): if c == '&' and not decode: decode.append('&') elif c == '-' and decode: @@ -415,26 +419,31 @@ def decoder(s): if decode: 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): def decode(self, s, errors='strict'): - return decoder(s) + return utf7m_decode(s) class StreamWriter(codecs.StreamWriter): def decode(self, s, errors='strict'): - return encoder(s) + return utf7m_encode(s) -def imap4_utf_7(name): - if name == 'imap4-utf-7': - return encoder, decoder, StreamReader, StreamWriter +def utf7m_search_function(name): + return codecs.CodecInfo( + 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): @@ -454,4 +463,4 @@ def foldername_to_imapname(folder_name): if any((c in atom_specials) for c in folder_name): folder_name = '"' + folder_name + '"' - return folder_name \ No newline at end of file + return folder_name