aboutsummaryrefslogtreecommitdiffstats
path: root/src/ical.c
diff options
context:
space:
mode:
authorLukas Fleischer <lfleischer@calcurse.org>2017-02-07 17:52:14 +0100
committerLukas Fleischer <lfleischer@calcurse.org>2017-02-07 21:54:05 +0100
commite4e2e0eb20794972b8d4c89dcfeb6c257c45c3a1 (patch)
treebee6a06be507aad5105b32610eb55b85d99a2ccd /src/ical.c
parent3375fddb4e594badf7a7ab0cc722dc33a3af1131 (diff)
downloadcalcurse-e4e2e0eb20794972b8d4c89dcfeb6c257c45c3a1.tar.gz
calcurse-e4e2e0eb20794972b8d4c89dcfeb6c257c45c3a1.zip
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>
Diffstat (limited to 'src/ical.c')
-rw-r--r--src/ical.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/src/ical.c b/src/ical.c
index f17b1cf..c2c8c5b 100644
--- a/src/ical.c
+++ b/src/ical.c
@@ -671,6 +671,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.
*
* Value Name: RECUR
@@ -717,14 +732,13 @@ static ical_rpt_t *ical_read_rrule(FILE * log, char *rrulestr,
ical_rpt_t *rpt;
char *p;
- p = strchr(rrulestr, ':');
+ p = ical_get_value(rrulestr);
if (!p) {
ical_log(log, ICAL_VEVENT, itemline,
_("recurrence rule malformed."));
(*noskipped)++;
return NULL;
}
- p++;
rpt = mem_malloc(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;
- p = strchr(exstr, ':');
+ p = ical_get_value(exstr);
if (!p) {
ical_log(log, ICAL_VEVENT, itemline,
_("recurrence exception dates malformed."));
(*noskipped)++;
return;
}
- p++;
while ((q = strchr(p, ',')) != NULL) {
char buf[BUFSIZ];
@@ -835,14 +848,13 @@ static char *ical_read_note(char *line, unsigned *noskipped,
{
char *p, *notestr, *note;
- p = strchr(line, ':');
+ p = ical_get_value(line);
if (!p) {
ical_log(log, item_type, itemline,
_("description malformed."));
(*noskipped)++;
return NULL;
}
- p++;
notestr = ical_unformat_line(p);
if (notestr == NULL) {
@@ -865,11 +877,11 @@ static char *ical_read_summary(char *line)
{
char *p, *summary;
- p = strchr(line, ':');
+ p = ical_get_value(line);
if (!p)
return NULL;
- summary = ical_unformat_line(p + 1);
+ summary = ical_unformat_line(p);
if (!summary)
return NULL;
@@ -970,28 +982,28 @@ ical_read_event(FILE * fdi, FILE * log, unsigned *noevents,
}
if (starts_with_ci(buf, "DTSTART")) {
- p = strchr(buf, ':');
+ p = ical_get_value(buf);
if (!p) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
_("event start time malformed."));
goto cleanup;
}
- vevent.start = ical_datetime2time_t(++p, &vevent_type);
+ vevent.start = ical_datetime2time_t(p, &vevent_type);
if (!vevent.start) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
_("could not retrieve event start time."));
goto cleanup;
}
} else if (starts_with_ci(buf, "DTEND")) {
- p = strchr(buf, ':');
+ p = ical_get_value(buf);
if (!p) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
_("event end time malformed."));
goto cleanup;
}
- vevent.end = ical_datetime2time_t(++p, &vevent_type);
+ vevent.end = ical_datetime2time_t(p, &vevent_type);
if (!vevent.end) {
ical_log(log, ICAL_VEVENT, ITEMLINE,
_("could not retrieve event end time."));