Monotone-Parent: 3f8608c82d9c379cc9e0fea6ffe853cc1949a24b

Monotone-Revision: 905276f295d6f28a6946297f6a7af9ad60f71842

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2012-06-29T17:59:38
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2012-06-29 17:59:38 +00:00
parent 591306481b
commit 95a443d89a
67 changed files with 2606 additions and 1873 deletions

View File

@ -1,3 +1,11 @@
2012-06-29 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/SOGoMAPIDBObject.m: new class module that replaced
SOGoMAPIFSMessage.
* OpenChange/SOGoMAPIDBFolder.m: new class module that replaced
SOGoMAPIFSFolder.
2012-06-28 Wolfgang Sourdeau <wsourdeau@inverse.ca> 2012-06-28 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoObject.m (-initWithName:inContainer:): make * SoObjects/SOGo/SOGoObject.m (-initWithName:inContainer:): make

View File

@ -25,11 +25,11 @@
#import <EOControl/EOQualifier.h> #import <EOControl/EOQualifier.h>
@class SOGoMAPIVolatileMessage; @class SOGoMAPIDBObject;
@interface EOQualifier (MAPIStoreRestrictions) @interface EOQualifier (MAPIStoreRestrictions)
- (BOOL) evaluateMAPIVolatileMessage: (SOGoMAPIVolatileMessage *) message; - (BOOL) evaluateSOGoMAPIDBObject: (SOGoMAPIDBObject *) object;
@end @end

View File

@ -28,28 +28,28 @@
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import "SOGoMAPIVolatileMessage.h" #import "EOBitmaskQualifier.h"
#import "SOGoMAPIDBObject.h"
#import "EOQualifier+MAPI.h" #import "EOQualifier+MAPI.h"
#import "EOBitmaskQualifier.h"
@implementation EOQualifier (MAPIStoreRestrictions) @implementation EOQualifier (MAPIStoreRestrictions)
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties - (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
{ {
[self subclassResponsibility: _cmd]; [self subclassResponsibility: _cmd];
return NO; return NO;
} }
- (BOOL) evaluateMAPIVolatileMessage: (SOGoMAPIVolatileMessage *) message - (BOOL) evaluateSOGoMAPIDBObject: (SOGoMAPIDBObject *) object
{ {
NSDictionary *properties; NSDictionary *properties;
BOOL rc; BOOL rc;
[self logWithFormat: @"evaluating message '%@'", message]; [self logWithFormat: @"evaluating object '%@'", object];
properties = [message properties]; properties = [object properties];
rc = [self _evaluateMAPIVolatileMessageProperties: properties]; rc = [self _evaluateSOGoMAPIDBObject: properties];
[self logWithFormat: @" evaluation result: %d", rc]; [self logWithFormat: @" evaluation result: %d", rc];
@ -60,7 +60,7 @@
@implementation EOAndQualifier (MAPIStoreRestrictionsPrivate) @implementation EOAndQualifier (MAPIStoreRestrictionsPrivate)
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties - (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
{ {
NSUInteger i; NSUInteger i;
BOOL rc; BOOL rc;
@ -69,7 +69,7 @@
for (i = 0; rc && i < count; i++) for (i = 0; rc && i < count; i++)
rc = [[qualifiers objectAtIndex: i] rc = [[qualifiers objectAtIndex: i]
_evaluateMAPIVolatileMessageProperties: properties]; _evaluateSOGoMAPIDBObject: properties];
return rc; return rc;
} }
@ -78,7 +78,7 @@
@implementation EOOrQualifier (MAPIStoreRestrictionsPrivate) @implementation EOOrQualifier (MAPIStoreRestrictionsPrivate)
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties - (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
{ {
NSUInteger i; NSUInteger i;
BOOL rc; BOOL rc;
@ -87,7 +87,7 @@
for (i = 0; !rc && i < count; i++) for (i = 0; !rc && i < count; i++)
rc = [[qualifiers objectAtIndex: i] rc = [[qualifiers objectAtIndex: i]
_evaluateMAPIVolatileMessageProperties: properties]; _evaluateSOGoMAPIDBObject: properties];
return rc; return rc;
} }
@ -96,9 +96,9 @@
@implementation EONotQualifier (MAPIStoreRestrictionsPrivate) @implementation EONotQualifier (MAPIStoreRestrictionsPrivate)
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties - (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
{ {
return ![qualifier _evaluateMAPIVolatileMessageProperties: properties]; return ![qualifier _evaluateSOGoMAPIDBObject: properties];
} }
@end @end
@ -107,7 +107,7 @@
typedef BOOL (*EOComparator) (id, SEL, id); typedef BOOL (*EOComparator) (id, SEL, id);
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties - (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
{ {
id finalKey; id finalKey;
id propValue; id propValue;
@ -136,7 +136,7 @@ typedef BOOL (*EOComparator) (id, SEL, id);
@implementation EOBitmaskQualifier (MAPIStoreRestrictionsPrivate) @implementation EOBitmaskQualifier (MAPIStoreRestrictionsPrivate)
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties - (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
{ {
NSNumber *propTag; NSNumber *propTag;
id propValue; id propValue;

View File

@ -0,0 +1,34 @@
/* GCSSpecialQueries+OpenChange.h - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef GCSSPECIALQUERIES_OPENCHANGE_H
#define GCSSPECIALQUERIES_OPENCHANGE_H
#import <GDLContentStore/GCSSpecialQueries.h>
@interface GCSSpecialQueries (OpenChangeHelpers)
- (NSString *) createOpenChangeFSTableWithName: (NSString *) tableName;
@end
#endif /* GCSSPECIALQUERIES_OPENCHANGE_H */

View File

@ -0,0 +1,102 @@
/* GCSSpecialQueries+OpenChange.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSString.h>
#import "GCSSpecialQueries+OpenChange.h"
@interface GCSPostgreSQLSpecialQueries (OpenChangeHelpers)
@end
@interface GCSMySQLSpecialQueries (OpenChangeHelpers)
@end
@interface GCSOracleSpecialQueries (OpenChangeHelpers)
@end
@implementation GCSSpecialQueries (OpenChangeHelpers)
- (NSString *) createOpenChangeFSTableWithName: (NSString *) tableName
{
[self subclassResponsibility: _cmd];
return nil;
}
@end
@implementation GCSPostgreSQLSpecialQueries (OpenChangeHelpers)
- (NSString *) createOpenChangeFSTableWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_path VARCHAR(255) PRIMARY KEY,"
@" c_type SMALLINT NOT NULL,"
@" c_creationdate INT4 NOT NULL,"
@" c_lastmodified INT4 NOT NULL,"
@" c_version INT4 NOT NULL DEFAULT 0,"
@" c_deleted SMALLINT NOT NULL DEFAULT 0,"
@" c_content TEXT)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
@end
@implementation GCSMySQLSpecialQueries (OpenChangeHelpers)
- (NSString *) createOpenChangeFSTableWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_path VARCHAR(255) PRIMARY KEY,"
@" c_type TINYINT NOT NULL,"
@" c_creationdate INT NOT NULL,"
@" c_lastmodified INT NOT NULL,"
@" c_version INT NOT NULL DEFAULT 0,"
@" c_deleted TINYINT NOT NULL DEFAULT 0,"
@" c_content TEXT)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
@end
@implementation GCSOracleSpecialQueries (OpenChangeHelpers)
- (NSString *) createOpenChangeFSTableWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_path VARCHAR2(255) PRIMARY KEY,"
@" c_type SMALLINT NOT NULL,"
@" c_creationdate INT4 NOT NULL,"
@" c_lastmodified INT4 NOT NULL,"
@" c_version INT4 NOT NULL DEFAULT 0,"
@" c_deleted SMALLINT NOT NULL DEFAULT 0,"
@" c_content CLOB)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
@end

View File

@ -41,9 +41,11 @@ $(SOGOBACKEND)_OBJC_FILES += \
MAPIStoreSamDBUtils.m \ MAPIStoreSamDBUtils.m \
MAPIStoreUserContext.m \ MAPIStoreUserContext.m \
\ \
SOGoMAPIVolatileMessage.m \ SOGoMAPIObject.m \
SOGoMAPIFSFolder.m \ \
SOGoMAPIFSMessage.m \ SOGoMAPIDBObject.m \
SOGoMAPIDBMessage.m \
SOGoMAPIDBFolder.m \
\ \
MAPIStoreAppointmentWrapper.m \ MAPIStoreAppointmentWrapper.m \
MAPIStoreAttachment.m \ MAPIStoreAttachment.m \
@ -53,18 +55,17 @@ $(SOGOBACKEND)_OBJC_FILES += \
MAPIStoreFolder.m \ MAPIStoreFolder.m \
MAPIStoreMessage.m \ MAPIStoreMessage.m \
MAPIStoreObject.m \ MAPIStoreObject.m \
MAPIStoreSOGoObject.m \
MAPIStoreTable.m \ MAPIStoreTable.m \
MAPIStoreMessageTable.m \ MAPIStoreMessageTable.m \
MAPIStoreFolderTable.m \ MAPIStoreFolderTable.m \
MAPIStorePermissionsTable.m \ MAPIStorePermissionsTable.m \
\ \
MAPIStoreVolatileMessage.m \ MAPIStoreDBBaseContext.m \
\ MAPIStoreDBFolder.m \
MAPIStoreFSBaseContext.m \ MAPIStoreDBFolderTable.m \
MAPIStoreFSFolder.m \ MAPIStoreDBMessage.m \
MAPIStoreFSFolderTable.m \ MAPIStoreDBMessageTable.m \
MAPIStoreFSMessage.m \
MAPIStoreFSMessageTable.m \
\ \
MAPIStoreFAIMessage.m \ MAPIStoreFAIMessage.m \
MAPIStoreFAIMessageTable.m \ MAPIStoreFAIMessageTable.m \
@ -113,7 +114,10 @@ $(SOGOBACKEND)_OBJC_FILES += \
NSValue+MAPIStore.m \ NSValue+MAPIStore.m \
\ \
EOBitmaskQualifier.m \ EOBitmaskQualifier.m \
EOQualifier+MAPI.m \ \
GCSSpecialQueries+OpenChange.m\
\
EOQualifier+MAPI.m
$(SOGOBACKEND)_RESOURCE_FILES += \ $(SOGOBACKEND)_RESOURCE_FILES += \
@ -145,7 +149,13 @@ PLREADER_TOOL = plreader
$(PLREADER_TOOL)_OBJC_FILES += \ $(PLREADER_TOOL)_OBJC_FILES += \
plreader.m \ plreader.m \
TEST_TOOL_NAME += $(PLREADER_TOOL) DBMSGREADER_TOOL = dbmsgreader
$(DBMSGREADER_TOOL)_OBJC_FILES += \
dbmsgreader.m
$(DBMSGREADER_TOOL)_LIB_DIRS += -L../SoObjects/SOGo/ -lSOGo -lNGObjWeb
TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL)
### cflags and libs ### cflags and libs
LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags) LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags)

View File

@ -67,10 +67,10 @@
{ {
MAPIStoreEmbeddedMessage *msg; MAPIStoreEmbeddedMessage *msg;
if (isNew) // if (isNew)
msg = nil;
else
msg = nil; msg = nil;
// else
// msg = nil;
return msg; return msg;
} }

View File

@ -1111,9 +1111,7 @@
newAid = [[self attachmentKeys] count]; newAid = [[self attachmentKeys] count];
newAttachment = [MAPIStoreCalendarAttachment newAttachment = [MAPIStoreCalendarAttachment
mapiStoreObjectWithSOGoObject: nil mapiStoreObjectInContainer: self];
inContainer: self];
[newAttachment setIsNew: YES];
[newAttachment setAID: newAid]; [newAttachment setAID: newAid];
newKey = [NSString stringWithFormat: @"%ul", newAid]; newKey = [NSString stringWithFormat: @"%ul", newAid];
[attachmentParts setObject: newAttachment [attachmentParts setObject: newAttachment

View File

@ -35,6 +35,7 @@
#import <Mailer/NSString+Mail.h> #import <Mailer/NSString+Mail.h>
#import <SOGo/SOGoPermissions.h> #import <SOGo/SOGoPermissions.h>
#import "MAPIStoreAttachment.h"
#import "MAPIStoreContactsAttachment.h" #import "MAPIStoreContactsAttachment.h"
#import "MAPIStoreContactsFolder.h" #import "MAPIStoreContactsFolder.h"
#import "MAPIStorePropertySelectors.h" #import "MAPIStorePropertySelectors.h"
@ -767,8 +768,7 @@
|| [encoding isEqualToString: @"BASE64"]) || [encoding isEqualToString: @"BASE64"])
{ {
attachment = [MAPIStoreContactsAttachment attachment = [MAPIStoreContactsAttachment
mapiStoreObjectWithSOGoObject: nil mapiStoreObjectInContainer: self];
inContainer: self];
[attachment setAID: 0]; [attachment setAID: 0];
[attachment setPhoto: photo]; [attachment setPhoto: photo];
[attachmentParts setObject: attachment forKey: @"photo"]; [attachmentParts setObject: attachment forKey: @"photo"];

View File

@ -28,11 +28,9 @@
#import <NGObjWeb/WOContext+SoObjects.h> #import <NGObjWeb/WOContext+SoObjects.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import <SOGo/SOGoFolder.h>
#import <SOGo/SOGoUser.h> #import <SOGo/SOGoUser.h>
#import "SOGoMAPIFSFolder.h"
#import "SOGoMAPIFSMessage.h"
#import "MAPIStoreAttachment.h" #import "MAPIStoreAttachment.h"
// #import "MAPIStoreAttachmentTable.h" // #import "MAPIStoreAttachmentTable.h"
#import "MAPIStoreFallbackContext.h" #import "MAPIStoreFallbackContext.h"
@ -433,25 +431,29 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
[self ensureContextFolder]; [self ensureContextFolder];
currentFolder = [self rootSOGoFolder]; currentFolder = [self rootSOGoFolder];
[containersBag addObject: currentFolder];
path = [contextUrl path]; path = [contextUrl path];
if ([path hasPrefix: @"/"]) if ([path hasPrefix: @"/"])
path = [path substringFromIndex: 1]; path = [path substringFromIndex: 1];
if ([path hasSuffix: @"/"]) if ([path hasSuffix: @"/"])
path = [path substringToIndex: [path length] - 1]; path = [path substringToIndex: [path length] - 1];
pathComponents = [path componentsSeparatedByString: @"/"]; if ([path length] > 0)
max = [pathComponents count];
for (count = 0; currentFolder && count < max; count++)
{ {
[woContext setClientObject: currentFolder]; pathComponents = [path componentsSeparatedByString: @"/"];
currentFolder max = [pathComponents count];
= [currentFolder lookupName: [pathComponents objectAtIndex: count] for (count = 0; currentFolder && count < max; count++)
inContext: woContext {
[woContext setClientObject: currentFolder];
currentFolder = [currentFolder
lookupName: [pathComponents objectAtIndex: count]
inContext: woContext
acquire: NO]; acquire: NO];
if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all
SOGo folder types */ SOGo folder types */
[containersBag addObject: currentFolder]; [containersBag addObject: currentFolder];
else else
currentFolder = nil; currentFolder = nil;
}
} }
if (currentFolder) if (currentFolder)
@ -460,7 +462,6 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
mapiStoreObjectWithSOGoObject: currentFolder mapiStoreObjectWithSOGoObject: currentFolder
inContainer: nil]; inContainer: nil];
[baseFolder setContext: self]; [baseFolder setContext: self];
*folderPtr = baseFolder; *folderPtr = baseFolder;
rc = MAPISTORE_SUCCESS; rc = MAPISTORE_SUCCESS;
} }

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSBaseContext.h - this file is part of SOGo /* MAPIStoreDBBaseContext.h - this file is part of SOGo
* *
* Copyright (C) 2010 Inverse inc. * Copyright (C) 2012 Inverse inc.
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -20,13 +20,13 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef MAPISTOREFSBASECONTEXT_H #ifndef MAPISTOREDBBASECONTEXT_H
#define MAPISTOREFSBASECONTEXT_H #define MAPISTOREDBBASECONTEXT_H
#import "MAPIStoreContext.h" #import "MAPIStoreContext.h"
@interface MAPIStoreFSBaseContext : MAPIStoreContext @interface MAPIStoreDBBaseContext : MAPIStoreContext
@end @end
#endif /* MAPISTOREFSBASECONTEXT_H */ #endif /* MAPISTOREDBBASECONTEXT_H */

View File

@ -0,0 +1,116 @@
/* MAPIStoreDBBaseContext.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* A generic parent class for all context that will store their data on the
disk in the form of a plist. */
#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <NGExtensions/NSObject+Logs.h>
#import "MAPIStoreDBFolder.h"
#import "MAPIStoreMapping.h"
#import "MAPIStoreUserContext.h"
#import "SOGoMAPIDBFolder.h"
#import "MAPIStoreDBBaseContext.h"
#undef DEBUG
#include <mapistore/mapistore.h>
static Class MAPIStoreDBFolderK;
@implementation MAPIStoreDBBaseContext
+ (void) initialize
{
MAPIStoreDBFolderK = [MAPIStoreDBFolder class];
}
+ (NSString *) MAPIModuleName
{
return nil;
}
- (Class) MAPIStoreFolderClass
{
return MAPIStoreDBFolderK;
}
- (void) ensureContextFolder
{
SOGoMAPIDBFolder *currentFolder;
NSArray *parts;
NSMutableArray *folders;
NSString *folderName;
NSUInteger count, max;
parts = [[contextUrl path] componentsSeparatedByString: @"/"];
max = [parts count];
folders = [NSMutableArray arrayWithCapacity: max];
/* build the folder chain */
currentFolder = [self rootSOGoFolder];
[folders addObject: currentFolder];
for (count = 1; count < max; count++)
{
folderName = [parts objectAtIndex: count];
if ([folderName length] > 0)
{
currentFolder = [SOGoMAPIDBFolder objectWithName: folderName
inContainer: currentFolder];
[folders addObject: currentFolder];
}
}
/* ensure each folder in the chain actually exists, so that it becomes
"listable" in further operations */
max = [folders count];
for (count = 0; count < max; count++)
{
currentFolder = [folders objectAtIndex: count];
[currentFolder reloadIfNeeded];
if ([currentFolder isNew])
[currentFolder save];
}
}
- (id) rootSOGoFolder
{
SOGoMAPIDBFolder *folder;
[userContext ensureFolderTableExists];
folder = [SOGoMAPIDBFolder objectWithName: [isa MAPIModuleName]
inContainer: nil];
[folder setTableUrl: [userContext folderTableURL]];
// [folder reloadIfNeeded];
/* we don't need to set the "path prefix" of the folder since the module
name is used as the label for the top folder */
return folder;
}
@end

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSFolder.h - this file is part of SOGo /* MAPIStoreDBFolder.h - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -20,14 +20,14 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef MAPISTOREFSFOLDER_H #ifndef MAPISTOREDBFOLDER_H
#define MAPISTOREFSFOLDER_H #define MAPISTOREDBFOLDER_H
#import "MAPIStoreFolder.h" #import "MAPIStoreFolder.h"
@interface MAPIStoreFSFolder : MAPIStoreFolder @interface MAPIStoreDBFolder : MAPIStoreFolder
@end @end
#endif /* MAPISTOREFSFOLDER_H */ #endif /* MAPISTOREDBFOLDER_H */

View File

@ -1,4 +1,4 @@
/* MAPIStoreFSFolder.m - this file is part of SOGo /* MAPIStoreDBFolder.m - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2011 Inverse inc
* *
@ -31,15 +31,15 @@
#import <SOGo/SOGoUser.h> #import <SOGo/SOGoUser.h>
#import "EOQualifier+MAPI.h" #import "EOQualifier+MAPI.h"
#import "MAPIStoreContext.h" #import "MAPIStoreContext.h"
#import "MAPIStoreFSFolderTable.h" #import "MAPIStoreDBFolderTable.h"
#import "MAPIStoreFSMessage.h" #import "MAPIStoreDBMessage.h"
#import "MAPIStoreFSMessageTable.h" #import "MAPIStoreDBMessageTable.h"
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "MAPIStoreUserContext.h" #import "MAPIStoreUserContext.h"
#import "SOGoMAPIFSFolder.h" #import "SOGoMAPIDBFolder.h"
#import "SOGoMAPIFSMessage.h" #import "SOGoMAPIDBMessage.h"
#import "MAPIStoreFSFolder.h" #import "MAPIStoreDBFolder.h"
#undef DEBUG #undef DEBUG
#include <mapistore/mapistore.h> #include <mapistore/mapistore.h>
@ -57,39 +57,34 @@ static NSString *MAPIStoreRightCreateSubfolders = @"RightsCreateSubfolders";
static NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner"; static NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner";
static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact"; static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
@implementation MAPIStoreFSFolder @implementation MAPIStoreDBFolder
+ (void) initialize + (void) initialize
{ {
EOKeyValueQualifierK = [EOKeyValueQualifier class]; EOKeyValueQualifierK = [EOKeyValueQualifier class];
} }
- (void) setupAuxiliaryObjects
{
[super setupAuxiliaryObjects];
ASSIGN (sogoObject, dbFolder);
}
- (MAPIStoreMessageTable *) messageTable - (MAPIStoreMessageTable *) messageTable
{ {
return [MAPIStoreFSMessageTable tableForContainer: self]; return [MAPIStoreDBMessageTable tableForContainer: self];
} }
- (MAPIStoreFolderTable *) folderTable - (MAPIStoreFolderTable *) folderTable
{ {
return [MAPIStoreFSFolderTable tableForContainer: self]; return [MAPIStoreDBFolderTable tableForContainer: self];
} }
- (enum mapistore_error) createFolder: (struct SRow *) aRow - (enum mapistore_error) createFolder: (struct SRow *) aRow
withFID: (uint64_t) newFID withFID: (uint64_t) newFID
andKey: (NSString **) newKeyP andKey: (NSString **) newKeyP
{ {
NSString *newKey, *urlString; *newKeyP = [NSString stringWithFormat: @"0x%.16"PRIx64, (unsigned long long) newFID];
NSURL *childURL;
SOGoMAPIFSFolder *childFolder;
newKey = [NSString stringWithFormat: @"0x%.16"PRIx64, (unsigned long long) newFID];
urlString = [NSString stringWithFormat: @"%@/%@", [self url], newKey];
childURL = [NSURL URLWithString: [urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
childFolder = [SOGoMAPIFSFolder folderWithURL: childURL
andTableType: MAPISTORE_MESSAGE_TABLE];
[childFolder ensureDirectory];
*newKeyP = newKey;
return MAPISTORE_SUCCESS; return MAPISTORE_SUCCESS;
} }
@ -97,14 +92,15 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
- (MAPIStoreMessage *) createMessage - (MAPIStoreMessage *) createMessage
{ {
MAPIStoreMessage *newMessage; MAPIStoreMessage *newMessage;
SOGoMAPIFSMessage *fsObject; SOGoMAPIDBMessage *fsObject;
NSString *newKey; NSString *newKey;
newKey = [NSString stringWithFormat: @"%@.plist", newKey = [NSString stringWithFormat: @"%@.plist",
[SOGoObject globallyUniqueObjectId]]; [SOGoObject globallyUniqueObjectId]];
fsObject = [SOGoMAPIFSMessage objectWithName: newKey fsObject = [SOGoMAPIDBMessage objectWithName: newKey
inContainer: sogoObject]; inContainer: sogoObject];
newMessage = [MAPIStoreFSMessage mapiStoreObjectWithSOGoObject: fsObject [fsObject setObjectType: MAPIDBObjectTypeMessage];
newMessage = [MAPIStoreDBMessage mapiStoreObjectWithSOGoObject: fsObject
inContainer: self]; inContainer: self];
return newMessage; return newMessage;
@ -119,9 +115,10 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
ownerUser = [[self userContext] sogoUser]; ownerUser = [[self userContext] sogoUser];
if ([[context activeUser] isEqual: ownerUser] if ([[context activeUser] isEqual: ownerUser]
|| [self subscriberCanReadMessages]) || [self subscriberCanReadMessages])
keys = [(SOGoMAPIFSFolder *) sogoObject keys = [(SOGoMAPIDBFolder *) sogoObject childKeysOfType: MAPIDBObjectTypeMessage
toOneRelationshipKeysMatchingQualifier: qualifier includeDeleted: NO
andSortOrderings: sortOrderings]; matchingQualifier: qualifier
andSortOrderings: sortOrderings];
else else
keys = [NSArray array]; keys = [NSArray array];
@ -131,39 +128,17 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier - (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings andSortOrderings: (NSArray *) sortOrderings
{ {
NSArray *entries; return [dbFolder childKeysOfType: MAPIDBObjectTypeFolder
NSMutableArray *filteredEntries; includeDeleted: NO
NSUInteger count, max; matchingQualifier: qualifier
MAPIStoreFSFolder *subfolder; andSortOrderings: sortOrderings];
SOGoMAPIFSMessage *propertiesMessage;
NSString *subfolderKey;
entries = [(SOGoMAPIFSFolder *) sogoObject toManyRelationshipKeys];
if (qualifier)
{
max = [entries count];
filteredEntries = [NSMutableArray arrayWithCapacity: max];
for (count = 0; count < max; count++)
{
subfolderKey = [entries objectAtIndex: count];
subfolder = [self lookupFolder: subfolderKey];
propertiesMessage = [subfolder propertiesMessage];
if ([qualifier evaluateMAPIVolatileMessage: propertiesMessage])
[filteredEntries addObject: subfolderKey];
}
entries = filteredEntries;
}
if (sortOrderings)
[self errorWithFormat: @"sort orderings are not used for folders"];
return entries;
} }
- (NSDate *) lastMessageModificationTime - (NSDate *) lastMessageModificationTime
{ {
NSUInteger count, max; NSUInteger count, max;
NSDate *date, *fileDate; NSDate *date, *fileDate;
MAPIStoreFSMessage *msg; MAPIStoreDBMessage *msg;
NSArray *messageKeys; NSArray *messageKeys;
messageKeys = [self messageKeys]; messageKeys = [self messageKeys];
@ -189,7 +164,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
- (SOGoFolder *) aclFolder - (SOGoFolder *) aclFolder
{ {
return propsFolder; return sogoObject;
} }
- (NSArray *) rolesForExchangeRights: (uint32_t) rights - (NSArray *) rolesForExchangeRights: (uint32_t) rights

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSFolderTable.h - this file is part of SOGo /* MAPIStoreDBFolderTable.h - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -20,12 +20,12 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef MAPISTOREFSFOLDERTABLE_H #ifndef MAPISTOREDBFOLDERTABLE_H
#define MAPISTOREFSFOLDERTABLE_H #define MAPISTOREDBFOLDERTABLE_H
#import "MAPIStoreFolderTable.h" #import "MAPIStoreFolderTable.h"
@interface MAPIStoreFSFolderTable : MAPIStoreFolderTable @interface MAPIStoreDBFolderTable : MAPIStoreFolderTable
@end @end
#endif /* MAPISTOREFSFOLDERTABLE_H */ #endif /* MAPISTOREDBFOLDERTABLE_H */

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSFolderTable.m - this file is part of SOGo /* MAPIStoreDBFolderTable.m - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -24,9 +24,9 @@
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "MAPIStoreFSFolderTable.h" #import "MAPIStoreDBFolderTable.h"
@implementation MAPIStoreFSFolderTable @implementation MAPIStoreDBFolderTable
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property - (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
{ {

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSMessage.h - this file is part of SOGo /* MAPIStoreDBMessage.h - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -20,12 +20,12 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef MAPISTOREFSMESSAGE_H #ifndef MAPISTOREDBMESSAGE_H
#define MAPISTOREFSMESSAGE_H #define MAPISTOREDBMESSAGE_H
#import "MAPIStoreVolatileMessage.h" #import "MAPIStoreMessage.h"
@interface MAPIStoreFSMessage : MAPIStoreVolatileMessage @interface MAPIStoreDBMessage : MAPIStoreMessage
@end @end
#endif /* MAPISTOREFSMESSAGE_H */ #endif /* MAPISTOREDBMESSAGE_H */

View File

@ -1,4 +1,4 @@
/* MAPIStoreFSMessage.m - this file is part of SOGo /* MAPIStoreDBMessage.m - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2011 Inverse inc
* *
@ -21,24 +21,25 @@
*/ */
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
#import <Foundation/NSValue.h> #import <Foundation/NSValue.h>
#import <NGExtensions/NSObject+Logs.h> #import <NGExtensions/NSObject+Logs.h>
#import "MAPIStoreContext.h" #import "MAPIStoreContext.h"
#import "MAPIStorePropertySelectors.h" #import "MAPIStorePropertySelectors.h"
#import "SOGoMAPIFSMessage.h" #import "SOGoMAPIDBMessage.h"
#import "MAPIStoreFSFolder.h" #import "MAPIStoreDBFolder.h"
#import "MAPIStoreFSMessage.h" #import "MAPIStoreDBMessage.h"
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h" #import "NSObject+MAPIStore.h"
#undef DEBUG #undef DEBUG
#include <mapistore/mapistore.h> #include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h> #include <mapistore/mapistore_errors.h>
@implementation MAPIStoreFSMessage @implementation MAPIStoreDBMessage
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP + (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
@ -60,13 +61,96 @@
/* FIXME (hack): append a few undocumented properties that can be added to /* FIXME (hack): append a few undocumented properties that can be added to
FAI messages */ FAI messages */
for (count = 0; count < 8; count++) for (count = 0; count < 8; count++)
properties->aulPropTag[MAPIStoreSupportedPropertiesCount+count] = faiProperties[count]; properties->aulPropTag[MAPIStoreSupportedPropertiesCount+count]
= faiProperties[count];
*propertiesP = properties; *propertiesP = properties;
return MAPISTORE_SUCCESS; return MAPISTORE_SUCCESS;
} }
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer
{
if ((self = [super initWithSOGoObject: newSOGoObject
inContainer: newContainer]))
{
[properties release];
properties = [newSOGoObject properties];
[properties retain];
}
return self;
}
- (uint64_t) objectVersion
{
NSNumber *versionNbr;
uint64_t objectVersion;
[(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded];
versionNbr = [properties objectForKey: @"version"];
if (versionNbr)
objectVersion = [versionNbr unsignedLongLongValue];
else
objectVersion = ULLONG_MAX;
return objectVersion;
}
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
{
[sogoObject reloadIfNeeded];
return [super getProperties: data
withTags: tags
andCount: columnCount
inMemCtx: memCtx];
}
- (int) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
{
id value;
int rc;
value = [properties objectForKey: MAPIPropertyKey (propTag)];
if (value)
rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
else
rc = [super getProperty: data withTag: propTag inMemCtx: memCtx];
return rc;
}
- (int) getPidTagSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
id value;
int rc;
value = [properties
objectForKey: MAPIPropertyKey (PidTagNormalizedSubject)];
if (value)
rc = [value getValue: data forTag: PidTagNormalizedSubject
inMemCtx: memCtx];
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
- (void) addProperties: (NSDictionary *) newNewProperties
{
[sogoObject reloadIfNeeded];
[super addProperties: newNewProperties];
}
- (void) save - (void) save
{ {
uint64_t newVersion; uint64_t newVersion;
@ -76,13 +160,11 @@
newVersion = exchange_globcnt ([[self context] getNewChangeNumber] >> 16); newVersion = exchange_globcnt ([[self context] getNewChangeNumber] >> 16);
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion] [properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
forKey: @"version"]; forKey: @"version"];
[self logWithFormat: @"%d props in dict", [properties count]]; [self logWithFormat: @"%d props in dict", [properties count]];
[sogoObject appendProperties: properties];
[sogoObject save]; [sogoObject save];
[properties removeAllObjects];
} }
- (BOOL) _messageIsFreeBusy - (BOOL) _messageIsFreeBusy
@ -91,7 +173,7 @@
/* This is a HACK until we figure out how to determine a message position in /* This is a HACK until we figure out how to determine a message position in
the mailbox hierarchy.... (missing: folderid and role) */ the mailbox hierarchy.... (missing: folderid and role) */
msgClass = [[sogoObject properties] msgClass = [properties
objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)]; objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)];
return [msgClass isEqualToString: @"IPM.Microsoft.ScheduleData.FreeBusy"]; return [msgClass isEqualToString: @"IPM.Microsoft.ScheduleData.FreeBusy"];
@ -115,12 +197,12 @@
- (NSDate *) creationTime - (NSDate *) creationTime
{ {
return [sogoObject creationTime]; return [sogoObject creationDate];
} }
- (NSDate *) lastModificationTime - (NSDate *) lastModificationTime
{ {
return [sogoObject lastModificationTime]; return [sogoObject lastModified];
} }
@end @end

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSMessageTable.h - this file is part of SOGo /* MAPIStoreDBMessageTable.h - this file is part of SOGo
* *
* Copyright (C) 2010 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -20,12 +20,12 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef MAPISTOREFSMESSAGETABLE_H #ifndef MAPISTOREDBMESSAGETABLE_H
#define MAPISTOREFSMESSAGETABLE_H #define MAPISTOREDBMESSAGETABLE_H
#import "MAPIStoreMessageTable.h" #import "MAPIStoreMessageTable.h"
@interface MAPIStoreFSMessageTable : MAPIStoreMessageTable @interface MAPIStoreDBMessageTable : MAPIStoreMessageTable
@end @end
#endif /* MAPISTOREFSMESSAGETABLE_H */ #endif /* MAPISTOREDBMESSAGETABLE_H */

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSMessageTable.m - this file is part of SOGo /* MAPIStoreDBMessageTable.m - this file is part of SOGo
* *
* Copyright (C) 2010 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -25,25 +25,25 @@
#import <EOControl/EOQualifier.h> #import <EOControl/EOQualifier.h>
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "MAPIStoreFSMessage.h" #import "MAPIStoreDBMessage.h"
#import "MAPIStoreFSMessageTable.h" #import "MAPIStoreDBMessageTable.h"
#undef DEBUG #undef DEBUG
#include <mapistore/mapistore.h> #include <mapistore/mapistore.h>
static Class MAPIStoreFSMessageK = Nil; static Class MAPIStoreDBMessageK = Nil;
@implementation MAPIStoreFSMessageTable @implementation MAPIStoreDBMessageTable
+ (void) initialize + (void) initialize
{ {
MAPIStoreFSMessageK = [MAPIStoreFSMessage class]; MAPIStoreDBMessageK = [MAPIStoreDBMessage class];
} }
+ (Class) childObjectClass + (Class) childObjectClass
{ {
return MAPIStoreFSMessageK; return MAPIStoreDBMessageK;
} }
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property - (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property

View File

@ -23,9 +23,9 @@
#ifndef MAPISTOREFAIMESSAGE_H #ifndef MAPISTOREFAIMESSAGE_H
#define MAPISTOREFAIMESSAGE_H #define MAPISTOREFAIMESSAGE_H
#import "MAPIStoreFSMessage.h" #import "MAPIStoreDBMessage.h"
@interface MAPIStoreFAIMessage : MAPIStoreFSMessage @interface MAPIStoreFAIMessage : MAPIStoreDBMessage
@end @end
#endif /* MAPISTOREFAIMESSAGE_H */ #endif /* MAPISTOREFAIMESSAGE_H */

View File

@ -23,9 +23,9 @@
#ifndef MAPISTOREFAIMESSAGETABLE_H #ifndef MAPISTOREFAIMESSAGETABLE_H
#define MAPISTOREFAIMESSAGETABLE_H #define MAPISTOREFAIMESSAGETABLE_H
#import "MAPIStoreFSMessageTable.h" #import "MAPIStoreDBMessageTable.h"
@interface MAPIStoreFAIMessageTable : MAPIStoreFSMessageTable @interface MAPIStoreFAIMessageTable : MAPIStoreDBMessageTable
@end @end
#endif /* MAPISTOREFAIMESSAGETABLE_H */ #endif /* MAPISTOREFAIMESSAGETABLE_H */

View File

@ -1,79 +0,0 @@
/* MAPIStoreFSBaseContext.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* A generic parent class for all context that will store their data on the
disk in the form of a plist. */
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <NGExtensions/NSObject+Logs.h>
#import "MAPIStoreFSFolder.h"
#import "MAPIStoreMapping.h"
#import "MAPIStoreUserContext.h"
#import "SOGoMAPIFSFolder.h"
#import "MAPIStoreFSBaseContext.h"
#undef DEBUG
#include <mapistore/mapistore.h>
static Class MAPIStoreFSFolderK;
@implementation MAPIStoreFSBaseContext
+ (void) initialize
{
MAPIStoreFSFolderK = [MAPIStoreFSFolder class];
}
+ (NSString *) MAPIModuleName
{
return nil;
}
- (Class) MAPIStoreFolderClass
{
return MAPIStoreFSFolderK;
}
- (void) ensureContextFolder
{
SOGoMAPIFSFolder *contextFolder;
contextFolder = [SOGoMAPIFSFolder folderWithURL: contextUrl
andTableType: MAPISTORE_MESSAGE_TABLE];
[contextFolder ensureDirectory];
}
- (id) rootSOGoFolder
{
NSString *urlString;
urlString = [NSString stringWithFormat: @"sogo://%@@%@/",
[userContext username], [isa MAPIModuleName]];
return [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: urlString]
andTableType: MAPISTORE_MESSAGE_TABLE];
}
@end

View File

@ -23,9 +23,9 @@
#ifndef MAPISTOREFALLBACKCONTEXT_H #ifndef MAPISTOREFALLBACKCONTEXT_H
#define MAPISTOREFALLBACKCONTEXT_H #define MAPISTOREFALLBACKCONTEXT_H
#import "MAPIStoreFSBaseContext.h" #import "MAPIStoreDBBaseContext.h"
@interface MAPIStoreFallbackContext : MAPIStoreFSBaseContext @interface MAPIStoreFallbackContext : MAPIStoreDBBaseContext
@end @end

View File

@ -26,7 +26,7 @@
#import "MAPIStoreUserContext.h" #import "MAPIStoreUserContext.h"
#import "NSString+MAPIStore.h" #import "NSString+MAPIStore.h"
#import "SOGoMAPIFSFolder.h" #import "SOGoMAPIDBFolder.h"
#import "MAPIStoreFallbackContext.h" #import "MAPIStoreFallbackContext.h"
@ -51,10 +51,11 @@
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
struct mapistore_contexts_list *firstContext = NULL, *context; struct mapistore_contexts_list *firstContext = NULL, *context;
SOGoMAPIFSFolder *root; SOGoMAPIDBFolder *root;
NSArray *names; NSArray *names;
NSUInteger count, max; NSUInteger count, max;
NSString *baseURL, *url, *name; NSString *baseURL, *url, *name;
MAPIStoreUserContext *userContext;
baseURL = [NSString stringWithFormat: @"sogo://%@@fallback/", userName]; baseURL = [NSString stringWithFormat: @"sogo://%@@fallback/", userName];
@ -67,11 +68,15 @@
DLIST_ADD_END (firstContext, context, void); DLIST_ADD_END (firstContext, context, void);
/* Maybe emsmdbp_provisioning should be fixed in order to only take the uri /* Maybe emsmdbp_provisioning should be fixed in order to only take the uri
returned above to avoid deleting its entries... */ returned above to avoid deleting its entries... */
root = [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: baseURL] root = [SOGoMAPIDBFolder objectWithName: [self MAPIModuleName]
andTableType: MAPISTORE_MESSAGE_TABLE]; inContainer: nil];
[root setOwner: userName];
userContext = [MAPIStoreUserContext userContextWithUsername: userName
andTDBIndexing: indexingTdb];
[userContext ensureFolderTableExists];
[root setTableUrl: [userContext folderTableURL]];
names = [root toManyRelationshipKeys]; names = [root toManyRelationshipKeys];
max = [names count]; max = [names count];
for (count = 0; count < max; count++) for (count = 0; count < max; count++)

View File

@ -38,29 +38,34 @@
@class MAPIStoreMessageTable; @class MAPIStoreMessageTable;
@class MAPIStorePermissionsTable; @class MAPIStorePermissionsTable;
@class SOGoFolder; @class SOGoFolder;
@class SOGoMAPIFSFolder; @class SOGoMAPIDBFolder;
@class SOGoMAPIFSMessage; @class SOGoMAPIDBMessage;
#import "MAPIStoreObject.h" #import "MAPIStoreSOGoObject.h"
@interface MAPIStoreFolder : MAPIStoreObject @interface MAPIStoreFolder : MAPIStoreSOGoObject
{ {
MAPIStoreContext *context; MAPIStoreContext *context;
// NSArray *messageKeys; // NSArray *messageKeys;
// NSArray *faiMessageKeys; // NSArray *faiMessageKeys;
// NSArray *folderKeys; // NSArray *folderKeys;
SOGoMAPIFSFolder *faiFolder; SOGoMAPIDBFolder *dbFolder;
SOGoMAPIFSFolder *propsFolder; // SOGoMAPIDBFolder *faiFolder;
SOGoMAPIFSMessage *propsMessage; // SOGoMAPIDBFolder *propsFolder;
// SOGoMAPIDBMessage *propsMessage;
} }
- (void) setContext: (MAPIStoreContext *) newContext; - (void) setContext: (MAPIStoreContext *) newContext;
- (void) setupAuxiliaryObjects;
- (SOGoMAPIDBFolder *) dbFolder;
- (NSArray *) activeMessageTables; - (NSArray *) activeMessageTables;
- (NSArray *) activeFAIMessageTables; - (NSArray *) activeFAIMessageTables;
- (SOGoMAPIFSMessage *) propertiesMessage; // - (SOGoMAPIDBMessage *) propertiesMessage;
- (id) lookupMessageByURL: (NSString *) messageURL; - (id) lookupMessageByURL: (NSString *) messageURL;
- (id) lookupFolderByURL: (NSString *) folderURL; - (id) lookupFolderByURL: (NSString *) folderURL;

View File

@ -48,8 +48,8 @@
#import "NSDate+MAPIStore.h" #import "NSDate+MAPIStore.h"
#import "NSString+MAPIStore.h" #import "NSString+MAPIStore.h"
#import "NSObject+MAPIStore.h" #import "NSObject+MAPIStore.h"
#import "SOGoMAPIFSFolder.h" #import "SOGoMAPIDBFolder.h"
#import "SOGoMAPIFSMessage.h" #import "SOGoMAPIDBMessage.h"
#include <gen_ndr/exchange.h> #include <gen_ndr/exchange.h>
@ -79,33 +79,67 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
// messageKeys = nil; // messageKeys = nil;
// faiMessageKeys = nil; // faiMessageKeys = nil;
// folderKeys = nil; // folderKeys = nil;
faiFolder = nil; dbFolder = nil;
context = nil; context = nil;
propsFolder = nil; // propsFolder = nil;
propsMessage = nil; // propsMessage = nil;
} }
return self; return self;
} }
- (void) _setupAuxiliaryObjects - (void) setupAuxiliaryObjects
{ {
NSURL *propsURL; NSURL *folderURL;
NSString *urlString; NSMutableString *pathPrefix;
NSString *path, *folderName;
NSArray *parts;
NSUInteger lastPartIdx;
MAPIStoreUserContext *userContext;
folderURL = [NSURL URLWithString: [self url]];
path = [folderURL path];
path = [path substringFromIndex: 1];
if ([path length] > 0)
{
parts = [path componentsSeparatedByString: @"/"];
lastPartIdx = [parts count] - 1;
if ([path hasSuffix: @"/"])
lastPartIdx--;
folderName = [parts objectAtIndex: lastPartIdx];
}
else
folderName = [folderURL host];
userContext = [self userContext];
[userContext ensureFolderTableExists];
ASSIGN (dbFolder,
[SOGoMAPIDBFolder objectWithName: folderName
inContainer: [container dbFolder]]);
[dbFolder setTableUrl: [userContext folderTableURL]];
if (!container && [path length] > 0)
{
pathPrefix = [NSMutableString stringWithCapacity: 64];
[pathPrefix appendFormat: @"/%@", [folderURL host]];
parts = [parts subarrayWithRange: NSMakeRange (0, lastPartIdx)];
if ([parts count] > 0)
[pathPrefix appendFormat: @"/%@", [parts componentsJoinedByString: @"/"]];
[dbFolder setPathPrefix: pathPrefix];
}
[dbFolder reloadIfNeeded];
/* propsMessage and self share the same properties dictionary */
// ASSIGN (propsMessage,
// [SOGoMAPIDBMessage objectWithName: @"properties.plist"
// inContainer: dbFolder]);
// [propsMessage setObjectType: MAPIDBObjectTypeInternal];
// [propsMessage reloadIfNeeded];
[properties release];
properties = [dbFolder properties];
[properties retain];
urlString = [[self url] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
propsURL = [NSURL URLWithString: urlString];
[self logWithFormat: @"_setupAuxiliaryObjects: %@", propsURL];
ASSIGN (faiFolder,
[SOGoMAPIFSFolder folderWithURL: propsURL
andTableType: MAPISTORE_FAI_TABLE]);
ASSIGN (propsFolder,
[SOGoMAPIFSFolder folderWithURL: propsURL
andTableType: MAPISTORE_FOLDER_TABLE]);
ASSIGN (propsMessage,
[SOGoMAPIFSMessage objectWithName: @"properties.plist"
inContainer: propsFolder]);
[self setupVersionsMessage]; [self setupVersionsMessage];
} }
@ -119,7 +153,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
inContainer: newContainer]) inContainer: newContainer])
&& newContainer) && newContainer)
{ {
[self _setupAuxiliaryObjects]; [self setupAuxiliaryObjects];
} }
return self; return self;
@ -129,13 +163,13 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
{ {
ASSIGN (context, newContext); ASSIGN (context, newContext);
if (newContext) if (newContext)
[self _setupAuxiliaryObjects]; [self setupAuxiliaryObjects];
} }
- (MAPIStoreContext *) context - (MAPIStoreContext *) context
{ {
if (!context) if (!context)
[self setContext: [container context]]; [self setContext: (MAPIStoreContext *) [container context]];
return context; return context;
} }
@ -145,29 +179,31 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
// [messageKeys release]; // [messageKeys release];
// [faiMessageKeys release]; // [faiMessageKeys release];
// [folderKeys release]; // [folderKeys release];
[propsMessage release]; // [propsMessage release];
[propsFolder release]; [dbFolder release];
[faiFolder release];
[context release]; [context release];
[super dealloc]; [super dealloc];
} }
- (SOGoMAPIDBFolder *) dbFolder
{
return dbFolder;
}
/* backend interface */ /* backend interface */
- (SOGoMAPIFSMessage *) propertiesMessage // - (SOGoMAPIDBMessage *) propertiesMessage
{ // {
return propsMessage; // return propsMessage;
} // }
- (uint64_t) objectVersion - (uint64_t) objectVersion
{ {
NSNumber *value; NSNumber *value;
NSDictionary *props;
uint64_t cn; uint64_t cn;
props = [propsMessage properties]; value = [properties objectForKey: MAPIPropertyKey (PidTagChangeNumber)];
value = [props objectForKey: MAPIPropertyKey (PidTagChangeNumber)];
if (value) if (value)
cn = [value unsignedLongLongValue]; cn = [value unsignedLongLongValue];
else else
@ -175,10 +211,10 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
[self logWithFormat: @"no value for PidTagChangeNumber, adding one now"]; [self logWithFormat: @"no value for PidTagChangeNumber, adding one now"];
cn = [[self context] getNewChangeNumber]; cn = [[self context] getNewChangeNumber];
value = [NSNumber numberWithUnsignedLongLong: cn]; value = [NSNumber numberWithUnsignedLongLong: cn];
props = [NSDictionary dictionaryWithObject: value
forKey: MAPIPropertyKey (PidTagChangeNumber)]; [properties setObject: value
[propsMessage appendProperties: props]; forKey: MAPIPropertyKey (PidTagChangeNumber)];
[propsMessage save]; [dbFolder save];
} }
return cn >> 16; return cn >> 16;
@ -186,21 +222,24 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (id) lookupFolder: (NSString *) folderKey - (id) lookupFolder: (NSString *) folderKey
{ {
MAPIStoreFolder *childFolder = nil; MAPIStoreFolder *childFolder;
SOGoFolder *sogoFolder; SOGoFolder *sogoFolder;
WOContext *woContext; WOContext *woContext;
if ([[self folderKeys] containsObject: folderKey]) if ([[self folderKeys] containsObject: folderKey])
{ {
woContext = [[self userContext] woContext]; woContext = [[self userContext] woContext];
sogoFolder = [sogoObject lookupName: folderKey sogoFolder = [sogoObject lookupName: folderKey inContext: woContext
inContext: woContext
acquire: NO]; acquire: NO];
[sogoFolder setContext: woContext];
if (sogoFolder && ![sogoFolder isKindOfClass: NSExceptionK]) if (sogoFolder && ![sogoFolder isKindOfClass: NSExceptionK])
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder {
inContainer: self]; [sogoFolder setContext: woContext];
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder
inContainer: self];
}
} }
else
childFolder = nil;
return childFolder; return childFolder;
} }
@ -264,9 +303,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
{ {
if ([[self faiMessageKeys] containsObject: messageKey]) if ([[self faiMessageKeys] containsObject: messageKey])
{ {
msgObject = [faiFolder lookupName: messageKey msgObject = [dbFolder lookupName: messageKey
inContext: nil inContext: nil
acquire: NO]; acquire: NO];
childMessage childMessage
= [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: msgObject = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: msgObject
inContainer: self]; inContainer: self];
@ -383,9 +422,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (int) deleteFolder - (int) deleteFolder
{ {
[propsMessage delete]; // [propsMessage delete];
[propsFolder delete]; [dbFolder delete];
[faiFolder delete];
[self cleanupCaches]; [self cleanupCaches];
@ -1004,7 +1042,11 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
/* TODO: this should no longer be required once mapistore v2 API is in /* TODO: this should no longer be required once mapistore v2 API is in
place, when we can then do this from -dealloc below */ place, when we can then do this from -dealloc below */
[dbFolder reloadIfNeeded];
propsCopy = [newProperties mutableCopy]; propsCopy = [newProperties mutableCopy];
[propsCopy autorelease];
currentProp = bannedProps; currentProp = bannedProps;
while (*currentProp) while (*currentProp)
{ {
@ -1012,9 +1054,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
currentProp++; currentProp++;
} }
[propsMessage appendProperties: propsCopy]; [properties addEntriesFromDictionary: propsCopy];
[propsMessage save]; [dbFolder save];
[propsCopy release];
} }
- (NSArray *) messageKeys - (NSArray *) messageKeys
@ -1039,9 +1080,10 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier - (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings andSortOrderings: (NSArray *) sortOrderings
{ {
return [faiFolder return [dbFolder childKeysOfType: MAPIDBObjectTypeFAI
toOneRelationshipKeysMatchingQualifier: qualifier includeDeleted: NO
andSortOrderings: sortOrderings]; matchingQualifier: qualifier
andSortOrderings: sortOrderings];
} }
- (NSArray *) faiMessageKeys - (NSArray *) faiMessageKeys
@ -1287,6 +1329,19 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
return MAPISTORE_SUCCESS; return MAPISTORE_SUCCESS;
} }
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
inMemCtx: (TALLOC_CTX *) memCtx
{
[dbFolder reloadIfNeeded];
return [super getProperties: data
withTags: tags
andCount: columnCount
inMemCtx: memCtx];
}
- (int) getProperty: (void **) data - (int) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
@ -1294,8 +1349,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
int rc; int rc;
id value; id value;
value = [[propsMessage properties] value = [properties objectForKey: MAPIPropertyKey (propTag)];
objectForKey: MAPIPropertyKey (propTag)];
if (value) if (value)
rc = [value getValue: data forTag: propTag inMemCtx: memCtx]; rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
else else
@ -1307,13 +1361,15 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (MAPIStoreMessage *) _createAssociatedMessage - (MAPIStoreMessage *) _createAssociatedMessage
{ {
MAPIStoreMessage *newMessage; MAPIStoreMessage *newMessage;
SOGoMAPIFSMessage *fsObject; SOGoMAPIDBMessage *dbObject;
NSString *newKey; NSString *newKey;
newKey = [NSString stringWithFormat: @"%@.plist", newKey = [NSString stringWithFormat: @"%@.plist",
[SOGoObject globallyUniqueObjectId]]; [SOGoObject globallyUniqueObjectId]];
fsObject = [SOGoMAPIFSMessage objectWithName: newKey inContainer: faiFolder]; dbObject = [SOGoMAPIDBMessage objectWithName: newKey inContainer: dbFolder];
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: fsObject [dbObject setObjectType: MAPIDBObjectTypeFAI];
[dbObject setIsNew: YES];
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: dbObject
inContainer: self]; inContainer: self];
return newMessage; return newMessage;
@ -1328,9 +1384,15 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
newMessage = [self _createAssociatedMessage]; newMessage = [self _createAssociatedMessage];
else else
newMessage = [self createMessage]; newMessage = [self createMessage];
[newMessage setIsNew: YES]; /* FIXME: this is ugly as the specifics of message creation should all be
delegated to subclasses */
if ([newMessage respondsToSelector: @selector (setIsNew:)])
[newMessage setIsNew: YES];
woContext = [[self userContext] woContext]; woContext = [[self userContext] woContext];
[[newMessage sogoObject] setContext: woContext]; /* FIXME: this is ugly too as the specifics of message creation should all
be delegated to subclasses */
if ([newMessage respondsToSelector: @selector (sogoObject:)])
[[newMessage sogoObject] setContext: woContext];
return newMessage; return newMessage;
} }
@ -1598,12 +1660,12 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (NSDate *) creationTime - (NSDate *) creationTime
{ {
return [propsMessage creationTime]; return [dbFolder creationDate];
} }
- (NSDate *) lastModificationTime - (NSDate *) lastModificationTime
{ {
return [propsMessage lastModificationTime]; return [dbFolder lastModified];
} }
/* subclasses */ /* subclasses */

View File

@ -34,7 +34,7 @@
@interface MAPIStoreGCSFolder : MAPIStoreFolder @interface MAPIStoreGCSFolder : MAPIStoreFolder
{ {
SOGoMAPIFSMessage *versionsMessage; SOGoMAPIDBMessage *versionsMessage;
NSArray *activeUserRoles; NSArray *activeUserRoles;
EOQualifier *componentQualifier; EOQualifier *componentQualifier;
} }

View File

@ -40,7 +40,7 @@
#import "NSData+MAPIStore.h" #import "NSData+MAPIStore.h"
#import "NSDate+MAPIStore.h" #import "NSDate+MAPIStore.h"
#import "NSString+MAPIStore.h" #import "NSString+MAPIStore.h"
#import "SOGoMAPIFSMessage.h" #import "SOGoMAPIDBMessage.h"
#import "MAPIStoreGCSFolder.h" #import "MAPIStoreGCSFolder.h"
@ -71,8 +71,9 @@ static Class NSNumberK;
- (void) setupVersionsMessage - (void) setupVersionsMessage
{ {
ASSIGN (versionsMessage, ASSIGN (versionsMessage,
[SOGoMAPIFSMessage objectWithName: @"versions.plist" [SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: propsFolder]); inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
} }
- (void) dealloc - (void) dealloc
@ -288,7 +289,8 @@ static Class NSNumberK;
forKey: @"PredecessorChangeList"]; forKey: @"PredecessorChangeList"];
[changeList release]; [changeList release];
} }
[changeList setObject: globCnt forKey: guid]; [changeList setObject: globCnt
forKey: guid];
} }
- (EOQualifier *) componentQualifier - (EOQualifier *) componentQualifier
@ -349,6 +351,7 @@ static Class NSNumberK;
[sortOrdering retain]; [sortOrdering retain];
} }
[versionsMessage reloadIfNeeded];
currentProperties = [versionsMessage properties]; currentProperties = [versionsMessage properties];
lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"]; lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"];
@ -451,7 +454,6 @@ static Class NSNumberK;
forKey: @"SyncLastSynchronisationDate"]; forKey: @"SyncLastSynchronisationDate"];
[currentProperties setObject: lastModificationDate [currentProperties setObject: lastModificationDate
forKey: @"SyncLastModificationDate"]; forKey: @"SyncLastModificationDate"];
[versionsMessage appendProperties: currentProperties];
[versionsMessage save]; [versionsMessage save];
} }
} }

View File

@ -30,9 +30,11 @@
@interface MAPIStoreMailAttachment : MAPIStoreAttachment @interface MAPIStoreMailAttachment : MAPIStoreAttachment
{ {
NSDictionary *bodyInfo; NSDictionary *bodyInfo;
SOGoMailBodyPart *bodyPart;
} }
- (void) setBodyInfo: (NSDictionary *) newBodyInfo; - (void) setBodyInfo: (NSDictionary *) newBodyInfo;
- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart;
@end @end

View File

@ -52,6 +52,7 @@
if ((self = [super init])) if ((self = [super init]))
{ {
bodyInfo = nil; bodyInfo = nil;
bodyPart = nil;
} }
return self; return self;
@ -60,6 +61,7 @@
- (void) dealloc - (void) dealloc
{ {
[bodyInfo release]; [bodyInfo release];
[bodyPart release];
[super dealloc]; [super dealloc];
} }
@ -68,6 +70,11 @@
ASSIGN (bodyInfo, newBodyInfo); ASSIGN (bodyInfo, newBodyInfo);
} }
- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart
{
ASSIGN (bodyPart, newBodyPart);
}
- (int) getPidTagAttachMethod: (void **) data - (int) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
@ -187,7 +194,7 @@
- (int) getPidTagAttachDataBinary: (void **) data - (int) getPidTagAttachDataBinary: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
*data = [[sogoObject fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx]; *data = [[bodyPart fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS; return MAPISTORE_SUCCESS;
} }

View File

@ -36,7 +36,7 @@
@interface MAPIStoreMailFolder : MAPIStoreFolder @interface MAPIStoreMailFolder : MAPIStoreFolder
{ {
SOGoMAPIFSMessage *versionsMessage; SOGoMAPIDBMessage *versionsMessage;
} }
- (BOOL) ensureFolderExists; - (BOOL) ensureFolderExists;

View File

@ -54,9 +54,8 @@
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h" #import "NSData+MAPIStore.h"
#import "NSString+MAPIStore.h" #import "NSString+MAPIStore.h"
#import "SOGoMAPIFSMessage.h" #import "SOGoMAPIDBMessage.h"
#import "SOGoMAPIVolatileMessage.h"
#import "MAPIStoreMailVolatileMessage.h" #import "MAPIStoreMailVolatileMessage.h"
#import "MAPIStoreMailFolder.h" #import "MAPIStoreMailFolder.h"
@ -97,8 +96,9 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
- (void) setupVersionsMessage - (void) setupVersionsMessage
{ {
ASSIGN (versionsMessage, ASSIGN (versionsMessage,
[SOGoMAPIFSMessage objectWithName: @"versions.plist" [SOGoMAPIDBMessage objectWithName: @"versions.plist"
inContainer: propsFolder]); inContainer: dbFolder]);
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
} }
- (BOOL) ensureFolderExists - (BOOL) ensureFolderExists
@ -119,6 +119,9 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
&& ![[(SOGoMailFolder *) sogoObject displayName] && ![[(SOGoMailFolder *) sogoObject displayName]
isEqualToString: newDisplayName]) isEqualToString: newDisplayName])
{ {
[NSException raise: @"MAPIStoreIOException"
format: @"renaming a mail folder via OpenChange is"
@" currently a bad idea"];
[(SOGoMailFolder *) sogoObject renameTo: newDisplayName]; [(SOGoMailFolder *) sogoObject renameTo: newDisplayName];
propsCopy = [newProperties mutableCopy]; propsCopy = [newProperties mutableCopy];
[propsCopy removeObjectForKey: key]; [propsCopy removeObjectForKey: key];
@ -489,10 +492,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
now = [NSCalendarDate date]; now = [NSCalendarDate date];
[now setTimeZone: utcTZ]; [now setTimeZone: utcTZ];
currentProperties = [[versionsMessage properties] mutableCopy]; [versionsMessage reloadIfNeeded];
if (!currentProperties) currentProperties = [versionsMessage properties];
currentProperties = [NSMutableDictionary new];
[currentProperties autorelease];
messages = [currentProperties objectForKey: @"Messages"]; messages = [currentProperties objectForKey: @"Messages"];
if (!messages) if (!messages)
{ {
@ -613,7 +614,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]]; ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]];
[currentProperties setObject: ti [currentProperties setObject: ti
forKey: @"SyncLastSynchronisationDate"]; forKey: @"SyncLastSynchronisationDate"];
[versionsMessage appendProperties: currentProperties];
[versionsMessage save]; [versionsMessage save];
} }
@ -1004,20 +1004,16 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
- (MAPIStoreMessage *) createMessage - (MAPIStoreMessage *) createMessage
{ {
MAPIStoreMailVolatileMessage *newMessage; SOGoMAPIObject *childObject;
SOGoMAPIVolatileMessage *newObject;
newObject = [SOGoMAPIVolatileMessage childObject = [SOGoMAPIObject objectWithName: [SOGoMAPIObject
objectWithName: [SOGoObject globallyUniqueObjectId] globallyUniqueObjectId]
inContainer: sogoObject]; inContainer: sogoObject];
newMessage return [MAPIStoreMailVolatileMessage
= [MAPIStoreMailVolatileMessage mapiStoreObjectWithSOGoObject: newObject mapiStoreObjectWithSOGoObject: childObject
inContainer: self]; inContainer: self];
return newMessage;
} }
- (NSArray *) rolesForExchangeRights: (uint32_t) rights - (NSArray *) rolesForExchangeRights: (uint32_t) rights
{ {
NSMutableArray *roles; NSMutableArray *roles;

View File

@ -373,7 +373,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
if (uid) if (uid)
{ {
changeNumber = [(MAPIStoreMailFolder *) container changeNumber = [(MAPIStoreMailFolder *) container
changeNumberForMessageUID: uid]; changeNumberForMessageUID: uid];
if (!changeNumber) if (!changeNumber)
{ {
[self warnWithFormat: @"attempting to get change number" [self warnWithFormat: @"attempting to get change number"
@ -1529,8 +1529,8 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
if (currentPart) if (currentPart)
{ {
attachment = [MAPIStoreMailAttachment attachment = [MAPIStoreMailAttachment
mapiStoreObjectWithSOGoObject: currentPart mapiStoreObjectInContainer: self];
inContainer: self]; [attachment setBodyPart: currentPart];
[attachment setBodyInfo: [attachmentParts objectForKey: childKey]]; [attachment setBodyInfo: [attachmentParts objectForKey: childKey]];
[attachment setAID: [[self attachmentKeys] indexOfObject: childKey]]; [attachment setAID: [[self attachmentKeys] indexOfObject: childKey]];
} }

View File

@ -332,7 +332,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
if (!fetchedCoreInfos) if (!fetchedCoreInfos)
{ {
fetchedCoreInfos = YES; fetchedCoreInfos = YES;
[(SOGoMailFolder *) [container sogoObject] [(SOGoMailFolder *) [(MAPIStoreMailFolder *) container sogoObject]
prefetchCoreInfosForMessageKeys: [self restrictedChildKeys]]; prefetchCoreInfosForMessageKeys: [self restrictedChildKeys]];
} }

View File

@ -23,9 +23,9 @@
#ifndef MAPISTOREMAILVOLATILEMESSAGE_H #ifndef MAPISTOREMAILVOLATILEMESSAGE_H
#define MAPISTOREMAILVOLATILEMESSAGE_H #define MAPISTOREMAILVOLATILEMESSAGE_H
#import "MAPIStoreVolatileMessage.h" #import "MAPIStoreMessage.h"
@interface MAPIStoreMailVolatileMessage : MAPIStoreVolatileMessage @interface MAPIStoreMailVolatileMessage : MAPIStoreMessage
- (int) submitWithFlags: (enum SubmitFlags) flags; - (int) submitWithFlags: (enum SubmitFlags) flags;

View File

@ -51,6 +51,7 @@
#import <Mailer/NSString+Mail.h> #import <Mailer/NSString+Mail.h>
#import "MAPIStoreAttachment.h" #import "MAPIStoreAttachment.h"
#import "MAPIStoreAttachmentTable.h"
#import "MAPIStoreContext.h" #import "MAPIStoreContext.h"
#import "MAPIStoreMailFolder.h" #import "MAPIStoreMailFolder.h"
#import "MAPIStoreMIME.h" #import "MAPIStoreMIME.h"
@ -60,7 +61,7 @@
#import "NSData+MAPIStore.h" #import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h" #import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h" #import "NSString+MAPIStore.h"
#import "SOGoMAPIVolatileMessage.h" #import "SOGoMAPIObject.h"
#import "MAPIStoreMailVolatileMessage.h" #import "MAPIStoreMailVolatileMessage.h"
@ -68,6 +69,8 @@
#include <mapistore/mapistore.h> #include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h> #include <mapistore/mapistore_errors.h>
static Class NSNumberK = Nil;
static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" }; static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
// //
@ -242,6 +245,106 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
@implementation MAPIStoreMailVolatileMessage @implementation MAPIStoreMailVolatileMessage
+ (void) initialize
{
NSNumberK = [NSNumber class];
}
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer
{
if ((self = [super initWithSOGoObject: newSOGoObject
inContainer: newContainer]))
{
ASSIGN (properties, [sogoObject properties]);
}
return self;
}
- (void) addProperties: (NSDictionary *) newProperties
{
[super addProperties: newProperties];
[sogoObject adjustLastModified];
}
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
{
return ([super canGetProperty: propTag]
|| [properties objectForKey: MAPIPropertyKey (propTag)] != nil);
}
- (uint64_t) objectVersion
{
NSNumber *version;
version = [properties objectForKey: @"version"];
return (version
? exchange_globcnt ([version unsignedLongLongValue])
: ULLONG_MAX);
}
- (int) getPidTagSubject: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
/* if we get here, it means that the properties file didn't contain a
relevant value */
return [self getEmptyString: data inMemCtx: memCtx];
}
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagChangeKey: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
NSData *changeKey;
int rc;
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
if (changeKey)
{
*data = [changeKey asBinaryInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else
rc = [super getPidTagChangeKey: data inMemCtx: memCtx];
return rc;
}
- (NSArray *) attachmentsKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings
{
NSDictionary *attachments;
attachments = [properties objectForKey: @"attachments"];
return [attachments allKeys];
}
- (NSDate *) creationTime
{
return [sogoObject creationDate];
}
- (NSDate *) lastModificationTime
{
return [sogoObject lastModified];
}
- (id) lookupAttachment: (NSString *) childKey
{
NSDictionary *attachments;
attachments = [properties objectForKey: @"attachments"];
return [attachments objectForKey: childKey];
}
- (void) getMessageData: (struct mapistore_message **) dataPtr - (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
@ -258,9 +361,11 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
samCtx = [[self context] connectionInfo]->sam_ctx; samCtx = [[self context] connectionInfo]->sam_ctx;
[super getMessageData: &msgData inMemCtx: memCtx]; // [super getMessageData: &msgData inMemCtx: memCtx];
allRecipients = [[sogoObject properties] objectForKey: @"recipients"]; msgData = talloc_zero (memCtx, struct mapistore_message);
allRecipients = [properties objectForKey: @"recipients"];
msgData->columns = set_SPropTagArray (msgData, 9, msgData->columns = set_SPropTagArray (msgData, 9,
PR_OBJECT_TYPE, PR_OBJECT_TYPE,
PR_DISPLAY_TYPE, PR_DISPLAY_TYPE,
@ -660,10 +765,13 @@ MakeTextPartBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
return textBody; return textBody;
} }
// static id
// MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
// NSString **contentType)
static id static id
MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, MakeMessageBody (NSDictionary *mailProperties, NSString **contentType)
NSString **contentType)
{ {
NSDictionary *attachmentParts;
id messageBody, textBody; id messageBody, textBody;
NSString *textContentType; NSString *textContentType;
NSArray *parts; NSArray *parts;
@ -671,6 +779,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
NGMutableHashMap *headers; NGMutableHashMap *headers;
NSUInteger count, max; NSUInteger count, max;
attachmentParts = [mailProperties objectForKey: @"attachments"];
textBody = MakeTextPartBody (mailProperties, attachmentParts, textBody = MakeTextPartBody (mailProperties, attachmentParts,
&textContentType); &textContentType);
@ -707,22 +816,20 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
- (NGMimeMessage *) _generateMessage - (NGMimeMessage *) _generateMessage
{ {
NSDictionary *mailProperties;
NSString *contentType; NSString *contentType;
NGMimeMessage *message; NGMimeMessage *message;
NGMutableHashMap *headers; NGMutableHashMap *headers;
id messageBody; id messageBody;
mailProperties = [sogoObject properties];
headers = [[NGMutableHashMap alloc] initWithCapacity: 16]; headers = [[NGMutableHashMap alloc] initWithCapacity: 16];
FillMessageHeadersFromProperties (headers, mailProperties, FillMessageHeadersFromProperties (headers, properties,
[[self context] connectionInfo]); [[self context] connectionInfo]);
message = [[NGMimeMessage alloc] initWithHeader: headers]; message = [[NGMimeMessage alloc] initWithHeader: headers];
[message autorelease]; [message autorelease];
[headers release]; [headers release];
messageBody = MakeMessageBody (mailProperties, attachmentParts, &contentType); messageBody = MakeMessageBody (properties, &contentType);
// messageBody = MakeMessageBody (mailProperties, attachmentParts, &contentType);
if (messageBody) if (messageBody)
{ {
[headers setObject: contentType forKey: @"content-type"]; [headers setObject: contentType forKey: @"content-type"];
@ -775,7 +882,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
- (int) submitWithFlags: (enum SubmitFlags) flags - (int) submitWithFlags: (enum SubmitFlags) flags
{ {
NSDictionary *mailProperties, *recipients; NSDictionary *recipients;
NSData *messageData; NSData *messageData;
NSMutableArray *recipientEmails; NSMutableArray *recipientEmails;
NSArray *list; NSArray *list;
@ -785,19 +892,17 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
// SOGoMailFolder *sentFolder; // SOGoMailFolder *sentFolder;
SOGoDomainDefaults *dd; SOGoDomainDefaults *dd;
NSException *error; NSException *error;
MAPIStoreMapping *mapping; // MAPIStoreMapping *mapping;
mailProperties = [sogoObject properties]; msgClass = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
msgClass = [mailProperties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
if ([msgClass isEqualToString: @"IPM.Note"]) /* we skip invitation replies */ if ([msgClass isEqualToString: @"IPM.Note"]) /* we skip invitation replies */
{ {
/* send mail */ /* send mail */
messageData = [self _generateMailDataWithBcc: NO]; messageData = [self _generateMailDataWithBcc: NO];
mailProperties = [sogoObject properties];
recipientEmails = [NSMutableArray arrayWithCapacity: 32]; recipientEmails = [NSMutableArray arrayWithCapacity: 32];
recipients = [mailProperties objectForKey: @"recipients"]; recipients = [properties objectForKey: @"recipients"];
for (count = 0; count < 3; count++) for (count = 0; count < 3; count++)
{ {
recId = recTypes[count]; recId = recTypes[count];
@ -819,11 +924,11 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
if (error) if (error)
[self logWithFormat: @"an error occurred: '%@'", error]; [self logWithFormat: @"an error occurred: '%@'", error];
mapping = [self mapping]; // mapping = [self mapping];
[mapping unregisterURLWithID: [self objectId]]; // [mapping unregisterURLWithID: [self objectId]];
[self setIsNew: NO]; // [self setIsNew: NO];
[properties removeAllObjects]; // [properties removeAllObjects];
[[self container] cleanupCaches]; [(MAPIStoreMailFolder *) [self container] cleanupCaches];
} }
else else
[self logWithFormat: @"skipping submit of message with class '%@'", [self logWithFormat: @"skipping submit of message with class '%@'",
@ -834,14 +939,14 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
- (void) save - (void) save
{ {
NSString *folderName, *flag, *newIdString; NSString *folderName, *flag, *newIdString, *messageKey;
NSData *changeKey, *messageData; NSData *changeKey, *messageData;
NGImap4Connection *connection; NGImap4Connection *connection;
NGImap4Client *client; NGImap4Client *client;
SOGoMailFolder *containerFolder; SOGoMailFolder *containerFolder;
NSDictionary *result, *responseResult; NSDictionary *result, *responseResult;
MAPIStoreMapping *mapping; // MAPIStoreMapping *mapping;
uint64_t mid; // uint64_t mid;
messageData = [self _generateMailDataWithBcc: YES]; messageData = [self _generateMailDataWithBcc: YES];
@ -860,21 +965,24 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
flag = [responseResult objectForKey: @"flag"]; flag = [responseResult objectForKey: @"flag"];
newIdString = [[flag componentsSeparatedByString: @" "] newIdString = [[flag componentsSeparatedByString: @" "]
objectAtIndex: 2]; objectAtIndex: 2];
mid = [self objectId]; // mid = [self objectId];
mapping = [self mapping]; // mapping = [self mapping];
[mapping unregisterURLWithID: mid]; // [mapping unregisterURLWithID: mid];
[sogoObject setNameInContainer: [NSString stringWithFormat: @"%@.eml", newIdString]]; // [sogoObject setNameInContainer: ];
[mapping registerURL: [self url] withID: mid]; messageKey = [NSString stringWithFormat: @"%@.eml", newIdString];
} // [mapping registerURL: [NSString stringWithFormat: @"%@%@",
// [(MAPIStoreMailFolder *) container url], messageKey]
// withID: mid];
/* synchronise the cache and update the change key with the one provided by /* synchronise the cache and update the change key with the one provided
the client */ by the client */
[(MAPIStoreMailFolder *) container synchroniseCache]; [(MAPIStoreMailFolder *) container synchroniseCache];
changeKey = [[sogoObject properties] changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)]; if (changeKey)
if (changeKey) [(MAPIStoreMailFolder *) container
[(MAPIStoreMailFolder *) container setChangeKey: changeKey
setChangeKey: changeKey forMessageWithKey: [self nameInContainer]]; forMessageWithKey: messageKey];
}
} }
@end @end

View File

@ -35,9 +35,9 @@
@class MAPIStoreAttachmentTable; @class MAPIStoreAttachmentTable;
@class MAPIStoreFolder; @class MAPIStoreFolder;
#import "MAPIStoreObject.h" #import "MAPIStoreSOGoObject.h"
@interface MAPIStoreMessage : MAPIStoreObject @interface MAPIStoreMessage : MAPIStoreSOGoObject
{ {
NSArray *attachmentKeys; NSArray *attachmentKeys;
NSMutableDictionary *attachmentParts; NSMutableDictionary *attachmentParts;

View File

@ -36,6 +36,7 @@
#import "MAPIStoreAttachmentTable.h" #import "MAPIStoreAttachmentTable.h"
#import "MAPIStoreContext.h" #import "MAPIStoreContext.h"
#import "MAPIStoreFolder.h" #import "MAPIStoreFolder.h"
#import "MAPIStoreMessageTable.h"
#import "MAPIStorePropertySelectors.h" #import "MAPIStorePropertySelectors.h"
#import "MAPIStoreSamDBUtils.h" #import "MAPIStoreSamDBUtils.h"
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
@ -116,7 +117,6 @@ rtf2html (NSData *compressedRTF)
@interface SOGoObject (MAPIStoreProtocol) @interface SOGoObject (MAPIStoreProtocol)
- (NSString *) davEntityTag;
- (NSString *) davContentLength; - (NSString *) davContentLength;
@end @end
@ -304,6 +304,7 @@ rtf2html (NSData *compressedRTF)
NSData *htmlData, *rtfData; NSData *htmlData, *rtfData;
static NSNumber *htmlKey = nil, *rtfKey = nil; static NSNumber *htmlKey = nil, *rtfKey = nil;
/* we intercept any RTF content and convert it to HTML */
[super addProperties: newNewProperties]; [super addProperties: newNewProperties];
if (!htmlKey) if (!htmlKey)
@ -339,10 +340,8 @@ rtf2html (NSData *compressedRTF)
newAid = [[self attachmentKeys] count]; newAid = [[self attachmentKeys] count];
newAttachment = [MAPIStoreAttachment newAttachment = [MAPIStoreAttachment mapiStoreObjectInContainer: self];
mapiStoreObjectWithSOGoObject: nil // [newAttachment setIsNew: YES];
inContainer: self];
[newAttachment setIsNew: YES];
[newAttachment setAID: newAid]; [newAttachment setAID: newAid];
newKey = [NSString stringWithFormat: @"%ul", newAid]; newKey = [NSString stringWithFormat: @"%ul", newAid];
[attachmentParts setObject: newAttachment [attachmentParts setObject: newAttachment
@ -497,7 +496,6 @@ rtf2html (NSData *compressedRTF)
[[containerTables objectAtIndex: count] [[containerTables objectAtIndex: count]
notifyChangesForChild: self]; notifyChangesForChild: self];
[self setIsNew: NO]; [self setIsNew: NO];
[properties removeAllObjects];
[container cleanupCaches]; [container cleanupCaches];
rc = MAPISTORE_SUCCESS; rc = MAPISTORE_SUCCESS;
} }
@ -792,7 +790,7 @@ rtf2html (NSData *compressedRTF)
- (int) getPidTagOriginalMessageClass: (void **) data - (int) getPidTagOriginalMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
return [self getPidTagMessageClass: data inMemCtx: memCtx]; return [self getProperty: data withTag: PidTagMessageClass inMemCtx: memCtx];
} }
- (int) getPidTagHasAttachments: (void **) data - (int) getPidTagHasAttachments: (void **) data

View File

@ -28,6 +28,7 @@
@interface MAPIStoreMessageTable : MAPIStoreTable @interface MAPIStoreMessageTable : MAPIStoreTable
- (void) setSortOrder: (const struct SSortOrderSet *) set; - (void) setSortOrder: (const struct SSortOrderSet *) set;
- (void) notifyChangesForChild: (MAPIStoreMessage *) child;
@end @end

View File

@ -27,6 +27,7 @@
#import <SOGo/SOGoFolder.h> #import <SOGo/SOGoFolder.h>
#import <SOGo/SOGoObject.h> #import <SOGo/SOGoObject.h>
#import "MAPIStoreContext.h"
#import "MAPIStoreFolder.h" #import "MAPIStoreFolder.h"
#import "MAPIStoreTypes.h" #import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h" #import "NSData+MAPIStore.h"
@ -83,4 +84,60 @@
return [(MAPIStoreFolder *) container lookupMessage: childKey]; return [(MAPIStoreFolder *) container lookupMessage: childKey];
} }
- (void) notifyChangesForChild: (MAPIStoreMessage *) child
{
NSUInteger currentChildRow, newChildRow;
NSArray *list;
NSString *childName;
struct mapistore_table_notification_parameters notif_parameters;
struct mapistore_context *mstoreCtx;
mstoreCtx = [[(MAPIStoreFolder *) container context]
connectionInfo]->mstore_ctx;
notif_parameters.table_type = tableType;
notif_parameters.handle = handleId;
notif_parameters.folder_id = [(MAPIStoreFolder *) container objectId];
notif_parameters.object_id = [child objectId];
notif_parameters.instance_id = 0; /* TODO: always 0 ? */
childName = [child nameInContainer];
list = [self restrictedChildKeys];
currentChildRow = [list indexOfObject: childName];
notif_parameters.row_id = currentChildRow;
[self cleanupCaches];
list = [self restrictedChildKeys];
newChildRow = [list indexOfObject: childName];
if (currentChildRow == NSNotFound)
{
if (newChildRow != NSNotFound)
{
notif_parameters.row_id = newChildRow;
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_CREATED,
&notif_parameters);
}
}
else
{
if (newChildRow == NSNotFound)
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_DELETED,
&notif_parameters);
else
{
/* the fact that the row order has changed has no impact here */
notif_parameters.row_id = newChildRow;
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_MODIFIED,
&notif_parameters);
}
}
}
@end @end

View File

@ -23,9 +23,9 @@
#ifndef MAPISTORENOTESCONTEXT_H #ifndef MAPISTORENOTESCONTEXT_H
#define MAPISTORENOTESCONTEXT_H #define MAPISTORENOTESCONTEXT_H
#import "MAPIStoreFSBaseContext.h" #import "MAPIStoreDBBaseContext.h"
@interface MAPIStoreNotesContext : MAPIStoreFSBaseContext @interface MAPIStoreNotesContext : MAPIStoreDBBaseContext
@end @end

View File

@ -23,9 +23,9 @@
#ifndef MAPISTORENOTESFOLDER_H #ifndef MAPISTORENOTESFOLDER_H
#define MAPISTORENOTESFOLDER_H #define MAPISTORENOTESFOLDER_H
#import "MAPIStoreFSFolder.h" #import "MAPIStoreDBFolder.h"
@interface MAPIStoreNotesFolder : MAPIStoreFSFolder @interface MAPIStoreNotesFolder : MAPIStoreDBFolder
@end @end
#endif /* MAPISTORENOTESFOLDER_H */ #endif /* MAPISTORENOTESFOLDER_H */

View File

@ -23,9 +23,9 @@
#ifndef MAPISTORENOTESMESSAGE_H #ifndef MAPISTORENOTESMESSAGE_H
#define MAPISTORENOTESMESSAGE_H #define MAPISTORENOTESMESSAGE_H
#import "MAPIStoreFSMessage.h" #import "MAPIStoreDBMessage.h"
@interface MAPIStoreNotesMessage : MAPIStoreFSMessage @interface MAPIStoreNotesMessage : MAPIStoreDBMessage
@end @end
#endif /* MAPISTORENOTESMESSAGE_H */ #endif /* MAPISTORENOTESMESSAGE_H */

View File

@ -53,21 +53,4 @@
return MAPISTORE_SUCCESS; return MAPISTORE_SUCCESS;
} }
- (int) getPidTagSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
id value;
int rc;
value = [[sogoObject properties]
objectForKey: MAPIPropertyKey (PidTagNormalizedSubject)];
if (value)
rc = [value getValue: data forTag: PidTagNormalizedSubject
inMemCtx: memCtx];
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
@end @end

View File

@ -33,56 +33,38 @@
@class NSMutableArray; @class NSMutableArray;
@class NSMutableDictionary; @class NSMutableDictionary;
@class EOQualifier;
@class MAPIStoreContext; @class MAPIStoreContext;
@class MAPIStoreFolder;
@class MAPIStoreMapping; @class MAPIStoreMapping;
@class MAPIStoreTable;
@class MAPIStoreUserContext; @class MAPIStoreUserContext;
@class MAPIStoreSOGoObject;
@interface MAPIStoreObject : NSObject @interface MAPIStoreObject : NSObject
{ {
const IMP *classGetters; const IMP *classGetters;
NSMutableArray *parentContainersBag; NSMutableArray *parentContainersBag;
MAPIStoreObject *container; id container;
id sogoObject;
NSMutableDictionary *properties; NSMutableDictionary *properties;
BOOL isNew;
} }
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject + (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer;
inContainer: (MAPIStoreObject *) newContainer; - (id) initInContainer: (MAPIStoreObject *) newContainer;
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP + (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx; inMemCtx: (TALLOC_CTX *) memCtx;
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newFolder;
- (void) setIsNew: (BOOL) newIsNew;
- (BOOL) isNew;
- (NSString *) nameInContainer;
- (id) sogoObject;
- (MAPIStoreObject *) container; - (MAPIStoreObject *) container;
- (MAPIStoreContext *) context; - (MAPIStoreContext *) context;
- (MAPIStoreUserContext *) userContext; - (MAPIStoreUserContext *) userContext;
- (MAPIStoreMapping *) mapping; - (MAPIStoreMapping *) mapping;
- (void) cleanupCaches;
- (uint64_t) objectId;
- (NSString *) url;
/* properties */ /* properties */
- (BOOL) canGetProperty: (enum MAPITAGS) propTag; - (BOOL) canGetProperty: (enum MAPITAGS) propTag;
- (void) addProperties: (NSDictionary *) newProperties; - (void) addProperties: (NSDictionary *) newProperties;
- (NSDictionary *) properties; - (NSMutableDictionary *) properties;
/* ops */ /* ops */
- (int) getAvailableProperties: (struct SPropTagArray **) propertiesP - (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
@ -104,26 +86,12 @@
fromGlobCnt: (uint64_t) objectCnt fromGlobCnt: (uint64_t) objectCnt
inMemCtx: (TALLOC_CTX *) memCtx; inMemCtx: (TALLOC_CTX *) memCtx;
/* implemented getters */
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSearchKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagCreationTime: (void **) data - (int) getPidTagCreationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx; inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagLastModificationTime: (void **) data - (int) getPidTagLastModificationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx; inMemCtx: (TALLOC_CTX *) memCtx;
/* subclasses */ /* subclasses */
- (uint64_t) objectVersion;
- (NSDate *) creationTime; - (NSDate *) creationTime;
- (NSDate *) lastModificationTime; - (NSDate *) lastModificationTime;

View File

@ -58,13 +58,11 @@ static Class NSExceptionK, MAPIStoreFolderK;
MAPIStoreFolderK = [MAPIStoreFolder class]; MAPIStoreFolderK = [MAPIStoreFolder class];
} }
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject + (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer
inContainer: (MAPIStoreObject *) newContainer
{ {
id newObject; id newObject;
newObject = [[self alloc] initWithSOGoObject: newSOGoObject newObject = [[self alloc] initInContainer: newContainer];
inContainer: newContainer];
[newObject autorelease]; [newObject autorelease];
return newObject; return newObject;
@ -106,22 +104,18 @@ static Class NSExceptionK, MAPIStoreFolderK;
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa); classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
parentContainersBag = [NSMutableArray new]; parentContainersBag = [NSMutableArray new];
container = nil; container = nil;
sogoObject = nil;
properties = [NSMutableDictionary new]; properties = [NSMutableDictionary new];
isNew = NO;
} }
[self logWithFormat: @"-init"]; // [self logWithFormat: @"-init"];
return self; return self;
} }
- (id) initWithSOGoObject: (id) newSOGoObject - (id) initInContainer: (MAPIStoreObject *) newContainer
inContainer: (MAPIStoreObject *) newContainer
{ {
if ((self = [self init])) if ((self = [self init]))
{ {
ASSIGN (sogoObject, newSOGoObject);
ASSIGN (container, newContainer); ASSIGN (container, newContainer);
} }
@ -130,42 +124,21 @@ static Class NSExceptionK, MAPIStoreFolderK;
- (void) dealloc - (void) dealloc
{ {
[self logWithFormat: @"-dealloc"]; // [self logWithFormat: @"-dealloc"];
[sogoObject release];
[properties release]; [properties release];
[parentContainersBag release]; [parentContainersBag release];
[container release]; [container release];
[super dealloc]; [super dealloc];
} }
- (void) setIsNew: (BOOL) newIsNew
{
isNew = newIsNew;
}
- (BOOL) isNew
{
return isNew;
}
- (id) sogoObject
{
return sogoObject;
}
- (MAPIStoreObject *) container - (MAPIStoreObject *) container
{ {
return container; return container;
} }
- (NSString *) nameInContainer
{
return [sogoObject nameInContainer];
}
- (MAPIStoreContext *) context - (MAPIStoreContext *) context
{ {
return [container context]; return (MAPIStoreContext *) [container context];
} }
- (MAPIStoreUserContext *) userContext - (MAPIStoreUserContext *) userContext
@ -178,47 +151,14 @@ static Class NSExceptionK, MAPIStoreFolderK;
return [[self userContext] mapping]; return [[self userContext] mapping];
} }
- (void) cleanupCaches
{
}
/* helpers */ /* helpers */
- (uint64_t) objectId
{
uint64_t objectId;
if ([container isKindOfClass: MAPIStoreFolderK])
objectId = [(MAPIStoreFolder *) container
idForObjectWithKey: [sogoObject nameInContainer]];
else
{
[self errorWithFormat: @"%s: container is not a folder", __PRETTY_FUNCTION__];
objectId = (uint64_t) -1;
}
return objectId;
}
- (NSString *) url
{
NSString *containerURL, *format;
containerURL = [container url];
if ([containerURL hasSuffix: @"/"])
format = @"%@%@";
else
format = @"%@/%@";
return [NSString stringWithFormat: format,
containerURL, [self nameInContainer]];
}
- (void) addProperties: (NSDictionary *) newNewProperties - (void) addProperties: (NSDictionary *) newNewProperties
{ {
[properties addEntriesFromDictionary: newNewProperties]; [properties addEntriesFromDictionary: newNewProperties];
} }
- (NSDictionary *) properties - (NSMutableDictionary *) properties
{ {
return properties; return properties;
} }
@ -248,124 +188,8 @@ static Class NSExceptionK, MAPIStoreFolderK;
return rc; return rc;
} }
/* helper getters */
- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt
{
struct mapistore_connection_info *connInfo;
NSMutableData *replicaKey;
char buffer[6];
NSUInteger count;
connInfo = [[self context] connectionInfo];
for (count = 0; count < 6; count++)
{
buffer[count] = objectCnt & 0xff;
objectCnt >>= 8;
}
replicaKey = [NSMutableData dataWithCapacity: 22];
[replicaKey appendBytes: &connInfo->replica_guid
length: sizeof (struct GUID)];
[replicaKey appendBytes: buffer length: 6];
return replicaKey;
}
- (int) getReplicaKey: (void **) data
fromGlobCnt: (uint64_t) objectCnt
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self getReplicaKeyFromGlobCnt: objectCnt] asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
/* getters */
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagSearchKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *stringValue;
stringValue = [sogoObject nameInContainer];
*data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding]
asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getReplicaKey: data fromGlobCnt: [container objectId] >> 16
inMemCtx: memCtx];
}
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getReplicaKey: data fromGlobCnt: [self objectId] >> 16
inMemCtx: memCtx];
}
- (uint64_t) objectVersion
{
[self subclassResponsibility: _cmd];
return ULLONG_MAX;
}
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
uint64_t obVersion;
obVersion = [self objectVersion];
if (obVersion == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
rc = [self getReplicaKey: data fromGlobCnt: obVersion
inMemCtx: memCtx];
return rc;
}
- (int) getPidTagChangeNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
uint64_t obVersion;
obVersion = [self objectVersion];
if (obVersion == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
{
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
| 0x0001));
rc = MAPISTORE_SUCCESS;
}
return rc;
}
- (int) getPidTagCreationTime: (void **) data - (int) getPidTagCreationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx inMemCtx: (TALLOC_CTX *) memCtx
{ {
*data = [[self creationTime] asFileTimeInMemCtx: memCtx]; *data = [[self creationTime] asFileTimeInMemCtx: memCtx];
@ -474,6 +298,38 @@ static Class NSExceptionK, MAPIStoreFolderK;
return MAPISTORE_SUCCESS; return MAPISTORE_SUCCESS;
} }
- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt
{
struct mapistore_connection_info *connInfo;
NSMutableData *replicaKey;
char buffer[6];
NSUInteger count;
connInfo = [[self context] connectionInfo];
for (count = 0; count < 6; count++)
{
buffer[count] = objectCnt & 0xff;
objectCnt >>= 8;
}
replicaKey = [NSMutableData dataWithCapacity: 22];
[replicaKey appendBytes: &connInfo->replica_guid
length: sizeof (struct GUID)];
[replicaKey appendBytes: buffer length: 6];
return replicaKey;
}
- (int) getReplicaKey: (void **) data
fromGlobCnt: (uint64_t) objectCnt
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self getReplicaKeyFromGlobCnt: objectCnt] asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
/* subclasses */ /* subclasses */
- (NSDate *) creationTime - (NSDate *) creationTime
{ {

View File

@ -50,7 +50,7 @@
MAPIStorePermissionEntry *newEntry; MAPIStorePermissionEntry *newEntry;
newEntry = [[self alloc] initWithUserId: newUserId andMemberId: newMemberId newEntry = [[self alloc] initWithUserId: newUserId andMemberId: newMemberId
forFolder: newFolder]; forFolder: newFolder];
[newEntry autorelease]; [newEntry autorelease];
return newEntry; return newEntry;
@ -60,7 +60,7 @@
andMemberId: (uint64_t) newMemberId andMemberId: (uint64_t) newMemberId
forFolder: (MAPIStoreFolder *) newFolder forFolder: (MAPIStoreFolder *) newFolder
{ {
if ((self = [self initWithSOGoObject: nil inContainer: newFolder])) if ((self = [self initInContainer: newFolder]))
{ {
ASSIGN (userId, newUserId); ASSIGN (userId, newUserId);
memberId = newMemberId; memberId = newMemberId;

View File

@ -0,0 +1,89 @@
/* MAPIStoreObject.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef MAPISTORESOGOOBJECT_H
#define MAPISTORESOGOOBJECT_H
#include <talloc.h>
#import "MAPIStoreObject.h"
@class NSDate;
@class NSData;
@class NSString;
@class NSMutableArray;
@class NSMutableDictionary;
@class EOQualifier;
@class MAPIStoreContext;
@class MAPIStoreFolder;
@class MAPIStoreMapping;
@class MAPIStoreTable;
@class MAPIStoreUserContext;
@interface MAPIStoreSOGoObject : MAPIStoreObject
{
id sogoObject;
BOOL isNew;
}
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer;
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newFolder;
- (void) setIsNew: (BOOL) newIsNew;
- (BOOL) isNew;
- (id) sogoObject;
- (NSString *) nameInContainer;
- (MAPIStoreObject *) container;
- (void) cleanupCaches;
- (uint64_t) objectId;
- (NSString *) url;
/* implemented getters */
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSearchKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
/* subclasses */
- (uint64_t) objectVersion;
@end
#endif /* MAPISTORESOGOOBJECT_H */

View File

@ -0,0 +1,255 @@
/* MAPIStoreObject.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/SOGoObject.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import "MAPIStoreContext.h"
#import "MAPIStoreFolder.h"
#import "MAPIStorePropertySelectors.h"
#import "MAPIStoreTypes.h"
#import "MAPIStoreUserContext.h"
#import "NSDate+MAPIStore.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "MAPIStoreSOGoObject.h"
#undef DEBUG
#include <stdbool.h>
#include <talloc.h>
#include <gen_ndr/exchange.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
@implementation MAPIStoreSOGoObject
static Class MAPIStoreFolderK;
+ (void) initialize
{
MAPIStoreFolderK = [MAPIStoreFolder class];
}
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer
{
id newObject;
newObject = [[self alloc] initWithSOGoObject: newSOGoObject
inContainer: newContainer];
[newObject autorelease];
return newObject;
}
- (id) init
{
if ((self = [super init]))
{
sogoObject = nil;
isNew = NO;
}
[self logWithFormat: @"-init"];
return self;
}
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer
{
if ((self = [self initInContainer: newContainer]))
{
ASSIGN (sogoObject, newSOGoObject);
}
return self;
}
- (void) dealloc
{
// [self logWithFormat: @"-dealloc"];
[sogoObject release];
[super dealloc];
}
- (void) setIsNew: (BOOL) newIsNew
{
isNew = newIsNew;
}
- (BOOL) isNew
{
return isNew;
}
- (id) sogoObject
{
return sogoObject;
}
- (MAPIStoreObject *) container
{
return container;
}
- (NSString *) nameInContainer
{
return [sogoObject nameInContainer];
}
- (void) cleanupCaches
{
}
/* helpers */
- (uint64_t) objectId
{
uint64_t objectId;
if ([container isKindOfClass: MAPIStoreFolderK])
objectId = [(MAPIStoreFolder *) container
idForObjectWithKey: [sogoObject nameInContainer]];
else
{
[self errorWithFormat: @"%s: container is not a folder", __PRETTY_FUNCTION__];
objectId = (uint64_t) -1;
}
return objectId;
}
- (NSString *) url
{
NSString *containerURL, *format;
containerURL = (NSString *) [container url];
if ([containerURL hasSuffix: @"/"])
format = @"%@%@";
else
format = @"%@/%@";
return [NSString stringWithFormat: format,
containerURL, [self nameInContainer]];
}
/* getters */
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagSearchKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *stringValue;
stringValue = [sogoObject nameInContainer];
*data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding]
asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getReplicaKey: data fromGlobCnt: [container objectId] >> 16
inMemCtx: memCtx];
}
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getReplicaKey: data fromGlobCnt: [self objectId] >> 16
inMemCtx: memCtx];
}
/* helper getters */
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
uint64_t obVersion;
obVersion = [self objectVersion];
if (obVersion == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
rc = [self getReplicaKey: data fromGlobCnt: obVersion
inMemCtx: memCtx];
return rc;
}
- (int) getPidTagChangeNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
uint64_t obVersion;
obVersion = [self objectVersion];
if (obVersion == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
{
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
| 0x0001));
rc = MAPISTORE_SUCCESS;
}
return rc;
}
/* subclasses */
- (uint64_t) objectVersion
{
[self subclassResponsibility: _cmd];
return ULLONG_MAX;
}
/* logging */
- (NSString *) loggingPrefix
{
return [NSString stringWithFormat:@"<%@:%p:%@>",
NSStringFromClass (isa), self, [self nameInContainer]];
}
@end

View File

@ -100,8 +100,6 @@ typedef enum {
- (int) getRowCount: (uint32_t *) countP - (int) getRowCount: (uint32_t *) countP
withQueryType: (enum mapistore_query_type) queryType; withQueryType: (enum mapistore_query_type) queryType;
- (void) notifyChangesForChild: (MAPIStoreObject *) child;
/* helpers */ /* helpers */
- (SEL) operatorFromRestrictionOperator: (uint32_t) resOp; - (SEL) operatorFromRestrictionOperator: (uint32_t) resOp;

View File

@ -874,61 +874,6 @@ static Class NSDataK, NSStringK;
return MAPISTORE_SUCCESS; return MAPISTORE_SUCCESS;
} }
- (void) notifyChangesForChild: (MAPIStoreObject *) child
{
NSUInteger currentChildRow, newChildRow;
NSArray *list;
NSString *childName;
struct mapistore_table_notification_parameters notif_parameters;
struct mapistore_context *mstoreCtx;
mstoreCtx = [[container context] connectionInfo]->mstore_ctx;
notif_parameters.table_type = tableType;
notif_parameters.handle = handleId;
notif_parameters.folder_id = [container objectId];
notif_parameters.object_id = [child objectId];
notif_parameters.instance_id = 0; /* TODO: always 0 ? */
childName = [child nameInContainer];
list = [self restrictedChildKeys];
currentChildRow = [list indexOfObject: childName];
notif_parameters.row_id = currentChildRow;
[self cleanupCaches];
list = [self restrictedChildKeys];
newChildRow = [list indexOfObject: childName];
if (currentChildRow == NSNotFound)
{
if (newChildRow != NSNotFound)
{
notif_parameters.row_id = newChildRow;
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_CREATED,
&notif_parameters);
}
}
else
{
if (newChildRow == NSNotFound)
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_DELETED,
&notif_parameters);
else
{
/* the fact that the row order has changed has no impact here */
notif_parameters.row_id = newChildRow;
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_MODIFIED,
&notif_parameters);
}
}
}
/* subclasses */ /* subclasses */
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property - (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
{ {

View File

@ -28,6 +28,7 @@
@class NSMutableDictionary; @class NSMutableDictionary;
@class NSString; @class NSString;
@class NSTimeZone; @class NSTimeZone;
@class NSURL;
@class WOContext; @class WOContext;
@ -52,6 +53,9 @@
MAPIStoreMapping *mapping; MAPIStoreMapping *mapping;
BOOL userDbTableExists;
NSURL *folderTableURL;
WOContext *woContext; WOContext *woContext;
MAPIStoreAuthenticator *authenticator; MAPIStoreAuthenticator *authenticator;
} }
@ -71,8 +75,11 @@
- (NSDictionary *) rootFolders; - (NSDictionary *) rootFolders;
- (NSURL *) folderTableURL;
- (MAPIStoreMapping *) mapping; - (MAPIStoreMapping *) mapping;
- (void) ensureFolderTableExists;
/* SOGo hacky magic */ /* SOGo hacky magic */
- (void) activateWithUser: (SOGoUser *) activeUser; - (void) activateWithUser: (SOGoUser *) activeUser;
- (MAPIStoreAuthenticator *) authenticator; - (MAPIStoreAuthenticator *) authenticator;

View File

@ -6,7 +6,7 @@
* *
* This file is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 3, or (at your option)
* any later version. * any later version.
* *
* This file is distributed in the hope that it will be useful, * This file is distributed in the hope that it will be useful,
@ -23,17 +23,21 @@
#import <Foundation/NSDictionary.h> #import <Foundation/NSDictionary.h>
#import <Foundation/NSMapTable.h> #import <Foundation/NSMapTable.h>
#import <Foundation/NSThread.h> #import <Foundation/NSThread.h>
#import <Foundation/NSURL.h>
#import <NGObjWeb/WOContext.h> #import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h> #import <NGObjWeb/WOContext+SoObjects.h>
#import <NGImap4/NGImap4Connection.h> #import <NGImap4/NGImap4Connection.h>
#import <GDLContentStore/GCSChannelManager.h>
#import <SOGo/SOGoDomainDefaults.h>
#import <SOGo/SOGoUser.h> #import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserFolder.h> #import <SOGo/SOGoUserFolder.h>
#import <Mailer/SOGoMailAccount.h> #import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailAccounts.h> #import <Mailer/SOGoMailAccounts.h>
#import "GCSSpecialQueries+OpenChange.h"
#import "MAPIApplication.h" #import "MAPIApplication.h"
#import "MAPIStoreAuthenticator.h" #import "MAPIStoreAuthenticator.h"
#import "MAPIStoreMapping.h" #import "MAPIStoreMapping.h"
@ -80,6 +84,9 @@ static NSMapTable *contextsTable = nil;
mapping = nil; mapping = nil;
userDbTableExists = NO;
folderTableURL = nil;
authenticator = nil; authenticator = nil;
woContext = [WOContext contextWithRequest: nil]; woContext = [WOContext contextWithRequest: nil];
[woContext retain]; [woContext retain];
@ -117,6 +124,8 @@ static NSMapTable *contextsTable = nil;
[authenticator release]; [authenticator release];
[mapping release]; [mapping release];
[folderTableURL release];
[sogoUser release]; [sogoUser release];
[contextsTable removeObjectForKey: username]; [contextsTable removeObjectForKey: username];
@ -213,6 +222,72 @@ static NSMapTable *contextsTable = nil;
return mapping; return mapping;
} }
/* OpenChange db table */
- (NSURL *) folderTableURL
{
NSString *urlString, *ocFSTableName;
NSMutableArray *parts;
SOGoUser *user;
if (!folderTableURL)
{
user = [self sogoUser];
urlString = [[user domainDefaults] folderInfoURL];
parts = [[urlString componentsSeparatedByString: @"/"]
mutableCopy];
[parts autorelease];
if ([parts count] == 5)
{
/* If "OCSFolderInfoURL" is properly configured, we must have 5
parts in this url. */
ocFSTableName = [NSString stringWithFormat: @"socfs_%@", username];
[parts replaceObjectAtIndex: 4 withObject: ocFSTableName];
folderTableURL
= [NSURL URLWithString: [parts componentsJoinedByString: @"/"]];
[folderTableURL retain];
}
else
[NSException raise: @"MAPIStoreIOException"
format: @"'OCSFolderInfoURL' is not set"];
}
return folderTableURL;
}
- (void) ensureFolderTableExists
{
GCSChannelManager *cm;
EOAdaptorChannel *channel;
NSString *tableName, *query;
GCSSpecialQueries *queries;
[self folderTableURL];
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: folderTableURL];
/* FIXME: make use of [EOChannelAdaptor describeTableNames] instead */
tableName = [[folderTableURL path] lastPathComponent];
if ([channel evaluateExpressionX:
[NSString stringWithFormat: @"SELECT count(*) FROM %@",
tableName]])
{
queries = [channel specialQueries];
query = [queries createOpenChangeFSTableWithName: tableName];
if ([channel evaluateExpressionX: query])
[NSException raise: @"MAPIStoreIOException"
format: @"could not create special table '%@'", tableName];
}
else
[channel cancelFetch];
[cm releaseChannel: channel];
}
/* SOGo context objects */
- (WOContext *) woContext - (WOContext *) woContext
{ {
return woContext; return woContext;

View File

@ -1,37 +0,0 @@
/* MAPIStoreVolatileMessage.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef MAPISTOREVOLATILEMESSAGE_H
#define MAPISTOREVOLATILEMESSAGE_H
#import "MAPIStoreMessage.h"
@interface MAPIStoreVolatileMessage : MAPIStoreMessage
{
BOOL fetchedAttachments;
NSDate *creationTime;
NSDate *lastModificationTime;
}
@end
#endif /* MAPISTOREVOLATILEMESSAGE_H */

View File

@ -1,208 +0,0 @@
/* MAPIStoreVolatileMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NGHashMap.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSString+Encoding.h>
#import <NGMail/NGMimeMessage.h>
#import <NGMail/NGMimeMessageGenerator.h>
#import <NGImap4/NGImap4Client.h>
#import <NGImap4/NGImap4Connection.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSCalendarDate+SOGo.h>
#import <SOGo/NSString+Utilities.h>
#import <Mailer/SOGoMailFolder.h>
#import <Mailer/NSString+Mail.h>
#import "MAPIStoreContext.h"
#import "MAPIStoreMailFolder.h"
#import "MAPIStoreMapping.h"
#import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "SOGoMAPIVolatileMessage.h"
#import "MAPIStoreVolatileMessage.h"
#undef DEBUG
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
Class NSNumberK;
@implementation MAPIStoreVolatileMessage
+ (void) initialize
{
NSNumberK = [NSNumber class];
}
- (id) init
{
if ((self = [super init]))
{
fetchedAttachments = NO;
ASSIGN (creationTime, [NSDate date]);
lastModificationTime = [creationTime copy];
}
return self;
}
- (void) dealloc
{
[creationTime release];
[lastModificationTime release];
[super dealloc];
}
- (void) addProperties: (NSDictionary *) newProperties
{
[super addProperties: newProperties];
[sogoObject appendProperties: properties];
[properties removeAllObjects];
ASSIGN (lastModificationTime, [NSDate date]);
}
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
{
return ([super canGetProperty: propTag]
|| [[sogoObject properties] objectForKey: MAPIPropertyKey (propTag)]);
}
- (uint64_t) objectVersion
{
NSNumber *version;
version = [[sogoObject properties] objectForKey: @"version"];
return (version
? exchange_globcnt ([version unsignedLongLongValue])
: ULLONG_MAX);
}
- (int) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
{
id value;
int rc;
value = [[sogoObject properties] objectForKey: MAPIPropertyKey (propTag)];
if (value)
rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
else
rc = [super getProperty: data withTag: propTag inMemCtx: memCtx];
return rc;
}
- (int) getPidTagSubject: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
/* if we get here, it means that the properties file didn't contain a
relevant value */
return [self getEmptyString: data inMemCtx: memCtx];
}
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagChangeKey: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
NSData *changeKey;
int rc;
changeKey = [[sogoObject properties]
objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
if (changeKey)
{
*data = [changeKey asBinaryInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else
rc = [super getPidTagChangeKey: data inMemCtx: memCtx];
return rc;
}
- (NSArray *) attachmentsKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings
{
NSDictionary *attachments;
NSArray *keys;
NSString *key, *newKey;
NSUInteger count, max, aid;
MAPIStoreAttachment *attachment;
if (!fetchedAttachments)
{
attachments = [[sogoObject properties] objectForKey: @"attachments"];
keys = [attachments allKeys];
max = [keys count];
if (max > 0)
{
aid = [keys count];
for (count = 0; count < max; count++)
{
key = [keys objectAtIndex: count];
attachment = [attachments objectForKey: key];
newKey = [NSString stringWithFormat: @"%ul", (aid + count)];
[attachmentParts setObject: attachment forKey: newKey];
}
}
fetchedAttachments = YES;
}
return [super attachmentKeysMatchingQualifier: qualifier
andSortOrderings: sortOrderings];
}
- (NSDate *) creationTime
{
return creationTime;
}
- (NSDate *) lastModificationTime
{
return lastModificationTime;
}
- (id) lookupAttachment: (NSString *) childKey
{
return [attachmentParts objectForKey: childKey];
}
- (void) save
{
[self subclassResponsibility: _cmd];
}
@end

View File

@ -0,0 +1,182 @@
/* dbmsgdump.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* A format-agnostic property list dumper.
Usage: dbmsgdump [filename] */
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NSNull+misc.h>
const char *indentationStep = " ";
@interface NSObject (plext)
- (void) displayWithIndentation: (NSInteger) anInt;
@end
@implementation NSObject (plext)
- (void) _outputIndentation: (NSInteger) anInt
{
NSInteger i;
for (i = 0; i < anInt; i++)
printf ("%s", indentationStep);
}
- (void) displayWithIndentation: (NSInteger) anInt
{
printf ("(%s) %s",
[NSStringFromClass (isa) UTF8String],
[[self description] UTF8String]);
}
@end
@implementation NSDictionary (plext)
- (void) displayKey: (NSString *) key
withIndentation: (NSInteger) anInt
{
[self _outputIndentation: anInt];
printf ("%s ", [[key description] UTF8String]);
if ([key isKindOfClass: [NSValue class]])
printf ("(%s: 0x%.8x) ", [(NSValue *) key objCType], [key intValue]);
printf ("= ");
}
- (void) displayWithIndentation: (NSInteger) anInt
{
NSUInteger i, max;
NSArray *keys;
NSInteger subIndent;
NSString *key;
keys = [self allKeys];
max = [keys count];
printf ("{ (%ld) items\n", (long) max);
subIndent = anInt + 1;
for (i = 0; i < max; i++)
{
key = [keys objectAtIndex: i];
[self displayKey: key withIndentation: subIndent];
[[self objectForKey: key] displayWithIndentation: subIndent];
if (i < (max - 1))
printf (",");
printf ("\n");
}
[self _outputIndentation: anInt];
printf ("}");
}
@end
@implementation NSArray (plext)
- (void) displayCount: (NSUInteger) count
withIndentation: (NSInteger) anInt
{
[self _outputIndentation: anInt];
printf ("%lu = ", (unsigned long) count);
}
- (void) displayWithIndentation: (NSInteger) anInt
{
NSUInteger i, max;
NSInteger subIndent;
max = [self count];
printf ("[ (%ld) items\n", (long) max);
subIndent = anInt + 1;
for (i = 0; i < max; i++)
{
[self displayCount: i withIndentation: subIndent];
[[self objectAtIndex: i] displayWithIndentation: subIndent];
if (i < (max - 1))
printf (",");
printf ("\n");
}
[self _outputIndentation: anInt];
printf ("]");
}
@end
static void
OCDumpPListData (NSData *content)
{
NSDictionary *d;
NSPropertyListFormat format;
NSString *error = nil;
const char *formatName;
d = [NSPropertyListSerialization propertyListFromData: content
mutabilityOption: NSPropertyListImmutable
format: &format
errorDescription: &error];
if (d)
{
switch (format)
{
case NSPropertyListOpenStepFormat:
formatName = "OpenStep";
break;
case NSPropertyListXMLFormat_v1_0:
formatName = "XML";
break;
case NSPropertyListBinaryFormat_v1_0:
formatName = "Binary";
break;
case NSPropertyListGNUstepFormat:
formatName = "GNUstep";
break;
case NSPropertyListGNUstepBinaryFormat:
formatName = "GNUstep binary";
break;
default: formatName = "unknown";
}
printf ("File format is: %s\n", formatName);
[d displayWithIndentation: 0];
printf ("\n");
}
else
printf ("an error occurred: %s\n", [error UTF8String]);
}

View File

@ -1,6 +1,6 @@
/* SOGoMAPIFSFolder.h - this file is part of SOGo /* SOGoMAPIDBFolder.h - this file is part of SOGo
* *
* Copyright (C) 2010 Inverse inc. * Copyright (C) 2012 Inverse inc.
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -20,41 +20,38 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef SOGOMAPIFSFOLDER_H #ifndef SOGOMAPIDBFOLDER_H
#define SOGOMAPIFSFOLDER_H #define SOGOMAPIDBFOLDER_H
#import <SOGo/SOGoFolder.h> #import "SOGoMAPIDBObject.h"
@class NSArray; @class NSArray;
@class NSMutableString;
@class NSString; @class NSString;
@class NSURL; @class NSURL;
@class EOQualifier; @class EOQualifier;
@class SOGoMAPIFSMessage; @class SOGoMAPIDBMessage;
@interface SOGoMAPIFSFolder : SOGoFolder @interface SOGoMAPIDBFolder : SOGoMAPIDBObject
{ {
NSString *directory; NSString *pathPrefix; /* for root folders */
BOOL directoryIsSane; SOGoMAPIDBObject *aclMessage;
} }
+ (id) folderWithURL: (NSURL *) url - (void) setPathPrefix: (NSString *) newPathPrefix;
andTableType: (uint8_t) tableType;
- (id) initWithURL: (NSURL *) url
andTableType: (uint8_t) tableType;
- (NSString *) directory; - (NSMutableString *) pathForChild: (NSString *) childName;
- (SOGoMAPIFSMessage *) newMessage; - (NSArray *) toOneRelationshipKeys;
- (void) ensureDirectory; - (NSArray *) toManyRelationshipKeys;
- (NSCalendarDate *) creationTime; - (NSArray *) childKeysOfType: (MAPIDBObjectType) type
- (NSCalendarDate *) lastModificationTime; includeDeleted: (BOOL) includeDeleted
matchingQualifier: (EOQualifier *) qualifier
- (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier andSortOrderings: (NSArray *) sortOrderings;
andSortOrderings: (NSArray *) sortOrderings;
@end @end
#endif /* SOGOMAPIFSFOLDER_H */ #endif /* SOGOMAPIDBFOLDER_H */

View File

@ -0,0 +1,402 @@
/* SOGoMAPIDBFolder.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSURL.h>
#import <NGExtensions/NSObject+Logs.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLContentStore/GCSChannelManager.h>
// #import <GDLContentStore/EOQualifier+GCS.m>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/SOGoDomainDefaults.h>
#import <SOGo/SOGoUser.h>
#import "EOQualifier+MAPI.h"
#import "GCSSpecialQueries+OpenChange.h"
#import "SOGoMAPIDBMessage.h"
#import "SOGoMAPIDBFolder.h"
#undef DEBUG
#include <stdbool.h>
#include <talloc.h>
#include <util/time.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
#include <libmapiproxy.h>
#include <param.h>
Class SOGoMAPIDBObjectK = Nil;
@implementation SOGoMAPIDBFolder
+ (void) initialize
{
SOGoMAPIDBObjectK = [SOGoMAPIDBObject class];
}
- (id) init
{
if ((self = [super init]))
{
pathPrefix = nil;
}
return self;
}
- (id) initWithName: (NSString *) name inContainer: (id) newContainer
{
if ((self = [super initWithName: name inContainer: newContainer]))
{
objectType = MAPIDBObjectTypeFolder;
aclMessage = [SOGoMAPIDBObject objectWithName: @"permissions"
inContainer: self];
[aclMessage setObjectType: MAPIDBObjectTypeInternal];
[aclMessage retain];
}
return self;
}
- (void) dealloc
{
[aclMessage release];
[pathPrefix release];
[super dealloc];
}
- (BOOL) isFolderish
{
return YES;
}
- (void) setPathPrefix: (NSString *) newPathPrefix
{
ASSIGN (pathPrefix, newPathPrefix);
}
- (NSMutableString *) pathForChild: (NSString *) childName
{
NSMutableString *path;
path = [self path];
[path appendFormat: @"/%@", childName];
return path;
}
- (NSMutableString *) path
{
NSMutableString *path;
path = [super path];
if (pathPrefix)
[path insertString: pathPrefix atIndex: 0];
return path;
}
// - (SOGoMAPIDBMessage *) newMessage
// {
// NSString *newFilename;
// newFilename = [NSString stringWithFormat: @"%@.plist",
// [SOGoObject globallyUniqueObjectId]];
// return [SOGoMAPIDBMessage objectWithName: filename inContainer: self];
// }
- (NSArray *) childKeysOfType: (MAPIDBObjectType) type
includeDeleted: (BOOL) includeDeleted
matchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings
{
NSMutableArray *childKeys;
NSMutableString *sql// , *qualifierClause
;
NSString *childPathPrefix, *childPath, *childKey;
NSMutableArray *whereClause;
NSArray *records;
NSDictionary *record;
NSUInteger childPathPrefixLen, count, max;
SOGoMAPIDBObject *currentChild;
/* query construction */
sql = [NSMutableString stringWithCapacity: 256];
[sql appendFormat: @"SELECT * FROM %@", [self tableName]];
whereClause = [NSMutableArray arrayWithCapacity: 2];
childPathPrefix = [NSString stringWithFormat: @"%@/", [self path]];
[whereClause addObject: [NSString stringWithFormat: @"c_path LIKE '%@%%'",
childPathPrefix]];
[whereClause addObject: [NSString stringWithFormat: @"c_type = %d", type]];
if (!includeDeleted)
[whereClause addObject: @"c_deleted = 0"];
[sql appendFormat: @" WHERE %@",
[whereClause componentsJoinedByString: @" AND "]];
/* results */
records = [self performSQLQuery: sql];
if (records)
{
max = [records count];
childKeys = [NSMutableArray arrayWithCapacity: max];
childPathPrefixLen = [childPathPrefix length];
for (count = 0; count < max; count++)
{
record = [records objectAtIndex: count];
childPath = [record objectForKey: @"c_path"];
childKey = [childPath substringFromIndex: childPathPrefixLen];
if ([childKey rangeOfString: @"/"].location == NSNotFound)
{
if (qualifier)
{
currentChild = [SOGoMAPIDBObject objectWithName: childKey
inContainer: self];
[currentChild setupFromRecord: record];
if ([qualifier evaluateSOGoMAPIDBObject: currentChild])
[childKeys addObject: childKey];
}
else
[childKeys addObject: childKey];
}
}
}
else
childKeys = nil;
return childKeys;
}
- (NSArray *) toManyRelationshipKeys
{
return [self childKeysOfType: MAPIDBObjectTypeFolder
includeDeleted: NO
matchingQualifier: nil
andSortOrderings: nil];
}
- (NSArray *) toOneRelationshipKeys
{
return [self childKeysOfType: MAPIDBObjectTypeMessage
includeDeleted: NO
matchingQualifier: nil
andSortOrderings: nil];
}
// - (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
// andSortOrderings: (NSArray *) sortOrderings
// {
// NSArray *allKeys;
// NSMutableArray *keys;
// NSUInteger count, max;
// NSString *messageKey;
// SOGoMAPIDBMessage *message;
// if (sortOrderings)
// [self warnWithFormat: @"sorting is not handled yet"];
// allKeys = [self toOneRelationshipKeys];
// if (qualifier)
// {
// [self logWithFormat: @"%s: getting restricted FAI keys", __PRETTY_FUNCTION__];
// max = [allKeys count];
// keys = [NSMutableArray arrayWithCapacity: max];
// for (count = 0; count < max; count++)
// {
// messageKey = [allKeys objectAtIndex: count];
// message = [self lookupName: messageKey
// inContext: nil
// acquire: NO];
// if ([qualifier evaluateMAPIVolatileMessage: message])
// [keys addObject: messageKey];
// }
// }
// else
// keys = (NSMutableArray *) allKeys;
// return keys;
// }
- (id) lookupName: (NSString *) childName
inContext: (WOContext *) woContext
acquire: (BOOL) acquire
{
id object;
Class objectClass;
NSString *childPath;
NSDictionary *record;
childPath = [self pathForChild: childName];
record = [self lookupRecord: childPath newerThanVersion: -1];
if (record)
{
if ([[record objectForKey: @"c_type"] intValue] == MAPIDBObjectTypeFolder)
objectClass = isa;
else
objectClass = SOGoMAPIDBObjectK;
object = [objectClass objectWithName: childName
inContainer: self];
[object setupFromRecord: record];
}
else
object = nil;
return object;
}
- (id) lookupFolder: (NSString *) folderName
inContext: (WOContext *) woContext
{
id object;
object = [SOGoMAPIDBFolder objectWithName: folderName
inContainer: self];
[object reloadIfNeeded];
return object;
}
// - (id) _fileAttributeForKey: (NSString *) key
// {
// NSDictionary *attributes;
// attributes = [[NSFileManager defaultManager]
// fileAttributesAtPath: directory
// traverseLink: NO];
// return [attributes objectForKey: key];
// }
// - (NSCalendarDate *) creationTime
// {
// return [self _fileAttributeForKey: NSFileCreationDate];
// }
// - (NSCalendarDate *) lastModificationTime
// {
// return [self _fileAttributeForKey: NSFileModificationDate];
// }
- (NSException *) delete
{
[self notImplemented: _cmd];
// NSFileManager *fm;
// NSException *error;
// fm = [NSFileManager defaultManager];
// if (![fm removeFileAtPath: directory handler: NULL])
// error = [NSException exceptionWithName: @"MAPIStoreIOException"
// reason: @"could not delete folder"
// userInfo: nil];
// else
// error = nil;
// return error;
return nil;
}
/* acl */
- (NSString *) defaultUserID
{
return @"default";
}
- (NSMutableDictionary *) _aclEntries
{
NSMutableDictionary *aclEntries;
[aclMessage reloadIfNeeded];
aclEntries = [aclMessage properties];
if (![aclEntries objectForKey: @"users"])
[aclEntries setObject: [NSMutableArray array] forKey: @"users"];
if (![aclEntries objectForKey: @"entries"])
[aclEntries setObject: [NSMutableDictionary dictionary]
forKey: @"entries"];
return aclEntries;
}
- (void) addUserInAcls: (NSString *) user
{
NSMutableDictionary *acl;
NSMutableArray *users;
acl = [self _aclEntries];
users = [acl objectForKey: @"users"];
[users addObjectUniquely: user];
[aclMessage save];
}
- (void) removeAclsForUsers: (NSArray *) oldUsers
{
NSDictionary *acl;
NSMutableDictionary *entries;
NSMutableArray *users;
acl = [self _aclEntries];
entries = [acl objectForKey: @"entries"];
[entries removeObjectsForKeys: oldUsers];
users = [acl objectForKey: @"users"];
[users removeObjectsInArray: oldUsers];
[aclMessage save];
}
- (NSArray *) aclUsers
{
return [[self _aclEntries] objectForKey: @"users"];
}
- (NSArray *) aclsForUser: (NSString *) uid
{
NSDictionary *entries;
entries = [[self _aclEntries] objectForKey: @"entries"];
return [entries objectForKey: uid];
}
- (void) setRoles: (NSArray *) roles
forUser: (NSString *) uid
{
NSMutableDictionary *acl;
NSMutableDictionary *entries;
acl = [self _aclEntries];
entries = [acl objectForKey: @"entries"];
[entries setObject: roles forKey: uid];
[aclMessage save];
}
@end

View File

@ -0,0 +1,83 @@
/* SOGoMAPIDBObject.h - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef SOGOMAPIDBOBJECT_H
#define SOGOMAPIDBOBJECT_H
#import "SOGoMAPIObject.h"
@class NSArray;
@class NSMutableDictionary;
@class NSMutableString;
@class NSString;
@class NSURL;
@class EOAdaptor;
typedef enum {
MAPIDBObjectTypeFolder = 1,
MAPIDBObjectTypeMessage = 2,
MAPIDBObjectTypeFAI = 3,
MAPIDBObjectTypeInternal = 99 /* object = property list */
} MAPIDBObjectType;
@interface SOGoMAPIDBObject : SOGoMAPIObject
{
NSURL *tableUrl;
BOOL initialized; /* safe guard */
MAPIDBObjectType objectType;
NSInteger version;
BOOL deleted;
}
/* actions */
- (void) setupFromRecord: (NSDictionary *) record;
- (void) reloadIfNeeded;
- (void) save;
/* accessors */
- (NSMutableString *) path; /* full filename */
- (void) setTableUrl: (NSURL *) newTableUrl;
- (NSURL *) tableUrl;
- (NSString *) tableName;
- (NSArray *) performSQLQuery: (NSString *) sql;
- (NSDictionary *) lookupRecord: (NSString *) path
newerThanVersion: (NSInteger) startVersion;
- (void) setObjectType: (MAPIDBObjectType) newObjectType;
- (MAPIDBObjectType) objectType; /* message, fai, folder */
/* automatically set from actions */
- (BOOL) deleted;
/* db helpers */
- (EOAdaptor *) tableChannelAdaptor;
- (NSArray *) performSQLQuery: (NSString *) sql;
@end
#endif /* SOGOMAPIDBOBJECT_H */

View File

@ -0,0 +1,483 @@
/* SOGoMAPIDBObject.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSNull.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <Foundation/NSValue.h>
#import <GDLAccess/EOAdaptor.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLAccess/EOAdaptorContext.h>
#import <GDLAccess/EOAttribute.h>
#import <GDLContentStore/GCSChannelManager.h>
#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/NSObject+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoDomainDefaults.h>
#import <SOGo/SOGoUser.h>
#import "GCSSpecialQueries+OpenChange.h"
#import "MAPIStoreTypes.h"
#import "SOGoMAPIDBFolder.h"
#import "SOGoMAPIDBObject.h"
static EOAttribute *textColumn = nil;
@implementation SOGoMAPIDBObject
+ (void) initialize
{
NSDictionary *description;
if (!textColumn)
{
/* TODO: this is a hack for providing an EOAttribute definition that is
compatible with all the backends that we support. We should make use
of EOModel instead. */
description = [NSDictionary dictionaryWithObjectsAndKeys:
@"c_textfield", @"columnName",
@"VARCHAR", @"externalType",
nil];
textColumn = [EOAttribute attributeFromPropertyList: description];
[textColumn retain];
}
}
/*
= (@"CREATE TABLE %@ ("
@" c_path VARCHAR(255) PRIMARY KEY,"
@" c_type VARCHAR(20) NOT NULL,"
@" c_creationdate INT4 NOT NULL,"
@" c_lastmodified INT4 NOT NULL,"
@" c_version INT4 NOT NULL DEFAULT 0,"
@" c_deleted SMALLINT NOT NULL DEFAULT 0,"
*/
/* indexes:
c_path (primary key)
c_counter
c_path, c_type
c_path, c_creationdate */
- (id) init
{
if ((self = [super init]))
{
tableUrl = nil;
initialized = NO;
objectType = -1;
deleted = NO;
version = 0;
}
return self;
}
- (void) dealloc
{
[tableUrl release];
[super dealloc];
}
- (void) setTableUrl: (NSURL *) newTableUrl
{
ASSIGN (tableUrl, newTableUrl);
}
- (NSURL *) tableUrl
{
if (!tableUrl)
{
tableUrl = [container tableUrl];
[tableUrl retain];
if (!tableUrl)
[NSException raise: @"MAPIStoreIOException"
format: @"table url is not set for object '%@'", self];
}
return tableUrl;
}
- (NSString *) tableName
{
NSArray *parts;
[self tableUrl];
parts = [[tableUrl path] componentsSeparatedByString: @"/"];
return [parts lastObject];
}
- (void) setupFromRecord: (NSDictionary *) record
{
NSInteger intValue;
NSString *propsValue, *error;
NSDictionary *newValues;
NSPropertyListFormat format;
objectType = [[record objectForKey: @"c_type"] intValue];
intValue = [[record objectForKey: @"c_creationdate"] intValue];
ASSIGN (creationDate,
[NSCalendarDate
dateWithTimeIntervalSince1970: (NSTimeInterval) intValue]);
intValue = [[record objectForKey: @"c_lastmodified"] intValue];
ASSIGN (lastModified,
[NSCalendarDate
dateWithTimeIntervalSince1970: (NSTimeInterval) intValue]);
deleted = ([[record objectForKey: @"c_deleted"] intValue] > 0);
version = [[record objectForKey: @"c_version"] intValue];
propsValue = [record objectForKey: @"c_content"];
if ([propsValue isNotNull])
{
newValues = [NSPropertyListSerialization propertyListFromData: [propsValue dataByDecodingBase64]
mutabilityOption: NSPropertyListMutableContainers
format: &format
errorDescription: &error];
[properties addEntriesFromDictionary: newValues];
// [properties addEntriesFromDictionary: [propsValue
// objectFromJSONString]];
}
else
[properties removeAllObjects];
initialized = YES;
}
/* accessors */
- (NSMutableString *) path
{
NSMutableString *path;
if (container)
path = [container pathForChild: nameInContainer];
else
path = [NSMutableString stringWithFormat: @"/%@", nameInContainer];
if ([path rangeOfString: @"//"].location != NSNotFound)
[NSException raise: @"MAPIStoreIOException"
format: @"object path has not been properly set for"
" folder '%@' (%@)",
self, path];
return path;
}
- (void) setObjectType: (MAPIDBObjectType) newObjectType
{
objectType = newObjectType;
}
- (MAPIDBObjectType) objectType /* message, fai, folder */
{
return objectType;
}
- (NSCalendarDate *) creationDate
{
if (!initialized)
[NSException raise: @"MAPIStoreIOException"
format: @"record has not been initialized: %@", self];
return creationDate;
}
- (NSCalendarDate *) lastModified
{
if (!initialized)
[NSException raise: @"MAPIStoreIOException"
format: @"record has not been initialized: %@", self];
return lastModified;
}
- (BOOL) deleted
{
return deleted;
}
- (Class) mapistoreMessageClass
{
NSString *className, *mapiMsgClass;
switch (objectType)
{
case MAPIDBObjectTypeMessage:
mapiMsgClass = [properties
objectForKey: MAPIPropertyKey (PidTagMessageClass)];
if (mapiMsgClass)
{
if ([mapiMsgClass isEqualToString: @"IPM.StickyNote"])
className = @"MAPIStoreNotesMessage";
else
className = @"MAPIStoreDBMessage";
[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
mapiMsgClass, className];
}
else
{
[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
@" to 'MAPIStoreDBMessage'"];
className = @"MAPIStoreDBMessage";
}
break;
case MAPIDBObjectTypeFAI:
className = @"MAPIStoreFAIMessage";
break;
default:
[NSException raise: @"MAPIStoreIOException"
format: @"message class should not be queried for objects"
@" of type '%d'", objectType];
}
return NSClassFromString (className);
}
/* actions */
- (EOAdaptor *) tableChannelAdaptor
{
GCSChannelManager *cm;
EOAdaptor *adaptor;
EOAdaptorChannel *channel;
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
adaptor = [[channel adaptorContext] adaptor];
[cm releaseChannel: channel];
return adaptor;
}
- (NSArray *) performSQLQuery: (NSString *) sql
{
NSMutableArray *records;
GCSChannelManager *cm;
EOAdaptorChannel *channel;
NSException *error;
NSArray *attrs;
NSDictionary *record;
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
error = [channel evaluateExpressionX: sql];
if (error)
{
records = nil;
[self logWithFormat:
@"an exception occurred when executing query '%@'",
sql];
[self logWithFormat: @"exception is '%@'", error];
}
else
{
records = [NSMutableArray arrayWithCapacity: 256];
attrs = [channel describeResults: NO];
while ((record = [channel fetchAttributes: attrs withZone: NULL]))
[records addObject: record];
}
[cm releaseChannel: channel];
return records;
}
- (NSDictionary *) lookupRecord: (NSString *) path
newerThanVersion: (NSInteger) startVersion
{
NSDictionary *record;
NSArray *records;
NSString *tableName, *pathValue;
NSMutableString *sql;
EOAdaptor *adaptor;
if ([path hasSuffix: @"/"])
[NSException raise: @"MAPIStoreIOException"
format: @"path ends with a slash: %@", path];
tableName = [self tableName];
adaptor = [self tableChannelAdaptor];
pathValue = [adaptor formatValue: path
forAttribute: textColumn];
/* query */
sql = [NSMutableString stringWithFormat:
@"SELECT * FROM %@ WHERE c_path = %@",
tableName, pathValue];
if (startVersion > -1)
[sql appendFormat: @" AND c_version > %d", startVersion];
/* execution */
records = [self performSQLQuery: sql];
if ([records count] > 0)
record = [records objectAtIndex: 0];
else
record = nil;
return record;
}
- (void) reloadIfNeeded
{
/* if object is uninitialized: reload without condition, otherwise, load if
c_version > :version */
NSDictionary *record;
if (initialized)
{
if (!isNew)
{
record = [self lookupRecord: [self path]
newerThanVersion: version];
if (record)
[self setupFromRecord: record];
}
}
else
{
record = [self lookupRecord: [self path]
newerThanVersion: -1];
if (record)
{
[self setupFromRecord: record];
isNew = NO;
}
else
isNew = YES;
initialized = YES;
}
}
- (NSException *) delete
{
deleted = YES;
[properties removeAllObjects];
[self save];
return nil;
}
- (void) save
{
NSString *sql;
NSData *content;
NSCalendarDate *now;
GCSChannelManager *cm;
EOAdaptor *adaptor;
EOAdaptorChannel *channel;
NSInteger creationDateValue, lastModifiedValue, deletedValue;
NSString *tableName, *pathValue, *propsValue;
NSException *result;
if (!initialized)
[NSException raise: @"MAPIStoreIOException"
format: @"record has not been initialized: %@", self];
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
tableName = [self tableName];
now = [NSCalendarDate date];
ASSIGN (lastModified, now);
/*
- (NSException *)insertRowX:(NSDictionary *)_row forEntity:(EOEntity *)_entity;
- (NSException *)updateRowX:(NSDictionary*)aRow
describedByQualifier:(EOSQLQualifier*)aQualifier;
*/
adaptor = [[channel adaptorContext] adaptor];
pathValue = [adaptor formatValue: [self path]
forAttribute: textColumn];
lastModifiedValue = (NSInteger) [lastModified timeIntervalSince1970];
if (objectType == -1)
[NSException raise: @"MAPIStoreIOException"
format: @"object type has not been set for object '%@'",
self];
if ([properties count] > 0)
{
content = [NSPropertyListSerialization
dataFromPropertyList: properties
format: NSPropertyListBinaryFormat_v1_0
errorDescription: NULL];
propsValue = [adaptor formatValue: [content stringByEncodingBase64]
forAttribute: textColumn];
}
else
propsValue = @"NULL";
if (isNew)
{
ASSIGN (creationDate, now);
creationDateValue = (NSInteger) [creationDate timeIntervalSince1970];
sql = [NSString stringWithFormat:
(@"INSERT INTO %@"
@" (c_path, c_type, c_creationdate, c_lastmodified,"
@" c_deleted, c_version, c_content)"
@" VALUES (%@, %d, %d, %d, 0, 0, %@"
@")"),
tableName,
pathValue, objectType,
creationDateValue, lastModifiedValue,
propsValue];
isNew = NO;
}
else
{
version++;
deletedValue = (deleted ? 1 : 0);
sql = [NSString stringWithFormat:
(@"UPDATE %@"
@" SET c_lastmodified = %d, c_deleted = %d,"
@" c_version = %d, c_content = %@"
@" WHERE c_path = %@"),
tableName,
lastModifiedValue, deletedValue, version, propsValue,
pathValue];
}
result = [channel evaluateExpressionX: sql];
if (result)
[self errorWithFormat: @"could not insert/update record for record %@"
@" in %@: %@", pathValue, tableName, result];
// @" c_path VARCHAR(255) PRIMARY KEY,"
// @" c_type SMALLINT NOT NULL,"
// @" c_creationdate INT4 NOT NULL,"
// @" c_lastmodified INT4 NOT NULL,"
// @" c_deleted SMALLINT NOT NULL DEFAULT 0,"
// @" c_content BLOB");
[cm releaseChannel: channel];
}
@end

View File

@ -1,439 +0,0 @@
/* SOGoMAPIFSFolder.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSURL.h>
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/NSArray+Utilities.h>
#import "EOQualifier+MAPI.h"
#import "SOGoMAPIFSMessage.h"
#import "SOGoMAPIFSFolder.h"
#undef DEBUG
#include <stdbool.h>
#include <talloc.h>
#include <util/time.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
#include <libmapiproxy.h>
#include <param.h>
static NSString *privateDir = nil;
@implementation SOGoMAPIFSFolder
+ (void) initialize
{
struct loadparm_context *lpCtx;
const char *cPrivateDir;
if (!privateDir)
{
lpCtx = loadparm_init_global (true);
cPrivateDir = lpcfg_private_dir (lpCtx);
privateDir = [NSString stringWithUTF8String: cPrivateDir];
[privateDir retain];
}
}
+ (id) folderWithURL: (NSURL *) url
andTableType: (uint8_t) tableType
{
SOGoMAPIFSFolder *newFolder;
newFolder = [[self alloc] initWithURL: url
andTableType: tableType];
[newFolder autorelease];
return newFolder;
}
- (id) init
{
if ((self = [super init]))
{
directory = nil;
directoryIsSane = NO;
}
return self;
}
- (void) dealloc
{
[directory release];
[super dealloc];
}
- (id) initWithURL: (NSURL *) url
andTableType: (uint8_t) tableType
{
NSString *path, *username, *tableParticle;
if ((self = [self init]))
{
if (tableType == MAPISTORE_MESSAGE_TABLE)
tableParticle = @"message";
else if (tableType == MAPISTORE_FAI_TABLE)
tableParticle = @"fai";
else if (tableType == MAPISTORE_FOLDER_TABLE)
tableParticle = @"folder";
else
{
[NSException raise: @"MAPIStoreIOException"
format: @"unsupported table type: %d", tableType];
tableParticle = nil;
}
path = [url path];
if (![path hasSuffix: @"/"])
path = [NSString stringWithFormat: @"%@/", path];
username = [url user];
directory = [NSString stringWithFormat: @"%@/mapistore/SOGo/%@/%@/%@%@",
privateDir, username, tableParticle,
[url host], path];
[self setOwner: username];
[self logWithFormat: @"directory: %@", directory];
[directory retain];
ASSIGN (nameInContainer, [path stringByDeletingLastPathComponent]);
}
return self;
}
- (id) initWithName: (NSString *) newName
inContainer: (id) newContainer
{
if ((self = [super initWithName: newName inContainer: newContainer]))
{
directory = [[newContainer directory]
stringByAppendingPathComponent: newName];
[directory retain];
}
return self;
}
- (NSString *) directory
{
return directory;
}
- (SOGoMAPIFSMessage *) newMessage
{
NSString *filename;
filename = [NSString stringWithFormat: @"%@.plist",
[SOGoObject globallyUniqueObjectId]];
return [SOGoMAPIFSMessage objectWithName: filename inContainer: self];
}
- (void) ensureDirectory
{
NSFileManager *fm;
NSDictionary *attributes;
BOOL isDir;
if (!directory)
[NSException raise: @"MAPIStoreIOException"
format: @"directory is nil"];
fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath: directory isDirectory: &isDir])
{
if (!isDir)
[NSException raise: @"MAPIStoreIOException"
format: @"object at path '%@' is not a directory",
directory];
}
else
{
attributes
= [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: 0700]
forKey: NSFilePosixPermissions];
[fm createDirectoryAtPath: directory
attributes: attributes];
}
directoryIsSane = YES;
}
- (NSArray *) _objectsInDirectory: (BOOL) dirs
{
NSFileManager *fm;
NSArray *contents;
NSMutableArray *files;
NSUInteger count, max;
NSString *file, *fullName;
BOOL isDir;
if (!directoryIsSane)
[self ensureDirectory];
fm = [NSFileManager defaultManager];
contents = [fm directoryContentsAtPath: directory];
max = [contents count];
files = [NSMutableArray arrayWithCapacity: max];
for (count = 0; count < max; count++)
{
file = [contents objectAtIndex: count];
if (![file isEqualToString: @"permissions.plist"])
{
fullName = [directory stringByAppendingPathComponent: file];
if ([fm fileExistsAtPath: fullName
isDirectory: &isDir]
&& dirs == isDir)
[files addObject: file];
}
}
return files;
}
- (NSArray *) toManyRelationshipKeys
{
return [self _objectsInDirectory: YES];
}
- (NSArray *) toOneRelationshipKeys
{
return [self _objectsInDirectory: NO];
}
- (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings
{
NSArray *allKeys;
NSMutableArray *keys;
NSUInteger count, max;
NSString *messageKey;
SOGoMAPIFSMessage *message;
if (sortOrderings)
[self warnWithFormat: @"sorting is not handled yet"];
allKeys = [self toOneRelationshipKeys];
if (qualifier)
{
[self logWithFormat: @"%s: getting restricted FAI keys", __PRETTY_FUNCTION__];
max = [allKeys count];
keys = [NSMutableArray arrayWithCapacity: max];
for (count = 0; count < max; count++)
{
messageKey = [allKeys objectAtIndex: count];
message = [self lookupName: messageKey
inContext: nil
acquire: NO];
if ([qualifier evaluateMAPIVolatileMessage: message])
[keys addObject: messageKey];
}
}
else
keys = (NSMutableArray *) allKeys;
return keys;
}
- (id) lookupName: (NSString *) fileName
inContext: (WOContext *) woContext
acquire: (BOOL) acquire
{
NSFileManager *fm;
NSString *fullName;
id object;
BOOL isDir;
if (!directoryIsSane)
[self ensureDirectory];
fm = [NSFileManager defaultManager];
fullName = [directory stringByAppendingPathComponent: fileName];
if ([fm fileExistsAtPath: fullName
isDirectory: &isDir])
{
if (isDir)
object = [isa objectWithName: fileName
inContainer: self];
else
object = [SOGoMAPIFSMessage objectWithName: fileName
inContainer: self];
}
else
object = nil;
return object;
}
- (id) _fileAttributeForKey: (NSString *) key
{
NSDictionary *attributes;
attributes = [[NSFileManager defaultManager]
fileAttributesAtPath: directory
traverseLink: NO];
return [attributes objectForKey: key];
}
- (NSCalendarDate *) creationTime
{
return [self _fileAttributeForKey: NSFileCreationDate];
}
- (NSCalendarDate *) lastModificationTime
{
return [self _fileAttributeForKey: NSFileModificationDate];
}
- (NSException *) delete
{
NSFileManager *fm;
NSException *error;
fm = [NSFileManager defaultManager];
if (![fm removeFileAtPath: directory handler: NULL])
error = [NSException exceptionWithName: @"MAPIStoreIOException"
reason: @"could not delete folder"
userInfo: nil];
else
error = nil;
return error;
}
/* acl */
- (NSString *) defaultUserID
{
return @"default";
}
- (NSMutableDictionary *) _aclEntries
{
NSMutableDictionary *aclEntries;
NSData *content;
NSString *error, *filename;
NSPropertyListFormat format;
filename = [directory stringByAppendingPathComponent: @"permissions.plist"];
content = [NSData dataWithContentsOfFile: filename];
if (content)
aclEntries = [NSPropertyListSerialization propertyListFromData: content
mutabilityOption: NSPropertyListMutableContainers
format: &format
errorDescription: &error];
else
aclEntries = nil;
if (!aclEntries)
{
aclEntries = [NSMutableDictionary dictionary];
[aclEntries setObject: [NSMutableArray array] forKey: @"users"];
[aclEntries setObject: [NSMutableDictionary dictionary]
forKey: @"entries"];
}
return aclEntries;
}
- (void) _saveAcl: (NSDictionary *) acl
{
NSString *filename;
NSData *content;
filename = [directory stringByAppendingPathComponent: @"permissions.plist"];
[self ensureDirectory];
if (acl)
content = [NSPropertyListSerialization
dataFromPropertyList: acl
format: NSPropertyListBinaryFormat_v1_0
errorDescription: NULL];
else
content = [NSData data];
if (![content writeToFile: filename atomically: NO])
[NSException raise: @"MAPIStoreIOException"
format: @"could not save acl"];
}
- (void) addUserInAcls: (NSString *) user
{
NSMutableDictionary *acl;
NSMutableArray *users;
acl = [self _aclEntries];
users = [acl objectForKey: @"users"];
[users addObjectUniquely: user];
[self _saveAcl: acl];
}
- (void) removeAclsForUsers: (NSArray *) oldUsers
{
NSDictionary *acl;
NSMutableDictionary *entries;
NSMutableArray *users;
acl = [self _aclEntries];
entries = [acl objectForKey: @"entries"];
[entries removeObjectsForKeys: oldUsers];
users = [acl objectForKey: @"users"];
[users removeObjectsInArray: oldUsers];
[self _saveAcl: acl];
}
- (NSArray *) aclUsers
{
return [[self _aclEntries] objectForKey: @"users"];
}
- (NSArray *) aclsForUser: (NSString *) uid
{
NSDictionary *entries;
entries = [[self _aclEntries] objectForKey: @"entries"];
return [entries objectForKey: uid];
}
- (void) setRoles: (NSArray *) roles
forUser: (NSString *) uid
{
NSMutableDictionary *acl;
NSMutableDictionary *entries;
acl = [self _aclEntries];
entries = [acl objectForKey: @"entries"];
[entries setObject: roles forKey: uid];
[self _saveAcl: acl];
}
@end

View File

@ -1,47 +0,0 @@
/* SOGoMAPIFSMessage.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef SOGOMAPIFSMESSAGE_H
#define SOGOMAPIFSMESSAGE_H
#import "SOGoMAPIVolatileMessage.h"
@class NSDate;
@class NSString;
@interface SOGoMAPIFSMessage : SOGoMAPIVolatileMessage
{
NSString *completeFilename;
NSUInteger inode;
NSData *lastModificationTime;
}
- (void) save;
- (NSString *) completeFilename;
- (NSDate *) creationTime;
- (NSDate *) lastModificationTime;
@end
#endif /* SOGOMAPIFSMESSAGE_H */

View File

@ -1,238 +0,0 @@
/* SOGoMAPIFSMessage.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSException.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import <NGExtensions/NSObject+Logs.h>
#import "SOGoMAPIFSFolder.h"
#import "SOGoMAPIFSMessage.h"
@implementation SOGoMAPIFSMessage
- (id) init
{
if ((self = [super init]))
{
completeFilename = nil;
inode = 0;
lastModificationTime = nil;
}
return self;
}
- (void) dealloc
{
[completeFilename release];
[super dealloc];
}
- (Class) mapistoreMessageClass
{
NSArray *dirMembers;
NSString *className;
/* FIXME: this method is a bit dirty */
dirMembers = [[container directory] componentsSeparatedByString: @"/"];
if ([dirMembers containsObject: @"fai"]) /* should not occur as FAI message
are instantiated directly in
MAPIStoreFolder */
className = @"MAPIStoreFAIMessage";
else if ([dirMembers containsObject: @"notes"])
className = @"MAPIStoreNotesMessage";
else
className = @"MAPIStoreFSMessage";
return NSClassFromString (className);
}
- (NSString *) completeFilename
{
if (!completeFilename)
{
completeFilename = [[container directory]
stringByAppendingPathComponent: nameInContainer];
[completeFilename retain];
}
return completeFilename;
}
- (BOOL) _readFileChangesDataWithDate: (NSDate **) newLMTime
andInode: (NSUInteger *) newInode
{
BOOL rc;
NSDictionary *attributes;
attributes = [[NSFileManager defaultManager]
fileAttributesAtPath: [self completeFilename]
traverseLink: NO];
if (attributes)
{
*newLMTime = [attributes fileModificationDate];
*newInode = [attributes fileSystemFileNumber];
rc = YES;
}
else
rc = NO;
return rc;
}
- (BOOL) _checkFileChangesDataWithDate: (NSDate **) newLMTime
andInode: (NSUInteger *) newInode
{
BOOL hasChanged = NO;
NSDate *lastLMTime;
NSUInteger lastInode;
if ([self _readFileChangesDataWithDate: &lastLMTime
andInode: &lastInode])
{
if (inode != lastInode
|| ![lastModificationTime isEqual: lastLMTime])
{
if (lastLMTime)
*newLMTime = lastLMTime;
if (newInode)
*newInode = lastInode;
hasChanged = YES;
}
}
return hasChanged;
}
- (NSMutableDictionary *) properties
{
NSData *content;
NSString *error;
NSPropertyListFormat format;
NSDate *lastLMTime;
NSUInteger lastInode;
if ([self _checkFileChangesDataWithDate: &lastLMTime
andInode: &lastInode])
{
[self logWithFormat: @"file '%@' new or modified: rereading properties",
[self completeFilename]];
[properties release];
properties = nil;
content = [NSData dataWithContentsOfFile: [self completeFilename]];
if (content)
{
properties = [NSPropertyListSerialization propertyListFromData: content
mutabilityOption: NSPropertyListMutableContainers
format: &format
errorDescription: &error];
[properties retain];
if (!properties)
[self logWithFormat: @"an error occurred during deserialization"
@" of message: '%@'", error];
}
ASSIGN (lastModificationTime, lastLMTime);
inode = lastInode;
}
return [super properties];
}
- (void) save
{
NSData *content;
NSDate *lastLMTime;
NSUInteger lastInode;
[container ensureDirectory];
// [self logWithFormat: @"%d props in whole dict", [properties count]];
content = [NSPropertyListSerialization
dataFromPropertyList: [self properties]
format: NSPropertyListBinaryFormat_v1_0
errorDescription: NULL];
if (![content writeToFile: [self completeFilename] atomically: YES])
[NSException raise: @"MAPIStoreIOException"
format: @"could not save message"];
[self _readFileChangesDataWithDate: &lastLMTime andInode: &lastInode];
ASSIGN (lastModificationTime, lastLMTime);
inode = lastInode;
// [self logWithFormat: @"fs message written to '%@'", [self completeFilename]];
}
- (NSString *) davEntityTag
{
NSDate *lm;
lm = [self lastModificationTime];
return [NSString stringWithFormat: @"%d", (int) [lm timeIntervalSince1970]];
}
- (NSException *) delete
{
NSFileManager *fm;
NSException *error;
fm = [NSFileManager defaultManager];
if (![fm removeFileAtPath: [self completeFilename] handler: NULL])
error = [NSException exceptionWithName: @"MAPIStoreIOException"
reason: @"could not delete message"
userInfo: nil];
else
error = nil;
return error;
}
- (id) _fileAttributeForKey: (NSString *) key
{
NSDictionary *attributes;
attributes = [[NSFileManager defaultManager]
fileAttributesAtPath: [self completeFilename]
traverseLink: NO];
return [attributes objectForKey: key];
}
- (NSDate *) creationTime
{
return [self _fileAttributeForKey: NSFileCreationDate];
}
- (NSDate *) lastModificationTime
{
return [self _fileAttributeForKey: NSFileModificationDate];
}
@end

View File

@ -1,12 +1,12 @@
/* SOGoMAPIVolatileMessage.h - this file is part of SOGo /* SOGoMAPIObject.h - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
* This file is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* This file is distributed in the hope that it will be useful, * This file is distributed in the hope that it will be useful,
@ -20,22 +20,30 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef SOGOMAPIVOLATILEMESSAGE_H #ifndef SOGOMAPIOBJECT_H
#define SOGOMAPIVOLATILEMESSAGE_H #define SOGOMAPIOBJECT_H
#import <SOGo/SOGoObject.h> #import <SOGo/SOGoObject.h>
@class NSDictionary;
@class NSMutableDictionary; @class NSMutableDictionary;
@interface SOGoMAPIVolatileMessage : SOGoObject @interface SOGoMAPIObject : SOGoObject
{ {
BOOL isNew;
NSMutableDictionary *properties; NSMutableDictionary *properties;
NSCalendarDate *creationDate;
NSCalendarDate *lastModified;
} }
- (void) setIsNew: (BOOL) newIsNew;
- (BOOL) isNew;
- (void) adjustLastModified;
- (NSMutableDictionary *) properties; - (NSMutableDictionary *) properties;
- (void) appendProperties: (NSDictionary *) newProperties; - (NSCalendarDate *) creationDate;
- (NSCalendarDate *) lastModified;
@end @end
#endif /* SOGOMAPIVOLATILEMESSAGE_H */ #endif /* SOGOMAPIOBJECT_H */

View File

@ -1,6 +1,6 @@
/* SOGoMAPIVolatileMessage.m - this file is part of SOGo /* SOGoMAPIObject.m - this file is part of SOGo
* *
* Copyright (C) 2011 Inverse inc * Copyright (C) 2012 Inverse inc
* *
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca> * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* *
@ -20,17 +20,19 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#import <Foundation/NSDictionary.h> #import "SOGoMAPIObject.h"
#import "SOGoMAPIVolatileMessage.h" @implementation SOGoMAPIObject
@implementation SOGoMAPIVolatileMessage
- (id) init - (id) init
{ {
if ((self = [super init])) if ((self = [super init]))
{ {
properties = nil; isNew = NO;
creationDate = [NSCalendarDate date];
[creationDate retain];
lastModified = [creationDate copy];
properties = [NSMutableDictionary new];
} }
return self; return self;
@ -38,21 +40,45 @@
- (void) dealloc - (void) dealloc
{ {
[creationDate release];
[lastModified release];
[properties release]; [properties release];
[super dealloc]; [super dealloc];
} }
- (void) setIsNew: (BOOL) newIsNew
{
isNew = newIsNew;
}
- (BOOL) isNew
{
return isNew;
}
- (void) adjustLastModified
{
ASSIGN (lastModified, [NSCalendarDate date]);
}
- (BOOL) isFolderish
{
return NO;
}
- (NSMutableDictionary *) properties - (NSMutableDictionary *) properties
{ {
if (!properties)
properties = [NSMutableDictionary new];
return properties; return properties;
} }
- (void) appendProperties: (NSDictionary *) newProperties - (NSCalendarDate *) creationDate
{ {
[[self properties] addEntriesFromDictionary: newProperties]; return creationDate;
}
- (NSCalendarDate *) lastModified
{
return lastModified;
} }
@end @end

View File

@ -23,164 +23,19 @@
/* A format-agnostic property list dumper. /* A format-agnostic property list dumper.
Usage: plreader [filename] */ Usage: plreader [filename] */
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSArray.h> #import <Foundation/NSArray.h>
#import <Foundation/NSData.h> #import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSProcessInfo.h> #import <Foundation/NSProcessInfo.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NSNull+misc.h>
const char *indentationStep = " "; #import "NSObject+PropertyList.m"
@interface NSObject (plext)
- (void) displayWithIndentation: (NSInteger) anInt;
@end
@implementation NSObject (plext)
- (void) _outputIndentation: (NSInteger) anInt
{
NSInteger i;
for (i = 0; i < anInt; i++)
printf ("%s", indentationStep);
}
- (void) displayWithIndentation: (NSInteger) anInt
{
printf ("(%s) %s",
[NSStringFromClass (isa) UTF8String],
[[self description] UTF8String]);
}
@end
@implementation NSDictionary (plext)
- (void) displayKey: (NSString *) key
withIndentation: (NSInteger) anInt
{
[self _outputIndentation: anInt];
printf ("%s ", [[key description] UTF8String]);
if ([key isKindOfClass: [NSValue class]])
printf ("(%s: 0x%.8x) ", [(NSValue *) key objCType], [key intValue]);
printf ("= ");
}
- (void) displayWithIndentation: (NSInteger) anInt
{
NSUInteger i, max;
NSArray *keys;
NSInteger subIndent;
NSString *key;
keys = [self allKeys];
max = [keys count];
printf ("{ (%ld) items\n", (long) max);
subIndent = anInt + 1;
for (i = 0; i < max; i++)
{
key = [keys objectAtIndex: i];
[self displayKey: key withIndentation: subIndent];
[[self objectForKey: key] displayWithIndentation: subIndent];
if (i < (max - 1))
printf (",");
printf ("\n");
}
[self _outputIndentation: anInt];
printf ("}");
}
@end
@implementation NSArray (plext)
- (void) displayCount: (NSUInteger) count
withIndentation: (NSInteger) anInt
{
[self _outputIndentation: anInt];
printf ("%lu = ", (unsigned long) count);
}
- (void) displayWithIndentation: (NSInteger) anInt
{
NSUInteger i, max;
NSInteger subIndent;
max = [self count];
printf ("[ (%ld) items\n", (long) max);
subIndent = anInt + 1;
for (i = 0; i < max; i++)
{
[self displayCount: i withIndentation: subIndent];
[[self objectAtIndex: i] displayWithIndentation: subIndent];
if (i < (max - 1))
printf (",");
printf ("\n");
}
[self _outputIndentation: anInt];
printf ("]");
}
@end
static void static void
PLReaderDumpPListFile (NSString *filename) PLReaderDumpPListFile (NSString *filename)
{ {
NSData *content; NSData *content;
NSDictionary *d;
NSPropertyListFormat format;
NSString *error = nil;
const char *formatName;
content = [NSData dataWithContentsOfFile: filename]; content = [NSData dataWithContentsOfFile: filename];
d = [NSPropertyListSerialization propertyListFromData: content OCDumpPListData (content);
mutabilityOption: NSPropertyListImmutable
format: &format
errorDescription: &error];
if (d)
{
switch (format)
{
case NSPropertyListOpenStepFormat:
formatName = "OpenStep";
break;
case NSPropertyListXMLFormat_v1_0:
formatName = "XML";
break;
case NSPropertyListBinaryFormat_v1_0:
formatName = "Binary";
break;
case NSPropertyListGNUstepFormat:
formatName = "GNUstep";
break;
case NSPropertyListGNUstepBinaryFormat:
formatName = "GNUstep binary";
break;
default: formatName = "unknown";
}
printf ("File format is: %s\n", formatName);
[d displayWithIndentation: 0];
printf ("\n");
}
else
printf ("an error occurred: %s\n", [error UTF8String]);
} }
int main() int main()