Skip to content

Incorrect parsing of vCalendar files from Exchange #22

@bokysan

Description

@bokysan

The following valid VCLANEDAR gets parsed wrongly:

BEGIN:VCALENDAR
METHOD:CANCEL
PRODID:Microsoft Exchange Server 2010
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Central Europe Standard Time
BEGIN:STANDARD
DTSTART:16010101T030000
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:16010101T020000
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
ORGANIZER;CN=Demo:MAILTO:demo@example.com
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Demo:
 MAILTO:demo@example.com
DESCRIPTION;LANGUAGE=en-US:\n
SUMMARY;LANGUAGE=en-US:Canceled: Vacation request 1
DTSTART;VALUE=DATE:20180625
DTEND;VALUE=DATE:20180626
UID:040000008200E00074C5B7101A82E008000000006FAC5537120BD401000000000000000
 010000000B0CC569DE55F9A4CADF9A4EDE41DA534
CLASS:PUBLIC
PRIORITY:5
DTSTAMP:20180623T165005Z
TRANSP:OPAQUE
STATUS:CANCELLED
SEQUENCE:1
CATEGORIES:\\\\Seen
LOCATION;LANGUAGE=en-US:
X-MICROSOFT-CDO-APPT-SEQUENCE:1
X-MICROSOFT-CDO-OWNERAPPTID:2116467830
X-MICROSOFT-CDO-BUSYSTATUS:FREE
X-MICROSOFT-CDO-INTENDEDSTATUS:FREE
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-CDO-INSTTYPE:0
X-MICROSOFT-DISALLOW-COUNTER:FALSE
END:VEVENT
END:VCALENDAR

When calling event.getSummary() an empty string is returned, although there's a specific summary in there.

I've tracked down the issue to the fact that regex seems to be used for parsing, e.g.:

func (p *Parser) parseEventSummary(eventData string) string {
	re, _ := regexp.Compile(`SUMMARY:.*?\n`)
	result := re.FindString(eventData)
	return trimField(result, "SUMMARY:")
}

As per RFC 5545 parameters are practically allowed on any vCalendar line, including SUMMARY.

Short term, this could easily be something along these lines:

func (p *Parser) parseEventSummary(eventData string) string {
	re, _ := regexp.Compile(`SUMMARY(;.*?)*:.*?\n`)
	result := re.FindString(eventData)
	return trimField(result, "SUMMARY(;.*?)*:")
}

Long term, however, some kind of parser generator would make more sense and even providing an API to get/set the additional parameters. There seems to be some for go, e.g.:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions