fix(ics): reject an RRULE carrying both UNTIL and COUNT (#225)
EventRecurrence.parse ends with two global checks, not one: a missing FREQ throws, and so does UNTIL together with COUNT. Only the first was mirrored, so a rule with both still threw out of insert — the failure sanitizeRrule exists to prevent. UNTIL is kept; it bounds the series at a date a stale COUNT can't outrun. Also mark a part that carries text but no '=' as a repair. It took the branch meant for a trailing ';', so the rule was altered while the user was told nothing had changed.
This commit is contained in:
@@ -80,10 +80,12 @@ fun sanitizeRrule(raw: String?): SanitizedRrule {
|
||||
}
|
||||
|
||||
for (part in rule.split(';')) {
|
||||
// A stray separator ("FREQ=DAILY;") normalises away; nothing was lost.
|
||||
// A part that carries text but no '=' ("FREQ=WEEKLY;BYDAY") is a part
|
||||
// being dropped, so it falls through and marks the rule repaired.
|
||||
if (part.isBlank()) continue
|
||||
val key = part.substringBefore('=', "").trim().uppercase()
|
||||
val value = if ('=' in part) part.substringAfter('=').trim() else ""
|
||||
// A stray separator ("FREQ=DAILY;") normalises away; nothing was lost.
|
||||
if (key.isEmpty() && value.isEmpty()) continue
|
||||
val kept = when {
|
||||
key.isEmpty() || value.isEmpty() -> null
|
||||
key == "FREQ" ->
|
||||
@@ -105,6 +107,15 @@ fun sanitizeRrule(raw: String?): SanitizedRrule {
|
||||
}
|
||||
if (kept == null) repaired = true else parts += kept
|
||||
}
|
||||
// `EventRecurrence.parse` ends with *two* global checks, not one: a missing
|
||||
// FREQ throws, and so does an UNTIL that arrives together with a COUNT. A
|
||||
// rule carrying both is malformed per RFC 5545 §3.3.10 but real producers
|
||||
// emit it, and left alone it would throw straight out of `insert` — the very
|
||||
// failure this function exists to prevent. UNTIL is kept: it bounds the
|
||||
// series at an absolute date, so a stale COUNT can't over-generate past it.
|
||||
if (parts.any { it.startsWith("UNTIL=") }) {
|
||||
if (parts.removeAll { it.startsWith("COUNT=") }) repaired = true
|
||||
}
|
||||
return if (freqSeen) {
|
||||
SanitizedRrule(rule = parts.joinToString(";"), repaired = repaired)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user