Skip to content

Commit e1b3386

Browse files
committed
Remove quotes from safe characters
1 parent 5fc38a8 commit e1b3386

File tree

3 files changed

+108
-1
lines changed

3 files changed

+108
-1
lines changed

src/icalendar/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def validate_param_value(value, quoted=True):
129129

130130
# chars presence of which in parameter value will be cause the value
131131
# to be enclosed in double-quotes
132-
QUOTABLE = re.compile("[,;: ’']")
132+
QUOTABLE = re.compile("[,;:]")
133133

134134

135135
def dquote(val, always_quote=False):
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
BEGIN:VCALENDAR
2+
METHOD:PUBLISH
3+
PRODID:Microsoft Exchange Server 2010
4+
VERSION:2.0
5+
BEGIN:VTIMEZONE
6+
TZID:Eastern Standard Time
7+
BEGIN:STANDARD
8+
DTSTART:16010101T020000
9+
TZOFFSETFROM:-0400
10+
TZOFFSETTO:-0500
11+
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
12+
END:STANDARD
13+
BEGIN:DAYLIGHT
14+
DTSTART:16010101T020000
15+
TZOFFSETFROM:-0500
16+
TZOFFSETTO:-0400
17+
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3
18+
END:DAYLIGHT
19+
END:VTIMEZONE
20+
BEGIN:VEVENT
21+
22+
SUMMARY:Anonymous Test Event for TZID
23+
DTSTART;TZID=Eastern Standard Time:20241028T170000
24+
DTEND;TZID=Eastern Standard Time:20241028T180000
25+
DTSTAMP:20250514T023916Z
26+
END:VEVENT
27+
END:VCALENDAR
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""Quoting the TZID parameter creates compatibility problems.
2+
3+
See https://github.com/collective/icalendar/issues/836
4+
5+
:rfc:`5545`:
6+
7+
.. code-block:: text
8+
9+
param-value = paramtext / quoted-string
10+
paramtext = *SAFE-CHAR
11+
quoted-string = DQUOTE *QSAFE-CHAR DQUOTE
12+
SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E
13+
/ NON-US-ASCII
14+
; Any character except CONTROL, DQUOTE, ";", ":", ","
15+
NON-US-ASCII = UTF8-2 / UTF8-3 / UTF8-4
16+
; UTF8-2, UTF8-3, and UTF8-4 are defined in [RFC3629]
17+
18+
"""
19+
from datetime import datetime, time
20+
from icalendar import Event, Parameters, vDDDTypes, vDatetime, vPeriod, vTime
21+
import pytest
22+
23+
from icalendar.prop import vDDDLists
24+
25+
# All the controls except HTAB
26+
CONTROL = {
27+
i for i in range(256) if 0x00 <= i <= 0x08 or 0x0A <= i <= 0x1F or i == 0x7F
28+
}
29+
30+
# Any character except CONTROL, DQUOTE, ";", ":", ","
31+
SAFE_CHAR = set(range(256)) - CONTROL - set(b'";:,')
32+
33+
param_tzid = pytest.mark.parametrize(
34+
"tzid",
35+
[
36+
"Europe/London",
37+
"Eastern Standard Time",
38+
]
39+
)
40+
41+
@param_tzid
42+
@pytest.mark.parametrize(
43+
"vdt",
44+
[
45+
vDatetime(datetime(2024, 10, 11, 12, 0)),
46+
vTime(time(23, 59, 59)),
47+
vDDDTypes(datetime(2024, 10, 11, 12, 0)),
48+
vPeriod((datetime(2024, 10, 11, 12, 0), datetime(2024, 10, 11, 13, 0))),
49+
vDDDLists([datetime(2024, 10, 11, 12, 0)]),
50+
]
51+
)
52+
def test_parameter_is_not_quoted_when_not_needed(tzid, vdt):
53+
"""Check that serializing the value works without quoting."""
54+
e = Event()
55+
vdt.params["TZID"] = tzid
56+
e["DTSTART"] = vdt
57+
ics = e.to_ical().decode()
58+
print(ics)
59+
assert tzid in ics
60+
assert f'"{tzid}' not in ics
61+
assert f'{tzid}"' not in ics
62+
63+
64+
@pytest.mark.parametrize(
65+
"safe_char",
66+
list(map(chr, sorted(SAFE_CHAR)))
67+
)
68+
def test_safe_char_is_not_escaped(safe_char):
69+
"""Check that paramerter serialization is without quotes for safe chars."""
70+
params = Parameters(tzid=safe_char)
71+
result = params.to_ical().decode()
72+
assert '"' not in result
73+
74+
75+
def test_get_calendar_and_serialize_it_wihtout_quotes(calendars):
76+
"""The example calendar should not contain the timezone with quotes."""
77+
ics = calendars.issue_836_do_not_quote_tzid.to_ical().decode()
78+
assert '"Eastern Standard' not in ics
79+
assert 'Standard Time"' not in ics
80+
assert "Eastern Standard Time" in ics

0 commit comments

Comments
 (0)