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
This commit is contained in:
Unrud 2017-06-06 20:01:04 +02:00
parent a6a3756e05
commit bea855cb80

View File

@ -27,7 +27,6 @@ entry.
import binascii import binascii
import contextlib import contextlib
import errno
import json import json
import os import os
import pickle import pickle
@ -541,13 +540,14 @@ class Collection(BaseCollection):
self._sync_directory(directory) self._sync_directory(directory)
@staticmethod @staticmethod
def _find_available_file_name(exists_fn): def _find_available_file_name(exists_fn, suffix=""):
# Prevent infinite loop # Prevent infinite loop
for _ in range(10000): for _ in range(1000):
file_name = hex(getrandbits(32))[2:] file_name = "%016x" % getrandbits(64) + suffix
if not exists_fn(file_name): if not exists_fn(file_name):
return 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 @classmethod
def _fsync(cls, fd): def _fsync(cls, fd):
@ -690,15 +690,19 @@ class Collection(BaseCollection):
new_collection = vobject.iCalendar() new_collection = vobject.iCalendar()
for item in items: for item in items:
new_collection.add(item) 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( href = self._find_available_file_name(
vobject_items.get) vobject_items.get, suffix=".ics")
vobject_items[href] = new_collection vobject_items[href] = new_collection
self.upload_all_nonatomic(vobject_items) self.upload_all_nonatomic(vobject_items)
elif props.get("tag") == "VCARD": elif props.get("tag") == "VCARD":
vobject_items = {} vobject_items = {}
for card in collection: 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( href = self._find_available_file_name(
vobject_items.get) vobject_items.get, suffix=".vcf")
vobject_items[href] = card vobject_items[href] = card
self.upload_all_nonatomic(vobject_items) self.upload_all_nonatomic(vobject_items)