diff --git a/src/calanonsync/caldav.go b/src/calanonsync/caldav.go index 7495a29..d08ab3d 100644 --- a/src/calanonsync/caldav.go +++ b/src/calanonsync/caldav.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "encoding/xml" - "errors" "fmt" "io" "log" @@ -29,6 +28,10 @@ type ICal struct { eventData []string // sub slice } +func (i ICal) Valid() bool { + return len(i.eventData) > 0 +} + // Retrieve the summary (aka title) of the event. func (i ICal) Summary() string { for _, s := range i.eventData { @@ -195,7 +198,11 @@ func ParseICal(r io.Reader) (*ICal, error) { // If we didn't find a start or an end, abort. if eventStart < 0 || eventEnd <= eventStart { - return nil, errors.New("calendar item without event") + log.Println("Encountered calendar item without event") + return &ICal{ + data: data, + eventData: make([]string, 0), + }, err } return &ICal{ @@ -288,8 +295,10 @@ func (c *CalDAV) GetEvents() ([]CalDAVItem, error) { result := make([]CalDAVItem, 0, len(ms.Response)) for _, p := range ms.Response { ical := p.PropStat.Prop.CalendarData - item := CalDAVItem{p.HRef, &ical} - result = append(result, item) + if ical.Valid() { + item := CalDAVItem{p.HRef, &ical} + result = append(result, item) + } } return result, nil diff --git a/src/calanonsync/caldav_test.go b/src/calanonsync/caldav_test.go index 69314da..41abdb8 100644 --- a/src/calanonsync/caldav_test.go +++ b/src/calanonsync/caldav_test.go @@ -1,6 +1,7 @@ package main import ( + "encoding/xml" "strings" "testing" "time" @@ -174,6 +175,36 @@ END:VCALENDAR` { }) } +func TestXMLUnmarshal(t *testing.T) { + response := `/calendar/HTTP/1.1 404 Not Found/calendar/f10545b91c12a44ef7ed2ee3aa250df4-z2QSIWY.icsBEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//some//NONSGML Calendar//EN +X-WR-Timezone: Europe/London +BEGIN:VEVENT +DTSTART:20180404T080000Z +DTEND:20180404T081500Z +DTSTAMP:20180404T070805Z +SEQUENCE:1522825685 +SUMMARY:Test +UID:f10545b91c12a44ef7ed2ee3aa250df4-z2QSIWY +END:VEVENT +END:VCALENDARHTTP/1.1 200 OK` + ms := &MultiStatus{} + err := xml.Unmarshal([]byte(response), ms) + if err != nil { + t.Fatal("Decoding should have worked") + } + if len(ms.Response) != 2 { + t.Fatal("Invalid number of results.") + } + if ms.Response[0].PropStat.Prop.CalendarData.Valid() { + t.Error("CalendarData 0 should not be valid") + } + if !ms.Response[1].PropStat.Prop.CalendarData.Valid() { + t.Error("CalendarData 1 should be valid") + } +} + const icsWithTZ = `BEGIN:VCALENDAR PRODID:-//Ximian//NONSGML Evolution Calendar//EN VERSION:2.0