Skip to content

Commit

Permalink
fix(calendar): adjust invalid dates when importing a vEvent
Browse files Browse the repository at this point in the history
Fixes #4845
  • Loading branch information
cgx committed Nov 27, 2019
1 parent f872dc5 commit 3bb40e4
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 201 deletions.
106 changes: 22 additions & 84 deletions SoObjects/Appointments/SOGoAppointmentFolder.m
@@ -1,5 +1,5 @@
/*
Copyright (C) 2007-2014 Inverse inc.
Copyright (C) 2007-2019 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of SOGo.
Expand Down Expand Up @@ -37,6 +37,7 @@
#import <NGCards/iCalTimeZonePeriod.h>
#import <NGCards/iCalToDo.h>
#import <NGCards/NSString+NGCards.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NGCalendarDateRange.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
Expand All @@ -50,6 +51,7 @@
#import <SOGo/SOGoBuild.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoDomainDefaults.h>
#import <SOGo/SOGoGroup.h>
#import <SOGo/SOGoPermissions.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserSettings.h>
Expand Down Expand Up @@ -3392,7 +3394,6 @@ - (int) importCalendar: (iCalCalendar *) calendar
NSMutableDictionary *timezones, *uids;
NSString *tzId, *uid, *originalUid;
iCalEntityObject *element;
iCalDateTime *startDate;
iCalTimeZone *timezone;
iCalCalendar *masterCalendar;
iCalEvent *event;
Expand Down Expand Up @@ -3436,92 +3437,29 @@ - (int) importCalendar: (iCalCalendar *) calendar

timezone = nil;
element = [components objectAtIndex: i];
// Use the timezone of the start date.
startDate = (iCalDateTime *) [element uniqueChildWithTag: @"dtstart"];
if (startDate)

if ([element isKindOfClass: iCalEventK])
{
tzId = [startDate value: 0 ofAttribute: @"tzid"];
if ([tzId length])
timezone = [timezones valueForKey: tzId];
else
{
// If the start date is a "floating time", let's use the user's timezone
// during the import for both the start and end dates. This is similar
// to what we do in SOGoAppointmentObject: -_adjustFloatingTimeInRequestCalendar:
NSString *s;

s = [[startDate valuesAtIndex: 0 forKey: @""] objectAtIndex: 0];

if ([element isKindOfClass: iCalEventK] &&
![(iCalEvent *)element isAllDay] &&
![s hasSuffix: @"Z"] &&
![s hasSuffix: @"z"])
{
iCalDateTime *endDate;
int delta;

timezone = [iCalTimeZone timeZoneForName: [[[self->context activeUser] userDefaults] timeZoneName]];
[calendar addTimeZone: timezone];

delta = [[timezone periodForDate: [startDate dateTime]] secondsOffsetFromGMT];
event = (iCalEvent *)element;

[event setStartDate: [[event startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -delta]];
[startDate setTimeZone: timezone];

endDate = (iCalDateTime *) [element uniqueChildWithTag: @"dtend"];

if (endDate)
{
[event setEndDate: [[event endDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -delta]];
[endDate setTimeZone: timezone];
}
}
}

if ([element isKindOfClass: iCalEventK])
event = (iCalEvent *)element;
timezone = [event adjustInContext: self->context];

if ([event recurrenceId])
{
event = (iCalEvent *)element;
if (![event hasEndDate] && ![event hasDuration])
{
// No end date, no duration
if ([event isAllDay])
[event setDuration: @"P1D"];
else
[event setDuration: @"PT1H"];

[self errorWithFormat: @"Importing event with no end date; setting duration to %@ for UID = %@", [event duration], [event uid]];
}
//
// We check for broken all-day events (like the ones coming from the "WebCalendar" tool) where
// the start date is equal to the end date. This clearly violates the RFC:
//
// 3.8.2.2. Date-Time End
// The value MUST be later in time than the value of the "DTSTART" property.
//
if ([event isAllDay] && [[event startDate] isEqual: [event endDate]])
{
[event setEndDate: [[event startDate] dateByAddingYears: 0 months: 0 days: 1 hours: 0 minutes: 0 seconds: 0]];
[self errorWithFormat: @"Fixed broken all-day event; setting end date to %@ for UID = %@", [event endDate], [event uid]];
}
if ([event recurrenceId])
// Event is an occurrence of a repeating event
if ((uid = [uids valueForKey: [event uid]]))
{
// Event is an occurrence of a repeating event
if ((uid = [uids valueForKey: [event uid]]))
SOGoAppointmentObject *master = [self lookupName: uid
inContext: context
acquire: NO];
if (master)
{
SOGoAppointmentObject *master = [self lookupName: uid
inContext: context
acquire: NO];
if (master)
{
// Associate the occurrence to the master event and skip the actual import process
masterCalendar = [master calendar: NO secure: NO];
[masterCalendar addToEvents: event];
if (timezone)
[masterCalendar addTimeZone: timezone];
[master saveCalendar: masterCalendar];
continue;
}
// Associate the occurrence to the master event and skip the actual import process
masterCalendar = [master calendar: NO secure: NO];
[masterCalendar addToEvents: event];
if (timezone)
[masterCalendar addTimeZone: timezone];
[master saveCalendar: masterCalendar];
continue;
}
}
}
Expand Down
62 changes: 5 additions & 57 deletions SoObjects/Appointments/SOGoAppointmentObject.m
Expand Up @@ -54,6 +54,7 @@
#import <SOGo/WORequest+SOGo.h>

#import "iCalCalendar+SOGo.h"
#import "iCalEvent+SOGo.h"
#import "iCalEventChanges+SOGo.h"
#import "iCalEntityObject+SOGo.h"
#import "iCalPerson+SOGo.h"
Expand Down Expand Up @@ -1930,6 +1931,7 @@ - (void) _adjustEventsInRequestCalendar: (iCalCalendar *) rqCalendar
{
NSArray *allEvents;
iCalEvent *event;
iCalTimeZone *tz;
NSUInteger i;
int j;

Expand All @@ -1939,15 +1941,9 @@ - (void) _adjustEventsInRequestCalendar: (iCalCalendar *) rqCalendar
{
event = [allEvents objectAtIndex: i];

if (![event hasEndDate] && ![event hasDuration])
{
// No end date, no duration
if ([event isAllDay])
[event setDuration: @"P1D"];
else
[event setDuration: @"PT1H"];
[self warnWithFormat: @"Invalid event: no end date; setting duration to %@", [event duration]];
}
tz = [event adjustInContext: context];
if (tz)
[rqCalendar addTimeZone: tz];

if ([event organizer])
{
Expand Down Expand Up @@ -1994,53 +1990,6 @@ - (void) _adjustEventsInRequestCalendar: (iCalCalendar *) rqCalendar
}
}

//
// This is similar to what we do in SOGoAppointmentFolder: -importCalendar:
//
- (void) _adjustFloatingTimeInRequestCalendar: (iCalCalendar *) rqCalendar
{
iCalDateTime *startDate, *endDate;
NSString *startDateAsString;
SOGoUserDefaults *ud;
NSArray *allEvents;
iCalTimeZone *tz;
iCalEvent *event;
int i, delta;

allEvents = [rqCalendar events];
for (i = 0; i < [allEvents count]; i++)
{
event = [allEvents objectAtIndex: i];

if ([event isAllDay])
continue;

startDate = (iCalDateTime *)[event uniqueChildWithTag: @"dtstart"];
startDateAsString = [[startDate valuesAtIndex: 0 forKey: @""] objectAtIndex: 0];

if (![startDate timeZone] &&
![startDateAsString hasSuffix: @"Z"] &&
![startDateAsString hasSuffix: @"z"])
{
ud = [[context activeUser] userDefaults];
tz = [iCalTimeZone timeZoneForName: [ud timeZoneName]];
if ([rqCalendar addTimeZone: tz])
{
delta = [[tz periodForDate: [startDate dateTime]] secondsOffsetFromGMT];

[event setStartDate: [[event startDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -delta]];
[startDate setTimeZone: tz];

endDate = (iCalDateTime *) [event uniqueChildWithTag: @"dtend"];
if (endDate)
{
[event setEndDate: [[event endDate] dateByAddingYears: 0 months: 0 days: 0 hours: 0 minutes: 0 seconds: -delta]];
[endDate setTimeZone: tz];
}
}
}
}
}

- (void) _decomposeGroupsInRequestCalendar: (iCalCalendar *) rqCalendar
{
Expand Down Expand Up @@ -2163,7 +2112,6 @@ - (NSException *) updateContentWithCalendar: (iCalCalendar *) calendar
[self _adjustEventsInRequestCalendar: calendar];
[self adjustClassificationInRequestCalendar: calendar];
[self _adjustPartStatInRequestCalendar: calendar];
[self _adjustFloatingTimeInRequestCalendar: calendar];
}

//
Expand Down
4 changes: 3 additions & 1 deletion SoObjects/Appointments/iCalEvent+SOGo.h
@@ -1,6 +1,6 @@
/* iCalEvent+SOGo.h - this file is part of SOGo
*
* Copyright (C) 2007-2015 Inverse inc.
* Copyright (C) 2007-2019 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -23,13 +23,15 @@

#import <NGCards/iCalEvent.h>

@class iCalTimeZone;
@class NSMutableDictionary;

@interface iCalEvent (SOGoExtensions)

- (BOOL) isStillRelevant;
- (NSTimeInterval) occurenceInterval;
- (void) updateRecurrenceRulesUntilDate: (NSCalendarDate *) previousEndDate;
- (iCalTimeZone *) adjustInContext: (WOContext *) context;

@end

Expand Down

0 comments on commit 3bb40e4

Please sign in to comment.