From 6aa8c38a63c8f81a1b7359fbd64aeea0e81355b4 Mon Sep 17 00:00:00 2001 From: helge Date: Tue, 17 Apr 2007 21:47:07 +0000 Subject: [PATCH] applied patch #1850 git-svn-id: http://svn.opengroupware.org/SOPE/trunk@1471 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-gdl1/GDLContentStore/ChangeLog | 9 + sope-gdl1/GDLContentStore/GCSFolder.h | 2 + sope-gdl1/GDLContentStore/GCSFolder.m | 38 +++- sope-gdl1/GDLContentStore/GCSFolderManager.h | 5 + sope-gdl1/GDLContentStore/GCSFolderManager.m | 205 ++++++++++++++++++- sope-gdl1/GDLContentStore/Version | 2 +- 6 files changed, 250 insertions(+), 11 deletions(-) diff --git a/sope-gdl1/GDLContentStore/ChangeLog b/sope-gdl1/GDLContentStore/ChangeLog index 269d7350..4e01dfc5 100644 --- a/sope-gdl1/GDLContentStore/ChangeLog +++ b/sope-gdl1/GDLContentStore/ChangeLog @@ -1,3 +1,12 @@ +2007-04-17 Helge Hess + + * fixed a few GNUstep compilation warnings (v4.7.42) + +2007-03-21 Wolfgang Sourdeau + + * GCSFolder.[hm], GCSFolderManager.[hm]: added ability to create and + delete GCS folders programmatically (OGo bug #1850) (v4.7.41) + 2007-02-12 Helge Hess * GCSFolder.m: fixed a gnustep-base compilation warning (v4.7.40) diff --git a/sope-gdl1/GDLContentStore/GCSFolder.h b/sope-gdl1/GDLContentStore/GCSFolder.h index 6abd810d..e461666c 100644 --- a/sope-gdl1/GDLContentStore/GCSFolder.h +++ b/sope-gdl1/GDLContentStore/GCSFolder.h @@ -112,6 +112,8 @@ - (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name; - (NSException *)deleteContentWithName:(NSString *)_name; +- (NSException *)deleteFolder; + - (NSDictionary *)fetchContentsOfAllFiles; - (NSArray *)fetchFields:(NSArray *)_flds diff --git a/sope-gdl1/GDLContentStore/GCSFolder.m b/sope-gdl1/GDLContentStore/GCSFolder.m index cdac1c30..5033c6db 100644 --- a/sope-gdl1/GDLContentStore/GCSFolder.m +++ b/sope-gdl1/GDLContentStore/GCSFolder.m @@ -367,7 +367,7 @@ static GCSStringFormatter *stringFormatter = nil; _value = [_value stringValue]; return ([(NSString *)_value hasPrefix:@"Y"] || [(NSString *)_value hasPrefix:@"N"]) - ? ([_value boolValue] ? @"1" : @"0") + ? (id)([_value boolValue] ? @"1" : @"0") : _value; #endif return [_value stringValue]; @@ -637,6 +637,7 @@ static GCSStringFormatter *stringFormatter = nil; return error; } + - (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name { /* this method does not check for concurrent writes */ return [self writeContent:_content toName:_name baseVersion:0]; @@ -706,6 +707,41 @@ static GCSStringFormatter *stringFormatter = nil; return error; } +- (NSException *)deleteFolder { + EOAdaptorChannel *channel; + NSString *delsql; + NSString *table; + + /* open channels */ + + if ((channel = [self acquireStoreChannel]) == nil) { + [self errorWithFormat:@"could not open channel!"]; + return nil; + } + + /* delete rows */ + + table = [self storeTableName]; + if ([table length] > 0) { + delsql = [@"DROP TABLE " stringByAppendingString: table]; + [channel evaluateExpressionX:delsql]; + } + table = [self quickTableName]; + if ([table length] > 0) { + delsql = [@"DROP TABLE " stringByAppendingString: table]; + [channel evaluateExpressionX:delsql]; + } + table = [self aclTableName]; + if ([table length] > 0) { + delsql = [@"DROP TABLE " stringByAppendingString: table]; + [channel evaluateExpressionX:delsql]; + } + + [self releaseChannel:channel]; + + return nil; +} + - (NSString *)columnNameForFieldName:(NSString *)_fieldName { return _fieldName; } diff --git a/sope-gdl1/GDLContentStore/GCSFolderManager.h b/sope-gdl1/GDLContentStore/GCSFolderManager.h index 4610ce7d..eaafae84 100644 --- a/sope-gdl1/GDLContentStore/GCSFolderManager.h +++ b/sope-gdl1/GDLContentStore/GCSFolderManager.h @@ -39,6 +39,7 @@ GCSChannelManager *channelManager; NSDictionary *nameToType; NSURL *folderInfoLocation; + NSString *folderNamePrefix; } + (id)defaultFolderManager; @@ -46,6 +47,9 @@ /* accessors */ +- (void) setFolderNamePrefix:(NSString *)_folderNamePrefix; +- (NSString *) folderNamePrefix; + - (NSURL *)folderInfoLocation; - (NSString *)folderInfoTableName; @@ -68,6 +72,7 @@ - (GCSFolder *)folderAtPath:(NSString *)_path; - (NSException *)createFolderOfType:(NSString *)_type atPath:(NSString *)_path; +- (NSException *)deleteFolderAtPath:(NSString *)_path; /* folder types */ diff --git a/sope-gdl1/GDLContentStore/GCSFolderManager.m b/sope-gdl1/GDLContentStore/GCSFolderManager.m index 3d1adeff..5de55dd9 100644 --- a/sope-gdl1/GDLContentStore/GCSFolderManager.m +++ b/sope-gdl1/GDLContentStore/GCSFolderManager.m @@ -57,6 +57,7 @@ static NSString *GCSTypeRecordName = @"c_folder_type"; static NSString *GCSPathRecordName = @"c_path"; static NSString *GCSGenericFolderTypeName = @"Container"; static const char *GCSPathColumnPattern = "c_path%i"; +static NSCharacterSet *asciiAlphaNumericCS = nil; + (void)initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; @@ -64,6 +65,15 @@ static const char *GCSPathColumnPattern = "c_path%i"; debugOn = [ud boolForKey:@"GCSFolderManagerDebugEnabled"]; debugSQLGen = [ud boolForKey:@"GCSFolderManagerSQLDebugEnabled"]; emptyArray = [[NSArray alloc] init]; + if (!asciiAlphaNumericCS) + { + asciiAlphaNumericCS + = [NSCharacterSet characterSetWithCharactersInString: + @"0123456789" + @"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + @"abcdefghijklmnopqrstuvwxyz"]; + [asciiAlphaNumericCS retain]; + } } + (id)defaultFolderManager { @@ -134,6 +144,7 @@ static const char *GCSPathColumnPattern = "c_path%i"; if ((self = [super init])) { self->channelManager = [[GCSChannelManager defaultChannelManager] retain]; self->folderInfoLocation = [_url retain]; + self->folderNamePrefix = nil; if ([[self folderInfoTableName] length] == 0) { [self logWithFormat:@"ERROR(%s): missing tablename in URL: %@", @@ -152,11 +163,22 @@ static const char *GCSPathColumnPattern = "c_path%i"; [self->nameToType release]; [self->folderInfoLocation release]; [self->channelManager release]; + [self->folderNamePrefix release]; [super dealloc]; } /* accessors */ +- (void) setFolderNamePrefix:(NSString *)_folderNamePrefix +{ + ASSIGN(self->folderNamePrefix, _folderNamePrefix); +} + +- (NSString *) folderNamePrefix +{ + return self->folderNamePrefix; +} + - (NSURL *)folderInfoLocation { return self->folderInfoLocation; } @@ -605,21 +627,186 @@ static const char *GCSPathColumnPattern = "c_path%i"; return [self folderForRecord:record]; } +- (NSString *)sqlCreateWithTableName: (NSString *)_tabName { + return [NSString stringWithFormat: @"CREATE TABLE %@ (\n" + @" c_name VARCHAR (256) NOT NULL,\n" + @" c_content VARCHAR (100000) NOT NULL,\n" + @" c_creationdate INT4 NOT NULL,\n" + @" c_lastmodified INT4 NOT NULL,\n" + @" c_version INT4 NOT NULL\n" + @")", + _tabName]; +} + +- (NSString *)sqlAclCreateWithTableName: (NSString *)_tabName { + return [NSString stringWithFormat: @"CREATE TABLE %@ (\n" + @" c_uid VARCHAR (256) NOT NULL,\n" + @" c_object VARCHAR (256) NOT NULL,\n" + @" c_role VARCHAR (80) NOT NULL\n" + @")", + _tabName]; +} + +- (NSString *)baseTableNameForFolderAtPath:(NSString *)_path { + NSMutableString *fixedPath; + unsigned int count, max; + unichar currentChar; + + fixedPath = [NSMutableString new]; + [fixedPath autorelease]; + + if (self->folderNamePrefix != nil) + [fixedPath appendString: self->folderNamePrefix]; + + max = [_path length]; + for (count = 0; count < max; count++) { + currentChar = [_path characterAtIndex: count]; + if ([asciiAlphaNumericCS characterIsMember: currentChar]) + [fixedPath appendFormat: @"%Lc", currentChar]; + else + [fixedPath appendString: @"_"]; + } + + return (([fixedPath length] < 49) + ? (NSString *)fixedPath : [fixedPath substringToIndex: 49]); +} + +- (NSString *)finalizedTableNameForBaseName:(NSString *)_baseName + atBaseURL:(NSString *)_baseURL + withChannel:(EOAdaptorChannel *)_channel { + NSString *potentialName, *sqlTestFormat, *sqlTest; + unsigned int count; + + potentialName = _baseName; + sqlTestFormat = [NSString stringWithFormat: @"SELECT * FROM %@" + @" WHERE c_location = '%@/%%@'" + @" OR c_quick_location = '%@/%%@_quick'" + @" OR c_acl_location = '%@/%%@_acl'", + [self folderInfoTableName], + _baseURL, _baseURL, _baseURL]; + + sqlTest = [NSString stringWithFormat: sqlTestFormat, + potentialName, potentialName, potentialName]; + count = 0; + while ([[self performSQL: sqlTest] count] > 0) { + count++; + potentialName = [NSString stringWithFormat: @"%@%d", _baseName, count]; + sqlTest = [NSString stringWithFormat: sqlTestFormat, + potentialName, potentialName, potentialName]; + } + + return potentialName; +} + - (NSException *)createFolderOfType:(NSString *)_type atPath:(NSString *)_path{ - // TODO: implement folder create GCSFolderType *ftype; - + NSString *tableName, *quickTableName, *aclTableName; + NSString *baseURL; + EOAdaptorChannel *channel; + NSMutableArray *paths; + + if ([[self performSQL: [NSString stringWithFormat: @"SELECT * FROM %@" + @" WHERE c_path = '%@'", + [self folderInfoTableName], _path]] + count] > 0) { + return [NSException exceptionWithName:@"GCSExitingFolder" + reason:@"a folder already exists at that path" + userInfo:nil]; + } if ((ftype = [self folderTypeWithName:_type]) == nil) { return [NSException exceptionWithName:@"GCSMissingFolderType" - reason:@"missing folder type" + reason:@"missing folder type"userInfo:nil]; + } + if ((channel = [self acquireOpenChannel]) == nil) { + return [NSException exceptionWithName:@"GCSNoChannel" + reason:@"could not open channel" userInfo:nil]; } - - [self logWithFormat:@"create folder of type: %@", ftype]; - - return [NSException exceptionWithName:@"NotYetImplemented" - reason:@"no money, no time, ..." - userInfo:nil]; + + tableName = [self baseTableNameForFolderAtPath: _path]; + baseURL + = [[folderInfoLocation absoluteString] stringByDeletingLastPathComponent]; + tableName = [self finalizedTableNameForBaseName: tableName + atBaseURL: baseURL withChannel: channel]; + quickTableName = [NSString stringWithFormat: @"%@_quick", tableName]; + aclTableName = [NSString stringWithFormat: @"%@_acl", tableName]; + + [channel evaluateExpressionX: + [NSString stringWithFormat: @"DROP TABLE %@", tableName]]; + [channel evaluateExpressionX: + [NSString stringWithFormat: @"DROP TABLE %@", quickTableName]]; + [channel evaluateExpressionX: + [NSString stringWithFormat: @"DROP TABLE %@", aclTableName]]; + [channel evaluateExpressionX: + [self sqlCreateWithTableName: tableName]]; + [channel evaluateExpressionX: + [ftype sqlQuickCreateWithTableName: quickTableName]]; + [channel evaluateExpressionX: + [self sqlAclCreateWithTableName: aclTableName]]; + + paths = [NSMutableArray + arrayWithArray: [_path componentsSeparatedByString: @"/"]]; + while ([paths count] < 5) + [paths addObject: @""]; + + [channel evaluateExpressionX: + [NSString stringWithFormat: @"INSERT INTO %@" + @" (c_path, c_path1, c_path2, c_path3, c_path4," + @" c_foldername, c_location, c_quick_location," + @" c_acl_location, c_folder_type)" + @" VALUES ('%@', '%@', '%@', '%@', '%@', '%@', '%@/%@'," + @" '%@/%@', '%@/%@', '%@')", + [self folderInfoTableName], _path, + [paths objectAtIndex: 1], [paths objectAtIndex: 2], + [paths objectAtIndex: 3], [paths objectAtIndex: 4], + [_path lastPathComponent], + baseURL, tableName, + baseURL, quickTableName, + baseURL, aclTableName, + _type]]; + + [self releaseChannel: channel]; + + return nil; +} + +- (NSException *)deleteFolderAtPath:(NSString *)_path { + GCSFolder *folder; + NSArray *fnames; + NSString *sql, *ws; + EOAdaptorChannel *channel; + NSException *ex; + + if ((folder = [self folderAtPath:_path]) == nil) { + return [NSException exceptionWithName:@"GCSMissingFolder" + reason:@"missing folder" + userInfo:nil]; + } + + if ((fnames = [self internalNamesFromPath:_path]) == nil) { + [self debugWithFormat:@"got no internal names for path: '%@'", _path]; + return nil; + } + + ws = [self generateSQLWhereForInternalNames:fnames + exactMatch:YES orDirectSubfolderMatch:NO]; + + sql = [NSString stringWithFormat: @"DELETE FROM %@ WHERE %@", + [self folderInfoTableName], ws]; + if ((channel = [self acquireOpenChannel]) == nil) { + return [NSException exceptionWithName:@"GCSNoChannel" + reason:@"could not " + userInfo:nil]; + } + + if ((ex = [channel evaluateExpressionX:sql]) != nil) { + [self releaseChannel:channel]; + return ex; + } + + [self releaseChannel:channel]; + + return [folder deleteFolder]; } /* folder types */ diff --git a/sope-gdl1/GDLContentStore/Version b/sope-gdl1/GDLContentStore/Version index 28606453..945ea188 100644 --- a/sope-gdl1/GDLContentStore/Version +++ b/sope-gdl1/GDLContentStore/Version @@ -2,7 +2,7 @@ MAJOR_VERSION:=4 MINOR_VERSION:=7 -SUBMINOR_VERSION:=40 +SUBMINOR_VERSION:=42 # v4.5.29 requires libNGExtensions v4.5.161 # v4.5.26 does not require libNGiCal anymore -- 2.39.5