Repair nonascii UIDs

This commit is contained in:
Markus Unterwaditzer 2015-06-16 00:15:02 +02:00
parent 3a8d5aed77
commit 1730cc34c9
2 changed files with 37 additions and 16 deletions

View file

@ -23,6 +23,16 @@ def test_repair_uids():
assert uid1 != uid2 assert uid1 != uid2
def test_repair_nonascii_uids():
s = MemoryStorage()
href, etag = s.upload(Item(u'BEGIN:VCARD\nUID:äää\nEND:VCARD'))
assert s.get(href)[0].uid == u'äää'
repair_storage(s)
newuid = s.get(href)[0].uid
assert newuid != u'äää'
assert newuid.encode('ascii', 'ignore').decode('ascii') == newuid
def test_full(tmpdir, runner): def test_full(tmpdir, runner):
runner.write_with_general(dedent(''' runner.write_with_general(dedent('''
[storage foo] [storage foo]

View file

@ -676,27 +676,38 @@ def repair_storage(storage):
.format(href)) .format(href))
continue continue
if item.uid is None or item.uid in seen_uids: if item.uid is None:
if item.uid is None: cli_logger.warning('No UID, assigning random one.')
cli_logger.warning('No UID, assigning random one.') changed = reroll_uid(parsed) or changed
else: elif item.uid in seen_uids:
cli_logger.warning('Duplicate UID, reassigning random one.') cli_logger.warning('Duplicate UID, assigning random one.')
changed = reroll_uid(parsed) or changed
new_uid = uuid.uuid4() elif item.uid.encode('ascii', 'ignore').decode('ascii') != item.uid:
stack = [parsed] cli_logger.warning('UID is non-ascii, assigning, random one.')
while stack: changed = reroll_uid(parsed) or changed
component = stack.pop()
if component.name in ('VEVENT', 'VTODO', 'VJOURNAL', 'VCARD'):
component['UID'] = new_uid
changed = True
else:
stack.extend(component.subcomponents)
new_item = Item(u'\r\n'.join(parsed.dump_lines())) new_item = Item(u'\r\n'.join(parsed.dump_lines()))
assert new_item.uid assert new_item.uid
seen_uids.add(new_item.uid) seen_uids.add(new_item.uid)
if changed: if changed:
storage.update(href, new_item, etag) try:
storage.update(href, new_item, etag)
except Exception:
cli_logger.exception('Server rejected new item.')
def reroll_uid(component):
new_uid = uuid.uuid4()
stack = [component]
changed = False
while stack:
component = stack.pop()
if component.name in ('VEVENT', 'VTODO', 'VJOURNAL', 'VCARD'):
component['UID'] = new_uid
changed = True
else:
stack.extend(component.subcomponents)
return changed
def assert_permissions(path, wanted): def assert_permissions(path, wanted):