Gracefully parse iCal parameters with colons
According to RFC 5545, iCalendar content lines can have optional parameters, which can be quoted strings containing colons (":"). Make sure that such colons are not interpreted as delimiters marking the start of the value string. Also, add a test case that covers this corner case. Reported-by: Håkan Jerning <jerning@home.se> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
3375fddb4e
commit
e4e2e0eb20
36
src/ical.c
36
src/ical.c
@ -670,6 +670,21 @@ static long ical_compute_rpt_until(long start, ical_rpt_t * rpt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip to the value part of an iCalendar content line.
|
||||||
|
*/
|
||||||
|
static char *ical_get_value(char *p)
|
||||||
|
{
|
||||||
|
for (; *p != ':'; p++) {
|
||||||
|
if (*p == '\0')
|
||||||
|
return NULL;
|
||||||
|
if (*p == '"')
|
||||||
|
for (p++; *p != '"'; p++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read a recurrence rule from an iCalendar RRULE string.
|
* Read a recurrence rule from an iCalendar RRULE string.
|
||||||
*
|
*
|
||||||
@ -717,14 +732,13 @@ static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr,
|
|||||||
ical_rpt_t *rpt;
|
ical_rpt_t *rpt;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = strchr(rrulestr, ':');
|
p = ical_get_value(rrulestr);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ical_log(log, ICAL_VEVENT, itemline,
|
ical_log(log, ICAL_VEVENT, itemline,
|
||||||
_("recurrence rule malformed."));
|
_("recurrence rule malformed."));
|
||||||
(*noskipped)++;
|
(*noskipped)++;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
p++;
|
|
||||||
|
|
||||||
rpt = mem_malloc(sizeof(ical_rpt_t));
|
rpt = mem_malloc(sizeof(ical_rpt_t));
|
||||||
memset(rpt, 0, sizeof(ical_rpt_t));
|
memset(rpt, 0, sizeof(ical_rpt_t));
|
||||||
@ -807,14 +821,13 @@ ical_read_exdate(llist_t * exc, FILE * log, char *exstr,
|
|||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
|
|
||||||
p = strchr(exstr, ':');
|
p = ical_get_value(exstr);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ical_log(log, ICAL_VEVENT, itemline,
|
ical_log(log, ICAL_VEVENT, itemline,
|
||||||
_("recurrence exception dates malformed."));
|
_("recurrence exception dates malformed."));
|
||||||
(*noskipped)++;
|
(*noskipped)++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p++;
|
|
||||||
|
|
||||||
while ((q = strchr(p, ',')) != NULL) {
|
while ((q = strchr(p, ',')) != NULL) {
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
@ -835,14 +848,13 @@ static char *ical_read_note(char *line, unsigned *noskipped,
|
|||||||
{
|
{
|
||||||
char *p, *notestr, *note;
|
char *p, *notestr, *note;
|
||||||
|
|
||||||
p = strchr(line, ':');
|
p = ical_get_value(line);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ical_log(log, item_type, itemline,
|
ical_log(log, item_type, itemline,
|
||||||
_("description malformed."));
|
_("description malformed."));
|
||||||
(*noskipped)++;
|
(*noskipped)++;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
p++;
|
|
||||||
|
|
||||||
notestr = ical_unformat_line(p);
|
notestr = ical_unformat_line(p);
|
||||||
if (notestr == NULL) {
|
if (notestr == NULL) {
|
||||||
@ -865,11 +877,11 @@ static char *ical_read_summary(char *line)
|
|||||||
{
|
{
|
||||||
char *p, *summary;
|
char *p, *summary;
|
||||||
|
|
||||||
p = strchr(line, ':');
|
p = ical_get_value(line);
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
summary = ical_unformat_line(p + 1);
|
summary = ical_unformat_line(p);
|
||||||
if (!summary)
|
if (!summary)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -970,28 +982,28 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (starts_with_ci(buf, "DTSTART")) {
|
if (starts_with_ci(buf, "DTSTART")) {
|
||||||
p = strchr(buf, ':');
|
p = ical_get_value(buf);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
||||||
_("event start time malformed."));
|
_("event start time malformed."));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
vevent.start = ical_datetime2time_t(++p, &vevent_type);
|
vevent.start = ical_datetime2time_t(p, &vevent_type);
|
||||||
if (!vevent.start) {
|
if (!vevent.start) {
|
||||||
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
||||||
_("could not retrieve event start time."));
|
_("could not retrieve event start time."));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
} else if (starts_with_ci(buf, "DTEND")) {
|
} else if (starts_with_ci(buf, "DTEND")) {
|
||||||
p = strchr(buf, ':');
|
p = ical_get_value(buf);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
||||||
_("event end time malformed."));
|
_("event end time malformed."));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
vevent.end = ical_datetime2time_t(++p, &vevent_type);
|
vevent.end = ical_datetime2time_t(p, &vevent_type);
|
||||||
if (!vevent.end) {
|
if (!vevent.end) {
|
||||||
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
ical_log(log, ICAL_VEVENT, ITEMLINE,
|
||||||
_("could not retrieve event end time."));
|
_("could not retrieve event end time."));
|
||||||
|
@ -49,6 +49,7 @@ TESTS = \
|
|||||||
ical-005.sh \
|
ical-005.sh \
|
||||||
ical-006.sh \
|
ical-006.sh \
|
||||||
ical-007.sh \
|
ical-007.sh \
|
||||||
|
ical-008.sh \
|
||||||
next-001.sh \
|
next-001.sh \
|
||||||
search-001.sh \
|
search-001.sh \
|
||||||
bug-002.sh \
|
bug-002.sh \
|
||||||
|
12
test/data/ical-008.ical
Normal file
12
test/data/ical-008.ical
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien":19800101T000100
|
||||||
|
DURATION:P1DT9H17M0S
|
||||||
|
SUMMARY:Calibrator's
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VTODO
|
||||||
|
PRIORITY:1
|
||||||
|
SUMMARY:Nary parabled Louvre's fleetest mered
|
||||||
|
END:VTODO
|
||||||
|
END:VCALENDAR
|
28
test/ical-008.sh
Executable file
28
test/ical-008.sh
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. "${TEST_INIT:-./test-init.sh}"
|
||||||
|
|
||||||
|
if [ "$1" = 'actual' ]; then
|
||||||
|
mkdir .calcurse || exit 1
|
||||||
|
cp "$DATA_DIR/conf" .calcurse || exit 1
|
||||||
|
"$CALCURSE" -D "$PWD/.calcurse" -i "$DATA_DIR/ical-008.ical"
|
||||||
|
"$CALCURSE" -D "$PWD/.calcurse" -s01/01/1980 -r2
|
||||||
|
"$CALCURSE" -D "$PWD/.calcurse" -t
|
||||||
|
rm -rf .calcurse || exit 1
|
||||||
|
elif [ "$1" = 'expected' ]; then
|
||||||
|
cat <<EOD
|
||||||
|
Import process report: 0017 lines read
|
||||||
|
1 app / 0 events / 1 todo / 0 skipped
|
||||||
|
01/01/80:
|
||||||
|
- 00:01 -> ..:..
|
||||||
|
Calibrator's
|
||||||
|
|
||||||
|
01/02/80:
|
||||||
|
- ..:.. -> 09:18
|
||||||
|
Calibrator's
|
||||||
|
to do:
|
||||||
|
0. Nary parabled Louvre's fleetest mered
|
||||||
|
EOD
|
||||||
|
else
|
||||||
|
./run-test "$0"
|
||||||
|
fi
|
Loading…
x
Reference in New Issue
Block a user