View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0002734 | SOGo | ActiveSync | public | 2014-04-24 19:29 | 2014-06-25 19:07 |
| Reporter | tfu | Assigned To | ludovic | ||
| Priority | normal | Severity | minor | Reproducibility | always |
| Status | resolved | Resolution | fixed | ||
| Product Version | 2.2.3 | ||||
| Target Version | 2.2.6 | Fixed in Version | 2.2.6 | ||
| Summary | 0002734: mails are not removed from device when outside of the date range to be downloaded | ||||
| Description | If "Download past mail" is set e.g. to 3 days mails older than that timeframe should be removed from the device if previously synced. | ||||
| Tags | No tags attached. | ||||
|
0001-mail-softdelete.patch (11,522 bytes)
From 3e51b66d8ef1656567ec7ceb6e2aa4c2a96cefab Mon Sep 17 00:00:00 2001
From: root <root@example.com>
Date: Thu, 24 Apr 2014 21:21:41 +0200
Subject: [PATCH] mail-softdelete
---
ActiveSync/SOGoActiveSyncDispatcher+Sync.m | 69 ++++++++++++++++++++++++----
ActiveSync/SOGoActiveSyncDispatcher.m | 19 ++++++++
SoObjects/Mailer/SOGoMailFolder.h | 3 +-
SoObjects/Mailer/SOGoMailFolder.m | 33 +++++++++++++
4 files changed, 115 insertions(+), 9 deletions(-)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
index 396c266..0668cb0 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
@@ -442,12 +442,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
BOOL more_available;
int i, max;
+ // tfu softdelete - extract the 3rd pard of the SyncKey if available (this is the date of the oldest mail synced)
+ NSArray *a;
+ NSString *oldestDate;
+
+ NSLog(@"tfu - old theSyncKey %@", theSyncKey);
+ if (theFolderType == ActiveSyncMailFolder) {
+ a = [theSyncKey componentsSeparatedByString: @"-"];
+ if ([a count] > 2) {
+ oldestDate = [a objectAtIndex: 2];
+ theSyncKey = [NSString stringWithFormat: @"%@-%@",[a objectAtIndex: 0], [a objectAtIndex: 1]];
+ } else {
+ oldestDate = nil;
+ }
+ } else {
+ oldestDate = nil;
+ }
+
+ NSLog(@"tfu - new theSyncKey %@ oldestDate %@", theSyncKey, oldestDate);
+
//
// No changes in the collection - 2.2.2.19.1.1 Empty Sync Request.
// We check this and we don't generate any commands if we don't have to.
//
- if ([theSyncKey isEqualToString: [theCollection davCollectionTag]])
- return;
+ if ([theSyncKey isEqualToString: [theCollection davCollectionTag]]) {
+ NSLog(@"tfu no change -- checking cutof date");
+ // tfu if the oldestDate is == to the current filter (cutoff date) then there is nothing to do about softdelets
+ if (oldestDate && theFilterType) {
+ NSLog(@"tfu dayOfCommonEra Oldest %d", [[[NSCalendarDate alloc] initWithTimeIntervalSince1970:[oldestDate intValue]] dayOfCommonEra]);
+ NSLog(@"tfu dayOfCommonEra Filder %d", [theFilterType dayOfCommonEra]);
+ if ( [[[NSCalendarDate alloc] initWithTimeIntervalSince1970:[oldestDate intValue]] dayOfCommonEra] == [theFilterType dayOfCommonEra])
+ return;
+ }
+ else
+ return;
+ }
s = [NSMutableString string];
more_available = NO;
@@ -574,10 +603,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NSArray *allMessages;
int deleted_count;
- allMessages = [theCollection syncTokenFieldsWithProperties: nil matchingSyncToken: theSyncKey fromDate: theFilterType];
+ allMessages = [theCollection syncTokenFieldsWithProperties: nil matchingSyncToken: theSyncKey fromDate: theFilterType oldestDate: oldestDate];
addedOrChangedMessages = [NSMutableArray array];
deleted_count = 0;
-
+
// Check for the WindowSize.
// FIXME: we should eventually check for modseq and slice the maximum
// amount of messages returned to ensure we don't have the same
@@ -597,12 +626,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ([command isEqualToString: @"deleted"])
{
+ NSLog(@"tfu delete uid=%@", uid);
[s appendString: @"<Delete xmlns=\"AirSync:\">"];
[s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
[s appendString: @"</Delete>"];
deleted_count++;
}
- else
+ else if ([command isEqualToString: @"softdelete"]) {
+ NSLog(@"tfu softdelete uid=%@", uid);
+ [s appendString: @"<SoftDelete xmlns=\"AirSync:\">"];
+ [s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", uid];
+ [s appendString: @"</SoftDelete>"];
+ deleted_count++;
+ }
+ else
{
[addedOrChangedMessages addObject: aMessage];
}
@@ -633,6 +670,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
command = @"changed";
}
+ NSLog(@"tfu %@ uid %@", command, uid);
+
if ([command isEqualToString: @"added"])
[s appendString: @"<Add xmlns=\"AirSync:\">"];
else
@@ -768,7 +807,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NSMutableString *changeBuffer, *commandsBuffer;
BOOL getChanges, first_sync;
unsigned int windowSize, v;
-
+
changeBuffer = [NSMutableString string];
commandsBuffer = [NSMutableString string];
@@ -783,7 +822,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (windowSize == 0 || windowSize > 512)
windowSize = 100;
-
+
// We check if we must overwrite the windowSize with a system preference. This can be useful
// if the user population has large mailboxes and slow connectivity
if ((v = [[SOGoSystemDefaults sharedSystemDefaults] maximumSyncWindowSize]))
@@ -879,7 +918,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else if (folderType == ActiveSyncTaskFolder)
[theBuffer appendString: @"<Class>Tasks</Class>"];
- [theBuffer appendFormat: @"<SyncKey>%@</SyncKey>", davCollectionTag];
+
+ //tfu soft-delete - if a date filter is set and changes have been found then there should be no older mails on device -> the "oldestDate" can be updated
+ if ([NSCalendarDate dateFromFilterType: [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]] && [changeBuffer length]) {
+ [theBuffer appendFormat: @"<SyncKey>%@-%@</SyncKey>", davCollectionTag,
+ [NSString stringWithFormat: @"%d",(int)[[NSCalendarDate dateFromFilterType:
+ [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]] timeIntervalSince1970]]];
+ NSLog(@"tfu serverkey with date x %@ %@",davCollectionTag,
+ [NSString stringWithFormat: @"%d",(int)[[NSCalendarDate dateFromFilterType:
+ [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]] timeIntervalSince1970]]);
+ }
+ else {
+ [theBuffer appendFormat: @"<SyncKey>%@</SyncKey>", davCollectionTag];
+ }
+
+
[theBuffer appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
[theBuffer appendFormat: @"<Status>%d</Status>", 1];
diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m
index b1b8e4e..68925aa 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher.m
@@ -634,6 +634,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sortOrdering: @"REVERSE ARRIVAL"
threaded: NO];
count = [uids count];
+
+ // tfu if nothing found lets see whether there are softdeletes which needs to be handled.
+ if (count == 0) {
+ NSString *syncKey;
+ NSArray *a;
+ NSString *oldestDate;
+
+ syncKey = [[(id)[theDocumentElement getElementsByTagName: @"SyncKey"] lastObject] textValue];
+ a = [syncKey componentsSeparatedByString: @"-"];
+ if ([a count] > 2) {
+ oldestDate = [a objectAtIndex: 2];
+ NSLog(@"tfu GetItmeEstimate dayOfCommonEra Oldest %d", [[[NSCalendarDate alloc] initWithTimeIntervalSince1970:[oldestDate intValue]] dayOfCommonEra]);
+ NSLog(@"tfu GetItmeEstimate dayOfCommonEra Filder %d", [filter dayOfCommonEra]);
+ if ( [[[NSCalendarDate alloc] initWithTimeIntervalSince1970:[oldestDate intValue]] dayOfCommonEra] != [filter dayOfCommonEra] && [filter dayOfCommonEra] > 0)
+ count=1;
+ }
+ }
}
else
{
@@ -647,6 +664,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
[s appendFormat: @"<Estimate>%d</Estimate>", count];
+ NSLog(@"tfu GetItmeEstimate count %d", count);
+
[s appendString: @"</Collection></Response></GetItemEstimate>"];
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h
index eac1aec..441031b 100644
--- a/SoObjects/Mailer/SOGoMailFolder.h
+++ b/SoObjects/Mailer/SOGoMailFolder.h
@@ -99,7 +99,8 @@
- (NSArray *) syncTokenFieldsWithProperties: (NSDictionary *) properties
matchingSyncToken: (NSString *) syncToken
- fromDate: (NSCalendarDate *) theStartDate;
+ fromDate: (NSCalendarDate *) theStartDate
+ oldestDate: (NSString *) theOldestDate;
/* flags */
diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m
index 6408828..c42ad8f 100644
--- a/SoObjects/Mailer/SOGoMailFolder.m
+++ b/SoObjects/Mailer/SOGoMailFolder.m
@@ -2030,6 +2030,7 @@ static NSString *defaultUserID = @"anyone";
- (NSArray *) syncTokenFieldsWithProperties: (NSArray *) theProperties
matchingSyncToken: (NSString *) theSyncToken
fromDate: (NSCalendarDate *) theStartDate
+ oldestDate: (NSString *) theOldestDate
{
EOQualifier *searchQualifier;
NSMutableArray *allTokens;
@@ -2122,6 +2123,38 @@ static NSString *defaultUserID = @"anyone";
d = [NSDictionary dictionaryWithObject: @"deleted" forKey: uid];
[allTokens addObject: d];
}
+ if (theStartDate)
+ {
+ EOQualifier *sinceDateQualifier, *beforeDateQualifier;
+ EOAndQualifier *qualifier;
+ NSArray *uids;
+
+ beforeDateQualifier = [EOQualifier qualifierWithQualifierFormat:
+ @"(DATE >= %@)", [[NSCalendarDate alloc] initWithTimeIntervalSince1970:[theOldestDate intValue]] ];
+
+
+ sinceDateQualifier = [EOQualifier qualifierWithQualifierFormat:
+ @"(DATE <= %@)", theStartDate ];
+
+
+ qualifier = [[EOAndQualifier alloc] initWithQualifiers: [self _nonDeletedQualifier], sinceDateQualifier, beforeDateQualifier,
+ nil];
+ AUTORELEASE(qualifier);
+
+ uids = [self fetchUIDsMatchingQualifier: qualifier
+ sortOrdering: nil
+ ];
+
+ for (i = 0; i < [uids count]; i++)
+ {
+ uid = [uids objectAtIndex: i];
+ NSLog(@"tfu uid %@ OldestDate %@", uid , theOldestDate);
+ d = [NSDictionary dictionaryWithObject: @"softdelete" forKey: uid];
+ [allTokens addObject: d];
+ }
+
+ NSLog(@"tfu softdelete %d theOldestDate %@ theStartDate %@", [uids count], theOldestDate, theStartDate);
+ }
}
return allTokens;
--
1.7.9.5
|
|
|
0002-mail-softdelete-hasPrefix.patch (1,321 bytes)
From 5a97832e5c3d7acd532fb7352185a02eb1fdf012 Mon Sep 17 00:00:00 2001
From: root <root@example.com>
Date: Tue, 29 Apr 2014 10:22:17 +0200
Subject: [PATCH 2/2] mail-softdelete-hasPrefix
---
ActiveSync/SOGoActiveSyncDispatcher+Sync.m | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
index 0668cb0..9b59b9e 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
@@ -465,8 +465,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// No changes in the collection - 2.2.2.19.1.1 Empty Sync Request.
// We check this and we don't generate any commands if we don't have to.
//
- if ([theSyncKey isEqualToString: [theCollection davCollectionTag]]) {
- NSLog(@"tfu no change -- checking cutof date");
+ if ([theSyncKey hasPrefix: [theCollection davCollectionTag]]) {
+ NSLog(@"tfu no change -- checking cutoff date");
// tfu if the oldestDate is == to the current filter (cutoff date) then there is nothing to do about softdelets
if (oldestDate && theFilterType) {
NSLog(@"tfu dayOfCommonEra Oldest %d", [[[NSCalendarDate alloc] initWithTimeIntervalSince1970:[oldestDate intValue]] dayOfCommonEra]);
--
1.7.9.5
|
|
|
While doing additional tests I found a small amendment to the first patch. |
|
|
For this one, instead of storing the date in the SyncKey, I suggest storing it inside our new cache system (coming up!). In our new cache system, we'll store a structure like this: message-uid -> (sequence, last-seen). Last-seen could be updated during a Change command, otherwise it'll be set to 'now' when we Add it. When proceeding with processSyncGetChanges... we could then loop in the cache and soft-delete everything based on the filter-type. Makes sense? |
|
|
The new caching code has landed. You must re-create the ActiveSync profile if you want to test it. Could you adapt your patch to the new code? Please have a look at SOGActiveSyncDispatcher+Sync.m and search for "DateCache". I've modified to code to ease your work. |
|
|
0001-softDelete-with-dateCache.patch (5,375 bytes)
From 4ab660a94c98924a1f30cbbbf16f43bef509c052 Mon Sep 17 00:00:00 2001
From: root <root@example.com>
Date: Sun, 18 May 2014 15:16:37 +0200
Subject: [PATCH] softDelete with dateCache
---
ActiveSync/SOGoActiveSyncDispatcher+Sync.m | 40 +++++++++++++++++++++++++++-
ActiveSync/SOGoActiveSyncDispatcher.h | 1 +
ActiveSync/SOGoActiveSyncDispatcher.m | 25 +++++++++++++++++
3 files changed, 65 insertions(+), 1 deletion(-)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
index 49cc21c..14fb5db 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
@@ -483,7 +483,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// No changes in the collection - 2.2.2.19.1.1 Empty Sync Request.
// We check this and we don't generate any commands if we don't have to.
//
- if ([theSyncKey isEqualToString: [theCollection davCollectionTag]])
+ if ([theSyncKey isEqualToString: [theCollection davCollectionTag]] && !([self checkSoftDeletes: [theCollection nameInContainer]]))
return;
s = [NSMutableString string];
@@ -642,6 +642,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
else
folderMetadata = [self _folderMetadataForKey: [theCollection nameInContainer]];
+
syncCache = [folderMetadata objectForKey: @"SyncCache"];
dateCache = [folderMetadata objectForKey: @"DateCache"];
@@ -711,6 +712,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: @"</Delete>"];
[syncCache removeObjectForKey: [aCacheObject uid]];
+ [dateCache removeObjectForKey: [aCacheObject uid]];
}
else
{
@@ -773,6 +775,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//NSLog(@"skipping old deleted UID: %@", [aCacheObject uid]);
}
}
+
+ }
+
+ // handle soft-deletes
+ if (theFilterType) {
+ for (NSString* key in [dateCache allKeys]) {
+ if (return_count >= theWindowSize)
+ {
+ more_available = YES;
+
+ if (!(*theLastServerKey))
+ *theLastServerKey = [theCollection davCollectionTag];
+
+ // make sure that checkSoftDelets find some work
+ NSString *cacheKey;
+ cacheKey = [NSString stringWithFormat: @"%@+%@+%@",
+ [[context activeUser] login],
+ [context objectForKey: @"DeviceId"],
+ [theCollection nameInContainer]];
+
+ [[SOGoCache sharedCache] setValue: @"0" forKey: cacheKey];
+
+ break;
+ }
+
+ if ([[dateCache objectForKey:key] compare: theFilterType ] == NSOrderedAscending )
+ {
+ [s appendString: @"<SoftDelete xmlns=\"AirSync:\">"];
+ [s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", key];
+ [s appendString: @"</SoftDelete>"];
+
+ [dateCache removeObjectForKey: key];
+ [syncCache removeObjectForKey: key];
+ return_count++;
+ }
+ }
}
if (more_available)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher.h b/ActiveSync/SOGoActiveSyncDispatcher.h
index eda6a3d..2dd7acd 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher.h
+++ b/ActiveSync/SOGoActiveSyncDispatcher.h
@@ -49,5 +49,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (NSURL *) folderTableURL;
- (void) ensureFolderTableExists;
+- (BOOL) checkSoftDeletes: (NSString *) theFolder;
@end
diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m
index d8c2807..b035cab 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher.m
@@ -165,6 +165,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
return [o properties];
}
+- (BOOL) checkSoftDeletes: (NSString *) theFolder
+{
+
+ NSString *key, *value;
+
+ key = [NSString stringWithFormat: @"%@+%@+%@",
+ [[context activeUser] login],
+ [context objectForKey: @"DeviceId"],
+ theFolder];
+ value = [NSString stringWithFormat: @"%d", [[NSCalendarDate date] dayOfCommonEra]];
+
+ if ([[[SOGoCache sharedCache] valueForKey: key] isEqualToString: value]) {
+ return false;
+ }
+
+ [[SOGoCache sharedCache] setValue: value forKey: key];
+
+ return true;
+}
+
//
//
//
@@ -668,6 +688,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sortOrdering: @"REVERSE ARRIVAL"
threaded: NO];
count = [uids count];
+
+ if (count == 0) {
+ if ( [self checkSoftDeletes: [currentCollection nameInContainer]] )
+ count = 1;
+ }
}
else
{
--
1.7.9.5
|
|
|
Please review attached patch. |
|
|
I've reviewed the patch. I don't really like the idea of using SOGoCache to detect if we must process soft-deletes or not. Why not modify GetItemEstimate so that it gets the 'dateCache' and count properly the number of items that are about to be soft-deleted? |
|
|
I'm not sure whether I understand your suggestion. After counting the soft-deletes in GetItemEstimate how can following line in processSyncGetChanges be passed if nothing else has changed in the folder: It would be cool if you could amend the patch with what you have in mind. |
|
|
That check should be moved down after we check for soft-deletes. |
|
|
Why -checkSoftDeletes doesn't return the item count to delete? You know what to delete by looking at the cache. |
|
|
0003-sd2.patch (4,028 bytes)
From 96aab54fcd65bd7702ff526342b343a1d50abbd1 Mon Sep 17 00:00:00 2001
From: root <root@example.com>
Date: Tue, 27 May 2014 20:02:32 +0200
Subject: [PATCH 3/3] sd2
---
ActiveSync/SOGoActiveSyncDispatcher+Sync.m | 44 ++++++++++++++++++++++++++--
ActiveSync/SOGoActiveSyncDispatcher.m | 21 +++++++++++++
2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
index 91f5d5d..787fe9a 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
@@ -480,7 +480,47 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NSMutableString *s;
BOOL more_available;
- int i, max;
+ int i, max, sd_count;
+ s = [NSMutableString string];
+
+ NSMutableDictionary *folderMetadata, *dateCache, *syncCache;
+ NSMutableArray *sdUids;
+
+ if (theFolderType == ActiveSyncMailFolder && !([theSyncKey isEqualToString: @"-1"])) {
+ if (theFilterType) {
+ sdUids =[[NSMutableArray alloc] init];
+ sd_count=0;
+
+ folderMetadata = [self _folderMetadataForKey: [theCollection nameInContainer]];
+ dateCache = [folderMetadata objectForKey: @"DateCache"];
+ syncCache = [folderMetadata objectForKey: @"SyncCache"];
+
+ for (NSString* key in [dateCache allKeys]) {
+ if ([[dateCache objectForKey:key] compare: theFilterType ] == NSOrderedAscending ) {
+ [s appendString: @"<SoftDelete xmlns=\"AirSync:\">"];
+ [s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", key];
+ [s appendString: @"</SoftDelete>"];
+NSLog(@"tfu softdelete %@ %@",key,syncCache);
+NSLog(@"tfu softdelete %@ %@",key,dateCache);
+ [syncCache removeObjectForKey: key];
+ [dateCache removeObjectForKey: key];
+
+ sd_count++;
+ }
+
+ if (sd_count >= theWindowSize) {
+ [folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"];
+ *theLastServerKey = theSyncKey;
+
+ [self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
+
+ return;
+ }
+ }
+
+ [self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
+ }
+ }
//
// No changes in the collection - 2.2.2.19.1.1 Empty Sync Request.
@@ -489,8 +529,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if ([theSyncKey isEqualToString: [theCollection davCollectionTag]])
return;
- s = [NSMutableString string];
-
more_available = NO;
switch (theFolderType)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m
index 48d5c53..fd99bab 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher.m
@@ -845,6 +845,27 @@ break;
sortOrdering: @"REVERSE ARRIVAL"
threaded: NO];
count = [uids count];
+
+ // count number of uids due to softdelete
+ NSMutableDictionary *dateCache;
+ SOGoCacheGCSObject *o;
+ NSMutableArray *sdUids;
+
+ sdUids =[[NSMutableArray alloc] init];
+
+ if (filter) {
+ o = [SOGoCacheGCSObject objectWithName: [NSString stringWithFormat: @"%@+folder%@", [context objectForKey: @"DeviceId"], realCollectionId] inContainer: nil];
+ [o setObjectType: ActiveSyncGlobalCacheObject];
+ [o setTableUrl: [self folderTableURL]];
+ [o reloadIfNeeded];
+ dateCache = [[o properties] objectForKey: @"DateCache"];
+ for (NSString* key in [dateCache allKeys]) {
+ if ([[dateCache objectForKey:key] compare: filter ] == NSOrderedAscending )
+ [sdUids addObject:[dateCache objectForKey:key]];
+ }
+
+ count+= [sdUids count];
+ }
}
else
{
--
1.7.9.5
|
|
|
Due to other priorities a cannot work on it at the moment, but I just uploaded what I have at the moment: 0003-sd2.patch. |
|
|
Good start - I'll bump this to v2.2.5 as we want to get 2.2.4 out ASAP. It won't be a problem to add this feature later because the cache will still be populated correctly. |
|
|
0001-softDelete.patch (5,845 bytes)
From 82cf481afec0dc1503d6d732be63f96173c7dbf6 Mon Sep 17 00:00:00 2001
From: root <root@poldi.hopto.org>
Date: Fri, 20 Jun 2014 15:56:05 +0200
Subject: [PATCH 1/2] softDelete
---
ActiveSync/SOGoActiveSyncDispatcher+Sync.m | 58 ++++++++++++++++++++++++----
ActiveSync/SOGoActiveSyncDispatcher.m | 30 ++++++++++++++
2 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
index 8c206ba..5259da6 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
@@ -477,21 +477,64 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
lastServerKey: (NSString **) theLastServerKey
{
- NSMutableDictionary *folderMetadata;
+ //NSMutableDictionary *folderMetadata;
NSMutableString *s;
BOOL more_available;
- int i, max;
+ int i, max, sd_count;
+ s = [NSMutableString string];
+
+ NSMutableDictionary *folderMetadata, *dateCache, *syncCache;
+
+ more_available = NO;
+
+ if (theFolderType == ActiveSyncMailFolder && !([theSyncKey isEqualToString: @"-1"])) {
+ if (theFilterType) {
+ sd_count=0;
+
+ folderMetadata = [self _folderMetadataForKey: [theCollection nameInContainer]];
+ dateCache = [folderMetadata objectForKey: @"DateCache"];
+ syncCache = [folderMetadata objectForKey: @"SyncCache"];
+
+ for (NSString* key in [dateCache allKeys]) {
+ if ([[dateCache objectForKey:key] compare: theFilterType ] == NSOrderedAscending ) {
+ [s appendString: @"<SoftDelete xmlns=\"AirSync:\">"];
+ [s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", key];
+ [s appendString: @"</SoftDelete>"];
+
+ [syncCache removeObjectForKey: key];
+ [dateCache removeObjectForKey: key];
+
+ sd_count++;
+ }
+
+ if (sd_count >= theWindowSize) {
+ [folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"];
+ more_available = YES;
+ *theLastServerKey = theSyncKey;
+
+ [self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
+
+ goto return_response;
+ }
+ }
+
+ if (more_available)
+ [folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"];
+ else
+ [folderMetadata removeObjectForKey: @"MoreAvailable"];
+
+ [self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
+ }
+ }
//
// No changes in the collection - 2.2.2.19.1.1 Empty Sync Request.
// We check this and we don't generate any commands if we don't have to.
//
- if ([theSyncKey isEqualToString: [theCollection davCollectionTag]])
+ if ([theSyncKey isEqualToString: [theCollection davCollectionTag]] && !([s length]))
return;
- s = [NSMutableString string];
-
more_available = NO;
switch (theFolderType)
@@ -777,7 +820,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: @"</Add>"];
[syncCache setObject: [aCacheObject sequence] forKey: [aCacheObject uid]];
- [dateCache setObject: [NSCalendarDate date] forKey: [aCacheObject uid]];
+ [dateCache setObject: [mailObject date] forKey: [aCacheObject uid]];
return_count++;
}
else
@@ -805,6 +848,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
break;
} // switch (folderType) ...
+return_response:
+
if ([s length])
{
[theBuffer appendString: @"<Commands>"];
@@ -1008,7 +1053,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
davCollectionTag = [collection davCollectionTag];
}
-
// Generate the response buffer
[theBuffer appendString: @"<Collection>"];
diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m
index b98ce3b..35ae9d0 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher.m
@@ -919,6 +919,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sortOrdering: @"REVERSE ARRIVAL"
threaded: NO];
count = [uids count];
+ // add number of uids due to softDelete
+ count+= [[self softDeleteUids: filter collectionId: realCollectionId] count];
+
}
else
{
@@ -2216,4 +2219,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[cm releaseChannel: channel];
}
+- (NSArray *) softDeleteUids: (NSCalendarDate *) theFilter
+ collectionId: (NSString *) theCollectionId
+{
+
+ // count number of uids due to softdelete
+ NSMutableDictionary *dateCache;
+ SOGoCacheGCSObject *o;
+ NSMutableArray *sdUids;
+
+ sdUids =[[NSMutableArray alloc] init];
+
+ if (theFilter) {
+ o = [SOGoCacheGCSObject objectWithName: [NSString stringWithFormat: @"%@+folder%@", [context objectForKey: @"DeviceId"], theCollectionId] inContainer: nil];
+ [o setObjectType: ActiveSyncGlobalCacheObject];
+ [o setTableUrl: [self folderTableURL]];
+ [o reloadIfNeeded];
+ dateCache = [[o properties] objectForKey: @"DateCache"];
+ for (NSString* key in [dateCache allKeys]) {
+ if ([[dateCache objectForKey:key] compare: theFilter ] == NSOrderedAscending ) {
+ [sdUids addObject:[dateCache objectForKey:key]];
+ }
+ }
+ }
+
+ return sdUids;
+
+}
@end
--
1.7.10.4
|
|
|
Can you please review attach patch (0001-softDelete.patch) and let me know what you thing about. |
|
|
It seems to me that your call to "goto return_response;" should just be a break, otherwise you don't set MoreAvailable. |
|
|
You do set it, but:
should probably just be: |
|
|
0001-softDelete1.patch (6,251 bytes)
From 85ad95ae7c60984d7dce9a17085a59c8cbef2349 Mon Sep 17 00:00:00 2001
From: root <root@poldi.hopto.org>
Date: Tue, 24 Jun 2014 21:05:53 +0200
Subject: [PATCH] softDelete1
---
ActiveSync/SOGoActiveSyncDispatcher+Sync.m | 56 ++++++++++++++++++++++++----
ActiveSync/SOGoActiveSyncDispatcher.m | 30 +++++++++++++++
2 files changed, 79 insertions(+), 7 deletions(-)
diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
index 8c206ba..347e6a7 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m
@@ -126,6 +126,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[[o properties] removeObjectForKey: @"SyncKey"];
[[o properties] removeObjectForKey: @"SyncCache"];
[[o properties] removeObjectForKey: @"DateCache"];
+ [[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] addEntriesFromDictionary: theFolderMetadata];
[o save];
@@ -477,21 +478,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
lastServerKey: (NSString **) theLastServerKey
{
- NSMutableDictionary *folderMetadata;
+ //NSMutableDictionary *folderMetadata;
NSMutableString *s;
BOOL more_available;
- int i, max;
+ int i, max, sd_count;
+ s = [NSMutableString string];
+
+ NSMutableDictionary *folderMetadata, *dateCache, *syncCache;
+
+ more_available = NO;
+
+ if (theFolderType == ActiveSyncMailFolder && !([theSyncKey isEqualToString: @"-1"])) {
+ if (theFilterType) {
+ sd_count=0;
+
+ folderMetadata = [self _folderMetadataForKey: [theCollection nameInContainer]];
+ dateCache = [folderMetadata objectForKey: @"DateCache"];
+ syncCache = [folderMetadata objectForKey: @"SyncCache"];
+
+ for (NSString* key in [dateCache allKeys]) {
+ if ([[dateCache objectForKey:key] compare: theFilterType ] == NSOrderedAscending ) {
+ [s appendString: @"<SoftDelete xmlns=\"AirSync:\">"];
+ [s appendFormat: @"<ServerId xmlns=\"AirSync:\">%@</ServerId>", key];
+ [s appendString: @"</SoftDelete>"];
+
+ [syncCache removeObjectForKey: key];
+ [dateCache removeObjectForKey: key];
+
+ sd_count++;
+ }
+
+ if (sd_count >= theWindowSize) {
+ // set MoreAvailable in cache
+ [folderMetadata setObject: [NSNumber numberWithBool: YES] forKey: @"MoreAvailable"];
+ [self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
+
+ more_available = YES;
+ *theLastServerKey = theSyncKey;
+ // since WindowSize is reached don't even try to add more to the response - jump to the end and return the response
+ goto return_response;
+ }
+ }
+
+ [folderMetadata removeObjectForKey: @"MoreAvailable"];
+ [self _setFolderMetadata: folderMetadata forKey: [theCollection nameInContainer]];
+ }
+ }
//
// No changes in the collection - 2.2.2.19.1.1 Empty Sync Request.
// We check this and we don't generate any commands if we don't have to.
//
- if ([theSyncKey isEqualToString: [theCollection davCollectionTag]])
+ if ([theSyncKey isEqualToString: [theCollection davCollectionTag]] && !([s length]))
return;
- s = [NSMutableString string];
-
more_available = NO;
switch (theFolderType)
@@ -777,7 +818,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: @"</Add>"];
[syncCache setObject: [aCacheObject sequence] forKey: [aCacheObject uid]];
- [dateCache setObject: [NSCalendarDate date] forKey: [aCacheObject uid]];
+ [dateCache setObject: [mailObject date] forKey: [aCacheObject uid]];
return_count++;
}
else
@@ -805,6 +846,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
break;
} // switch (folderType) ...
+return_response:
+
if ([s length])
{
[theBuffer appendString: @"<Commands>"];
@@ -1008,7 +1051,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
davCollectionTag = [collection davCollectionTag];
}
-
// Generate the response buffer
[theBuffer appendString: @"<Collection>"];
diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m
index b98ce3b..35ae9d0 100644
--- a/ActiveSync/SOGoActiveSyncDispatcher.m
+++ b/ActiveSync/SOGoActiveSyncDispatcher.m
@@ -919,6 +919,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sortOrdering: @"REVERSE ARRIVAL"
threaded: NO];
count = [uids count];
+ // add number of uids due to softDelete
+ count+= [[self softDeleteUids: filter collectionId: realCollectionId] count];
+
}
else
{
@@ -2216,4 +2219,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[cm releaseChannel: channel];
}
+- (NSArray *) softDeleteUids: (NSCalendarDate *) theFilter
+ collectionId: (NSString *) theCollectionId
+{
+
+ // count number of uids due to softdelete
+ NSMutableDictionary *dateCache;
+ SOGoCacheGCSObject *o;
+ NSMutableArray *sdUids;
+
+ sdUids =[[NSMutableArray alloc] init];
+
+ if (theFilter) {
+ o = [SOGoCacheGCSObject objectWithName: [NSString stringWithFormat: @"%@+folder%@", [context objectForKey: @"DeviceId"], theCollectionId] inContainer: nil];
+ [o setObjectType: ActiveSyncGlobalCacheObject];
+ [o setTableUrl: [self folderTableURL]];
+ [o reloadIfNeeded];
+ dateCache = [[o properties] objectForKey: @"DateCache"];
+ for (NSString* key in [dateCache allKeys]) {
+ if ([[dateCache objectForKey:key] compare: theFilter ] == NSOrderedAscending ) {
+ [sdUids addObject:[dateCache objectForKey:key]];
+ }
+ }
+ }
+
+ return sdUids;
+
+}
@end
--
1.7.10.4
|
|
|
Yes - I slightly modified the patch and added some comments. |
|
|
Are you sure about that;
What I don't like is that a spammer could set a mail in the future, say 2020 and the mail would 'never' softdelete itself. |
|
|
You are right if you want to avoid such a scenario and as long the device is synced on regular basis it would make no difference for the user whether a mail is soft-deleted based on [NSCalendarDate date] (synced) or [mailObject date] (received). |
|
|
Modified patch pushed: https://github.com/inverse-inc/sogo/commit/5419f411e5bae58cc17ab22b3b95a88efab74252 Thanks for your contribution! |
|
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2014-04-24 19:29 | tfu | New Issue | |
| 2014-04-24 19:29 | tfu | File Added: 0001-mail-softdelete.patch | |
| 2014-04-29 14:02 | tfu | File Added: 0002-mail-softdelete-hasPrefix.patch | |
| 2014-04-29 14:07 | tfu | Note Added: 0006973 | |
| 2014-05-05 18:04 | ludovic | Note Added: 0006990 | |
| 2014-05-05 18:24 | ludovic | Target Version | => 2.2.4 |
| 2014-05-15 19:12 | ludovic | Note Added: 0007027 | |
| 2014-05-18 13:50 | tfu | File Added: 0001-softDelete-with-dateCache.patch | |
| 2014-05-18 13:50 | tfu | Note Added: 0007048 | |
| 2014-05-22 13:32 | ludovic | Note Added: 0007066 | |
| 2014-05-22 20:21 | tfu | Note Added: 0007080 | |
| 2014-05-22 23:49 | ludovic | Note Added: 0007083 | |
| 2014-05-27 19:03 | ludovic | Note Added: 0007133 | |
| 2014-05-27 19:23 | tfu | File Added: 0003-sd2.patch | |
| 2014-05-27 19:26 | tfu | Note Added: 0007134 | |
| 2014-05-27 20:02 | ludovic | Note Added: 0007135 | |
| 2014-05-27 20:02 | ludovic | Target Version | 2.2.4 => 2.2.5 |
| 2014-06-24 17:47 | tfu | File Added: 0001-softDelete.patch | |
| 2014-06-24 17:52 | tfu | Note Added: 0007234 | |
| 2014-06-24 18:44 | ludovic | Note Added: 0007235 | |
| 2014-06-24 18:44 | ludovic | Note Edited: 0007235 | |
| 2014-06-24 19:00 | ludovic | Note Added: 0007236 | |
| 2014-06-24 19:28 | tfu | File Added: 0001-softDelete1.patch | |
| 2014-06-24 19:30 | tfu | Note Added: 0007237 | |
| 2014-06-25 16:40 | ludovic | Note Added: 0007238 | |
| 2014-06-25 18:40 | tfu | Note Added: 0007239 | |
| 2014-06-25 19:06 | ludovic | Target Version | 2.2.5 => 2.2.6 |
| 2014-06-25 19:07 | ludovic | Note Added: 0007240 | |
| 2014-06-25 19:07 | ludovic | Status | new => resolved |
| 2014-06-25 19:07 | ludovic | Fixed in Version | => 2.2.6 |
| 2014-06-25 19:07 | ludovic | Resolution | open => fixed |
| 2014-06-25 19:07 | ludovic | Assigned To | => ludovic |