2011-02-24 21:32:27 +01:00
|
|
|
/* MAPIStoreFolder.m - this file is part of SOGo
|
|
|
|
*
|
2014-05-14 03:06:59 +02:00
|
|
|
* Copyright (C) 2011-2014 Inverse inc
|
2011-02-24 21:32:27 +01:00
|
|
|
*
|
|
|
|
* 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
|
2011-08-12 17:02:01 +02:00
|
|
|
* the Free Software Foundation; either version 3, or (at your option)
|
2011-02-24 21:32:27 +01: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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* TODO: main key arrays must be initialized */
|
|
|
|
|
|
|
|
#import <Foundation/NSArray.h>
|
2012-08-15 03:02:08 +02:00
|
|
|
#import <Foundation/NSAutoreleasePool.h>
|
2011-10-14 21:42:16 +02:00
|
|
|
#import <Foundation/NSCalendarDate.h>
|
2012-08-21 22:39:36 +02:00
|
|
|
#import <Foundation/NSData.h>
|
2011-06-07 02:17:46 +02:00
|
|
|
#import <Foundation/NSDictionary.h>
|
2011-02-24 21:32:27 +01:00
|
|
|
#import <Foundation/NSException.h>
|
|
|
|
#import <Foundation/NSString.h>
|
|
|
|
#import <Foundation/NSURL.h>
|
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
2014-12-16 23:39:42 +01:00
|
|
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
2011-10-04 01:35:49 +02:00
|
|
|
#import <SOGo/SOGoContentObject.h>
|
2012-06-01 17:15:30 +02:00
|
|
|
#import <SOGo/SOGoUser.h>
|
2011-02-24 21:32:27 +01:00
|
|
|
#import <SOGo/SOGoFolder.h>
|
|
|
|
|
2011-05-31 05:39:36 +02:00
|
|
|
#import "MAPIStoreActiveTables.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "MAPIStoreContext.h"
|
2011-03-07 20:15:16 +01:00
|
|
|
#import "MAPIStoreFAIMessage.h"
|
|
|
|
#import "MAPIStoreFAIMessageTable.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "MAPIStoreFolder.h"
|
2011-07-14 23:35:54 +02:00
|
|
|
#import "MAPIStoreFolderTable.h"
|
|
|
|
#import "MAPIStoreMapping.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "MAPIStoreMessage.h"
|
2011-08-02 22:44:15 +02:00
|
|
|
#import "MAPIStorePermissionsTable.h"
|
2011-11-18 16:26:03 +01:00
|
|
|
#import "MAPIStoreSamDBUtils.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "MAPIStoreTypes.h"
|
2012-01-29 20:55:21 +01:00
|
|
|
#import "MAPIStoreUserContext.h"
|
2012-08-21 22:39:36 +02:00
|
|
|
#import "NSData+MAPIStore.h"
|
2011-06-07 02:17:46 +02:00
|
|
|
#import "NSDate+MAPIStore.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "NSString+MAPIStore.h"
|
2011-06-07 02:17:46 +02:00
|
|
|
#import "NSObject+MAPIStore.h"
|
2014-05-14 03:06:59 +02:00
|
|
|
#import <SOGo/SOGoCacheGCSFolder.h>
|
2012-06-29 19:59:38 +02:00
|
|
|
#import "SOGoMAPIDBMessage.h"
|
2014-05-14 03:14:57 +02:00
|
|
|
#import "SOGoCacheGCSObject+MAPIStore.h"
|
2014-11-12 16:21:44 +01:00
|
|
|
#import <Mailer/SOGoMailObject.h>
|
2011-02-24 21:32:27 +01:00
|
|
|
|
|
|
|
#include <gen_ndr/exchange.h>
|
|
|
|
|
|
|
|
#undef DEBUG
|
2011-11-09 16:02:29 +01:00
|
|
|
#include <util/attr.h>
|
2011-08-11 18:37:23 +02:00
|
|
|
#include <libmapiproxy.h>
|
2011-02-24 21:32:27 +01:00
|
|
|
#include <mapistore/mapistore.h>
|
2011-06-07 02:17:46 +02:00
|
|
|
#include <mapistore/mapistore_errors.h>
|
2011-02-24 21:32:27 +01:00
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMessageTableK, MAPIStoreFolderTableK;
|
2011-02-24 21:32:27 +01:00
|
|
|
|
|
|
|
@implementation MAPIStoreFolder
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
NSExceptionK = [NSException class];
|
2011-07-15 16:15:03 +02:00
|
|
|
MAPIStoreFAIMessageK = [MAPIStoreFAIMessage class];
|
2011-03-07 20:15:16 +01:00
|
|
|
MAPIStoreMessageTableK = [MAPIStoreMessageTable class];
|
|
|
|
MAPIStoreFAIMessageTableK = [MAPIStoreFAIMessageTable class];
|
|
|
|
MAPIStoreFolderTableK = [MAPIStoreFolderTable class];
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
if ((self = [super init]))
|
|
|
|
{
|
2012-03-09 03:08:57 +01:00
|
|
|
// messageKeys = nil;
|
|
|
|
// faiMessageKeys = nil;
|
|
|
|
// folderKeys = nil;
|
2012-06-29 19:59:38 +02:00
|
|
|
dbFolder = nil;
|
2011-02-24 21:32:27 +01:00
|
|
|
context = nil;
|
2011-03-07 20:15:16 +01:00
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
// propsFolder = nil;
|
|
|
|
// propsMessage = nil;
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
- (void) setupAuxiliaryObjects
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
2012-06-29 19:59:38 +02:00
|
|
|
NSURL *folderURL;
|
|
|
|
NSMutableString *pathPrefix;
|
2012-09-07 18:46:18 +02:00
|
|
|
NSString *path, *folderName;
|
2012-06-29 19:59:38 +02:00
|
|
|
NSArray *parts;
|
|
|
|
NSUInteger lastPartIdx;
|
|
|
|
MAPIStoreUserContext *userContext;
|
|
|
|
|
2015-01-19 15:35:44 +01:00
|
|
|
parts = 0;
|
|
|
|
lastPartIdx = 0;
|
2012-09-07 18:46:18 +02:00
|
|
|
folderURL = [NSURL URLWithString: [self url]];
|
|
|
|
/* note: -[NSURL path] returns an unescaped representation */
|
2012-06-29 19:59:38 +02:00
|
|
|
path = [folderURL path];
|
|
|
|
path = [path substringFromIndex: 1];
|
|
|
|
if ([path length] > 0)
|
|
|
|
{
|
|
|
|
parts = [path componentsSeparatedByString: @"/"];
|
|
|
|
lastPartIdx = [parts count] - 1;
|
|
|
|
if ([path hasSuffix: @"/"])
|
|
|
|
lastPartIdx--;
|
|
|
|
folderName = [parts objectAtIndex: lastPartIdx];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
folderName = [folderURL host];
|
|
|
|
|
|
|
|
userContext = [self userContext];
|
2015-08-03 15:16:55 +02:00
|
|
|
[userContext activate];
|
2012-06-29 19:59:38 +02:00
|
|
|
[userContext ensureFolderTableExists];
|
|
|
|
|
|
|
|
ASSIGN (dbFolder,
|
2014-05-14 12:56:05 +02:00
|
|
|
[SOGoCacheGCSFolder objectWithName: folderName
|
2012-06-29 19:59:38 +02:00
|
|
|
inContainer: [container dbFolder]]);
|
|
|
|
[dbFolder setTableUrl: [userContext folderTableURL]];
|
|
|
|
if (!container && [path length] > 0)
|
|
|
|
{
|
|
|
|
pathPrefix = [NSMutableString stringWithCapacity: 64];
|
|
|
|
[pathPrefix appendFormat: @"/%@", [folderURL host]];
|
|
|
|
parts = [parts subarrayWithRange: NSMakeRange (0, lastPartIdx)];
|
|
|
|
if ([parts count] > 0)
|
|
|
|
[pathPrefix appendFormat: @"/%@", [parts componentsJoinedByString: @"/"]];
|
|
|
|
[dbFolder setPathPrefix: pathPrefix];
|
|
|
|
}
|
|
|
|
[dbFolder reloadIfNeeded];
|
|
|
|
|
|
|
|
/* propsMessage and self share the same properties dictionary */
|
|
|
|
// ASSIGN (propsMessage,
|
|
|
|
// [SOGoMAPIDBMessage objectWithName: @"properties.plist"
|
|
|
|
// inContainer: dbFolder]);
|
2014-05-13 23:54:02 +02:00
|
|
|
// [propsMessage setObjectType: MAPIInternalCacheObject];
|
2012-06-29 19:59:38 +02:00
|
|
|
// [propsMessage reloadIfNeeded];
|
|
|
|
[properties release];
|
|
|
|
properties = [dbFolder properties];
|
|
|
|
[properties retain];
|
2011-06-07 02:17:46 +02:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
[self setupVersionsMessage];
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithSOGoObject: (id) newSOGoObject
|
|
|
|
inContainer: (MAPIStoreObject *) newContainer
|
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
/* The instantiation of auxiliary folders is postponed when newContainer is
|
|
|
|
nil since there is no way to deduce the parent url. When setContext: is
|
|
|
|
invoked, it becomes possible again. */
|
|
|
|
if ((self = [super initWithSOGoObject: newSOGoObject
|
|
|
|
inContainer: newContainer])
|
|
|
|
&& newContainer)
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2012-06-29 19:59:38 +02:00
|
|
|
[self setupAuxiliaryObjects];
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
- (void) setContext: (MAPIStoreContext *) newContext
|
|
|
|
{
|
|
|
|
ASSIGN (context, newContext);
|
|
|
|
if (newContext)
|
2012-06-29 19:59:38 +02:00
|
|
|
[self setupAuxiliaryObjects];
|
2012-01-29 20:55:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (MAPIStoreContext *) context
|
|
|
|
{
|
|
|
|
if (!context)
|
2012-06-29 19:59:38 +02:00
|
|
|
[self setContext: (MAPIStoreContext *) [container context]];
|
2012-01-29 20:55:21 +01:00
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
2013-03-13 20:04:11 +01:00
|
|
|
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
2012-12-03 15:18:17 +01:00
|
|
|
|
2012-03-09 03:08:57 +01:00
|
|
|
// [messageKeys release];
|
|
|
|
// [faiMessageKeys release];
|
|
|
|
// [folderKeys release];
|
2012-06-29 19:59:38 +02:00
|
|
|
// [propsMessage release];
|
|
|
|
[dbFolder release];
|
2012-01-29 20:55:21 +01:00
|
|
|
[context release];
|
|
|
|
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2014-05-14 12:56:05 +02:00
|
|
|
- (SOGoCacheGCSFolder *) dbFolder
|
2011-08-12 00:56:04 +02:00
|
|
|
{
|
2012-06-29 19:59:38 +02:00
|
|
|
return dbFolder;
|
2011-08-12 00:56:04 +02:00
|
|
|
}
|
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
/* backend interface */
|
|
|
|
|
|
|
|
// - (SOGoMAPIDBMessage *) propertiesMessage
|
|
|
|
// {
|
|
|
|
// return propsMessage;
|
|
|
|
// }
|
|
|
|
|
2011-08-11 18:37:23 +02:00
|
|
|
- (uint64_t) objectVersion
|
|
|
|
{
|
|
|
|
NSNumber *value;
|
|
|
|
uint64_t cn;
|
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
value = [properties objectForKey: MAPIPropertyKey (PidTagChangeNumber)];
|
2011-08-11 18:37:23 +02:00
|
|
|
if (value)
|
|
|
|
cn = [value unsignedLongLongValue];
|
|
|
|
else
|
|
|
|
{
|
2012-03-02 21:44:24 +01:00
|
|
|
[self logWithFormat: @"no value for PidTagChangeNumber, adding one now"];
|
2011-08-11 18:37:23 +02:00
|
|
|
cn = [[self context] getNewChangeNumber];
|
|
|
|
value = [NSNumber numberWithUnsignedLongLong: cn];
|
2012-06-29 19:59:38 +02:00
|
|
|
|
|
|
|
[properties setObject: value
|
|
|
|
forKey: MAPIPropertyKey (PidTagChangeNumber)];
|
|
|
|
[dbFolder save];
|
2011-08-11 18:37:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return cn >> 16;
|
|
|
|
}
|
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
- (id) lookupFolder: (NSString *) folderKey
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
MAPIStoreFolder *childFolder = nil;
|
2011-07-14 23:35:54 +02:00
|
|
|
SOGoFolder *sogoFolder;
|
|
|
|
|
|
|
|
if ([[self folderKeys] containsObject: folderKey])
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
[[self userContext] activate];
|
|
|
|
sogoFolder = [sogoObject lookupName: folderKey
|
|
|
|
inContext: nil
|
2011-07-20 20:21:12 +02:00
|
|
|
acquire: NO];
|
2011-07-14 23:35:54 +02:00
|
|
|
if (sogoFolder && ![sogoFolder isKindOfClass: NSExceptionK])
|
2015-08-03 15:16:55 +02:00
|
|
|
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder
|
|
|
|
inContainer: self];
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return childFolder;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) lookupFolderByURL: (NSString *) childURL
|
|
|
|
{
|
2012-10-05 19:51:58 +02:00
|
|
|
MAPIStoreObject *foundObject;
|
|
|
|
NSString *key, *slashLessURL;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2012-10-05 19:51:58 +02:00
|
|
|
if ([childURL hasSuffix: @"/"])
|
|
|
|
slashLessURL = [childURL substringToIndex: [childURL length] - 1];
|
|
|
|
else
|
|
|
|
slashLessURL = childURL;
|
|
|
|
key = [self childKeyFromURL: slashLessURL];
|
|
|
|
if (key)
|
|
|
|
foundObject = [self lookupFolder: key];
|
|
|
|
else
|
|
|
|
foundObject = nil;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
|
|
|
return foundObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) lookupMessage: (NSString *) messageKey
|
|
|
|
{
|
|
|
|
MAPIStoreObject *childMessage = nil;
|
2011-09-23 17:36:49 +02:00
|
|
|
Class messageClass;
|
2011-07-14 23:35:54 +02:00
|
|
|
SOGoObject *msgObject;
|
|
|
|
|
2011-07-26 21:02:45 +02:00
|
|
|
if (messageKey)
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
[[self userContext] activate];
|
2011-07-26 21:02:45 +02:00
|
|
|
msgObject = [sogoObject lookupName: messageKey
|
|
|
|
inContext: nil
|
|
|
|
acquire: NO];
|
2014-11-12 16:21:44 +01:00
|
|
|
/* If the lookup in the indexing table works, but the IMAP does
|
|
|
|
not have the message, then the message does not exist in this
|
|
|
|
folder */
|
|
|
|
if (msgObject && [msgObject isKindOfClass: [SOGoMailObject class]]
|
|
|
|
&& ! [(SOGoMailObject *)msgObject doesMailExist])
|
|
|
|
return nil;
|
2011-07-26 21:02:45 +02:00
|
|
|
if (msgObject && ![msgObject isKindOfClass: NSExceptionK])
|
2011-08-08 21:04:53 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
[msgObject setContext: [[self userContext] woContext]];
|
2011-09-23 17:36:49 +02:00
|
|
|
messageClass = [msgObject mapistoreMessageClass];
|
2011-08-08 21:04:53 +02:00
|
|
|
childMessage
|
2011-09-23 17:36:49 +02:00
|
|
|
= [messageClass mapiStoreObjectWithSOGoObject: msgObject
|
|
|
|
inContainer: self];
|
2011-08-08 21:04:53 +02:00
|
|
|
}
|
2011-07-26 21:02:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return childMessage;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) lookupFAIMessage: (NSString *) messageKey
|
|
|
|
{
|
|
|
|
MAPIStoreObject *childMessage = nil;
|
|
|
|
SOGoObject *msgObject;
|
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
if (messageKey)
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
[[self userContext] activate];
|
2012-03-09 03:08:57 +01:00
|
|
|
if ([[self faiMessageKeys] containsObject: messageKey])
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2012-06-29 19:59:38 +02:00
|
|
|
msgObject = [dbFolder lookupName: messageKey
|
|
|
|
inContext: nil
|
|
|
|
acquire: NO];
|
2011-07-14 23:35:54 +02:00
|
|
|
childMessage
|
|
|
|
= [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: msgObject
|
|
|
|
inContainer: self];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return childMessage;
|
|
|
|
}
|
|
|
|
|
2012-10-05 19:51:58 +02:00
|
|
|
- (NSString *) childKeyFromURL: (NSString *) childURL
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2012-10-05 19:51:58 +02:00
|
|
|
NSString *baseURL, *subURL, *key = nil;
|
2011-07-14 23:35:54 +02:00
|
|
|
NSArray *parts;
|
|
|
|
NSUInteger partsCount;
|
|
|
|
|
|
|
|
baseURL = [self url];
|
|
|
|
if (![baseURL hasSuffix: @"/"])
|
|
|
|
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
|
|
|
|
if ([childURL hasPrefix: baseURL])
|
|
|
|
{
|
|
|
|
subURL = [childURL substringFromIndex: [baseURL length]];
|
|
|
|
if ([subURL length] > 0)
|
|
|
|
{
|
|
|
|
parts = [subURL componentsSeparatedByString: @"/"];
|
|
|
|
partsCount = [parts count];
|
|
|
|
if (partsCount == 1)
|
2011-07-26 21:02:45 +02:00
|
|
|
{
|
2012-09-07 18:46:18 +02:00
|
|
|
key = [[parts objectAtIndex: 0]
|
|
|
|
stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
|
2011-07-26 21:02:45 +02:00
|
|
|
}
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-05 19:51:58 +02:00
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) lookupMessageByURL: (NSString *) childURL
|
|
|
|
{
|
|
|
|
MAPIStoreObject *foundObject;
|
|
|
|
NSString *key;
|
|
|
|
|
|
|
|
key = [self childKeyFromURL: childURL];
|
|
|
|
if (key)
|
|
|
|
{
|
|
|
|
foundObject = [self lookupFAIMessage: key];
|
|
|
|
if (!foundObject)
|
|
|
|
foundObject = [self lookupMessage: key];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
foundObject = nil;
|
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
return foundObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) openFolder: (MAPIStoreFolder **) childFolderPtr
|
|
|
|
withFID: (uint64_t) fid
|
|
|
|
{
|
|
|
|
int rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
MAPIStoreFolder *childFolder;
|
|
|
|
MAPIStoreMapping *mapping;
|
|
|
|
NSString *childURL;
|
|
|
|
|
2013-03-13 20:04:11 +01:00
|
|
|
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [self mapping];
|
2011-07-14 23:35:54 +02:00
|
|
|
childURL = [mapping urlFromID: fid];
|
|
|
|
if (childURL)
|
|
|
|
{
|
|
|
|
childFolder = [self lookupFolderByURL: childURL];
|
|
|
|
if (childFolder)
|
|
|
|
{
|
|
|
|
*childFolderPtr = childFolder;
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) createFolder: (MAPIStoreFolder **) childFolderPtr
|
|
|
|
withRow: (struct SRow *) aRow
|
|
|
|
andFID: (uint64_t) fid
|
|
|
|
{
|
2015-04-13 11:48:42 +02:00
|
|
|
BOOL mapped;
|
|
|
|
enum mapistore_error rc = MAPISTORE_SUCCESS;
|
2011-07-14 23:35:54 +02:00
|
|
|
MAPIStoreMapping *mapping;
|
|
|
|
NSString *baseURL, *childURL, *folderKey;
|
|
|
|
MAPIStoreFolder *childFolder;
|
2012-01-29 20:55:21 +01:00
|
|
|
SOGoUser *ownerUser;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2013-03-13 20:04:11 +01:00
|
|
|
//[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
ownerUser = [[self userContext] sogoUser];
|
|
|
|
if ([[context activeUser] isEqual: ownerUser]
|
2011-12-01 23:36:35 +01:00
|
|
|
|| [self subscriberCanCreateSubFolders])
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [self mapping];
|
2011-12-01 23:36:35 +01:00
|
|
|
childURL = [mapping urlFromID: fid];
|
|
|
|
if (childURL)
|
|
|
|
rc = MAPISTORE_ERR_EXIST;
|
|
|
|
else
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2012-02-03 16:05:19 +01:00
|
|
|
rc = [self createFolder: aRow withFID: fid andKey: &folderKey];
|
|
|
|
if (rc == MAPISTORE_SUCCESS)
|
2011-07-15 15:43:38 +02:00
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
[self cleanupCaches];
|
|
|
|
baseURL = [self url];
|
|
|
|
if (![baseURL hasSuffix: @"/"])
|
|
|
|
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
|
2012-08-13 21:42:08 +02:00
|
|
|
childURL = [NSString stringWithFormat: @"%@%@/",
|
2012-09-07 18:46:18 +02:00
|
|
|
baseURL,
|
|
|
|
[folderKey stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
|
2015-04-13 11:48:42 +02:00
|
|
|
|
|
|
|
mapped = [mapping registerURL: childURL withID: fid];
|
|
|
|
if (!mapped)
|
|
|
|
/* Enforce the creation if the backend does know the fid */
|
|
|
|
[mapping updateURL: childURL withID: fid];
|
|
|
|
|
2011-12-01 23:36:35 +01:00
|
|
|
childFolder = [self lookupFolder: folderKey];
|
|
|
|
if (childFolder)
|
|
|
|
{
|
|
|
|
[childFolder addPropertiesFromRow: aRow];
|
|
|
|
*childFolderPtr = childFolder;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
2012-03-02 21:44:24 +01:00
|
|
|
format: @"unable to fetch created folder"];
|
2011-07-15 15:43:38 +02:00
|
|
|
}
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
}
|
2011-12-01 23:36:35 +01:00
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2015-01-21 12:44:31 +01:00
|
|
|
- (int) deleteFolder
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2014-05-07 01:26:34 +02:00
|
|
|
// TODO: raise exception in case underlying delete fails?
|
2012-06-29 19:59:38 +02:00
|
|
|
// [propsMessage delete];
|
|
|
|
[dbFolder delete];
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2012-02-03 18:22:45 +01:00
|
|
|
[self cleanupCaches];
|
|
|
|
|
2012-02-02 02:45:17 +01:00
|
|
|
return MAPISTORE_SUCCESS;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int) getChildCount: (uint32_t *) rowCount
|
2012-01-16 00:58:26 +01:00
|
|
|
ofTableType: (enum mapistore_table_type) tableType
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
|
|
|
NSArray *keys;
|
2011-07-15 21:29:30 +02:00
|
|
|
int rc = MAPISTORE_SUCCESS;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2013-03-13 20:04:11 +01:00
|
|
|
//[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
|
|
|
|
//__FUNCTION__, __LINE__, tableType];
|
2011-07-14 23:35:54 +02:00
|
|
|
|
|
|
|
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
|
|
|
keys = [self messageKeys];
|
|
|
|
else if (tableType == MAPISTORE_FOLDER_TABLE)
|
|
|
|
keys = [self folderKeys];
|
|
|
|
else if (tableType == MAPISTORE_FAI_TABLE)
|
|
|
|
keys = [self faiMessageKeys];
|
2011-07-28 02:45:35 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
keys = nil;
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
}
|
2011-07-14 23:35:54 +02:00
|
|
|
*rowCount = [keys count];
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) openMessage: (MAPIStoreMessage **) messagePtr
|
|
|
|
withMID: (uint64_t) mid
|
2011-12-01 23:28:12 +01:00
|
|
|
forWriting: (BOOL) readWrite
|
2011-07-14 23:35:54 +02:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
|
|
{
|
|
|
|
NSString *messageURL;
|
|
|
|
MAPIStoreMapping *mapping;
|
|
|
|
MAPIStoreMessage *message;
|
2012-01-29 20:55:21 +01:00
|
|
|
SOGoUser *ownerUser;
|
2011-07-14 23:35:54 +02:00
|
|
|
int rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [self mapping];
|
2011-07-14 23:35:54 +02:00
|
|
|
messageURL = [mapping urlFromID: mid];
|
|
|
|
if (messageURL)
|
|
|
|
{
|
|
|
|
message = [self lookupMessageByURL: messageURL];
|
|
|
|
if (message)
|
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
ownerUser = [[self userContext] sogoUser];
|
|
|
|
if ([[context activeUser] isEqual: ownerUser]
|
2011-12-01 23:28:12 +01:00
|
|
|
|| (readWrite && [message subscriberCanModifyMessage])
|
|
|
|
|| (!readWrite && [message subscriberCanReadMessage]))
|
|
|
|
{
|
|
|
|
*messagePtr = message;
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
2014-11-12 16:21:44 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Unregistering from indexing table as the backend says the
|
|
|
|
object was not found */
|
|
|
|
[mapping unregisterURLWithID: mid];
|
|
|
|
}
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) createMessage: (MAPIStoreMessage **) messagePtr
|
|
|
|
withMID: (uint64_t) mid
|
|
|
|
isAssociated: (BOOL) isAssociated
|
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
enum mapistore_error rc;
|
2011-07-14 23:35:54 +02:00
|
|
|
MAPIStoreMessage *message;
|
|
|
|
NSString *baseURL, *childURL;
|
|
|
|
MAPIStoreMapping *mapping;
|
2012-01-29 20:55:21 +01:00
|
|
|
SOGoUser *ownerUser;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2013-03-13 20:04:11 +01:00
|
|
|
//[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16llx associated: %d",
|
|
|
|
// __FUNCTION__, mid, isAssociated];
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2011-12-01 23:36:35 +01:00
|
|
|
context = [self context];
|
2012-01-29 20:55:21 +01:00
|
|
|
ownerUser = [[self userContext] sogoUser];
|
2015-08-03 15:16:55 +02:00
|
|
|
[[self userContext] activate];
|
2012-01-29 20:55:21 +01:00
|
|
|
|
|
|
|
if ([[context activeUser] isEqual: ownerUser]
|
2011-12-01 23:36:35 +01:00
|
|
|
|| (!isAssociated && [self subscriberCanCreateMessages]))
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [self mapping];
|
2011-12-01 23:36:35 +01:00
|
|
|
if ([mapping urlFromID: mid])
|
|
|
|
rc = MAPISTORE_ERR_EXIST;
|
|
|
|
else
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
message = [self createMessage: isAssociated];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
baseURL = [self url];
|
|
|
|
if (![baseURL hasSuffix: @"/"])
|
|
|
|
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
|
|
|
|
childURL = [NSString stringWithFormat: @"%@%@",
|
|
|
|
baseURL, [message nameInContainer]];
|
|
|
|
[mapping registerURL: childURL withID: mid];
|
|
|
|
*messagePtr = message;
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERROR;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
}
|
2011-12-01 23:36:35 +01:00
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) deleteMessageWithMID: (uint64_t) mid
|
|
|
|
andFlags: (uint8_t) flags
|
|
|
|
{
|
|
|
|
NSString *childURL;
|
|
|
|
MAPIStoreMapping *mapping;
|
|
|
|
MAPIStoreMessage *message;
|
|
|
|
NSArray *activeTables;
|
|
|
|
NSUInteger count, max;
|
2011-10-04 01:35:49 +02:00
|
|
|
id msgObject;
|
2012-01-29 20:55:21 +01:00
|
|
|
SOGoUser *ownerUser;
|
2011-07-14 23:35:54 +02:00
|
|
|
int rc;
|
|
|
|
|
2014-10-14 23:48:36 +02:00
|
|
|
/* flags that control the behaviour of the operation
|
|
|
|
(MAPISTORE_SOFT_DELETE or MAPISTORE_PERMANENT_DELETE) */
|
2011-08-12 18:10:33 +02:00
|
|
|
[self logWithFormat: @"-deleteMessageWithMID: mid: 0x%.16llx flags: %d", mid, flags];
|
2014-11-12 16:21:44 +01:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [self mapping];
|
2011-07-14 23:35:54 +02:00
|
|
|
childURL = [mapping urlFromID: mid];
|
|
|
|
if (childURL)
|
|
|
|
{
|
|
|
|
message = [self lookupMessageByURL: childURL];
|
|
|
|
if (message)
|
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
ownerUser = [[self userContext] sogoUser];
|
|
|
|
|
|
|
|
if ([[context activeUser] isEqual: ownerUser]
|
2011-12-01 23:36:35 +01:00
|
|
|
|| (![message isKindOfClass: MAPIStoreFAIMessageK]
|
|
|
|
&& [self subscriberCanDeleteMessages]))
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
/* we ensure the table caches are loaded so that old and new state
|
|
|
|
can be compared */
|
|
|
|
activeTables = ([message isKindOfClass: MAPIStoreFAIMessageK]
|
|
|
|
? [self activeFAIMessageTables]
|
|
|
|
: [self activeMessageTables]);
|
|
|
|
max = [activeTables count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
[[activeTables objectAtIndex: count] restrictedChildKeys];
|
|
|
|
|
|
|
|
msgObject = [message sogoObject];
|
|
|
|
if (([msgObject respondsToSelector: @selector (prepareDelete)]
|
|
|
|
&& [msgObject prepareDelete])
|
|
|
|
|| [msgObject delete])
|
2011-07-14 23:35:54 +02:00
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
rc = MAPISTORE_ERROR;
|
|
|
|
[self logWithFormat: @"ERROR deleting object at URL: %@", childURL];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self logWithFormat: @"successfully deleted object at URL: %@", childURL];
|
2014-10-14 23:48:36 +02:00
|
|
|
/* Ensure we are respecting flags parameter */
|
|
|
|
[mapping unregisterURLWithID: mid andFlags: flags];
|
2011-12-01 23:36:35 +01:00
|
|
|
[self cleanupCaches];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
}
|
2011-12-01 23:36:35 +01:00
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
else
|
2011-07-15 21:29:30 +02:00
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-12-03 15:18:17 +01:00
|
|
|
// private method
|
|
|
|
- (int) _moveCopyMessageWithMID: (uint64_t) srcMid
|
|
|
|
fromFolder: (MAPIStoreFolder *) sourceFolder
|
|
|
|
withMID: (uint64_t) targetMid
|
|
|
|
andChangeKey: (struct Binary_r *) targetChangeKey
|
2015-09-09 14:22:33 +02:00
|
|
|
andPredecessorChangeList: (struct Binary_r *) targetPredecessorChangeList
|
2012-12-03 15:18:17 +01:00
|
|
|
wantCopy: (uint8_t) wantCopy
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-09-22 17:39:53 +02:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
MAPIStoreMessage *sourceMsg, *destMsg;
|
2012-12-03 15:18:17 +01:00
|
|
|
//TALLOC_CTX *memCtx;
|
2012-08-15 03:02:08 +02:00
|
|
|
struct SRow aRow;
|
|
|
|
struct SPropValue property;
|
2014-10-15 00:35:17 +02:00
|
|
|
uint8_t deleteFlags;
|
2011-09-22 17:39:53 +02:00
|
|
|
|
2012-12-03 15:18:17 +01:00
|
|
|
[self logWithFormat: @"-moveCopyMessageWithMID: 0x%.16llx .. withMID: 0x%.16llx .. wantCopy: %d", srcMid, targetMid, wantCopy];
|
|
|
|
|
|
|
|
//memCtx = talloc_zero (NULL, TALLOC_CTX);
|
2011-09-22 17:39:53 +02:00
|
|
|
rc = [sourceFolder openMessage: &sourceMsg
|
|
|
|
withMID: srcMid
|
2011-12-01 23:28:12 +01:00
|
|
|
forWriting: NO
|
2011-09-22 17:39:53 +02:00
|
|
|
inMemCtx: memCtx];
|
|
|
|
if (rc != MAPISTORE_SUCCESS)
|
|
|
|
goto end;
|
|
|
|
|
2012-08-15 03:02:08 +02:00
|
|
|
rc = [self createMessage: &destMsg withMID: targetMid
|
|
|
|
isAssociated: [sourceMsg isKindOfClass: MAPIStoreFAIMessageK]];
|
2011-09-22 17:39:53 +02:00
|
|
|
if (rc != MAPISTORE_SUCCESS)
|
|
|
|
goto end;
|
|
|
|
|
2012-12-03 15:18:17 +01:00
|
|
|
[sourceMsg copyToMessage: destMsg inMemCtx: memCtx];
|
2011-09-22 17:39:53 +02:00
|
|
|
|
2015-09-09 14:22:33 +02:00
|
|
|
if (targetPredecessorChangeList)
|
2011-09-27 21:25:18 +02:00
|
|
|
{
|
2015-09-09 14:22:33 +02:00
|
|
|
property.ulPropTag = PidTagPredecessorChangeList;
|
|
|
|
property.value.bin = *targetPredecessorChangeList;
|
2012-08-15 03:02:08 +02:00
|
|
|
aRow.cValues = 1;
|
|
|
|
aRow.lpProps = &property;
|
|
|
|
rc = [destMsg addPropertiesFromRow: &aRow];
|
|
|
|
if (rc != MAPISTORE_SUCCESS)
|
2015-09-09 14:22:33 +02:00
|
|
|
{
|
|
|
|
[self errorWithFormat: @"Cannot add PredecessorChangeList on move"];
|
|
|
|
goto end;
|
|
|
|
}
|
2011-09-27 21:25:18 +02:00
|
|
|
}
|
2013-03-13 20:04:11 +01:00
|
|
|
[destMsg save: memCtx];
|
2011-09-22 17:39:53 +02:00
|
|
|
if (!wantCopy)
|
2014-10-15 00:35:17 +02:00
|
|
|
/* We want to keep mid for restoring/shared data to work if mids are different. */
|
|
|
|
deleteFlags = (srcMid == targetMid) ? MAPISTORE_PERMANENT_DELETE : MAPISTORE_SOFT_DELETE;
|
|
|
|
rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: deleteFlags];
|
2011-09-22 17:39:53 +02:00
|
|
|
|
|
|
|
end:
|
2012-12-03 15:18:17 +01:00
|
|
|
//talloc_free (memCtx);
|
2011-09-22 17:39:53 +02:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2011-09-21 21:33:35 +02:00
|
|
|
- (int) moveCopyMessagesWithMIDs: (uint64_t *) srcMids
|
2011-09-22 17:39:53 +02:00
|
|
|
andCount: (uint32_t) midCount
|
2011-09-22 15:39:41 +02:00
|
|
|
fromFolder: (MAPIStoreFolder *) sourceFolder
|
2011-09-21 21:33:35 +02:00
|
|
|
withMIDs: (uint64_t *) targetMids
|
2011-09-27 20:26:40 +02:00
|
|
|
andChangeKeys: (struct Binary_r **) targetChangeKeys
|
2015-09-09 14:22:33 +02:00
|
|
|
andPredecessorChangeLists: (struct Binary_r **) targetPredecessorChangeLists
|
2011-09-22 17:39:53 +02:00
|
|
|
wantCopy: (uint8_t) wantCopy
|
2012-12-03 15:18:17 +01:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-09-14 20:33:44 +02:00
|
|
|
{
|
2011-09-22 17:39:53 +02:00
|
|
|
int rc = MAPISTORE_SUCCESS;
|
|
|
|
NSUInteger count;
|
2011-09-22 17:54:47 +02:00
|
|
|
NSMutableArray *oldMessageURLs;
|
2011-09-27 16:44:53 +02:00
|
|
|
NSString *oldMessageURL;
|
2011-09-22 17:54:47 +02:00
|
|
|
MAPIStoreMapping *mapping;
|
2012-01-29 20:55:21 +01:00
|
|
|
SOGoUser *ownerUser;
|
2015-09-09 14:22:33 +02:00
|
|
|
struct Binary_r *targetChangeKey, *targetPredecessorChangeList;
|
2012-12-03 15:18:17 +01:00
|
|
|
//TALLOC_CTX *memCtx;
|
|
|
|
|
|
|
|
//memCtx = talloc_zero (NULL, TALLOC_CTX);
|
2011-09-22 17:39:53 +02:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
ownerUser = [[self userContext] sogoUser];
|
|
|
|
|
|
|
|
if (wantCopy || [[context activeUser] isEqual: ownerUser])
|
2011-09-22 17:54:47 +02:00
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
if ([sourceFolder isKindOfClass: isa]
|
|
|
|
|| [self isKindOfClass: [sourceFolder class]])
|
|
|
|
[self logWithFormat: @"%s: this class could probably implement"
|
|
|
|
@" a specialized/optimized version", __FUNCTION__];
|
|
|
|
oldMessageURLs = [NSMutableArray arrayWithCapacity: midCount];
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [self mapping];
|
2011-12-01 23:36:35 +01:00
|
|
|
for (count = 0; rc == MAPISTORE_SUCCESS && count < midCount; count++)
|
2011-09-27 16:44:53 +02:00
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
oldMessageURL = [mapping urlFromID: srcMids[count]];
|
|
|
|
if (oldMessageURL)
|
|
|
|
{
|
|
|
|
[oldMessageURLs addObject: oldMessageURL];
|
2015-09-09 14:22:33 +02:00
|
|
|
if (targetChangeKeys && targetPredecessorChangeList)
|
|
|
|
{
|
|
|
|
targetChangeKey = targetChangeKeys[count];
|
|
|
|
targetPredecessorChangeList = targetPredecessorChangeLists[count];
|
|
|
|
}
|
2011-12-01 23:36:35 +01:00
|
|
|
else
|
2015-09-09 14:22:33 +02:00
|
|
|
{
|
|
|
|
targetChangeKey = NULL;
|
|
|
|
targetPredecessorChangeList = NULL;
|
|
|
|
}
|
2012-12-03 15:18:17 +01:00
|
|
|
rc = [self _moveCopyMessageWithMID: srcMids[count]
|
|
|
|
fromFolder: sourceFolder
|
|
|
|
withMID: targetMids[count]
|
|
|
|
andChangeKey: targetChangeKey
|
2015-09-09 14:22:33 +02:00
|
|
|
andPredecessorChangeList: targetPredecessorChangeList
|
2012-12-03 15:18:17 +01:00
|
|
|
wantCopy: wantCopy
|
|
|
|
inMemCtx: memCtx];
|
2011-12-01 23:36:35 +01:00
|
|
|
}
|
2011-09-27 20:26:40 +02:00
|
|
|
else
|
2011-12-01 23:36:35 +01:00
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2011-09-27 16:44:53 +02:00
|
|
|
}
|
2011-09-22 17:54:47 +02:00
|
|
|
|
2011-12-01 23:36:35 +01:00
|
|
|
/* Notifications */
|
|
|
|
if (rc == MAPISTORE_SUCCESS)
|
|
|
|
{
|
|
|
|
// We cleanup cache of our source and destination folders
|
|
|
|
[self cleanupCaches];
|
|
|
|
[sourceFolder cleanupCaches];
|
|
|
|
}
|
2011-09-22 17:54:47 +02:00
|
|
|
}
|
2011-12-01 23:36:35 +01:00
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2012-12-03 15:18:17 +01:00
|
|
|
//talloc_free (memCtx);
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2011-09-14 20:33:44 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-08-15 03:02:08 +02:00
|
|
|
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
|
|
|
|
withNewName: (NSString *) newFolderName
|
|
|
|
isMove: (BOOL) isMove
|
|
|
|
isRecursive: (BOOL) isRecursive
|
2012-12-07 19:30:50 +01:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
|
2012-08-09 21:43:17 +02:00
|
|
|
{
|
2012-08-15 03:02:08 +02:00
|
|
|
enum mapistore_error rc;
|
|
|
|
NSAutoreleasePool *pool;
|
|
|
|
struct SRow folderRow;
|
|
|
|
struct SPropValue nameProperty;
|
|
|
|
MAPIStoreFolder *subFolder, *newFolder;
|
|
|
|
NSArray *children;
|
|
|
|
MAPIStoreMapping *mapping;
|
|
|
|
MAPIStoreMessage *message, *targetMessage;
|
|
|
|
NSUInteger count, max;
|
|
|
|
NSString *childKey;
|
|
|
|
uint64_t fmid;
|
2012-12-07 19:30:50 +01:00
|
|
|
//TALLOC_CTX *memCtx;
|
2012-12-03 15:18:17 +01:00
|
|
|
|
2012-12-07 19:30:50 +01:00
|
|
|
//memCtx = talloc_zero (NULL, TALLOC_CTX);
|
2012-08-15 03:02:08 +02:00
|
|
|
|
|
|
|
/* TODO: one possible issue with this algorithm is that moved messages will
|
|
|
|
lack a version number and will all be assigned a new one, even though
|
|
|
|
they have not changed. This also means that they will be transferred
|
|
|
|
again to the client during a sync operation. */
|
|
|
|
|
|
|
|
if ([targetFolder supportsSubFolders])
|
|
|
|
{
|
|
|
|
mapping = [self mapping];
|
|
|
|
|
|
|
|
if (!newFolderName)
|
|
|
|
newFolderName = [sogoObject displayName];
|
|
|
|
nameProperty.ulPropTag = PidTagDisplayName;
|
|
|
|
nameProperty.value.lpszW = [newFolderName UTF8String];
|
|
|
|
folderRow.lpProps = &nameProperty;
|
|
|
|
folderRow.cValues = 1;
|
|
|
|
rc = [targetFolder createFolder: &folderRow
|
|
|
|
withFID: [self objectId]
|
|
|
|
andKey: &childKey];
|
|
|
|
if (rc == MAPISTORE_SUCCESS)
|
|
|
|
{
|
|
|
|
newFolder = [targetFolder lookupFolder: childKey];
|
2012-12-03 15:18:17 +01:00
|
|
|
[self copyPropertiesToObject: newFolder inMemCtx: memCtx];
|
2012-08-15 03:02:08 +02:00
|
|
|
|
|
|
|
pool = [NSAutoreleasePool new];
|
|
|
|
children = [self messageKeys];
|
|
|
|
max = [children count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
childKey = [children objectAtIndex: count];
|
|
|
|
message = [self lookupMessage: childKey];
|
|
|
|
targetMessage = [newFolder createMessage: NO];
|
2012-08-15 15:13:15 +02:00
|
|
|
[targetMessage setIsNew: YES];
|
2012-12-03 15:18:17 +01:00
|
|
|
[message copyToMessage: targetMessage inMemCtx: memCtx];
|
2012-08-15 03:02:08 +02:00
|
|
|
if (isMove)
|
|
|
|
{
|
|
|
|
fmid = [mapping idFromURL: [message url]];
|
2014-10-15 00:39:49 +02:00
|
|
|
[self deleteMessageWithMID: fmid andFlags: MAPISTORE_PERMANENT_DELETE];
|
2012-08-15 03:02:08 +02:00
|
|
|
[mapping registerURL: [targetMessage url]
|
|
|
|
withID: fmid];
|
|
|
|
}
|
2013-03-13 20:04:11 +01:00
|
|
|
[targetMessage save: memCtx];
|
2012-08-15 03:02:08 +02:00
|
|
|
}
|
|
|
|
[pool release];
|
|
|
|
|
|
|
|
pool = [NSAutoreleasePool new];
|
|
|
|
children = [self faiMessageKeys];
|
|
|
|
max = [children count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
childKey = [children objectAtIndex: count];
|
|
|
|
message = [self lookupFAIMessage: childKey];
|
|
|
|
targetMessage = [newFolder createMessage: YES];
|
2012-08-15 15:13:15 +02:00
|
|
|
[targetMessage setIsNew: YES];
|
2012-12-03 15:18:17 +01:00
|
|
|
[message copyToMessage: targetMessage inMemCtx: memCtx];
|
2012-08-15 03:02:08 +02:00
|
|
|
if (isMove)
|
|
|
|
{
|
|
|
|
fmid = [mapping idFromURL: [message url]];
|
2014-10-15 00:39:49 +02:00
|
|
|
[self deleteMessageWithMID: fmid andFlags: MAPISTORE_PERMANENT_DELETE];
|
2012-08-15 03:02:08 +02:00
|
|
|
[mapping registerURL: [targetMessage url]
|
|
|
|
withID: fmid];
|
|
|
|
}
|
2013-03-13 20:04:11 +01:00
|
|
|
[targetMessage save: memCtx];
|
2012-08-15 03:02:08 +02:00
|
|
|
}
|
|
|
|
[pool release];
|
|
|
|
|
|
|
|
if (isRecursive)
|
|
|
|
{
|
|
|
|
pool = [NSAutoreleasePool new];
|
|
|
|
children = [self folderKeys];
|
|
|
|
max = [children count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
childKey = [children objectAtIndex: count];
|
|
|
|
subFolder = [self lookupFolder: childKey];
|
|
|
|
[subFolder moveCopyToFolder: newFolder withNewName: nil
|
|
|
|
isMove: isMove
|
2012-12-07 19:30:50 +01:00
|
|
|
isRecursive: isRecursive
|
|
|
|
inMemCtx: memCtx];
|
|
|
|
|
2012-08-15 03:02:08 +02:00
|
|
|
}
|
|
|
|
[pool release];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isMove)
|
2015-01-21 12:44:31 +01:00
|
|
|
[self deleteFolder];
|
2015-01-27 18:27:11 +01:00
|
|
|
|
2012-08-15 03:02:08 +02:00
|
|
|
[targetFolder cleanupCaches];
|
|
|
|
}
|
|
|
|
[self cleanupCaches];
|
2015-01-27 18:27:11 +01:00
|
|
|
|
|
|
|
/* We perform the mapping operations at the
|
|
|
|
end as objectId is required to be available
|
|
|
|
until the caches are cleaned up */
|
|
|
|
if (isMove && rc == MAPISTORE_SUCCESS)
|
|
|
|
{
|
|
|
|
fmid = [mapping idFromURL: [self url]];
|
|
|
|
[mapping unregisterURLWithID: fmid];
|
|
|
|
[mapping registerURL: [newFolder url]
|
|
|
|
withID: fmid];
|
|
|
|
}
|
|
|
|
|
2012-08-15 03:02:08 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
|
|
|
|
2012-12-07 19:30:50 +01:00
|
|
|
//talloc_free (memCtx);
|
2012-12-03 15:18:17 +01:00
|
|
|
|
2012-08-15 03:02:08 +02:00
|
|
|
return rc;
|
2012-08-09 21:43:17 +02:00
|
|
|
}
|
|
|
|
|
2011-11-18 16:26:03 +01:00
|
|
|
- (SOGoFolder *) aclFolder
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _modifyPermissionEntryForUser: (NSString *) user
|
|
|
|
withRoles: (NSArray *) roles
|
|
|
|
isAddition: (BOOL) isAddition
|
|
|
|
withACLFolder: (SOGoFolder *) aclFolder
|
|
|
|
{
|
2012-03-13 22:16:12 +01:00
|
|
|
if (user)
|
|
|
|
{
|
|
|
|
if (isAddition)
|
|
|
|
[aclFolder addUserInAcls: user];
|
|
|
|
[aclFolder setRoles: roles forUser: user];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[self logWithFormat: @"user is nil, keeping intended entry intact"];
|
2011-11-18 16:26:03 +01:00
|
|
|
}
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
- (void) setupVersionsMessage
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-10-13 05:28:47 +02:00
|
|
|
- (void) ensureIDsForChildKeys: (NSArray *) keys
|
|
|
|
{
|
|
|
|
NSMutableArray *missingURLs;
|
|
|
|
MAPIStoreMapping *mapping;
|
|
|
|
NSUInteger count, max;
|
|
|
|
NSString *baseURL, *URL, *key;
|
|
|
|
NSArray *newIDs;
|
|
|
|
uint64_t idNbr;
|
2014-10-15 00:35:17 +02:00
|
|
|
bool softDeleted;
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2012-10-13 05:28:47 +02:00
|
|
|
baseURL = [self url];
|
|
|
|
|
|
|
|
mapping = [self mapping];
|
|
|
|
max = [keys count];
|
|
|
|
missingURLs = [NSMutableArray arrayWithCapacity: max];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
key = [keys objectAtIndex: count];
|
|
|
|
URL = [NSString stringWithFormat: @"%@%@", baseURL, key];
|
2014-10-15 00:35:17 +02:00
|
|
|
idNbr = [mapping idFromURL: URL isSoftDeleted: &softDeleted];
|
|
|
|
if (idNbr == NSNotFound && !softDeleted)
|
2012-10-13 05:28:47 +02:00
|
|
|
[missingURLs addObject: URL];
|
|
|
|
}
|
|
|
|
|
|
|
|
max = [missingURLs count];
|
|
|
|
newIDs = [[self context] getNewFMIDs: max];
|
|
|
|
[mapping registerURLs: missingURLs
|
|
|
|
withIDs: newIDs];
|
|
|
|
}
|
|
|
|
|
2012-10-05 15:59:45 +02:00
|
|
|
- (int) getDeletedFMIDs: (struct UI8Array_r **) fmidsPtr
|
2011-07-29 04:13:39 +02:00
|
|
|
andCN: (uint64_t *) cnPtr
|
|
|
|
fromChangeNumber: (uint64_t) changeNum
|
2012-01-16 00:58:26 +01:00
|
|
|
inTableType: (enum mapistore_table_type) tableType
|
2011-07-29 04:13:39 +02:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
NSString *baseURL, *format, *url;
|
|
|
|
NSArray *keys;
|
|
|
|
NSNumber *cnNbr;
|
|
|
|
NSUInteger count, max;
|
|
|
|
MAPIStoreMapping *mapping;
|
2012-10-05 15:59:45 +02:00
|
|
|
struct UI8Array_r *fmids;
|
2011-07-29 04:13:39 +02:00
|
|
|
uint64_t fmid;
|
2014-10-15 00:35:17 +02:00
|
|
|
bool softDeleted;
|
2011-07-29 04:13:39 +02:00
|
|
|
|
|
|
|
keys = [self getDeletedKeysFromChangeNumber: changeNum andCN: &cnNbr
|
|
|
|
inTableType: tableType];
|
|
|
|
if (keys)
|
|
|
|
{
|
2012-01-29 20:55:21 +01:00
|
|
|
mapping = [self mapping];
|
2011-07-29 04:13:39 +02:00
|
|
|
|
|
|
|
max = [keys count];
|
|
|
|
|
2012-10-05 15:59:45 +02:00
|
|
|
fmids = talloc_zero (memCtx, struct UI8Array_r);
|
2011-07-29 04:13:39 +02:00
|
|
|
fmids->cValues = 0;
|
2012-10-05 15:59:45 +02:00
|
|
|
fmids->lpui8 = talloc_array (fmids, uint64_t, max);
|
2011-07-29 04:13:39 +02:00
|
|
|
*fmidsPtr = fmids;
|
|
|
|
if (max > 0)
|
|
|
|
*cnPtr = [cnNbr unsignedLongLongValue];
|
|
|
|
|
|
|
|
baseURL = [self url];
|
|
|
|
if ([baseURL hasSuffix: @"/"])
|
|
|
|
format = @"%@%@";
|
|
|
|
else
|
|
|
|
format = @"%@/%@";
|
|
|
|
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
url = [NSString stringWithFormat: format,
|
|
|
|
baseURL, [keys objectAtIndex: count]];
|
2014-10-15 00:35:17 +02:00
|
|
|
fmid = [mapping idFromURL: url isSoftDeleted: &softDeleted];
|
2011-07-29 04:13:39 +02:00
|
|
|
if (fmid != NSNotFound) /* if no fmid is returned, then the object
|
|
|
|
"never existed" in the OpenChange
|
2014-10-15 00:35:17 +02:00
|
|
|
databases. Soft-deleted messages are returned back */
|
2011-07-29 04:13:39 +02:00
|
|
|
{
|
2012-10-05 15:59:45 +02:00
|
|
|
fmids->lpui8[fmids->cValues] = fmid;
|
2011-07-29 04:13:39 +02:00
|
|
|
fmids->cValues++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2011-07-14 23:35:54 +02:00
|
|
|
- (int) getTable: (MAPIStoreTable **) tablePtr
|
|
|
|
andRowCount: (uint32_t *) countPtr
|
2012-01-16 00:58:26 +01:00
|
|
|
tableType: (enum mapistore_table_type) tableType
|
2011-07-14 23:35:54 +02:00
|
|
|
andHandleId: (uint32_t) handleId
|
|
|
|
{
|
2011-07-15 17:08:30 +02:00
|
|
|
int rc = MAPISTORE_SUCCESS;
|
2011-07-14 23:35:54 +02:00
|
|
|
MAPIStoreTable *table;
|
2012-03-09 23:12:07 +01:00
|
|
|
SOGoUser *ownerUser;
|
2011-07-14 23:35:54 +02:00
|
|
|
|
|
|
|
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
|
|
|
table = [self messageTable];
|
|
|
|
else if (tableType == MAPISTORE_FAI_TABLE)
|
|
|
|
table = [self faiMessageTable];
|
|
|
|
else if (tableType == MAPISTORE_FOLDER_TABLE)
|
|
|
|
table = [self folderTable];
|
2011-08-02 22:44:15 +02:00
|
|
|
else if (tableType == MAPISTORE_PERMISSIONS_TABLE)
|
2012-03-09 23:12:07 +01:00
|
|
|
{
|
|
|
|
ownerUser = [[self userContext] sogoUser];
|
|
|
|
if ([[context activeUser] isEqual: ownerUser])
|
|
|
|
table = [self permissionsTable];
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_DENIED;
|
|
|
|
}
|
2011-07-14 23:35:54 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
table = nil;
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
|
|
|
format: @"unsupported table type: %d", tableType];
|
|
|
|
}
|
2012-03-09 23:12:07 +01:00
|
|
|
|
|
|
|
if (rc == MAPISTORE_SUCCESS)
|
2011-07-15 17:08:30 +02:00
|
|
|
{
|
2012-03-09 23:12:07 +01:00
|
|
|
if (table)
|
|
|
|
{
|
|
|
|
[table setHandleId: handleId];
|
|
|
|
*tablePtr = table;
|
|
|
|
*countPtr = [[table childKeys] count];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2011-07-15 17:08:30 +02:00
|
|
|
}
|
2011-07-14 23:35:54 +02:00
|
|
|
|
2011-07-15 17:08:30 +02:00
|
|
|
return rc;
|
2011-07-14 23:35:54 +02:00
|
|
|
}
|
|
|
|
|
2011-11-07 16:07:37 +01:00
|
|
|
- (void) addProperties: (NSDictionary *) newProperties
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
static enum MAPITAGS bannedProps[] = { PR_MID, PR_FID, PR_PARENT_FID,
|
|
|
|
PR_SOURCE_KEY, PR_PARENT_SOURCE_KEY,
|
2015-08-03 15:16:55 +02:00
|
|
|
PR_CHANGE_KEY, PidTagChangeNumber, 0x00000000 };
|
2011-06-07 02:17:46 +02:00
|
|
|
enum MAPITAGS *currentProp;
|
2011-11-07 16:07:37 +01:00
|
|
|
NSMutableDictionary *propsCopy;
|
2015-08-03 15:16:55 +02:00
|
|
|
uint64_t cn;
|
2011-06-07 02:17:46 +02:00
|
|
|
|
|
|
|
/* TODO: this should no longer be required once mapistore v2 API is in
|
|
|
|
place, when we can then do this from -dealloc below */
|
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
[dbFolder reloadIfNeeded];
|
|
|
|
|
2011-11-07 16:07:37 +01:00
|
|
|
propsCopy = [newProperties mutableCopy];
|
2012-06-29 19:59:38 +02:00
|
|
|
[propsCopy autorelease];
|
|
|
|
|
2011-11-07 16:07:37 +01:00
|
|
|
currentProp = bannedProps;
|
|
|
|
while (*currentProp)
|
|
|
|
{
|
|
|
|
[propsCopy removeObjectForKey: MAPIPropertyKey (*currentProp)];
|
|
|
|
currentProp++;
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
[properties addEntriesFromDictionary: propsCopy];
|
2015-08-03 15:16:55 +02:00
|
|
|
|
|
|
|
/* Update change number after setting the properties */
|
|
|
|
cn = [[self context] getNewChangeNumber];
|
|
|
|
[properties setObject: [NSNumber numberWithUnsignedLongLong: cn]
|
|
|
|
forKey: MAPIPropertyKey (PidTagChangeNumber)];
|
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
[dbFolder save];
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (NSArray *) messageKeys
|
|
|
|
{
|
2012-03-09 03:08:57 +01:00
|
|
|
return [self messageKeysMatchingQualifier: nil
|
|
|
|
andSortOrderings: nil];
|
|
|
|
// if (!messageKeys)
|
|
|
|
// {
|
|
|
|
// messageKeys = [self messageKeysMatchingQualifier: nil
|
|
|
|
// andSortOrderings: nil];
|
|
|
|
// [messageKeys retain];
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return messageKeys;
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
2011-03-07 20:15:16 +01:00
|
|
|
- (MAPIStoreFAIMessageTable *) faiMessageTable
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
2011-03-07 20:15:16 +01:00
|
|
|
return [MAPIStoreFAIMessageTable tableForContainer: self];
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
2011-07-26 22:13:10 +02:00
|
|
|
- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier
|
|
|
|
andSortOrderings: (NSArray *) sortOrderings
|
|
|
|
{
|
2015-08-03 15:16:55 +02:00
|
|
|
[[self userContext] activate];
|
2014-05-13 23:54:02 +02:00
|
|
|
return [dbFolder childKeysOfType: MAPIFAICacheObject
|
2012-06-29 19:59:38 +02:00
|
|
|
includeDeleted: NO
|
|
|
|
matchingQualifier: qualifier
|
|
|
|
andSortOrderings: sortOrderings];
|
2011-07-26 22:13:10 +02:00
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (NSArray *) faiMessageKeys
|
|
|
|
{
|
2012-03-09 03:08:57 +01:00
|
|
|
return [self faiMessageKeysMatchingQualifier: nil
|
|
|
|
andSortOrderings: nil];
|
|
|
|
// if (!faiMessageKeys)
|
|
|
|
// {
|
|
|
|
// faiMessageKeys = [self faiMessageKeysMatchingQualifier: nil
|
|
|
|
// andSortOrderings: nil];
|
|
|
|
// [faiMessageKeys retain];
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return faiMessageKeys;
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (MAPIStoreFolderTable *) folderTable
|
|
|
|
{
|
2011-07-26 22:13:10 +02:00
|
|
|
return [MAPIStoreFolderTable tableForContainer: self];
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) folderKeys
|
|
|
|
{
|
2012-03-09 03:08:57 +01:00
|
|
|
return [self folderKeysMatchingQualifier: nil
|
|
|
|
andSortOrderings: nil];
|
|
|
|
// if (!folderKeys)
|
|
|
|
// {
|
|
|
|
// folderKeys = [self folderKeysMatchingQualifier: nil
|
|
|
|
// andSortOrderings: nil];
|
|
|
|
// [folderKeys retain];
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return folderKeys;
|
2011-07-26 22:13:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier
|
|
|
|
andSortOrderings: (NSArray *) sortOrderings
|
|
|
|
{
|
|
|
|
if (qualifier)
|
|
|
|
[self errorWithFormat: @"qualifier is not used for folders"];
|
|
|
|
if (sortOrderings)
|
|
|
|
[self errorWithFormat: @"sort orderings are not used for folders"];
|
|
|
|
|
|
|
|
return [sogoObject toManyRelationshipKeys];
|
2011-03-07 20:15:16 +01:00
|
|
|
}
|
2011-02-24 21:32:27 +01:00
|
|
|
|
2011-03-07 20:15:16 +01:00
|
|
|
- (NSArray *) activeMessageTables
|
|
|
|
{
|
2011-05-31 05:39:36 +02:00
|
|
|
return [[MAPIStoreActiveTables activeTables]
|
|
|
|
activeTablesForFMID: [self objectId]
|
|
|
|
andType: MAPISTORE_MESSAGE_TABLE];
|
2011-03-07 20:15:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) activeFAIMessageTables
|
|
|
|
{
|
2011-05-31 05:39:36 +02:00
|
|
|
return [[MAPIStoreActiveTables activeTables]
|
|
|
|
activeTablesForFMID: [self objectId]
|
|
|
|
andType: MAPISTORE_FAI_TABLE];
|
2011-03-07 20:15:16 +01:00
|
|
|
}
|
|
|
|
|
2012-01-16 00:58:26 +01:00
|
|
|
- (void) _cleanupTableCaches: (enum mapistore_table_type) tableType
|
2011-03-07 20:15:16 +01:00
|
|
|
{
|
2011-05-31 05:39:36 +02:00
|
|
|
NSArray *tables;
|
2011-03-07 20:15:16 +01:00
|
|
|
NSUInteger count, max;
|
|
|
|
|
2011-05-31 05:39:36 +02:00
|
|
|
tables = [[MAPIStoreActiveTables activeTables]
|
|
|
|
activeTablesForFMID: [self objectId]
|
|
|
|
andType: tableType];
|
|
|
|
max = [tables count];
|
2011-03-07 20:15:16 +01:00
|
|
|
for (count = 0; count < max; count++)
|
2011-05-31 05:39:36 +02:00
|
|
|
[[tables objectAtIndex: count] cleanupCaches];
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) cleanupCaches
|
|
|
|
{
|
2011-05-31 05:39:36 +02:00
|
|
|
[self _cleanupTableCaches: MAPISTORE_MESSAGE_TABLE];
|
|
|
|
[self _cleanupTableCaches: MAPISTORE_FAI_TABLE];
|
|
|
|
[self _cleanupTableCaches: MAPISTORE_FOLDER_TABLE];
|
2012-03-09 03:08:57 +01:00
|
|
|
// [faiMessageKeys release];
|
|
|
|
// faiMessageKeys = nil;
|
|
|
|
// [messageKeys release];
|
|
|
|
// messageKeys = nil;
|
|
|
|
// [folderKeys release];
|
|
|
|
// folderKeys = nil;
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagParentFolderId: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
*data = MAPILongLongValue (memCtx, [container objectId]);
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagFolderId: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
*data = MAPILongLongValue (memCtx, [self objectId]);
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-09-14 20:33:44 +02:00
|
|
|
/*
|
|
|
|
Possible values are:
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2011-09-14 20:33:44 +02:00
|
|
|
0x00000001 Modify
|
|
|
|
0x00000002 Read
|
|
|
|
0x00000004 Delete
|
|
|
|
0x00000008 Create Hierarchy Table
|
|
|
|
0x00000010 Create Contents Table
|
|
|
|
0x00000020 Create Associated Contents Table
|
|
|
|
*/
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagAccess: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2011-12-01 23:36:35 +01:00
|
|
|
uint32_t access = 0;
|
2012-01-29 20:55:21 +01:00
|
|
|
SOGoUser *ownerUser;
|
2011-12-01 23:36:35 +01:00
|
|
|
BOOL userIsOwner;
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
ownerUser = [[self userContext] sogoUser];
|
|
|
|
|
|
|
|
userIsOwner = [[context activeUser] isEqual: ownerUser];
|
2011-12-01 23:36:35 +01:00
|
|
|
if (userIsOwner || [self subscriberCanModifyMessages])
|
|
|
|
access |= 0x01;
|
|
|
|
if (userIsOwner || [self subscriberCanReadMessages])
|
|
|
|
access |= 0x02;
|
|
|
|
if (userIsOwner || [self subscriberCanDeleteMessages])
|
|
|
|
access |= 0x04;
|
2012-01-26 20:56:24 +01:00
|
|
|
if ((userIsOwner || [self subscriberCanCreateSubFolders])
|
|
|
|
&& [self supportsSubFolders])
|
2011-12-01 23:36:35 +01:00
|
|
|
access |= 0x08;
|
|
|
|
if (userIsOwner || [self subscriberCanCreateMessages])
|
|
|
|
access |= 0x10;
|
|
|
|
if (userIsOwner)
|
|
|
|
access |= 0x20;
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2011-12-01 23:36:35 +01:00
|
|
|
*data = MAPILongValue (memCtx, access);
|
2011-06-07 02:17:46 +02:00
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-08-21 22:39:36 +02:00
|
|
|
- (int) getPidTagRights: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
{
|
|
|
|
uint32_t rights = 0;
|
|
|
|
SOGoUser *ownerUser;
|
|
|
|
BOOL userIsOwner;
|
|
|
|
|
|
|
|
ownerUser = [[self userContext] sogoUser];
|
|
|
|
|
|
|
|
userIsOwner = [[context activeUser] isEqual: ownerUser];
|
|
|
|
if (userIsOwner || [self subscriberCanReadMessages])
|
|
|
|
rights |= RightsReadItems;
|
|
|
|
if (userIsOwner || [self subscriberCanCreateMessages])
|
|
|
|
rights |= RightsCreateItems;
|
|
|
|
if (userIsOwner || [self subscriberCanModifyMessages])
|
|
|
|
rights |= RightsEditOwn | RightsEditAll;
|
|
|
|
if (userIsOwner || [self subscriberCanDeleteMessages])
|
|
|
|
rights |= RightsDeleteOwn | RightsDeleteAll;
|
|
|
|
if ((userIsOwner || [self subscriberCanCreateSubFolders])
|
|
|
|
&& [self supportsSubFolders])
|
|
|
|
rights |= RightsCreateSubfolders;
|
|
|
|
if (userIsOwner)
|
|
|
|
rights |= RightsFolderOwner | RightsFolderContact;
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2012-08-21 22:39:36 +02:00
|
|
|
*data = MAPILongValue (memCtx, rights);
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) getPidTagAccessControlListData: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
{
|
|
|
|
*data = [[NSData data] asBinaryInMemCtx: memCtx];
|
2011-06-07 02:17:46 +02:00
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagAttributeHidden: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2011-07-11 23:40:47 +02:00
|
|
|
return [self getNo: data inMemCtx: memCtx];
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagAttributeSystem: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2011-07-11 23:40:47 +02:00
|
|
|
return [self getNo: data inMemCtx: memCtx];
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagAttributeReadOnly: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2011-07-11 23:40:47 +02:00
|
|
|
return [self getNo: data inMemCtx: memCtx];
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagSubfolders: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2012-09-28 01:23:56 +02:00
|
|
|
*data = MAPIBoolValue (memCtx, [self supportsSubFolders] && [[self folderKeys] count] > 0);
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagFolderChildCount: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
*data = MAPILongValue (memCtx, [[self folderKeys] count]);
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagContentCount: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
*data = MAPILongValue (memCtx, [[self messageKeys] count]);
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagContentUnreadCount: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
*data = MAPILongValue (memCtx, 0);
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagAssociatedContentCount: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
*data = MAPILongValue (memCtx, [[self faiMessageKeys] count]);
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagDeletedCountTotal: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
*data = MAPILongValue (memCtx, 0);
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-03-02 21:44:24 +01:00
|
|
|
- (int) getPidTagLocalCommitTimeMax: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2012-03-12 06:57:15 +01:00
|
|
|
int rc = MAPISTORE_SUCCESS;
|
|
|
|
NSDate *date;
|
2011-06-07 02:17:46 +02:00
|
|
|
|
2012-03-12 06:57:15 +01:00
|
|
|
date = [self lastMessageModificationTime];
|
|
|
|
if (date)
|
|
|
|
*data = [date asFileTimeInMemCtx: memCtx];
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
return rc;
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2012-03-16 21:56:01 +01:00
|
|
|
- (int) getPidTagDefaultPostMessageClass: (void **) data
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
{
|
|
|
|
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
- (int) getProperties: (struct mapistore_property_data *) data
|
|
|
|
withTags: (enum MAPITAGS *) tags
|
|
|
|
andCount: (uint16_t) columnCount
|
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
|
|
|
{
|
|
|
|
[dbFolder reloadIfNeeded];
|
|
|
|
|
|
|
|
return [super getProperties: data
|
|
|
|
withTags: tags
|
|
|
|
andCount: columnCount
|
|
|
|
inMemCtx: memCtx];
|
|
|
|
}
|
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
- (int) getProperty: (void **) data
|
|
|
|
withTag: (enum MAPITAGS) propTag
|
2011-07-11 23:40:47 +02:00
|
|
|
inMemCtx: (TALLOC_CTX *) memCtx
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
|
|
|
int rc;
|
2011-06-07 02:17:46 +02:00
|
|
|
id value;
|
2011-02-24 21:32:27 +01:00
|
|
|
|
2012-06-29 19:59:38 +02:00
|
|
|
value = [properties objectForKey: MAPIPropertyKey (propTag)];
|
2011-06-07 02:17:46 +02:00
|
|
|
if (value)
|
2011-11-22 18:48:46 +01:00
|
|
|
rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
|
2011-06-07 02:17:46 +02:00
|
|
|
else
|
2011-07-11 23:40:47 +02:00
|
|
|
rc = [super getProperty: data withTag: propTag inMemCtx: memCtx];
|
2011-02-24 21:32:27 +01:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (MAPIStoreMessage *) _createAssociatedMessage
|
|
|
|
{
|
|
|
|
MAPIStoreMessage *newMessage;
|
2012-06-29 19:59:38 +02:00
|
|
|
SOGoMAPIDBMessage *dbObject;
|
2011-02-24 21:32:27 +01:00
|
|
|
NSString *newKey;
|
|
|
|
|
|
|
|
newKey = [NSString stringWithFormat: @"%@.plist",
|
|
|
|
[SOGoObject globallyUniqueObjectId]];
|
2012-06-29 19:59:38 +02:00
|
|
|
dbObject = [SOGoMAPIDBMessage objectWithName: newKey inContainer: dbFolder];
|
2014-05-13 23:54:02 +02:00
|
|
|
[dbObject setObjectType: MAPIFAICacheObject];
|
2012-06-29 19:59:38 +02:00
|
|
|
[dbObject setIsNew: YES];
|
|
|
|
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: dbObject
|
2011-07-14 23:35:54 +02:00
|
|
|
inContainer: self];
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
return newMessage;
|
|
|
|
}
|
|
|
|
|
2011-09-21 21:33:35 +02:00
|
|
|
- (MAPIStoreMessage *) createMessage: (BOOL) isAssociated
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
|
|
|
MAPIStoreMessage *newMessage;
|
2011-07-20 20:21:12 +02:00
|
|
|
WOContext *woContext;
|
2011-02-24 21:32:27 +01:00
|
|
|
|
2015-08-03 15:16:55 +02:00
|
|
|
[[self userContext] activate];
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
if (isAssociated)
|
|
|
|
newMessage = [self _createAssociatedMessage];
|
|
|
|
else
|
2011-09-21 21:33:35 +02:00
|
|
|
newMessage = [self createMessage];
|
2012-06-29 19:59:38 +02:00
|
|
|
/* FIXME: this is ugly as the specifics of message creation should all be
|
|
|
|
delegated to subclasses */
|
|
|
|
if ([newMessage respondsToSelector: @selector (setIsNew:)])
|
|
|
|
[newMessage setIsNew: YES];
|
2012-01-29 20:55:21 +01:00
|
|
|
woContext = [[self userContext] woContext];
|
2012-06-29 19:59:38 +02:00
|
|
|
/* FIXME: this is ugly too as the specifics of message creation should all
|
|
|
|
be delegated to subclasses */
|
|
|
|
if ([newMessage respondsToSelector: @selector (sogoObject:)])
|
|
|
|
[[newMessage sogoObject] setContext: woContext];
|
2011-02-24 21:32:27 +01:00
|
|
|
|
|
|
|
return newMessage;
|
|
|
|
}
|
|
|
|
|
2012-02-03 16:05:19 +01:00
|
|
|
- (enum mapistore_error) createFolder: (struct SRow *) aRow
|
|
|
|
withFID: (uint64_t) newFID
|
|
|
|
andKey: (NSString **) newKeyP
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
|
|
|
[self errorWithFormat: @"new folders cannot be created in this context"];
|
|
|
|
|
2012-02-03 16:05:19 +01:00
|
|
|
return MAPISTORE_ERR_DENIED;
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* helpers */
|
|
|
|
|
|
|
|
- (NSString *) url
|
|
|
|
{
|
|
|
|
NSString *url;
|
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
if (container)
|
2011-02-24 21:32:27 +01:00
|
|
|
url = [NSString stringWithFormat: @"%@/", [super url]];
|
2012-01-29 20:55:21 +01:00
|
|
|
else
|
|
|
|
{
|
2012-09-07 18:46:18 +02:00
|
|
|
url = [[context url] absoluteString];
|
2012-01-29 20:55:21 +01:00
|
|
|
if (![url hasSuffix: @"/"])
|
|
|
|
url = [NSString stringWithFormat: @"%@/", url];
|
|
|
|
}
|
2011-02-24 21:32:27 +01:00
|
|
|
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2011-08-02 22:44:15 +02:00
|
|
|
- (MAPIStorePermissionsTable *) permissionsTable
|
|
|
|
{
|
|
|
|
return [MAPIStorePermissionsTable tableForContainer: self];
|
|
|
|
}
|
|
|
|
|
2011-11-18 16:26:03 +01:00
|
|
|
- (NSArray *) permissionEntries
|
|
|
|
{
|
|
|
|
NSMutableArray *permissionEntries;
|
|
|
|
MAPIStorePermissionEntry *entry;
|
|
|
|
NSArray *aclUsers;
|
|
|
|
uint64_t memberId, regularMemberId = 1;
|
|
|
|
NSUInteger count, max;
|
|
|
|
NSString *username, *defaultUserId;
|
|
|
|
SOGoFolder *aclFolder;
|
|
|
|
|
|
|
|
aclFolder = [self aclFolder];
|
|
|
|
|
|
|
|
defaultUserId = [aclFolder defaultUserID];
|
|
|
|
aclUsers = [aclFolder aclUsers];
|
|
|
|
max = [aclUsers count];
|
|
|
|
permissionEntries = [NSMutableArray arrayWithCapacity: max];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
username = [aclUsers objectAtIndex: count];
|
|
|
|
if (![username hasPrefix: @"@"])
|
|
|
|
{
|
|
|
|
if ([username isEqualToString: defaultUserId])
|
|
|
|
memberId = 0;
|
|
|
|
else if ([username isEqualToString: @"anonymous"])
|
|
|
|
memberId = ULLONG_MAX;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memberId = regularMemberId;
|
|
|
|
regularMemberId++;
|
|
|
|
}
|
|
|
|
entry = [MAPIStorePermissionEntry entryWithUserId: username
|
|
|
|
andMemberId: memberId
|
|
|
|
forFolder: self];
|
|
|
|
[permissionEntries addObject: entry];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return permissionEntries;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (uint32_t) exchangeRightsForRoles: (NSArray *) roles
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) _usernameFromEntryId: (struct SBinary_short *) bin
|
|
|
|
{
|
|
|
|
struct Binary_r bin32;
|
|
|
|
struct AddressBookEntryId *entryId;
|
|
|
|
NSString *username;
|
|
|
|
struct ldb_context *samCtx;
|
|
|
|
|
2012-03-13 22:16:12 +01:00
|
|
|
if (bin && bin->cb)
|
2011-11-18 16:26:03 +01:00
|
|
|
{
|
2012-03-13 22:16:12 +01:00
|
|
|
bin32.cb = bin->cb;
|
|
|
|
bin32.lpb = bin->lpb;
|
|
|
|
|
|
|
|
entryId = get_AddressBookEntryId (NULL, &bin32);
|
|
|
|
if (entryId)
|
|
|
|
{
|
|
|
|
samCtx = [[self context] connectionInfo]->sam_ctx;
|
|
|
|
username = MAPIStoreSamDBUserAttribute (samCtx, @"legacyExchangeDN",
|
|
|
|
[NSString stringWithUTF8String: entryId->X500DN],
|
|
|
|
@"sAMAccountName");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
username = nil;
|
|
|
|
talloc_free (entryId);
|
2011-11-18 16:26:03 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
username = nil;
|
|
|
|
|
|
|
|
return username;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) _usernameFromMemberId: (uint64_t) memberId
|
|
|
|
inEntries: (NSArray *) entries
|
|
|
|
{
|
|
|
|
NSString *username = nil;
|
|
|
|
NSUInteger count, max;
|
|
|
|
MAPIStorePermissionEntry *entry;
|
|
|
|
|
2012-03-13 22:16:12 +01:00
|
|
|
if (memberId == 0)
|
|
|
|
username = [[self aclFolder] defaultUserID];
|
|
|
|
else if (memberId == ULLONG_MAX)
|
|
|
|
username = @"anonymous";
|
|
|
|
else
|
2011-11-18 16:26:03 +01:00
|
|
|
{
|
2012-03-13 22:16:12 +01:00
|
|
|
max = [entries count];
|
|
|
|
for (count = 0; !username && count < max; count++)
|
|
|
|
{
|
|
|
|
entry = [entries objectAtIndex: count];
|
|
|
|
if ([entry memberId] == memberId)
|
|
|
|
username = [entry userId];
|
|
|
|
}
|
2011-11-18 16:26:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return username;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _emptyACL
|
|
|
|
{
|
|
|
|
NSUInteger count, max;
|
|
|
|
NSArray *users;
|
|
|
|
SOGoFolder *aclFolder;
|
|
|
|
|
|
|
|
aclFolder = [self aclFolder];
|
|
|
|
|
2015-03-19 00:06:14 +01:00
|
|
|
users = [[aclFolder aclUsers] copy];
|
2011-11-18 16:26:03 +01:00
|
|
|
max = [users count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
[aclFolder removeUserFromAcls: [users objectAtIndex: count]];
|
2015-03-19 00:06:14 +01:00
|
|
|
|
|
|
|
[users release];
|
2011-11-18 16:26:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int) modifyPermissions: (struct PermissionData *) permissions
|
|
|
|
withCount: (uint16_t) pcount
|
|
|
|
andFlags: (int8_t) flags
|
|
|
|
{
|
|
|
|
NSUInteger count, propCount;
|
|
|
|
struct PermissionData *currentPermission;
|
|
|
|
struct mapi_SPropValue *mapiValue;
|
|
|
|
NSString *permissionUser;
|
|
|
|
NSArray *entries;
|
|
|
|
NSArray *permissionRoles;
|
2012-03-13 22:16:12 +01:00
|
|
|
BOOL reset, isAdd = NO, isDelete = NO, isModify = NO;
|
2011-11-18 16:26:03 +01:00
|
|
|
SOGoFolder *aclFolder;
|
|
|
|
|
|
|
|
aclFolder = [self aclFolder];
|
|
|
|
|
|
|
|
reset = ((flags & ModifyPerms_ReplaceRows) != 0);
|
|
|
|
if (reset)
|
|
|
|
[self _emptyACL];
|
|
|
|
|
|
|
|
entries = [self permissionEntries];
|
|
|
|
|
|
|
|
for (count = 0; count < pcount; count++)
|
|
|
|
{
|
|
|
|
currentPermission = permissions + count;
|
|
|
|
|
|
|
|
permissionUser = nil;
|
|
|
|
permissionRoles = nil;
|
2015-08-03 15:16:55 +02:00
|
|
|
|
2012-03-13 22:16:12 +01:00
|
|
|
if (currentPermission->PermissionDataFlags == ROW_ADD)
|
|
|
|
isAdd = YES;
|
|
|
|
else if (currentPermission->PermissionDataFlags == ROW_MODIFY)
|
|
|
|
isModify = YES;
|
|
|
|
else
|
|
|
|
isDelete = YES;
|
|
|
|
|
2011-11-18 16:26:03 +01:00
|
|
|
for (propCount = 0;
|
|
|
|
propCount < currentPermission->lpProps.cValues;
|
|
|
|
propCount++)
|
|
|
|
{
|
|
|
|
mapiValue = currentPermission->lpProps.lpProps + propCount;
|
|
|
|
switch (mapiValue->ulPropTag)
|
|
|
|
{
|
|
|
|
case PR_ENTRYID:
|
2012-03-13 22:16:12 +01:00
|
|
|
if (isAdd)
|
|
|
|
permissionUser
|
|
|
|
= [self _usernameFromEntryId: &mapiValue->value.bin];
|
2011-11-18 16:26:03 +01:00
|
|
|
break;
|
|
|
|
case PR_MEMBER_ID:
|
2012-03-13 22:16:12 +01:00
|
|
|
if (isModify || isDelete)
|
|
|
|
permissionUser = [self _usernameFromMemberId: mapiValue->value.d
|
|
|
|
inEntries: entries];
|
2011-11-18 16:26:03 +01:00
|
|
|
break;
|
|
|
|
case PR_MEMBER_RIGHTS:
|
2012-03-13 22:16:12 +01:00
|
|
|
if (isAdd || isModify)
|
|
|
|
permissionRoles
|
|
|
|
= [self rolesForExchangeRights: mapiValue->value.l];
|
2011-11-18 16:26:03 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (mapiValue->ulPropTag != PR_MEMBER_NAME)
|
|
|
|
[self warnWithFormat: @"unhandled permission property: %.8x",
|
|
|
|
mapiValue->ulPropTag];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reset)
|
|
|
|
{
|
|
|
|
if (isAdd)
|
|
|
|
[self _modifyPermissionEntryForUser: permissionUser
|
|
|
|
withRoles: permissionRoles
|
|
|
|
isAddition: YES
|
|
|
|
withACLFolder: aclFolder];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (isAdd || currentPermission->PermissionDataFlags == ROW_MODIFY)
|
|
|
|
[self _modifyPermissionEntryForUser: permissionUser
|
|
|
|
withRoles: permissionRoles
|
|
|
|
isAddition: isAdd
|
|
|
|
withACLFolder: aclFolder];
|
|
|
|
else if (currentPermission->PermissionDataFlags == ROW_REMOVE)
|
|
|
|
[aclFolder removeUserFromAcls: permissionUser];
|
|
|
|
else
|
|
|
|
[self errorWithFormat: @"unhandled permission action flag: %d",
|
|
|
|
currentPermission->PermissionDataFlags];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2012-10-06 19:01:44 +02:00
|
|
|
- (enum mapistore_error) preloadMessageBodiesWithMIDs: (const struct UI8Array_r *) mids
|
2012-10-10 16:38:25 +02:00
|
|
|
ofTableType: (enum mapistore_table_type) tableType
|
2012-10-06 19:01:44 +02:00
|
|
|
{
|
|
|
|
uint32_t count;
|
|
|
|
NSMutableArray *messageKeys;
|
|
|
|
MAPIStoreMapping *mapping;
|
|
|
|
NSString *messageURL, *messageKey;
|
|
|
|
|
|
|
|
messageKeys = [NSMutableArray arrayWithCapacity: mids->cValues];
|
|
|
|
|
|
|
|
mapping = [self mapping];
|
|
|
|
for (count = 0; count < mids->cValues; count++)
|
|
|
|
{
|
|
|
|
messageURL = [mapping urlFromID: mids->lpui8[count]];
|
|
|
|
if (messageURL)
|
|
|
|
{
|
|
|
|
messageKey = [self childKeyFromURL: messageURL];
|
|
|
|
if (messageKey)
|
|
|
|
[messageKeys addObject: messageKey];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-10 16:38:25 +02:00
|
|
|
return [self preloadMessageBodiesWithKeys: messageKeys
|
|
|
|
ofTableType: tableType];
|
2012-10-06 19:01:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (enum mapistore_error) preloadMessageBodiesWithKeys: (NSArray *) keys
|
2012-10-10 16:38:25 +02:00
|
|
|
ofTableType: (enum mapistore_table_type) tableType
|
2012-10-05 15:55:01 +02:00
|
|
|
{
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (uint64_t) objectId
|
|
|
|
{
|
|
|
|
uint64_t objectId;
|
2012-08-13 05:56:16 +02:00
|
|
|
NSString *folderKey;
|
2011-02-24 21:32:27 +01:00
|
|
|
|
2012-01-29 20:55:21 +01:00
|
|
|
if (container)
|
2012-08-13 05:56:16 +02:00
|
|
|
{
|
|
|
|
folderKey = [NSString stringWithFormat: @"%@/",
|
|
|
|
[sogoObject nameInContainer]];
|
|
|
|
objectId = [container idForObjectWithKey: folderKey];
|
|
|
|
}
|
2012-01-29 20:55:21 +01:00
|
|
|
else
|
|
|
|
objectId = [self idForObjectWithKey: nil];
|
2011-02-24 21:32:27 +01:00
|
|
|
|
|
|
|
return objectId;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (uint64_t) idForObjectWithKey: (NSString *) childKey
|
|
|
|
{
|
|
|
|
return [[self context] idForObjectWithKey: childKey
|
|
|
|
inFolderURL: [self url]];
|
|
|
|
}
|
|
|
|
|
2014-12-01 23:19:38 +01:00
|
|
|
- (MAPIStoreFolder *) rootContainer
|
|
|
|
{
|
|
|
|
/* Return the oldest ancestor, which does not have
|
|
|
|
container. If there is not container, it returns itself.
|
|
|
|
*/
|
|
|
|
if (container)
|
|
|
|
return [container rootContainer];
|
|
|
|
else
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2011-10-14 21:42:16 +02:00
|
|
|
- (NSDate *) creationTime
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2012-06-29 19:59:38 +02:00
|
|
|
return [dbFolder creationDate];
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2011-10-14 21:42:16 +02:00
|
|
|
- (NSDate *) lastModificationTime
|
2011-06-07 02:17:46 +02:00
|
|
|
{
|
2012-06-29 19:59:38 +02:00
|
|
|
return [dbFolder lastModified];
|
2011-06-07 02:17:46 +02:00
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
/* subclasses */
|
|
|
|
|
|
|
|
- (MAPIStoreMessageTable *) messageTable
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2011-07-26 22:13:10 +02:00
|
|
|
- (NSArray *) messageKeysMatchingQualifier: (EOQualifier *) qualifier
|
|
|
|
andSortOrderings: (NSArray *) sortOrderings
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
2015-08-03 15:16:55 +02:00
|
|
|
return nil;
|
2011-07-26 22:13:10 +02:00
|
|
|
}
|
|
|
|
|
2011-07-29 04:13:39 +02:00
|
|
|
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
|
|
|
|
andCN: (NSNumber **) cnNbrs
|
2012-01-16 00:58:26 +01:00
|
|
|
inTableType: (enum mapistore_table_type) tableType
|
2011-07-29 04:13:39 +02:00
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2011-09-21 21:33:35 +02:00
|
|
|
- (MAPIStoreMessage *) createMessage
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
2011-04-19 23:42:02 +02:00
|
|
|
[self logWithFormat: @"ignored method: %s", __PRETTY_FUNCTION__];
|
2011-02-24 21:32:27 +01:00
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
- (NSCalendarDate *) lastMessageModificationTime
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2011-12-01 22:13:09 +01:00
|
|
|
- (BOOL) subscriberCanCreateMessages
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) subscriberCanModifyMessages
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) subscriberCanReadMessages
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) subscriberCanDeleteMessages
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) subscriberCanCreateSubFolders
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2012-01-26 20:56:24 +01:00
|
|
|
- (BOOL) supportsSubFolders
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
@end
|