diff --git a/OpenChange/GNUmakefile b/OpenChange/GNUmakefile index 07d41a5b7..e3adc5f7e 100644 --- a/OpenChange/GNUmakefile +++ b/OpenChange/GNUmakefile @@ -133,7 +133,8 @@ $(PLREADER_TOOL)_OBJC_FILES += \ DBMSGREADER_TOOL = dbmsgreader $(DBMSGREADER_TOOL)_OBJC_FILES += \ - dbmsgreader.m + dbmsgreader.m \ + NSObject+PropertyList.m $(DBMSGREADER_TOOL)_LIB_DIRS += \ -L../SoObjects/SOGo/SOGo.framework/ -lSOGo \ diff --git a/OpenChange/MAPIStoreAppointmentWrapper.m b/OpenChange/MAPIStoreAppointmentWrapper.m index 5445f989c..24c6e1ad3 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.m +++ b/OpenChange/MAPIStoreAppointmentWrapper.m @@ -1218,7 +1218,9 @@ static NSCharacterSet *hexCharacterSet = nil; inMemCtx: (TALLOC_CTX *) memCtx { int rc; + NSRange range; NSString *stringValue; + NSString *trimingString = @"\r\n\n"; /* FIXME: there is a confusion in NGCards around "comment" and "description" */ stringValue = [event comment]; @@ -1226,6 +1228,14 @@ static NSCharacterSet *hexCharacterSet = nil; && ![stringValue isEqualToString: @"\r\n"] && ![stringValue isEqualToString: @"\n"]) { + /* Avoiding those trail weird characters at event description */ + range = [stringValue rangeOfString: trimingString + options: NSBackwardsSearch]; + if (range.location > 0) + { + stringValue = [stringValue substringToIndex: (NSMaxRange(range) -1)]; + } + rc = MAPISTORE_SUCCESS; *data = [stringValue asUnicodeInMemCtx: memCtx]; } diff --git a/OpenChange/MAPIStoreContext.h b/OpenChange/MAPIStoreContext.h index 9987b8d2f..533d7f278 100644 --- a/OpenChange/MAPIStoreContext.h +++ b/OpenChange/MAPIStoreContext.h @@ -61,10 +61,10 @@ } + (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx; + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx; + (enum mapistore_error) createRootFolder: (NSString **) mapistoreUriP withFID: (uint64_t ) fid @@ -75,11 +75,11 @@ + (int) openContext: (MAPIStoreContext **) contextPtr withURI: (const char *) newUri connectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct tdb_wrap *) indexingTdb; + andTDBIndexing: (struct indexing_context *) indexing; - (id) initFromURL: (NSURL *) newUri withConnectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct tdb_wrap *) indexingTdb; + andTDBIndexing: (struct indexing_context *) indexing; - (NSURL *) url; - (struct mapistore_connection_info *) connectionInfo; diff --git a/OpenChange/MAPIStoreContext.m b/OpenChange/MAPIStoreContext.m index 4f1e67819..5b73173d8 100644 --- a/OpenChange/MAPIStoreContext.m +++ b/OpenChange/MAPIStoreContext.m @@ -100,7 +100,7 @@ static NSMutableDictionary *contextClassMapping; } + (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx { struct mapistore_contexts_list *list, *current; @@ -112,7 +112,7 @@ static NSMutableDictionary *contextClassMapping; list = NULL; userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; [userContext activateWithUser: [userContext sogoUser]]; classes = GSObjCAllSubclassesOfClass (self); @@ -121,7 +121,7 @@ static NSMutableDictionary *contextClassMapping; { currentClass = [classes objectAtIndex: count]; current = [currentClass listContextsForUser: userName - withTDBIndexing: indexingTdb + withIndexing: indexing inMemCtx: memCtx]; if (current) DLIST_CONCATENATE(list, current, void); @@ -131,7 +131,7 @@ static NSMutableDictionary *contextClassMapping; } + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx { return NULL; @@ -216,7 +216,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) + (int) openContext: (MAPIStoreContext **) contextPtr withURI: (const char *) newUri connectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct tdb_wrap *) indexingTdb + andTDBIndexing: (struct indexing_context *) indexing { MAPIStoreContext *context; Class contextClass; @@ -239,7 +239,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) { context = [[contextClass alloc] initFromURL: baseURL withConnectionInfo: newConnInfo - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; if (context) { [context autorelease]; @@ -272,7 +272,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) - (id) initFromURL: (NSURL *) newUrl withConnectionInfo: (struct mapistore_connection_info *) newConnInfo - andTDBIndexing: (struct tdb_wrap *) indexingTdb + andTDBIndexing: (struct indexing_context *) indexing { NSString *username; @@ -291,7 +291,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) ASSIGN (userContext, [MAPIStoreUserContext userContextWithUsername: username - andTDBIndexing: indexingTdb]); + andTDBIndexing: indexing]); #if 0 mapistore_mgmt_backend_register_user (newConnInfo, @@ -374,17 +374,14 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) { if ([objectURL hasPrefix: url]) { - *path = [[objectURL substringFromIndex: 7] - asUnicodeInMemCtx: memCtx]; - [self logWithFormat: @"found path '%s' for fmid %.16x", - *path, fmid]; + *path = [[objectURL substringFromIndex: 7] asUnicodeInMemCtx: memCtx]; + [self logWithFormat: @"found path '%s' for fmid 0x%.16"PRIx64"", *path, fmid]; rc = MAPISTORE_SUCCESS; } else { - [self logWithFormat: @"context (%@, %@) does not contain" - @" found fmid: 0x%.16x", - objectURL, url, fmid]; + [self logWithFormat: @"context (%@, %@) does not contain " + @"found fmid: 0x%.16"PRIx64"", objectURL, url, fmid]; *path = NULL; rc = MAPISTORE_SUCCESS; } @@ -534,7 +531,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) { //[self warnWithFormat: @"no id exist yet for '%@', requesting one...", // childURL]; - openchangedb_get_new_folderID (connInfo->oc_ctx, &mappingId); + mapistore_indexing_get_new_folderID (connInfo->mstore_ctx, &mappingId); [mapping registerURL: childURL withID: mappingId]; contextId = 0; @@ -597,9 +594,9 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri) memCtx = talloc_zero(NULL, TALLOC_CTX); newFMIDs = [NSMutableArray arrayWithCapacity: max]; - if (openchangedb_get_new_folderIDs (connInfo->oc_ctx, - memCtx, max, &numbers) - != MAPI_E_SUCCESS || numbers->cValues != max) + if (mapistore_indexing_get_new_folderIDs (connInfo->mstore_ctx, + memCtx, max, &numbers) + != MAPISTORE_SUCCESS || numbers->cValues != max) abort (); for (count = 0; count < max; count++) { diff --git a/OpenChange/MAPIStoreFallbackContext.m b/OpenChange/MAPIStoreFallbackContext.m index 1c9a0106b..41463542a 100644 --- a/OpenChange/MAPIStoreFallbackContext.m +++ b/OpenChange/MAPIStoreFallbackContext.m @@ -45,7 +45,7 @@ } + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx { struct mapistore_contexts_list *firstContext = NULL, *context; @@ -72,7 +72,7 @@ inContainer: nil]; [root setOwner: userName]; userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; [userContext ensureFolderTableExists]; [root setTableUrl: [userContext folderTableURL]]; names = [root toManyRelationshipKeys]; diff --git a/OpenChange/MAPIStoreFolder.m b/OpenChange/MAPIStoreFolder.m index 3dba819b8..a0455efb6 100644 --- a/OpenChange/MAPIStoreFolder.m +++ b/OpenChange/MAPIStoreFolder.m @@ -433,10 +433,16 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe return rc; } -- (int) deleteFolder +- (void) deleteFolderImpl { + // TODO: raise exception in case underlying delete fails? // [propsMessage delete]; [dbFolder delete]; +} + +- (int) deleteFolder +{ + [self deleteFolderImpl]; [self cleanupCaches]; @@ -890,7 +896,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe { fmid = [mapping idFromURL: [self url]]; [mapping unregisterURLWithID: fmid]; - [self deleteFolder]; + [self deleteFolderImpl]; [mapping registerURL: [newFolder url] withID: fmid]; } diff --git a/OpenChange/MAPIStoreGCSBaseContext.m b/OpenChange/MAPIStoreGCSBaseContext.m index cc09a41fe..216eab01c 100644 --- a/OpenChange/MAPIStoreGCSBaseContext.m +++ b/OpenChange/MAPIStoreGCSBaseContext.m @@ -64,7 +64,7 @@ } + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx { struct mapistore_contexts_list *firstContext = NULL, *context; @@ -79,7 +79,7 @@ if (moduleName) { userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; parentFolder = [[userContext rootFolders] objectForKey: moduleName]; baseUrl = [NSString stringWithFormat: @"sogo://%@@%@/", userName, moduleName]; diff --git a/OpenChange/MAPIStoreMailContext.m b/OpenChange/MAPIStoreMailContext.m index 79ea0b62e..24d974e5a 100644 --- a/OpenChange/MAPIStoreMailContext.m +++ b/OpenChange/MAPIStoreMailContext.m @@ -83,7 +83,7 @@ MakeDisplayFolderName (NSString *folderName) } + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx { struct mapistore_contexts_list *firstContext = NULL, *context; @@ -100,7 +100,7 @@ MakeDisplayFolderName (NSString *folderName) WOContext *woContext; userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; accountFolder = [[userContext rootFolders] objectForKey: @"mail"]; woContext = [userContext woContext]; @@ -245,7 +245,7 @@ MakeDisplayFolderName (NSString *folderName) } + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx { struct mapistore_contexts_list *context; @@ -256,7 +256,7 @@ MakeDisplayFolderName (NSString *folderName) WOContext *woContext; userContext = [MAPIStoreUserContext userContextWithUsername: userName - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; accountFolder = [[userContext rootFolders] objectForKey: @"mail"]; woContext = [userContext woContext]; diff --git a/OpenChange/MAPIStoreMailVolatileMessage.m b/OpenChange/MAPIStoreMailVolatileMessage.m index c640ab7db..7df01fdf1 100644 --- a/OpenChange/MAPIStoreMailVolatileMessage.m +++ b/OpenChange/MAPIStoreMailVolatileMessage.m @@ -367,7 +367,7 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; msgData->recipients_count = max; msgData->recipients = talloc_array (msgData, struct mapistore_message_recipient, max); current = 0; - for (type = 0; type < 4; type++) + for (type = MAPI_ORIG; type <= MAPI_BCC; type++) { recipients = [allRecipients objectForKey: recTypes[type]]; recipientsMax = [recipients count]; @@ -541,7 +541,7 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers, NSArray *list; NSCalendarDate *date; NSDictionary *recipients; - NSUInteger type, bccLimit; + enum ulRecipClass type, bccLimit; SOGoUser *activeUser; NSNumber *priority; @@ -561,8 +561,8 @@ FillMessageHeadersFromProperties (NGMutableHashMap *headers, bccLimit = MAPI_BCC; else bccLimit = MAPI_CC; - bccLimit++; - for (type = MAPI_TO; type < bccLimit; type++) + + for (type = MAPI_TO; type <= bccLimit; type++) { recId = recTypes[type]; list = MakeRecipientsList ([recipients objectForKey: recId]); @@ -865,7 +865,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS NSMutableArray *recipientEmails; NSArray *list; NSString *recId, *from, *msgClass; - NSUInteger count; + enum ulRecipClass type; SOGoUser *activeUser; SOGoDomainDefaults *dd; NSException *error; @@ -881,9 +881,9 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NS recipientEmails = [NSMutableArray arrayWithCapacity: 32]; recipients = [properties objectForKey: @"recipients"]; - for (count = 0; count < 3; count++) + for (type = MAPI_ORIG; type <= MAPI_BCC; type++) { - recId = recTypes[count]; + recId = recTypes[type]; list = [recipients objectForKey: recId]; [recipientEmails addObjectsFromArray: [list objectsForKey: @"email" diff --git a/OpenChange/MAPIStoreMapping.h b/OpenChange/MAPIStoreMapping.h index c974c7496..620112d76 100644 --- a/OpenChange/MAPIStoreMapping.h +++ b/OpenChange/MAPIStoreMapping.h @@ -32,17 +32,15 @@ { void *memCtx; NSString *username; - struct tdb_wrap *indexing; - NSMutableDictionary *mapping; /* FID/MID -> url */ - NSMutableDictionary *reverseMapping; /* url -> FID/MID */ + struct indexing_context *indexing; NSUInteger useCount; } + (id) mappingForUsername: (NSString *) username - withIndexing: (struct tdb_wrap *) indexing; + withIndexing: (struct indexing_context *) indexing; - (id) initForUsername: (NSString *) username - withIndexing: (struct tdb_wrap *) indexing; + withIndexing: (struct indexing_context *) indexing; - (void) increaseUseCount; diff --git a/OpenChange/MAPIStoreMapping.m b/OpenChange/MAPIStoreMapping.m index ffc035aea..194488bc7 100644 --- a/OpenChange/MAPIStoreMapping.m +++ b/OpenChange/MAPIStoreMapping.m @@ -33,16 +33,15 @@ #import +#undef DEBUG +#include +#include + #import "MAPIStoreTypes.h" #import "MAPIStoreMapping.h" #include -#include - -struct tdb_wrap { - struct tdb_context *tdb; -}; static NSMutableDictionary *mappingRegistry = nil; @@ -59,51 +58,9 @@ MAPIStoreMappingKeyFromId (uint64_t idNbr) return [NSString stringWithUnsignedLongLong: idNbr]; } -static int -MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, - void *data) -{ - NSMutableDictionary *mapping; - id idKey; - NSString *uri; - char *idStr, *uriStr; - uint64_t idNbr; - - // get the key - // key examples : key(18) = "0x6900000000000001" - // key(31) = "SOFT_DELETED:0xb100020000000001" - // - idStr = (char *) data1.dptr; - idKey = nil; - - if (strncmp(idStr, "SOFT_DELETED:", 13) != 0) - { - // It's very important here to use strtoull and NOT strtoll as - // the latter will overflow a long long with typical key values. - idNbr = strtoull(idStr, NULL, 0); - // idKey = [NSNumber numberWithUnsignedLongLong: idNbr]; - idKey = MAPIStoreMappingKeyFromId(idNbr); - } - - // get the value and null-terminate it - uriStr = (char *)malloc(sizeof(char *) * data2.dsize+1); - memset(uriStr, 0, data2.dsize+1); - memcpy(uriStr, (const char *) data2.dptr, data2.dsize); - uri = [NSString stringWithUTF8String: uriStr]; - free (uriStr); - - mapping = data; - - if (uri && idKey) - { - [mapping setObject: uri forKey: idKey]; - } - - return 0; -} + (id) mappingForUsername: (NSString *) username - withIndexing: (struct tdb_wrap *) indexing + withIndexing: (struct indexing_context *) indexing { id mapping; @@ -123,8 +80,6 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, if ((self = [super init])) { memCtx = talloc_zero (NULL, TALLOC_CTX); - mapping = [NSMutableDictionary new]; - reverseMapping = [NSMutableDictionary new]; indexing = NULL; useCount = 0; } @@ -153,29 +108,12 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, } - (id) initForUsername: (NSString *) newUsername - withIndexing: (struct tdb_wrap *) newIndexing + withIndexing: (struct indexing_context *) newIndexing { - NSString *idNbr, *uri; - NSArray *keys; - NSUInteger count, max; - if ((self = [self init])) { ASSIGN (username, newUsername); indexing = newIndexing; - (void) talloc_reference (memCtx, newIndexing); - tdb_traverse_read (indexing->tdb, MAPIStoreMappingTDBTraverse, mapping); - keys = [mapping allKeys]; - max = [keys count]; - for (count = 0; count < max; count++) - { - idNbr = [keys objectAtIndex: count]; - uri = [mapping objectForKey: idNbr]; - //[self logWithFormat: @"preregistered id '%@' for url '%@'", idNbr, uri]; - [reverseMapping setObject: idNbr forKey: uri]; - } - - //[self logWithFormat: @"Complete mapping: %@ \nComplete reverse mapping: %@", mapping, reverseMapping]; } return self; @@ -184,83 +122,72 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, - (void) dealloc { [username release]; - [mapping release]; - [reverseMapping release]; talloc_free (memCtx); [super dealloc]; } - (NSString *) urlFromID: (uint64_t) idNbr { - return [mapping objectForKey: MAPIStoreMappingKeyFromId (idNbr)]; + char* url = NULL; + enum mapistore_error ret; + bool soft_delete = false; + + ret = indexing->get_uri(indexing, [username UTF8String], + memCtx, idNbr, &url, &soft_delete); + if (ret != MAPISTORE_SUCCESS) + return NULL; + NSString *res = [[[NSString alloc] initWithUTF8String:url] autorelease]; + talloc_free(url); + + return res; } - (uint64_t) idFromURL: (NSString *) url { - id key; + enum mapistore_error ret; uint64_t idNbr; + bool softDeleted; - key = [reverseMapping objectForKey: url]; - if (key) - idNbr = [key unsignedLongLongValue]; + ret = indexing->get_fmid(indexing, [username UTF8String], [url UTF8String], + false, &idNbr, &softDeleted); + + if (ret == MAPISTORE_SUCCESS && !softDeleted) + return idNbr; else - idNbr = NSNotFound; - - return idNbr; + return NSNotFound; } - (void) _updateFolderWithURL: (NSString *) oldURL withURL: (NSString *) urlString { - NSArray *allKeys; - NSUInteger count, max; - NSString *currentKey, *newKey; - id idKey; - TDB_DATA key, dbuf; + const char *searchURL; + uint64_t idNbr; + bool softDeleted; + NSString *current; + NSString *newURL; - [oldURL retain]; + if ([oldURL isEqualToString: urlString]) return; - allKeys = [reverseMapping allKeys]; - max = [allKeys count]; - for (count = 0; count < max; count++) - { - currentKey = [allKeys objectAtIndex: count]; - if ([currentKey hasPrefix: oldURL]) - { - newKey = [currentKey stringByReplacingPrefix: oldURL - withPrefix: urlString]; + searchURL = [[oldURL stringByAppendingString:@"*"] UTF8String]; - idKey = [reverseMapping objectForKey: currentKey]; - [mapping setObject: newKey forKey: idKey]; - [reverseMapping setObject: idKey forKey: newKey]; - [reverseMapping removeObjectForKey: currentKey]; + while (indexing->get_fmid(indexing, [username UTF8String], + searchURL,true, &idNbr, &softDeleted) == MAPISTORE_SUCCESS) + { + // Ignore deleted + if (softDeleted) continue; - /* update the record in the indexing database */ - key.dptr = (unsigned char *) talloc_asprintf (NULL, "0x%.16"PRIx64, - (uint64_t) [idKey unsignedLongLongValue]); - key.dsize = strlen ((const char *) key.dptr); - - dbuf.dptr = (unsigned char *) talloc_strdup (NULL, - [newKey UTF8String]); - dbuf.dsize = strlen ((const char *) dbuf.dptr); - tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY); - talloc_free (key.dptr); - talloc_free (dbuf.dptr); - } - } - - [oldURL release]; + current = [self urlFromID:idNbr]; + newURL = [current stringByReplacingPrefix: oldURL withPrefix: urlString]; + indexing->update_fmid(indexing, [username UTF8String], idNbr, [newURL UTF8String]); + } } - (void) updateID: (uint64_t) idNbr withURL: (NSString *) urlString { NSString *oldURL; - id idKey; - TDB_DATA key, dbuf; - idKey = MAPIStoreMappingKeyFromId (idNbr); - oldURL = [mapping objectForKey: idKey]; + oldURL = [self urlFromID: idNbr]; if (oldURL) { if ([oldURL hasSuffix: @"/"]) /* is container ? */ @@ -268,28 +195,16 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, if (![urlString hasSuffix: @"/"]) [NSException raise: NSInvalidArgumentException format: @"a container url must have an ending '/'"]; - tdb_transaction_start (indexing->tdb); [self _updateFolderWithURL: oldURL withURL: urlString]; - tdb_transaction_commit (indexing->tdb); } else { if ([urlString hasSuffix: @"/"]) [NSException raise: NSInvalidArgumentException format: @"a leaf url must not have an ending '/'"]; - [mapping setObject: urlString forKey: idKey]; - [reverseMapping setObject: idKey forKey: urlString]; - [reverseMapping removeObjectForKey: oldURL]; - /* update the record in the indexing database */ - key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr); - key.dsize = strlen((const char *) key.dptr); - - dbuf.dptr = (unsigned char *) talloc_strdup (NULL, [urlString UTF8String]); - dbuf.dsize = strlen((const char *) dbuf.dptr); - tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY); - talloc_free (key.dptr); - talloc_free (dbuf.dptr); + indexing->update_fmid(indexing, [username UTF8String], + idNbr, [urlString UTF8String]); } } } @@ -297,37 +212,37 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, - (BOOL) registerURL: (NSString *) urlString withID: (uint64_t) idNbr { - id idKey; - BOOL rc; - TDB_DATA key, dbuf; + NSString *oldURL; + uint64_t oldIdNbr; + bool rc; - idKey = MAPIStoreMappingKeyFromId (idNbr); - if ([mapping objectForKey: idKey] - || [reverseMapping objectForKey: urlString]) + oldURL = [self urlFromID: idNbr]; + if (oldURL != NULL) { [self errorWithFormat: - @"attempt to double register an entry ('%@', %lld," - @" 0x%.16"PRIx64")", - urlString, idNbr, idNbr]; - rc = NO; + @"url with idNbr already registered: (oldUrl='%@', newUrl='%@', id=x%.16"PRIx64")", + oldURL, urlString, idNbr]; + return NO; + } + + oldIdNbr = [self idFromURL: urlString]; + if (oldIdNbr != NSNotFound) + { + [self errorWithFormat: + @"attempt to double register an entry with idNbr ('%@', %lld," + @" 0x%.16"PRIx64", oldid=0x%.16"PRIx64")", + urlString, idNbr, idNbr, oldIdNbr]; + return NO; } else { - [mapping setObject: urlString forKey: idKey]; - [reverseMapping setObject: idKey forKey: urlString]; rc = YES; // [self logWithFormat: @"registered url '%@' with id %lld (0x%.16"PRIx64")", // urlString, idNbr, idNbr]; /* Add the record given its fid and mapistore_uri */ - key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr); - key.dsize = strlen((const char *) key.dptr); - - dbuf.dptr = (unsigned char *) talloc_strdup(NULL, [urlString UTF8String]); - dbuf.dsize = strlen((const char *) dbuf.dptr); - tdb_store (indexing->tdb, key, dbuf, TDB_INSERT); - talloc_free (key.dptr); - talloc_free (dbuf.dptr); + indexing->add_fmid(indexing, [username UTF8String], + idNbr, [urlString UTF8String]); } return rc; @@ -341,7 +256,6 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, max = [urlStrings count]; if (max == [idNbrs count]) { - tdb_transaction_start (indexing->tdb); for (count = 0; count < max; count++) { newID = [[idNbrs objectAtIndex: count] @@ -349,7 +263,6 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, [self registerURL: [urlStrings objectAtIndex: count] withID: newID]; } - tdb_transaction_commit (indexing->tdb); } else [NSException raise: NSInvalidArgumentException @@ -358,26 +271,8 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2, - (void) unregisterURLWithID: (uint64_t) idNbr { - NSString *urlString; - id idKey; - TDB_DATA key; - - idKey = MAPIStoreMappingKeyFromId (idNbr); - urlString = [mapping objectForKey: idKey]; - if (urlString) - { - // [self logWithFormat: @"unregistering url '%@' with id %lld (0x%.16"PRIx64")", - // urlString, idNbr, idNbr]; - [reverseMapping removeObjectForKey: urlString]; - [mapping removeObjectForKey: idKey]; - - /* We hard-delete the entry from the indexing database */ - key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr); - key.dsize = strlen((const char *) key.dptr); - - tdb_delete(indexing->tdb, key); - talloc_free(key.dptr); - } + indexing->del_fmid(indexing, [username UTF8String], + idNbr, MAPISTORE_PERMANENT_DELETE); } @end diff --git a/OpenChange/MAPIStoreNotesContext.m b/OpenChange/MAPIStoreNotesContext.m index 36d6804b9..594a819b5 100644 --- a/OpenChange/MAPIStoreNotesContext.m +++ b/OpenChange/MAPIStoreNotesContext.m @@ -38,7 +38,7 @@ } + (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName - withTDBIndexing: (struct tdb_wrap *) indexingTdb + withIndexing: (struct indexing_context *) indexing inMemCtx: (TALLOC_CTX *) memCtx { struct mapistore_contexts_list *context; diff --git a/OpenChange/MAPIStoreSOGo.m b/OpenChange/MAPIStoreSOGo.m index 720635975..923541764 100644 --- a/OpenChange/MAPIStoreSOGo.m +++ b/OpenChange/MAPIStoreSOGo.m @@ -49,9 +49,32 @@ #include #include +#include static Class MAPIStoreContextK = Nil; static BOOL leakDebugging = NO; +static BOOL initialization_done = NO; + +#define NS_CURRENT_THREAD_REGISTER() \ + BOOL __nsrct_thread_registered = GSRegisterCurrentThread(); \ + if (!initialization_done) { \ + DEBUG(5, ("[SOGo: %s:%d] You should call sogo_backend_init() first. Current thread: %p, pid: %d\n", \ + __FUNCTION__, __LINE__, GSCurrentThread(), getpid())); \ + } +#define NS_CURRENT_THREAD_TRY_UNREGISTER() \ + if (__nsrct_thread_registered) { \ + GSUnregisterCurrentThread(); \ + } + +#define TRYCATCH_START @try { +#define TRYCATCH_END(pool) \ + } @catch (NSException * e) { \ + enum mapistore_error ret = sogo_backend_handle_objc_exception(e, __PRETTY_FUNCTION__, __LINE__); \ + [pool release]; \ + NS_CURRENT_THREAD_TRY_UNREGISTER(); \ + return ret; \ + } + static enum mapistore_error sogo_backend_unexpected_error() @@ -61,6 +84,35 @@ sogo_backend_unexpected_error() return MAPISTORE_SUCCESS; } +static enum mapistore_error +sogo_backend_handle_objc_exception(NSException *e, const char *fn_name, const int line_no) +{ + NSString *callStackSymbols = nil; + if ([e respondsToSelector:@selector(callStackSymbols)]) + { + callStackSymbols = [[e callStackSymbols] componentsJoinedByString:@"\n\t"]; + } + NSLog(@"[SOGo: %s:%d] - EXCEPTION: %@, reason: %@, backtrace: \n\t%@\n", + fn_name, line_no, [e name], [e reason], callStackSymbols); + + // Another point of view on the stack trace + { + void *frames[128]; + int i, len = backtrace(frames, 128); + char **symbols = backtrace_symbols(frames, len); + NSLog(@"Backtrace using execinfo.h:\n"); + for (i = 0; i < len; ++i) + NSLog(@"\t%s", symbols[i]); + free(symbols); + } + + if ([[e name] isEqual:@"NotImplementedException"]) + { + return MAPISTORE_ERR_NOT_IMPLEMENTED; + } + return MAPISTORE_ERROR; +} + static void sogo_backend_atexit (void) { @@ -73,6 +125,7 @@ sogo_backend_atexit (void) GSUnregisterCurrentThread (); } + /** \details Initialize sogo mapistore backend @@ -88,7 +141,13 @@ sogo_backend_init (void) SoProductRegistry *registry; char *argv[] = { SAMBA_PREFIX "/sbin/samba", NULL }; - GSRegisterCurrentThread (); + GSRegisterCurrentThread(); + + if (initialization_done) { + DEBUG(0, ("SOGo backend already initialized.\n")); + return MAPISTORE_SUCCESS; + } + pool = [NSAutoreleasePool new]; /* Here we work around a bug in GNUstep which decodes XML user @@ -130,6 +189,9 @@ sogo_backend_init (void) [pool release]; + DEBUG(0, ("[SOGo: %s:%d] backend init SUCCESS. Current thread: %p, pid: %d\n", __FUNCTION__, __LINE__, GSCurrentThread(), getpid())); + initialization_done = YES; + return MAPISTORE_SUCCESS; } @@ -144,7 +206,7 @@ sogo_backend_init (void) static enum mapistore_error sogo_backend_create_context(TALLOC_CTX *mem_ctx, struct mapistore_connection_info *conn_info, - struct tdb_wrap *indexingTdb, + struct indexing_context *indexing, const char *uri, void **context_object) { NSAutoreleasePool *pool; @@ -153,23 +215,25 @@ sogo_backend_create_context(TALLOC_CTX *mem_ctx, DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; if (MAPIStoreContextK) { + TRYCATCH_START rc = [MAPIStoreContextK openContext: &context withURI: uri connectionInfo: conn_info - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; if (rc == MAPISTORE_SUCCESS) *context_object = [context tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) } else rc = MAPISTORE_ERROR; [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); return rc; } @@ -178,7 +242,7 @@ 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, + // struct indexing_context *indexing, TALLOC_CTX *mem_ctx, char **mapistore_urip) { NSAutoreleasePool *pool; @@ -188,11 +252,12 @@ sogo_backend_create_root_folder (const char *username, DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; if (MAPIStoreContextK) { + TRYCATCH_START userName = [NSString stringWithUTF8String: username]; folderName = [NSString stringWithUTF8String: name]; rc = [MAPIStoreContextK createRootFolder: &mapistoreUri @@ -202,18 +267,19 @@ sogo_backend_create_root_folder (const char *username, withRole: role]; if (rc == MAPISTORE_SUCCESS) *mapistore_urip = [mapistoreUri asUnicodeInMemCtx: mem_ctx]; + TRYCATCH_END(pool) } else rc = MAPISTORE_ERROR; [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); return rc; } static enum mapistore_error -sogo_backend_list_contexts(const char *username, struct tdb_wrap *indexingTdb, +sogo_backend_list_contexts(const char *username, struct indexing_context *indexing, TALLOC_CTX *mem_ctx, struct mapistore_contexts_list **contexts_listp) { @@ -223,22 +289,24 @@ sogo_backend_list_contexts(const char *username, struct tdb_wrap *indexingTdb, DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__)); - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; if (MAPIStoreContextK) { + TRYCATCH_START userName = [NSString stringWithUTF8String: username]; *contexts_listp = [MAPIStoreContextK listAllContextsForUser: userName - withTDBIndexing: indexingTdb + withIndexing: indexing inMemCtx: mem_ctx]; rc = MAPISTORE_SUCCESS; + TRYCATCH_END(pool) } else rc = MAPISTORE_ERROR; [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); return rc; } @@ -273,11 +341,15 @@ sogo_context_get_path(void *backend_object, TALLOC_CTX *mem_ctx, { wrapper = backend_object; context = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -303,13 +375,17 @@ sogo_context_get_root_folder(void *backend_object, TALLOC_CTX *mem_ctx, { wrapper = backend_object; context = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [context getRootFolder: &folder withFID: fid]; if (rc == MAPISTORE_SUCCESS) *folder_object = [folder tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -342,14 +418,18 @@ sogo_folder_open_folder(void *folder_object, TALLOC_CTX *mem_ctx, uint64_t fid, { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder openFolder: &childFolder withFID: fid]; if (rc == MAPISTORE_SUCCESS) *childfolder_object = [childFolder tallocWrapper: mem_ctx]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -382,13 +462,17 @@ sogo_folder_create_folder(void *folder_object, TALLOC_CTX *mem_ctx, { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder createFolder: &childFolder withRow: aRow andFID: fid]; if (rc == MAPISTORE_SUCCESS) *childfolder_object = [childFolder tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -421,11 +505,15 @@ sogo_folder_delete(void *folder_object) { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder deleteFolder]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -449,11 +537,15 @@ sogo_folder_get_child_count(void *folder_object, enum mapistore_table_type table { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder getChildCount: child_count ofTableType: table_type]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -481,16 +573,20 @@ sogo_folder_open_message(void *folder_object, { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder openMessage: &message withMID: mid forWriting: write_access inMemCtx: mem_ctx]; if (rc == MAPISTORE_SUCCESS) *message_object = [message tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -519,15 +615,19 @@ sogo_folder_create_message(void *folder_object, { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder createMessage: &message withMID: mid isAssociated: associated]; if (rc == MAPISTORE_SUCCESS) *message_object = [message tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -551,11 +651,15 @@ sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags) { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder deleteMessageWithMID: mid andFlags: flags]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -589,8 +693,10 @@ sogo_folder_move_copy_messages(void *folder_object, wrapper = source_folder_object; sourceFolder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [targetFolder moveCopyMessagesWithMIDs: src_mids andCount: mid_count fromFolder: sourceFolder @@ -598,8 +704,10 @@ sogo_folder_move_copy_messages(void *folder_object, andChangeKeys: target_change_keys wantCopy: want_copy inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -632,7 +740,7 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object, else targetFolder = nil; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; if (new_folder_name) @@ -640,14 +748,16 @@ sogo_folder_move_folder(void *folder_object, void *target_folder_object, else newFolderName = nil; + TRYCATCH_START rc = [moveFolder moveCopyToFolder: targetFolder withNewName: newFolderName isMove: YES isRecursive: YES inMemCtx: mem_ctx]; + TRYCATCH_END(pool) [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -677,19 +787,21 @@ sogo_folder_copy_folder(void *folder_object, void *target_folder_object, TALLOC_ wrapper = target_folder_object; targetFolder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; newFolderName = [NSString stringWithUTF8String: new_folder_name]; + TRYCATCH_START rc = [copyFolder moveCopyToFolder: targetFolder withNewName: newFolderName isMove: NO isRecursive: recursive inMemCtx: mem_ctx]; - + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -715,15 +827,19 @@ sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx, { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder getDeletedFMIDs: fmidsp andCN: cnp fromChangeNumber: change_num inTableType: table_type inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -750,16 +866,20 @@ sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx, { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder getTable: &table andRowCount: row_count tableType: table_type andHandleId: handle_id]; if (rc == MAPISTORE_SUCCESS) *table_object = [table tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -785,13 +905,17 @@ sogo_folder_modify_permissions(void *folder_object, uint8_t flags, { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder modifyPermissions: permissions withCount: pcount andFlags: flags]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -815,12 +939,16 @@ sogo_folder_preload_message_bodies(void *folder_object, enum mapistore_table_typ { wrapper = folder_object; folder = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [folder preloadMessageBodiesWithMIDs: mids ofTableType: table_type]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -846,12 +974,16 @@ sogo_message_get_message_data(void *message_object, { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START [message getMessageData: msg_dataP inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); rc = MAPISTORE_SUCCESS; } else @@ -877,14 +1009,18 @@ sogo_message_create_attachment (void *message_object, TALLOC_CTX *mem_ctx, void { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [message createAttachment: &attachment inAID: aidp]; if (rc == MAPISTORE_SUCCESS) *attachment_object = [attachment tallocWrapper: mem_ctx]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -910,14 +1046,18 @@ sogo_message_open_attachment (void *message_object, TALLOC_CTX *mem_ctx, { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [message getAttachment: &attachment withAID: aid]; if (rc == MAPISTORE_SUCCESS) *attachment_object = [attachment tallocWrapper: mem_ctx]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -942,15 +1082,19 @@ sogo_message_get_attachment_table (void *message_object, TALLOC_CTX *mem_ctx, vo { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [message getAttachmentTable: &table andRowCount: row_count]; if (rc == MAPISTORE_SUCCESS) *table_object = [table tallocWrapper: mem_ctx]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -977,14 +1121,18 @@ sogo_message_modify_recipients (void *message_object, { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [message modifyRecipientsWithRecipients: recipients andCount: count andColumns: columns]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1008,12 +1156,16 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag) { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [message setReadFlag: flag]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1037,12 +1189,16 @@ sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx) { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [message saveMessage: mem_ctx]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1066,12 +1222,16 @@ sogo_message_submit (void *message_object, enum SubmitFlags flags) { wrapper = message_object; message = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [message submitWithFlags: flags]; // [context tearDownRequest]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1100,16 +1260,20 @@ sogo_message_attachment_open_embedded_message (void *attachment_object, { wrapper = attachment_object; attachment = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [attachment openEmbeddedMessage: &message withMID: midP withMAPIStoreMsg: msg inMemCtx: mem_ctx]; if (rc == MAPISTORE_SUCCESS) *message_object = [message tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1137,15 +1301,19 @@ sogo_message_attachment_create_embedded_message (void *attachment_object, { wrapper = attachment_object; attachment = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; - rc = [attachment createEmbeddedMessage: &message - withMAPIStoreMsg: msg - inMemCtx: mem_ctx]; - if (rc == MAPISTORE_SUCCESS) - *message_object = [message tallocWrapper: mem_ctx]; + + TRYCATCH_START + rc = [attachment createEmbeddedMessage: &message + withMAPIStoreMsg: msg + inMemCtx: mem_ctx]; + if (rc == MAPISTORE_SUCCESS) + *message_object = [message tallocWrapper: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1169,11 +1337,15 @@ static enum mapistore_error sogo_table_get_available_properties(void *table_obje { wrapper = table_object; table = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1197,12 +1369,16 @@ sogo_table_set_columns (void *table_object, uint16_t count, enum MAPITAGS *prope { wrapper = table_object; table = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [table setColumns: properties withCount: count]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1226,14 +1402,18 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr { wrapper = table_object; table = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START [table setRestrictions: restrictions]; //[table cleanupCaches]; rc = MAPISTORE_SUCCESS; *table_status = TBLSTAT_COMPLETE; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1257,14 +1437,18 @@ sogo_table_set_sort_order (void *table_object, struct SSortOrderSet *sort_order, { wrapper = table_object; table = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START [table setSortOrder: sort_order]; [table cleanupCaches]; rc = MAPISTORE_SUCCESS; *table_status = TBLSTAT_COMPLETE; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1290,12 +1474,16 @@ sogo_table_get_row (void *table_object, TALLOC_CTX *mem_ctx, { wrapper = table_object; table = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [table getRow: data withRowID: row_id andQueryType: query_type inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1321,12 +1509,16 @@ sogo_table_get_row_count (void *table_object, { wrapper = table_object; table = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [table getRowCount: row_countp withQueryType: query_type]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1350,11 +1542,15 @@ sogo_table_handle_destructor (void *table_object, uint32_t handle_id) { wrapper = table_object; table = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START [table destroyHandle: handle_id]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); rc = MAPISTORE_SUCCESS; } else @@ -1380,11 +1576,15 @@ static enum mapistore_error sogo_properties_get_available_properties(void *objec { wrapper = object; propObject = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1411,13 +1611,17 @@ sogo_properties_get_properties (void *object, { wrapper = object; propObject = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [propObject getProperties: data withTags: properties andCount: count inMemCtx: mem_ctx]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1441,11 +1645,15 @@ sogo_properties_set_properties (void *object, struct SRow *aRow) { wrapper = object; propObject = wrapper->instance; - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + + TRYCATCH_START rc = [propObject addPropertiesFromRow: aRow]; + TRYCATCH_END(pool) + [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); } else { @@ -1472,9 +1680,10 @@ sogo_manager_generate_uri (TALLOC_CTX *mem_ctx, /* This fixes a crash occurring during the instantiation of the NSAutoreleasePool below. */ - GSRegisterCurrentThread (); + NS_CURRENT_THREAD_REGISTER(); pool = [NSAutoreleasePool new]; + TRYCATCH_START // printf("rootURI = %s\n", rootURI); if (rootURI) partialURLString = [NSString stringWithUTF8String: rootURI]; @@ -1494,9 +1703,10 @@ sogo_manager_generate_uri (TALLOC_CTX *mem_ctx, // printf("uri = %s\n", [partialURLString UTF8String]); *uri = talloc_strdup (mem_ctx, [partialURLString UTF8String]); + TRYCATCH_END(pool) [pool release]; - GSUnregisterCurrentThread (); + NS_CURRENT_THREAD_TRY_UNREGISTER(); return MAPISTORE_SUCCESS; } diff --git a/OpenChange/MAPIStoreUserContext.h b/OpenChange/MAPIStoreUserContext.h index 237819655..f9867d15a 100644 --- a/OpenChange/MAPIStoreUserContext.h +++ b/OpenChange/MAPIStoreUserContext.h @@ -63,10 +63,10 @@ } + (id) userContextWithUsername: (NSString *) username - andTDBIndexing: (struct tdb_wrap *) indexingTdb; + andTDBIndexing: (struct indexing_context *) indexing; - (id) initWithUsername: (NSString *) newUsername - andTDBIndexing: (struct tdb_wrap *) indexingTdb; + andTDBIndexing: (struct indexing_context *) indexing; - (NSString *) username; - (SOGoUser *) sogoUser; diff --git a/OpenChange/MAPIStoreUserContext.m b/OpenChange/MAPIStoreUserContext.m index bad00b260..04300fd35 100644 --- a/OpenChange/MAPIStoreUserContext.m +++ b/OpenChange/MAPIStoreUserContext.m @@ -60,7 +60,7 @@ static NSMapTable *contextsTable = nil; } + (id) userContextWithUsername: (NSString *) username - andTDBIndexing: (struct tdb_wrap *) indexingTdb; + andTDBIndexing: (struct indexing_context *) indexing; { id userContext; @@ -68,7 +68,7 @@ static NSMapTable *contextsTable = nil; if (!userContext) { userContext = [[self alloc] initWithUsername: username - andTDBIndexing: indexingTdb]; + andTDBIndexing: indexing]; [userContext autorelease]; [contextsTable setObject: userContext forKey: username]; } @@ -100,16 +100,12 @@ static NSMapTable *contextsTable = nil; return self; } -- (NSString *) _readUserPassword: (NSString *) newUsername +- (NSString *) _readPasswordFile: (NSString *) path { - NSString *password, *path; + NSString *password; NSData *content; - - password = nil; - - path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR - @"/mapistore/%@/password", newUsername]; + password = nil; content = [NSData dataWithContentsOfFile: path]; if (content) @@ -124,8 +120,26 @@ static NSMapTable *contextsTable = nil; return password; } +- (NSString *) _readUserPassword: (NSString *) newUsername +{ + NSString *password, *path; + + path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR + @"/mapistore/%@/password", newUsername]; + + password = [self _readPasswordFile: path]; + if (password == nil) + { + // Try to get master password + path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR @"/mapistore/master.password"]; + password = [self _readPasswordFile: path]; + } + + return password; +} + - (id) initWithUsername: (NSString *) newUsername - andTDBIndexing: (struct tdb_wrap *) indexingTdb + andTDBIndexing: (struct indexing_context *) indexing { NSString *userPassword; @@ -133,9 +147,9 @@ static NSMapTable *contextsTable = nil; { /* "username" will be retained by table */ username = newUsername; - if (indexingTdb) + if (indexing) ASSIGN (mapping, [MAPIStoreMapping mappingForUsername: username - withIndexing: indexingTdb]); + withIndexing: indexing]); authenticator = [MAPIStoreAuthenticator new]; [authenticator setUsername: username]; diff --git a/OpenChange/NSObject+MAPIStore.m b/OpenChange/NSObject+MAPIStore.m index e02f29f07..9ed02b7ab 100644 --- a/OpenChange/NSObject+MAPIStore.m +++ b/OpenChange/NSObject+MAPIStore.m @@ -47,13 +47,13 @@ MAPIStoreTallocWrapperDestroy (void *data) struct MAPIStoreTallocWrapper *wrapper; NSAutoreleasePool *pool; - GSRegisterCurrentThread (); +// GSRegisterCurrentThread (); pool = [NSAutoreleasePool new]; wrapper = data; //NSLog (@"destroying wrapped object (wrapper: %p; object: %p (%@))...\n", wrapper, wrapper->instance, NSStringFromClass([wrapper->instance class])); [wrapper->instance release]; [pool release]; - GSUnregisterCurrentThread (); +// GSUnregisterCurrentThread (); return 0; } diff --git a/OpenChange/NSObject+PropertyList.h b/OpenChange/NSObject+PropertyList.h new file mode 100644 index 000000000..34ea28ea8 --- /dev/null +++ b/OpenChange/NSObject+PropertyList.h @@ -0,0 +1,64 @@ +/* dbmsgdump.m - this file is part of SOGo + * + * Copyright (C) 2014 Kamen Mazdrashki + * + * Based on implementation done by Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * A format-agnostic dump extensions for: + * NSArray + * NSObject + * NSDictionary + */ + +#ifndef NSOBJECT_PROPERTYLIST_H +#define NSOBJECT_PROPERTYLIST_H + +#import +#import +#import + + +@interface NSObject (plext) + +- (void) displayWithIndentation: (NSInteger) anInt; + +@end + + +@interface NSDictionary (plext) + +- (void) displayKey: (NSString *) key + withIndentation: (NSInteger) anInt; + +- (void) displayWithIndentation: (NSInteger) anInt; + +@end + + +@interface NSArray (plext) + +- (void) displayCount: (NSUInteger) count + withIndentation: (NSInteger) anInt; + +- (void) displayWithIndentation: (NSInteger) anInt; + +@end + +#endif /* NSOBJECT_PROPERTYLIST_H */ diff --git a/OpenChange/NSObject+PropertyList.m b/OpenChange/NSObject+PropertyList.m index 07a42d976..164ac5054 100644 --- a/OpenChange/NSObject+PropertyList.m +++ b/OpenChange/NSObject+PropertyList.m @@ -32,14 +32,10 @@ #import #import +#import "NSObject+PropertyList.h" const char *indentationStep = " "; -@interface NSObject (plext) - -- (void) displayWithIndentation: (NSInteger) anInt; - -@end @implementation NSObject (plext) @@ -139,46 +135,3 @@ const char *indentationStep = " "; @end -static void -OCDumpPListData (NSData *content) -{ - //NSDictionary *d; - //NSPropertyListFormat format; - //NSString *error = nil; - //const char *formatName; - - //d = [NSPropertyListSerialization propertyListFromData: content - // mutabilityOption: NSPropertyListImmutable - // format: &format - // errorDescription: &error]; - //d = [content BSONValue]; - - // if (d) - // { - // switch (format) - // { - // case NSPropertyListOpenStepFormat: - // formatName = "OpenStep"; - // break; - // case NSPropertyListXMLFormat_v1_0: - // formatName = "XML"; - // break; - // case NSPropertyListBinaryFormat_v1_0: - // formatName = "Binary"; - // break; - // case NSPropertyListGNUstepFormat: - // formatName = "GNUstep"; - // break; - // case NSPropertyListGNUstepBinaryFormat: - // formatName = "GNUstep binary"; - // break; - // default: formatName = "unknown"; - // } - - // printf ("File format is: %s\n", formatName); - // [d displayWithIndentation: 0]; - // printf ("\n"); - // } - // else - // printf ("an error occurred: %s\n", [error UTF8String]); -} diff --git a/OpenChange/dbmsgreader.m b/OpenChange/dbmsgreader.m index 97b3356d0..8e56655b8 100644 --- a/OpenChange/dbmsgreader.m +++ b/OpenChange/dbmsgreader.m @@ -36,10 +36,20 @@ #import "MAPIStoreUserContext.h" #import -#import "NSObject+PropertyList.m" +#import +#import "NSObject+PropertyList.h" Class MAPIStoreUserContextK, SOGoMAPIDBObjectK; +static void +DumpBSONData(NSData *data) +{ + NSDictionary *dvalue; + dvalue = [data BSONValue]; + [dvalue displayWithIndentation:0]; + printf("\n"); +} + static void DbDumpObject (NSString *username, NSString *path) { @@ -55,8 +65,9 @@ DbDumpObject (NSString *username, NSString *path) record = [dbobject lookupRecord: path newerThanVersion: -1]; if (record) { + printf("record found: %p\n", record); content = [[record objectForKey: @"c_content"] dataByDecodingBase64]; - OCDumpPListData (content); + DumpBSONData(content); } else NSLog (@"record not found"); @@ -99,9 +110,12 @@ int main (int argc, char *argv[], char *envp[]) SOGoMAPIDBObjectK = NSClassFromString (@"SOGoMAPIDBObject"); arguments = [[NSProcessInfo processInfo] arguments]; - if ([arguments count] > 2) + if ([arguments count] > 2) { DbDumpObject ([arguments objectAtIndex: 1], [arguments objectAtIndex: 2]); + } else if ([arguments count] > 1) { + DumpBSONData([[arguments objectAtIndex:1] dataByDecodingBase64]); + } [pool release]; diff --git a/OpenChange/iCalEvent+MAPIStore.m b/OpenChange/iCalEvent+MAPIStore.m index 4d64a7ac7..40eb0c0ef 100644 --- a/OpenChange/iCalEvent+MAPIStore.m +++ b/OpenChange/iCalEvent+MAPIStore.m @@ -228,6 +228,15 @@ [start setTimeZone: tz]; if (isAllDay) { + /* when user TZ is positive (East) all-day events were not + shown properly in SOGo UI. This day delay fixes it */ + tzOffset = [userTimeZone secondsFromGMTForDate: value]; + if (tzOffset > 0) + { + value = [value dateByAddingYears: 0 months: 0 days: 1 + hours: 0 minutes: 0 + seconds: 0]; + } [start setDate: value]; [start setTimeZone: nil]; } @@ -251,6 +260,15 @@ [end setTimeZone: tz]; if (isAllDay) { + /* when user TZ is positive (East) all-day events were not + shown properly in SOGo UI. This day delay fixes it */ + tzOffset = [userTimeZone secondsFromGMTForDate: value]; + if (tzOffset > 0) + { + value = [value dateByAddingYears: 0 months: 0 days: 1 + hours: 0 minutes: 0 + seconds: 0]; + } [end setDate: value]; [end setTimeZone: nil]; } diff --git a/OpenChange/plreader.m b/OpenChange/plreader.m index f6ee15672..69d0cd099 100644 --- a/OpenChange/plreader.m +++ b/OpenChange/plreader.m @@ -29,6 +29,50 @@ #import "NSObject+PropertyList.m" +static void +OCDumpPListData (NSData *content) +{ + //NSDictionary *d; + //NSPropertyListFormat format; + //NSString *error = nil; + //const char *formatName; + + //d = [NSPropertyListSerialization propertyListFromData: content + // mutabilityOption: NSPropertyListImmutable + // format: &format + // errorDescription: &error]; + //d = [content BSONValue]; + + // if (d) + // { + // switch (format) + // { + // case NSPropertyListOpenStepFormat: + // formatName = "OpenStep"; + // break; + // case NSPropertyListXMLFormat_v1_0: + // formatName = "XML"; + // break; + // case NSPropertyListBinaryFormat_v1_0: + // formatName = "Binary"; + // break; + // case NSPropertyListGNUstepFormat: + // formatName = "GNUstep"; + // break; + // case NSPropertyListGNUstepBinaryFormat: + // formatName = "GNUstep binary"; + // break; + // default: formatName = "unknown"; + // } + + // printf ("File format is: %s\n", formatName); + // [d displayWithIndentation: 0]; + // printf ("\n"); + // } + // else + // printf ("an error occurred: %s\n", [error UTF8String]); +} + static void PLReaderDumpPListFile (NSString *filename) { diff --git a/Scripts/openchange_user_cleanup b/Scripts/openchange_user_cleanup index 411479819..e67289480 100755 --- a/Scripts/openchange_user_cleanup +++ b/Scripts/openchange_user_cleanup @@ -9,12 +9,14 @@ import re import shutil import subprocess import sys +from samba.param import LoadParm imaphost = '127.0.0.1' imapport = 143 -sambaprivate = '/var/lib/samba/private' -mapistorefolder = "%s/mapistore" % (sambaprivate) +samba_lp = LoadParm() +sambaprivate = samba_lp.get("private dir") +mapistorefolder = samba_lp.private_path("mapistore") sogoSysDefaultsFile = "/etc/sogo/sogo.conf" sogoUserDefaultsFile = os.path.expanduser("~sogo/GNUstep/Defaults/.GNUstepDefaults") @@ -212,7 +214,7 @@ On RHEL, install it using 'yum install MySQL-python'""" c=conn.cursor() tablename="sogo_cache_folder_%s" % (username) c.execute("TRUNCATE TABLE %s" % tablename) - print "Table %s emptied" + print "Table %s emptied" % tablename def postgresqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username):