Skip to content

Fix incorrect unfolding of folded lines for vCard 2.1 imports (#9647) - #10218

Merged
alecpl merged 2 commits into
roundcube:masterfrom
dodjango:fix/vcard-2.1-unfolding
Jun 7, 2026
Merged

Fix incorrect unfolding of folded lines for vCard 2.1 imports (#9647)#10218
alecpl merged 2 commits into
roundcube:masterfrom
dodjango:fix/vcard-2.1-unfolding

Conversation

@dodjango

@dodjango dodjango commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #9647.

vCard line unfolding was hardcoded to the RFC 2425 rule used by vCard 3.0/4.0, which drops the folding whitespace entirely. vCard 2.1 instead follows RFC 822, where "CRLF immediately followed by a LWSP-char is equivalent to the LWSP-char" — i.e. the folding whitespace must be kept.

As a result, importing a folded vCard 2.1 value such as:

NOTE:an
 example

produced anexample instead of an example. Multi-word notes, organizations, etc. got their words fused together on import.

Changes

  • Extract a version-aware unfold() helper in rcube_vcard.
  • For VERSION:2.1, keep the single folding whitespace; otherwise behave exactly as before (drop it, per RFC 2425).
  • Use the helper at both unfolding sites (vcard_decode() and detect_encoding()), mirroring how vcard: Fix whitespace handling in line cont's #9637 fixed the related 3.0/4.0 whitespace bug.

Tests

  • Added test_parse_v21_continuation_line_keeps_whitespace to tests/Framework/VCardTest.php, alongside the existing 3.0 continuation-line test.
  • Full VCardTest suite passes; the existing 3.0/4.0 behaviour is unchanged.

Notes

This complements #9637 (which fixed the analogous whitespace handling for vCard 3.0/4.0). See also sabre/vobject#690 for the same distinction.

…ube#9647)

vCard line unfolding was hardcoded to the RFC 2425 rule used by vCard
3.0/4.0, which drops the folding whitespace entirely. vCard 2.1 follows
RFC 822, where a CRLF immediately followed by a LWSP-char is equivalent
to that LWSP-char, i.e. the folding whitespace must be kept.

As a result, a folded value such as

    NOTE:an
     example

was imported as "anexample" instead of "an example".

Extract a version-aware unfold() helper and use it in both vcard_decode()
and detect_encoding(), keeping the folding whitespace for vCard 2.1 while
preserving the existing behaviour for 3.0/4.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@dodjango

dodjango commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Friendly ping — this PR is ready for review whenever a maintainer has a moment. 🙏

A note on CI: the only red checks on the previous run were two Windows / PHP Unit jobs, and both were transient infrastructure failures unrelated to this change:

  • Windows / PHP 8.1 — failed in the Setup PHP step (runner setup)
  • Windows / PHP 8.3composer could not reach git.kolab.org to clone php-net_ldap3 (network timeout)

Everything substantive passed — Coding Style, Static Analysis, and the full Unit / E2E / Message Rendering matrix on Linux PHP 8.1–8.5 (plus Windows PHP 8.2/8.4/8.5).

I've pushed an empty commit to re-trigger CI, but the new runs are sitting in action_required (awaiting maintainer approval to run). Could a maintainer approve the workflows and take a look when convenient? Happy to address any feedback. Thanks!

@alecpl
alecpl merged commit 3f3d26f into roundcube:master Jun 7, 2026
17 checks passed
alecpl pushed a commit that referenced this pull request Jun 7, 2026
…#10218)

* Fix incorrect unfolding of folded lines for vCard 2.1 imports (#9647)

vCard line unfolding was hardcoded to the RFC 2425 rule used by vCard
3.0/4.0, which drops the folding whitespace entirely. vCard 2.1 follows
RFC 822, where a CRLF immediately followed by a LWSP-char is equivalent
to that LWSP-char, i.e. the folding whitespace must be kept.

As a result, a folded value such as

    NOTE:an
     example

was imported as "anexample" instead of "an example".

Extract a version-aware unfold() helper and use it in both vcard_decode()
and detect_encoding(), keeping the folding whitespace for vCard 2.1 while
preserving the existing behaviour for 3.0/4.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* ci: re-trigger checks (transient Windows infra failures)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
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.

Contacts import: vCard 2.1: Incorrect unfolding

2 participants