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>
|
2010-11-26 22:48:52 +01:00
|
|
|
#import <Foundation/NSFileHandle.h>
|
2010-10-01 20:54:30 +02:00
|
|
|
#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/NSString+misc.h>
|
|
|
|
#import <NGExtensions/NSObject+Logs.h>
|
|
|
|
|
|
|
|
#import <SOGo/NSString+Utilities.h>
|
|
|
|
#import <Mailer/SOGoMailAccount.h>
|
|
|
|
#import <Mailer/SOGoMailFolder.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"
|
|
|
|
#import "MAPIStoreAuthenticator.h"
|
2010-12-30 15:18:42 +01:00
|
|
|
#import "MAPIStoreFolderTable.h"
|
|
|
|
#import "MAPIStoreFAIMessageTable.h"
|
2010-10-01 20:54:30 +02:00
|
|
|
#import "MAPIStoreMapping.h"
|
2010-11-19 22:14:53 +01:00
|
|
|
#import "MAPIStoreTypes.h"
|
2010-12-30 15:18:42 +01:00
|
|
|
#import "NSArray+MAPIStore.h"
|
|
|
|
#import "NSString+MAPIStore.h"
|
2010-10-01 20:54:30 +02:00
|
|
|
|
|
|
|
#import "MAPIStoreContext.h"
|
|
|
|
|
|
|
|
#undef DEBUG
|
|
|
|
#include <mapistore/mapistore.h>
|
|
|
|
#include <mapistore/mapistore_errors.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
|
|
|
@interface SOGoFolder (MAPIStoreProtocol)
|
|
|
|
|
|
|
|
- (BOOL) create;
|
|
|
|
- (NSException *) delete;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface SOGoObject (MAPIStoreProtocol)
|
|
|
|
|
2010-11-18 23:32:05 +01:00
|
|
|
- (void) setMAPIProperties: (NSDictionary *) properties;
|
2010-11-22 22:32:11 +01:00
|
|
|
- (void) MAPISave;
|
|
|
|
- (void) MAPISubmit;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation MAPIStoreContext : NSObject
|
|
|
|
|
|
|
|
/* sogo://username:password@{contacts,calendar,tasks,journal,notes,mail}/dossier/id */
|
|
|
|
|
2010-11-19 22:14:53 +01:00
|
|
|
static Class SOGoObjectK, SOGoMailAccountK, SOGoMailFolderK;
|
2010-12-13 18:03:25 +01:00
|
|
|
static Class NSArrayK, NSDataK, NSStringK;
|
2010-11-19 22:14:53 +01:00
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
static MAPIStoreMapping *mapping;
|
|
|
|
static NSMutableDictionary *contextClassMapping;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
2010-11-22 22:32:11 +01:00
|
|
|
NSArray *classes;
|
|
|
|
Class currentClass;
|
|
|
|
NSUInteger count, max;
|
|
|
|
NSString *moduleName;
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
SOGoObjectK = [SOGoObject class];
|
2010-11-19 22:14:53 +01:00
|
|
|
SOGoMailAccountK = [SOGoMailAccount class];
|
|
|
|
SOGoMailFolderK = [SOGoMailFolder class];
|
2010-11-22 17:03:30 +01:00
|
|
|
NSArrayK = [NSArray class];
|
2010-12-13 18:03:25 +01:00
|
|
|
NSDataK = [NSData class];
|
|
|
|
NSStringK = [NSString class];
|
|
|
|
|
2010-10-15 19:24:09 +02:00
|
|
|
mapping = [MAPIStoreMapping sharedMapping];
|
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
|
|
|
}
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
+ (NSString *) MAPIModuleName
|
2010-11-22 17:03:30 +01:00
|
|
|
{
|
2010-11-22 22:32:11 +01:00
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return nil;
|
2010-11-22 17:03:30 +01:00
|
|
|
}
|
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
+ (void) registerFixedMappings: (MAPIStoreMapping *) storeMapping
|
2010-11-22 17:03:30 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (Class) messageTableClass
|
|
|
|
{
|
|
|
|
[self subclassResponsibility: _cmd];
|
|
|
|
|
|
|
|
return Nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (Class) folderTableClass
|
|
|
|
{
|
|
|
|
return [MAPIStoreFolderTable class];
|
|
|
|
}
|
|
|
|
|
2010-11-22 17:03:30 +01:00
|
|
|
static inline MAPIStoreContext *
|
|
|
|
_prepareContextClass (struct mapistore_context *newMemCtx,
|
2010-11-22 22:32:11 +01:00
|
|
|
Class contextClass, NSString *completeURLString,
|
2010-11-22 17:03:30 +01:00
|
|
|
NSString *username, NSString *password)
|
|
|
|
{
|
|
|
|
MAPIStoreContext *context;
|
|
|
|
MAPIStoreAuthenticator *authenticator;
|
|
|
|
static NSMutableDictionary *registration = nil;
|
|
|
|
|
|
|
|
if (!registration)
|
|
|
|
registration = [NSMutableDictionary new];
|
|
|
|
|
|
|
|
if (![registration objectForKey: contextClass])
|
|
|
|
{
|
2010-11-22 22:32:11 +01:00
|
|
|
[contextClass registerFixedMappings: mapping];
|
2010-11-22 17:03:30 +01:00
|
|
|
[registration setObject: [NSNull null]
|
|
|
|
forKey: contextClass];
|
|
|
|
}
|
|
|
|
|
2010-11-22 22:32:11 +01:00
|
|
|
context = [contextClass new];
|
2010-11-22 17:03:30 +01:00
|
|
|
[context setURI: completeURLString andMemCtx: newMemCtx];
|
|
|
|
[context autorelease];
|
|
|
|
|
|
|
|
authenticator = [MAPIStoreAuthenticator new];
|
|
|
|
[authenticator setUsername: username];
|
|
|
|
[authenticator setPassword: password];
|
|
|
|
[context setAuthenticator: authenticator];
|
|
|
|
[authenticator release];
|
|
|
|
|
|
|
|
[context setupRequest];
|
|
|
|
[context setupModuleFolder];
|
|
|
|
[context tearDownRequest];
|
|
|
|
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
+ (id) contextFromURI: (const char *) newUri
|
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,
|
|
|
|
completeURLString,
|
|
|
|
[baseURL user],
|
|
|
|
[baseURL password]);
|
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];
|
2010-10-01 22:35:29 +02:00
|
|
|
woContext = [WOContext contextWithRequest: nil];
|
|
|
|
[woContext retain];
|
2010-12-01 17:34:41 +01:00
|
|
|
parentFoldersBag = [NSMutableArray new];
|
2010-10-01 22:35:29 +02:00
|
|
|
moduleFolder = nil;
|
2010-12-30 15:18:42 +01:00
|
|
|
faiModuleFolder = nil;
|
2010-10-13 23:40:50 +02:00
|
|
|
uri = nil;
|
2010-12-30 15:18:42 +01:00
|
|
|
messageTable = nil;
|
|
|
|
faiTable = nil;
|
|
|
|
folderTable = 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
|
|
|
[self logWithFormat: @"-init"];
|
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
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"-dealloc"];
|
2010-10-01 22:35:29 +02:00
|
|
|
|
2010-12-01 17:34:41 +01:00
|
|
|
[parentFoldersBag release];
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
[messageTable release];
|
|
|
|
[faiTable release];
|
|
|
|
[folderTable release];
|
|
|
|
|
2010-11-06 00:27:08 +01:00
|
|
|
[messages release];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
[moduleFolder release];
|
2010-12-30 15:18:42 +01:00
|
|
|
[faiModuleFolder release];
|
2010-10-01 22:35:29 +02:00
|
|
|
[woContext release];
|
|
|
|
[authenticator release];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-10-13 23:40:50 +02:00
|
|
|
[uri release];
|
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
[super dealloc];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-10-13 23:40:50 +02:00
|
|
|
- (void) setURI: (NSString *) newUri
|
|
|
|
andMemCtx: (struct mapistore_context *) newMemCtx
|
|
|
|
{
|
|
|
|
ASSIGN (uri, newUri);
|
|
|
|
memCtx = newMemCtx;
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
faiModuleFolder = [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: newUri]
|
|
|
|
andTableType: MAPISTORE_FAI_TABLE];
|
|
|
|
[faiModuleFolder retain];
|
2010-10-13 23:40:50 +02:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
- (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
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setupModuleFolder
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
[self subclassResponsibility: _cmd];
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
// - (void) _setNewLastObject: (id) newLastObject
|
|
|
|
// {
|
|
|
|
// id currentObject, container;
|
|
|
|
|
|
|
|
// if (newLastObject != lastObject)
|
|
|
|
// {
|
|
|
|
// currentObject = lastObject;
|
|
|
|
// while (currentObject)
|
|
|
|
// {
|
|
|
|
// container = [currentObject container];
|
|
|
|
// [currentObject release];
|
|
|
|
// currentObject = container;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// currentObject = newLastObject;
|
|
|
|
// while (currentObject)
|
|
|
|
// {
|
|
|
|
// [currentObject retain];
|
|
|
|
// currentObject = [currentObject container];
|
|
|
|
// }
|
|
|
|
|
|
|
|
// lastObject = newLastObject;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
|
|
|
|
- (id) _lookupObject: (NSString *) objectURLString
|
|
|
|
fromBaseFolder: (SOGoFolder *) baseFolder
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
id object;
|
|
|
|
NSURL *objectURL;
|
|
|
|
NSArray *path;
|
|
|
|
int count, max;
|
|
|
|
NSString *pathString, *nameInContainer;
|
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
// [self logWithFormat: @"lookup of '%@'", objectURLString];
|
2010-10-01 22:35:29 +02:00
|
|
|
objectURL = [NSURL URLWithString: objectURLString];
|
2010-10-01 23:24:15 +02:00
|
|
|
if (objectURL)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
object = baseFolder;
|
2010-10-01 23:24:15 +02:00
|
|
|
pathString = [objectURL path];
|
|
|
|
if ([pathString hasPrefix: @"/"])
|
|
|
|
pathString = [pathString substringFromIndex: 1];
|
|
|
|
if ([pathString length] > 0)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-10-01 23:24:15 +02:00
|
|
|
path = [pathString componentsSeparatedByString: @"/"];
|
|
|
|
max = [path count];
|
|
|
|
if (max > 0)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-10-01 23:24:15 +02:00
|
|
|
for (count = 0;
|
|
|
|
object && count < max;
|
|
|
|
count++)
|
|
|
|
{
|
|
|
|
nameInContainer = [[path objectAtIndex: count]
|
2010-10-01 22:35:29 +02:00
|
|
|
stringByUnescapingURL];
|
2010-10-01 23:24:15 +02:00
|
|
|
object = [object lookupName: nameInContainer
|
|
|
|
inContext: woContext
|
|
|
|
acquire: NO];
|
|
|
|
if ([object isKindOfClass: SOGoObjectK])
|
|
|
|
[woContext setClientObject: object];
|
|
|
|
else
|
|
|
|
object = nil;
|
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// [self _setNewLastObject: object];
|
|
|
|
// ASSIGN (lastObjectURL, objectURLString);
|
2010-10-01 23:24:15 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
object = nil;
|
|
|
|
[self errorWithFormat: @"url string gave nil NSURL: '%@'", objectURLString];
|
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
|
|
|
|
[woContext setClientObject: object];
|
2010-12-30 15:18:42 +01:00
|
|
|
|
2010-10-01 22:35:29 +02:00
|
|
|
return object;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (id) lookupObject: (NSString *) objectURLString
|
|
|
|
{
|
|
|
|
if (!moduleFolder)
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
|
|
|
format: @"no moduleFolder set for context"];
|
|
|
|
|
|
|
|
return [self _lookupObject: objectURLString
|
|
|
|
fromBaseFolder: moduleFolder];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) lookupFAIObject: (NSString *) objectURLString
|
|
|
|
{
|
|
|
|
if (!faiModuleFolder)
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
|
|
|
format: @"no moduleFolder set for context"];
|
|
|
|
|
|
|
|
return [self _lookupObject: objectURLString
|
|
|
|
fromBaseFolder: faiModuleFolder];
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (NSString *) _createFolder: (struct SRow *) aRow
|
|
|
|
inParentURL: (NSString *) parentFolderURL
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
NSString *newFolderURL;
|
|
|
|
NSString *folderName, *nameInContainer;
|
|
|
|
SOGoFolder *parentFolder, *newFolder;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
newFolderURL = nil;
|
|
|
|
|
|
|
|
folderName = nil;
|
|
|
|
for (i = 0; !folderName && i < aRow->cValues; i++)
|
|
|
|
{
|
|
|
|
if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME_UNICODE)
|
|
|
|
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszW];
|
|
|
|
else if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME)
|
|
|
|
folderName = [NSString stringWithUTF8String: aRow->lpProps[i].value.lpszA];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (folderName)
|
|
|
|
{
|
|
|
|
parentFolder = [self lookupObject: parentFolderURL];
|
|
|
|
if (parentFolder)
|
|
|
|
{
|
|
|
|
if ([parentFolder isKindOfClass: SOGoMailAccountK]
|
|
|
|
|| [parentFolder isKindOfClass: SOGoMailFolderK])
|
|
|
|
{
|
|
|
|
nameInContainer = [NSString stringWithFormat: @"folder%@",
|
|
|
|
[folderName asCSSIdentifier]];
|
|
|
|
newFolder = [SOGoMailFolderK objectWithName: nameInContainer
|
|
|
|
inContainer: parentFolder];
|
|
|
|
if ([newFolder create])
|
|
|
|
newFolderURL = [NSString stringWithFormat: @"%@/%@",
|
|
|
|
parentFolderURL,
|
|
|
|
[nameInContainer stringByEscapingURL]];
|
|
|
|
}
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
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 newFolderURL;
|
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
|
|
|
|
{
|
2010-10-01 22:35:29 +02:00
|
|
|
NSString *folderURL, *parentFolderURL;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
[self logWithFormat: @"METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
|
|
|
|
|
|
|
folderURL = [mapping urlFromID: fid];
|
|
|
|
if (folderURL)
|
|
|
|
rc = MAPISTORE_ERR_EXIST;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
parentFolderURL = [mapping urlFromID: parentFID];
|
|
|
|
if (!parentFolderURL)
|
|
|
|
[self errorWithFormat: @"No url found for FID: %lld", parentFID];
|
2010-10-13 23:40:50 +02:00
|
|
|
if (parentFolderURL)
|
|
|
|
{
|
|
|
|
folderURL = [self _createFolder: aRow inParentURL: parentFolderURL];
|
|
|
|
if (folderURL)
|
|
|
|
{
|
|
|
|
[mapping registerURL: folderURL withID: fid];
|
|
|
|
// if ([sogoFolder isKindOfClass: SOGoMailAccountK])
|
|
|
|
// [sogoFolder subscribe];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
2010-10-01 22:35:29 +02:00
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NO_DIRECTORY;
|
|
|
|
}
|
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
|
|
|
|
inParentFID: (uint64_t) parentFID
|
|
|
|
{
|
2010-12-03 23:31:56 +01:00
|
|
|
[self logWithFormat:
|
|
|
|
@"UNIMPLEMENTED METHOD '%s' (%d):\n fid=0x%.16x, parentFID=0x%.16x",
|
|
|
|
__FUNCTION__, __LINE__,
|
|
|
|
(unsigned long long) fid,
|
|
|
|
(unsigned long long) parentFID];
|
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 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
|
|
|
/* TODO: should handle folder hierarchies */
|
|
|
|
- (MAPIStoreTable *) _tableForFID: (uint64_t) fid
|
|
|
|
andTableType: (uint8_t) tableType
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
MAPIStoreTable *table;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
if (!messageTable)
|
|
|
|
{
|
|
|
|
messageTable = [[self messageTableClass] new];
|
|
|
|
[messageTable setContext: self
|
|
|
|
withMemCtx: memCtx];
|
|
|
|
[messageTable setFolder: moduleFolder
|
|
|
|
withURL: uri
|
|
|
|
andFID: fid];
|
|
|
|
}
|
|
|
|
table = messageTable;
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2010-12-30 15:18:42 +01:00
|
|
|
else if (tableType == MAPISTORE_FAI_TABLE)
|
2010-12-13 18:03:25 +01:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
if (!faiTable)
|
|
|
|
{
|
|
|
|
faiTable = [MAPIStoreFAIMessageTable new];
|
|
|
|
[faiTable setContext: self
|
|
|
|
withMemCtx: memCtx];
|
|
|
|
[faiTable setFolder: faiModuleFolder
|
|
|
|
withURL: uri
|
|
|
|
andFID: fid];
|
|
|
|
}
|
|
|
|
table = faiTable;
|
|
|
|
}
|
|
|
|
else if (tableType == MAPISTORE_FOLDER_TABLE)
|
|
|
|
{
|
|
|
|
if (!folderTable)
|
|
|
|
{
|
|
|
|
folderTable = [[self folderTableClass] new];
|
|
|
|
[folderTable setContext: self
|
|
|
|
withMemCtx: memCtx];
|
|
|
|
[folderTable setFolder: moduleFolder
|
|
|
|
withURL: uri
|
|
|
|
andFID: fid];
|
|
|
|
}
|
|
|
|
table = folderTable;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
table = nil;
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
|
|
|
format: @"unsupported table type: %d", tableType];
|
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
|
|
|
MAPIStoreTable *table;
|
|
|
|
NSArray *keys;
|
2010-10-01 22:35:29 +02:00
|
|
|
NSString *url;
|
|
|
|
int rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
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
|
|
|
// [self logWithFormat: @"context restriction state is: %@",
|
|
|
|
// MAPIStringForRestrictionState (restrictionState)];
|
|
|
|
// if (restriction)
|
|
|
|
// [self logWithFormat: @" active qualifier: %@", restriction];
|
2010-12-03 23:31:56 +01:00
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
// if (restrictionState == MAPIRestrictionStateAlwaysFalse)
|
|
|
|
// {
|
|
|
|
// *rowCount = 0;
|
|
|
|
// rc = MAPI_E_SUCCESS;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
url = [mapping urlFromID: fid];
|
|
|
|
if (url)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
table = [self _tableForFID: fid andTableType: tableType];
|
|
|
|
keys = [table cachedChildKeys];
|
|
|
|
*rowCount = [keys count];
|
2010-12-03 23:31:56 +01:00
|
|
|
rc = MAPI_E_SUCCESS;
|
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
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
table = [self _tableForFID: fid andTableType: tableType];
|
|
|
|
[table setRestrictions: res];
|
|
|
|
|
2010-12-03 23:31:56 +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
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
NSArray *children, *restrictedChildren;
|
2010-12-30 15:18:42 +01:00
|
|
|
NSString *folderURL, *childKey;
|
|
|
|
MAPIStoreTable *table;
|
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
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
propName = get_proptag_name (propTag);
|
2010-12-13 18:03:25 +01:00
|
|
|
if (!propName)
|
|
|
|
propName = "<unknown>";
|
2010-12-17 20:39:21 +01:00
|
|
|
// [self logWithFormat: @"METHOD '%s' (%d) -- proptag: %s (0x%.8x), pos: %.8x,"
|
|
|
|
// @" tableType: %d, queryType: %d, fid: %.16x",
|
|
|
|
// __FUNCTION__, __LINE__, propName, proptag, pos, tableType, queryType, fid];
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-12-14 21:58:19 +01:00
|
|
|
// [self logWithFormat: @"context restriction state is: %@",
|
|
|
|
// MAPIStringForRestrictionState (restrictionState)];
|
2010-12-13 18:03:25 +01:00
|
|
|
// if (restriction)
|
|
|
|
// [self logWithFormat: @" active qualifier: %@", restriction];
|
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
|
|
|
restrictedChildren = nil;
|
|
|
|
table = [self _tableForFID: fid andTableType: tableType];
|
|
|
|
if (queryType == MAPISTORE_PREFILTERED_QUERY)
|
2010-12-03 23:31:56 +01:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
children = [table cachedRestrictedChildKeys];
|
2010-12-13 18:03:25 +01:00
|
|
|
restrictedChildren = nil;
|
2010-12-30 15:18:42 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
children = [table cachedChildKeys];
|
|
|
|
restrictedChildren = [table cachedRestrictedChildKeys];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([children count] > pos)
|
|
|
|
{
|
|
|
|
childKey = [children objectAtIndex: pos];
|
|
|
|
|
|
|
|
// TODO: the use of restrictedChildren might be optimized by
|
|
|
|
// making it a dictionary (hash versus linear search)
|
|
|
|
if (queryType == MAPISTORE_PREFILTERED_QUERY
|
|
|
|
|| [restrictedChildren containsObject: childKey])
|
2010-12-03 23:31:56 +01:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
rc = [table getChildProperty: data
|
|
|
|
forKey: childKey
|
|
|
|
withTag: propTag];
|
2010-12-13 18:03:25 +01:00
|
|
|
if (rc == MAPI_E_SUCCESS && *data == NULL)
|
|
|
|
{
|
|
|
|
[self errorWithFormat: @"both 'success' and NULL data"
|
|
|
|
@" returned for proptag %s(0x%.8x)",
|
2010-12-30 15:18:42 +01:00
|
|
|
propName, propTag];
|
2010-12-13 18:03:25 +01:00
|
|
|
rc = MAPI_E_NOT_FOUND;
|
2010-12-03 23:31:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-12-30 15:18:42 +01:00
|
|
|
// [self logWithFormat:
|
|
|
|
// @"child '%@' does not match active restriction",
|
|
|
|
// childURL];
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
2010-12-03 23:31:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
// [self errorWithFormat:
|
|
|
|
// @"Invalid row position %d for table type %d"
|
|
|
|
// @" in FID: %lld",
|
|
|
|
// pos, tableType, fid];
|
2010-12-13 18:03:25 +01:00
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
2010-12-03 23:31:56 +01:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (int) openMessage: (struct mapistore_message *) msg
|
|
|
|
forKey: (NSString *) childKey
|
|
|
|
inTable: (MAPIStoreTable *) table
|
|
|
|
{
|
|
|
|
static enum MAPITAGS tags[] = { PR_SUBJECT_UNICODE, PR_HASATTACH,
|
|
|
|
PR_MESSAGE_DELIVERY_TIME, PR_MESSAGE_FLAGS,
|
|
|
|
PR_FLAG_STATUS, PR_SENSITIVITY,
|
|
|
|
PR_SENT_REPRESENTING_NAME_UNICODE,
|
|
|
|
PR_INTERNET_MESSAGE_ID_UNICODE,
|
|
|
|
PR_READ_RECEIPT_REQUESTED };
|
|
|
|
struct SRowSet *recipients;
|
|
|
|
struct SRow *properties;
|
|
|
|
NSInteger count, max;
|
|
|
|
const char *propName;
|
|
|
|
void *propValue;
|
|
|
|
|
|
|
|
[self logWithFormat: @"INCOMPLETE METHOD '%s' (%d): no recipient handling",
|
|
|
|
__FUNCTION__, __LINE__];
|
|
|
|
recipients = talloc_zero (memCtx, struct SRowSet);
|
|
|
|
recipients->cRows = 0;
|
|
|
|
recipients->aRow = NULL;
|
|
|
|
msg->recipients = recipients;
|
|
|
|
|
|
|
|
max = 9;
|
|
|
|
properties = talloc_zero (memCtx, struct SRow);
|
|
|
|
properties->cValues = 0;
|
|
|
|
properties->ulAdrEntryPad = 0;
|
|
|
|
properties->lpProps = talloc_array (properties, struct SPropValue, max);
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
if ([table getChildProperty: &propValue
|
|
|
|
forKey: childKey
|
|
|
|
withTag: tags[count]]
|
|
|
|
== MAPI_E_SUCCESS)
|
|
|
|
{
|
|
|
|
if (propValue == NULL)
|
|
|
|
{
|
|
|
|
propName = get_proptag_name (tags[count]);
|
|
|
|
if (!propName)
|
|
|
|
propName = "<unknown>";
|
|
|
|
[self errorWithFormat: @"both 'success' and NULL data"
|
|
|
|
@" returned for proptag %s(0x%.8x)",
|
|
|
|
propName, tags[count]];
|
|
|
|
}
|
2011-01-11 22:17:52 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
set_SPropValue_proptag (properties->lpProps + properties->cValues,
|
|
|
|
tags[count],
|
|
|
|
propValue);
|
|
|
|
properties->cValues++;
|
|
|
|
}
|
2010-12-30 15:18:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
msg->properties = properties;
|
|
|
|
|
|
|
|
return MAPI_E_SUCCESS;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
NSString *childURL, *childKey, *folderURL;
|
|
|
|
MAPIStoreTable *table;
|
2011-01-12 00:07:41 +01:00
|
|
|
BOOL isAssociated;
|
2011-01-12 01:10:21 +01:00
|
|
|
int rc;
|
2010-10-14 15:22:26 +02:00
|
|
|
|
|
|
|
childURL = [mapping urlFromID: mid];
|
|
|
|
if (childURL)
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
childKey = [self extractChildNameFromURL: childURL
|
|
|
|
andFolderURLAt: &folderURL];
|
|
|
|
table = [self _tableForFID: fid andTableType: MAPISTORE_FAI_TABLE];
|
|
|
|
if ([[table cachedChildKeys] containsObject: childKey])
|
2011-01-12 00:07:41 +01:00
|
|
|
{
|
|
|
|
isAssociated = YES;
|
|
|
|
rc = [self openMessage: msg forKey: childKey inTable: table];
|
|
|
|
}
|
2010-12-30 15:18:42 +01:00
|
|
|
else
|
|
|
|
{
|
2011-01-12 00:07:41 +01:00
|
|
|
isAssociated = NO;
|
2010-12-30 15:18:42 +01:00
|
|
|
table = [self _tableForFID: fid andTableType: MAPISTORE_MESSAGE_TABLE];
|
|
|
|
if ([[table cachedChildKeys] containsObject: childKey])
|
|
|
|
rc = [self openMessage: msg forKey: childKey inTable: table];
|
|
|
|
else
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
|
|
|
}
|
2010-10-14 15:22:26 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
2011-01-12 00:07:41 +01:00
|
|
|
if (rc == MAPI_E_SUCCESS)
|
|
|
|
[self createMessagePropertiesWithMID: mid
|
|
|
|
inFID: fid
|
|
|
|
isAssociated: isAssociated];
|
|
|
|
|
2010-10-14 15:22:26 +02:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-11-18 23:32:05 +01:00
|
|
|
- (int) createMessagePropertiesWithMID: (uint64_t) mid
|
|
|
|
inFID: (uint64_t) fid
|
2010-12-30 15:18:42 +01:00
|
|
|
isAssociated: (BOOL) isAssociated
|
2010-10-01 20:54:30 +02:00
|
|
|
{
|
2011-01-12 01:10:21 +01:00
|
|
|
NSMutableDictionary *messageProperties;
|
2010-11-06 00:27:08 +01:00
|
|
|
NSNumber *midNbr;
|
2011-01-12 01:10:21 +01:00
|
|
|
NSUInteger retainCount;
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2011-01-12 01:10:21 +01:00
|
|
|
messageProperties = [messages objectForKey:
|
|
|
|
[NSNumber numberWithUnsignedLongLong: mid]];
|
|
|
|
if (messageProperties)
|
|
|
|
{
|
|
|
|
[self logWithFormat:
|
|
|
|
@"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x; retainCount++",
|
|
|
|
__FUNCTION__, mid, fid];
|
|
|
|
retainCount = [[messageProperties objectForKey: @"mapiRetainCount"]
|
|
|
|
unsignedIntValue];
|
|
|
|
[messageProperties
|
|
|
|
setObject: [NSNumber numberWithUnsignedInt: retainCount + 1]
|
|
|
|
forKey: @"mapiRetainCount"];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self logWithFormat: @"METHOD '%s' -- mid: 0x%.16x, fid: 0x%.16x",
|
|
|
|
__FUNCTION__, mid, fid];
|
|
|
|
messageProperties = [NSMutableDictionary new];
|
|
|
|
[messageProperties setObject: [NSNumber numberWithUnsignedLongLong: fid]
|
|
|
|
forKey: @"fid"];
|
|
|
|
midNbr = [NSNumber numberWithUnsignedLongLong: mid];
|
|
|
|
[messageProperties setObject: midNbr forKey: @"mid"];
|
|
|
|
[messageProperties setObject: [NSNumber numberWithBool: isAssociated]
|
|
|
|
forKey: @"associated"];
|
|
|
|
[messageProperties setObject: [NSNumber numberWithInt: 1]
|
|
|
|
forKey: @"mapiRetainCount"];
|
|
|
|
[messages setObject: messageProperties forKey: midNbr];
|
|
|
|
[messageProperties release];
|
|
|
|
}
|
2010-11-06 00:27:08 +01:00
|
|
|
|
|
|
|
return MAPISTORE_SUCCESS;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (id) createMessageOfClass: (NSString *) messageClass
|
|
|
|
inFolderAtURL: (NSString *) folderURL
|
2010-11-18 23:32:05 +01:00
|
|
|
{
|
2010-11-19 15:41:15 +01:00
|
|
|
[self subclassResponsibility: _cmd];
|
2010-11-18 23:32:05 +01:00
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
- (id) _createMessageOfClass: (NSString *) messageClass
|
|
|
|
associated: (BOOL) associated
|
|
|
|
withMID: (uint64_t) mid
|
|
|
|
inFID: (uint64_t) fid
|
2010-11-18 23:32:05 +01:00
|
|
|
{
|
|
|
|
NSString *folderURL, *messageURL;
|
|
|
|
id message;
|
|
|
|
|
|
|
|
message = nil;
|
|
|
|
|
|
|
|
folderURL = [mapping urlFromID: fid];
|
|
|
|
if (folderURL)
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
if (associated)
|
|
|
|
{
|
|
|
|
message = [[self lookupFAIObject: folderURL] newMessage];
|
|
|
|
[faiTable cleanupCaches];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
message = [self createMessageOfClass: messageClass
|
|
|
|
inFolderAtURL: folderURL];
|
|
|
|
[messageTable cleanupCaches];
|
|
|
|
}
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
if (![folderURL hasSuffix: @"/"])
|
|
|
|
folderURL = [NSString stringWithFormat: @"%@/", folderURL];
|
|
|
|
messageURL = [NSString stringWithFormat: @"%@%@", folderURL,
|
|
|
|
[message nameInContainer]];
|
|
|
|
[mapping registerURL: messageURL withID: mid];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[self errorWithFormat:
|
|
|
|
@"no message created in folder '%.16x' with mid '%.16x'",
|
|
|
|
fid, mid];
|
2010-11-18 23:32:05 +01:00
|
|
|
}
|
|
|
|
else
|
2010-11-22 22:32:11 +01:00
|
|
|
[self errorWithFormat: @"registered message without a valid fid (%.16x)", fid];
|
2010-11-18 23:32:05 +01:00
|
|
|
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
id message;
|
|
|
|
NSMutableDictionary *messageProperties;
|
|
|
|
NSString *messageURL;
|
|
|
|
uint64_t fid;
|
2011-01-12 01:10:21 +01:00
|
|
|
BOOL associated;
|
2010-11-18 23:32:05 +01:00
|
|
|
|
|
|
|
messageProperties = [messages objectForKey:
|
|
|
|
[NSNumber numberWithUnsignedLongLong: mid]];
|
|
|
|
if (messageProperties)
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
messageURL = [mapping urlFromID: mid];
|
2011-01-12 01:10:21 +01:00
|
|
|
associated = [[messageProperties objectForKey: @"associated"] boolValue];
|
|
|
|
if (messageURL)
|
2010-12-03 23:31:56 +01:00
|
|
|
{
|
2011-01-12 01:10:21 +01:00
|
|
|
if (associated)
|
2010-12-30 15:18:42 +01:00
|
|
|
message = [self lookupFAIObject: messageURL];
|
|
|
|
else
|
2011-01-12 01:10:21 +01:00
|
|
|
message = [self lookupObject: messageURL];
|
2010-12-03 23:31:56 +01:00
|
|
|
}
|
2010-11-18 23:32:05 +01:00
|
|
|
else
|
2010-12-03 23:31:56 +01:00
|
|
|
{
|
2011-01-12 01:10:21 +01:00
|
|
|
fid = [[messageProperties objectForKey: @"fid"]
|
|
|
|
unsignedLongLongValue];
|
|
|
|
message = [self _createMessageOfClass: [messageProperties objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)]
|
|
|
|
associated: associated
|
|
|
|
withMID: mid inFID: fid];
|
2010-12-30 15:18:42 +01:00
|
|
|
}
|
|
|
|
if (message)
|
|
|
|
{
|
2011-01-12 01:10:21 +01:00
|
|
|
if (associated)
|
|
|
|
[faiTable cleanupCaches];
|
|
|
|
else
|
|
|
|
[messageTable cleanupCaches];
|
|
|
|
|
2010-12-30 15:18:42 +01:00
|
|
|
[message setMAPIProperties: messageProperties];
|
|
|
|
if (isSave)
|
|
|
|
[message MAPISave];
|
2010-12-03 23:31:56 +01:00
|
|
|
else
|
2010-12-30 15:18:42 +01:00
|
|
|
[message MAPISubmit];
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
2010-12-03 23:31:56 +01:00
|
|
|
}
|
2010-12-30 15:18:42 +01:00
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERROR;
|
2010-11-18 23:32:05 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
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
|
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
MAPIStoreTable *table;
|
|
|
|
NSArray *children;
|
|
|
|
NSString *childURL, *folderURL, *childKey;
|
|
|
|
NSInteger count;
|
|
|
|
void *propValue;
|
|
|
|
uint64_t fid;
|
|
|
|
const char *propName;
|
|
|
|
enum MAPITAGS tag;
|
|
|
|
enum MAPISTATUS propRc;
|
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];
|
|
|
|
|
2010-10-14 18:38:15 +02:00
|
|
|
childURL = [mapping urlFromID: fmid];
|
|
|
|
if (childURL)
|
2010-10-01 22:35:29 +02:00
|
|
|
{
|
2010-12-30 15:18:42 +01:00
|
|
|
childKey = [self extractChildNameFromURL: childURL
|
|
|
|
andFolderURLAt: &folderURL];
|
|
|
|
fid = [mapping idFromURL: folderURL];
|
|
|
|
if (fid == NSNotFound)
|
|
|
|
[NSException raise: @"MAPIStoreIOException"
|
|
|
|
format: @"no fid found for url '%@'", folderURL];
|
|
|
|
|
|
|
|
table = [self _tableForFID: fid andTableType: tableType];
|
|
|
|
children = [table cachedChildKeys];
|
|
|
|
if ([children containsObject: childKey])
|
|
|
|
{
|
|
|
|
aRow->lpProps = talloc_array (aRow, struct SPropValue,
|
|
|
|
sPropTagArray->cValues);
|
|
|
|
for (count = 0; count < sPropTagArray->cValues; count++)
|
|
|
|
{
|
|
|
|
tag = sPropTagArray->aulPropTag[count];
|
|
|
|
|
|
|
|
propValue = NULL;
|
|
|
|
propRc = [table getChildProperty: &propValue
|
|
|
|
forKey: childKey
|
|
|
|
withTag: tag];
|
|
|
|
// 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)
|
|
|
|
{
|
|
|
|
if (propValue)
|
|
|
|
talloc_free (propValue);
|
|
|
|
propValue = MAPILongValue (memCtx, propRc);
|
|
|
|
tag = (tag & 0xffff0000) | 0x000a;
|
|
|
|
}
|
|
|
|
set_SPropValue_proptag (&(aRow->lpProps[aRow->cValues]),
|
|
|
|
tag, propValue);
|
|
|
|
aRow->cValues++;
|
|
|
|
}
|
|
|
|
rc = MAPI_E_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
2010-10-14 18:38:15 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self errorWithFormat: @"No url found for FMID: %lld", fmid];
|
2010-12-30 15:18:42 +01:00
|
|
|
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;
|
|
|
|
NSString *objectURL;
|
2010-10-15 19:24:09 +02:00
|
|
|
// TDB_DATA key, dbuf;
|
2010-10-13 23:40:50 +02:00
|
|
|
|
|
|
|
objectURL = [mapping urlFromID: fmid];
|
|
|
|
if (objectURL)
|
|
|
|
{
|
2010-10-15 19:24:09 +02:00
|
|
|
if ([objectURL hasPrefix: uri])
|
|
|
|
{
|
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",
|
|
|
|
*path, fmid];
|
2010-10-15 19:24:09 +02:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-14 14:13:32 +01:00
|
|
|
[self logWithFormat: @"context (%@, %@) does not contain"
|
|
|
|
@" found fmid: 0x%.16x",
|
|
|
|
objectURL, uri, 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
|
|
|
|
{
|
|
|
|
NSMutableDictionary *message;
|
|
|
|
NSNumber *midNbr;
|
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:
|
2010-11-06 00:27:08 +01:00
|
|
|
midNbr = [NSNumber numberWithUnsignedLongLong: fmid];
|
|
|
|
message = [messages objectForKey: midNbr];
|
|
|
|
if (message)
|
2010-11-24 20:28:45 +01:00
|
|
|
{
|
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;
|
2010-11-24 20:28:45 +01:00
|
|
|
[message setObject: NSObjectFromSPropValue (cValue)
|
2010-12-13 18:03:25 +01:00
|
|
|
forKey: MAPIPropertyKey (cValue->ulPropTag)];
|
2010-11-24 20:28:45 +01:00
|
|
|
}
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"(%s) message props after op", __PRETTY_FUNCTION__];
|
|
|
|
MAPIStoreDumpMessageProperties (message);
|
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:
|
|
|
|
default:
|
|
|
|
[self errorWithFormat: @"%s: value of tableType not handled: %d",
|
|
|
|
__FUNCTION__, tableType];
|
|
|
|
rc = MAPISTORE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) setProperty: (enum MAPITAGS) property
|
|
|
|
withFMID: (uint64_t) fmid
|
|
|
|
ofTableType: (uint8_t) tableType
|
|
|
|
fromFile: (NSFileHandle *) aFile
|
|
|
|
{
|
|
|
|
NSMutableDictionary *message;
|
|
|
|
NSNumber *midNbr;
|
|
|
|
NSData *fileData;
|
2010-12-13 18:03:25 +01:00
|
|
|
const char *propName;
|
2010-11-26 22:48:52 +01:00
|
|
|
int rc;
|
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
propName = get_proptag_name (property);
|
|
|
|
if (!propName)
|
|
|
|
propName = "<unknown>";
|
|
|
|
[self logWithFormat: @"METHOD '%s' -- property: %s(%.8x), fmid: 0x%.16x, tableType: %d",
|
|
|
|
__FUNCTION__, propName, property, fmid, tableType];
|
|
|
|
|
2010-11-26 22:48:52 +01:00
|
|
|
fileData = [aFile readDataToEndOfFile];
|
|
|
|
switch (tableType)
|
|
|
|
{
|
|
|
|
case MAPISTORE_MESSAGE:
|
|
|
|
midNbr = [NSNumber numberWithUnsignedLongLong: fmid];
|
|
|
|
message = [messages objectForKey: midNbr];
|
|
|
|
if (message)
|
|
|
|
{
|
|
|
|
[message setObject: NSObjectFromStreamData (property, fileData)
|
2010-12-13 18:03:25 +01:00
|
|
|
forKey: MAPIPropertyKey (property)];
|
|
|
|
[self logWithFormat: @"(%s) message props after op", __PRETTY_FUNCTION__];
|
|
|
|
MAPIStoreDumpMessageProperties (message);
|
2010-11-26 22:48:52 +01:00
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
2010-10-01 22:35:29 +02:00
|
|
|
break;
|
2010-11-19 22:14:53 +01:00
|
|
|
case MAPISTORE_FOLDER:
|
2010-11-06 00:27:08 +01:00
|
|
|
default:
|
2010-11-19 22:14:53 +01:00
|
|
|
[self errorWithFormat: @"%s: value of tableType not handled: %d",
|
|
|
|
__FUNCTION__, tableType];
|
2010-11-06 00:27:08 +01:00
|
|
|
rc = MAPISTORE_ERROR;
|
2010-10-01 22:35:29 +02:00
|
|
|
}
|
2010-10-01 20:54:30 +02:00
|
|
|
|
2010-11-06 00:27:08 +01:00
|
|
|
return rc;
|
2010-10-01 20:54:30 +02:00
|
|
|
}
|
|
|
|
|
2010-11-30 22:04:05 +01:00
|
|
|
- (int) getProperty: (enum MAPITAGS) property
|
|
|
|
withFMID: (uint64_t) fmid
|
|
|
|
ofTableType: (uint8_t) tableType
|
|
|
|
intoFile: (NSFileHandle *) aFile
|
|
|
|
{
|
|
|
|
NSMutableDictionary *message;
|
|
|
|
NSNumber *midNbr;
|
|
|
|
NSData *fileData;
|
2010-12-13 18:03:25 +01:00
|
|
|
const char *propName;
|
2010-11-30 22:04:05 +01:00
|
|
|
enum MAPISTATUS rc;
|
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
propName = get_proptag_name (property);
|
|
|
|
if (!propName)
|
|
|
|
propName = "<unknown>";
|
|
|
|
[self logWithFormat: @"METHOD '%s' -- property: %s(%.8x), fmid: 0x%.16x, tableType: %d",
|
|
|
|
__FUNCTION__, propName, property, fmid, tableType];
|
|
|
|
|
2010-11-30 22:04:05 +01:00
|
|
|
switch (tableType)
|
|
|
|
{
|
|
|
|
case MAPISTORE_MESSAGE:
|
|
|
|
midNbr = [NSNumber numberWithUnsignedLongLong: fmid];
|
|
|
|
message = [messages objectForKey: midNbr];
|
|
|
|
if (message)
|
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
fileData = [message objectForKey: MAPIPropertyKey (property)];
|
2010-11-30 22:04:05 +01:00
|
|
|
/* TODO: only NSData is supported right now */
|
|
|
|
if (fileData)
|
|
|
|
{
|
|
|
|
[aFile writeData: fileData];
|
|
|
|
rc = MAPI_E_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
2010-12-13 18:03:25 +01:00
|
|
|
{
|
|
|
|
[self errorWithFormat: @"no data for property %s(%.8x)"
|
|
|
|
@" in mid %.16x", propName, fmid];
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
}
|
2010-11-30 22:04:05 +01:00
|
|
|
}
|
|
|
|
else
|
2010-12-13 18:03:25 +01:00
|
|
|
{
|
|
|
|
[self errorWithFormat: @"no message found with mid %.16x", fmid];
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
|
|
|
}
|
2010-11-30 22:04:05 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
// [message setObject: NSObjectFromStreamData (property, fileData)
|
|
|
|
// forKey: MAPIPropertyNumber (property)];
|
|
|
|
// rc = MAPISTORE_SUCCESS;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
case MAPISTORE_FOLDER:
|
2010-12-17 20:39:21 +01:00
|
|
|
[self errorWithFormat: @"%s: folder properties not handled yet",
|
|
|
|
__FUNCTION__];
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
break;
|
2010-11-30 22:04:05 +01:00
|
|
|
default:
|
|
|
|
[self errorWithFormat: @"%s: value of tableType not handled: %d",
|
|
|
|
__FUNCTION__, tableType];
|
|
|
|
rc = MAPI_E_INVALID_OBJECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-11-24 20:28:45 +01:00
|
|
|
- (NSDictionary *) _convertRecipientFromRow: (struct RecipientRow *) row
|
|
|
|
{
|
|
|
|
NSMutableDictionary *recipient;
|
|
|
|
NSString *value;
|
|
|
|
|
|
|
|
recipient = [NSMutableDictionary dictionaryWithCapacity: 5];
|
|
|
|
|
|
|
|
if ((row->RecipientFlags & 0x07) == 1)
|
|
|
|
{
|
|
|
|
value = [NSString stringWithUTF8String: row->X500DN.recipient_x500name];
|
|
|
|
[recipient setObject: value forKey: @"x500dn"];
|
|
|
|
}
|
|
|
|
|
|
|
|
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"];
|
|
|
|
|
|
|
|
return recipient;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int) modifyRecipientsWithMID: (uint64_t) mid
|
|
|
|
inRows: (struct ModifyRecipientRow *) rows
|
|
|
|
withCount: (NSUInteger) max
|
|
|
|
{
|
|
|
|
static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
|
|
|
NSMutableDictionary *message, *recipients;
|
|
|
|
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];
|
|
|
|
[message setObject: recipients forKey: @"recipients"];
|
|
|
|
[recipients release];
|
|
|
|
for (count = 0; count < max; count++)
|
|
|
|
{
|
|
|
|
currentRow = rows + count;
|
|
|
|
if (currentRow->RecipClass >= 0
|
|
|
|
&& currentRow->RecipClass < 3)
|
|
|
|
{
|
|
|
|
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)]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rc = MAPISTORE_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
- (int) deleteMessageWithMID: (uint64_t) mid
|
|
|
|
withFlags: (uint8_t) flags
|
|
|
|
{
|
2010-11-19 15:41:15 +01:00
|
|
|
[self logWithFormat: @"UNIMPLEMENTED METHOD '%s' (%d)", __FUNCTION__, __LINE__];
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @" mid: 0x%.16x flags: %d", mid, flags];
|
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-12-13 18:03:25 +01:00
|
|
|
- (int) releaseRecordWithFMID: (uint64_t) fmid
|
|
|
|
ofTableType: (uint8_t) tableType
|
|
|
|
{
|
|
|
|
NSNumber *midNbr;
|
2011-01-12 01:10:21 +01:00
|
|
|
NSMutableDictionary *messageProperties;
|
|
|
|
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;
|
2010-12-13 18:03:25 +01:00
|
|
|
midNbr = [NSNumber numberWithUnsignedLongLong: fmid];
|
2011-01-12 01:10:21 +01:00
|
|
|
messageProperties = [messages objectForKey: midNbr];
|
|
|
|
if (messageProperties)
|
2010-12-13 18:03:25 +01:00
|
|
|
{
|
2011-01-12 01:10:21 +01:00
|
|
|
retainCount = [[messageProperties objectForKey: @"mapiRetainCount"]
|
|
|
|
unsignedIntValue];
|
|
|
|
if (retainCount == 1)
|
|
|
|
{
|
|
|
|
[self logWithFormat: @"message with mid %.16x successfully removed"
|
|
|
|
@" from message cache",
|
|
|
|
fmid];
|
|
|
|
[messages removeObjectForKey: midNbr];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[messageProperties
|
|
|
|
setObject: [NSNumber numberWithUnsignedInt: retainCount - 1]
|
|
|
|
forKey: @"mapiRetainCount"];
|
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-10-13 23:40:50 +02:00
|
|
|
- (int) getFoldersList: (struct indexing_folders_list **) folders_list
|
|
|
|
withFMID: (uint64_t) fmid
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
NSString *currentURL;
|
|
|
|
NSMutableArray *nsFolderList;
|
|
|
|
uint64_t fid;
|
|
|
|
|
2010-12-13 18:03:25 +01:00
|
|
|
[self logWithFormat: @"METHOD '%s' -- fmid: 0x%.16x", __FUNCTION__, fmid];
|
|
|
|
|
2010-10-13 23:40:50 +02:00
|
|
|
rc = MAPI_E_SUCCESS;
|
|
|
|
|
|
|
|
currentURL = [mapping urlFromID: fmid];
|
2010-10-15 19:24:09 +02:00
|
|
|
if (currentURL && ![currentURL isEqualToString: uri]
|
|
|
|
&& [currentURL hasPrefix: uri])
|
2010-10-13 23:40:50 +02:00
|
|
|
{
|
|
|
|
nsFolderList = [NSMutableArray arrayWithCapacity: 32];
|
2010-12-30 15:18:42 +01:00
|
|
|
[self extractChildNameFromURL: currentURL
|
|
|
|
andFolderURLAt: ¤tURL];
|
2010-10-13 23:40:50 +02:00
|
|
|
while (currentURL && rc == MAPI_E_SUCCESS
|
|
|
|
&& ![currentURL isEqualToString: uri])
|
|
|
|
{
|
|
|
|
fid = [mapping idFromURL: currentURL];
|
|
|
|
if (fid == NSNotFound)
|
2010-12-13 18:03:25 +01:00
|
|
|
{
|
|
|
|
[self logWithFormat: @"no fid found for url '%@'", currentURL];
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
}
|
2010-10-13 23:40:50 +02:00
|
|
|
else
|
|
|
|
{
|
2010-12-13 18:03:25 +01:00
|
|
|
[nsFolderList addObject: [NSNumber numberWithUnsignedLongLong: fid]];
|
2010-12-30 15:18:42 +01:00
|
|
|
[self extractChildNameFromURL: currentURL
|
|
|
|
andFolderURLAt: ¤tURL];
|
2010-10-13 23:40:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc != MAPI_E_NOT_FOUND)
|
|
|
|
{
|
|
|
|
fid = [mapping idFromURL: uri];
|
2010-12-13 18:03:25 +01:00
|
|
|
[nsFolderList addObject: [NSNumber numberWithUnsignedLongLong: fid]];
|
|
|
|
[self logWithFormat: @"resulting folder list: %@", nsFolderList];
|
2010-10-13 23:40:50 +02:00
|
|
|
*folders_list = [nsFolderList asFoldersListInCtx: memCtx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = MAPI_E_NOT_FOUND;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-11-30 22:04:05 +01:00
|
|
|
/* utils */
|
|
|
|
|
|
|
|
- (void) registerValue: (id) value
|
|
|
|
asProperty: (enum MAPITAGS) property
|
|
|
|
forURL: (NSString *) url
|
|
|
|
{
|
|
|
|
/* TODO: this method is a hack to enable the saving of property values which
|
|
|
|
need to be passed as streams. Must be removed after the
|
|
|
|
getProperty/setProperty mechanisms have been rethought. */
|
|
|
|
NSMutableDictionary *message;
|
|
|
|
uint64_t fmid;
|
|
|
|
NSNumber *midNbr;
|
|
|
|
|
|
|
|
fmid = [mapping idFromURL: url];
|
|
|
|
if (fmid != NSNotFound)
|
|
|
|
{
|
|
|
|
midNbr = [NSNumber numberWithUnsignedLongLong: fmid];
|
|
|
|
message = [messages objectForKey: midNbr];
|
|
|
|
if (!message)
|
|
|
|
{
|
|
|
|
message = [NSMutableDictionary new];
|
|
|
|
[messages setObject: message forKey: midNbr];
|
|
|
|
[message release];
|
|
|
|
[message setObject: midNbr forKey: @"mid"];
|
|
|
|
}
|
2010-12-13 18:03:25 +01:00
|
|
|
[message setObject: value forKey: MAPIPropertyKey (property)];
|
2010-11-30 22:04:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-10-01 20:54:30 +02:00
|
|
|
@end
|