1752 lines
48 KiB
Objective-C
1752 lines
48 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 <libmapi/libmapi.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) { \
|
|
OC_DEBUG(5, "[SOGo] You should call sogo_backend_init() first. Current thread: %p, pid: %d\n", \
|
|
GSCurrentThread(), getpid()); \
|
|
} \
|
|
OC_DEBUG(5, "[SOGo] --->");
|
|
|
|
#define NS_CURRENT_THREAD_TRY_UNREGISTER(rc) \
|
|
if (__nsrct_thread_registered) { \
|
|
GSUnregisterCurrentThread(); \
|
|
} \
|
|
OC_DEBUG(6, "[SOGo] <--- [%s]", mapistore_errstr (rc));
|
|
|
|
#define TRYCATCH_START @try {
|
|
#define TRYCATCH_END(pool) \
|
|
} @catch (NSException * e) { \
|
|
enum mapistore_error ret = sogo_backend_handle_objc_exception(e, __PRETTY_FUNCTION__, __LINE__); \
|
|
mapiapp_cleanup(); \
|
|
[pool release]; \
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(ret); \
|
|
return ret; \
|
|
} \
|
|
mapiapp_cleanup();
|
|
|
|
|
|
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 };
|
|
NSString *debugLevel;
|
|
uint8_t parentLogLevel;
|
|
|
|
GSRegisterCurrentThread();
|
|
|
|
if (initialization_done) {
|
|
OC_DEBUG(5, "[SOGo] 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];
|
|
|
|
/* Ensure imap4Connection calls raise Exception if
|
|
IMAP connection is not established. See NGImap4Connection.m */
|
|
[ud setBool: YES forKey: @"SoIMAP4ExceptionsEnabled"];
|
|
|
|
if (!leakDebugging && [ud boolForKey: @"SOGoDebugLeaks"])
|
|
{
|
|
NSLog (@" leak debugging on");
|
|
GSDebugAllocationActive (YES);
|
|
atexit (sogo_backend_atexit);
|
|
leakDebugging = YES;
|
|
}
|
|
|
|
/* Set debug level according to samba */
|
|
parentLogLevel = DEBUGLEVEL_CLASS[DBGC_ALL]; // FIXME: samba logger specific code
|
|
if (parentLogLevel >= 4)
|
|
debugLevel = @"DEBUG";
|
|
else if (parentLogLevel >= 3)
|
|
debugLevel = @"INFO";
|
|
else if (parentLogLevel >= 2)
|
|
debugLevel = @"WARN";
|
|
else if (parentLogLevel >= 1)
|
|
debugLevel = @"ERROR";
|
|
else
|
|
debugLevel = @"FATAL";
|
|
OC_DEBUG(3, "[SOGo] Setting log level to %s", [debugLevel UTF8String]);
|
|
[ud setObject: debugLevel forKey: @"NGLogDefaultLogLevel"];
|
|
[ud synchronize];
|
|
|
|
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];
|
|
|
|
OC_DEBUG(5, "[SOGo] backend init SUCCESS. Current thread: %p, pid: %d\n", GSCurrentThread(), getpid());
|
|
initialization_done = YES;
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
\details Cleanup operation to execute after an action has been performed
|
|
so there won't be any conflicts with future calls.
|
|
In practice this will deactivate the current user context set on MAPIApp
|
|
(which is the current WOApplication), this means two things: (1) set nil
|
|
as current user context on MAPIApp and (2) remove woContext from current
|
|
thread dictionary (this is used on WOContext.m).
|
|
*/
|
|
static void mapiapp_cleanup(void)
|
|
{
|
|
Class MAPIApplicationK;
|
|
MAPIApplicationK = NSClassFromString (@"MAPIApplication");
|
|
if (MAPIApplicationK)
|
|
[[MAPIApplicationK application] cleanup];
|
|
}
|
|
|
|
/**
|
|
\details Create a connection context to the sogo backend
|
|
|
|
\param mem_ctx pointer to the memory context
|
|
\param conn_info pointer to the connection information available for this context
|
|
(database connection, connected user, replica server info)
|
|
\param indexing pointer to the indexing database connection
|
|
\param uri pointer to the sogo path
|
|
\param private_data pointer to the private backend context
|
|
|
|
\note the developer must free allocated private_data
|
|
*/
|
|
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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,
|
|
struct Binary_r **target_predecessor_change_lists,
|
|
uint8_t want_copy)
|
|
{
|
|
MAPIStoreFolder *sourceFolder, *targetFolder;
|
|
NSAutoreleasePool *pool;
|
|
struct MAPIStoreTallocWrapper *wrapper;
|
|
enum mapistore_error rc;
|
|
|
|
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
|
|
andPredecessorChangeLists: target_predecessor_change_lists
|
|
wantCopy: want_copy
|
|
inMemCtx: mem_ctx];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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];
|
|
rc = MAPISTORE_SUCCESS;
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
if (message_object)
|
|
{
|
|
wrapper = message_object;
|
|
message = wrapper->instance;
|
|
NS_CURRENT_THREAD_REGISTER();
|
|
pool = [NSAutoreleasePool new];
|
|
|
|
TRYCATCH_START
|
|
rc = [message setReadFlag: flag];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
if (message_object)
|
|
{
|
|
wrapper = message_object;
|
|
message = wrapper->instance;
|
|
NS_CURRENT_THREAD_REGISTER();
|
|
pool = [NSAutoreleasePool new];
|
|
|
|
TRYCATCH_START
|
|
rc = [message saveMessage: mem_ctx];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
if (message_object)
|
|
{
|
|
wrapper = message_object;
|
|
message = wrapper->instance;
|
|
NS_CURRENT_THREAD_REGISTER();
|
|
pool = [NSAutoreleasePool new];
|
|
|
|
TRYCATCH_START
|
|
rc = [message submitWithFlags: flags];
|
|
TRYCATCH_END(pool)
|
|
|
|
[pool release];
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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];
|
|
rc = MAPISTORE_SUCCESS;
|
|
NS_CURRENT_THREAD_TRY_UNREGISTER(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
enum mapistore_error rc;
|
|
|
|
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(rc);
|
|
}
|
|
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;
|
|
|
|
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 stringByReplacingOccurrencesOfString: @"@"
|
|
withString: @"%40"],
|
|
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(MAPISTORE_SUCCESS);
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
\details Entry point for mapistore SOGO backend
|
|
|
|
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
|
|
*/
|
|
enum mapistore_error mapistore_init_backend(void)
|
|
{
|
|
struct mapistore_backend backend;
|
|
enum mapistore_error 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)
|
|
OC_DEBUG(0, "[SOGo] Failed to register the '%s' mapistore backend!\n", backend.backend.name);
|
|
}
|
|
|
|
return ret;
|
|
}
|