From bea855cb80e7033384ed3b0e2c2302a39ce406d3 Mon Sep 17 00:00:00 2001 From: Unrud Date: Tue, 6 Jun 2017 20:01:04 +0200 Subject: [PATCH] Improve file names used when uploading whole collection * Use 64 bit random sequence (extremely low chance of collisions) * Improve error message in case of collisions * Add file extension to names --- radicale/storage.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/radicale/storage.py b/radicale/storage.py index 3c3258a..ba54ac9 100644 --- a/radicale/storage.py +++ b/radicale/storage.py @@ -27,7 +27,6 @@ entry. import binascii import contextlib -import errno import json import os import pickle @@ -541,13 +540,14 @@ class Collection(BaseCollection): self._sync_directory(directory) @staticmethod - def _find_available_file_name(exists_fn): + def _find_available_file_name(exists_fn, suffix=""): # Prevent infinite loop - for _ in range(10000): - file_name = hex(getrandbits(32))[2:] + for _ in range(1000): + file_name = "%016x" % getrandbits(64) + suffix if not exists_fn(file_name): return file_name - raise FileExistsError(errno.EEXIST, "No usable file name found") + # something is wrong with the PRNG + raise RuntimeError("No unique random sequence found") @classmethod def _fsync(cls, fd): @@ -690,15 +690,19 @@ class Collection(BaseCollection): new_collection = vobject.iCalendar() for item in items: new_collection.add(item) + # href must comply to is_safe_filesystem_path_component + # and no file name collisions must exist between hrefs href = self._find_available_file_name( - vobject_items.get) + vobject_items.get, suffix=".ics") vobject_items[href] = new_collection self.upload_all_nonatomic(vobject_items) elif props.get("tag") == "VCARD": vobject_items = {} for card in collection: + # href must comply to is_safe_filesystem_path_component + # and no file name collisions must exist between hrefs href = self._find_available_file_name( - vobject_items.get) + vobject_items.get, suffix=".vcf") vobject_items[href] = card self.upload_all_nonatomic(vobject_items)