2010-10-01 22:35:29 +02:00
|
|
|
/* MAPIStoreContext.m - this file is part of SOGo
|
2010-10-01 20:54:30 +02:00
|
|
|
*
|
2012-08-17 21:04:57 +02:00
|
|
|
* Copyright (C) 2010-2012 Inverse inc.
|
2010-10-01 20:54:30 +02:00
|
|
|
*
|
|
|
|
* 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
|
2010-10-18 14:57:31 +02:00
|
|
|
* the Free Software Foundation; either version 3, or (at your option)
|
2010-10-01 20:54:30 +02:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2016-02-17 16:09:18 +01:00
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
#import <Foundation/NSException.h>
|
|
|
|
#import <Foundation/NSNull.h>
|
|
|
|
#import <Foundation/NSURL.h>
|
2010-12-03 23:31:56 +01:00
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
2012-10-12 23:42:43 +02:00
|
|
|
#import <NGExtensions/NSObject+Values.h>
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2016-02-17 16:09:18 +01:00
|
|
|
#import <SOGo/SOGoFolder.h>
|
|
|
|
#import <SOGo/SOGoUser.h>
|
2011-03-08 14:35:44 +01:00
|
|
|
|
2016-02-17 16:09:18 +01:00
|
|
|
#import "MAPIStoreAttachment.h"
|
|
|
|
#import "MAPIStoreFallbackContext.h"
|
|
|
|
#import "MAPIStoreFolder.h"
|
|
|
|
#import "MAPIStoreFolderTable.h"
|
|
|
|
#import "MAPIStoreMapping.h"
|
|
|
|
#import "MAPIStoreMessage.h"
|
|
|
|
#import "MAPIStoreMessageTable.h"
|
|
|
|
#import "MAPIStoreFAIMessage.h"
|
|
|
|
#import "MAPIStoreFAIMessageTable.h"
|
|
|
|
#import "MAPIStoreTypes.h"
|
|
|
|
#import "MAPIStoreUserContext.h"
|
2010-12-30 15:18:42 +01:00
|
|
|
#import "NSArray+MAPIStore.h"
|
2011-02-15 00:43:05 +01:00
|
|
|
#import "NSObject+MAPIStore.h"
|
2010-12-30 15:18:42 +01:00
|
|
|
#import "NSString+MAPIStore.h"
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2016-02-17 16:09:18 +01:00
|
|
|
#import "MAPIStoreContext.h"
|
2010-10-01 20:54:30 +02:00
|
|
|
|
|
|
|
#undef DEBUG
|
2016-02-17 16:09:18 +01:00
|
|
|
#include <dlinklist.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <gen_ndr/exchange.h>
|
|
|
|
#include <util/attr.h>
|
|
|
|
#include <libmapiproxy.h>
|
|
|
|
#include <mapistore/mapistore.h>
|
|
|
|
#include <mapistore/mapistore_errors.h>
|
|
|
|
#include <mapistore/mapistore_nameid.h>
|
|
|
|
#include <talloc.h>
|
2010-11-06 00:27:08 +01:00
|
|
|
|
2010-11-30 22:04:05 +01:00
|
|
|
/* TODO: homogenize method names and order of parameters */
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
@implementation MAPIStoreContext : NSObject
|
|
|
|
|
|
|
|
/* sogo://username:password@{contacts,calendar,tasks,journal,notes,mail}/dossier/id */
|
|
|
|
|
2012-03-09 03:07:31 +01:00
|
|
|
static Class NSExceptionK, MAPIStoreFallbackContextK, SOGoObjectK;
|
2010-11-19 22:14:53 +01:00
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
static NSMutableDictionary *contextClassMapping;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
2010-11-22 22:32:11 +01:00
|
|
|
NSArray *classes;
|
|
|
|
Class currentClass;
|
|
|
|
NSUInteger count, max;
|
|
|
|
NSString *moduleName;
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
NSExceptionK = [NSException class];
|
2012-03-09 03:07:31 +01:00
|
|
|
SOGoObjectK = [SOGoObject class];
|
2010-12-13 18:03:25 +01:00
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
contextClassMapping = [NSMutableDictionary new];
|
|
|
|
classes = GSObjCAllSubclassesOfClass (self);
|
|
|
|
max = [classes count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentClass = [classes objectAtIndex: count];
|
|
|
|
moduleName = [currentClass MAPIModuleName];
|
2010-12-13 18:03:25 +01:00
|
|
|
if (moduleName)
|
2015-08-03 15:16:55 +02:00
|
|
|
{
|
|
|
|
[contextClassMapping setObject: currentClass
|
2012-02-03 16:05:55 +01:00
|
|
|
forKey: moduleName];
|
2015-08-03 15:16:55 +02:00
|
|
|
NSLog (@" registered class '%@' as handler of '%@' contexts",
|
|
|
|
NSStringFromClass (currentClass), moduleName);
|
|
|
|
}
|
2010-11-22 22:32:11 +01:00
|
|
|
}
|
2012-02-03 16:05:55 +01:00
|
|
|
|
|
|
|
MAPIStoreFallbackContextK = [MAPIStoreFallbackContext class];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2012-01-26 20:54:36 +01:00
|
|
|
+ (struct mapistore_contexts_list *) listAllContextsForUser: (NSString *) userName
|
2015-08-03 15:16:55 +02:00
|
|
|
withIndexing: (struct indexing_context *) indexing
|
2012-01-26 20:54:36 +01:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
{
|
|
|
|
struct mapistore_contexts_list *list, *current;
|
|
|
|
NSArray *classes;
|
|
|
|
Class currentClass;
|
|
|
|
NSUInteger count, max;
|
|
|
|
|
2012-01-30 21:12:18 +01:00
|
|
|
list = NULL;
|
|
|
|
|
2015-08-03 15:16:55 +02:00
|
|
|
// User context is activated on initialization
|
|
|
|
[MAPIStoreUserContext userContextWithUsername: userName
|
|
|
|
andTDBIndexing: indexing];
|
2012-01-26 20:54:36 +01:00
|
|
|
|
|
|
|
classes = GSObjCAllSubclassesOfClass (self);
|
|
|
|
max = [classes count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentClass = [classes objectAtIndex: count];
|
|
|
|
current = [currentClass listContextsForUser: userName
|
2015-08-03 15:16:55 +02:00
|
|
|
withIndexing: indexing
|
2012-01-26 20:54:36 +01:00
|
|
|
inMemCtx: memCtx];
|
|
|
|
if (current)
|
2012-01-30 21:12:18 +01:00
|
|
|
DLIST_CONCATENATE(list, current, void);
|
2012-01-26 20:54:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2012-02-03 16:05:55 +01:00
|
|
|
+ (struct mapistore_contexts_list *) listContextsForUser: (NSString *) userName
|
2015-08-03 15:16:55 +02:00
|
|
|
withIndexing: (struct indexing_context *) indexing
|
2012-01-26 20:54:36 +01:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-03 16:05:55 +01:00
|
|
|
static Class
|
|
|
|
MAPIStoreLookupContextClassByRole (Class self, enum mapistore_context_role role)
|
|
|
|
{
|
|
|
|
static NSMutableDictionary *classMapping = nil;
|
|
|
|
Class currentClass;
|
|
|
|
enum mapistore_context_role classRole;
|
|
|
|
NSNumber *roleNbr;
|
|
|
|
NSArray *classes;
|
|
|
|
NSUInteger count, max;
|
|
|
|
|
|
|
|
if (!classMapping)
|
|
|
|
{
|
|
|
|
classMapping = [NSMutableDictionary new];
|
|
|
|
classes = GSObjCAllSubclassesOfClass (self);
|
|
|
|
max = [classes count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentClass = [classes objectAtIndex: count];
|
|
|
|
classRole = [currentClass MAPIContextRole];
|
|
|
|
if (classRole != -1)
|
|
|
|
{
|
|
|
|
roleNbr = [NSNumber numberWithUnsignedInt: classRole];
|
|
|
|
[classMapping setObject: currentClass
|
|
|
|
forKey: roleNbr];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
roleNbr = [NSNumber numberWithUnsignedInt: role];
|
|
|
|
|
|
|
|
return [classMapping objectForKey: roleNbr];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (enum mapistore_error) createRootFolder: (NSString **) mapistoreUriP
|
|
|
|
withFID: (uint64_t) fid
|
|
|
|
andName: (NSString *) folderName
|
|
|
|
forUser: (NSString *) userName
|
|
|
|
withRole: (enum mapistore_context_role) role
|
|
|
|
{
|
|
|
|
Class contextClass;
|
|
|
|
NSString *mapistoreURI;
|
|
|
|
enum mapistore_error rc = MAPISTORE_SUCCESS;
|
|
|
|
|
|
|
|
contextClass = MAPIStoreLookupContextClassByRole (self, role);
|
|
|
|
if (!contextClass)
|
|
|
|
contextClass = MAPIStoreFallbackContextK;
|
|
|
|
|
|
|
|
mapistoreURI = [contextClass createRootSecondaryFolderWithFID: fid
|
2012-02-23 22:14:02 +01:00
|
|
|
andName: folderName
|
2012-02-14 15:47:06 +01:00
|
|
|
forUser: userName];
|
2012-02-23 22:14:02 +01:00
|
|
|
if (!mapistoreURI && contextClass != MAPIStoreFallbackContextK)
|
|
|
|
mapistoreURI = [MAPIStoreFallbackContextK createRootSecondaryFolderWithFID: fid
|
|
|
|
andName: folderName
|
|
|
|
forUser: userName];
|
2012-02-03 16:05:55 +01:00
|
|
|
if (mapistoreURI)
|
|
|
|
*mapistoreUriP = mapistoreURI;
|
|
|
|
else
|
2012-02-23 22:14:02 +01:00
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2012-02-03 16:05:55 +01:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
2010-11-22 17:03:30 +01:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
NSString *urlString;
|
|
|
|
NSURL *completeURL;
|
2010-11-22 17:03:30 +01:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
urlString = [NSString stringWithFormat: @"sogo://%@",
|
|
|
|
[NSString stringWithUTF8String: uri]];
|
|
|
|
if (![urlString hasSuffix: @"/"])
|
|
|
|
urlString = [urlString stringByAppendingString: @"/"];
|
2012-09-07 18:46:18 +02:00
|
|
|
completeURL = [NSURL URLWithString: urlString];
|
2010-11-22 17:03:30 +01:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
return completeURL;
|
2010-11-22 17:03:30 +01:00
|
|
|
}
|
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
+ (int) openContext: (MAPIStoreContext **) contextPtr
|
|
|
|
withURI: (const char *) newUri
|
2011-08-04 16:09:59 +02:00
|
|
|
connectionInfo: (struct mapistore_connection_info *) newConnInfo
|
2013-11-08 17:02:50 +01:00
|
|
|
andTDBIndexing: (struct indexing_context *) indexing
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
MAPIStoreContext *context;
|
2010-11-22 22:32:11 +01:00
|
|
|
Class contextClass;
|
2012-01-29 20:55:21 +01:00
|
|
|
NSString *module;
|
2010-10-01 22:35:29 +02:00
|
|
|
NSURL *baseURL;
|
2011-07-14 23:35:54 +02:00
|
|
|
int rc = MAPISTORE_ERR_NOT_FOUND;
|
2010-10-01 22:35:29 +02:00
|
|
|
|
|
|
|
context = nil;
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
baseURL = CompleteURLFromMapistoreURI (newUri);
|
|
|
|
if (baseURL)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
module = [baseURL host];
|
|
|
|
if (module)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
contextClass = [contextClassMapping objectForKey: module];
|
|
|
|
if (contextClass)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
context = [[contextClass alloc] initFromURL: baseURL
|
|
|
|
withConnectionInfo: newConnInfo
|
2013-11-08 17:02:50 +01:00
|
|
|
andTDBIndexing: indexing];
|
2012-01-29 20:55:21 +01:00
|
|
|
if (context)
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
[context autorelease];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
*contextPtr = context;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2012-01-29 20:55:21 +01:00
|
|
|
else
|
|
|
|
NSLog (@"ERROR: unrecognized module name '%@'", module);
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
|
|
|
else
|
2012-01-29 20:55:21 +01:00
|
|
|
NSLog (@"ERROR: url could not be parsed");
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
if ((self = [super init]))
|
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
activeUser = nil;
|
|
|
|
userContext = nil;
|
2011-03-07 22:33:13 +01:00
|
|
|
contextUrl = nil;
|
2012-02-23 22:10:18 +01:00
|
|
|
containersBag = [NSMutableArray new];
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
return self;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2011-05-31 07:01:43 +02:00
|
|
|
- (id) initFromURL: (NSURL *) newUrl
|
|
|
|
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
2013-11-08 17:02:50 +01:00
|
|
|
andTDBIndexing: (struct indexing_context *) indexing
|
2011-03-07 22:33:13 +01:00
|
|
|
{
|
2011-08-10 20:33:13 +02:00
|
|
|
NSString *username;
|
|
|
|
|
2014-08-19 22:24:34 +02:00
|
|
|
if (newConnInfo == NULL)
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2011-03-07 22:33:13 +01:00
|
|
|
if ((self = [self init]))
|
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
ASSIGN (contextUrl, newUrl);
|
|
|
|
|
2011-11-29 02:39:07 +01:00
|
|
|
username = [newUrl user];
|
|
|
|
if ([username length] == 0)
|
|
|
|
{
|
|
|
|
[self errorWithFormat:
|
|
|
|
@"attempt to instantiate a context with an empty owner"];
|
|
|
|
[self release];
|
|
|
|
return nil;
|
|
|
|
}
|
2012-01-29 20:55:21 +01:00
|
|
|
|
|
|
|
ASSIGN (userContext,
|
|
|
|
[MAPIStoreUserContext userContextWithUsername: username
|
2013-11-08 17:02:50 +01:00
|
|
|
andTDBIndexing: indexing]);
|
2012-01-29 20:55:21 +01:00
|
|
|
connInfo = newConnInfo;
|
|
|
|
username = [NSString stringWithUTF8String: newConnInfo->username];
|
|
|
|
ASSIGN (activeUser, [SOGoUser userWithLogin: username]);
|
|
|
|
if (!activeUser)
|
2011-11-29 02:39:07 +01:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
[self errorWithFormat: @"user '%@' not found in SOGo environment",
|
|
|
|
username];
|
2011-11-29 02:39:07 +01:00
|
|
|
[self release];
|
|
|
|
return nil;
|
|
|
|
}
|
2011-03-07 22:33:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (void) dealloc
|
|
|
|
{
|
2011-03-07 22:33:13 +01:00
|
|
|
[contextUrl release];
|
2012-01-29 20:55:21 +01:00
|
|
|
[userContext release];
|
2012-02-23 22:10:18 +01:00
|
|
|
[containersBag release];
|
2010-10-13 23:40:50 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
[super dealloc];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
- (MAPIStoreUserContext *) userContext
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
return userContext;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2011-04-13 21:55:17 +02:00
|
|
|
- (NSURL *) url
|
|
|
|
{
|
|
|
|
return contextUrl;
|
|
|
|
}
|
|
|
|
|
2011-05-31 07:01:43 +02:00
|
|
|
- (struct mapistore_connection_info *) connectionInfo
|
|
|
|
{
|
|
|
|
return connInfo;
|
|
|
|
}
|
|
|
|
|
2011-08-08 20:54:02 +02:00
|
|
|
- (SOGoUser *) activeUser
|
|
|
|
{
|
|
|
|
return activeUser;
|
|
|
|
}
|
|
|
|
|
2010-10-13 23:40:50 +02:00
|
|
|
- (int) getPath: (char **) path
|
|
|
|
ofFMID: (uint64_t) fmid
|
2011-07-11 23:40:47 +02:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2010-10-13 23:40:50 +02:00
|
|
|
{
|
|
|
|
int rc;
|
2011-03-07 22:33:13 +01:00
|
|
|
NSString *objectURL, *url;
|
2010-10-13 23:40:50 +02:00
|
|
|
|
2014-06-20 17:12:26 +02:00
|
|
|
url = [contextUrl absoluteString];
|
|
|
|
// FIXME transform percent escapes but not for user part of the url
|
2015-08-03 15:16:55 +02:00
|
|
|
//[xxxx stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
|
2012-01-29 20:55:21 +01:00
|
|
|
objectURL = [[userContext mapping] urlFromID: fmid];
|
2010-10-13 23:40:50 +02:00
|
|
|
if (objectURL)
|
|
|
|
{
|
2011-03-07 22:33:13 +01:00
|
|
|
if ([objectURL hasPrefix: url])
|
2010-10-15 19:24:09 +02:00
|
|
|
{
|
2014-02-27 17:47:28 +01:00
|
|
|
*path = [[objectURL substringFromIndex: 7] asUnicodeInMemCtx: memCtx];
|
2014-03-19 17:19:07 +01:00
|
|
|
[self logWithFormat: @"found path '%s' for fmid 0x%.16"PRIx64"", *path, fmid];
|
2011-07-15 21:29:30 +02:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
2010-10-15 19:24:09 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-03-19 17:19:07 +01:00
|
|
|
[self logWithFormat: @"context (%@, %@) does not contain "
|
|
|
|
@"found fmid: 0x%.16"PRIx64"", objectURL, url, fmid];
|
2010-10-15 19:24:09 +02:00
|
|
|
*path = NULL;
|
2011-07-15 21:29:30 +02:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
2010-10-15 19:24:09 +02:00
|
|
|
}
|
2010-10-13 23:40:50 +02:00
|
|
|
}
|
|
|
|
else
|
2010-10-15 19:24:09 +02:00
|
|
|
{
|
|
|
|
[self errorWithFormat: @"%s: you should *never* get here", __PRETTY_FUNCTION__];
|
|
|
|
*path = NULL;
|
2011-07-15 21:29:30 +02:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
2010-10-15 19:24:09 +02:00
|
|
|
}
|
|
|
|
|
2010-10-13 23:40:50 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
- (void) ensureContextFolder
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
- (int) getRootFolder: (MAPIStoreFolder **) folderPtr
|
|
|
|
withFID: (uint64_t) newFid
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
enum mapistore_error rc;
|
|
|
|
MAPIStoreFolder *baseFolder;
|
|
|
|
SOGoFolder *currentFolder;
|
|
|
|
WOContext *woContext;
|
2012-09-07 18:46:18 +02:00
|
|
|
NSString *path;
|
2012-01-29 20:55:21 +01:00
|
|
|
NSArray *pathComponents;
|
|
|
|
NSUInteger count, max;
|
|
|
|
|
2015-08-03 15:16:55 +02:00
|
|
|
[userContext activate];
|
2012-01-29 20:55:21 +01:00
|
|
|
woContext = [userContext woContext];
|
|
|
|
|
|
|
|
[self ensureContextFolder];
|
|
|
|
currentFolder = [self rootSOGoFolder];
|
2012-06-29 19:59:38 +02:00
|
|
|
[containersBag addObject: currentFolder];
|
2012-09-07 18:46:18 +02:00
|
|
|
|
|
|
|
/* HACK:
|
|
|
|
-[NSURL path] returns unescaped strings in theory. In pratice, sometimes
|
|
|
|
it does, sometimes not. Therefore we use the result of our own
|
|
|
|
implementation of -[NSString
|
|
|
|
stringByReplacingPercentEscapeUsingEncoding:], which returns nil if the
|
|
|
|
original string contains non-ascii chars, from which we can determine
|
|
|
|
whether the path was unescaped or not. */
|
|
|
|
path = [[contextUrl path]
|
|
|
|
stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
|
|
|
|
if (!path)
|
|
|
|
path = [contextUrl path];
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
if ([path hasPrefix: @"/"])
|
|
|
|
path = [path substringFromIndex: 1];
|
|
|
|
if ([path hasSuffix: @"/"])
|
|
|
|
path = [path substringToIndex: [path length] - 1];
|
2012-06-29 19:59:38 +02:00
|
|
|
if ([path length] > 0)
|
2012-01-29 20:55:21 +01:00
|
|
|
{
|
2012-06-29 19:59:38 +02:00
|
|
|
pathComponents = [path componentsSeparatedByString: @"/"];
|
|
|
|
max = [pathComponents count];
|
|
|
|
for (count = 0; currentFolder && count < max; count++)
|
|
|
|
{
|
|
|
|
[woContext setClientObject: currentFolder];
|
|
|
|
currentFolder = [currentFolder
|
|
|
|
lookupName: [pathComponents objectAtIndex: count]
|
|
|
|
inContext: woContext
|
2012-01-29 20:55:21 +01:00
|
|
|
acquire: NO];
|
2012-06-29 19:59:38 +02:00
|
|
|
if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all
|
|
|
|
SOGo folder types */
|
|
|
|
[containersBag addObject: currentFolder];
|
|
|
|
else
|
|
|
|
currentFolder = nil;
|
|
|
|
}
|
2012-01-29 20:55:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (currentFolder)
|
|
|
|
{
|
|
|
|
baseFolder = [[self MAPIStoreFolderClass]
|
|
|
|
mapiStoreObjectWithSOGoObject: currentFolder
|
|
|
|
inContainer: nil];
|
|
|
|
[baseFolder setContext: self];
|
|
|
|
*folderPtr = baseFolder;
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
2012-03-09 03:07:31 +01:00
|
|
|
else if ([[userContext sogoUser] isEqual: activeUser])
|
2012-01-29 20:55:21 +01:00
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2012-03-09 03:07:31 +01:00
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
2012-01-29 20:55:21 +01:00
|
|
|
|
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-11-30 22:04:05 +01:00
|
|
|
/* utils */
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (NSString *) extractChildNameFromURL: (NSString *) objectURL
|
2015-08-03 15:16:55 +02:00
|
|
|
andFolderURLAt: (NSString **) folderURL;
|
2010-12-30 15:18:42 +01:00
|
|
|
{
|
|
|
|
NSString *childKey;
|
|
|
|
NSRange lastSlash;
|
|
|
|
NSUInteger slashPtr;
|
|
|
|
|
|
|
|
if ([objectURL hasSuffix: @"/"])
|
|
|
|
objectURL = [objectURL substringToIndex: [objectURL length] - 2];
|
|
|
|
lastSlash = [objectURL rangeOfString: @"/"
|
2015-08-03 15:16:55 +02:00
|
|
|
options: NSBackwardsSearch];
|
2010-12-30 15:18:42 +01:00
|
|
|
if (lastSlash.location != NSNotFound)
|
|
|
|
{
|
|
|
|
slashPtr = NSMaxRange (lastSlash);
|
|
|
|
childKey = [objectURL substringFromIndex: slashPtr];
|
|
|
|
if ([childKey length] == 0)
|
2015-08-03 15:16:55 +02:00
|
|
|
childKey = nil;
|
2010-12-30 15:18:42 +01:00
|
|
|
if (folderURL)
|
2015-08-03 15:16:55 +02:00
|
|
|
*folderURL = [objectURL substringToIndex: slashPtr];
|
2010-12-30 15:18:42 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
childKey = nil;
|
|
|
|
|
|
|
|
return childKey;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (uint64_t) idForObjectWithKey: (NSString *) key
|
|
|
|
inFolderURL: (NSString *) folderURL
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
NSString *childURL;
|
2012-01-29 20:55:21 +01:00
|
|
|
MAPIStoreMapping *mapping;
|
2011-02-24 21:32:27 +01:00
|
|
|
uint64_t mappingId;
|
2015-08-03 15:16:55 +02:00
|
|
|
enum mapistore_error ret;
|
2011-02-24 21:32:27 +01:00
|
|
|
|
|
|
|
if (key)
|
2012-09-07 18:46:18 +02:00
|
|
|
childURL = [NSString stringWithFormat: @"%@%@", folderURL,
|
|
|
|
[key stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
|
2011-02-24 21:32:27 +01:00
|
|
|
else
|
|
|
|
childURL = folderURL;
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [userContext mapping];
|
2011-02-24 21:32:27 +01:00
|
|
|
mappingId = [mapping idFromURL: childURL];
|
|
|
|
if (mappingId == NSNotFound)
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
[self logWithFormat: @"No id exist yet for '%@', requesting one", childURL];
|
|
|
|
ret = mapistore_indexing_get_new_folderID (connInfo->mstore_ctx, &mappingId);
|
|
|
|
if (ret == MAPISTORE_SUCCESS)
|
|
|
|
[mapping registerURL: childURL withID: mappingId];
|
|
|
|
else
|
|
|
|
[self errorWithFormat: @"Error trying to get new folder id (%d): %s",
|
|
|
|
ret, mapistore_errstr (ret)];
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return mappingId;
|
|
|
|
}
|
|
|
|
|
2011-07-27 23:55:49 +02:00
|
|
|
- (uint64_t) getNewChangeNumber
|
|
|
|
{
|
|
|
|
uint64_t newVersionNumber;
|
|
|
|
|
2014-06-27 15:40:21 +02:00
|
|
|
if (openchangedb_get_new_changeNumber (connInfo->oc_ctx, connInfo->username, &newVersionNumber)
|
2011-11-29 02:39:07 +01:00
|
|
|
!= MAPI_E_SUCCESS)
|
2011-07-27 23:55:49 +02:00
|
|
|
abort ();
|
|
|
|
|
|
|
|
return newVersionNumber;
|
|
|
|
}
|
|
|
|
|
2012-10-12 23:42:43 +02:00
|
|
|
- (NSArray *) getNewChangeNumbers: (uint64_t) max
|
|
|
|
{
|
|
|
|
TALLOC_CTX *memCtx;
|
|
|
|
NSMutableArray *newChangeNumbers;
|
|
|
|
uint64_t count;
|
|
|
|
struct UI8Array_r *numbers;
|
|
|
|
NSString *newNumber;
|
|
|
|
|
|
|
|
memCtx = talloc_zero(NULL, TALLOC_CTX);
|
|
|
|
newChangeNumbers = [NSMutableArray arrayWithCapacity: max];
|
2014-06-27 15:40:21 +02:00
|
|
|
|
2012-10-12 23:42:43 +02:00
|
|
|
if (openchangedb_get_new_changeNumbers (connInfo->oc_ctx,
|
2014-06-27 15:40:21 +02:00
|
|
|
memCtx, connInfo->username, max, &numbers)
|
2012-10-12 23:42:43 +02:00
|
|
|
!= MAPI_E_SUCCESS || numbers->cValues != max)
|
|
|
|
abort ();
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
newNumber
|
|
|
|
= [NSString stringWithUnsignedLongLong: numbers->lpui8[count]];
|
|
|
|
[newChangeNumbers addObject: newNumber];
|
|
|
|
}
|
|
|
|
|
|
|
|
talloc_free (memCtx);
|
|
|
|
|
|
|
|
return newChangeNumbers;
|
|
|
|
}
|
|
|
|
|
2012-10-13 05:25:51 +02:00
|
|
|
- (NSArray *) getNewFMIDs: (uint64_t) max
|
|
|
|
{
|
|
|
|
TALLOC_CTX *memCtx;
|
|
|
|
NSMutableArray *newFMIDs;
|
|
|
|
uint64_t count;
|
|
|
|
struct UI8Array_r *numbers;
|
|
|
|
NSString *newNumber;
|
|
|
|
|
|
|
|
memCtx = talloc_zero(NULL, TALLOC_CTX);
|
|
|
|
newFMIDs = [NSMutableArray arrayWithCapacity: max];
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2013-11-19 15:24:31 +01:00
|
|
|
if (mapistore_indexing_get_new_folderIDs (connInfo->mstore_ctx,
|
|
|
|
memCtx, max, &numbers)
|
2013-12-20 11:26:09 +01:00
|
|
|
!= MAPISTORE_SUCCESS || numbers->cValues != max)
|
2012-10-13 05:25:51 +02:00
|
|
|
abort ();
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
newNumber = [NSString stringWithUnsignedLongLong: numbers->lpui8[count]];
|
2012-10-13 05:25:51 +02:00
|
|
|
[newFMIDs addObject: newNumber];
|
|
|
|
}
|
|
|
|
|
|
|
|
talloc_free (memCtx);
|
|
|
|
|
|
|
|
return newFMIDs;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
/* subclasses */
|
|
|
|
|
|
|
|
+ (NSString *) MAPIModuleName
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2012-02-03 16:05:55 +01:00
|
|
|
+ (enum mapistore_context_role) MAPIContextRole
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSString *)
|
|
|
|
createRootSecondaryFolderWithFID: (uint64_t) fid
|
|
|
|
andName: (NSString *) folderName
|
|
|
|
forUser: (NSString *) userName
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
- (Class) MAPIStoreFolderClass
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) rootSOGoFolder
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
2012-01-29 20:55:21 +01:00
|
|
|
|
|
|
|
return nil;
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
@end
|