Skip to content

fix: do not split flat text values on unescaped commas - #797

Open
odolbeau wants to merge 1 commit into
sabre-io:masterfrom
odolbeau:fix/flat-text-commas
Open

odolbeau wants to merge 1 commit into
sabre-io:masterfrom
odolbeau:fix/flat-text-commas

Conversation

@odolbeau

@odolbeau odolbeau commented Oct 2, 2026

Copy link
Copy Markdown

Property\FlatText represents single-value text properties: NOTE, FN, TITLE, EMAIL… in vCard, and SUMMARY, DESCRIPTION, LOCATION… in iCalendar. Its documentation says unescaped commas "are not delimiters". Yet it inherits Text::setRawMimeDirValue(), which splits values on them.

RFC 6350 and RFC 5545 require commas in text to be escaped, but many producers don't. When they don't, the value is split into several parts. That breaks reading in two ways:

  • getValue() returns the value escaped again. For multi-part values, Property::getValue() returns getRawMimeDirValue(), so newlines come back as a literal \n, and backslashes and semicolons come back escaped:

    Input getValue() before after
    NOTE:Line 1\nLine 2 Line 1⏎Line 2 unchanged
    NOTE:Line 1\nLine 2, and more Line 1\nLine 2, and more (literal \n) Line 1⏎Line 2, and more
  • jCard/jCal gets several values where there is one: FN:Doe, Jane gives ["fn", {}, "text", "Doe", " Jane"].

Change

FlatText::setRawMimeDirValue() unescapes the value without splitting it.

As a result, an unescaped comma is now written back escaped (FN:Doe\, Jane), as the RFCs require.

LineFoldingIssueTest relied on the unescaped comma being written back as is. Its data originally had TEST\, TEST, and bedefa1 ("Tweaked test to come out correctly") removed the backslash so that the output matched the input. This PR restores the escaped comma, checks the value, and expects the line folded at 75 octets, since it is now one octet longer.

Tests

tests/VObject/Property/FlatTextTest.php covers a vCard NOTE, an iCalendar DESCRIPTION, an escaped comma, the jCard value, and writing. Four of its tests fail without the fix.

🤖 Generated with Claude Code

FlatText inherited Text::setRawMimeDirValue(), which splits values on
unescaped commas, although its documentation says they are not
delimiters. getValue() then returned the value escaped again (newlines
as a literal \n), and jCard got several values for one.

LineFoldingIssueTest gets back the escaped comma its data had before
bedefa1, and expects the line folded since it is one octet longer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant