public void FixTimeZoneComponentOrder_EventHasNoTimeZones_DoesntChangeEvent() { string input = @"BEGIN:VCALENDAR PRODID:-//bitfire web engineering//DAVdroid 0.8.4.1 (ical4j 2.0-beta1)//EN VERSION:2.0 BEGIN:VEVENT DTSTAMP:20150925T061111Z UID:566745d3-04ed-497a-9d1b-47db1bb12629 DTSTART;TZID=Europe/Vienna:20151125T133500 DTEND;TZID=Europe/Vienna:20151125T151500 SUMMARY:EZG-ILV EDV_F1.03 - MGS-1 LOCATION:EDV_F1.03 DESCRIPTION:EZG-ILV\nHesinaGe\nMGS-1 \nEDV_F1.03 CLASS:PUBLIC LAST-MODIFIED:20150927T175324Z TRANSP:OPAQUE SEQUENCE:2 END:VEVENT END:VCALENDAR "; var processed = CalendarDataPreprocessor.FixTimeZoneComponentOrderNoThrow(input); Assert.That(processed, Is.EqualTo(input)); AssertCanDeserialize(processed); }
public void Map1To2(ITaskItemWrapper source, ITodo target, iCalTimeZone localIcalTimeZone, IEntitySynchronizationLogger logger) { target.Summary = CalendarDataPreprocessor.EscapeBackslash(source.Inner.Subject); if (_configuration.MapBody) { target.Description = CalendarDataPreprocessor.EscapeBackslash(source.Inner.Body); } if (source.Inner.StartDate != OutlookUtility.OUTLOOK_DATE_NONE) { target.Start = new iCalDateTime(source.Inner.StartDate.Year, source.Inner.StartDate.Month, source.Inner.StartDate.Day, true); if (!_configuration.MapStartAndDueAsFloating) { target.Start.SetTimeZone(localIcalTimeZone); } } if (source.Inner.Complete && source.Inner.DateCompleted != OutlookUtility.OUTLOOK_DATE_NONE) { target.Completed = new iCalDateTime(source.Inner.DateCompleted.ToUniversalTime()) { IsUniversalTime = true, HasTime = true }; } target.PercentComplete = source.Inner.PercentComplete; if (_configuration.MapRecurringTasks) { MapRecurrance1To2(source.Inner, target, localIcalTimeZone); } if (source.Inner.DueDate != OutlookUtility.OUTLOOK_DATE_NONE) { target.Due = new iCalDateTime(source.Inner.DueDate.Year, source.Inner.DueDate.Month, source.Inner.DueDate.Day, 23, 59, 59); if (!_configuration.MapStartAndDueAsFloating) { target.Due.SetTimeZone(localIcalTimeZone); } // Workaround for a bug in DDay.iCal, according to RFC5545 DUE must not occur together with DURATION target.Properties.Remove(new CalendarProperty("DURATION")); } target.Properties.Set("STATUS", MapStatus1To2(source.Inner.Status)); if (_configuration.MapPriority) { target.Priority = CommonEntityMapper.MapPriority1To2(source.Inner.Importance); } target.Class = CommonEntityMapper.MapPrivacy1To2(source.Inner.Sensitivity, false, false); MapReminder1To2(source, target); MapCategories1To2(source, target); if (_configuration.MapCustomProperties || _configuration.UserDefinedCustomPropertyMappings.Length > 0) { using (var userPropertiesWrapper = GenericComObjectWrapper.Create(source.Inner.UserProperties)) { CommonEntityMapper.MapCustomProperties1To2(userPropertiesWrapper, target.Properties, _configuration.MapCustomProperties, _configuration.UserDefinedCustomPropertyMappings, logger, s_logger); } } }
public void FixTimeZoneComponentOrder_CalenderDataIsNull_ReturnsNull() { Assert.That(CalendarDataPreprocessor.FixTimeZoneComponentOrderNoThrow(null), Is.Null); }
public void FixTimeZoneComponentOrder_EventHasMultipleTimeZomes() { string input = @"BEGIN:VCALENDAR BEGIN:VTIMEZONE TZID:Europe/Vienna X-LIC-LOCATION:Europe/Vienna BEGIN:STANDARD TZNAME:CET DTSTART:19901027T030000 END:STANDARD BEGIN:DAYLIGHT TZNAME:CEST DTSTART:19800329T020000 END:DAYLIGHT END:VTIMEZONE BEGIN:VTIMEZONE TZID:Blablubb X-LIC-LOCATION:SomewhereElse BEGIN:STANDARD TZNAME:CET DTSTART:19601027T030000 END:STANDARD BEGIN:DAYLIGHT TZNAME:CEST DTSTART:19500329T020000 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT SUMMARY:Termin END:VEVENT END:VCALENDAR "; string expected = @"BEGIN:VCALENDAR BEGIN:VTIMEZONE TZID:Europe/Vienna X-LIC-LOCATION:Europe/Vienna BEGIN:DAYLIGHT TZNAME:CEST DTSTART:19800329T020000 END:DAYLIGHT BEGIN:STANDARD TZNAME:CET DTSTART:19901027T030000 END:STANDARD END:VTIMEZONE BEGIN:VTIMEZONE TZID:Blablubb X-LIC-LOCATION:SomewhereElse BEGIN:DAYLIGHT TZNAME:CEST DTSTART:19500329T020000 END:DAYLIGHT BEGIN:STANDARD TZNAME:CET DTSTART:19601027T030000 END:STANDARD END:VTIMEZONE BEGIN:VEVENT SUMMARY:Termin END:VEVENT END:VCALENDAR "; var processed = CalendarDataPreprocessor.FixTimeZoneComponentOrderNoThrow(input); Assert.That(processed, Is.EqualTo(expected)); }
public void FixTimeZoneComponentOrder_TestRealEvent() { string input = @"BEGIN:VCALENDAR PRODID:-//bitfire web engineering//DAVdroid 0.8.4.1 (ical4j 2.0-beta1)//EN VERSION:2.0 BEGIN:VTIMEZONE TZID:Europe/Vienna TZURL:http://tzurl.org/zoneinfo/Europe/Vienna X-LIC-LOCATION:Europe/Vienna BEGIN:DAYLIGHT TZOFFSETFROM:+0100 TZOFFSETTO:+0200 TZNAME:CEST DTSTART:19810329T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:+0200 TZOFFSETTO:+0100 TZNAME:CET DTSTART:19961027T030000 RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU END:STANDARD BEGIN:STANDARD TZOFFSETFROM:+010521 TZOFFSETTO:+0100 TZNAME:CET DTSTART:18930401T000000 RDATE:18930401T000000 END:STANDARD BEGIN:DAYLIGHT TZOFFSETFROM:+0100 TZOFFSETTO:+0200 TZNAME:CEST DTSTART:19160501T000000 RDATE:19160501T000000 RDATE:19170416T030000 RDATE:19180415T030000 RDATE:19200405T030000 RDATE:19400401T030000 RDATE:19430329T030000 RDATE:19440403T030000 RDATE:19450402T030000 RDATE:19460414T030000 RDATE:19470406T030000 RDATE:19480418T030000 RDATE:19800406T000000 END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:+0200 TZOFFSETTO:+0100 TZNAME:CET DTSTART:19161001T010000 RDATE:19161001T010000 RDATE:19170917T030000 RDATE:19180916T030000 RDATE:19200913T030000 RDATE:19421102T030000 RDATE:19431004T030000 RDATE:19441002T030000 RDATE:19450412T030000 RDATE:19461006T030000 RDATE:19471005T030000 RDATE:19481003T030000 RDATE:19800928T000000 RDATE:19810927T030000 RDATE:19820926T030000 RDATE:19830925T030000 RDATE:19840930T030000 RDATE:19850929T030000 RDATE:19860928T030000 RDATE:19870927T030000 RDATE:19880925T030000 RDATE:19890924T030000 RDATE:19900930T030000 RDATE:19910929T030000 RDATE:19920927T030000 RDATE:19930926T030000 RDATE:19940925T030000 RDATE:19950924T030000 END:STANDARD BEGIN:STANDARD TZOFFSETFROM:+0100 TZOFFSETTO:+0100 TZNAME:CET DTSTART:19200101T000000 RDATE:19200101T000000 RDATE:19460101T000000 RDATE:19810101T000000 END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTAMP:20150925T061111Z UID:566745d3-04ed-497a-9d1b-47db1bb12629 DTSTART;TZID=Europe/Vienna:20151125T133500 DTEND;TZID=Europe/Vienna:20151125T151500 SUMMARY:EZG-ILV EDV_F1.03 - MGS-1 LOCATION:EDV_F1.03 DESCRIPTION:EZG-ILV\nHesinaGe\nMGS-1 \nEDV_F1.03 CLASS:PUBLIC LAST-MODIFIED:20150927T175324Z TRANSP:OPAQUE SEQUENCE:2 END:VEVENT END:VCALENDAR "; string expected = @"BEGIN:VCALENDAR PRODID:-//bitfire web engineering//DAVdroid 0.8.4.1 (ical4j 2.0-beta1)//EN VERSION:2.0 BEGIN:VTIMEZONE TZID:Europe/Vienna TZURL:http://tzurl.org/zoneinfo/Europe/Vienna X-LIC-LOCATION:Europe/Vienna BEGIN:STANDARD TZOFFSETFROM:+010521 TZOFFSETTO:+0100 TZNAME:CET DTSTART:18930401T000000 RDATE:18930401T000000 END:STANDARD BEGIN:DAYLIGHT TZOFFSETFROM:+0100 TZOFFSETTO:+0200 TZNAME:CEST DTSTART:19160501T000000 RDATE:19160501T000000 RDATE:19170416T030000 RDATE:19180415T030000 RDATE:19200405T030000 RDATE:19400401T030000 RDATE:19430329T030000 RDATE:19440403T030000 RDATE:19450402T030000 RDATE:19460414T030000 RDATE:19470406T030000 RDATE:19480418T030000 RDATE:19800406T000000 END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:+0200 TZOFFSETTO:+0100 TZNAME:CET DTSTART:19161001T010000 RDATE:19161001T010000 RDATE:19170917T030000 RDATE:19180916T030000 RDATE:19200913T030000 RDATE:19421102T030000 RDATE:19431004T030000 RDATE:19441002T030000 RDATE:19450412T030000 RDATE:19461006T030000 RDATE:19471005T030000 RDATE:19481003T030000 RDATE:19800928T000000 RDATE:19810927T030000 RDATE:19820926T030000 RDATE:19830925T030000 RDATE:19840930T030000 RDATE:19850929T030000 RDATE:19860928T030000 RDATE:19870927T030000 RDATE:19880925T030000 RDATE:19890924T030000 RDATE:19900930T030000 RDATE:19910929T030000 RDATE:19920927T030000 RDATE:19930926T030000 RDATE:19940925T030000 RDATE:19950924T030000 END:STANDARD BEGIN:STANDARD TZOFFSETFROM:+0100 TZOFFSETTO:+0100 TZNAME:CET DTSTART:19200101T000000 RDATE:19200101T000000 RDATE:19460101T000000 RDATE:19810101T000000 END:STANDARD BEGIN:DAYLIGHT TZOFFSETFROM:+0100 TZOFFSETTO:+0200 TZNAME:CEST DTSTART:19810329T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:+0200 TZOFFSETTO:+0100 TZNAME:CET DTSTART:19961027T030000 RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTAMP:20150925T061111Z UID:566745d3-04ed-497a-9d1b-47db1bb12629 DTSTART;TZID=Europe/Vienna:20151125T133500 DTEND;TZID=Europe/Vienna:20151125T151500 SUMMARY:EZG-ILV EDV_F1.03 - MGS-1 LOCATION:EDV_F1.03 DESCRIPTION:EZG-ILV\nHesinaGe\nMGS-1 \nEDV_F1.03 CLASS:PUBLIC LAST-MODIFIED:20150927T175324Z TRANSP:OPAQUE SEQUENCE:2 END:VEVENT END:VCALENDAR "; var processed = CalendarDataPreprocessor.FixTimeZoneComponentOrderNoThrow(input); Assert.That(processed, Is.EqualTo(expected)); AssertCanDeserialize(processed); }
public void FixTimeZoneComponentOrder_StartTimeOfOneComponentIsNotParseable_IgnoresComnponentAndAddsItAfterSortedConmponents() { string input = @"BEGIN:VCALENDAR BEGIN:VTIMEZONE TZID:Europe/Vienna X-LIC-LOCATION:Europe/Vienna BEGIN:STANDARD TZNAME:CET DTSTART:19961027T030000 END:STANDARD BEGIN:DAYLIGHT TZNAME:CEST DTSTART:19810329T020000 END:DAYLIGHT BEGIN:STANDARD TZNAME:CET DTSTART:19200101T000000 END:STANDARD BEGIN:DAYLIGHT TZNAME:CEST DTSTART:xxxxxxxxxxxxxxxxxxxxxxx END:DAYLIGHT BEGIN:STANDARD TZNAME:CET DTSTART:19161001T010000 END:STANDARD BEGIN:STANDARD TZNAME:CET DTSTART:18930401T000000 END:STANDARD END:VTIMEZONE BEGIN:VEVENT SUMMARY:Termin END:VEVENT END:VCALENDAR "; string expected = @"BEGIN:VCALENDAR BEGIN:VTIMEZONE TZID:Europe/Vienna X-LIC-LOCATION:Europe/Vienna BEGIN:STANDARD TZNAME:CET DTSTART:18930401T000000 END:STANDARD BEGIN:STANDARD TZNAME:CET DTSTART:19161001T010000 END:STANDARD BEGIN:STANDARD TZNAME:CET DTSTART:19200101T000000 END:STANDARD BEGIN:DAYLIGHT TZNAME:CEST DTSTART:19810329T020000 END:DAYLIGHT BEGIN:STANDARD TZNAME:CET DTSTART:19961027T030000 END:STANDARD BEGIN:DAYLIGHT TZNAME:CEST DTSTART:xxxxxxxxxxxxxxxxxxxxxxx END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT SUMMARY:Termin END:VEVENT END:VCALENDAR "; var processed = CalendarDataPreprocessor.FixTimeZoneComponentOrderNoThrow(input); Assert.That(processed, Is.EqualTo(expected)); }
private Task <IReadOnlyList <EntityWithId <WebResourceName, IICalendar> > > ParallelDeserialize(IReadOnlyList <EntityWithId <WebResourceName, string> > serializedEntities, ILoadEntityLogger logger) { return(Task.Factory.StartNew(() => { var result = new List <EntityWithId <WebResourceName, IICalendar> >(); Parallel.ForEach( serializedEntities, () => Tuple.Create(new iCalendarSerializer(), new List <Tuple <WebResourceName, IICalendar> >()), (serialized, loopState, threadLocal) => { IICalendar calendar; string normalizedICalData, fixedICalData; // fix some linebreak issues with Open-Xchange if (serialized.Entity.Contains("\r\r\n")) { normalizedICalData = CalendarDataPreprocessor.NormalizeLineBreaks(serialized.Entity); } else { normalizedICalData = serialized.Entity; } // emClient sets DTSTART in VTIMEZONE to year 0001, which causes a 90 sec delay in DDay.iCal to evaluate the recurrence rule. // If we find such a DTSTART we replace it 0001 with 1970 since the historic data is not valid anyway and avoid the performance issue. if (normalizedICalData.Contains("DTSTART:00010101")) { fixedICalData = CalendarDataPreprocessor.FixInvalidDTSTARTInTimeZoneNoThrow(normalizedICalData); s_logger.InfoFormat("Changed DTSTART from year 0001 to 1970 in VTIMEZONE of ICalData '{0}'.", serialized.Id); } else { fixedICalData = normalizedICalData; } if (TryDeserializeCalendar(fixedICalData, out calendar, serialized.Id, threadLocal.Item1, NullLoadEntityLogger.Instance)) { threadLocal.Item2.Add(Tuple.Create(serialized.Id, calendar)); } else { // maybe deserialization failed because of the iCal-TimeZone-Bug => try to fix it var fixedICalData2 = CalendarDataPreprocessor.FixTimeZoneComponentOrderNoThrow(fixedICalData); if (TryDeserializeCalendar(fixedICalData2, out calendar, serialized.Id, threadLocal.Item1, logger)) { threadLocal.Item2.Add(Tuple.Create(serialized.Id, calendar)); s_logger.Info(string.Format("Deserialized ICalData with reordering of TimeZone data '{0}'.", serialized.Id)); } } return threadLocal; }, threadLocal => { lock (result) { foreach (var calendar in threadLocal.Item2) { result.Add(EntityWithId.Create(calendar.Item1, calendar.Item2)); } } }); IReadOnlyList <EntityWithId <WebResourceName, IICalendar> > readOnlyResult = result; return readOnlyResult; })); }