2010-10-01 22:35:29 +02:00
|
|
|
/* MAPIStoreContext.m - this file is part of SOGo
|
2010-10-01 20:54:30 +02:00
|
|
|
*
|
2010-10-01 22:35:29 +02:00
|
|
|
* Copyright (C) 2010 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
#import <Foundation/NSNull.h>
|
|
|
|
#import <Foundation/NSURL.h>
|
|
|
|
#import <Foundation/NSThread.h>
|
2010-12-03 23:31:56 +01:00
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
#import <NGObjWeb/WOContext.h>
|
|
|
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
|
|
|
|
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
|
|
|
|
2011-03-08 14:35:44 +01:00
|
|
|
#import <SOGo/SOGoUser.h>
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
#import "SOGoMAPIFSFolder.h"
|
|
|
|
#import "SOGoMAPIFSMessage.h"
|
2010-10-13 23:40:50 +02:00
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
#import "MAPIApplication.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "MAPIStoreAttachment.h"
|
|
|
|
// #import "MAPIStoreAttachmentTable.h"
|
2010-10-01 20:54:30 +02:00
|
|
|
#import "MAPIStoreAuthenticator.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "MAPIStoreFolder.h"
|
2010-12-30 15:18:42 +01:00
|
|
|
#import "MAPIStoreFolderTable.h"
|
2010-10-01 20:54:30 +02:00
|
|
|
#import "MAPIStoreMapping.h"
|
2011-02-24 21:32:27 +01:00
|
|
|
#import "MAPIStoreMessage.h"
|
|
|
|
#import "MAPIStoreMessageTable.h"
|
2011-03-07 20:15:16 +01:00
|
|
|
#import "MAPIStoreFAIMessage.h"
|
|
|
|
#import "MAPIStoreFAIMessageTable.h"
|
2010-11-19 22:14:53 +01:00
|
|
|
#import "MAPIStoreTypes.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
|
|
|
|
|
|
|
#import "MAPIStoreContext.h"
|
|
|
|
|
|
|
|
#undef DEBUG
|
2011-02-24 21:32:27 +01:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <gen_ndr/exchange.h>
|
|
|
|
#include <libmapiproxy.h>
|
2010-10-01 20:54:30 +02:00
|
|
|
#include <mapistore/mapistore.h>
|
|
|
|
#include <mapistore/mapistore_errors.h>
|
2011-02-24 21:32:27 +01:00
|
|
|
#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 */
|
|
|
|
|
2011-03-07 20:15:16 +01:00
|
|
|
static Class NSDataK, NSStringK, MAPIStoreFAIMessageK;
|
2010-11-19 22:14:53 +01:00
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
static NSMutableDictionary *contextClassMapping;
|
2011-06-04 01:53:30 +02:00
|
|
|
static NSMutableDictionary *userMAPIStoreMapping;
|
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;
|
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
NSDataK = [NSData class];
|
|
|
|
NSStringK = [NSString class];
|
2011-03-07 20:15:16 +01:00
|
|
|
MAPIStoreFAIMessageK = [MAPIStoreFAIMessage 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)
|
|
|
|
{
|
|
|
|
[contextClassMapping setObject: currentClass
|
|
|
|
forKey: moduleName];
|
|
|
|
NSLog (@" registered class '%@' as handler of '%@' contexts",
|
|
|
|
NSStringFromClass (currentClass), moduleName);
|
|
|
|
}
|
2010-11-22 22:32:11 +01:00
|
|
|
}
|
2011-06-04 01:53:30 +02:00
|
|
|
|
|
|
|
userMAPIStoreMapping = [NSMutableDictionary new];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 17:03:30 +01:00
|
|
|
static inline MAPIStoreContext *
|
|
|
|
_prepareContextClass (struct mapistore_context *newMemCtx,
|
2011-03-07 22:33:13 +01:00
|
|
|
Class contextClass,
|
2011-05-31 07:01:43 +02:00
|
|
|
struct mapistore_connection_info *connInfo,
|
2011-03-07 22:33:13 +01:00
|
|
|
NSURL *url, uint64_t fid)
|
2010-11-22 17:03:30 +01:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
static NSMutableDictionary *registration = nil;
|
2010-11-22 17:03:30 +01:00
|
|
|
MAPIStoreContext *context;
|
|
|
|
MAPIStoreAuthenticator *authenticator;
|
|
|
|
|
|
|
|
if (!registration)
|
|
|
|
registration = [NSMutableDictionary new];
|
|
|
|
|
|
|
|
if (![registration objectForKey: contextClass])
|
2011-03-07 22:33:13 +01:00
|
|
|
[registration setObject: [NSNull null]
|
|
|
|
forKey: contextClass];
|
2010-11-22 17:03:30 +01:00
|
|
|
|
2011-05-31 07:01:43 +02:00
|
|
|
context = [[contextClass alloc] initFromURL: url
|
|
|
|
withConnectionInfo: connInfo
|
|
|
|
andFID: fid
|
2011-03-07 22:33:13 +01:00
|
|
|
inMemCtx: newMemCtx];
|
2010-11-22 17:03:30 +01:00
|
|
|
[context autorelease];
|
|
|
|
|
|
|
|
authenticator = [MAPIStoreAuthenticator new];
|
2011-02-24 21:32:27 +01:00
|
|
|
[authenticator setUsername: [url user]];
|
|
|
|
[authenticator setPassword: [url password]];
|
2010-11-22 17:03:30 +01:00
|
|
|
[context setAuthenticator: authenticator];
|
|
|
|
[authenticator release];
|
|
|
|
|
|
|
|
[context setupRequest];
|
2011-02-24 21:32:27 +01:00
|
|
|
[context setupBaseFolder: url];
|
2011-06-07 02:17:46 +02:00
|
|
|
[context->folders setObject: context->baseFolder
|
|
|
|
forKey: [NSNumber numberWithUnsignedLongLong: fid]];
|
2010-11-22 17:03:30 +01:00
|
|
|
[context tearDownRequest];
|
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
+ (id) contextFromURI: (const char *) newUri
|
2011-05-31 07:01:43 +02:00
|
|
|
withConnectionInfo: (struct mapistore_connection_info *) connInfo
|
2011-03-07 22:33:13 +01:00
|
|
|
andFID: (uint64_t) fid
|
2010-10-13 23:40:50 +02:00
|
|
|
inMemCtx: (struct mapistore_context *) newMemCtx
|
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;
|
|
|
|
NSString *module, *completeURLString, *urlString;
|
2010-10-01 22:35:29 +02:00
|
|
|
NSURL *baseURL;
|
|
|
|
|
|
|
|
NSLog (@"METHOD '%s' (%d) -- uri: '%s'", __FUNCTION__, __LINE__, newUri);
|
|
|
|
|
|
|
|
context = nil;
|
|
|
|
|
|
|
|
urlString = [NSString stringWithUTF8String: newUri];
|
|
|
|
if (urlString)
|
|
|
|
{
|
|
|
|
completeURLString = [@"sogo://" stringByAppendingString: urlString];
|
2010-12-13 18:03:25 +01:00
|
|
|
if (![completeURLString hasSuffix: @"/"])
|
|
|
|
completeURLString = [completeURLString stringByAppendingString: @"/"];
|
2010-10-01 22:35:29 +02:00
|
|
|
baseURL = [NSURL URLWithString: completeURLString];
|
|
|
|
if (baseURL)
|
|
|
|
{
|
|
|
|
module = [baseURL host];
|
|
|
|
if (module)
|
|
|
|
{
|
2010-11-22 22:32:11 +01:00
|
|
|
contextClass = [contextClassMapping objectForKey: module];
|
2010-10-01 22:35:29 +02:00
|
|
|
if (contextClass)
|
2010-11-22 17:03:30 +01:00
|
|
|
context = _prepareContextClass (newMemCtx,
|
|
|
|
contextClass,
|
2011-05-31 07:01:43 +02:00
|
|
|
connInfo,
|
2011-03-07 22:33:13 +01:00
|
|
|
baseURL,
|
|
|
|
fid);
|
2010-11-22 22:32:11 +01:00
|
|
|
else
|
|
|
|
NSLog (@"ERROR: unrecognized module name '%@'", module);
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
else
|
|
|
|
NSLog (@"ERROR: url could not be parsed");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
NSLog (@"ERROR: url is an invalid UTF-8 string");
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
return context;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
if ((self = [super init]))
|
|
|
|
{
|
2010-11-06 00:27:08 +01:00
|
|
|
messages = [NSMutableDictionary new];
|
2011-06-07 02:17:46 +02:00
|
|
|
folders = [NSMutableDictionary new];
|
2010-10-01 22:35:29 +02:00
|
|
|
woContext = [WOContext contextWithRequest: nil];
|
|
|
|
[woContext retain];
|
2011-02-24 21:32:27 +01:00
|
|
|
baseFolder = nil;
|
2011-03-07 22:33:13 +01:00
|
|
|
contextUrl = nil;
|
2011-06-07 02:17:46 +02:00
|
|
|
cachedTable = nil;
|
|
|
|
cachedFolder = nil;
|
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
|
|
|
|
andFID: (uint64_t) newFid
|
|
|
|
inMemCtx: (struct mapistore_context *) newMemCtx
|
2011-03-07 22:33:13 +01:00
|
|
|
{
|
2011-06-04 01:53:30 +02:00
|
|
|
NSString *username;
|
2011-03-07 22:33:13 +01:00
|
|
|
|
|
|
|
if ((self = [self init]))
|
|
|
|
{
|
|
|
|
ASSIGN (contextUrl, newUrl);
|
|
|
|
|
2011-06-04 01:53:30 +02:00
|
|
|
username = [NSString stringWithUTF8String: newConnInfo->username];
|
|
|
|
mapping = [userMAPIStoreMapping objectForKey: username];
|
|
|
|
if (!mapping)
|
|
|
|
{
|
|
|
|
[self logWithFormat: @"generating mapping of ids for user '%@'",
|
|
|
|
username];
|
|
|
|
mapping = [MAPIStoreMapping mappingWithIndexing: newConnInfo->indexing];
|
|
|
|
[userMAPIStoreMapping setObject: mapping forKey: username];
|
|
|
|
}
|
2011-03-07 22:33:13 +01:00
|
|
|
if (![mapping urlFromID: newFid])
|
|
|
|
[mapping registerURL: [newUrl absoluteString]
|
|
|
|
withID: newFid];
|
|
|
|
contextFid = newFid;
|
|
|
|
|
|
|
|
memCtx = newMemCtx;
|
2011-05-31 07:01:43 +02:00
|
|
|
connInfo = newConnInfo;
|
2011-03-07 22:33:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (void) dealloc
|
|
|
|
{
|
2010-11-06 00:27:08 +01:00
|
|
|
[messages release];
|
2011-06-07 02:17:46 +02:00
|
|
|
[folders release];
|
|
|
|
[cachedTable release];
|
|
|
|
[cachedFolder release];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
[baseFolder release];
|
2010-10-01 22:35:29 +02:00
|
|
|
[woContext release];
|
|
|
|
[authenticator release];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-03-07 22:33:13 +01:00
|
|
|
[contextUrl 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
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (WOContext *) woContext
|
|
|
|
{
|
|
|
|
return woContext;
|
2010-10-13 23:40:50 +02:00
|
|
|
}
|
|
|
|
|
2011-06-04 01:53:30 +02:00
|
|
|
- (MAPIStoreMapping *) mapping
|
|
|
|
{
|
|
|
|
return mapping;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (void) setAuthenticator: (MAPIStoreAuthenticator *) newAuthenticator
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
ASSIGN (authenticator, newAuthenticator);
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (MAPIStoreAuthenticator *) authenticator
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
return authenticator;
|
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;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (void) setupRequest
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
NSMutableDictionary *info;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
[MAPIApp setMAPIStoreContext: self];
|
|
|
|
info = [[NSThread currentThread] threadDictionary];
|
2010-12-30 15:18:42 +01:00
|
|
|
[info setObject: woContext forKey: @"WOContext"];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) tearDownRequest
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
NSMutableDictionary *info;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
info = [[NSThread currentThread] threadDictionary];
|
2010-12-30 15:18:42 +01:00
|
|
|
[info removeObjectForKey: @"WOContext"];
|
2010-10-01 22:35:29 +02:00
|
|
|
[MAPIApp setMAPIStoreContext: nil];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
- (MAPIStoreObject *) _lookupObjectWithParts: (NSArray *) parts
|
|
|
|
{
|
|
|
|
NSUInteger count, max;
|
|
|
|
NSString *currentPart;
|
|
|
|
MAPIStoreObject *currentObject;
|
|
|
|
|
|
|
|
currentObject = baseFolder;
|
|
|
|
max = [parts count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentPart = [parts objectAtIndex: count];
|
|
|
|
if ([currentPart length] > 0)
|
|
|
|
currentObject = [currentObject lookupChild: currentPart];
|
|
|
|
}
|
|
|
|
|
|
|
|
return currentObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) lookupObject: (NSString *) childURL
|
2010-12-30 15:18:42 +01:00
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
NSString *baseURL, *subURL;
|
|
|
|
MAPIStoreObject *foundObject;
|
|
|
|
NSArray *parts;
|
|
|
|
|
|
|
|
baseURL = [contextUrl absoluteString];
|
|
|
|
if (![baseURL hasSuffix: @"/"])
|
|
|
|
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
|
|
|
|
if (![childURL hasSuffix: @"/"])
|
|
|
|
childURL = [NSString stringWithFormat: @"%@/", childURL];
|
|
|
|
if ([childURL isEqualToString: baseURL])
|
|
|
|
foundObject = baseFolder;
|
|
|
|
else if ([childURL hasPrefix: baseURL])
|
|
|
|
{
|
|
|
|
subURL = [childURL substringFromIndex: [baseURL length]];
|
|
|
|
parts = [subURL componentsSeparatedByString: @"/"];
|
|
|
|
foundObject = [self _lookupObjectWithParts: parts];
|
|
|
|
[self logWithFormat: @"returning object '%@'", childURL];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self errorWithFormat: @"url '%@' is not a child of this context (%@)",
|
|
|
|
childURL, baseURL];
|
|
|
|
foundObject = nil;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
/* TODO hierarchy */
|
2011-06-07 02:17:46 +02:00
|
|
|
return foundObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) lookupFolderWithFID: (uint64_t) fid
|
|
|
|
{
|
|
|
|
MAPIStoreFolder *folder;
|
|
|
|
NSNumber *fidKey;
|
|
|
|
NSString *folderURL;
|
|
|
|
|
|
|
|
fidKey = [NSNumber numberWithUnsignedLongLong: fid];
|
|
|
|
folder = [folders objectForKey: fidKey];
|
|
|
|
if (!folder)
|
|
|
|
{
|
|
|
|
/* TODO: should handle folder hierarchies */
|
|
|
|
folderURL = [mapping urlFromID: fid];
|
|
|
|
if (folderURL)
|
|
|
|
{
|
|
|
|
folder = [self lookupObject: folderURL];
|
|
|
|
if (folder)
|
|
|
|
[folders setObject: folder forKey: fidKey];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[self errorWithFormat: @"folder with url '%@' not found", folderURL];
|
|
|
|
}
|
|
|
|
|
|
|
|
return folder;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
\details Create a folder in the sogo backend
|
|
|
|
|
|
|
|
\param private_data pointer to the current sogo context
|
|
|
|
|
|
|
|
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
|
2010-10-01 22:35:29 +02:00
|
|
|
*/
|
2010-10-01 20:54:30 +02:00
|
|
|
|
|
|
|
- (int) mkDir: (struct SRow *) aRow
|
|
|
|
withFID: (uint64_t) fid
|
|
|
|
inParentFID: (uint64_t) parentFID
|
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
NSString *folderURL, *folderKey;
|
|
|
|
MAPIStoreFolder *parentFolder, *newFolder;
|
2010-10-01 22:35:29 +02:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
|
|
|
|
|
|
|
folderURL = [mapping urlFromID: fid];
|
|
|
|
if (folderURL)
|
|
|
|
rc = MAPISTORE_ERR_EXIST;
|
|
|
|
else
|
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
parentFolder = [self lookupFolderWithFID: parentFID];
|
|
|
|
if (parentFolder)
|
2010-10-13 23:40:50 +02:00
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
folderKey = [parentFolder createFolder: aRow withFID: fid];
|
2011-02-24 21:32:27 +01:00
|
|
|
if (folderKey)
|
2010-10-13 23:40:50 +02:00
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
[parentFolder cleanupCaches];
|
|
|
|
folderURL = [NSString stringWithFormat: @"%@%@",
|
|
|
|
[parentFolder url], folderKey];
|
2010-10-13 23:40:50 +02:00
|
|
|
[mapping registerURL: folderURL withID: fid];
|
2011-06-07 02:17:46 +02:00
|
|
|
newFolder = [parentFolder lookupChild: folderKey];
|
|
|
|
if (newFolder)
|
|
|
|
[newFolder setProperties: aRow];
|
|
|
|
else
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
|
|
|
format: @"unable to fetch created folder"];
|
2010-10-13 23:40:50 +02:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPISTORE_ERROR;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
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 rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
\details Delete a folder from the sogo backend
|
|
|
|
|
|
|
|
\param private_data pointer to the current sogo context
|
|
|
|
\param parentFID the FID for the parent of the folder to delete
|
|
|
|
\param fid the FID for the folder to delete
|
|
|
|
|
|
|
|
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
|
2010-10-01 22:35:29 +02:00
|
|
|
*/
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) rmDirWithFID: (uint64_t) fid
|
|
|
|
inParentFID: (uint64_t) parentFid
|
|
|
|
{
|
2010-11-19 15:41:15 +01:00
|
|
|
[self logWithFormat: @"UNIMPLEMENTED METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-14 23:37:39 +02:00
|
|
|
return MAPISTORE_ERROR;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
\details Open a folder from the sogo backend
|
|
|
|
|
|
|
|
\param private_data pointer to the current sogo context
|
|
|
|
\param parentFID the parent folder identifier
|
|
|
|
\param fid the identifier of the colder to open
|
|
|
|
|
|
|
|
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
|
2010-10-01 22:35:29 +02:00
|
|
|
*/
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) openDir: (uint64_t) fid
|
|
|
|
{
|
2010-12-03 23:31:56 +01:00
|
|
|
[self logWithFormat:
|
2011-06-04 01:59:02 +02:00
|
|
|
@"UNIMPLEMENTED METHOD '%s' (%d):\n fid=0x%.16x",
|
2010-12-03 23:31:56 +01:00
|
|
|
__FUNCTION__, __LINE__,
|
2011-06-04 01:59:02 +02:00
|
|
|
(unsigned long long) fid];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-06-04 01:59:02 +02:00
|
|
|
return MAPISTORE_SUCCESS;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
\details Close a folder from the sogo backend
|
|
|
|
|
|
|
|
\param private_data pointer to the current sogo context
|
|
|
|
|
|
|
|
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
|
2010-10-01 22:35:29 +02:00
|
|
|
*/
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) closeDir
|
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"UNIMNPLEMENTED METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
return MAPISTORE_SUCCESS;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (MAPIStoreTable *) _tableForFID: (uint64_t) fid
|
|
|
|
andTableType: (uint8_t) tableType
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreFolder *folder;
|
2010-12-30 15:18:42 +01:00
|
|
|
MAPIStoreTable *table;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
if (fid == cachedTableFID && tableType == cachedTableType)
|
|
|
|
table = cachedTable;
|
|
|
|
else
|
2011-04-05 17:25:57 +02:00
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
[cachedTable release];
|
|
|
|
cachedTable = nil;
|
|
|
|
[cachedFolder release];
|
|
|
|
cachedFolder = nil;
|
|
|
|
cachedTableFID = 0;
|
|
|
|
cachedTableType = 0;
|
|
|
|
|
|
|
|
folder = [self lookupFolderWithFID: fid];
|
2011-04-05 17:25:57 +02:00
|
|
|
if (folder)
|
|
|
|
{
|
|
|
|
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
|
|
|
table = [folder messageTable];
|
|
|
|
else if (tableType == MAPISTORE_FAI_TABLE)
|
|
|
|
table = [folder faiMessageTable];
|
|
|
|
else if (tableType == MAPISTORE_FOLDER_TABLE)
|
|
|
|
table = [folder folderTable];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
table = nil;
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
2011-06-07 02:17:46 +02:00
|
|
|
format: @"unsupported table type: %d", tableType];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (table)
|
|
|
|
{
|
|
|
|
cachedTableFID = fid;
|
|
|
|
cachedTableType = tableType;
|
|
|
|
ASSIGN (cachedTable, table);
|
|
|
|
ASSIGN (cachedFolder, folder);
|
2011-04-05 17:25:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
table = nil;
|
2011-06-07 02:17:46 +02:00
|
|
|
[self errorWithFormat: @"folder with fid %Lu not found",
|
|
|
|
(unsigned long long) fid];
|
2011-04-05 17:25:57 +02:00
|
|
|
}
|
|
|
|
}
|
2010-12-13 18:03:25 +01:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
return table;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
\details Read directory content from the sogo backend
|
|
|
|
|
|
|
|
\param private_data pointer to the current sogo context
|
|
|
|
|
|
|
|
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
|
2010-10-01 22:35:29 +02:00
|
|
|
*/
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) readCount: (uint32_t *) rowCount
|
|
|
|
ofTableType: (uint8_t) tableType
|
|
|
|
inFID: (uint64_t) fid
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
NSArray *keys;
|
2010-10-01 22:35:29 +02:00
|
|
|
NSString *url;
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreFolder *folder;
|
2010-10-01 22:35:29 +02:00
|
|
|
int rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-03-07 20:15:16 +01:00
|
|
|
/* WARNING: make sure this method is no longer invoked for counting
|
|
|
|
table elements */
|
2011-01-06 04:24:06 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' (%d) -- tableType: %d",
|
|
|
|
__FUNCTION__, __LINE__, tableType];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
url = [mapping urlFromID: fid];
|
|
|
|
if (url)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
folder = [self lookupFolderWithFID: fid];
|
2011-02-24 21:32:27 +01:00
|
|
|
if (folder)
|
|
|
|
{
|
|
|
|
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
|
|
|
keys = [folder messageKeys];
|
|
|
|
else if (tableType == MAPISTORE_FOLDER_TABLE)
|
|
|
|
keys = [folder folderKeys];
|
|
|
|
else if (tableType == MAPISTORE_FAI_TABLE)
|
|
|
|
keys = [folder faiMessageKeys];
|
|
|
|
*rowCount = [keys count];
|
|
|
|
rc = MAPI_E_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self errorWithFormat: @"No folder found for URL: %@", url];
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2010-10-14 23:37:39 +02:00
|
|
|
else
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
[self errorWithFormat: @"No url found for FID: %lld", fid];
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2010-12-30 15:18:42 +01:00
|
|
|
// }
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"result: count = %d, rc = %d", *rowCount, rc];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
// - (void) logRestriction: (struct mapi_SRestriction *) res
|
|
|
|
// withState: (MAPIRestrictionState) state
|
|
|
|
// {
|
|
|
|
// NSString *resStr;
|
2010-12-13 18:03:25 +01:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
// resStr = MAPIStringForRestriction (res);
|
2010-12-13 18:03:25 +01:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
// [self logWithFormat: @"%@ --> %@", resStr, MAPIStringForRestrictionState (state)];
|
|
|
|
// }
|
2010-12-03 23:31:56 +01:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (int) setRestrictions: (const struct mapi_SRestriction *) res
|
2010-12-13 18:03:25 +01:00
|
|
|
withFID: (uint64_t) fid
|
2010-12-30 15:18:42 +01:00
|
|
|
andTableType: (uint8_t) tableType
|
2010-12-03 23:31:56 +01:00
|
|
|
getTableStatus: (uint8_t *) tableStatus
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
MAPIStoreTable *table;
|
2010-12-03 23:31:56 +01:00
|
|
|
|
2011-03-07 20:15:16 +01:00
|
|
|
[self errorWithFormat: @"%s: obsolete method", __FUNCTION__];
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
table = [self _tableForFID: fid andTableType: tableType];
|
|
|
|
[table setRestrictions: res];
|
2011-02-24 21:32:27 +01:00
|
|
|
// FIXME: we should not flush the caches if the restrictions matches
|
|
|
|
[table cleanupCaches];
|
|
|
|
|
2010-12-03 23:31:56 +01:00
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:45:34 +01:00
|
|
|
- (int) setSortOrder: (const struct SSortOrderSet *) set
|
|
|
|
withFID: (uint64_t) fid andTableType: (uint8_t) type
|
|
|
|
getTableStatus: (uint8_t *) tableStatus
|
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreTable *table;
|
2011-02-06 17:45:34 +01:00
|
|
|
|
2011-03-07 20:15:16 +01:00
|
|
|
[self errorWithFormat: @"%s: obsolete method", __FUNCTION__];
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
table = [self _tableForFID: fid andTableType: type];
|
2011-02-06 17:45:34 +01:00
|
|
|
[table setSortOrder: set];
|
2011-02-24 21:32:27 +01:00
|
|
|
[table cleanupCaches];
|
2011-02-06 17:45:34 +01:00
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2010-11-30 17:17:50 +01:00
|
|
|
- (enum MAPISTATUS) getTableProperty: (void **) data
|
2010-12-30 15:18:42 +01:00
|
|
|
withTag: (enum MAPITAGS) propTag
|
2010-11-30 17:17:50 +01:00
|
|
|
atPosition: (uint32_t) pos
|
|
|
|
withTableType: (uint8_t) tableType
|
2010-12-13 18:03:25 +01:00
|
|
|
andQueryType: (enum table_query_type) queryType
|
2010-11-30 17:17:50 +01:00
|
|
|
inFID: (uint64_t) fid
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
NSString *folderURL;
|
2010-12-30 15:18:42 +01:00
|
|
|
MAPIStoreTable *table;
|
2011-04-05 17:25:57 +02:00
|
|
|
MAPIStoreObject *object;
|
2010-12-13 18:03:25 +01:00
|
|
|
const char *propName;
|
2010-10-01 22:35:29 +02:00
|
|
|
int rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
// [self errorWithFormat: @"%s: obsolete method", __FUNCTION__];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
folderURL = [mapping urlFromID: fid];
|
|
|
|
if (folderURL)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
table = [self _tableForFID: fid andTableType: tableType];
|
2011-02-24 21:32:27 +01:00
|
|
|
*data = NULL;
|
2011-04-05 17:25:57 +02:00
|
|
|
object = [table childAtRowID: pos forQueryType: queryType];
|
|
|
|
if (object)
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
2011-04-05 17:25:57 +02:00
|
|
|
rc = [object getProperty: data withTag: propTag];
|
2011-02-24 21:32:27 +01:00
|
|
|
if (rc == MAPISTORE_ERR_NOT_FOUND)
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
else if (rc == MAPISTORE_ERR_NO_MEMORY)
|
|
|
|
rc = MAPI_E_NOT_ENOUGH_MEMORY;
|
|
|
|
else if (rc == MAPISTORE_SUCCESS && *data == NULL)
|
|
|
|
{
|
|
|
|
propName = get_proptag_name (propTag);
|
|
|
|
if (!propName)
|
|
|
|
propName = "<unknown>";
|
|
|
|
|
|
|
|
[self errorWithFormat: @"both 'success' and NULL data"
|
|
|
|
@" returned for proptag %s(0x%.8x)",
|
|
|
|
propName, propTag];
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
}
|
|
|
|
}
|
2010-12-03 23:31:56 +01:00
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2010-12-30 15:18:42 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
[self errorWithFormat: @"No url found for FID: %lld", fid];
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
|
|
|
}
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2011-06-07 02:02:54 +02:00
|
|
|
- (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
|
|
|
ofTableType: (uint8_t) type
|
|
|
|
{
|
|
|
|
int rc = MAPISTORE_SUCCESS;
|
|
|
|
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case MAPISTORE_FOLDER_TABLE:
|
|
|
|
[[baseFolder class] getAvailableProperties: propertiesP];
|
|
|
|
break;
|
|
|
|
case MAPISTORE_MESSAGE_TABLE:
|
|
|
|
[[baseFolder messageClass] getAvailableProperties: propertiesP];
|
|
|
|
break;
|
|
|
|
case MAPISTORE_FAI_TABLE:
|
|
|
|
[MAPIStoreFAIMessage getAvailableProperties: propertiesP];
|
|
|
|
break;
|
|
|
|
case MAPISTORE_RULE_TABLE:
|
|
|
|
[self errorWithFormat: @"%s: rules not handled yet",
|
|
|
|
__PRETTY_FUNCTION__];
|
|
|
|
rc = MAPISTORE_ERROR;
|
|
|
|
break;
|
|
|
|
case MAPISTORE_ATTACHMENT_TABLE:
|
|
|
|
[self errorWithFormat: @"%s: attachments not handled yet",
|
|
|
|
__PRETTY_FUNCTION__];
|
|
|
|
rc = MAPISTORE_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) openMessage: (struct mapistore_message *) msg
|
|
|
|
withMID: (uint64_t) mid
|
|
|
|
inFID: (uint64_t) fid
|
2010-10-14 15:22:26 +02:00
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
NSString *messageKey, *messageURL;
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreMessage *message;
|
|
|
|
MAPIStoreFolder *folder;
|
|
|
|
NSNumber *midKey;
|
2011-01-12 01:10:21 +01:00
|
|
|
int rc;
|
2010-10-14 15:22:26 +02:00
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: mid];
|
|
|
|
message = [messages objectForKey: midKey];
|
|
|
|
if (message)
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
2010-10-14 15:22:26 +02:00
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2010-10-14 15:22:26 +02:00
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
messageURL = [mapping urlFromID: mid];
|
|
|
|
if (messageURL)
|
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
folder = [self lookupFolderWithFID: fid];
|
2011-02-24 21:32:27 +01:00
|
|
|
messageKey = [self extractChildNameFromURL: messageURL
|
2011-06-07 02:17:46 +02:00
|
|
|
andFolderURLAt: NULL];
|
2011-02-24 21:32:27 +01:00
|
|
|
message = [folder lookupChild: messageKey];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
[message openMessage: msg];
|
|
|
|
[messages setObject: message forKey: midKey];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[message setMAPIRetainCount: [message mapiRetainCount] + 1];
|
2011-01-12 00:07:41 +01:00
|
|
|
|
2010-10-14 15:22:26 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (int) createMessageWithMID: (uint64_t) mid
|
|
|
|
inFID: (uint64_t) fid
|
|
|
|
isAssociated: (BOOL) isAssociated
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
NSNumber *midKey;
|
2011-06-07 02:17:46 +02:00
|
|
|
NSString *childURL;
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreMessage *message;
|
|
|
|
MAPIStoreFolder *folder;
|
|
|
|
int rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x, associated: %d",
|
|
|
|
__FUNCTION__, mid, fid, isAssociated];
|
|
|
|
|
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: mid];
|
|
|
|
message = [messages objectForKey: midKey];
|
|
|
|
if (message)
|
|
|
|
rc = MAPISTORE_ERR_EXIST;
|
2011-01-12 01:10:21 +01:00
|
|
|
else
|
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
folder = [self lookupFolderWithFID: fid];
|
|
|
|
if (folder)
|
2011-02-24 21:32:27 +01:00
|
|
|
{
|
|
|
|
message = [folder createMessage: isAssociated];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
[messages setObject: message forKey: midKey];
|
|
|
|
[message setMAPIRetainCount: [message mapiRetainCount] + 1];
|
|
|
|
childURL = [NSString stringWithFormat: @"%@%@",
|
2011-06-07 02:17:46 +02:00
|
|
|
[folder url], [message nameInContainer]];
|
2011-02-24 21:32:27 +01:00
|
|
|
[mapping registerURL: childURL withID: mid];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERROR;
|
2010-11-18 23:32:05 +01:00
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
// {
|
|
|
|
// if (![folderURL hasSuffix: @"/"])
|
|
|
|
// folderURL = [NSString stringWithFormat: @"%@/", folderURL];
|
|
|
|
// messageURL = [NSString stringWithFormat: @"%@%@", folderURL,
|
|
|
|
// [message nameInContainer]];
|
|
|
|
// [mapping registerURL: messageURL withID: mid];
|
2010-11-18 23:32:05 +01:00
|
|
|
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
}
|
2010-12-30 15:18:42 +01:00
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2010-11-18 23:32:05 +01:00
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
return rc;
|
2010-11-18 23:32:05 +01:00
|
|
|
}
|
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
- (int) _saveOrSubmitChangesInMessageWithMID: (uint64_t) mid
|
|
|
|
andFlags: (uint8_t) flags
|
|
|
|
save: (BOOL) isSave
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2010-11-18 23:32:05 +01:00
|
|
|
int rc;
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreMessage *message;
|
2011-03-07 20:15:16 +01:00
|
|
|
MAPIStoreFolder *folder;
|
2011-02-24 21:32:27 +01:00
|
|
|
NSNumber *midKey;
|
2011-03-07 20:15:16 +01:00
|
|
|
NSArray *activeTables;
|
|
|
|
NSUInteger count, max;
|
|
|
|
// NSArray *propKeys;
|
|
|
|
struct mapistore_object_notification_parameters *notif_parameters;
|
|
|
|
// uint16_t count, max;
|
|
|
|
uint64_t folderId;
|
2010-11-18 23:32:05 +01:00
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: mid];
|
|
|
|
message = [messages objectForKey: midKey];
|
|
|
|
if (message)
|
2010-11-18 23:32:05 +01:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
2011-03-07 20:15:16 +01:00
|
|
|
folder = (MAPIStoreFolder *) [message container];
|
2011-06-07 02:17:46 +02:00
|
|
|
[self logWithFormat: @"folder for message is: %p", folder];
|
2011-02-24 21:32:27 +01:00
|
|
|
if (isSave)
|
2011-03-07 20:15:16 +01:00
|
|
|
{
|
|
|
|
/* notifications */
|
|
|
|
folderId = [folder objectId];
|
|
|
|
|
|
|
|
/* folder modified */
|
|
|
|
notif_parameters
|
|
|
|
= talloc_zero(memCtx,
|
|
|
|
struct mapistore_object_notification_parameters);
|
|
|
|
notif_parameters->object_id = folderId;
|
|
|
|
if ([message isNew])
|
|
|
|
{
|
|
|
|
notif_parameters->tag_count = 3;
|
|
|
|
notif_parameters->tags = talloc_array (notif_parameters,
|
|
|
|
enum MAPITAGS, 3);
|
|
|
|
notif_parameters->tags[0] = PR_CONTENT_COUNT;
|
|
|
|
notif_parameters->tags[1] = PR_MESSAGE_SIZE;
|
|
|
|
notif_parameters->tags[2] = PR_NORMAL_MESSAGE_SIZE;
|
|
|
|
notif_parameters->new_message_count = true;
|
|
|
|
notif_parameters->message_count = [[folder messageKeys] count] + 1;
|
|
|
|
}
|
2011-06-06 23:58:46 +02:00
|
|
|
mapistore_push_notification (connInfo->mstore_ctx,
|
|
|
|
MAPISTORE_FOLDER,
|
2011-03-07 20:15:16 +01:00
|
|
|
MAPISTORE_OBJECT_MODIFIED,
|
|
|
|
notif_parameters);
|
|
|
|
|
|
|
|
/* message created */
|
|
|
|
if ([message isNew])
|
|
|
|
{
|
|
|
|
notif_parameters
|
|
|
|
= talloc_zero(memCtx,
|
|
|
|
struct mapistore_object_notification_parameters);
|
|
|
|
notif_parameters->object_id = [message objectId];
|
|
|
|
notif_parameters->folder_id = folderId;
|
|
|
|
|
|
|
|
notif_parameters->tag_count = 0xffff;
|
2011-06-06 23:58:46 +02:00
|
|
|
mapistore_push_notification (connInfo->mstore_ctx,
|
|
|
|
MAPISTORE_MESSAGE,
|
2011-03-07 20:15:16 +01:00
|
|
|
MAPISTORE_OBJECT_CREATED,
|
|
|
|
notif_parameters);
|
|
|
|
talloc_free (notif_parameters);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we ensure the table caches are loaded so that old and new state
|
|
|
|
can be compared */
|
|
|
|
activeTables = ([message isKindOfClass: MAPIStoreFAIMessageK]
|
|
|
|
? [folder activeFAIMessageTables]
|
|
|
|
: [folder activeMessageTables]);
|
|
|
|
max = [activeTables count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
[[activeTables objectAtIndex: count] restrictedChildKeys];
|
|
|
|
|
|
|
|
[message save];
|
|
|
|
|
|
|
|
/* table modified */
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
[[activeTables objectAtIndex: count]
|
|
|
|
notifyChangesForChild: message];
|
|
|
|
}
|
2010-11-18 23:32:05 +01:00
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
[message submit];
|
2011-03-07 20:15:16 +01:00
|
|
|
[message setIsNew: NO];
|
|
|
|
[message resetNewProperties];
|
|
|
|
[folder cleanupCaches];
|
2010-11-18 23:32:05 +01:00
|
|
|
}
|
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPISTORE_ERROR;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-11-18 23:32:05 +01:00
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
- (int) saveChangesInMessageWithMID: (uint64_t) mid
|
|
|
|
andFlags: (uint8_t) flags
|
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, flags: 0x%x",
|
|
|
|
__FUNCTION__, mid, flags];
|
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
return [self _saveOrSubmitChangesInMessageWithMID: mid
|
|
|
|
andFlags: flags
|
|
|
|
save: YES];
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) submitMessageWithMID: (uint64_t) mid
|
|
|
|
andFlags: (uint8_t) flags
|
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, flags: 0x%x",
|
|
|
|
__FUNCTION__, mid, flags];
|
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
return [self _saveOrSubmitChangesInMessageWithMID: mid
|
|
|
|
andFlags: flags
|
|
|
|
save: NO];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-10-14 18:38:15 +02:00
|
|
|
- (int) getProperties: (struct SPropTagArray *) sPropTagArray
|
2010-11-19 22:14:53 +01:00
|
|
|
ofTableType: (uint8_t) tableType
|
2010-10-01 20:54:30 +02:00
|
|
|
inRow: (struct SRow *) aRow
|
|
|
|
withMID: (uint64_t) fmid
|
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
NSNumber *midKey;
|
|
|
|
MAPIStoreObject *child;
|
2010-12-30 15:18:42 +01:00
|
|
|
NSInteger count;
|
|
|
|
void *propValue;
|
|
|
|
const char *propName;
|
|
|
|
enum MAPITAGS tag;
|
|
|
|
enum MAPISTATUS propRc;
|
2011-02-24 21:32:27 +01:00
|
|
|
struct mapistore_property_data *data;
|
2010-10-14 18:38:15 +02:00
|
|
|
int rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' -- fmid: 0x%.16x, tableType: %d",
|
|
|
|
__FUNCTION__, fmid, tableType];
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: fmid];
|
|
|
|
child = [messages objectForKey: midKey];
|
|
|
|
if (child)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
data = talloc_array (memCtx, struct mapistore_property_data,
|
|
|
|
sPropTagArray->cValues);
|
|
|
|
memset (data, 0,
|
|
|
|
sizeof (struct mapistore_property_data) * sPropTagArray->cValues);
|
|
|
|
rc = [child getProperties: data
|
|
|
|
withTags: sPropTagArray->aulPropTag
|
|
|
|
andCount: sPropTagArray->cValues];
|
|
|
|
if (rc == MAPISTORE_SUCCESS)
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
aRow->lpProps = talloc_array (aRow, struct SPropValue,
|
|
|
|
sPropTagArray->cValues);
|
2011-02-12 05:33:24 +01:00
|
|
|
aRow->cValues = sPropTagArray->cValues;
|
2010-12-30 15:18:42 +01:00
|
|
|
for (count = 0; count < sPropTagArray->cValues; count++)
|
|
|
|
{
|
|
|
|
tag = sPropTagArray->aulPropTag[count];
|
2011-02-24 21:32:27 +01:00
|
|
|
propValue = data[count].data;
|
|
|
|
propRc = data[count].error;
|
2010-12-30 15:18:42 +01:00
|
|
|
// propName = get_proptag_name (tag);
|
|
|
|
// if (!propName)
|
|
|
|
// propName = "<unknown>";
|
|
|
|
// [self logWithFormat: @" lookup of property %s (%.8x) returned %d",
|
|
|
|
// propName, tag, propRc];
|
|
|
|
|
|
|
|
if (propRc == MAPI_E_SUCCESS && !propValue)
|
|
|
|
{
|
|
|
|
propName = get_proptag_name (tag);
|
|
|
|
if (!propName)
|
|
|
|
propName = "<unknown>";
|
|
|
|
[self errorWithFormat: @"both 'success' and NULL data"
|
|
|
|
@" returned for proptag %s(0x%.8x)",
|
|
|
|
propName, tag];
|
|
|
|
propRc = MAPI_E_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (propRc != MAPI_E_SUCCESS)
|
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
if (propRc == MAPISTORE_ERR_NOT_FOUND)
|
|
|
|
propRc = MAPI_E_NOT_FOUND;
|
2011-04-20 00:22:26 +02:00
|
|
|
// else if (propRc == MAPISTORE_ERR_NO_MEMORY)
|
|
|
|
// propRc = MAPI_E_NOT_ENOUGH_MEMORY;
|
2010-12-30 15:18:42 +01:00
|
|
|
if (propValue)
|
|
|
|
talloc_free (propValue);
|
|
|
|
propValue = MAPILongValue (memCtx, propRc);
|
|
|
|
tag = (tag & 0xffff0000) | 0x000a;
|
|
|
|
}
|
2011-04-20 00:22:26 +02:00
|
|
|
set_SPropValue_proptag (aRow->lpProps + count, tag, propValue);
|
2010-12-30 15:18:42 +01:00
|
|
|
}
|
|
|
|
}
|
2011-02-24 21:32:27 +01:00
|
|
|
talloc_free (data);
|
2010-10-14 18:38:15 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
[self errorWithFormat: @"no message/folder found for fmid %lld", fmid];
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
2010-11-18 23:32:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-10-13 23:40:50 +02:00
|
|
|
- (int) getPath: (char **) path
|
|
|
|
ofFMID: (uint64_t) fmid
|
|
|
|
withTableType: (uint8_t) tableType
|
|
|
|
{
|
|
|
|
int rc;
|
2011-03-07 22:33:13 +01:00
|
|
|
NSString *objectURL, *url;
|
2010-10-15 19:24:09 +02:00
|
|
|
// TDB_DATA key, dbuf;
|
2010-10-13 23:40:50 +02:00
|
|
|
|
2011-03-07 22:33:13 +01:00
|
|
|
url = [contextUrl absoluteString];
|
2010-10-13 23:40:50 +02:00
|
|
|
objectURL = [mapping urlFromID: fmid];
|
|
|
|
if (objectURL)
|
|
|
|
{
|
2011-03-07 22:33:13 +01:00
|
|
|
if ([objectURL hasPrefix: url])
|
2010-10-15 19:24:09 +02:00
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
*path = [[objectURL substringFromIndex: 7]
|
|
|
|
asUnicodeInMemCtx: memCtx];
|
2011-01-14 14:13:32 +01:00
|
|
|
[self logWithFormat: @"found path '%s' for fmid %.16x",
|
2011-06-30 21:08:20 +02:00
|
|
|
*path, fmid];
|
2011-06-06 23:58:46 +02:00
|
|
|
rc = MAPI_E_SUCCESS;
|
2010-10-15 19:24:09 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-14 14:13:32 +01:00
|
|
|
[self logWithFormat: @"context (%@, %@) does not contain"
|
|
|
|
@" found fmid: 0x%.16x",
|
2011-03-07 22:33:13 +01:00
|
|
|
objectURL, url, fmid];
|
2010-10-15 19:24:09 +02:00
|
|
|
*path = NULL;
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
}
|
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__];
|
|
|
|
// /* attempt to populate our mapping dict with data from indexing.tdb */
|
|
|
|
// key.dptr = (unsigned char *) talloc_asprintf (memCtx, "0x%.16llx",
|
|
|
|
// (long long unsigned int )fmid);
|
|
|
|
// key.dsize = strlen ((const char *) key.dptr);
|
|
|
|
|
|
|
|
// dbuf = tdb_fetch (memCtx->indexing_list->index_ctx->tdb, key);
|
|
|
|
// talloc_free (key.dptr);
|
|
|
|
// uri = talloc_strndup (memCtx, (const char *)dbuf.dptr, dbuf.dsize);
|
|
|
|
*path = NULL;
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
2010-10-13 23:40:50 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) getFID: (uint64_t *) fid
|
|
|
|
byName: (const char *) foldername
|
|
|
|
inParentFID: (uint64_t) parent_fid
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
[self logWithFormat: @"METHOD '%s' (%d) -- foldername: %s, parent_fid: %lld",
|
|
|
|
__FUNCTION__, __LINE__, foldername, parent_fid];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-14 15:22:26 +02:00
|
|
|
return MAPISTORE_ERROR;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-11-06 00:27:08 +01:00
|
|
|
- (int) setPropertiesWithFMID: (uint64_t) fmid
|
2010-11-19 22:14:53 +01:00
|
|
|
ofTableType: (uint8_t) tableType
|
2010-11-06 00:27:08 +01:00
|
|
|
inRow: (struct SRow *) aRow
|
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreMessage *message;
|
2011-06-07 02:17:46 +02:00
|
|
|
MAPIStoreFolder *folder;
|
2011-02-24 21:32:27 +01:00
|
|
|
NSMutableDictionary *properties;
|
|
|
|
NSNumber *midKey;
|
2010-11-24 20:28:45 +01:00
|
|
|
struct SPropValue *cValue;
|
|
|
|
NSUInteger counter;
|
2010-11-06 00:27:08 +01:00
|
|
|
int rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' -- fmid: 0x%.16x, tableType: %d",
|
|
|
|
__FUNCTION__, fmid, tableType];
|
|
|
|
|
2010-11-19 22:14:53 +01:00
|
|
|
switch (tableType)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
|
|
|
case MAPISTORE_MESSAGE:
|
2011-02-24 21:32:27 +01:00
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: fmid];
|
|
|
|
message = [messages objectForKey: midKey];
|
2010-11-06 00:27:08 +01:00
|
|
|
if (message)
|
2010-11-24 20:28:45 +01:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
properties
|
|
|
|
= [NSMutableDictionary dictionaryWithCapacity: aRow->cValues];
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"fmid 0x%.16x found", fmid];
|
2010-11-24 20:28:45 +01:00
|
|
|
for (counter = 0; counter < aRow->cValues; counter++)
|
|
|
|
{
|
2011-01-12 00:07:41 +01:00
|
|
|
cValue = aRow->lpProps + counter;
|
2011-02-24 21:32:27 +01:00
|
|
|
[properties setObject: NSObjectFromSPropValue (cValue)
|
|
|
|
forKey: MAPIPropertyKey (cValue->ulPropTag)];
|
2010-11-24 20:28:45 +01:00
|
|
|
}
|
2011-02-24 21:32:27 +01:00
|
|
|
[message addNewProperties: properties];
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"(%s) message props after op", __PRETTY_FUNCTION__];
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreDumpMessageProperties (properties);
|
2010-11-24 20:28:45 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
2010-11-06 00:27:08 +01:00
|
|
|
else
|
2010-12-13 18:03:25 +01:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
[self errorWithFormat: @"fmid 0x%.16x *not* found (faking success)",
|
|
|
|
fmid];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
2010-12-13 18:03:25 +01:00
|
|
|
}
|
2010-11-26 22:48:52 +01:00
|
|
|
break;
|
|
|
|
case MAPISTORE_FOLDER:
|
2011-06-07 02:17:46 +02:00
|
|
|
folder = [self lookupFolderWithFID: fmid];
|
|
|
|
if (folder)
|
|
|
|
rc = [folder setProperties: aRow];
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2011-04-05 17:25:57 +02:00
|
|
|
break;
|
2010-11-26 22:48:52 +01:00
|
|
|
default:
|
|
|
|
[self errorWithFormat: @"%s: value of tableType not handled: %d",
|
|
|
|
__FUNCTION__, tableType];
|
|
|
|
rc = MAPISTORE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-11-24 20:28:45 +01:00
|
|
|
- (NSDictionary *) _convertRecipientFromRow: (struct RecipientRow *) row
|
|
|
|
{
|
|
|
|
NSMutableDictionary *recipient;
|
|
|
|
NSString *value;
|
2011-03-08 14:35:44 +01:00
|
|
|
SOGoUser *recipientUser;
|
2010-11-24 20:28:45 +01:00
|
|
|
|
|
|
|
recipient = [NSMutableDictionary dictionaryWithCapacity: 5];
|
|
|
|
|
|
|
|
if ((row->RecipientFlags & 0x07) == 1)
|
|
|
|
{
|
|
|
|
value = [NSString stringWithUTF8String: row->X500DN.recipient_x500name];
|
|
|
|
[recipient setObject: value forKey: @"x500dn"];
|
|
|
|
|
2011-03-08 14:35:44 +01:00
|
|
|
recipientUser = [SOGoUser userWithLogin: [value lowercaseString]];
|
|
|
|
if (recipientUser)
|
|
|
|
{
|
|
|
|
value = [recipientUser cn];
|
|
|
|
if ([value length] > 0)
|
|
|
|
[recipient setObject: value forKey: @"fullName"];
|
|
|
|
value = [[recipientUser allEmails] objectAtIndex: 0];
|
|
|
|
if ([value length] > 0)
|
|
|
|
[recipient setObject: value forKey: @"email"];
|
|
|
|
}
|
2010-11-24 20:28:45 +01:00
|
|
|
}
|
2011-03-08 14:35:44 +01:00
|
|
|
else
|
2010-11-24 20:28:45 +01:00
|
|
|
{
|
2011-03-08 14:35:44 +01:00
|
|
|
switch ((row->RecipientFlags & 0x208))
|
|
|
|
{
|
|
|
|
case 0x08:
|
|
|
|
// TODO: we cheat
|
|
|
|
value = [NSString stringWithUTF8String: row->EmailAddress.lpszA];
|
|
|
|
break;
|
|
|
|
case 0x208:
|
|
|
|
value = [NSString stringWithUTF8String: row->EmailAddress.lpszW];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
value = nil;
|
|
|
|
}
|
|
|
|
if (value)
|
|
|
|
[recipient setObject: value forKey: @"email"];
|
|
|
|
|
|
|
|
switch ((row->RecipientFlags & 0x210))
|
|
|
|
{
|
|
|
|
case 0x10:
|
|
|
|
// TODO: we cheat
|
|
|
|
value = [NSString stringWithUTF8String: row->DisplayName.lpszA];
|
|
|
|
break;
|
|
|
|
case 0x210:
|
|
|
|
value = [NSString stringWithUTF8String: row->DisplayName.lpszW];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
value = nil;
|
|
|
|
}
|
|
|
|
if (value)
|
|
|
|
[recipient setObject: value forKey: @"fullName"];
|
2010-11-24 20:28:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return recipient;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) modifyRecipientsWithMID: (uint64_t) mid
|
|
|
|
inRows: (struct ModifyRecipientRow *) rows
|
|
|
|
withCount: (NSUInteger) max
|
|
|
|
{
|
|
|
|
static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreMessage *message;
|
|
|
|
NSDictionary *newProperties;
|
|
|
|
NSMutableDictionary *recipients;
|
2010-11-24 20:28:45 +01:00
|
|
|
NSMutableArray *list;
|
|
|
|
NSString *recType;
|
|
|
|
struct ModifyRecipientRow *currentRow;
|
|
|
|
NSUInteger count;
|
|
|
|
int rc;
|
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x", __FUNCTION__, mid];
|
|
|
|
|
2010-11-24 20:28:45 +01:00
|
|
|
message = [messages
|
|
|
|
objectForKey: [NSNumber numberWithUnsignedLongLong: mid]];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
recipients = [NSMutableDictionary new];
|
2011-02-24 21:32:27 +01:00
|
|
|
newProperties = [NSDictionary dictionaryWithObject: recipients
|
|
|
|
forKey: @"recipients"];
|
2010-11-24 20:28:45 +01:00
|
|
|
[recipients release];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentRow = rows + count;
|
2011-02-03 23:39:02 +01:00
|
|
|
|
|
|
|
if (currentRow->RecipClass >= MAPI_ORIG
|
|
|
|
&& currentRow->RecipClass < MAPI_BCC)
|
2010-11-24 20:28:45 +01:00
|
|
|
{
|
|
|
|
recType = recTypes[currentRow->RecipClass];
|
|
|
|
list = [recipients objectForKey: recType];
|
|
|
|
if (!list)
|
|
|
|
{
|
|
|
|
list = [NSMutableArray new];
|
|
|
|
[recipients setObject: list forKey: recType];
|
|
|
|
[list release];
|
|
|
|
}
|
|
|
|
[list addObject: [self _convertRecipientFromRow:
|
|
|
|
&(currentRow->RecipientRow)]];
|
|
|
|
}
|
|
|
|
}
|
2011-02-24 21:32:27 +01:00
|
|
|
[message addNewProperties: newProperties];
|
2010-11-24 20:28:45 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) deleteMessageWithMID: (uint64_t) mid
|
2011-02-03 23:39:02 +01:00
|
|
|
inFID: (uint64_t) fid
|
2010-10-01 20:54:30 +02:00
|
|
|
withFlags: (uint8_t) flags
|
|
|
|
{
|
2011-06-07 02:17:46 +02:00
|
|
|
NSString *childURL, *childKey;
|
2011-02-24 21:32:27 +01:00
|
|
|
MAPIStoreFolder *folder;
|
|
|
|
MAPIStoreMessage *message;
|
2011-03-07 20:15:16 +01:00
|
|
|
NSArray *activeTables;
|
|
|
|
NSUInteger count, max;
|
|
|
|
struct mapistore_object_notification_parameters *notif_parameters;
|
2011-02-03 23:39:02 +01:00
|
|
|
int rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-02-03 23:39:02 +01:00
|
|
|
[self logWithFormat: @"-deleteMessageWithMID: mid: 0x%.16x flags: %d", mid, flags];
|
|
|
|
|
|
|
|
childURL = [mapping urlFromID: mid];
|
|
|
|
if (childURL)
|
|
|
|
{
|
|
|
|
[self logWithFormat: @"-deleteMessageWithMID: url (%@) found for object", childURL];
|
|
|
|
|
2011-06-07 02:17:46 +02:00
|
|
|
folder = [self lookupFolderWithFID: fid];
|
|
|
|
|
2011-02-03 23:39:02 +01:00
|
|
|
childKey = [self extractChildNameFromURL: childURL
|
2011-06-07 02:17:46 +02:00
|
|
|
andFolderURLAt: NULL];
|
2011-02-24 21:32:27 +01:00
|
|
|
message = [folder lookupChild: childKey];
|
2011-02-03 23:39:02 +01:00
|
|
|
if (message)
|
|
|
|
{
|
2011-03-07 20:15:16 +01:00
|
|
|
/* we ensure the table caches are loaded so that old and new state
|
|
|
|
can be compared */
|
|
|
|
/* we ensure the table caches are loaded so that old and new state
|
|
|
|
can be compared */
|
|
|
|
activeTables = ([message isKindOfClass: MAPIStoreFAIMessageK]
|
|
|
|
? [folder activeFAIMessageTables]
|
|
|
|
: [folder activeMessageTables]);
|
|
|
|
max = [activeTables count];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
[[activeTables objectAtIndex: count] restrictedChildKeys];
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
if ([[message sogoObject] delete])
|
2011-02-03 23:39:02 +01:00
|
|
|
{
|
|
|
|
rc = MAPISTORE_ERROR;
|
|
|
|
[self logWithFormat: @"ERROR deleting object at URL: %@", childURL];
|
|
|
|
}
|
2011-03-07 20:15:16 +01:00
|
|
|
else
|
2011-02-03 23:39:02 +01:00
|
|
|
{
|
2011-03-07 20:15:16 +01:00
|
|
|
if (![message isNew])
|
|
|
|
{
|
|
|
|
/* folder notification */
|
|
|
|
notif_parameters
|
|
|
|
= talloc_zero(memCtx,
|
|
|
|
struct mapistore_object_notification_parameters);
|
|
|
|
notif_parameters->object_id = fid;
|
|
|
|
notif_parameters->tag_count = 5;
|
|
|
|
notif_parameters->tags = talloc_array (notif_parameters,
|
|
|
|
enum MAPITAGS, 5);
|
|
|
|
notif_parameters->tags[0] = PR_CONTENT_COUNT;
|
|
|
|
notif_parameters->tags[1] = PR_DELETED_COUNT_TOTAL;
|
|
|
|
notif_parameters->tags[2] = PR_MESSAGE_SIZE;
|
|
|
|
notif_parameters->tags[3] = PR_NORMAL_MESSAGE_SIZE;
|
|
|
|
notif_parameters->tags[4] = PR_DELETED_MSG_COUNT;
|
|
|
|
notif_parameters->new_message_count = true;
|
|
|
|
notif_parameters->message_count = [[folder messageKeys]
|
|
|
|
count] - 1;
|
2011-06-06 23:58:46 +02:00
|
|
|
mapistore_push_notification (connInfo->mstore_ctx,
|
|
|
|
MAPISTORE_FOLDER,
|
2011-03-07 20:15:16 +01:00
|
|
|
MAPISTORE_OBJECT_MODIFIED,
|
|
|
|
notif_parameters);
|
|
|
|
talloc_free(notif_parameters);
|
|
|
|
|
|
|
|
/* message notification */
|
|
|
|
notif_parameters
|
|
|
|
= talloc_zero(memCtx,
|
|
|
|
struct mapistore_object_notification_parameters);
|
|
|
|
notif_parameters->object_id = mid;
|
|
|
|
notif_parameters->folder_id = fid;
|
|
|
|
/* Exchange sends a fnevObjectCreated!! */
|
2011-06-06 23:58:46 +02:00
|
|
|
mapistore_push_notification (connInfo->mstore_ctx,
|
|
|
|
MAPISTORE_MESSAGE,
|
2011-03-07 20:15:16 +01:00
|
|
|
MAPISTORE_OBJECT_CREATED,
|
|
|
|
notif_parameters);
|
|
|
|
talloc_free(notif_parameters);
|
|
|
|
|
|
|
|
/* table notification */
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
[[activeTables objectAtIndex: count]
|
|
|
|
notifyChangesForChild: message];
|
|
|
|
}
|
2011-06-07 02:17:46 +02:00
|
|
|
[self logWithFormat: @"successfully deleted object at URL: %@", childURL];
|
2011-02-03 23:39:02 +01:00
|
|
|
[mapping unregisterURLWithID: mid];
|
2011-03-07 20:15:16 +01:00
|
|
|
[folder cleanupCaches];
|
2011-02-03 23:39:02 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
- (int) releaseRecordWithFMID: (uint64_t) fmid
|
|
|
|
ofTableType: (uint8_t) tableType
|
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
NSNumber *midKey;
|
|
|
|
MAPIStoreMessage *message;
|
2011-01-12 01:10:21 +01:00
|
|
|
NSUInteger retainCount;
|
|
|
|
int rc;
|
2010-12-13 18:03:25 +01:00
|
|
|
|
|
|
|
switch (tableType)
|
|
|
|
{
|
|
|
|
case MAPISTORE_MESSAGE_TABLE:
|
2010-12-14 21:58:19 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
2011-02-24 21:32:27 +01:00
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: fmid];
|
|
|
|
message = [messages objectForKey: midKey];
|
|
|
|
if (message)
|
2010-12-13 18:03:25 +01:00
|
|
|
{
|
2011-02-24 21:32:27 +01:00
|
|
|
retainCount = [message mapiRetainCount];
|
|
|
|
if (retainCount == 0)
|
2011-01-12 01:10:21 +01:00
|
|
|
{
|
|
|
|
[self logWithFormat: @"message with mid %.16x successfully removed"
|
|
|
|
@" from message cache",
|
|
|
|
fmid];
|
2011-02-24 21:32:27 +01:00
|
|
|
[messages removeObjectForKey: midKey];
|
2011-01-12 01:10:21 +01:00
|
|
|
}
|
|
|
|
else
|
2011-02-24 21:32:27 +01:00
|
|
|
[message setMAPIRetainCount: retainCount - 1];
|
2010-12-13 18:03:25 +01:00
|
|
|
}
|
|
|
|
else
|
2010-12-14 21:58:19 +01:00
|
|
|
[self warnWithFormat: @"message with mid %.16x not found"
|
|
|
|
@" in message cache", fmid];
|
2010-12-13 18:03:25 +01:00
|
|
|
break;
|
|
|
|
case MAPISTORE_FOLDER_TABLE:
|
|
|
|
default:
|
|
|
|
[self errorWithFormat: @"%s: value of tableType not handled: %d",
|
|
|
|
__FUNCTION__, tableType];
|
|
|
|
[self logWithFormat: @" fmid: 0x%.16x tableType: %d", fmid, tableType];
|
|
|
|
|
|
|
|
rc = MAPISTORE_ERR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-11-30 22:04:05 +01:00
|
|
|
/* utils */
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (NSString *) extractChildNameFromURL: (NSString *) objectURL
|
|
|
|
andFolderURLAt: (NSString **) folderURL;
|
|
|
|
{
|
|
|
|
NSString *childKey;
|
|
|
|
NSRange lastSlash;
|
|
|
|
NSUInteger slashPtr;
|
|
|
|
|
|
|
|
if ([objectURL hasSuffix: @"/"])
|
|
|
|
objectURL = [objectURL substringToIndex: [objectURL length] - 2];
|
|
|
|
lastSlash = [objectURL rangeOfString: @"/"
|
|
|
|
options: NSBackwardsSearch];
|
|
|
|
if (lastSlash.location != NSNotFound)
|
|
|
|
{
|
|
|
|
slashPtr = NSMaxRange (lastSlash);
|
|
|
|
childKey = [objectURL substringFromIndex: slashPtr];
|
|
|
|
if ([childKey length] == 0)
|
|
|
|
childKey = nil;
|
|
|
|
if (folderURL)
|
|
|
|
*folderURL = [objectURL substringToIndex: slashPtr];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
childKey = nil;
|
|
|
|
|
|
|
|
return childKey;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (uint64_t) idForObjectWithKey: (NSString *) key
|
|
|
|
inFolderURL: (NSString *) folderURL
|
|
|
|
{
|
|
|
|
NSString *childURL;
|
|
|
|
uint64_t mappingId;
|
|
|
|
uint32_t contextId;
|
|
|
|
|
|
|
|
if (key)
|
|
|
|
childURL = [NSString stringWithFormat: @"%@%@", folderURL, key];
|
|
|
|
else
|
|
|
|
childURL = folderURL;
|
|
|
|
mappingId = [mapping idFromURL: childURL];
|
|
|
|
if (mappingId == NSNotFound)
|
|
|
|
{
|
2011-06-30 21:08:20 +02:00
|
|
|
openchangedb_get_new_folderID (connInfo->oc_ctx, &mappingId);
|
2011-02-24 21:32:27 +01:00
|
|
|
[mapping registerURL: childURL withID: mappingId];
|
|
|
|
contextId = 0;
|
|
|
|
mapistore_search_context_by_uri (memCtx, [folderURL UTF8String] + 7,
|
|
|
|
&contextId);
|
|
|
|
mapistore_indexing_record_add_mid (memCtx, contextId, mappingId);
|
|
|
|
}
|
|
|
|
|
|
|
|
return mappingId;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* proof of concept */
|
2011-03-07 20:15:16 +01:00
|
|
|
- (int) getTable: (void **) tablePtr
|
|
|
|
andRowCount: (uint32_t *) countPtr
|
|
|
|
withFID: (uint64_t) fid
|
|
|
|
tableType: (uint8_t) tableType
|
|
|
|
andHandleId: (uint32_t) handleId
|
|
|
|
{
|
|
|
|
MAPIStoreTable *table;
|
|
|
|
|
|
|
|
table = [self _tableForFID: fid andTableType: tableType];
|
|
|
|
[table retain];
|
|
|
|
[table setHandleId: handleId];
|
|
|
|
*countPtr = [[table childKeys] count];
|
|
|
|
*tablePtr = table;
|
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-02-24 21:32:27 +01:00
|
|
|
- (int) getAttachmentTable: (void **) tablePtr
|
|
|
|
andRowCount: (uint32_t *) count
|
|
|
|
withMID: (uint64_t) mid
|
|
|
|
{
|
|
|
|
MAPIStoreAttachmentTable *attTable;
|
|
|
|
MAPIStoreMessage *message;
|
|
|
|
NSNumber *midKey;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: mid];
|
|
|
|
message = [messages objectForKey: midKey];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
*count = [[message childKeysMatchingQualifier: nil
|
2011-03-22 22:21:55 +01:00
|
|
|
andSortOrderings: nil] count];
|
2011-02-24 21:32:27 +01:00
|
|
|
attTable = [message attachmentTable];
|
|
|
|
if (attTable)
|
|
|
|
{
|
|
|
|
[attTable retain];
|
2011-06-07 02:17:46 +02:00
|
|
|
*tablePtr = attTable;
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) getAttachment: (void **) attachmentPtr
|
|
|
|
withAID: (uint32_t) aid
|
|
|
|
inMID: (uint64_t) mid
|
|
|
|
{
|
|
|
|
MAPIStoreMessage *message;
|
|
|
|
MAPIStoreAttachment *attachment;
|
|
|
|
NSNumber *midKey;
|
|
|
|
NSArray *keys;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: mid];
|
|
|
|
message = [messages objectForKey: midKey];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
keys = [message childKeysMatchingQualifier: nil
|
|
|
|
andSortOrderings: nil];
|
|
|
|
if (aid < [keys count])
|
|
|
|
{
|
|
|
|
attachment = [message lookupChild: [keys objectAtIndex: aid]];
|
|
|
|
if (attachment)
|
|
|
|
{
|
|
|
|
[attachment retain];
|
2011-06-07 02:17:46 +02:00
|
|
|
*attachmentPtr = attachment;
|
2011-02-24 21:32:27 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) createAttachment: (void **) attachmentPtr
|
|
|
|
inAID: (uint32_t *) aid
|
|
|
|
withMessage: (uint64_t) mid
|
|
|
|
{
|
|
|
|
MAPIStoreMessage *message;
|
|
|
|
MAPIStoreAttachment *attachment;
|
|
|
|
NSNumber *midKey;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
midKey = [NSNumber numberWithUnsignedLongLong: mid];
|
|
|
|
message = [messages objectForKey: midKey];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
attachment = [message createAttachment];
|
|
|
|
if (attachment)
|
|
|
|
{
|
|
|
|
[attachment retain];
|
|
|
|
*attachmentPtr = attachment;
|
|
|
|
*aid = [attachment AID];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* subclasses */
|
|
|
|
|
|
|
|
+ (NSString *) MAPIModuleName
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setupBaseFolder: (NSURL *) newURL
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
@end
|