diff --git a/ChangeLog b/ChangeLog index 3e1e4651e..e578ce025 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2012-02-03 Wolfgang Sourdeau + * OpenChange/MAPIStoreSOGo.m (sogo_backend_create_root_folder): + new backend method. + * OpenChange/MAPIStoreFolder.m (-createFolder:withFID:andKey:): modified method to return a enum mapistore_error, in order to better determine of the failures that occur. diff --git a/OpenChange/MAPIStoreContext.h b/OpenChange/MAPIStoreContext.h index 1ff8dc609..3d41985ad 100644 --- a/OpenChange/MAPIStoreContext.h +++ b/OpenChange/MAPIStoreContext.h @@ -68,6 +68,12 @@ + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName withTDBIndexing: (struct tdb_wrap *) indexingTdb inMemCtx: (TALLOC_CTX *) memCtx; ++ (enum mapistore_error) createRootFolder: (NSString **) mapistoreUriP + withFID: (uint64_t ) fid + andName: (NSString *) folderName + forUser: (NSString *) username + withRole: (enum mapistore_context_role) role + andTDBIndexing: (struct tdb_wrap *) indexingTdb; + (int) openContext: (MAPIStoreContext **) contextPtr withURI: (const char *) newUri @@ -104,6 +110,12 @@ /* subclass methods */ + (NSString *) MAPIModuleName; ++ (enum mapistore_context_role) MAPIContextRole; ++ (NSString *) + createRootSecondaryFolderWithFID: (uint64_t) fid + andName: (NSString *) folderName + forUser: (NSString *) userName + withTDBIndexing: (struct tdb_wrap *) indexingTdb; - (Class) MAPIStoreFolderClass; /* the top-most parent of the context folder: SOGoMailAccount, diff --git a/OpenChange/MAPIStoreContext.m b/OpenChange/MAPIStoreContext.m index 921aaafef..376e5e63b 100644 --- a/OpenChange/MAPIStoreContext.m +++ b/OpenChange/MAPIStoreContext.m @@ -35,6 +35,7 @@ #import "MAPIStoreAttachment.h" // #import "MAPIStoreAttachmentTable.h" +#import "MAPIStoreFallbackContext.h" #import "MAPIStoreFolder.h" #import "MAPIStoreFolderTable.h" #import "MAPIStoreMapping.h" @@ -66,7 +67,7 @@ /* sogo://username:password@{contacts,calendar,tasks,journal,notes,mail}/dossier/id */ -static Class NSExceptionK; +static Class NSExceptionK, MAPIStoreFallbackContextK; static NSMutableDictionary *contextClassMapping; @@ -89,11 +90,13 @@ static NSMutableDictionary *contextClassMapping; if (moduleName) { [contextClassMapping setObject: currentClass - forKey: moduleName]; + forKey: moduleName]; NSLog (@" registered class '%@' as handler of '%@' contexts", NSStringFromClass (currentClass), moduleName); } } + + MAPIStoreFallbackContextK = [MAPIStoreFallbackContext class]; } + (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName @@ -127,13 +130,73 @@ static NSMutableDictionary *contextClassMapping; return list; } -+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName ++ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName withTDBIndexing: (struct tdb_wrap *) indexingTdb inMemCtx: (TALLOC_CTX *) memCtx { return NULL; } +static Class +MAPIStoreLookupContextClassByRole (Class self, enum mapistore_context_role role) +{ + static NSMutableDictionary *classMapping = nil; + Class currentClass; + enum mapistore_context_role classRole; + NSNumber *roleNbr; + NSArray *classes; + NSUInteger count, max; + + if (!classMapping) + { + classMapping = [NSMutableDictionary new]; + classes = GSObjCAllSubclassesOfClass (self); + max = [classes count]; + for (count = 0; count < max; count++) + { + currentClass = [classes objectAtIndex: count]; + classRole = [currentClass MAPIContextRole]; + if (classRole != -1) + { + roleNbr = [NSNumber numberWithUnsignedInt: classRole]; + [classMapping setObject: currentClass + forKey: roleNbr]; + } + } + } + + roleNbr = [NSNumber numberWithUnsignedInt: role]; + + return [classMapping objectForKey: roleNbr]; +} + ++ (enum mapistore_error) createRootFolder: (NSString **) mapistoreUriP + withFID: (uint64_t) fid + andName: (NSString *) folderName + forUser: (NSString *) userName + withRole: (enum mapistore_context_role) role + andTDBIndexing: (struct tdb_wrap *) indexingTdb +{ + Class contextClass; + NSString *mapistoreURI; + enum mapistore_error rc = MAPISTORE_SUCCESS; + + contextClass = MAPIStoreLookupContextClassByRole (self, role); + if (!contextClass) + contextClass = MAPIStoreFallbackContextK; + + mapistoreURI = [contextClass createRootSecondaryFolderWithFID: fid + andName: (NSString *) folderName + forUser: userName + withTDBIndexing: indexingTdb]; + if (mapistoreURI) + *mapistoreUriP = mapistoreURI; + else + rc = MAPISTORE_ERROR; + + return rc; +} + static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) { NSString *urlString; @@ -474,6 +537,22 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) return nil; } ++ (enum mapistore_context_role) MAPIContextRole +{ + return -1; +} + ++ (NSString *) + createRootSecondaryFolderWithFID: (uint64_t) fid + andName: (NSString *) folderName + forUser: (NSString *) userName + withTDBIndexing: (struct tdb_wrap *) indexingTdb +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + - (Class) MAPIStoreFolderClass { [self subclassResponsibility: _cmd]; diff --git a/OpenChange/MAPIStoreFallbackContext.m b/OpenChange/MAPIStoreFallbackContext.m index c234e1f84..c3ff666bb 100644 --- a/OpenChange/MAPIStoreFallbackContext.m +++ b/OpenChange/MAPIStoreFallbackContext.m @@ -24,10 +24,12 @@ #import #import -#import "MAPIStoreFallbackContext.h" +#import "MAPIStoreUserContext.h" #import "NSString+MAPIStore.h" #import "SOGoMAPIFSFolder.h" +#import "MAPIStoreFallbackContext.h" + #undef DEBUG #include @@ -38,6 +40,11 @@ return @"fallback"; } ++ (enum mapistore_context_role) MAPIContextRole +{ + return MAPISTORE_MAIL_ROLE; +} + + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName withTDBIndexing: (struct tdb_wrap *) indexingTdb inMemCtx: (TALLOC_CTX *) memCtx @@ -82,4 +89,14 @@ return firstContext; } ++ (NSString *) + createRootSecondaryFolderWithFID: (uint64_t) fid + andName: (NSString *) folderName + forUser: (NSString *) userName + withTDBIndexing: (struct tdb_wrap *) indexingTdb +{ + return [NSString stringWithFormat: @"sogo://%@@fallback/0x%.16"PRIx64"/", + userName, (unsigned long long) fid]; +} + @end diff --git a/OpenChange/MAPIStoreGCSBaseContext.m b/OpenChange/MAPIStoreGCSBaseContext.m index 5b8344f1c..a8e552e9c 100644 --- a/OpenChange/MAPIStoreGCSBaseContext.m +++ b/OpenChange/MAPIStoreGCSBaseContext.m @@ -88,6 +88,30 @@ return firstContext; } ++ (NSString *) + createRootSecondaryFolderWithFID: (uint64_t) fid + andName: (NSString *) folderName + forUser: (NSString *) userName + withTDBIndexing: (struct tdb_wrap *) indexingTdb +{ + NSString *mapistoreURI, *nameInContainer, *moduleName; + MAPIStoreUserContext *userContext; + SOGoParentFolder *parentFolder; + + userContext = [MAPIStoreUserContext userContextWithUsername: userName + andTDBIndexing: indexingTdb]; + moduleName = [self MAPIModuleName]; + parentFolder = [[userContext rootFolders] objectForKey: moduleName]; + if (![parentFolder newFolderWithName: folderName + nameInContainer: &nameInContainer]) + mapistoreURI = [NSString stringWithFormat: @"sogo://%@@%@/%@/", + userName, moduleName, nameInContainer]; + else + mapistoreURI = nil; + + return mapistoreURI; +} + - (id) rootSOGoFolder { return [[userContext rootFolders] objectForKey: [isa MAPIModuleName]]; diff --git a/OpenChange/MAPIStoreMailContext.m b/OpenChange/MAPIStoreMailContext.m index 58825e166..84d4c935a 100644 --- a/OpenChange/MAPIStoreMailContext.m +++ b/OpenChange/MAPIStoreMailContext.m @@ -31,6 +31,7 @@ #import "MAPIStoreUserContext.h" #import "NSString+MAPIStore.h" +#import #import "MAPIStoreMailContext.h" #include @@ -51,6 +52,11 @@ static Class MAPIStoreMailFolderK; return @"mail"; } ++ (enum mapistore_context_role) MAPIContextRole +{ + return MAPISTORE_MAIL_ROLE; +} + + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName withTDBIndexing: (struct tdb_wrap *) indexingTdb inMemCtx: (TALLOC_CTX *) memCtx @@ -93,7 +99,7 @@ static Class MAPIStoreMailFolderK; folderName[count]]; context->url = [stringData asUnicodeInMemCtx: context]; /* remove "folder" prefix */ - stringData = [folderName[count] substringFromIndex: 6]; + stringData = [[folderName[count] substringFromIndex: 6] fromCSSIdentifier]; context->name = [stringData asUnicodeInMemCtx: context]; context->main_folder = true; context->role = role[count]; @@ -116,7 +122,7 @@ static Class MAPIStoreMailFolderK; currentName = [secondaryFolders objectAtIndex: count]; stringData = [NSString stringWithFormat: @"%@%@", urlBase, currentName]; context->url = [stringData asUnicodeInMemCtx: context]; - stringData = [currentName substringFromIndex: 6]; + stringData = [[currentName substringFromIndex: 6] fromCSSIdentifier]; context->name = [stringData asUnicodeInMemCtx: context]; context->main_folder = false; context->role = MAPISTORE_MAIL_ROLE; @@ -127,6 +133,33 @@ static Class MAPIStoreMailFolderK; return firstContext; } ++ (NSString *) + createRootSecondaryFolderWithFID: (uint64_t) fid + andName: (NSString *) newFolderName + forUser: (NSString *) userName + withTDBIndexing: (struct tdb_wrap *) indexingTdb +{ + NSString *mapistoreURI, *folderName; + MAPIStoreUserContext *userContext; + SOGoMailAccount *accountFolder; + SOGoMailFolder *newFolder; + + userContext = [MAPIStoreUserContext userContextWithUsername: userName + andTDBIndexing: indexingTdb]; + accountFolder = [[userContext rootFolders] objectForKey: @"mail"]; + folderName = [NSString stringWithFormat: @"folder%@", + [newFolderName asCSSIdentifier]]; + newFolder = [SOGoMailFolder objectWithName: folderName + inContainer: accountFolder]; + if ([newFolder create]) + mapistoreURI = [NSString stringWithFormat: @"sogo://%@:%@@mail/%@/", + userName, userName, folderName]; + else + mapistoreURI = nil; + + return mapistoreURI; +} + - (Class) MAPIStoreFolderClass { return MAPIStoreMailFolderK; diff --git a/OpenChange/MAPIStoreSOGo.m b/OpenChange/MAPIStoreSOGo.m index 1c8bc75a9..7f6767eb6 100644 --- a/OpenChange/MAPIStoreSOGo.m +++ b/OpenChange/MAPIStoreSOGo.m @@ -42,6 +42,7 @@ #import "MAPIStoreObject.h" #import "MAPIStoreTable.h" #import "NSObject+MAPIStore.h" +#import "NSString+MAPIStore.h" #include #include @@ -147,6 +148,43 @@ sogo_backend_create_context(TALLOC_CTX *mem_ctx, return rc; } +static enum mapistore_error +sogo_backend_create_root_folder (const char *username, + enum mapistore_context_role role, + uint64_t fid, const char *name, + struct tdb_wrap *indexingTdb, + TALLOC_CTX *mem_ctx, char **mapistore_urip) +{ + NSAutoreleasePool *pool; + NSString *userName, *folderName; + NSString *mapistoreUri; + int rc; + + DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); + + pool = [NSAutoreleasePool new]; + + if (MAPIStoreContextK) + { + userName = [NSString stringWithUTF8String: username]; + folderName = [NSString stringWithUTF8String: name]; + rc = [MAPIStoreContextK createRootFolder: &mapistoreUri + withFID: fid + andName: folderName + forUser: userName + withRole: role + andTDBIndexing: indexingTdb]; + if (rc == MAPISTORE_SUCCESS) + *mapistore_urip = [mapistoreUri asUnicodeInMemCtx: mem_ctx]; + } + else + rc = MAPISTORE_ERROR; + + [pool release]; + + return rc; +} + static enum mapistore_error sogo_backend_list_contexts(const char *username, struct tdb_wrap *indexingTdb, TALLOC_CTX *mem_ctx, @@ -1239,6 +1277,7 @@ int mapistore_init_backend(void) backend.backend.namespace = "sogo://"; backend.backend.init = sogo_backend_init; backend.backend.create_context = sogo_backend_create_context; + backend.backend.create_root_folder = sogo_backend_create_root_folder; backend.backend.list_contexts = sogo_backend_list_contexts; backend.context.get_path = sogo_context_get_path; backend.context.get_root_folder = sogo_context_get_root_folder;