sogo/OpenChange/MAPIStoreSOGo.m

1784 lines
47 KiB
Objective-C

/* MAPIStoreSOGo.m - this file is part of SOGo
*
* Copyright (C) 2010-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* 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.
*/
/* OpenChange SOGo storage backend */
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSDebug.h>
#import <Foundation/NSFileHandle.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSThread.h>
#import <NGObjWeb/SoProductRegistry.h>
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoProductLoader.h>
#import <SOGo/SOGoSystemDefaults.h>
#import "MAPIApplication.h"
#import "MAPIStoreAttachment.h"
#import "MAPIStoreAttachmentTable.h"
#import "MAPIStoreContext.h"
#import "MAPIStoreEmbeddedMessage.h"
#import "MAPIStoreFolder.h"
#import "MAPIStoreMessage.h"
#import "MAPIStoreMailVolatileMessage.h"
#import "MAPIStoreObject.h"
#import "MAPIStoreTable.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
#include <execinfo.h>
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()
{
NSLog (@" UNEXPECTED WEIRDNESS: RECEIVED NO OBJECT");
abort();
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)
{
NSAutoreleasePool *pool;
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
//NSLog (@"allocated classes:\n%s", GSDebugAllocationList (YES));
[pool release];
GSUnregisterCurrentThread ();
}
/**
\details Initialize sogo mapistore backend
\return MAPISTORE_SUCCESS on success
*/
static enum mapistore_error
sogo_backend_init (void)
{
NSAutoreleasePool *pool;
SOGoProductLoader *loader;
Class MAPIApplicationK;
NSUserDefaults *ud;
SoProductRegistry *registry;
char *argv[] = { SAMBA_PREFIX "/sbin/samba", NULL };
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
defaults using the system encoding rather than honouring
the encoding specified in the file. */
putenv ("GNUSTEP_STRING_ENCODING=NSUTF8StringEncoding");
//putenv ("NSZombieEnabled=YES");
[NSProcessInfo initializeWithArguments: argv
count: 1
environment: environ];
[SOGoSystemDefaults sharedSystemDefaults];
/* We force the plugin to base its configuration on the SOGo tree. */
ud = [NSUserDefaults standardUserDefaults];
if (!leakDebugging && [ud boolForKey: @"SOGoDebugLeaks"])
{
NSLog (@" leak debugging on");
GSDebugAllocationActive (YES);
atexit (sogo_backend_atexit);
leakDebugging = YES;
}
registry = [SoProductRegistry sharedProductRegistry];
[registry scanForProductsInDirectory: SOGO_BUNDLES_DIR];
loader = [SOGoProductLoader productLoader];
[loader loadProducts: [NSArray arrayWithObject: BACKEND_BUNDLE_NAME]];
MAPIApplicationK = NSClassFromString (@"MAPIApplication");
if (MAPIApplicationK)
[[MAPIApplicationK new] activateApplication];
[[SOGoCache sharedCache] disableRequestsCache];
[[SOGoCache sharedCache] disableLocalCache];
MAPIStoreContextK = NSClassFromString (@"MAPIStoreContext");
[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;
}
/**
\details Create a connection context to the sogo backend
\param mem_ctx pointer to the memory context
\param uri pointer to the sogo path
\param private_data pointer to the private backend context
*/
static enum mapistore_error
sogo_backend_create_context(TALLOC_CTX *mem_ctx,
struct mapistore_connection_info *conn_info,
struct indexing_context *indexing,
const char *uri, void **context_object)
{
NSAutoreleasePool *pool;
MAPIStoreContext *context;
int rc;
DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
if (MAPIStoreContextK)
{
TRYCATCH_START
rc = [MAPIStoreContextK openContext: &context
withURI: uri
connectionInfo: conn_info
andTDBIndexing: indexing];
if (rc == MAPISTORE_SUCCESS)
*context_object = [context tallocWrapper: mem_ctx];
TRYCATCH_END(pool)
}
else
rc = MAPISTORE_ERROR;
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
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 indexing_context *indexing,
TALLOC_CTX *mem_ctx, char **mapistore_urip)
{
NSAutoreleasePool *pool;
NSString *userName, *folderName;
NSString *mapistoreUri;
int rc;
DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
if (MAPIStoreContextK)
{
TRYCATCH_START
userName = [NSString stringWithUTF8String: username];
folderName = [NSString stringWithUTF8String: name];
rc = [MAPIStoreContextK createRootFolder: &mapistoreUri
withFID: fid
andName: folderName
forUser: userName
withRole: role];
if (rc == MAPISTORE_SUCCESS)
*mapistore_urip = [mapistoreUri asUnicodeInMemCtx: mem_ctx];
TRYCATCH_END(pool)
}
else
rc = MAPISTORE_ERROR;
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
return rc;
}
static enum mapistore_error
sogo_backend_list_contexts(const char *username, struct indexing_context *indexing,
TALLOC_CTX *mem_ctx,
struct mapistore_contexts_list **contexts_listp)
{
NSAutoreleasePool *pool;
NSString *userName;
int rc;
DEBUG(0, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
if (MAPIStoreContextK)
{
TRYCATCH_START
userName = [NSString stringWithUTF8String: username];
*contexts_listp = [MAPIStoreContextK listAllContextsForUser: userName
withIndexing: indexing
inMemCtx: mem_ctx];
rc = MAPISTORE_SUCCESS;
TRYCATCH_END(pool)
}
else
rc = MAPISTORE_ERROR;
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
return rc;
}
// andFID: fid
// uint64_t fid,
// void **private_data)
/**
\details return the mapistore path associated to a given message or
folder ID
\param private_data pointer to the current sogo context
\param fmid the folder/message ID to lookup
\param type whether it is a folder or message
\param path pointer on pointer to the path to return
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
*/
static enum mapistore_error
sogo_context_get_path(void *backend_object, TALLOC_CTX *mem_ctx,
uint64_t fmid, char **path)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreContext *context;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (backend_object)
{
wrapper = backend_object;
context = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_context_get_root_folder(void *backend_object, TALLOC_CTX *mem_ctx,
uint64_t fid, void **folder_object)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreContext *context;
MAPIStoreFolder *folder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (backend_object)
{
wrapper = backend_object;
context = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
/**
\details Open a folder from the sogo backend
\param private_data pointer to the current sogo context
\param parent_fid the parent folder identifier
\param fid the identifier of the colder to open
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
*/
static enum mapistore_error
sogo_folder_open_folder(void *folder_object, TALLOC_CTX *mem_ctx, uint64_t fid, void **childfolder_object)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder, *childFolder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
/**
\details Create a folder in the sogo backend
\param private_data pointer to the current sogo context
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
*/
static enum mapistore_error
sogo_folder_create_folder(void *folder_object, TALLOC_CTX *mem_ctx,
uint64_t fid, struct SRow *aRow,
void **childfolder_object)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder, *childFolder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
/**
\details Delete a folder from the sogo backend
\param private_data pointer to the current sogo context
\param parent_fid the FID for the parent of the folder to delete
\param fid the FID for the folder to delete
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
*/
static enum mapistore_error
sogo_folder_delete(void *folder_object)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [folder deleteFolder];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_get_child_count(void *folder_object, enum mapistore_table_type table_type, uint32_t *child_count)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [folder getChildCount: child_count ofTableType: table_type];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_open_message(void *folder_object,
TALLOC_CTX *mem_ctx,
uint64_t mid, bool write_access,
void **message_object)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
MAPIStoreMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_create_message(void *folder_object,
TALLOC_CTX *mem_ctx,
uint64_t mid,
uint8_t associated,
void **message_object)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
MAPIStoreMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [folder deleteMessageWithMID: mid andFlags: flags];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_move_copy_messages(void *folder_object,
void *source_folder_object,
TALLOC_CTX *mem_ctx,
uint32_t mid_count,
uint64_t *src_mids, uint64_t *t_mids,
struct Binary_r **target_change_keys,
uint8_t want_copy)
{
MAPIStoreFolder *sourceFolder, *targetFolder;
NSAutoreleasePool *pool;
struct MAPIStoreTallocWrapper *wrapper;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
targetFolder = wrapper->instance;
wrapper = source_folder_object;
sourceFolder = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [targetFolder moveCopyMessagesWithMIDs: src_mids
andCount: mid_count
fromFolder: sourceFolder
withMIDs: t_mids
andChangeKeys: target_change_keys
wantCopy: want_copy
inMemCtx: mem_ctx];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_move_folder(void *folder_object, void *target_folder_object,
TALLOC_CTX *mem_ctx, const char *new_folder_name)
{
NSAutoreleasePool *pool;
MAPIStoreFolder *moveFolder, *targetFolder;
NSString *newFolderName;
struct MAPIStoreTallocWrapper *wrapper;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
moveFolder = wrapper->instance;
wrapper = target_folder_object;
if (wrapper)
targetFolder = wrapper->instance;
else
targetFolder = nil;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
if (new_folder_name)
newFolderName = [NSString stringWithUTF8String: new_folder_name];
else
newFolderName = nil;
TRYCATCH_START
rc = [moveFolder moveCopyToFolder: targetFolder
withNewName: newFolderName
isMove: YES
isRecursive: YES
inMemCtx: mem_ctx];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_copy_folder(void *folder_object, void *target_folder_object, TALLOC_CTX *mem_ctx,
bool recursive, const char *new_folder_name)
{
NSAutoreleasePool *pool;
MAPIStoreFolder *copyFolder, *targetFolder;
NSString *newFolderName;
struct MAPIStoreTallocWrapper *wrapper;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
copyFolder = wrapper->instance;
wrapper = target_folder_object;
targetFolder = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
enum mapistore_table_type table_type, uint64_t change_num,
struct UI8Array_r **fmidsp, uint64_t *cnp)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx,
enum mapistore_table_type table_type, uint32_t handle_id,
void **table_object, uint32_t *row_count)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_modify_permissions(void *folder_object, uint8_t flags,
uint16_t pcount,
struct PermissionData *permissions)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [folder modifyPermissions: permissions
withCount: pcount
andFlags: flags];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_preload_message_bodies(void *folder_object, enum mapistore_table_type table_type, const struct UI8Array_r *mids)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreFolder *folder;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
folder = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [folder preloadMessageBodiesWithMIDs: mids
ofTableType: table_type];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_get_message_data(void *message_object,
TALLOC_CTX *mem_ctx,
struct mapistore_message **msg_dataP)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
[message getMessageData: msg_dataP
inMemCtx: mem_ctx];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
rc = MAPISTORE_SUCCESS;
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_create_attachment (void *message_object, TALLOC_CTX *mem_ctx, void **attachment_object, uint32_t *aidp)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
MAPIStoreAttachment *attachment;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_open_attachment (void *message_object, TALLOC_CTX *mem_ctx,
uint32_t aid, void **attachment_object)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
MAPIStoreAttachment *attachment;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_get_attachment_table (void *message_object, TALLOC_CTX *mem_ctx, void **table_object, uint32_t *row_count)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
MAPIStoreAttachmentTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_modify_recipients (void *message_object,
struct SPropTagArray *columns,
uint16_t count,
struct mapistore_message_recipient *recipients)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [message modifyRecipientsWithRecipients: recipients
andCount: count
andColumns: columns];
// [context tearDownRequest];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_set_read_flag (void *message_object, uint8_t flag)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [message setReadFlag: flag];
// [context tearDownRequest];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_save (void *message_object, TALLOC_CTX *mem_ctx)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [message saveMessage: mem_ctx];
// [context tearDownRequest];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_submit (void *message_object, enum SubmitFlags flags)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreMailVolatileMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (message_object)
{
wrapper = message_object;
message = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [message submitWithFlags: flags];
// [context tearDownRequest];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_attachment_open_embedded_message (void *attachment_object,
TALLOC_CTX *mem_ctx,
void **message_object,
uint64_t *midP,
struct mapistore_message **msg)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreAttachment *attachment;
MAPIStoreEmbeddedMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (attachment_object)
{
wrapper = attachment_object;
attachment = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_message_attachment_create_embedded_message (void *attachment_object,
TALLOC_CTX *mem_ctx,
void **message_object,
struct mapistore_message **msg)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreAttachment *attachment;
MAPIStoreEmbeddedMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (attachment_object)
{
wrapper = attachment_object;
attachment = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error sogo_table_get_available_properties(void *table_object,
TALLOC_CTX *mem_ctx, struct SPropTagArray **propertiesP)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (table_object)
{
wrapper = table_object;
table = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_table_set_columns (void *table_object, uint16_t count, enum MAPITAGS *properties)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (table_object)
{
wrapper = table_object;
table = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [table setColumns: properties
withCount: count];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restrictions, uint8_t *table_status)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (table_object)
{
wrapper = table_object;
table = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_table_set_sort_order (void *table_object, struct SSortOrderSet *sort_order, uint8_t *table_status)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (table_object)
{
wrapper = table_object;
table = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_table_get_row (void *table_object, TALLOC_CTX *mem_ctx,
enum mapistore_query_type query_type, uint32_t row_id,
struct mapistore_property_data **data)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (table_object)
{
wrapper = table_object;
table = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_table_get_row_count (void *table_object,
enum mapistore_query_type query_type,
uint32_t *row_countp)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (table_object)
{
wrapper = table_object;
table = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [table getRowCount: row_countp
withQueryType: query_type];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_table_handle_destructor (void *table_object, uint32_t handle_id)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreTable *table;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (table_object)
{
wrapper = table_object;
table = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
[table destroyHandle: handle_id];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
rc = MAPISTORE_SUCCESS;
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error sogo_properties_get_available_properties(void *object,
TALLOC_CTX *mem_ctx,
struct SPropTagArray **propertiesP)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreObject *propObject;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (object)
{
wrapper = object;
propObject = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_properties_get_properties (void *object,
TALLOC_CTX *mem_ctx,
uint16_t count, enum MAPITAGS *properties,
struct mapistore_property_data *data)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreObject *propObject;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (object)
{
wrapper = object;
propObject = wrapper->instance;
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];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_properties_set_properties (void *object, struct SRow *aRow)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreObject *propObject;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (object)
{
wrapper = object;
propObject = wrapper->instance;
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
rc = [propObject addPropertiesFromRow: aRow];
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_manager_generate_uri (TALLOC_CTX *mem_ctx,
const char *user,
const char *folder,
const char *message,
const char *rootURI,
char **uri)
{
NSAutoreleasePool *pool;
NSString *partialURLString, *username, *directory;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (uri == NULL) return MAPISTORE_ERR_INVALID_PARAMETER;
/* This fixes a crash occurring during the instantiation of the
NSAutoreleasePool below. */
NS_CURRENT_THREAD_REGISTER();
pool = [NSAutoreleasePool new];
TRYCATCH_START
// printf("rootURI = %s\n", rootURI);
if (rootURI)
partialURLString = [NSString stringWithUTF8String: rootURI];
else
{
/* sogo uri are of type: sogo://[username]:[password]@[folder type]/folder/id */
username = [NSString stringWithUTF8String: (user ? user : "*")];
/* Do proper directory lookup here */
directory = [NSString stringWithUTF8String: (folder ? folder : "*")];
partialURLString = [NSString stringWithFormat: @"sogo://%@:*@%@", username, directory];
}
if (![partialURLString hasSuffix: @"/"])
partialURLString = [partialURLString stringByAppendingString: @"/"];
if (message)
partialURLString = [partialURLString stringByAppendingFormat: @"%s.eml", message];
// printf("uri = %s\n", [partialURLString UTF8String]);
*uri = talloc_strdup (mem_ctx, [partialURLString UTF8String]);
TRYCATCH_END(pool)
[pool release];
NS_CURRENT_THREAD_TRY_UNREGISTER();
return MAPISTORE_SUCCESS;
}
/**
\details Entry point for mapistore SOGO backend
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
*/
int mapistore_init_backend(void)
{
struct mapistore_backend backend;
int ret;
static BOOL registered = NO;
if (registered)
ret = MAPISTORE_SUCCESS;
else
{
registered = YES;
backend.backend.name = "SOGo";
backend.backend.description = "mapistore SOGo backend";
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;
backend.folder.open_folder = sogo_folder_open_folder;
backend.folder.create_folder = sogo_folder_create_folder;
backend.folder.delete = sogo_folder_delete;
backend.folder.open_message = sogo_folder_open_message;
backend.folder.create_message = sogo_folder_create_message;
backend.folder.delete_message = sogo_folder_delete_message;
backend.folder.move_copy_messages = sogo_folder_move_copy_messages;
backend.folder.move_folder = sogo_folder_move_folder;
backend.folder.copy_folder = sogo_folder_copy_folder;
backend.folder.get_deleted_fmids = sogo_folder_get_deleted_fmids;
backend.folder.get_child_count = sogo_folder_get_child_count;
backend.folder.open_table = sogo_folder_open_table;
backend.folder.modify_permissions = sogo_folder_modify_permissions;
backend.folder.preload_message_bodies = sogo_folder_preload_message_bodies;
backend.message.create_attachment = sogo_message_create_attachment;
backend.message.get_attachment_table = sogo_message_get_attachment_table;
backend.message.open_attachment = sogo_message_open_attachment;
backend.message.open_embedded_message = sogo_message_attachment_open_embedded_message;
backend.message.create_embedded_message = sogo_message_attachment_create_embedded_message;
backend.message.get_message_data = sogo_message_get_message_data;
backend.message.modify_recipients = sogo_message_modify_recipients;
backend.message.set_read_flag = sogo_message_set_read_flag;
backend.message.save = sogo_message_save;
backend.message.submit = sogo_message_submit;
backend.table.get_available_properties = sogo_table_get_available_properties;
backend.table.set_restrictions = sogo_table_set_restrictions;
backend.table.set_sort_order = sogo_table_set_sort_order;
backend.table.set_columns = sogo_table_set_columns;
backend.table.get_row = sogo_table_get_row;
backend.table.get_row_count = sogo_table_get_row_count;
backend.table.handle_destructor = sogo_table_handle_destructor;
backend.properties.get_available_properties = sogo_properties_get_available_properties;
backend.properties.get_properties = sogo_properties_get_properties;
backend.properties.set_properties = sogo_properties_set_properties;
backend.manager.generate_uri = sogo_manager_generate_uri;
/* Register ourselves with the MAPISTORE subsystem */
ret = mapistore_backend_register (&backend);
if (ret != MAPISTORE_SUCCESS)
DEBUG(0, ("Failed to register the '%s' mapistore backend!\n", backend.backend.name));
}
return ret;
}