From d5666ce91de13923f939edaf0f23ac227fb7fc06 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Fri, 6 Jan 2012 13:05:08 +0100 Subject: [PATCH] Don't create invalid maildir names with lower case maildir flags If someone had a custom :2,a flag, adding a new flag would lead to the invalid maildir filename ...a:2,... due to regex deficiencies not coping with this. Fix this so we alway produce valid maildir names. Note that custom flags are still problematic: as the syncing to the remote IMAP server will fail, the next sync will assume that they have been removed from the remote IMAP side and they will be removed from the local Maildir then. We will need to think about how to handle this. At least, with this patch we won't lose standard flags and won't produce invalid maildir names. Signed-off-by: Sebastian Spaeth --- offlineimap/folder/Maildir.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/offlineimap/folder/Maildir.py b/offlineimap/folder/Maildir.py index 47f76e8..c9ea63d 100644 --- a/offlineimap/folder/Maildir.py +++ b/offlineimap/folder/Maildir.py @@ -64,13 +64,13 @@ class MaildirFolder(BaseFolder): self.root = root self.sep = sep self.messagelist = None - + # check if we should use a different infosep to support Win file systems self.wincompatible = self.config.getdefaultboolean( "Account "+self.accountname, "maildir-windows-compatible", False) self.infosep = '!' if self.wincompatible else ':' """infosep is the separator between maildir name and flag appendix""" - self.flagmatchre = re.compile(self.infosep + '2,([A-Z]+)') + self.flagmatchre = re.compile('(%s2,)(\w*)' % self.infosep) #self.ui is set in BaseFolder.init() # Cache the full folder path, as we use getfullname() very often self._fullname = os.path.join(self.getroot(), self.getname()) @@ -162,7 +162,7 @@ class MaildirFolder(BaseFolder): #identify flags in the path name flagmatch = self.flagmatchre.search(messagename) if flagmatch: - flags = set(flagmatch.group(1)) + flags = set(flagmatch.group(2)) else: flags = set() # 'filename' is 'dirannex/filename', e.g. cur/123,U=1,FMD5=1:2,S @@ -185,7 +185,7 @@ class MaildirFolder(BaseFolder): def cachemessagelist(self): if self.messagelist is None: self.messagelist = self._scanfolder() - + def getmessagelist(self): return self.messagelist @@ -259,7 +259,7 @@ class MaildirFolder(BaseFolder): self.savemessageflags(uid, flags) self.ui.debug('maildir', 'savemessage: returning uid %d' % uid) return uid - + def getmessageflags(self, uid): return self.messagelist[uid]['flags'] @@ -274,15 +274,14 @@ class MaildirFolder(BaseFolder): else: dir_prefix = 'new' - infostr = self.infosep - infomatch = re.search('(' + self.infosep + '.*)$', newname) - if infomatch: # If the info string is present.. - infostr = infomatch.group(1) - newname = newname.split(self.infosep)[0] # Strip off the info string. - infostr = re.sub('2,[A-Z]*', '', infostr) - infostr += '2,' + ''.join(sorted(flags)) + # Strip off existing infostring (preserving small letter flags, that + # dovecot uses) + infomatch = self.flagmatchre.search(newname) + if infomatch: + newname = newname[:-len(infomatch.group())] #strip off + infostr = '%s2,%s' % (self.infosep, ''.join(sorted(flags))) newname += infostr - + newfilename = os.path.join(dir_prefix, newname) if (newfilename != oldfilename): try: @@ -292,7 +291,7 @@ class MaildirFolder(BaseFolder): raise OfflineImapError("Can't rename file '%s' to '%s': %s" % ( oldfilename, newfilename, e[1]), OfflineImapError.ERROR.FOLDER) - + self.messagelist[uid]['flags'] = flags self.messagelist[uid]['filename'] = newfilename