merge of '5253a478333e1c7fb21c61abd4592b1f92a0c899'

and '831abd52d51297f3a0de88978cf6abeda7fad46c'

Monotone-Parent: 5253a478333e1c7fb21c61abd4592b1f92a0c899
Monotone-Parent: 831abd52d51297f3a0de88978cf6abeda7fad46c
Monotone-Revision: 8fd2ccda774229842a01a4095b96f10a9511ede4

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2009-08-14T15:05:06
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2009-08-14 15:05:06 +00:00
commit 3b270cda01
4 changed files with 193 additions and 47 deletions

View File

@ -3,6 +3,15 @@
* Tools/SOGoToolRestore.m: new "sogo-tool" utility that restores
the specified user data previously created by the "backup"
command.
(+initialize): load the "Appointments.SOGo" and "Contacts.SOGo"
bundle in order to access some categories found therein that are
used by OGoContentStore.
(-parseModeArguments) mode arguments are now put at the beginning
of the command parameter string. Added "-F" mode that acts
"destructivelly". Added "-l" mode that enables the listing of
folders previously backed up.
(-createFolder:withFM:): new method that enables the restoration
of folders that were previously deleted.
* Tools/SOGoToolBackup.m (-extractUserPreferences:intoRecord:): we
must extract the values of the user defaults in order to put them

View File

@ -4,7 +4,7 @@ ADDITIONAL_CPPFLAGS += \
-DSOGO_MAJOR_VERSION=$(MAJOR_VERSION) \
-DSOGO_MINOR_VERSION=$(MINOR_VERSION) \
-DSOGO_SUBMINOR_VERSION=$(SUBMINOR_VERSION) \
-DSOGO_LIBDIR="\"$(SOGO_LIBDIR)\""
-DSOGO_LIBDIR="@\"$(SOGO_LIBDIR)\""
ADDITIONAL_INCLUDE_DIRS += \
-D_GNU_SOURCE -I../SOPE/ -I../SoObjects/

View File

@ -27,6 +27,8 @@
typedef enum SOGoToolRestoreMode {
SOGoToolRestoreFolderMode,
SOGoToolRestoreFolderDestructiveMode,
SOGoToolRestoreListFoldersMode,
SOGoToolRestorePreferencesMode
} SOGoToolRestoreMode;

View File

@ -47,8 +47,22 @@
- write methods in GDLContentStore to get/update displayname
and storing roles */
#import <NGExtensions/NGBundleManager.h>
@implementation SOGoToolRestore
+ (void) initialize
{
NGBundleManager *bm;
/* we need to load the SOGo bundles here because OGoContentStore make use of
certain categories found therein */
bm = [NGBundleManager defaultBundleManager];
[bm setBundleSearchPaths: [NSArray arrayWithObject: SOGO_LIBDIR]];
[[bm bundleWithName: @"Appointments" type: @"SOGo"] load];
[[bm bundleWithName: @"Contacts" type: @"SOGo"] load];
}
+ (NSString *) command
{
return @"restore";
@ -82,7 +96,7 @@
- (void) usage
{
fprintf (stderr, "restore directory user [-f folder|-p]\n\n"
fprintf (stderr, "restore [-l|-f/-F folder/ALL|-p] directory user\n\n"
" folder the folder where backup files will be stored\n"
" user the user of whom to save the data\n");
}
@ -133,54 +147,70 @@
return rc;
}
- (BOOL) parseModeArguments: (NSArray *) modeArguments
- (int) parseModeArguments
{
NSString *mode;
BOOL rc;
int count, max;
rc = NO;
mode = [modeArguments objectAtIndex: 0];
if ([mode isEqualToString: @"-f"])
max = [arguments count];
if (max > 0)
{
rc = YES;
restoreMode = SOGoToolRestoreFolderMode;
if ([modeArguments count] == 2)
mode = [arguments objectAtIndex: 0];
count = 1;
if ([mode isEqualToString: @"-f"]
|| [mode isEqualToString: @"-F"])
{
restoreFolder = [NSString stringWithFormat: @"/Users/%@/%@",
userID,
[modeArguments objectAtIndex: 1]];
[restoreFolder retain];
if ([mode hasSuffix: @"f"])
restoreMode = SOGoToolRestoreFolderMode;
else
restoreMode = SOGoToolRestoreFolderDestructiveMode;
if (max > 1)
{
count++;
ASSIGN (restoreFolder, [arguments objectAtIndex: 1]);
}
else
{
count = 0;
NSLog (@"missing 'folder' parameter");
}
}
else if ([mode isEqualToString: @"-l"])
restoreMode = SOGoToolRestoreListFoldersMode;
else if ([mode isEqualToString: @"-p"])
restoreMode = SOGoToolRestorePreferencesMode;
else
{
count = 0;
if ([mode hasPrefix: @"-"])
NSLog (@"specified mode is invalid");
else
NSLog (@"missing 'mode' parameter");
}
}
else if ([mode isEqualToString: @"-p"])
{
rc = YES;
restoreMode = SOGoToolRestorePreferencesMode;
}
else
[self usage];
count = 0;
return rc;
return count;
}
- (BOOL) parseArguments
{
BOOL rc;
NSString *identifier;
NSArray *modeArguments;
int max;
NSArray *newArguments;
int count, max;
max = [arguments count];
if ([arguments count] > 2)
count = [self parseModeArguments];
max = [arguments count] - count;
if (max == 2)
{
ASSIGN (directory, [arguments objectAtIndex: 0]);
identifier = [arguments objectAtIndex: 1];
modeArguments
= [arguments subarrayWithRange: NSMakeRange (2, max - 2)];
newArguments
= [arguments subarrayWithRange: NSMakeRange (count, max)];
ASSIGN (directory, [newArguments objectAtIndex: 0]);
identifier = [newArguments objectAtIndex: 1];
rc = ([self checkDirectory]
&& [self fetchUserID: identifier]
&& [self parseModeArguments: modeArguments]);
&& [self fetchUserID: identifier]);
}
else
{
@ -335,30 +365,93 @@
return rc;
}
- (BOOL) createFolder: (NSString *) folder
withFM: (GCSFolderManager *) fm
{
NSArray *pathElements;
NSException *error;
NSString *folderType;
BOOL rc;
pathElements = [folder componentsSeparatedByString: @"/"];
if ([[pathElements objectAtIndex: 3] isEqualToString: @"Contacts"])
folderType = @"Contact";
else
folderType = @"Appointment";
error = [fm createFolderOfType: folderType
withName: [pathElements objectAtIndex: 4]
atPath: folder];
if (error)
{
rc = NO;
NSLog (@"an error occured during folder creation: %@", error);
}
else
rc = YES;
return rc;
}
- (BOOL) restoreFolder: (NSString *) folder
withContent: (NSDictionary *) content
destructive: (BOOL) isDestructive
{
GCSFolderManager *fm;
GCSFolder *gcsFolder;
NSException *error;
BOOL rc;
rc = YES;
fm = [GCSFolderManager defaultFolderManager];
gcsFolder = [fm folderAtPath: folder];
if (gcsFolder && isDestructive)
{
error = [fm deleteFolderAtPath: folder];
if (error)
{
rc = NO;
NSLog (@"an error occured during folder deletion: %@", error);
}
else
gcsFolder = nil;
}
if (rc)
{
if (!gcsFolder)
{
rc = [self createFolder: folder withFM: fm];
if (rc)
{
gcsFolder = [fm folderAtPath: folder];
if (!gcsFolder)
{
rc = NO;
NSLog (@"missing folder '%@' could not be recreated",
folder);
}
}
}
return ([self restoreDisplayName: [content objectForKey: @"displayname"]
ofFolder: gcsFolder
withFM: fm]
&& [self restoreACL: [content objectForKey: @"acl"]
ofFolder: gcsFolder]
&& [self restoreRecords: [content objectForKey: @"records"]
ofFolder: gcsFolder]);
rc &= ([self restoreDisplayName: [content objectForKey: @"displayname"]
ofFolder: gcsFolder
withFM: fm]
&& [self restoreACL: [content objectForKey: @"acl"]
ofFolder: gcsFolder]
&& [self restoreRecords: [content objectForKey: @"records"]
ofFolder: gcsFolder]);
}
return rc;
}
- (BOOL)
restoreSpecifiedUserFolderFromUserRecord: (NSDictionary *) userRecord
- (BOOL) restoreUserFolderFromUserRecord: (NSDictionary *) userRecord
destructive: (BOOL) isDestructive
{
NSDictionary *tables, *content;
NSArray *restoreFolders;
NSString *currentFolder;
NSString *currentFolder, *folderPath;
int count, max;
BOOL rc;
@ -367,10 +460,14 @@
tables = [userRecord objectForKey: @"tables"];
if (tables)
{
if (restoreFolder)
restoreFolders = [NSArray arrayWithObject: restoreFolder];
else
if ([restoreFolder isEqualToString: @"ALL"])
restoreFolders = [tables allKeys];
else
{
folderPath = [NSString stringWithFormat: @"/Users/%@/%@",
userID, restoreFolder];
restoreFolders = [NSArray arrayWithObject: folderPath];
}
max = [restoreFolders count];
for (count = 0; count < max; count++)
{
@ -378,7 +475,8 @@
content = [tables objectForKey: currentFolder];
if (content)
rc &= [self restoreFolder: currentFolder
withContent: content];
withContent: content
destructive: isDestructive];
else
{
rc = NO;
@ -395,6 +493,37 @@
return rc;
}
- (BOOL) listRestorableFolders: (NSDictionary *) userRecord
{
BOOL rc;
NSDictionary *tables, *currentFolder;
NSEnumerator *tableKeys;
NSString *key, *folderKey;
int folderPrefixLen;
tables = [userRecord objectForKey: @"tables"];
if (tables)
{
NSLog (@"Restorable folders:");
folderPrefixLen = 8 + [userID length];
tableKeys = [[tables allKeys] objectEnumerator];
while ((key = [tableKeys nextObject]))
{
currentFolder = [tables objectForKey: key];
folderKey = [key substringFromIndex: folderPrefixLen];
NSLog (@" '%@': %@",
[currentFolder objectForKey: @"displayname"], folderKey);
}
}
else
{
rc = NO;
NSLog (@"no table information found in backup file");
}
return rc;
}
- (BOOL) restoreUserPreferencesFromUserRecord: (NSDictionary *) userRecord
{
SOGoUser *sogoUser;
@ -436,7 +565,13 @@
if (userRecord)
{
if (restoreMode == SOGoToolRestoreFolderMode)
rc = [self restoreSpecifiedUserFolderFromUserRecord: userRecord];
rc = [self restoreUserFolderFromUserRecord: userRecord
destructive: NO];
else if (restoreMode == SOGoToolRestoreFolderDestructiveMode)
rc = [self restoreUserFolderFromUserRecord: userRecord
destructive: YES];
else if (restoreMode == SOGoToolRestoreListFoldersMode)
rc = [self listRestorableFolders: userRecord];
else
rc = [self restoreUserPreferencesFromUserRecord: userRecord];
}