DavUtils.lastSegment (core/src/main/kotlin/at/bitfire/davdroid/util/DavUtils.kt) returns "/" in two distinct cases:
- the URL has no path segments at all (e.g.
https://example.com → "/"), and
- the URL's last raw path segment is
%2F, which decodes to a literal / character.
These are indistinguishable to callers. For display-only call sites (HomeSet.title() etc) this is harmless. But InternalMemberState.fileName (and anything that derives a local storage identity from it, e.g. SyncManager.decideDownload/findByName) relies on the same helper, so a remote member whose name decodes to a literal / would collide with the "no segment" sentinel.
Found while auditing decode/encode consistency for #2755's listChanges extraction (see core/src/test/kotlin/at/bitfire/davdroid/util/DavUtilsTest.kt:58, which pins the current "/"-for-empty-path behavior).
Possible fix:
- Make
Url.lastSegment nullable (String?), returning null only for a truly empty path; push the ?: "/" fallback into the display call sites that want it.
- Make sure that the same helpers are always used to extract the file name from an URL, and to append a file name to a collection URL.
- Probably unify with dav4jvm helpers.
DavUtils.lastSegment(core/src/main/kotlin/at/bitfire/davdroid/util/DavUtils.kt) returns"/"in two distinct cases:https://example.com→"/"), and%2F, which decodes to a literal/character.These are indistinguishable to callers. For display-only call sites (
HomeSet.title()etc) this is harmless. ButInternalMemberState.fileName(and anything that derives a local storage identity from it, e.g.SyncManager.decideDownload/findByName) relies on the same helper, so a remote member whose name decodes to a literal/would collide with the "no segment" sentinel.Found while auditing decode/encode consistency for #2755's
listChangesextraction (seecore/src/test/kotlin/at/bitfire/davdroid/util/DavUtilsTest.kt:58, which pins the current"/"-for-empty-path behavior).Possible fix:
Url.lastSegmentnullable (String?), returningnullonly for a truly empty path; push the?: "/"fallback into the display call sites that want it.