require usernames and passwords to be UTF-8 encoded
- Learn to support UTF-8 characters where it was not supported for usernames and passwords (but for netrc). - Fix the types in the code for both py2 and py3: we now expect unicode for usernames and passwords. Unicode (UTF-8) is required only for variables with non-ASCII characters. Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
092264c8e7
commit
08e17de7e2
@ -590,9 +590,16 @@ type = IMAP
|
|||||||
# "getcredentials" that parses a file "filename" and returns the account
|
# "getcredentials" that parses a file "filename" and returns the account
|
||||||
# details for "hostname".
|
# details for "hostname".
|
||||||
#
|
#
|
||||||
|
#
|
||||||
#remotehosteval = getcredentials("filename", "hostname", "hostname")
|
#remotehosteval = getcredentials("filename", "hostname", "hostname")
|
||||||
|
#
|
||||||
|
# The returned value must be int type.
|
||||||
#remoteporteval = getcredentials("filename", "hostname", "port")
|
#remoteporteval = getcredentials("filename", "hostname", "port")
|
||||||
|
#
|
||||||
|
# The returned value must be unicode type.
|
||||||
#remoteusereval = getcredentials("filename", "hostname", "user")
|
#remoteusereval = getcredentials("filename", "hostname", "user")
|
||||||
|
#
|
||||||
|
# The returned value must be unicode type.
|
||||||
#remotepasseval = getcredentials("filename", "hostname", "passwd")
|
#remotepasseval = getcredentials("filename", "hostname", "passwd")
|
||||||
|
|
||||||
|
|
||||||
@ -742,9 +749,9 @@ remotehost = examplehost
|
|||||||
|
|
||||||
# This option stands in the [Repository RemoteExample] section.
|
# This option stands in the [Repository RemoteExample] section.
|
||||||
#
|
#
|
||||||
# Specify the remote user name.
|
# Specify the remote user name. Must be unicode.
|
||||||
#
|
#
|
||||||
remoteuser = username
|
remoteuser = u"username"
|
||||||
|
|
||||||
|
|
||||||
# This option stands in the [Repository RemoteExample] section.
|
# This option stands in the [Repository RemoteExample] section.
|
||||||
@ -760,7 +767,9 @@ remoteuser = username
|
|||||||
# mechanism, so consider using auth_mechanisms to prioritize PLAIN
|
# mechanism, so consider using auth_mechanisms to prioritize PLAIN
|
||||||
# or even make it the only mechanism to be tried.
|
# or even make it the only mechanism to be tried.
|
||||||
#
|
#
|
||||||
#remote_identity = authzuser
|
# Must be unicode type.
|
||||||
|
#
|
||||||
|
#remote_identity = u"authzuser"
|
||||||
|
|
||||||
|
|
||||||
# This option stands in the [Repository RemoteExample] section.
|
# This option stands in the [Repository RemoteExample] section.
|
||||||
@ -842,7 +851,7 @@ remoteuser = username
|
|||||||
#
|
#
|
||||||
# 2. The remote password stored in this file with the remotepass
|
# 2. The remote password stored in this file with the remotepass
|
||||||
# option. Any '%' needs to be encoded as '%%'. Example:
|
# option. Any '%' needs to be encoded as '%%'. Example:
|
||||||
# remotepass = mypassword
|
#remotepass = u"mypassword"
|
||||||
#
|
#
|
||||||
# 3. The remote password stored as a single line in an external
|
# 3. The remote password stored as a single line in an external
|
||||||
# file, which is referenced by the remotefile option. Example:
|
# file, which is referenced by the remotefile option. Example:
|
||||||
@ -1186,7 +1195,9 @@ type = Gmail
|
|||||||
#
|
#
|
||||||
# Specify the Gmail user name. This is the only mandatory parameter.
|
# Specify the Gmail user name. This is the only mandatory parameter.
|
||||||
#
|
#
|
||||||
remoteuser = username@gmail.com
|
# Must be unicode type.
|
||||||
|
#
|
||||||
|
remoteuser = u"username@gmail.com"
|
||||||
|
|
||||||
|
|
||||||
# This option stands in the [Repository GmailExample] section.
|
# This option stands in the [Repository GmailExample] section.
|
||||||
|
@ -154,6 +154,7 @@ class IMAPServer(object):
|
|||||||
|
|
||||||
def __getpassword(self):
|
def __getpassword(self):
|
||||||
"""Returns the server password or None"""
|
"""Returns the server password or None"""
|
||||||
|
|
||||||
if self.goodpassword != None: # use cached good one first
|
if self.goodpassword != None: # use cached good one first
|
||||||
return self.goodpassword
|
return self.goodpassword
|
||||||
|
|
||||||
@ -216,12 +217,14 @@ class IMAPServer(object):
|
|||||||
|
|
||||||
authc = self.username
|
authc = self.username
|
||||||
passwd = self.__getpassword()
|
passwd = self.__getpassword()
|
||||||
authz = ''
|
authz = b''
|
||||||
if self.user_identity != None:
|
if self.user_identity != None:
|
||||||
authz = self.user_identity
|
authz = self.user_identity
|
||||||
NULL = u'\x00'
|
# At this point all authz, authc and passwd are expected bytes encoded
|
||||||
retval = NULL.join((authz, authc, passwd)).encode('utf-8')
|
# in UTF-8.
|
||||||
logsafe_retval = NULL.join((authz, authc, "(passwd hidden for log)")).encode('utf-8')
|
NULL = b'\x00'
|
||||||
|
retval = NULL.join((authz, authc, passwd))
|
||||||
|
logsafe_retval = NULL.join((authz, authc, "(passwd hidden for log)"))
|
||||||
self.ui.debug('imap', '__plainhandler: returning %s'% logsafe_retval)
|
self.ui.debug('imap', '__plainhandler: returning %s'% logsafe_retval)
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# IMAP repository support
|
# IMAP repository support
|
||||||
# Copyright (C) 2002-2015 John Goerzen & contributors
|
# Copyright (C) 2002-2016 John Goerzen & contributors
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -21,6 +21,7 @@ from sys import exc_info
|
|||||||
import netrc
|
import netrc
|
||||||
import errno
|
import errno
|
||||||
import six
|
import six
|
||||||
|
import codecs
|
||||||
|
|
||||||
from offlineimap.repository.Base import BaseRepository
|
from offlineimap.repository.Base import BaseRepository
|
||||||
from offlineimap import folder, imaputil, imapserver, OfflineImapError
|
from offlineimap import folder, imaputil, imapserver, OfflineImapError
|
||||||
@ -129,7 +130,10 @@ class IMAPRepository(BaseRepository):
|
|||||||
(currently -- PLAIN) to inform server about the ID
|
(currently -- PLAIN) to inform server about the ID
|
||||||
we want to authorize as instead of our login name."""
|
we want to authorize as instead of our login name."""
|
||||||
|
|
||||||
return self.getconf('remote_identity', default=None)
|
identity = self.getconf('remote_identity', default=None)
|
||||||
|
if identity != None:
|
||||||
|
identity = identity.encode('UTF-8')
|
||||||
|
return identity
|
||||||
|
|
||||||
def get_auth_mechanisms(self):
|
def get_auth_mechanisms(self):
|
||||||
supported = ["GSSAPI", "XOAUTH2", "CRAM-MD5", "PLAIN", "LOGIN"]
|
supported = ["GSSAPI", "XOAUTH2", "CRAM-MD5", "PLAIN", "LOGIN"]
|
||||||
@ -159,12 +163,12 @@ class IMAPRepository(BaseRepository):
|
|||||||
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 != None:
|
if user != None:
|
||||||
return localeval.eval(user)
|
return localeval.eval(user).encode('UTF-8')
|
||||||
|
|
||||||
if self.config.has_option(self.getsection(), 'remoteuser'):
|
if self.config.has_option(self.getsection(), 'remoteuser'):
|
||||||
user = self.getconf('remoteuser')
|
user = self.getconf('remoteuser')
|
||||||
if user != None:
|
if user != None:
|
||||||
return user
|
return user.encode('UTF-8')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
netrcentry = netrc.netrc().authenticators(self.gethost())
|
netrcentry = netrc.netrc().authenticators(self.gethost())
|
||||||
@ -326,18 +330,18 @@ class IMAPRepository(BaseRepository):
|
|||||||
# 1. evaluate Repository 'remotepasseval'
|
# 1. evaluate Repository 'remotepasseval'
|
||||||
passwd = self.getconf('remotepasseval', None)
|
passwd = self.getconf('remotepasseval', None)
|
||||||
if passwd != None:
|
if passwd != None:
|
||||||
return self.localeval.eval(passwd)
|
return self.localeval.eval(passwd).encode('UTF-8')
|
||||||
# 2. read password from Repository 'remotepass'
|
# 2. read password from Repository 'remotepass'
|
||||||
password = self.getconf('remotepass', None)
|
password = self.getconf('remotepass', None)
|
||||||
if password != None:
|
if password != None:
|
||||||
return password
|
return password.encode('UTF-8')
|
||||||
# 3. read password from file specified in Repository 'remotepassfile'
|
# 3. read password from file specified in Repository 'remotepassfile'
|
||||||
passfile = self.getconf('remotepassfile', None)
|
passfile = self.getconf('remotepassfile', None)
|
||||||
if passfile != None:
|
if passfile != None:
|
||||||
fd = open(os.path.expanduser(passfile))
|
fd = codecs.open(os.path.expanduser(passfile), 'r', 'UTF-8')
|
||||||
password = fd.readline().strip()
|
password = fd.readline().strip()
|
||||||
fd.close()
|
fd.close()
|
||||||
return password
|
return password.encode('UTF-8')
|
||||||
# 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