mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-07-14 12:54:54 +00:00
Added EAS folder merge support and fixed long GUID issue (fixes #3460)
Conflicts: ActiveSync/SOGoActiveSyncDispatcher+Sync.m
This commit is contained in:
+189
-12
@@ -25,6 +25,8 @@
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSUserDefaults.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <Foundation/NSProcessInfo.h>
|
||||
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGObjWeb/WOApplication.h>
|
||||
@@ -52,6 +54,8 @@ typedef enum
|
||||
ManageEASListFolders = 2,
|
||||
ManageEASResetDevice = 3,
|
||||
ManageEASRestFolder = 4,
|
||||
ManageEASVCard = 5,
|
||||
ManageEASVEvent = 6,
|
||||
} SOGoManageEASCommand;
|
||||
|
||||
@interface SOGoToolManageEAS : SOGoTool
|
||||
@@ -59,6 +63,8 @@ typedef enum
|
||||
|
||||
@implementation SOGoToolManageEAS
|
||||
|
||||
NSURL *folderTableURL;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
}
|
||||
@@ -73,15 +79,58 @@ typedef enum
|
||||
return @"manage EAS folders";
|
||||
}
|
||||
|
||||
- (void) _setOrUnsetSyncRequest: (BOOL) set
|
||||
collections: (NSArray *) collections
|
||||
{
|
||||
SOGoCacheGCSObject *o;
|
||||
NSNumber *processIdentifier;
|
||||
NSString *key;
|
||||
NSArray *a;
|
||||
int i;
|
||||
|
||||
processIdentifier = [NSNumber numberWithInt: [[NSProcessInfo processInfo] processIdentifier]];
|
||||
|
||||
o = [SOGoCacheGCSObject objectWithName: [[[collections objectAtIndex: 0] componentsSeparatedByString: @"+"] objectAtIndex: 0] inContainer: nil useCache: NO];
|
||||
[o setObjectType: ActiveSyncGlobalCacheObject];
|
||||
[o setTableUrl: folderTableURL];
|
||||
[o reloadIfNeeded];
|
||||
|
||||
if (set)
|
||||
{
|
||||
[[o properties] setObject: [NSNumber numberWithUnsignedInt: [[NSCalendarDate date] timeIntervalSince1970]] forKey: @"SyncRequest"];
|
||||
|
||||
for (i = 0; i < [collections count]; i++)
|
||||
{
|
||||
a = [[collections objectAtIndex: i] componentsSeparatedByString: @"+"];
|
||||
key = [NSString stringWithFormat: @"SyncRequest+%@", [a objectAtIndex: 1]];
|
||||
[[o properties] setObject: processIdentifier forKey: key];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[[o properties] removeObjectForKey: @"SyncRequest"];
|
||||
for (i = 0; i < [collections count]; i++)
|
||||
{
|
||||
a = [[collections objectAtIndex: i] componentsSeparatedByString: @"+"];
|
||||
key = [NSString stringWithFormat: @"SyncRequest+%@", [a objectAtIndex: 1]];
|
||||
[[o properties] removeObjectForKey: key];
|
||||
}
|
||||
}
|
||||
|
||||
[o save];
|
||||
}
|
||||
|
||||
- (void) usage
|
||||
{
|
||||
fprintf (stderr, "manage-eas listdevices|resetdevice|resetfolder user <devinceId | folderId> \n\n"
|
||||
fprintf (stderr, "manage-eas listdevices|resetdevice|resetfolder|mergevcard|mergevevent user <devinceId | folderId> <YES | NO>\n\n"
|
||||
" user the user of whom to reset the whole device or a single folder\n"
|
||||
" Examples:\n"
|
||||
" sogo-tool manage-eas listdevices janedoe\n"
|
||||
" sogo-tool manage-eas listfolders janedoe androidc316986417\n"
|
||||
" sogo-tool manage-eas resetdevice janedoe androidc316986417\n"
|
||||
" sogo-tool manage-eas resetfolder janedow androidc316986417+folderlala-dada-sasa_7a13_1a2386e0_e\n") ;
|
||||
" sogo-tool manage-eas resetfolder janedow androidc316986417+folderlala-dada-sasa_7a13_1a2386e0_e\n"
|
||||
" sogo-tool manage-eas mergevcard janedow androidc316986417 YES\n"
|
||||
" sogo-tool manage-eas mergevevent janedow androidc316986417 YES\n") ;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +146,10 @@ typedef enum
|
||||
return ManageEASResetDevice;
|
||||
else if ([theString caseInsensitiveCompare: @"resetfolder"] == NSOrderedSame)
|
||||
return ManageEASRestFolder;
|
||||
else if ([theString caseInsensitiveCompare: @"mergevcard"] == NSOrderedSame)
|
||||
return ManageEASVCard;
|
||||
else if ([theString caseInsensitiveCompare: @"mergevevent"] == NSOrderedSame)
|
||||
return ManageEASVEvent;
|
||||
}
|
||||
|
||||
return ManageEASUnknown;
|
||||
@@ -107,7 +160,6 @@ typedef enum
|
||||
NSString *urlString, *deviceId, *userId;
|
||||
NSMutableString *ocFSTableName;
|
||||
SOGoCacheGCSObject *oc, *foc;
|
||||
NSURL *folderTableURL;
|
||||
NSMutableArray *parts;
|
||||
NSArray *entries;
|
||||
id cacheEntry;
|
||||
@@ -169,6 +221,7 @@ typedef enum
|
||||
}
|
||||
|
||||
rc = YES;
|
||||
|
||||
break;
|
||||
|
||||
case ManageEASListFolders:
|
||||
@@ -195,6 +248,8 @@ typedef enum
|
||||
[foc reloadIfNeeded];
|
||||
|
||||
fprintf(stdout, " Folder Name: %s\n\n", [[[foc properties] objectForKey: @"displayName"] UTF8String]);
|
||||
if ([[foc properties] objectForKey: @"MergedFolder"])
|
||||
fprintf(stdout, " MergedFolder = YES\n\n");
|
||||
|
||||
if (verbose)
|
||||
fprintf(stdout, " metadata Name: %s\n\n", [[[foc properties] description] UTF8String]);
|
||||
@@ -227,7 +282,7 @@ typedef enum
|
||||
|
||||
NSMutableString *sql;
|
||||
|
||||
sql = [NSMutableString stringWithFormat: @"DELETE FROM %@ WHERE c_path like '/%@'", [oc tableName], deviceId];
|
||||
sql = [NSMutableString stringWithFormat: @"DELETE FROM %@ WHERE c_path like '/%@%'", [oc tableName], deviceId];
|
||||
|
||||
[oc performBatchSQLQueries: [NSArray arrayWithObject: sql]];
|
||||
rc = YES;
|
||||
@@ -260,16 +315,138 @@ typedef enum
|
||||
fprintf(stderr, "ERROR: Folder with ID \"%s\" not found\n", [deviceId UTF8String]);
|
||||
return rc;
|
||||
}
|
||||
[[oc properties] removeObjectForKey: @"SyncKey"];
|
||||
[[oc properties] removeObjectForKey: @"SyncCache"];
|
||||
[[oc properties] removeObjectForKey: @"DateCache"];
|
||||
[[oc properties] removeObjectForKey: @"MoreAvailable"];
|
||||
[[oc properties] removeObjectForKey: @"FirstIdInCache"];
|
||||
[[oc properties] removeObjectForKey: @"LastIdInCache"];
|
||||
|
||||
[oc save];
|
||||
if ((![deviceId hasSuffix: @"/personal"]) && [[oc properties] objectForKey: @"MergedFolder"])
|
||||
{
|
||||
fprintf(stderr, "ERROR: MergedFolder = true; only personal folder can be reset");
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _setOrUnsetSyncRequest: YES collections: [NSArray arrayWithObject: deviceId]];
|
||||
|
||||
[[oc properties] removeObjectForKey: @"SyncKey"];
|
||||
[[oc properties] removeObjectForKey: @"SyncCache"];
|
||||
[[oc properties] removeObjectForKey: @"DateCache"];
|
||||
[[oc properties] removeObjectForKey: @"UidCache"];
|
||||
[[oc properties] removeObjectForKey: @"MoreAvailable"];
|
||||
[[oc properties] removeObjectForKey: @"BodyPreferenceType"];
|
||||
[[oc properties] removeObjectForKey: @"SupportedElements"];
|
||||
[[oc properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
|
||||
[[oc properties] removeObjectForKey: @"InitialLoadSequence"];
|
||||
[[oc properties] removeObjectForKey: @"MergedFoldersSyncKeys"];
|
||||
[[oc properties] removeObjectForKey: @"CleanoutDate"];
|
||||
|
||||
[oc save];
|
||||
rc = YES;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "\nERROR: folderId not specified\n\n");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ManageEASVCard:
|
||||
case ManageEASVEvent:
|
||||
if (max > 3)
|
||||
{
|
||||
NSString *folderType;
|
||||
|
||||
if (cmd == ManageEASVCard)
|
||||
folderType = @"vcard";
|
||||
else
|
||||
folderType = @"vevent";
|
||||
|
||||
/* value specified on command line */
|
||||
deviceId = [sanitizedArguments objectAtIndex: 2];
|
||||
|
||||
oc = [SOGoCacheGCSObject objectWithName: @"0" inContainer: nil];
|
||||
[oc setObjectType: ActiveSyncFolderCacheObject];
|
||||
|
||||
[oc setTableUrl: folderTableURL];
|
||||
entries = [oc cacheEntriesForDeviceId: deviceId newerThanVersion: -1];
|
||||
|
||||
vtodo:
|
||||
|
||||
for (i = 0; i < [entries count]; i++)
|
||||
{
|
||||
cacheEntry = [entries objectAtIndex: i];
|
||||
|
||||
if ([[cacheEntry substringFromIndex: 1] hasPrefix: [NSString stringWithFormat: @"%@+%@/", deviceId, folderType]])
|
||||
{
|
||||
fprintf(stdout,"Folder Key: %s\n", [[cacheEntry substringFromIndex: 1] UTF8String]);
|
||||
|
||||
foc = [SOGoCacheGCSObject objectWithName: [cacheEntry substringFromIndex: 1] inContainer: nil];
|
||||
[foc setObjectType: ActiveSyncFolderCacheObject];
|
||||
[foc setTableUrl: folderTableURL];
|
||||
|
||||
[foc reloadIfNeeded];
|
||||
|
||||
if ([foc isNew])
|
||||
continue;
|
||||
|
||||
[self _setOrUnsetSyncRequest: YES collections: [NSArray arrayWithObject: [cacheEntry substringFromIndex: 1]]];
|
||||
|
||||
if (![[cacheEntry substringFromIndex: 1] hasPrefix: [NSString stringWithFormat: @"%@+%@/personal", deviceId, folderType]] &&
|
||||
[[sanitizedArguments objectAtIndex: 3] isEqualToString: @"NO"] &&
|
||||
[[[foc properties] objectForKey: @"MergedFolder"] isEqualToString: @"2"])
|
||||
{
|
||||
[foc destroy];
|
||||
continue;
|
||||
}
|
||||
else if ([[sanitizedArguments objectAtIndex: 3] isEqualToString: @"NO"])
|
||||
{
|
||||
[[foc properties] removeObjectForKey: @"SyncKey"];
|
||||
[[foc properties] removeObjectForKey: @"SyncCache"];
|
||||
[[foc properties] removeObjectForKey: @"DateCache"];
|
||||
[[foc properties] removeObjectForKey: @"UidCache"];
|
||||
[[foc properties] removeObjectForKey: @"MoreAvailable"];
|
||||
[[foc properties] removeObjectForKey: @"BodyPreferenceType"];
|
||||
[[foc properties] removeObjectForKey: @"SupportedElements"];
|
||||
[[foc properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
|
||||
[[foc properties] removeObjectForKey: @"InitialLoadSequence"];
|
||||
[[foc properties] removeObjectForKey: @"FirstIdInCache"];
|
||||
[[foc properties] removeObjectForKey: @"LastIdInCache"];
|
||||
[[foc properties] removeObjectForKey: @"MergedFoldersSyncKeys"];
|
||||
[[foc properties] removeObjectForKey: @"CleanoutDate"];
|
||||
|
||||
[[foc properties] removeObjectForKey: @"MergedFolder"];
|
||||
}
|
||||
else if ([[sanitizedArguments objectAtIndex: 3] isEqualToString: @"YES"] && ![[foc properties] objectForKey: @"MergedFolder"])
|
||||
{
|
||||
if (![[cacheEntry substringFromIndex: 1] hasPrefix: [NSString stringWithFormat: @"%@+%@/personal", deviceId, folderType]])
|
||||
{
|
||||
[[foc properties] removeObjectForKey: @"SyncKey"];
|
||||
[[foc properties] removeObjectForKey: @"SyncCache"];
|
||||
[[foc properties] removeObjectForKey: @"DateCache"];
|
||||
[[foc properties] removeObjectForKey: @"UidCache"];
|
||||
[[foc properties] removeObjectForKey: @"MoreAvailable"];
|
||||
[[foc properties] removeObjectForKey: @"BodyPreferenceType"];
|
||||
[[foc properties] removeObjectForKey: @"SupportedElements"];
|
||||
[[foc properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
|
||||
[[foc properties] removeObjectForKey: @"InitialLoadSequence"];
|
||||
[[foc properties] removeObjectForKey: @"FirstIdInCache"];
|
||||
[[foc properties] removeObjectForKey: @"LastIdInCache"];
|
||||
[[foc properties] removeObjectForKey: @"MergedFoldersSyncKeys"];
|
||||
[[foc properties] removeObjectForKey: @"CleanoutDate"];
|
||||
}
|
||||
|
||||
[[foc properties] setObject: @"1" forKey: @"MergedFolder"];
|
||||
}
|
||||
|
||||
[foc save];
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == ManageEASVEvent && [folderType isEqualToString: @"vevent"])
|
||||
{
|
||||
folderType = @"vtodo";
|
||||
goto vtodo;
|
||||
}
|
||||
|
||||
rc = YES;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user