Skip to content

Commit 5b5fc8d

Browse files
authored
Merge pull request #1971 from pbiering/fix-issue-1970
Support issue 1970
2 parents c6b9756 + 8613f9d commit 5b5fc8d

File tree

5 files changed

+109
-1
lines changed

5 files changed

+109
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## 3.6.1.dev
44

55
* Fix: MOVE failing with URL-encoded destination header
6+
* Improve: add workaround to remove empty lines in item to avoid reject by vobject parser
67

78
## 3.6.0
89

radicale/item/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright © 2014 Jean-Marc Martins
55
# Copyright © 2008-2017 Guillaume Ayoub
66
# Copyright © 2017-2022 Unrud <unrud@outlook.com>
7-
# Copyright © 2024-2025 Peter Bieringer <pb@bieringer.de>
7+
# Copyright © 2024-2026 Peter Bieringer <pb@bieringer.de>
88
#
99
# This library is free software: you can redistribute it and/or modify
1010
# it under the terms of the GNU General Public License as published by
@@ -56,6 +56,8 @@ def read_components(s: str) -> List[vobject.base.Component]:
5656
# * 0x0A Line Feed
5757
# * 0x0D Carriage Return
5858
s = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F]', '', s)
59+
# Workaround delete all empty lines to avoid vobject parsing errors
60+
s = re.sub(r'(?m)^[ \t]*\r?\n', '', s)
5961
return list(vobject.readComponents(s, allowQP=True))
6062

6163

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
BEGIN:VCALENDAR
2+
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
3+
VERSION:2.0
4+
BEGIN:VTIMEZONE
5+
TZID:Europe/Paris
6+
X-LIC-LOCATION:Europe/Paris
7+
BEGIN:DAYLIGHT
8+
TZOFFSETFROM:+0100
9+
TZOFFSETTO:+0200
10+
TZNAME:CEST
11+
DTSTART:19700329T020000
12+
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
13+
END:DAYLIGHT
14+
BEGIN:STANDARD
15+
TZOFFSETFROM:+0200
16+
TZOFFSETTO:+0100
17+
TZNAME:CET
18+
DTSTART:19701025T030000
19+
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
20+
END:STANDARD
21+
END:VTIMEZONE
22+
BEGIN:VEVENT
23+
CREATED:20130902T150157Z
24+
LAST-MODIFIED:20130902T150158Z
25+
DTSTAMP:20130902T150158Z
26+
UID:event1
27+
SUMMARY:Event
28+
CATEGORIES:some_category1,another_category2
29+
DESCRIPTION:Line1
30+
Line2
31+
Line3
32+
ORGANIZER:mailto:unclesam@example.com
33+
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=TENTATIVE;CN=Jane Doe:MAILTO:janedoe@example.com
34+
ATTENDEE;ROLE=REQ-PARTICIPANT;DELEGATED-FROM="MAILTO:bob@host.com";PARTSTAT=ACCEPTED;CN=John Doe:MAILTO:johndoe@example.com
35+
DTSTART;TZID=Europe/Paris:20130901T180000
36+
DTEND;TZID=Europe/Paris:20130901T190000
37+
END:VEVENT
38+
END:VCALENDAR
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
BEGIN:VCALENDAR
2+
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
3+
VERSION:2.0
4+
BEGIN:VTIMEZONE
5+
TZID:Europe/Paris
6+
X-LIC-LOCATION:Europe/Paris
7+
BEGIN:DAYLIGHT
8+
TZOFFSETFROM:+0100
9+
TZOFFSETTO:+0200
10+
TZNAME:CEST
11+
DTSTART:19700329T020000
12+
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
13+
END:DAYLIGHT
14+
BEGIN:STANDARD
15+
TZOFFSETFROM:+0200
16+
TZOFFSETTO:+0100
17+
TZNAME:CET
18+
DTSTART:19701025T030000
19+
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
20+
END:STANDARD
21+
END:VTIMEZONE
22+
BEGIN:VEVENT
23+
CREATED:20130902T150157Z
24+
LAST-MODIFIED:20130902T150158Z
25+
DTSTAMP:20130902T150158Z
26+
UID:event1
27+
SUMMARY:Event having description with empty line
28+
CATEGORIES:some_category1,another_category2
29+
DESCRIPTION:Line1
30+
Line2
31+
32+
Line4
33+
ORGANIZER:mailto:unclesam@example.com
34+
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=TENTATIVE;CN=Jane Doe:MAILTO:janedoe@example.com
35+
ATTENDEE;ROLE=REQ-PARTICIPANT;DELEGATED-FROM="MAILTO:bob@host.com";PARTSTAT=ACCEPTED;CN=John Doe:MAILTO:johndoe@example.com
36+
DTSTART;TZID=Europe/Paris:20130901T180000
37+
DTEND;TZID=Europe/Paris:20130901T190000
38+
END:VEVENT
39+
END:VCALENDAR

radicale/tests/test_base.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,34 @@ def test_add_event(self) -> None:
144144
assert "Event" in answer
145145
assert "UID:event" in answer
146146

147+
def test_add_event_with_desc_ok(self) -> None:
148+
"""Add an event."""
149+
self.mkcalendar("/calendar.ics/")
150+
event = get_file_content("event_issue1970_ok.ics")
151+
path = "/calendar.ics/event_issue1970_ok.ics"
152+
self.put(path, event)
153+
_, headers, answer = self.request("GET", path, check=200)
154+
assert "ETag" in headers
155+
assert headers["Content-Type"] == "text/calendar; charset=utf-8"
156+
assert "DESCRIPTION" in answer
157+
assert "VEVENT" in answer
158+
assert "Event" in answer
159+
assert "UID:event" in answer
160+
161+
def test_add_event_with_desc_problem(self) -> None:
162+
"""Add an event."""
163+
self.mkcalendar("/calendar.ics/")
164+
event = get_file_content("event_issue1970_problem.ics")
165+
path = "/calendar.ics/event_issue1970_problem.ics"
166+
self.put(path, event)
167+
_, headers, answer = self.request("GET", path, check=200)
168+
assert "ETag" in headers
169+
assert headers["Content-Type"] == "text/calendar; charset=utf-8"
170+
assert "DESCRIPTION" in answer
171+
assert "VEVENT" in answer
172+
assert "Event" in answer
173+
assert "UID:event" in answer
174+
147175
def test_add_event_exceed_size(self) -> None:
148176
"""Add an event which is exceeding max-resource-size."""
149177
self.configure({"server": {"max_resource_size": 20}})

0 commit comments

Comments
 (0)