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 <Sebastian@SSpaeth.de>
This commit is contained in:
Sebastian Spaeth 2012-01-06 13:05:08 +01:00
parent 64f5e557bc
commit d5666ce91d

View File

@ -64,13 +64,13 @@ class MaildirFolder(BaseFolder):
self.root = root self.root = root
self.sep = sep self.sep = sep
self.messagelist = None self.messagelist = None
# check if we should use a different infosep to support Win file systems
self.wincompatible = self.config.getdefaultboolean( self.wincompatible = self.config.getdefaultboolean(
"Account "+self.accountname, "maildir-windows-compatible", False) "Account "+self.accountname, "maildir-windows-compatible", False)
self.infosep = '!' if self.wincompatible else ':' self.infosep = '!' if self.wincompatible else ':'
"""infosep is the separator between maildir name and flag appendix""" """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() #self.ui is set in BaseFolder.init()
# Cache the full folder path, as we use getfullname() very often # Cache the full folder path, as we use getfullname() very often
self._fullname = os.path.join(self.getroot(), self.getname()) self._fullname = os.path.join(self.getroot(), self.getname())
@ -162,7 +162,7 @@ class MaildirFolder(BaseFolder):
#identify flags in the path name #identify flags in the path name
flagmatch = self.flagmatchre.search(messagename) flagmatch = self.flagmatchre.search(messagename)
if flagmatch: if flagmatch:
flags = set(flagmatch.group(1)) flags = set(flagmatch.group(2))
else: else:
flags = set() flags = set()
# 'filename' is 'dirannex/filename', e.g. cur/123,U=1,FMD5=1:2,S # 'filename' is 'dirannex/filename', e.g. cur/123,U=1,FMD5=1:2,S
@ -185,7 +185,7 @@ class MaildirFolder(BaseFolder):
def cachemessagelist(self): def cachemessagelist(self):
if self.messagelist is None: if self.messagelist is None:
self.messagelist = self._scanfolder() self.messagelist = self._scanfolder()
def getmessagelist(self): def getmessagelist(self):
return self.messagelist return self.messagelist
@ -259,7 +259,7 @@ class MaildirFolder(BaseFolder):
self.savemessageflags(uid, flags) self.savemessageflags(uid, flags)
self.ui.debug('maildir', 'savemessage: returning uid %d' % uid) self.ui.debug('maildir', 'savemessage: returning uid %d' % uid)
return uid return uid
def getmessageflags(self, uid): def getmessageflags(self, uid):
return self.messagelist[uid]['flags'] return self.messagelist[uid]['flags']
@ -274,15 +274,14 @@ class MaildirFolder(BaseFolder):
else: else:
dir_prefix = 'new' dir_prefix = 'new'
infostr = self.infosep # Strip off existing infostring (preserving small letter flags, that
infomatch = re.search('(' + self.infosep + '.*)$', newname) # dovecot uses)
if infomatch: # If the info string is present.. infomatch = self.flagmatchre.search(newname)
infostr = infomatch.group(1) if infomatch:
newname = newname.split(self.infosep)[0] # Strip off the info string. newname = newname[:-len(infomatch.group())] #strip off
infostr = re.sub('2,[A-Z]*', '', infostr) infostr = '%s2,%s' % (self.infosep, ''.join(sorted(flags)))
infostr += '2,' + ''.join(sorted(flags))
newname += infostr newname += infostr
newfilename = os.path.join(dir_prefix, newname) newfilename = os.path.join(dir_prefix, newname)
if (newfilename != oldfilename): if (newfilename != oldfilename):
try: try:
@ -292,7 +291,7 @@ class MaildirFolder(BaseFolder):
raise OfflineImapError("Can't rename file '%s' to '%s': %s" % ( raise OfflineImapError("Can't rename file '%s' to '%s': %s" % (
oldfilename, newfilename, e[1]), oldfilename, newfilename, e[1]),
OfflineImapError.ERROR.FOLDER) OfflineImapError.ERROR.FOLDER)
self.messagelist[uid]['flags'] = flags self.messagelist[uid]['flags'] = flags
self.messagelist[uid]['filename'] = newfilename self.messagelist[uid]['filename'] = newfilename