diff --git a/radicale/storage.py b/radicale/storage.py index 58e78b9..89e06dc 100644 --- a/radicale/storage.py +++ b/radicale/storage.py @@ -173,7 +173,13 @@ def path_to_filesystem(root, *paths): for part in path.split("/"): if not is_safe_filesystem_path_component(part): raise UnsafePathError(part) + safe_path_parent = safe_path safe_path = os.path.join(safe_path, part) + # Check for conflicting files (e.g. case-insensitive file systems + # or short names on Windows file systems) + if os.path.lexists(safe_path): + if not part in os.listdir(safe_path_parent): + raise CollidingPathError(part) return safe_path @@ -183,6 +189,12 @@ class UnsafePathError(ValueError): super().__init__(message) +class CollidingPathError(ValueError): + def __init__(self, path): + message = "File name collision: %s" % path + super().__init__(message) + + class ComponentExistsError(ValueError): def __init__(self, path): message = "Component already exists: %s" % path @@ -470,8 +482,9 @@ class Collection(BaseCollection): cls._makedirs_synced(folder) try: filesystem_path = path_to_filesystem(folder, sane_path) - except ValueError: + except ValueError as e: # Path is unsafe + cls.logger.info(e) return # Check if the path exists and if it leads to a collection or an item