a9f336c69d
This is a security issue that allowed a user to read the number of messages and its subjects when it does not have any permission to read. Now the user cannot see other's folder without asking for me to the owner.
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;
|
|
}
|