diff options
author | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2013-07-05 17:09:53 +0100 |
---|---|---|
committer | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2013-07-05 20:25:15 +0100 |
commit | 643a625bd75bcdc098b3c04ed7366207efb0dad0 (patch) | |
tree | d62c585ad08201dae2ab0b0b482b46e3ef7cdccb | |
parent | aa1b0da1dcca7cd0572ddfb88abed84490c7b383 (diff) | |
download | pykolab-643a625bd75bcdc098b3c04ed7366207efb0dad0.tar.gz |
Make sure folder names are utf-7 encoded
-rw-r--r-- | pykolab/imap/__init__.py | 17 | ||||
-rw-r--r-- | pykolab/imap_utf7.py | 87 |
2 files changed, 99 insertions, 5 deletions
diff --git a/pykolab/imap/__init__.py b/pykolab/imap/__init__.py index fa71014..8855909 100644 --- a/pykolab/imap/__init__.py +++ b/pykolab/imap/__init__.py @@ -243,6 +243,10 @@ class IMAP(object): else: raise AttributeError, _("%r has no attribute %s") % (self,name) + def folder_utf7(self, folder): + from pykolab import imap_utf7 + return imap_utf7.encode(folder_path) + def get_metadata(self, folder): """ Obtain all metadata entries on a folder @@ -328,7 +332,7 @@ class IMAP(object): shared = False metadata_path = metadata_path.replace('/private/', '/') - self.imap._setannotation(folder, metadata_path, metadata_value, shared) + self.imap._setannotation(self.folder_utf7(folder), metadata_path, metadata_value, shared) def shared_folder_create(self, folder_path, server=None): """ @@ -478,9 +482,12 @@ class IMAP(object): folder_name = "%s%s" % (personal, folder_name) try: - self.imap.cm(folder_name) + self.create_folder(folder_name) except: log.warning(_("Mailbox already exists: %s") % (folder_name)) + if conf.debuglevel > 8: + import traceback + traceback.print_exc() continue if additional_folders[additional_folder].has_key("annotations"): @@ -625,7 +632,7 @@ class IMAP(object): """ Check if the environment has a folder named folder. """ - folders = self.imap.lm(folder) + folders = self.imap.lm(self.folder_utf7(folder)) log.debug(_("Looking for folder '%s', we found folders: %r") % (folder,folders), level=8) # Greater then one, this folder may have subfolders. if len(folders) > 0: @@ -653,7 +660,7 @@ class IMAP(object): "%s") % (rights,subject,folder), level=8) self.set_acl( - folder, + self.folder_utf7(folder), "%s" % (subject), "%s" % (rights) ) @@ -664,7 +671,7 @@ class IMAP(object): "%s") % (rights,subject,folder), level=8) self.set_acl( - folder, + self.folder_utf7(folder), "%s" % (subject), "" ) diff --git a/pykolab/imap_utf7.py b/pykolab/imap_utf7.py new file mode 100644 index 0000000..6a670b5 --- /dev/null +++ b/pykolab/imap_utf7.py @@ -0,0 +1,87 @@ +# The contents of this file has been derived code from the Twisted project +# (http://twistedmatrix.com/). The original author is Jp Calderone. + +# Twisted project license follows: + +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +class FolderNameError(ValueError): + pass + + +def encode(s): + if isinstance(s, str) and sum(n for n in (ord(c) for c in s) if n > 127): + raise FolderNameError("%r contains characters not valid in a str folder name. " + "Convert to unicode first?" % s) + + r = [] + _in = [] + for c in s: + if ord(c) in (range(0x20, 0x26) + range(0x27, 0x7f)): + if _in: + r.extend(['&', modified_base64(''.join(_in)), '-']) + del _in[:] + r.append(str(c)) + elif c == '&': + if _in: + r.extend(['&', modified_base64(''.join(_in)), '-']) + del _in[:] + r.append('&-') + else: + _in.append(c) + if _in: + r.extend(['&', modified_base64(''.join(_in)), '-']) + return ''.join(r) + + +def decode(s): + r = [] + decode = [] + for c in s: + if c == '&' and not decode: + decode.append('&') + elif c == '-' and decode: + if len(decode) == 1: + r.append('&') + else: + r.append(modified_unbase64(''.join(decode[1:]))) + decode = [] + elif decode: + decode.append(c) + else: + r.append(c) + if decode: + r.append(modified_unbase64(''.join(decode[1:]))) + out = ''.join(r) + + if not isinstance(out, unicode): + out = unicode(out, 'latin-1') + return out + + +def modified_base64(s): + s_utf7 = s.encode('utf-7') + return s_utf7[1:-1].replace('/', ',') + + +def modified_unbase64(s): + s_utf7 = '+' + s.replace(',', '/') + '-' + return s_utf7.decode('utf-7') |