Merge branch 'master' into multiple_encoding_support. Dropping patch
for "Included charset detection"
This commit is contained in:
commit
f71ef226bf
@ -310,12 +310,8 @@ class IMAPServer:
|
|||||||
# This is a behavior we got from pykerberos. First byte is one,
|
# This is a behavior we got from pykerberos. First byte is one,
|
||||||
# first four bytes are preserved (pykerberos calls this a length).
|
# first four bytes are preserved (pykerberos calls this a length).
|
||||||
# Any additional bytes are username.
|
# Any additional bytes are username.
|
||||||
reply = []
|
reply = b'\x01' + response.message[1:4]
|
||||||
reply[0:4] = response.message[0:4]
|
reply += bytes(self.username, 'utf-8')
|
||||||
reply[0] = '\x01'
|
|
||||||
if self.username:
|
|
||||||
reply[5:] = self.username
|
|
||||||
reply = ''.join(reply)
|
|
||||||
|
|
||||||
response = self.gss_vc.wrap(reply, response.encrypted)
|
response = self.gss_vc.wrap(reply, response.encrypted)
|
||||||
return response.message if response.message else ""
|
return response.message if response.message else ""
|
||||||
|
@ -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):
|
||||||
|
@ -206,12 +206,23 @@ class IMAPRepository(BaseRepository):
|
|||||||
Returns: Returns the remoteusereval or remoteuser or netrc user value.
|
Returns: Returns the remoteusereval or remoteuser or netrc user value.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
localeval = self.localeval
|
|
||||||
|
|
||||||
if self.config.has_option(self.getsection(), 'remoteusereval'):
|
if self.config.has_option(self.getsection(), 'remoteusereval'):
|
||||||
user = self.getconf('remoteusereval')
|
user = self.getconf('remoteusereval')
|
||||||
if user is not None:
|
if user is not None:
|
||||||
return localeval.eval(user).encode('UTF-8')
|
l_user = self.localeval.eval(user)
|
||||||
|
|
||||||
|
# We need a str username
|
||||||
|
if isinstance(l_user, bytes):
|
||||||
|
return l_user.decode(encoding='utf-8')
|
||||||
|
elif isinstance(l_user, str):
|
||||||
|
return l_user
|
||||||
|
|
||||||
|
# If is not bytes or str, we have a problem
|
||||||
|
raise OfflineImapError("Could not get a right username format for"
|
||||||
|
" repository %s. Type found: %s. "
|
||||||
|
"Please, open a bug." %
|
||||||
|
(self.name, type(l_user)),
|
||||||
|
OfflineImapError.ERROR.FOLDER)
|
||||||
|
|
||||||
if self.config.has_option(self.getsection(), 'remoteuser'):
|
if self.config.has_option(self.getsection(), 'remoteuser'):
|
||||||
# Assume the configuration file to be UTF-8 encoded so we must not
|
# Assume the configuration file to be UTF-8 encoded so we must not
|
||||||
@ -590,7 +601,20 @@ class IMAPRepository(BaseRepository):
|
|||||||
encoding='utf-8')
|
encoding='utf-8')
|
||||||
password = file_desc.readline().strip()
|
password = file_desc.readline().strip()
|
||||||
file_desc.close()
|
file_desc.close()
|
||||||
return password.encode('UTF-8')
|
|
||||||
|
# We need a str password
|
||||||
|
if isinstance(password, bytes):
|
||||||
|
return password.decode(encoding='utf-8')
|
||||||
|
elif isinstance(password, str):
|
||||||
|
return password
|
||||||
|
|
||||||
|
# If is not bytes or str, we have a problem
|
||||||
|
raise OfflineImapError("Could not get a right password format for"
|
||||||
|
" repository %s. Type found: %s. "
|
||||||
|
"Please, open a bug." %
|
||||||
|
(self.name, type(password)),
|
||||||
|
OfflineImapError.ERROR.FOLDER)
|
||||||
|
|
||||||
# 4. Read password from ~/.netrc.
|
# 4. Read password from ~/.netrc.
|
||||||
try:
|
try:
|
||||||
netrcentry = netrc.netrc().authenticators(self.gethost())
|
netrcentry = netrc.netrc().authenticators(self.gethost())
|
||||||
|
Loading…
Reference in New Issue
Block a user