Implement RFC 6868 caret encoding for parameter values - #969
Conversation
A newline in a property parameter value made Calendar.Load(Serialize(cal)) throw: the newline terminated the content line, so the library emitted output its own parser rejected. A DQUOTE in a parameter value was silently stripped. Add a symmetric RFC 6868 codec: encode ^ -> ^^, DQUOTE -> ^', newline -> ^n on serialization (§3.1), and the exact inverse when parsing parameter values (§3.2), each a single left-to-right pass. This preserves the section's "parameter values MUST NOT contain DQUOTE" constraint without data loss.
|
|
@gaoflow, you appear to be mass committing to a bunch of repos. Does this issue directly affect you in any way? Do you know which major calendar services implement this? |
|
Hi @maknapp — fair question. Yes, I've been sending correctness fixes across a number of libraries; the account is AI-assisted (an agent finds and drafts the fix) but run under my direction, and I'm accountable for everything that goes in, so I'm glad to drop anything that isn't wanted. I don't have a production dependency on Ical.Net here — I found this while auditing the serializer against RFC 6868/5545, where a parameter value containing a double-quote or newline currently can't round-trip. I don't have a survey of which calendar clients decode 6868, so if the real-world payoff feels too thin, I'm fine with you closing it — no argument. |



A newline in a property parameter value makes
Calendar.Load(Serialize(cal))throw: the raw newline terminates the content line, so ical.net emits output its own parser rejects.RFC 6868 is the standard remedy and was unimplemented. This adds the symmetric codec: encode
^->^^, DQUOTE->^', newline->^non serialization (§3.1) and the exact inverse when parsing parameter values (§3.2), each a single left-to-right pass.DQUOTE was previously stripped, under a comment that parameter values MUST NOT contain DQUOTE. RFC 6868
^'keeps that guarantee (no literal DQUOTE reaches the wire) while round-tripping the character instead of dropping it, so I implemented that half too.Tests cover
decode(encode(v)) == vfor^, newline, DQUOTE, a literal^n/^^and mixed values, theLoad(Serialize())round-trip through the public API, and that plain values stay byte-identical. Full suite passes on net10.0; net8.0/net48 build (no net8 runtime on my machine to run them).