diff --git a/ActiveSync/NGVCard+ActiveSync.m b/ActiveSync/NGVCard+ActiveSync.m index aaf6c8581..3f246c8d1 100644 --- a/ActiveSync/NGVCard+ActiveSync.m +++ b/ActiveSync/NGVCard+ActiveSync.m @@ -193,11 +193,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. if ((o = [self note])) { + // It is very important here to NOT set 0 in the response, + // otherwise it'll prevent WP8 phones from sync'ing. See #3028 for details. o = [o activeSyncRepresentationInContext: context]; [s appendString: @""]; [s appendFormat: @"%d", 1]; [s appendFormat: @"%d", [o length]]; - [s appendFormat: @"%d", 0]; [s appendFormat: @"%@", o]; [s appendString: @""]; } diff --git a/ActiveSync/NSString+ActiveSync.m b/ActiveSync/NSString+ActiveSync.m index 8317f8fe9..01f593352 100644 --- a/ActiveSync/NSString+ActiveSync.m +++ b/ActiveSync/NSString+ActiveSync.m @@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -127,13 +128,17 @@ static NSArray *easCommandParameters = nil; // - (NSCalendarDate *) calendarDate { + NSString *s; id o; - o = [NSCalendarDate dateWithString: self calendarFormat: @"%Y%m%dT%H%M%SZ"]; + // We force parsing in the GMT timezone. If we don't do that, the date will be parsed + // in the default timezone. + s = [NSString stringWithFormat: @"%@ GMT", self]; + o = [NSCalendarDate dateWithString: s calendarFormat: @"%Y%m%dT%H%M%SZ %Z"]; if (!o) - o = [NSCalendarDate dateWithString: self calendarFormat: @"%Y-%m-%dT%H:%M:%S.%FZ"]; - + o = [NSCalendarDate dateWithString: s calendarFormat: @"%Y-%m-%dT%H:%M:%S.%FZ %Z"]; + return o; } diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m index db70bde32..100c85807 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m +++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m @@ -531,6 +531,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - (void) processSyncGetChanges: (id ) theDocumentElement inCollection: (id) theCollection withWindowSize: (unsigned int) theWindowSize + withMaxSyncResponseSize: (unsigned int) theMaxSyncResponseSize withSyncKey: (NSString *) theSyncKey withFolderType: (SOGoMicrosoftActiveSyncFolderType) theFolderType withFilterType: (NSCalendarDate *) theFilterType @@ -562,7 +563,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. dateCache = [folderMetadata objectForKey: @"DateCache"]; if ((theFolderType == ActiveSyncMailFolder || theFolderType == ActiveSyncEventFolder || theFolderType == ActiveSyncTaskFolder) && - !([folderMetadata objectForKey: @"MoreAvailable"]) && // previous sync operation reached the windowSize + !([folderMetadata objectForKey: @"MoreAvailable"]) && // previous sync operation reached the windowSize or maximumSyncReponseSize !([theSyncKey isEqualToString: @"-1"]) && // new sync operation theFilterType) { @@ -590,7 +591,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. softdelete_count++; } - if (softdelete_count >= theWindowSize) + if (softdelete_count >= theWindowSize || (theMaxSyncResponseSize > 0 && [s length] >= theMaxSyncResponseSize)) { [folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"]; [self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]]; @@ -653,7 +654,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pool = [[NSAutoreleasePool alloc] init]; // Check for the WindowSize and slice accordingly - if (return_count >= theWindowSize) + if (return_count >= theWindowSize || (theMaxSyncResponseSize > 0 && [s length] >= theMaxSyncResponseSize)) { more_available = YES; @@ -668,7 +669,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. deleted = [[component objectForKey: @"c_deleted"] intValue]; if (!deleted && ![[component objectForKey: @"c_component"] isEqualToString: component_name]) - continue; + { + DESTROY(pool); + continue; + } uid = [[component objectForKey: @"c_name"] sanitizedServerIdWithType: theFolderType]; @@ -692,10 +696,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. if (![syncCache objectForKey: uid]) updated = NO; else if ([[component objectForKey: @"c_lastmodified"] intValue] == [[syncCache objectForKey: uid] intValue]) - continue; + { + DESTROY(pool); + continue; + } return_count++; - + sogoObject = [theCollection lookupName: [uid sanitizedServerIdWithType: theFolderType] inContext: context acquire: 0]; @@ -705,7 +712,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. else componentObject = [sogoObject component: NO secure: NO]; - // // We do NOT synchronize NEW events that are in fact, invitations // to events. This is due to the fact that Outlook 2013 creates @@ -732,17 +738,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } [syncCache setObject: [component objectForKey: @"c_lastmodified"] forKey: uid]; + + // No need to set dateCache for Contacts + if ((theFolderType == ActiveSyncEventFolder || theFolderType == ActiveSyncTaskFolder)) + { + NSCalendarDate *d; + + if ([[component objectForKey: @"c_cycleenddate"] intValue]) + d = [NSCalendarDate dateWithTimeIntervalSince1970: [[component objectForKey: @"c_cycleenddate"] intValue]]; + else if ([[component objectForKey: @"c_enddate"] intValue]) + d = [NSCalendarDate dateWithTimeIntervalSince1970: [[component objectForKey: @"c_enddate"] intValue]]; + else + d = [NSCalendarDate distantFuture]; + + [dateCache setObject: d forKey: uid]; + } if (updated) [s appendString: @""]; else - { - // no need to set dateCache for Contacts - if ((theFolderType == ActiveSyncEventFolder || theFolderType == ActiveSyncTaskFolder)) - [dateCache setObject: [componentObject startDate] ? [componentObject startDate] : [NSCalendarDate date] forKey: uid]; // FIXME: need to set proper date for recurring events - softDelete - [s appendString: @""]; - } [s appendFormat: @"%@", uid]; [s appendString: @""]; @@ -829,7 +844,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. else found_in_cache = NO; - if (found_in_cache) k = j+1; else @@ -847,7 +861,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pool = [[NSAutoreleasePool alloc] init]; // Check for the WindowSize and slice accordingly - if (return_count >= theWindowSize) + if (return_count >= theWindowSize || (theMaxSyncResponseSize > 0 && [s length] >= theMaxSyncResponseSize)) { NSString *lastSequence; more_available = YES; @@ -1047,6 +1061,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - (void) processSyncCollection: (id ) theDocumentElement inBuffer: (NSMutableString *) theBuffer changeDetected: (BOOL *) changeDetected + maxSyncResponseSize: (int) theMaxSyncResponseSize { NSString *collectionId, *realCollectionId, *syncKey, *davCollectionTag, *bodyPreferenceType, *lastServerKey; SOGoMicrosoftActiveSyncFolderType folderType; @@ -1076,7 +1091,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //[theBuffer appendFormat: @"%@", collectionId]; //[theBuffer appendFormat: @"%d", 8]; //[theBuffer appendString: @""]; - return; } @@ -1139,6 +1153,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [self processSyncGetChanges: theDocumentElement inCollection: collection withWindowSize: windowSize + withMaxSyncResponseSize: theMaxSyncResponseSize withSyncKey: syncKey withFolderType: folderType withFilterType: [NSCalendarDate dateFromFilterType: [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]] @@ -1324,15 +1339,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NSArray *allCollections; NSData *d; - int i, j, defaultInterval, heartbeatInterval, internalInterval; + int i, j, defaultInterval, heartbeatInterval, internalInterval, maxSyncResponseSize; BOOL changeDetected; + changeDetected = NO; + + maxSyncResponseSize = [[SOGoSystemDefaults sharedSystemDefaults] maximumSyncResponseSize]; + // We initialize our output buffer output = [[NSMutableString alloc] init]; [output appendString: @""]; [output appendString: @""]; [output appendString: @""]; + + // + // We don't support yet empty Sync requests. See: http://msdn.microsoft.com/en-us/library/ee203280(v=exchg.80).aspx + // We return '13' - see http://msdn.microsoft.com/en-us/library/gg675457(v=exchg.80).aspx + // + if (!theDocumentElement || [[(id)[theDocumentElement getElementsByTagName: @"Partial"] lastObject] textValue]) + { + [output appendString: @"13"]; + [output appendString: @""]; + d = [[output dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; + [theResponse setContent: d]; + return; + } defaults = [SOGoSystemDefaults sharedSystemDefaults]; heartbeatInterval = [[[(id)[theDocumentElement getElementsByTagName: @"HeartbeatInterval"] lastObject] textValue] intValue]; @@ -1363,7 +1395,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { aCollection = [allCollections objectAtIndex: j]; - [self processSyncCollection: aCollection inBuffer: s changeDetected: &changeDetected]; + [self processSyncCollection: aCollection + inBuffer: s + changeDetected: &changeDetected + maxSyncResponseSize: maxSyncResponseSize]; } if (changeDetected) @@ -1378,21 +1413,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } } - // We always return the last generated response. - // If we only return , - // iOS powered devices will simply crash. - [output appendString: s]; + // Only send a response if there are changes otherwise send an empty response. + if (changeDetected) + { + // We always return the last generated response. + // If we only return , + // iOS powered devices will simply crash. + [output appendString: s]; - [output appendString: @""]; + [output appendString: @""]; + + d = [output dataUsingEncoding: NSUTF8StringEncoding]; + d = [d xml2wbxml]; + [theResponse setContent: d]; + } // Avoid overloading the autorelease pool here, as Sync command can // generate fairly large responses. - d = [output dataUsingEncoding: NSUTF8StringEncoding]; RELEASE(output); - - d = [d xml2wbxml]; - - [theResponse setContent: d]; } @end diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m index 9ac964b0e..4ddd1427b 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher.m +++ b/ActiveSync/SOGoActiveSyncDispatcher.m @@ -793,10 +793,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { cKey = [allKeys objectAtIndex: i]; - // ignore invalid folder in cache caused by fs code bugs - if ([cKey isEqualToString:@"(null)"]) - continue; - // if a cache entry is not found in imapGUIDs its either an imap which has been deleted or its an other folder type which can be checked via lookupName. if (![imapGUIDs allKeysForObject: cKey]) { @@ -807,7 +803,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [o setTableUrl: [self folderTableURL]]; [o reloadIfNeeded]; - if ([cKey hasPrefix: @"folder"]) + if ([cKey hasPrefix: @"folder"] || [cKey isEqualToString:@"(null)"]) { [commands appendFormat: @"%@", [[NSString stringWithFormat: @"mail/%@", [cKey substringFromIndex: 6]] stringByEscapingURL]] ; command_count++; @@ -849,6 +845,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. folderMetadata = [allFoldersMetadata objectAtIndex: i]; nameInCache = [NSString stringWithFormat: @"folder%@", [[folderMetadata objectForKey: @"path"] substringFromIndex: 1]]; + + // we have no guid - ignore the folder + if (![imapGUIDs objectForKey: nameInCache]) + continue; + serverId = [NSString stringWithFormat: @"mail/%@", [[imapGUIDs objectForKey: nameInCache] substringFromIndex: 6]]; name = [folderMetadata objectForKey: @"displayName"]; @@ -2480,8 +2481,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { // We check if it's a Ping command with no body. // See http://msdn.microsoft.com/en-us/library/ee200913(v=exchg.80).aspx for details - if ([cmdName caseInsensitiveCompare: @"Ping"] != NSOrderedSame && [cmdName caseInsensitiveCompare: @"GetAttachment"] != NSOrderedSame) - return [NSException exceptionWithHTTPStatus: 500]; + if ([cmdName caseInsensitiveCompare: @"Ping"] != NSOrderedSame && [cmdName caseInsensitiveCompare: @"GetAttachment"] != NSOrderedSame && [cmdName caseInsensitiveCompare: @"Sync"] != NSOrderedSame) + { + RELEASE(context); + RELEASE(pool); + return [NSException exceptionWithHTTPStatus: 500]; + } } if (d) diff --git a/ActiveSync/SOGoSyncCacheObject.m b/ActiveSync/SOGoSyncCacheObject.m index ab973348d..63c545b34 100644 --- a/ActiveSync/SOGoSyncCacheObject.m +++ b/ActiveSync/SOGoSyncCacheObject.m @@ -55,7 +55,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [o setUID: theUID]; [o setSequence: theSequence]; - return o; + return [o autorelease]; } - (void) dealloc diff --git a/ActiveSync/iCalEvent+ActiveSync.m b/ActiveSync/iCalEvent+ActiveSync.m index dc996f381..d1a4b6f8a 100644 --- a/ActiveSync/iCalEvent+ActiveSync.m +++ b/ActiveSync/iCalEvent+ActiveSync.m @@ -332,7 +332,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. iCalTimeZone *tz; id o; - NSInteger tzOffset; BOOL isAllDay; if ((o = [theValues objectForKey: @"UID"])) @@ -384,10 +383,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Some Windows devices don't send during event updates. //if ((o = [theValues objectForKey: @"TimeZone"])) // { - userTimeZone = [[[context activeUser] userDefaults] timeZone]; - tz = [iCalTimeZone timeZoneForName: [userTimeZone name]]; - [(iCalCalendar *) parent addTimeZone: tz]; - //} + // } + //else + { + // We haven't received a timezone, let's use the user's timezone + // specified in SOGo for now. + userTimeZone = [[[context activeUser] userDefaults] timeZone]; + tz = [iCalTimeZone timeZoneForName: [userTimeZone name]]; + [(iCalCalendar *) parent addTimeZone: tz]; + } // FIXME: merge with iCalToDo if ((o = [[theValues objectForKey: @"Body"] objectForKey: @"Data"])) @@ -402,21 +406,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"]; [start setTimeZone: tz]; - if (isAllDay) - { - tzOffset = [userTimeZone secondsFromGMTForDate: o]; - o = [o dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: tzOffset]; + if (isAllDay) + { [start setDate: o]; [start setTimeZone: nil]; } else { - tzOffset = [userTimeZone secondsFromGMTForDate: o]; - o = [o dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: tzOffset]; [start setDateTime: o]; } } @@ -429,19 +425,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. if (isAllDay) { - tzOffset = [userTimeZone secondsFromGMTForDate: o]; - o = [o dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: tzOffset]; [end setDate: o]; [end setTimeZone: nil]; } else { - tzOffset = [userTimeZone secondsFromGMTForDate: o]; - o = [o dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: tzOffset]; [end setDateTime: o]; } } diff --git a/ActiveSync/iCalToDo+ActiveSync.m b/ActiveSync/iCalToDo+ActiveSync.m index 58b0d4c04..5f237a31b 100644 --- a/ActiveSync/iCalToDo+ActiveSync.m +++ b/ActiveSync/iCalToDo+ActiveSync.m @@ -143,8 +143,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. iCalTimeZone *tz; id o; - NSInteger tzOffset; - userTimeZone = [[[context activeUser] userDefaults] timeZone]; tz = [iCalTimeZone timeZoneForName: [userTimeZone name]]; [(iCalCalendar *) parent addTimeZone: tz]; @@ -165,10 +163,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. o = [o calendarDate]; completed = (iCalDateTime *) [self uniqueChildWithTag: @"completed"]; - //tzOffset = [[o timeZone] secondsFromGMTForDate: o]; - //o = [o dateByAddingYears: 0 months: 0 days: 0 - // hours: 0 minutes: 0 - // seconds: -tzOffset]; [completed setDate: o]; [self setStatus: @"COMPLETED"]; } @@ -177,15 +171,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { iCalDateTime *due; - o = [o calendarDate]; due = (iCalDateTime *) [self uniqueChildWithTag: @"due"]; [due setTimeZone: tz]; - - tzOffset = [userTimeZone secondsFromGMTForDate: o]; - o = [o dateByAddingYears: 0 months: 0 days: 0 - hours: 0 minutes: 0 - seconds: tzOffset]; [due setDateTime: o]; } diff --git a/ChangeLog b/ChangeLog index 942c03d5f..f8728b5e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,122 @@ +commit ead665de85e2202dbde926c316cbba927d38dfa7 +Author: Ludovic Marcotte +Date: Mon Dec 29 16:19:10 2014 -0500 + + fix tz issue when the user one was different from the system one with EAS + +M ActiveSync/NSString+ActiveSync.m +M ActiveSync/iCalEvent+ActiveSync.m +M ActiveSync/iCalToDo+ActiveSync.m +M NEWS + +commit a0c1ce8f3b7c22002661d40c24e95a1233b6a6e8 +Author: Ludovic Marcotte +Date: Mon Dec 29 12:43:20 2014 -0500 + + Improved handling of non-existant vs. subscribed folders over EAS + +M ActiveSync/SOGoActiveSyncDispatcher.m +M SoObjects/Mailer/SOGoMailAccount.m +M SoObjects/Mailer/SOGoMailFolder.m + +commit 204a62aa6ac8feb5a13d5a2ee162bb26cc495a50 +Author: Ludovic Marcotte +Date: Tue Dec 23 10:25:53 2014 -0500 + + Improved comments in the code + +M SoObjects/Appointments/SOGoAppointmentFolder.m + +commit 31cffdffd34429d1f4873d07d67e822bff82b7cf +Author: Ludovic Marcotte +Date: Tue Dec 23 10:24:16 2014 -0500 + + Fix freebusy info not always returned + +M NEWS +M SoObjects/Appointments/SOGoAppointmentFolder.m +M SoObjects/SOGo/SOGoFolder.h +M SoObjects/SOGo/SOGoFolder.m + +commit 255bcbe92fa6b4610edf5f4d05c97b74537ecb6e +Author: Ludovic Marcotte +Date: Mon Dec 22 19:59:33 2014 -0500 + + Fixed memory leaks in SOGoSyncCacheObject and correctly kill the cache upon each EAS iteration + +M ActiveSync/SOGoSyncCacheObject.m +M SoObjects/Mailer/SOGoMailBaseObject.m +M SoObjects/SOGo/NSObject+Utilities.m +M UI/MainUI/SOGoMicrosoftActiveSyncActions.m + +commit 72732879fafe8ef928593c0cf3e39d962b096ec9 +Author: Ludovic Marcotte +Date: Mon Dec 22 19:32:17 2014 -0500 + + Added memory statistics - set SOGoDebugLeaks = YES and call [[self class] memoryStatistics] + +M SoObjects/SOGo/NSObject+Utilities.h +M SoObjects/SOGo/NSObject+Utilities.m + +commit 24a934275f5678f7ab86cb706aa817dfb5ef8991 +Author: Ludovic Marcotte +Date: Mon Dec 22 16:12:26 2014 -0500 + + Fix small memory leak incase of errors + +M ActiveSync/SOGoActiveSyncDispatcher.m + +commit 58f634bffe35b3a1f6a02072ba0103fea2155a45 +Author: Ludovic Marcotte +Date: Mon Dec 22 15:26:22 2014 -0500 + + Cosmetic improvements to the code + +M SoObjects/Appointments/SOGoAppointmentObject.m +M SoObjects/SOGo/SOGoMailer.h +M SoObjects/SOGo/SOGoMailer.m + +commit ca4a754f2c12784ff437df34c255d3dccbf5c6f2 +Author: Ludovic Marcotte +Date: Mon Dec 22 12:39:58 2014 -0500 + + Use the right cutoff date + +M ActiveSync/SOGoActiveSyncDispatcher+Sync.m +M NEWS +M SoObjects/SOGo/SOGoGCSFolder.m + +commit 8015688df31a3e3254093b260851d4664d725ea6 +Author: Ludovic Marcotte +Date: Mon Dec 22 11:50:51 2014 -0500 + + Added SOGoMaximumSyncResponseSize to support memory-limited EAS syncs + +M ActiveSync/SOGoActiveSyncDispatcher+Sync.m +M Documentation/SOGoInstallationGuide.asciidoc +M NEWS +M SoObjects/SOGo/SOGoSystemDefaults.h +M SoObjects/SOGo/SOGoSystemDefaults.m + +commit b07913d66d4a47919e09cbcd0c41d92bd97ea0a3 +Author: Ludovic Marcotte +Date: Mon Dec 22 08:36:55 2014 -0500 + + See NEWS file + +M ActiveSync/NGVCard+ActiveSync.m +M ActiveSync/SOGoActiveSyncDispatcher+Sync.m +M ActiveSync/SOGoActiveSyncDispatcher.m +M NEWS + +commit df8a0d8715d97873e782ccfbfaab8b580c88c66e +Author: Ludovic Marcotte +Date: Fri Dec 19 09:03:37 2014 -0500 + + Update ChangeLog + +M ChangeLog + commit e6cc56dca1126e09cb8336bdbd4e5dabc7b83cf1 Author: Ludovic Marcotte Date: Fri Dec 19 09:03:19 2014 -0500 @@ -15,6 +134,24 @@ Date: Fri Dec 19 09:01:39 2014 -0500 M NEWS M SoObjects/Mailer/SOGoDraftObject.m +commit 0e56527e05566e78ac8fe4687d19423de78b0276 +Author: Chris Rosenhain +Date: Fri Dec 19 11:04:05 2014 +1030 + + Change ACL modification text to non-gender specific terms + +M SoObjects/Appointments/SOGoAppointmentObject.m +M SoObjects/Appointments/SOGoCalendarComponent.m +M SoObjects/SOGo/SOGoGCSFolder.m +M SoObjects/SOGo/SOGoUserFolder.h +M UI/MainUI/SOGoRootPage.m +M UI/Templates/SOGoACLDanishModificationAdvisory.wox +M UI/Templates/SOGoACLDanishRemovalAdvisory.wox +M UI/Templates/SOGoACLDutchModificationAdvisory.wox +M UI/Templates/SOGoACLDutchRemovalAdvisory.wox +M UI/Templates/SOGoACLEnglishModificationAdvisory.wox +M UI/Templates/SOGoACLEnglishRemovalAdvisory.wox + commit db911f323d23f263f5fa9c5fb02d8234127687b3 Author: Ludovic Marcotte Date: Thu Dec 18 08:56:23 2014 -0500 diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index 36e6e65ba..08c819154 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -2390,6 +2390,15 @@ _SOGoMaximumPingInterval_. If not set, it defaults to `10` seconds. +|S |SOGoMaximumSyncResponseSize +|Parameter used to overwrite the maximum response size during +a Sync operation. The value is in kilobytes. Setting this to 512 +means the response size will be of 524288 bytes or less. Note that +if you set the value too low and a mail message (or any other object) +surpasses it, it will still be synced but only this item will be. + +Defaults to `0`, which means no overwrite is performed. + |S |SOGoMaximumSyncWindowSize |Parameter used to overwrite the maximum number of items returned during a Sync operation. diff --git a/Documentation/docinfo.xml b/Documentation/docinfo.xml index 247cd8a9b..aa1164747 100644 --- a/Documentation/docinfo.xml +++ b/Documentation/docinfo.xml @@ -1,7 +1,7 @@ -Version 2.2.12 - December 2014 -for version 2.2.12 -2014-12-18 +Version 2.2.13 - December 2014 +for version 2.2.13 +2014-12-30 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". diff --git a/Documentation/includes/global-attributes.asciidoc b/Documentation/includes/global-attributes.asciidoc index 064ce5b49..0bce4709c 100644 --- a/Documentation/includes/global-attributes.asciidoc +++ b/Documentation/includes/global-attributes.asciidoc @@ -13,6 +13,6 @@ // TODO have the build system take care of this -:release_version: 2.2.12 +:release_version: 2.2.13 // vim: set syntax=asciidoc tabstop=2 shiftwidth=2 expandtab: diff --git a/NEWS b/NEWS index e0fbbe3a0..e6aeb7c61 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,17 @@ +2.2.13 (2014-12-30) +------------------- + +Bug fixes + - fix contact description truncation on WP8 phones (#3028) + - fix freebusy information not always returned + - fix tz issue when the user one was different from the system one with EAS + +Enhancements + - initial support for empty sync request/response for EAS + - added the SOGoMaximumSyncResponseSize EAS configuration parameter to + support memory-limited sync response sizes + - we now not only use the creation date for event's cutoff date (EAS) + 2.2.12a (2014-12-19) -------------------- diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index a01c10c62..c3e29c9ca 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -492,6 +492,9 @@ static Class iCalEventK = nil; // // If the user is NOT the owner of the calendar, by default we exclude the freebusy information. // +// We must include the freebusy information of other users if we are actually looking at their freebusy information +// but we aren't necessarily subscribed to their calendars. +// - (BOOL) includeInFreeBusy { NSNumber *excludeFromFreeBusy; @@ -500,16 +503,31 @@ static Class iCalEventK = nil; userLogin = [[context activeUser] login]; is_owner = [userLogin isEqualToString: [self ownerInContext: context]]; - + // Check if the owner (not the active user) has excluded the calendar from her/his free busy data. excludeFromFreeBusy = [self folderPropertyValueInCategory: @"FreeBusyExclusions" forUser: [SOGoUser userWithLogin: userLogin]]; - if (!excludeFromFreeBusy && !is_owner) - return NO; - - return ![excludeFromFreeBusy boolValue]; + if ([self isSubscription]) + { + // If the user has not yet set an include/not include fb information let's EXCLUDE it. + if (!excludeFromFreeBusy) + return NO; + else + return ![excludeFromFreeBusy boolValue]; + } + else if (is_owner) + { + // We are the owner but we haven't included/excluded freebusy info, let's INCLUDE it. + if (!excludeFromFreeBusy) + return YES; + else + return ![excludeFromFreeBusy boolValue]; + } + + // It's not a subscribtion and we aren't the owner. Let's INCLUDE the freebusy info. + return YES; } - (void) setIncludeInFreeBusy: (BOOL) newInclude diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index f4ece14de..1d7538da1 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -400,9 +400,9 @@ { currentUID = [currentAttendee uid]; if (currentUID) - [self _addOrUpdateEvent: newEvent - forUID: currentUID - owner: owner]; + [self _addOrUpdateEvent: newEvent + forUID: currentUID + owner: owner]; } [self sendEMailUsingTemplateNamed: @"Update" @@ -443,7 +443,7 @@ us = [user userSettings]; moduleSettings = [us objectForKey:@"Calendar"]; - // Check if the user prevented his account from beeing invited to events + // Check if the user prevented their account from beeing invited to events if (![user isResource] && [[moduleSettings objectForKey:@"PreventInvitations"] boolValue]) { // Check if the user have a whiteList @@ -734,7 +734,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // the modification was actually NOT made on the master event if ([theEvent recurrenceId]) return; - + events = [[theEvent parent] events]; for (i = 0; i < [events count]; i++) @@ -743,12 +743,12 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent if ([e recurrenceId]) for (j = 0; j < [theAttendees count]; j++) if (shouldAdd) - [e addToAttendees: [theAttendees objectAtIndex: j]]; - else - [e removeFromAttendees: [theAttendees objectAtIndex: j]]; + [e addToAttendees: [theAttendees objectAtIndex: j]]; + else + [e removeFromAttendees: [theAttendees objectAtIndex: j]]; } } - + // // // @@ -803,14 +803,17 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // We insert the attendees in all exception occurences, if // the attendees were added to the master event. [self _addOrDeleteAttendees: addedAttendees - inRecurrenceExceptionsForEvent: newEvent - add: YES]; + inRecurrenceExceptionsForEvent: newEvent + add: YES]; if ([changes sequenceShouldBeIncreased]) { [newEvent increaseSequence]; + // Update attendees calendars and send them an update - // notification by email + // notification by email. We ignore the newly added + // attendees as we don't want to send them invitation + // update emails [self _handleSequenceUpdateInEvent: newEvent ignoringAttendees: addedAttendees fromOldEvent: oldEvent]; @@ -1093,7 +1096,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent else { // We must REMOVE any SENT-BY here. This is important since if A accepted - // the event for B and then, B changes by himself his participation status, + // the event for B and then, B changes by theirself their participation status, // we don't want to keep the previous SENT-BY attribute there. [(NSMutableDictionary *)[otherAttendee attributes] removeObjectForKey: @"SENT-BY"]; } @@ -1191,7 +1194,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent else { // We must REMOVE any SENT-BY here. This is important since if A accepted - // the event for B and then, B changes by himself his participation status, + // the event for B and then, B changes by theirself their participation status, // we don't want to keep the previous SENT-BY attribute there. [(NSMutableDictionary *)[attendee attributes] removeObjectForKey: @"SENT-BY"]; } @@ -1208,7 +1211,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent delegatedUID = [otherDelegate uid]; if (delegatedUID) - // Delegate attendee is a local user; remove event from his calendar + // Delegate attendee is a local user; remove event from their calendar [self _removeEventFromUID: delegatedUID owner: [theOwnerUser login] withRecurrenceId: [event recurrenceId]]; @@ -1240,7 +1243,7 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent [event addToAttendees: delegate]; if (delegatedUID) - // Delegate attendee is a local user; add event to his calendar + // Delegate attendee is a local user; add event to their calendar [self _addOrUpdateEvent: event forUID: delegatedUID owner: [theOwnerUser login]]; diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index f8822c061..ce600715b 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -644,8 +644,8 @@ // As much as we can, we try to use c_name == c_uid in order // to avoid tricky scenarios with some CalDAV clients. For example, // if Alice invites Bob (both use SOGo) and Bob accepts the invitation - // using Lightning before having refreshed his calendar, he'll end up - // with a duplicate of the event in his database tables. + // using Lightning before having refreshed their calendar, they'll end up + // with a duplicate of the event in their database tables. if (isNew) { newUid = nameInContainer; diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index 772c49ecd..97057a1c4 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -40,6 +40,7 @@ #import #import #import +#import #import #import @@ -667,19 +668,14 @@ static NSString *inboxFolderName = @"INBOX"; NSDictionary *result, *nresult, *namespaceDict; NSMutableDictionary *folders; NGImap4Client *client; - SOGoUserDefaults *ud; NSArray *folderList; NSEnumerator *e; NSString *guid; id object; - BOOL subscribedOnly, hasAnnotatemore; + BOOL hasAnnotatemore; - ud = [[context activeUser] userDefaults]; - subscribedOnly = [ud mailShowSubscribedFoldersOnly]; - - folderList = [[self imap4Connection] allFoldersForURL: [self imap4URL] - onlySubscribedFolders: subscribedOnly]; + folderList = [self allFolderPaths]; folders = [NSMutableDictionary dictionary]; @@ -688,19 +684,19 @@ static NSString *inboxFolderName = @"INBOX"; hasAnnotatemore = [self hasCapability: @"annotatemore"]; if (hasAnnotatemore) - result = [client annotation: @"*" entryName: @"/comment" attributeName: @"value.priv"]; + result = [client annotation: @"*" entryName: @"/comment" attributeName: @"value.priv"]; else - result = [client lstatus: @"*" flags: [NSArray arrayWithObjects: @"x-guid", nil]]; - + result = [client lstatus: @"*" flags: [NSArray arrayWithObjects: @"x-guid", nil]]; + e = [folderList objectEnumerator]; - + while ((object = [e nextObject])) { if (hasAnnotatemore) - guid = [[[[result objectForKey: @"FolderList"] objectForKey: [object substringFromIndex: 1]] objectForKey: @"/comment"] objectForKey: @"value.priv"]; + guid = [[[[result objectForKey: @"FolderList"] objectForKey: [object substringFromIndex: 1]] objectForKey: @"/comment"] objectForKey: @"value.priv"]; else - guid = [[[result objectForKey: @"status"] objectForKey: [object substringFromIndex: 1]] objectForKey: @"x-guid"]; - + guid = [[[result objectForKey: @"status"] objectForKey: [object substringFromIndex: 1]] objectForKey: @"x-guid"]; + if (!guid) { // Don't generate a GUID for "Other users" and "Shared" namespace folders - user foldername instead @@ -710,18 +706,28 @@ static NSString *inboxFolderName = @"INBOX"; [folders setObject: [NSString stringWithFormat: @"folder%@", [object substringFromIndex: 1]] forKey: [NSString stringWithFormat: @"folder%@", [object substringFromIndex: 1]]]; continue; } - - guid = [[NSProcessInfo processInfo] globallyUniqueString]; - nresult = [client annotation: [object substringFromIndex: 1] entryName: @"/comment" attributeName: @"value.priv" attributeValue: guid]; - if (![[nresult objectForKey: @"result"] boolValue]) - guid = [NSString stringWithFormat: @"%@", [object substringFromIndex: 1]]; + // if folder doesn't exists - ignore it + nresult = [client status: [object substringFromIndex: 1] + flags: [NSArray arrayWithObject: @"UIDVALIDITY"]]; + if (![[nresult valueForKey: @"result"] boolValue]) + continue; + + if (hasAnnotatemore) + { + guid = [[NSProcessInfo processInfo] globallyUniqueString]; + nresult = [client annotation: [object substringFromIndex: 1] entryName: @"/comment" attributeName: @"value.priv" attributeValue: guid]; + } + + // setannotation failed or annotatemore is not available + if (![[nresult objectForKey: @"result"] boolValue] || !hasAnnotatemore) + guid = [NSString stringWithFormat: @"%@", [object substringFromIndex: 1]]; } - + [folders setObject: [NSString stringWithFormat: @"folder%@", guid] forKey: [NSString stringWithFormat: @"folder%@", [object substringFromIndex: 1]]]; - + } - + return folders; } diff --git a/SoObjects/Mailer/SOGoMailBaseObject.m b/SoObjects/Mailer/SOGoMailBaseObject.m index 73967efe0..863491e2e 100644 --- a/SoObjects/Mailer/SOGoMailBaseObject.m +++ b/SoObjects/Mailer/SOGoMailBaseObject.m @@ -43,10 +43,6 @@ @implementation SOGoMailBaseObject -#if 0 -static BOOL debugOn = YES; -#endif - - (id) initWithImap4URL: (NSURL *) _url inContainer: (id) _container { diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index 3607b9dd2..d83ca78a6 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -1069,7 +1069,11 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data) NSException *error; if ([self imap4Connection]) - error = [imap4 deleteMailboxAtURL: [self imap4URL]]; + { + error = [imap4 deleteMailboxAtURL: [self imap4URL]]; + if (!error) + [[imap4 client] unsubscribe: [[self imap4URL] path]]; + } else error = [NSException exceptionWithName: @"SOGoMailException" reason: @"IMAP connection is invalid" diff --git a/SoObjects/SOGo/NSObject+Utilities.h b/SoObjects/SOGo/NSObject+Utilities.h index 469eab8b9..102ab7ef3 100644 --- a/SoObjects/SOGo/NSObject+Utilities.h +++ b/SoObjects/SOGo/NSObject+Utilities.h @@ -40,6 +40,8 @@ - (NSString *) labelForKey: (NSString *) key inContext: (WOContext *) context; ++ (void) memoryStatistics; + @end #endif /* NSOBJECT+UTILITIES_H */ diff --git a/SoObjects/SOGo/NSObject+Utilities.m b/SoObjects/SOGo/NSObject+Utilities.m index 2f9ed96cd..3dca1f0f5 100644 --- a/SoObjects/SOGo/NSObject+Utilities.m +++ b/SoObjects/SOGo/NSObject+Utilities.m @@ -22,6 +22,7 @@ #import #import +#import #import #import @@ -122,4 +123,33 @@ return label; } +// +// Set SOGoDebugLeaks = YES in your defaults to enable. +// ++ (void) memoryStatistics +{ + Class *classList = GSDebugAllocationClassList (); + Class *pointer; + int i, count, total, peak; + NSString *className; + + pointer = classList; + i = 0; + + printf("Class count total peak\n"); + while (pointer[i] != NULL) + { + className = NSStringFromClass (pointer[i]); + count = GSDebugAllocationCount (pointer[i]); + total = GSDebugAllocationTotal (pointer[i]); + peak = GSDebugAllocationPeak (pointer[i]); + + printf("%s %d %d %d\n", [className UTF8String], count, total, peak); + i++; + } + NSZoneFree(NSDefaultMallocZone(), classList); + + printf("Done!\n"); +} + @end diff --git a/SoObjects/SOGo/SOGoFolder.h b/SoObjects/SOGo/SOGoFolder.h index 186036db3..018cfe7e0 100644 --- a/SoObjects/SOGo/SOGoFolder.h +++ b/SoObjects/SOGo/SOGoFolder.h @@ -1,6 +1,6 @@ /* SOGoFolder.h - this file is part of SOGo * - * Copyright (C) 2007-2013 Inverse inc. + * Copyright (C) 2007-2014 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 diff --git a/SoObjects/SOGo/SOGoFolder.m b/SoObjects/SOGo/SOGoFolder.m index a27466cdd..a390b9267 100644 --- a/SoObjects/SOGo/SOGoFolder.m +++ b/SoObjects/SOGo/SOGoFolder.m @@ -1,8 +1,6 @@ /* SOGoFolder.m - this file is part of SOGo * - * Copyright (C) 2007-2011 Inverse inc. - * - * Author: Wolfgang Sourdeau + * Copyright (C) 2007-2014 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 diff --git a/SoObjects/SOGo/SOGoGCSFolder.m b/SoObjects/SOGo/SOGoGCSFolder.m index 921d312c0..9f77359e9 100644 --- a/SoObjects/SOGo/SOGoGCSFolder.m +++ b/SoObjects/SOGo/SOGoGCSFolder.m @@ -302,7 +302,7 @@ static NSArray *childRecordFields = nil; } /* This method fetches the display name defined by the owner, but is also the - fallback when a subscriber has not redefined the display name yet in his + fallback when a subscriber has not redefined the display name yet in their environment. */ - (NSString *) _displayNameFromOwner { @@ -895,7 +895,7 @@ static NSArray *childRecordFields = nil; allUsers = [NSMutableArray arrayWithArray: [aGroup members]]; // We remove the active user from the group (if present) in order to - // not subscribe him to his own resource! + // not subscribe him to their own resource! [allUsers removeObject: [context activeUser]]; } else @@ -1165,7 +1165,14 @@ static NSArray *childRecordFields = nil; int syncTokenInt; fields = [NSMutableArray arrayWithObjects: @"c_name", @"c_component", - @"c_creationdate", @"c_lastmodified", nil]; + @"c_creationdate", @"c_lastmodified", nil]; + + if ([[self folderType] isEqualToString: @"Appointment"]) + { + [fields addObject: @"c_enddate"]; + [fields addObject: @"c_cycleenddate"]; + } + addFields = [[properties allValues] objectEnumerator]; while ((currentField = [addFields nextObject])) if ([currentField length]) @@ -1181,7 +1188,9 @@ static NSArray *childRecordFields = nil; if (theStartDate) { EOQualifier *sinceDateQualifier = [EOQualifier qualifierWithQualifierFormat: - @"c_creationdate > %d", (int)[theStartDate timeIntervalSince1970]]; + @"(c_enddate > %d OR c_enddate = NULL) OR (c_iscycle = 1 and (c_cycleenddate > %d OR c_cycleenddate = NULL))", + (int)[theStartDate timeIntervalSince1970], + (int)[theStartDate timeIntervalSince1970]]; qualifier = [[EOAndQualifier alloc] initWithQualifiers: sinceDateQualifier, qualifier, nil]; @@ -1211,7 +1220,9 @@ static NSArray *childRecordFields = nil; if (theStartDate) { EOQualifier *sinceDateQualifier = [EOQualifier qualifierWithQualifierFormat: - @"c_creationdate > %d", (int)[theStartDate timeIntervalSince1970]]; + @"(c_enddate > %d OR c_enddate = NULL) OR (c_iscycle = 1 and (c_cycleenddate > %d OR c_cycleenddate = NULL))", + (int)[theStartDate timeIntervalSince1970], + (int)[theStartDate timeIntervalSince1970]]; qualifier = [[EOAndQualifier alloc] initWithQualifiers: sinceDateQualifier, qualifier, nil]; diff --git a/SoObjects/SOGo/SOGoMailer.h b/SoObjects/SOGo/SOGoMailer.h index 6ebc0ef7d..6f82092e2 100644 --- a/SoObjects/SOGo/SOGoMailer.h +++ b/SoObjects/SOGo/SOGoMailer.h @@ -1,8 +1,6 @@ /* SOGoMailer.h - this file is part of SOGo * - * Copyright (C) 2007 Inverse inc. - * - * Author: Wolfgang Sourdeau + * Copyright (C) 2007-2014 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 diff --git a/SoObjects/SOGo/SOGoMailer.m b/SoObjects/SOGo/SOGoMailer.m index bbf59540d..413c29a96 100644 --- a/SoObjects/SOGo/SOGoMailer.m +++ b/SoObjects/SOGo/SOGoMailer.m @@ -1,8 +1,6 @@ /* SOGoMailer.m - this file is part of SOGo * - * Copyright (C) 2007-2013 Inverse inc. - * - * Author: Wolfgang Sourdeau + * Copyright (C) 2007-2014 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 diff --git a/SoObjects/SOGo/SOGoSystemDefaults.h b/SoObjects/SOGo/SOGoSystemDefaults.h index de5a140fa..7f811f208 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.h +++ b/SoObjects/SOGo/SOGoSystemDefaults.h @@ -99,6 +99,7 @@ - (int) maximumSyncInterval; - (int) internalSyncInterval; - (int) maximumSyncWindowSize; +- (int) maximumSyncResponseSize; @end diff --git a/SoObjects/SOGo/SOGoSystemDefaults.m b/SoObjects/SOGo/SOGoSystemDefaults.m index f9aa5fcc2..9fbb9ef48 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.m +++ b/SoObjects/SOGo/SOGoSystemDefaults.m @@ -636,4 +636,16 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict, return [self integerForKey: @"SOGoMaximumSyncWindowSize"]; } +- (int) maximumSyncResponseSize +{ + int v; + + v = [self integerForKey: @"SOGoMaximumSyncResponseSize"]; + + if (v > 0) + v = v * 1024; + + return v; +} + @end diff --git a/SoObjects/SOGo/SOGoUserFolder.h b/SoObjects/SOGo/SOGoUserFolder.h index 4ee6bdd65..0621728a7 100644 --- a/SoObjects/SOGo/SOGoUserFolder.h +++ b/SoObjects/SOGo/SOGoUserFolder.h @@ -31,7 +31,7 @@ Child objects: 'Calendar': SOGoAppointmentFolder - The SOGoUserFolder is the "home directory" of the user where all his + The SOGoUserFolder is the "home directory" of the user where all their processing starts. It is the 'znek' in such a path: /SOGo/so/znek/Calendar */ diff --git a/UI/MainUI/SOGoMicrosoftActiveSyncActions.m b/UI/MainUI/SOGoMicrosoftActiveSyncActions.m index a00344fba..c487d5cce 100644 --- a/UI/MainUI/SOGoMicrosoftActiveSyncActions.m +++ b/UI/MainUI/SOGoMicrosoftActiveSyncActions.m @@ -21,6 +21,8 @@ #import +#import +#import #import #import @@ -54,13 +56,17 @@ ex = [dispatcher dispatchRequest: request inResponse: response context: context]; + //[[self class] memoryStatistics]; + if (ex) { return [NSException exceptionWithHTTPStatus: 500]; } RELEASE(dispatcher); - + + [[SOGoCache sharedCache] killCache]; + return response; } diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index d8e32c1db..df3e944b1 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -361,7 +361,7 @@ if (login) { - /* We redirect the user to his "homepage" when newLocation could not be + /* We redirect the user to their "homepage" when newLocation could not be deduced from the "cas-location" cookie and the current action is not a login callback (ticket != nil). */ if (!newLocation || !ticket) diff --git a/UI/Templates/SOGoACLDanishModificationAdvisory.wox b/UI/Templates/SOGoACLDanishModificationAdvisory.wox index 20b7dbb0a..929552839 100644 --- a/UI/Templates/SOGoACLDanishModificationAdvisory.wox +++ b/UI/Templates/SOGoACLDanishModificationAdvisory.wox @@ -12,7 +12,7 @@ - has modified your access rights for his folder. + has modified your access rights for their folder.