propagate from branch 'ca.inverse.sogo.1_3_17' (head 29aefdeb26834742b8cd9f01120573b4dcbcc7ed)
to branch 'ca.inverse.sogo' (head 3dfe653dfcaeadc5fe93ff1f2c0a1f9d049c1836) Monotone-Parent: 29aefdeb26834742b8cd9f01120573b4dcbcc7ed Monotone-Parent: 3dfe653dfcaeadc5fe93ff1f2c0a1f9d049c1836 Monotone-Revision: 4117fa474ee2ae428f109a99cb50a33479342fa8 Monotone-Author: jraby@inverse.ca Monotone-Date: 2012-07-12T16:47:28 Monotone-Branch: ca.inverse.sogomaint-2.0.2
commit
6a4657d23d
36
ChangeLog
36
ChangeLog
|
@ -114,6 +114,25 @@
|
|||
This still need some css tweaks.
|
||||
|
||||
|
||||
2012-07-01 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* OpenChange/MAPIStoreRecurrenceUtils.m
|
||||
(-setupRecurrenceWithMasterEntity:fromRecurrencePattern:): add
|
||||
exception dates to master entity based on the
|
||||
"DeletedInstanceDates" member of the struct.
|
||||
(-fillRecurrencePattern:withEvent:inTimeZone:inMemCtx:): new name
|
||||
for fillRecurrencePattern:withStartDate:andEndDate:, add exception
|
||||
dates to struct.
|
||||
|
||||
* OpenChange/NSDate+MAPIStore.m (NSDateCompare): new comparison
|
||||
function for sorting array of NSDate instances.
|
||||
|
||||
2012-06-30 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* OpenChange/NSObject+MAPIStore.h: renamed
|
||||
MAPIStoreTallocWrapper.MAPIStoreSOGoObject to .instance, to avoid
|
||||
confusion in certain versions of GCC with our new class type.
|
||||
|
||||
2012-06-29 Jean Raby <jraby@inverse.ca>
|
||||
|
||||
* SoObjects/SOGo/WORequest+SOGo.[mh]
|
||||
|
@ -124,6 +143,23 @@
|
|||
Let sogo append system sources if the request comes from an android
|
||||
client even if its user agent matches the IPhoneAddressBook
|
||||
|
||||
2012-06-29 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* OpenChange/MAPIStoreSOGo.m
|
||||
(sogo_message_attachment_open_embedded_message): added the "mode"
|
||||
parameter.
|
||||
|
||||
* 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>
|
||||
|
||||
* SoObjects/SOGo/SOGoObject.m (-initWithName:inContainer:): make
|
||||
sure that "_name" is neither nil nor empty.
|
||||
|
||||
2012-06-27 Jean Raby <jraby@inverse.ca>
|
||||
|
||||
* SoObjects/Appointments/SOGoAppointmentObject.m
|
||||
|
|
Binary file not shown.
|
@ -201,6 +201,7 @@ static BOOL debugLeaks;
|
|||
fileSuffix = [channelURL scheme];
|
||||
tc = [cm acquireOpenChannelForURL: channelURL];
|
||||
|
||||
/* FIXME: make use of [EOChannelAdaptor describeTableNames] instead */
|
||||
tableName = [url lastPathComponent];
|
||||
if ([tc evaluateExpressionX:
|
||||
[NSString stringWithFormat: @"SELECT count(*) FROM %@",
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
|
||||
#import <EOControl/EOQualifier.h>
|
||||
|
||||
@class SOGoMAPIVolatileMessage;
|
||||
@class SOGoMAPIDBObject;
|
||||
|
||||
@interface EOQualifier (MAPIStoreRestrictions)
|
||||
|
||||
- (BOOL) evaluateMAPIVolatileMessage: (SOGoMAPIVolatileMessage *) message;
|
||||
- (BOOL) evaluateSOGoMAPIDBObject: (SOGoMAPIDBObject *) object;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -28,28 +28,28 @@
|
|||
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import "SOGoMAPIVolatileMessage.h"
|
||||
#import "EOBitmaskQualifier.h"
|
||||
#import "SOGoMAPIDBObject.h"
|
||||
|
||||
#import "EOQualifier+MAPI.h"
|
||||
#import "EOBitmaskQualifier.h"
|
||||
|
||||
@implementation EOQualifier (MAPIStoreRestrictions)
|
||||
|
||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
||||
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) evaluateMAPIVolatileMessage: (SOGoMAPIVolatileMessage *) message
|
||||
- (BOOL) evaluateSOGoMAPIDBObject: (SOGoMAPIDBObject *) object
|
||||
{
|
||||
NSDictionary *properties;
|
||||
BOOL rc;
|
||||
|
||||
[self logWithFormat: @"evaluating message '%@'", message];
|
||||
[self logWithFormat: @"evaluating object '%@'", object];
|
||||
|
||||
properties = [message properties];
|
||||
rc = [self _evaluateMAPIVolatileMessageProperties: properties];
|
||||
properties = [object properties];
|
||||
rc = [self _evaluateSOGoMAPIDBObject: properties];
|
||||
|
||||
[self logWithFormat: @" evaluation result: %d", rc];
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
|||
|
||||
@implementation EOAndQualifier (MAPIStoreRestrictionsPrivate)
|
||||
|
||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
||||
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||
{
|
||||
NSUInteger i;
|
||||
BOOL rc;
|
||||
|
@ -69,7 +69,7 @@
|
|||
|
||||
for (i = 0; rc && i < count; i++)
|
||||
rc = [[qualifiers objectAtIndex: i]
|
||||
_evaluateMAPIVolatileMessageProperties: properties];
|
||||
_evaluateSOGoMAPIDBObject: properties];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@
|
|||
|
||||
@implementation EOOrQualifier (MAPIStoreRestrictionsPrivate)
|
||||
|
||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
||||
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||
{
|
||||
NSUInteger i;
|
||||
BOOL rc;
|
||||
|
@ -87,7 +87,7 @@
|
|||
|
||||
for (i = 0; !rc && i < count; i++)
|
||||
rc = [[qualifiers objectAtIndex: i]
|
||||
_evaluateMAPIVolatileMessageProperties: properties];
|
||||
_evaluateSOGoMAPIDBObject: properties];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -96,9 +96,9 @@
|
|||
|
||||
@implementation EONotQualifier (MAPIStoreRestrictionsPrivate)
|
||||
|
||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
||||
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||
{
|
||||
return ![qualifier _evaluateMAPIVolatileMessageProperties: properties];
|
||||
return ![qualifier _evaluateSOGoMAPIDBObject: properties];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -107,7 +107,7 @@
|
|||
|
||||
typedef BOOL (*EOComparator) (id, SEL, id);
|
||||
|
||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
||||
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||
{
|
||||
id finalKey;
|
||||
id propValue;
|
||||
|
@ -136,7 +136,7 @@ typedef BOOL (*EOComparator) (id, SEL, id);
|
|||
|
||||
@implementation EOBitmaskQualifier (MAPIStoreRestrictionsPrivate)
|
||||
|
||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
||||
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||
{
|
||||
NSNumber *propTag;
|
||||
id propValue;
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -41,9 +41,11 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
|||
MAPIStoreSamDBUtils.m \
|
||||
MAPIStoreUserContext.m \
|
||||
\
|
||||
SOGoMAPIVolatileMessage.m \
|
||||
SOGoMAPIFSFolder.m \
|
||||
SOGoMAPIFSMessage.m \
|
||||
SOGoMAPIObject.m \
|
||||
\
|
||||
SOGoMAPIDBObject.m \
|
||||
SOGoMAPIDBMessage.m \
|
||||
SOGoMAPIDBFolder.m \
|
||||
\
|
||||
MAPIStoreAppointmentWrapper.m \
|
||||
MAPIStoreAttachment.m \
|
||||
|
@ -53,18 +55,17 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
|||
MAPIStoreFolder.m \
|
||||
MAPIStoreMessage.m \
|
||||
MAPIStoreObject.m \
|
||||
MAPIStoreSOGoObject.m \
|
||||
MAPIStoreTable.m \
|
||||
MAPIStoreMessageTable.m \
|
||||
MAPIStoreFolderTable.m \
|
||||
MAPIStorePermissionsTable.m \
|
||||
\
|
||||
MAPIStoreVolatileMessage.m \
|
||||
\
|
||||
MAPIStoreFSBaseContext.m \
|
||||
MAPIStoreFSFolder.m \
|
||||
MAPIStoreFSFolderTable.m \
|
||||
MAPIStoreFSMessage.m \
|
||||
MAPIStoreFSMessageTable.m \
|
||||
MAPIStoreDBBaseContext.m \
|
||||
MAPIStoreDBFolder.m \
|
||||
MAPIStoreDBFolderTable.m \
|
||||
MAPIStoreDBMessage.m \
|
||||
MAPIStoreDBMessageTable.m \
|
||||
\
|
||||
MAPIStoreFAIMessage.m \
|
||||
MAPIStoreFAIMessageTable.m \
|
||||
|
@ -113,7 +114,10 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
|||
NSValue+MAPIStore.m \
|
||||
\
|
||||
EOBitmaskQualifier.m \
|
||||
EOQualifier+MAPI.m \
|
||||
\
|
||||
GCSSpecialQueries+OpenChange.m\
|
||||
\
|
||||
EOQualifier+MAPI.m
|
||||
|
||||
|
||||
$(SOGOBACKEND)_RESOURCE_FILES += \
|
||||
|
@ -145,7 +149,13 @@ PLREADER_TOOL = plreader
|
|||
$(PLREADER_TOOL)_OBJC_FILES += \
|
||||
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
|
||||
LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags)
|
||||
|
|
|
@ -28,11 +28,8 @@
|
|||
#import <Foundation/NSTimeZone.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
#import <NGCards/iCalAlarm.h>
|
||||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
#import <NGCards/iCalTrigger.h>
|
||||
#import <NGCards/NSString+NGCards.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
@ -995,7 +992,8 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
return [self getPidLidLocation: data inMemCtx: memCtx];
|
||||
}
|
||||
|
||||
- (int) getPidLidServerProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
||||
- (int) getPidLidServerProcessed: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
/* TODO: we need to check whether the event has been processed internally by
|
||||
SOGo or if it was received only by mail. We only assume the SOGo case
|
||||
|
@ -1003,7 +1001,8 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
return [self getYes: data inMemCtx: memCtx];
|
||||
}
|
||||
|
||||
- (int) getPidLidServerProcessingActions: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
||||
- (int) getPidLidServerProcessingActions: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
*data = MAPILongValue (memCtx,
|
||||
0x00000010 /* cpsCreatedOnPrincipal */
|
||||
|
@ -1074,29 +1073,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
|||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
|
||||
NSCalendarDate *startDate, NSTimeInterval duration,
|
||||
NSCalendarDate * endDate, iCalRecurrenceRule *rule)
|
||||
{
|
||||
uint32_t startMinutes;
|
||||
|
||||
[rule fillRecurrencePattern: &arp->RecurrencePattern
|
||||
withStartDate: startDate andEndDate: endDate];
|
||||
arp->ReaderVersion2 = 0x00003006;
|
||||
arp->WriterVersion2 = 0x00003009;
|
||||
|
||||
startMinutes = ([startDate hourOfDay] * 60 + [startDate minuteOfHour]);
|
||||
arp->StartTimeOffset = startMinutes;
|
||||
arp->EndTimeOffset = startMinutes + (uint32_t) (duration / 60);
|
||||
|
||||
arp->ExceptionCount = 0;
|
||||
arp->ReservedBlock1Size = 0;
|
||||
|
||||
/* Currently ignored in property.idl:
|
||||
arp->ReservedBlock2Size = 0; */
|
||||
}
|
||||
|
||||
- (struct SBinary_short *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx
|
||||
|
||||
{
|
||||
|
@ -1105,6 +1081,7 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
|
|||
struct SBinary_short *sBin;
|
||||
NSCalendarDate *firstStartDate;
|
||||
iCalRecurrenceRule *rule;
|
||||
NSUInteger startMinutes;
|
||||
|
||||
rule = [[event recurrenceRules] objectAtIndex: 0];
|
||||
|
||||
|
@ -1114,10 +1091,27 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
|
|||
[firstStartDate setTimeZone: timeZone];
|
||||
|
||||
arp = talloc_zero (memCtx, struct AppointmentRecurrencePattern);
|
||||
_fillAppointmentRecurrencePattern (arp, firstStartDate,
|
||||
[event durationAsTimeInterval],
|
||||
[event lastPossibleRecurrenceStartDate],
|
||||
rule);
|
||||
[rule fillRecurrencePattern: &arp->RecurrencePattern
|
||||
withEvent: event
|
||||
inTimeZone: timeZone
|
||||
inMemCtx: arp];
|
||||
arp->ReaderVersion2 = 0x00003006;
|
||||
arp->WriterVersion2 = 0x00003009;
|
||||
|
||||
startMinutes = ([firstStartDate hourOfDay] * 60
|
||||
+ [firstStartDate minuteOfHour]);
|
||||
arp->StartTimeOffset = startMinutes;
|
||||
arp->EndTimeOffset = (startMinutes
|
||||
+ (NSUInteger) ([event durationAsTimeInterval]
|
||||
/ 60));
|
||||
|
||||
arp->ExceptionCount = 0;
|
||||
arp->ReservedBlock1Size = 0;
|
||||
|
||||
/* Currently ignored in property.idl: arp->ReservedBlock2Size = 0; */
|
||||
|
||||
|
||||
/* convert struct to blob */
|
||||
sBin = talloc_zero (memCtx, struct SBinary_short);
|
||||
bin = set_AppointmentRecurrencePattern (sBin, arp);
|
||||
sBin->cb = bin->cb;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
- (uint32_t) AID;
|
||||
|
||||
- (int) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
|
||||
inMode: (enum OpenEmbeddedMessage_OpenModeFlags) mode
|
||||
withMID: (uint64_t *) mid
|
||||
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
}
|
||||
|
||||
- (int) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
|
||||
inMode: (enum OpenEmbeddedMessage_OpenModeFlags) mode
|
||||
withMID: (uint64_t *) mid
|
||||
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
|
@ -103,6 +104,13 @@
|
|||
|
||||
mapping = [self mapping];
|
||||
|
||||
if (mode == MAPI_CREATE)
|
||||
attMessage = [self createEmbeddedMessage];
|
||||
else
|
||||
{
|
||||
// if (attMessage)
|
||||
// [mapping registerURL: [attMessage url]
|
||||
// withID: *mid];
|
||||
attMessage = [self openEmbeddedMessage];
|
||||
if (attMessage)
|
||||
{
|
||||
|
@ -110,12 +118,9 @@
|
|||
*messagePtr = attMessage;
|
||||
*mapistoreMsgPtr = mapistoreMsg;
|
||||
}
|
||||
}
|
||||
// else if (flags == MAPI_CREATE)
|
||||
// {
|
||||
// attMessage = [self createEmbeddedMessage];
|
||||
// if (attMessage)
|
||||
// [mapping registerURL: [attMessage url]
|
||||
// withID: *mid];
|
||||
// }
|
||||
|
||||
return (attMessage ? MAPISTORE_SUCCESS : MAPISTORE_ERROR);
|
||||
|
|
|
@ -67,10 +67,10 @@
|
|||
{
|
||||
MAPIStoreEmbeddedMessage *msg;
|
||||
|
||||
if (isNew)
|
||||
msg = nil;
|
||||
else
|
||||
// if (isNew)
|
||||
msg = nil;
|
||||
// else
|
||||
// msg = nil;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
|
|
@ -1111,9 +1111,7 @@
|
|||
newAid = [[self attachmentKeys] count];
|
||||
|
||||
newAttachment = [MAPIStoreCalendarAttachment
|
||||
mapiStoreObjectWithSOGoObject: nil
|
||||
inContainer: self];
|
||||
[newAttachment setIsNew: YES];
|
||||
mapiStoreObjectInContainer: self];
|
||||
[newAttachment setAID: newAid];
|
||||
newKey = [NSString stringWithFormat: @"%ul", newAid];
|
||||
[attachmentParts setObject: newAttachment
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#import <Mailer/NSString+Mail.h>
|
||||
#import <SOGo/SOGoPermissions.h>
|
||||
|
||||
#import "MAPIStoreAttachment.h"
|
||||
#import "MAPIStoreContactsAttachment.h"
|
||||
#import "MAPIStoreContactsFolder.h"
|
||||
#import "MAPIStorePropertySelectors.h"
|
||||
|
@ -767,8 +768,7 @@
|
|||
|| [encoding isEqualToString: @"BASE64"])
|
||||
{
|
||||
attachment = [MAPIStoreContactsAttachment
|
||||
mapiStoreObjectWithSOGoObject: nil
|
||||
inContainer: self];
|
||||
mapiStoreObjectInContainer: self];
|
||||
[attachment setAID: 0];
|
||||
[attachment setPhoto: photo];
|
||||
[attachmentParts setObject: attachment forKey: @"photo"];
|
||||
|
|
|
@ -28,11 +28,9 @@
|
|||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import <SOGo/SOGoFolder.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
||||
#import "SOGoMAPIFSFolder.h"
|
||||
#import "SOGoMAPIFSMessage.h"
|
||||
|
||||
#import "MAPIStoreAttachment.h"
|
||||
// #import "MAPIStoreAttachmentTable.h"
|
||||
#import "MAPIStoreFallbackContext.h"
|
||||
|
@ -294,9 +292,11 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
|||
[MAPIStoreUserContext userContextWithUsername: username
|
||||
andTDBIndexing: indexingTdb]);
|
||||
|
||||
#if 0
|
||||
mapistore_mgmt_backend_register_user (newConnInfo,
|
||||
"SOGo",
|
||||
[username UTF8String]);
|
||||
#endif
|
||||
|
||||
connInfo = newConnInfo;
|
||||
username = [NSString stringWithUTF8String: newConnInfo->username];
|
||||
|
@ -315,9 +315,12 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
#if 0
|
||||
mapistore_mgmt_backend_unregister_user ([self connectionInfo], "SOGo",
|
||||
[[userContext username]
|
||||
UTF8String]);
|
||||
#endif
|
||||
|
||||
[contextUrl release];
|
||||
[userContext release];
|
||||
[containersBag release];
|
||||
|
@ -428,18 +431,21 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
|||
|
||||
[self ensureContextFolder];
|
||||
currentFolder = [self rootSOGoFolder];
|
||||
[containersBag addObject: currentFolder];
|
||||
path = [contextUrl path];
|
||||
if ([path hasPrefix: @"/"])
|
||||
path = [path substringFromIndex: 1];
|
||||
if ([path hasSuffix: @"/"])
|
||||
path = [path substringToIndex: [path length] - 1];
|
||||
if ([path length] > 0)
|
||||
{
|
||||
pathComponents = [path componentsSeparatedByString: @"/"];
|
||||
max = [pathComponents count];
|
||||
for (count = 0; currentFolder && count < max; count++)
|
||||
{
|
||||
[woContext setClientObject: currentFolder];
|
||||
currentFolder
|
||||
= [currentFolder lookupName: [pathComponents objectAtIndex: count]
|
||||
currentFolder = [currentFolder
|
||||
lookupName: [pathComponents objectAtIndex: count]
|
||||
inContext: woContext
|
||||
acquire: NO];
|
||||
if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all
|
||||
|
@ -448,6 +454,7 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
|||
else
|
||||
currentFolder = nil;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFolder)
|
||||
{
|
||||
|
@ -455,7 +462,6 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
|||
mapiStoreObjectWithSOGoObject: currentFolder
|
||||
inContainer: nil];
|
||||
[baseFolder setContext: self];
|
||||
|
||||
*folderPtr = baseFolder;
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
*
|
||||
|
@ -20,13 +20,13 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPISTOREFSBASECONTEXT_H
|
||||
#define MAPISTOREFSBASECONTEXT_H
|
||||
#ifndef MAPISTOREDBBASECONTEXT_H
|
||||
#define MAPISTOREDBBASECONTEXT_H
|
||||
|
||||
#import "MAPIStoreContext.h"
|
||||
|
||||
@interface MAPIStoreFSBaseContext : MAPIStoreContext
|
||||
@interface MAPIStoreDBBaseContext : MAPIStoreContext
|
||||
|
||||
@end
|
||||
|
||||
#endif /* MAPISTOREFSBASECONTEXT_H */
|
||||
#endif /* MAPISTOREDBBASECONTEXT_H */
|
|
@ -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
|
|
@ -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>
|
||||
*
|
||||
|
@ -20,14 +20,14 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPISTOREFSFOLDER_H
|
||||
#define MAPISTOREFSFOLDER_H
|
||||
#ifndef MAPISTOREDBFOLDER_H
|
||||
#define MAPISTOREDBFOLDER_H
|
||||
|
||||
#import "MAPIStoreFolder.h"
|
||||
|
||||
@interface MAPIStoreFSFolder : MAPIStoreFolder
|
||||
@interface MAPIStoreDBFolder : MAPIStoreFolder
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif /* MAPISTOREFSFOLDER_H */
|
||||
#endif /* MAPISTOREDBFOLDER_H */
|
|
@ -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
|
||||
*
|
||||
|
@ -31,15 +31,15 @@
|
|||
#import <SOGo/SOGoUser.h>
|
||||
#import "EOQualifier+MAPI.h"
|
||||
#import "MAPIStoreContext.h"
|
||||
#import "MAPIStoreFSFolderTable.h"
|
||||
#import "MAPIStoreFSMessage.h"
|
||||
#import "MAPIStoreFSMessageTable.h"
|
||||
#import "MAPIStoreDBFolderTable.h"
|
||||
#import "MAPIStoreDBMessage.h"
|
||||
#import "MAPIStoreDBMessageTable.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
#import "MAPIStoreUserContext.h"
|
||||
#import "SOGoMAPIFSFolder.h"
|
||||
#import "SOGoMAPIFSMessage.h"
|
||||
#import "SOGoMAPIDBFolder.h"
|
||||
#import "SOGoMAPIDBMessage.h"
|
||||
|
||||
#import "MAPIStoreFSFolder.h"
|
||||
#import "MAPIStoreDBFolder.h"
|
||||
|
||||
#undef DEBUG
|
||||
#include <mapistore/mapistore.h>
|
||||
|
@ -57,39 +57,34 @@ static NSString *MAPIStoreRightCreateSubfolders = @"RightsCreateSubfolders";
|
|||
static NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner";
|
||||
static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||
|
||||
@implementation MAPIStoreFSFolder
|
||||
@implementation MAPIStoreDBFolder
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
EOKeyValueQualifierK = [EOKeyValueQualifier class];
|
||||
}
|
||||
|
||||
- (void) setupAuxiliaryObjects
|
||||
{
|
||||
[super setupAuxiliaryObjects];
|
||||
ASSIGN (sogoObject, dbFolder);
|
||||
}
|
||||
|
||||
- (MAPIStoreMessageTable *) messageTable
|
||||
{
|
||||
return [MAPIStoreFSMessageTable tableForContainer: self];
|
||||
return [MAPIStoreDBMessageTable tableForContainer: self];
|
||||
}
|
||||
|
||||
- (MAPIStoreFolderTable *) folderTable
|
||||
{
|
||||
return [MAPIStoreFSFolderTable tableForContainer: self];
|
||||
return [MAPIStoreDBFolderTable tableForContainer: self];
|
||||
}
|
||||
|
||||
- (enum mapistore_error) createFolder: (struct SRow *) aRow
|
||||
withFID: (uint64_t) newFID
|
||||
andKey: (NSString **) newKeyP
|
||||
{
|
||||
NSString *newKey, *urlString;
|
||||
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;
|
||||
*newKeyP = [NSString stringWithFormat: @"0x%.16"PRIx64, (unsigned long long) newFID];
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
@ -97,14 +92,15 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
|||
- (MAPIStoreMessage *) createMessage
|
||||
{
|
||||
MAPIStoreMessage *newMessage;
|
||||
SOGoMAPIFSMessage *fsObject;
|
||||
SOGoMAPIDBMessage *fsObject;
|
||||
NSString *newKey;
|
||||
|
||||
newKey = [NSString stringWithFormat: @"%@.plist",
|
||||
[SOGoObject globallyUniqueObjectId]];
|
||||
fsObject = [SOGoMAPIFSMessage objectWithName: newKey
|
||||
fsObject = [SOGoMAPIDBMessage objectWithName: newKey
|
||||
inContainer: sogoObject];
|
||||
newMessage = [MAPIStoreFSMessage mapiStoreObjectWithSOGoObject: fsObject
|
||||
[fsObject setObjectType: MAPIDBObjectTypeMessage];
|
||||
newMessage = [MAPIStoreDBMessage mapiStoreObjectWithSOGoObject: fsObject
|
||||
inContainer: self];
|
||||
|
||||
return newMessage;
|
||||
|
@ -119,8 +115,9 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
|||
ownerUser = [[self userContext] sogoUser];
|
||||
if ([[context activeUser] isEqual: ownerUser]
|
||||
|| [self subscriberCanReadMessages])
|
||||
keys = [(SOGoMAPIFSFolder *) sogoObject
|
||||
toOneRelationshipKeysMatchingQualifier: qualifier
|
||||
keys = [(SOGoMAPIDBFolder *) sogoObject childKeysOfType: MAPIDBObjectTypeMessage
|
||||
includeDeleted: NO
|
||||
matchingQualifier: qualifier
|
||||
andSortOrderings: sortOrderings];
|
||||
else
|
||||
keys = [NSArray array];
|
||||
|
@ -131,39 +128,17 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
|||
- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier
|
||||
andSortOrderings: (NSArray *) sortOrderings
|
||||
{
|
||||
NSArray *entries;
|
||||
NSMutableArray *filteredEntries;
|
||||
NSUInteger count, max;
|
||||
MAPIStoreFSFolder *subfolder;
|
||||
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;
|
||||
return [dbFolder childKeysOfType: MAPIDBObjectTypeFolder
|
||||
includeDeleted: NO
|
||||
matchingQualifier: qualifier
|
||||
andSortOrderings: sortOrderings];
|
||||
}
|
||||
|
||||
- (NSDate *) lastMessageModificationTime
|
||||
{
|
||||
NSUInteger count, max;
|
||||
NSDate *date, *fileDate;
|
||||
MAPIStoreFSMessage *msg;
|
||||
MAPIStoreDBMessage *msg;
|
||||
NSArray *messageKeys;
|
||||
|
||||
messageKeys = [self messageKeys];
|
||||
|
@ -189,7 +164,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
|||
|
||||
- (SOGoFolder *) aclFolder
|
||||
{
|
||||
return propsFolder;
|
||||
return sogoObject;
|
||||
}
|
||||
|
||||
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
|
|
@ -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>
|
||||
*
|
||||
|
@ -20,12 +20,12 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPISTOREFSFOLDERTABLE_H
|
||||
#define MAPISTOREFSFOLDERTABLE_H
|
||||
#ifndef MAPISTOREDBFOLDERTABLE_H
|
||||
#define MAPISTOREDBFOLDERTABLE_H
|
||||
|
||||
#import "MAPIStoreFolderTable.h"
|
||||
|
||||
@interface MAPIStoreFSFolderTable : MAPIStoreFolderTable
|
||||
@interface MAPIStoreDBFolderTable : MAPIStoreFolderTable
|
||||
@end
|
||||
|
||||
#endif /* MAPISTOREFSFOLDERTABLE_H */
|
||||
#endif /* MAPISTOREDBFOLDERTABLE_H */
|
|
@ -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>
|
||||
*
|
||||
|
@ -24,9 +24,9 @@
|
|||
|
||||
#import "MAPIStoreTypes.h"
|
||||
|
||||
#import "MAPIStoreFSFolderTable.h"
|
||||
#import "MAPIStoreDBFolderTable.h"
|
||||
|
||||
@implementation MAPIStoreFSFolderTable
|
||||
@implementation MAPIStoreDBFolderTable
|
||||
|
||||
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
||||
{
|
|
@ -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>
|
||||
*
|
||||
|
@ -20,12 +20,12 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPISTOREFSMESSAGE_H
|
||||
#define MAPISTOREFSMESSAGE_H
|
||||
#ifndef MAPISTOREDBMESSAGE_H
|
||||
#define MAPISTOREDBMESSAGE_H
|
||||
|
||||
#import "MAPIStoreVolatileMessage.h"
|
||||
#import "MAPIStoreMessage.h"
|
||||
|
||||
@interface MAPIStoreFSMessage : MAPIStoreVolatileMessage
|
||||
@interface MAPIStoreDBMessage : MAPIStoreMessage
|
||||
@end
|
||||
|
||||
#endif /* MAPISTOREFSMESSAGE_H */
|
||||
#endif /* MAPISTOREDBMESSAGE_H */
|
|
@ -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
|
||||
*
|
||||
|
@ -21,24 +21,25 @@
|
|||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import "MAPIStoreContext.h"
|
||||
#import "MAPIStorePropertySelectors.h"
|
||||
#import "SOGoMAPIFSMessage.h"
|
||||
#import "SOGoMAPIDBMessage.h"
|
||||
|
||||
#import "MAPIStoreFSFolder.h"
|
||||
#import "MAPIStoreFSMessage.h"
|
||||
#import "MAPIStoreDBFolder.h"
|
||||
#import "MAPIStoreDBMessage.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
#import "NSData+MAPIStore.h"
|
||||
#import "NSObject+MAPIStore.h"
|
||||
|
||||
#undef DEBUG
|
||||
#include <mapistore/mapistore.h>
|
||||
#include <mapistore/mapistore_errors.h>
|
||||
|
||||
@implementation MAPIStoreFSMessage
|
||||
@implementation MAPIStoreDBMessage
|
||||
|
||||
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
|
@ -60,13 +61,96 @@
|
|||
/* FIXME (hack): append a few undocumented properties that can be added to
|
||||
FAI messages */
|
||||
for (count = 0; count < 8; count++)
|
||||
properties->aulPropTag[MAPIStoreSupportedPropertiesCount+count] = faiProperties[count];
|
||||
properties->aulPropTag[MAPIStoreSupportedPropertiesCount+count]
|
||||
= faiProperties[count];
|
||||
|
||||
*propertiesP = properties;
|
||||
|
||||
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
|
||||
{
|
||||
uint64_t newVersion;
|
||||
|
@ -80,9 +164,7 @@
|
|||
|
||||
[self logWithFormat: @"%d props in dict", [properties count]];
|
||||
|
||||
[sogoObject appendProperties: properties];
|
||||
[sogoObject save];
|
||||
[properties removeAllObjects];
|
||||
}
|
||||
|
||||
- (BOOL) _messageIsFreeBusy
|
||||
|
@ -91,7 +173,7 @@
|
|||
|
||||
/* This is a HACK until we figure out how to determine a message position in
|
||||
the mailbox hierarchy.... (missing: folderid and role) */
|
||||
msgClass = [[sogoObject properties]
|
||||
msgClass = [properties
|
||||
objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)];
|
||||
|
||||
return [msgClass isEqualToString: @"IPM.Microsoft.ScheduleData.FreeBusy"];
|
||||
|
@ -115,12 +197,12 @@
|
|||
|
||||
- (NSDate *) creationTime
|
||||
{
|
||||
return [sogoObject creationTime];
|
||||
return [sogoObject creationDate];
|
||||
}
|
||||
|
||||
- (NSDate *) lastModificationTime
|
||||
{
|
||||
return [sogoObject lastModificationTime];
|
||||
return [sogoObject lastModified];
|
||||
}
|
||||
|
||||
@end
|
|
@ -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>
|
||||
*
|
||||
|
@ -20,12 +20,12 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPISTOREFSMESSAGETABLE_H
|
||||
#define MAPISTOREFSMESSAGETABLE_H
|
||||
#ifndef MAPISTOREDBMESSAGETABLE_H
|
||||
#define MAPISTOREDBMESSAGETABLE_H
|
||||
|
||||
#import "MAPIStoreMessageTable.h"
|
||||
|
||||
@interface MAPIStoreFSMessageTable : MAPIStoreMessageTable
|
||||
@interface MAPIStoreDBMessageTable : MAPIStoreMessageTable
|
||||
@end
|
||||
|
||||
#endif /* MAPISTOREFSMESSAGETABLE_H */
|
||||
#endif /* MAPISTOREDBMESSAGETABLE_H */
|
|
@ -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>
|
||||
*
|
||||
|
@ -25,25 +25,25 @@
|
|||
#import <EOControl/EOQualifier.h>
|
||||
|
||||
#import "MAPIStoreTypes.h"
|
||||
#import "MAPIStoreFSMessage.h"
|
||||
#import "MAPIStoreDBMessage.h"
|
||||
|
||||
#import "MAPIStoreFSMessageTable.h"
|
||||
#import "MAPIStoreDBMessageTable.h"
|
||||
|
||||
#undef DEBUG
|
||||
#include <mapistore/mapistore.h>
|
||||
|
||||
static Class MAPIStoreFSMessageK = Nil;
|
||||
static Class MAPIStoreDBMessageK = Nil;
|
||||
|
||||
@implementation MAPIStoreFSMessageTable
|
||||
@implementation MAPIStoreDBMessageTable
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
MAPIStoreFSMessageK = [MAPIStoreFSMessage class];
|
||||
MAPIStoreDBMessageK = [MAPIStoreDBMessage class];
|
||||
}
|
||||
|
||||
+ (Class) childObjectClass
|
||||
{
|
||||
return MAPIStoreFSMessageK;
|
||||
return MAPIStoreDBMessageK;
|
||||
}
|
||||
|
||||
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef MAPISTOREFAIMESSAGE_H
|
||||
#define MAPISTOREFAIMESSAGE_H
|
||||
|
||||
#import "MAPIStoreFSMessage.h"
|
||||
#import "MAPIStoreDBMessage.h"
|
||||
|
||||
@interface MAPIStoreFAIMessage : MAPIStoreFSMessage
|
||||
@interface MAPIStoreFAIMessage : MAPIStoreDBMessage
|
||||
@end
|
||||
|
||||
#endif /* MAPISTOREFAIMESSAGE_H */
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef MAPISTOREFAIMESSAGETABLE_H
|
||||
#define MAPISTOREFAIMESSAGETABLE_H
|
||||
|
||||
#import "MAPIStoreFSMessageTable.h"
|
||||
#import "MAPIStoreDBMessageTable.h"
|
||||
|
||||
@interface MAPIStoreFAIMessageTable : MAPIStoreFSMessageTable
|
||||
@interface MAPIStoreFAIMessageTable : MAPIStoreDBMessageTable
|
||||
@end
|
||||
|
||||
#endif /* MAPISTOREFAIMESSAGETABLE_H */
|
||||
|
|
|
@ -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
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef MAPISTOREFALLBACKCONTEXT_H
|
||||
#define MAPISTOREFALLBACKCONTEXT_H
|
||||
|
||||
#import "MAPIStoreFSBaseContext.h"
|
||||
#import "MAPIStoreDBBaseContext.h"
|
||||
|
||||
@interface MAPIStoreFallbackContext : MAPIStoreFSBaseContext
|
||||
@interface MAPIStoreFallbackContext : MAPIStoreDBBaseContext
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#import "MAPIStoreUserContext.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
#import "SOGoMAPIFSFolder.h"
|
||||
#import "SOGoMAPIDBFolder.h"
|
||||
|
||||
#import "MAPIStoreFallbackContext.h"
|
||||
|
||||
|
@ -51,10 +51,11 @@
|
|||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
struct mapistore_contexts_list *firstContext = NULL, *context;
|
||||
SOGoMAPIFSFolder *root;
|
||||
SOGoMAPIDBFolder *root;
|
||||
NSArray *names;
|
||||
NSUInteger count, max;
|
||||
NSString *baseURL, *url, *name;
|
||||
MAPIStoreUserContext *userContext;
|
||||
|
||||
baseURL = [NSString stringWithFormat: @"sogo://%@@fallback/", userName];
|
||||
|
||||
|
@ -67,11 +68,15 @@
|
|||
|
||||
DLIST_ADD_END (firstContext, context, void);
|
||||
|
||||
|
||||
/* Maybe emsmdbp_provisioning should be fixed in order to only take the uri
|
||||
returned above to avoid deleting its entries... */
|
||||
root = [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: baseURL]
|
||||
andTableType: MAPISTORE_MESSAGE_TABLE];
|
||||
root = [SOGoMAPIDBFolder objectWithName: [self MAPIModuleName]
|
||||
inContainer: nil];
|
||||
[root setOwner: userName];
|
||||
userContext = [MAPIStoreUserContext userContextWithUsername: userName
|
||||
andTDBIndexing: indexingTdb];
|
||||
[userContext ensureFolderTableExists];
|
||||
[root setTableUrl: [userContext folderTableURL]];
|
||||
names = [root toManyRelationshipKeys];
|
||||
max = [names count];
|
||||
for (count = 0; count < max; count++)
|
||||
|
|
|
@ -38,29 +38,34 @@
|
|||
@class MAPIStoreMessageTable;
|
||||
@class MAPIStorePermissionsTable;
|
||||
@class SOGoFolder;
|
||||
@class SOGoMAPIFSFolder;
|
||||
@class SOGoMAPIFSMessage;
|
||||
@class SOGoMAPIDBFolder;
|
||||
@class SOGoMAPIDBMessage;
|
||||
|
||||
#import "MAPIStoreObject.h"
|
||||
#import "MAPIStoreSOGoObject.h"
|
||||
|
||||
@interface MAPIStoreFolder : MAPIStoreObject
|
||||
@interface MAPIStoreFolder : MAPIStoreSOGoObject
|
||||
{
|
||||
MAPIStoreContext *context;
|
||||
// NSArray *messageKeys;
|
||||
// NSArray *faiMessageKeys;
|
||||
// NSArray *folderKeys;
|
||||
|
||||
SOGoMAPIFSFolder *faiFolder;
|
||||
SOGoMAPIFSFolder *propsFolder;
|
||||
SOGoMAPIFSMessage *propsMessage;
|
||||
SOGoMAPIDBFolder *dbFolder;
|
||||
// SOGoMAPIDBFolder *faiFolder;
|
||||
// SOGoMAPIDBFolder *propsFolder;
|
||||
// SOGoMAPIDBMessage *propsMessage;
|
||||
}
|
||||
|
||||
- (void) setContext: (MAPIStoreContext *) newContext;
|
||||
|
||||
- (void) setupAuxiliaryObjects;
|
||||
|
||||
- (SOGoMAPIDBFolder *) dbFolder;
|
||||
|
||||
- (NSArray *) activeMessageTables;
|
||||
- (NSArray *) activeFAIMessageTables;
|
||||
|
||||
- (SOGoMAPIFSMessage *) propertiesMessage;
|
||||
// - (SOGoMAPIDBMessage *) propertiesMessage;
|
||||
|
||||
- (id) lookupMessageByURL: (NSString *) messageURL;
|
||||
- (id) lookupFolderByURL: (NSString *) folderURL;
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
#import "NSDate+MAPIStore.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
#import "NSObject+MAPIStore.h"
|
||||
#import "SOGoMAPIFSFolder.h"
|
||||
#import "SOGoMAPIFSMessage.h"
|
||||
#import "SOGoMAPIDBFolder.h"
|
||||
#import "SOGoMAPIDBMessage.h"
|
||||
|
||||
#include <gen_ndr/exchange.h>
|
||||
|
||||
|
@ -79,33 +79,67 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
// messageKeys = nil;
|
||||
// faiMessageKeys = nil;
|
||||
// folderKeys = nil;
|
||||
faiFolder = nil;
|
||||
dbFolder = nil;
|
||||
context = nil;
|
||||
|
||||
propsFolder = nil;
|
||||
propsMessage = nil;
|
||||
// propsFolder = nil;
|
||||
// propsMessage = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) _setupAuxiliaryObjects
|
||||
- (void) setupAuxiliaryObjects
|
||||
{
|
||||
NSURL *propsURL;
|
||||
NSString *urlString;
|
||||
NSURL *folderURL;
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -119,7 +153,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
inContainer: newContainer])
|
||||
&& newContainer)
|
||||
{
|
||||
[self _setupAuxiliaryObjects];
|
||||
[self setupAuxiliaryObjects];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -129,13 +163,13 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
{
|
||||
ASSIGN (context, newContext);
|
||||
if (newContext)
|
||||
[self _setupAuxiliaryObjects];
|
||||
[self setupAuxiliaryObjects];
|
||||
}
|
||||
|
||||
- (MAPIStoreContext *) context
|
||||
{
|
||||
if (!context)
|
||||
[self setContext: [container context]];
|
||||
[self setContext: (MAPIStoreContext *) [container context]];
|
||||
|
||||
return context;
|
||||
}
|
||||
|
@ -145,29 +179,31 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
// [messageKeys release];
|
||||
// [faiMessageKeys release];
|
||||
// [folderKeys release];
|
||||
[propsMessage release];
|
||||
[propsFolder release];
|
||||
[faiFolder release];
|
||||
// [propsMessage release];
|
||||
[dbFolder release];
|
||||
[context release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (SOGoMAPIDBFolder *) dbFolder
|
||||
{
|
||||
return dbFolder;
|
||||
}
|
||||
|
||||
/* backend interface */
|
||||
|
||||
- (SOGoMAPIFSMessage *) propertiesMessage
|
||||
{
|
||||
return propsMessage;
|
||||
}
|
||||
// - (SOGoMAPIDBMessage *) propertiesMessage
|
||||
// {
|
||||
// return propsMessage;
|
||||
// }
|
||||
|
||||
- (uint64_t) objectVersion
|
||||
{
|
||||
NSNumber *value;
|
||||
NSDictionary *props;
|
||||
uint64_t cn;
|
||||
|
||||
props = [propsMessage properties];
|
||||
value = [props objectForKey: MAPIPropertyKey (PidTagChangeNumber)];
|
||||
value = [properties objectForKey: MAPIPropertyKey (PidTagChangeNumber)];
|
||||
if (value)
|
||||
cn = [value unsignedLongLongValue];
|
||||
else
|
||||
|
@ -175,10 +211,10 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
[self logWithFormat: @"no value for PidTagChangeNumber, adding one now"];
|
||||
cn = [[self context] getNewChangeNumber];
|
||||
value = [NSNumber numberWithUnsignedLongLong: cn];
|
||||
props = [NSDictionary dictionaryWithObject: value
|
||||
|
||||
[properties setObject: value
|
||||
forKey: MAPIPropertyKey (PidTagChangeNumber)];
|
||||
[propsMessage appendProperties: props];
|
||||
[propsMessage save];
|
||||
[dbFolder save];
|
||||
}
|
||||
|
||||
return cn >> 16;
|
||||
|
@ -186,21 +222,24 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
|
||||
- (id) lookupFolder: (NSString *) folderKey
|
||||
{
|
||||
MAPIStoreFolder *childFolder = nil;
|
||||
MAPIStoreFolder *childFolder;
|
||||
SOGoFolder *sogoFolder;
|
||||
WOContext *woContext;
|
||||
|
||||
if ([[self folderKeys] containsObject: folderKey])
|
||||
{
|
||||
woContext = [[self userContext] woContext];
|
||||
sogoFolder = [sogoObject lookupName: folderKey
|
||||
inContext: woContext
|
||||
sogoFolder = [sogoObject lookupName: folderKey inContext: woContext
|
||||
acquire: NO];
|
||||
[sogoFolder setContext: woContext];
|
||||
if (sogoFolder && ![sogoFolder isKindOfClass: NSExceptionK])
|
||||
{
|
||||
[sogoFolder setContext: woContext];
|
||||
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder
|
||||
inContainer: self];
|
||||
}
|
||||
}
|
||||
else
|
||||
childFolder = nil;
|
||||
|
||||
return childFolder;
|
||||
}
|
||||
|
@ -264,7 +303,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
{
|
||||
if ([[self faiMessageKeys] containsObject: messageKey])
|
||||
{
|
||||
msgObject = [faiFolder lookupName: messageKey
|
||||
msgObject = [dbFolder lookupName: messageKey
|
||||
inContext: nil
|
||||
acquire: NO];
|
||||
childMessage
|
||||
|
@ -383,9 +422,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
|
||||
- (int) deleteFolder
|
||||
{
|
||||
[propsMessage delete];
|
||||
[propsFolder delete];
|
||||
[faiFolder delete];
|
||||
// [propsMessage delete];
|
||||
[dbFolder delete];
|
||||
|
||||
[self cleanupCaches];
|
||||
|
||||
|
@ -1004,7 +1042,11 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
/* TODO: this should no longer be required once mapistore v2 API is in
|
||||
place, when we can then do this from -dealloc below */
|
||||
|
||||
[dbFolder reloadIfNeeded];
|
||||
|
||||
propsCopy = [newProperties mutableCopy];
|
||||
[propsCopy autorelease];
|
||||
|
||||
currentProp = bannedProps;
|
||||
while (*currentProp)
|
||||
{
|
||||
|
@ -1012,9 +1054,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
currentProp++;
|
||||
}
|
||||
|
||||
[propsMessage appendProperties: propsCopy];
|
||||
[propsMessage save];
|
||||
[propsCopy release];
|
||||
[properties addEntriesFromDictionary: propsCopy];
|
||||
[dbFolder save];
|
||||
}
|
||||
|
||||
- (NSArray *) messageKeys
|
||||
|
@ -1039,8 +1080,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier
|
||||
andSortOrderings: (NSArray *) sortOrderings
|
||||
{
|
||||
return [faiFolder
|
||||
toOneRelationshipKeysMatchingQualifier: qualifier
|
||||
return [dbFolder childKeysOfType: MAPIDBObjectTypeFAI
|
||||
includeDeleted: NO
|
||||
matchingQualifier: qualifier
|
||||
andSortOrderings: sortOrderings];
|
||||
}
|
||||
|
||||
|
@ -1287,6 +1329,19 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
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
|
||||
withTag: (enum MAPITAGS) propTag
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
|
@ -1294,8 +1349,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
int rc;
|
||||
id value;
|
||||
|
||||
value = [[propsMessage properties]
|
||||
objectForKey: MAPIPropertyKey (propTag)];
|
||||
value = [properties objectForKey: MAPIPropertyKey (propTag)];
|
||||
if (value)
|
||||
rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
|
||||
else
|
||||
|
@ -1307,13 +1361,15 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
- (MAPIStoreMessage *) _createAssociatedMessage
|
||||
{
|
||||
MAPIStoreMessage *newMessage;
|
||||
SOGoMAPIFSMessage *fsObject;
|
||||
SOGoMAPIDBMessage *dbObject;
|
||||
NSString *newKey;
|
||||
|
||||
newKey = [NSString stringWithFormat: @"%@.plist",
|
||||
[SOGoObject globallyUniqueObjectId]];
|
||||
fsObject = [SOGoMAPIFSMessage objectWithName: newKey inContainer: faiFolder];
|
||||
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: fsObject
|
||||
dbObject = [SOGoMAPIDBMessage objectWithName: newKey inContainer: dbFolder];
|
||||
[dbObject setObjectType: MAPIDBObjectTypeFAI];
|
||||
[dbObject setIsNew: YES];
|
||||
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: dbObject
|
||||
inContainer: self];
|
||||
|
||||
return newMessage;
|
||||
|
@ -1328,8 +1384,14 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
newMessage = [self _createAssociatedMessage];
|
||||
else
|
||||
newMessage = [self createMessage];
|
||||
/* 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];
|
||||
/* 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;
|
||||
|
@ -1598,12 +1660,12 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
|||
|
||||
- (NSDate *) creationTime
|
||||
{
|
||||
return [propsMessage creationTime];
|
||||
return [dbFolder creationDate];
|
||||
}
|
||||
|
||||
- (NSDate *) lastModificationTime
|
||||
{
|
||||
return [propsMessage lastModificationTime];
|
||||
return [dbFolder lastModified];
|
||||
}
|
||||
|
||||
/* subclasses */
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
@interface MAPIStoreGCSFolder : MAPIStoreFolder
|
||||
{
|
||||
SOGoMAPIFSMessage *versionsMessage;
|
||||
SOGoMAPIDBMessage *versionsMessage;
|
||||
NSArray *activeUserRoles;
|
||||
EOQualifier *componentQualifier;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#import "NSData+MAPIStore.h"
|
||||
#import "NSDate+MAPIStore.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
#import "SOGoMAPIFSMessage.h"
|
||||
#import "SOGoMAPIDBMessage.h"
|
||||
|
||||
#import "MAPIStoreGCSFolder.h"
|
||||
|
||||
|
@ -71,8 +71,9 @@ static Class NSNumberK;
|
|||
- (void) setupVersionsMessage
|
||||
{
|
||||
ASSIGN (versionsMessage,
|
||||
[SOGoMAPIFSMessage objectWithName: @"versions.plist"
|
||||
inContainer: propsFolder]);
|
||||
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
|
||||
inContainer: dbFolder]);
|
||||
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
|
@ -288,7 +289,8 @@ static Class NSNumberK;
|
|||
forKey: @"PredecessorChangeList"];
|
||||
[changeList release];
|
||||
}
|
||||
[changeList setObject: globCnt forKey: guid];
|
||||
[changeList setObject: globCnt
|
||||
forKey: guid];
|
||||
}
|
||||
|
||||
- (EOQualifier *) componentQualifier
|
||||
|
@ -349,6 +351,7 @@ static Class NSNumberK;
|
|||
[sortOrdering retain];
|
||||
}
|
||||
|
||||
[versionsMessage reloadIfNeeded];
|
||||
currentProperties = [versionsMessage properties];
|
||||
|
||||
lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"];
|
||||
|
@ -451,7 +454,6 @@ static Class NSNumberK;
|
|||
forKey: @"SyncLastSynchronisationDate"];
|
||||
[currentProperties setObject: lastModificationDate
|
||||
forKey: @"SyncLastModificationDate"];
|
||||
[versionsMessage appendProperties: currentProperties];
|
||||
[versionsMessage save];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
@interface MAPIStoreMailAttachment : MAPIStoreAttachment
|
||||
{
|
||||
NSDictionary *bodyInfo;
|
||||
SOGoMailBodyPart *bodyPart;
|
||||
}
|
||||
|
||||
- (void) setBodyInfo: (NSDictionary *) newBodyInfo;
|
||||
- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
if ((self = [super init]))
|
||||
{
|
||||
bodyInfo = nil;
|
||||
bodyPart = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -60,6 +61,7 @@
|
|||
- (void) dealloc
|
||||
{
|
||||
[bodyInfo release];
|
||||
[bodyPart release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -68,6 +70,11 @@
|
|||
ASSIGN (bodyInfo, newBodyInfo);
|
||||
}
|
||||
|
||||
- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart
|
||||
{
|
||||
ASSIGN (bodyPart, newBodyPart);
|
||||
}
|
||||
|
||||
- (int) getPidTagAttachMethod: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
|
@ -187,7 +194,7 @@
|
|||
- (int) getPidTagAttachDataBinary: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
*data = [[sogoObject fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx];
|
||||
*data = [[bodyPart fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx];
|
||||
|
||||
return MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
@interface MAPIStoreMailFolder : MAPIStoreFolder
|
||||
{
|
||||
SOGoMAPIFSMessage *versionsMessage;
|
||||
SOGoMAPIDBMessage *versionsMessage;
|
||||
}
|
||||
|
||||
- (BOOL) ensureFolderExists;
|
||||
|
|
|
@ -54,9 +54,8 @@
|
|||
#import "MAPIStoreTypes.h"
|
||||
#import "NSData+MAPIStore.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
#import "SOGoMAPIFSMessage.h"
|
||||
#import "SOGoMAPIDBMessage.h"
|
||||
|
||||
#import "SOGoMAPIVolatileMessage.h"
|
||||
#import "MAPIStoreMailVolatileMessage.h"
|
||||
|
||||
#import "MAPIStoreMailFolder.h"
|
||||
|
@ -97,8 +96,9 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
|
|||
- (void) setupVersionsMessage
|
||||
{
|
||||
ASSIGN (versionsMessage,
|
||||
[SOGoMAPIFSMessage objectWithName: @"versions.plist"
|
||||
inContainer: propsFolder]);
|
||||
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
|
||||
inContainer: dbFolder]);
|
||||
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
|
||||
}
|
||||
|
||||
- (BOOL) ensureFolderExists
|
||||
|
@ -119,6 +119,9 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
|
|||
&& ![[(SOGoMailFolder *) sogoObject displayName]
|
||||
isEqualToString: newDisplayName])
|
||||
{
|
||||
[NSException raise: @"MAPIStoreIOException"
|
||||
format: @"renaming a mail folder via OpenChange is"
|
||||
@" currently a bad idea"];
|
||||
[(SOGoMailFolder *) sogoObject renameTo: newDisplayName];
|
||||
propsCopy = [newProperties mutableCopy];
|
||||
[propsCopy removeObjectForKey: key];
|
||||
|
@ -489,10 +492,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
|||
now = [NSCalendarDate date];
|
||||
[now setTimeZone: utcTZ];
|
||||
|
||||
currentProperties = [[versionsMessage properties] mutableCopy];
|
||||
if (!currentProperties)
|
||||
currentProperties = [NSMutableDictionary new];
|
||||
[currentProperties autorelease];
|
||||
[versionsMessage reloadIfNeeded];
|
||||
currentProperties = [versionsMessage properties];
|
||||
messages = [currentProperties objectForKey: @"Messages"];
|
||||
if (!messages)
|
||||
{
|
||||
|
@ -613,7 +614,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
|||
ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]];
|
||||
[currentProperties setObject: ti
|
||||
forKey: @"SyncLastSynchronisationDate"];
|
||||
[versionsMessage appendProperties: currentProperties];
|
||||
[versionsMessage save];
|
||||
}
|
||||
|
||||
|
@ -1004,20 +1004,16 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
|||
|
||||
- (MAPIStoreMessage *) createMessage
|
||||
{
|
||||
MAPIStoreMailVolatileMessage *newMessage;
|
||||
SOGoMAPIVolatileMessage *newObject;
|
||||
SOGoMAPIObject *childObject;
|
||||
|
||||
newObject = [SOGoMAPIVolatileMessage
|
||||
objectWithName: [SOGoObject globallyUniqueObjectId]
|
||||
childObject = [SOGoMAPIObject objectWithName: [SOGoMAPIObject
|
||||
globallyUniqueObjectId]
|
||||
inContainer: sogoObject];
|
||||
newMessage
|
||||
= [MAPIStoreMailVolatileMessage mapiStoreObjectWithSOGoObject: newObject
|
||||
return [MAPIStoreMailVolatileMessage
|
||||
mapiStoreObjectWithSOGoObject: childObject
|
||||
inContainer: self];
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
|
||||
{
|
||||
NSMutableArray *roles;
|
||||
|
|
|
@ -1529,8 +1529,8 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
|||
if (currentPart)
|
||||
{
|
||||
attachment = [MAPIStoreMailAttachment
|
||||
mapiStoreObjectWithSOGoObject: currentPart
|
||||
inContainer: self];
|
||||
mapiStoreObjectInContainer: self];
|
||||
[attachment setBodyPart: currentPart];
|
||||
[attachment setBodyInfo: [attachmentParts objectForKey: childKey]];
|
||||
[attachment setAID: [[self attachmentKeys] indexOfObject: childKey]];
|
||||
}
|
||||
|
|
|
@ -332,7 +332,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
|
|||
if (!fetchedCoreInfos)
|
||||
{
|
||||
fetchedCoreInfos = YES;
|
||||
[(SOGoMailFolder *) [container sogoObject]
|
||||
[(SOGoMailFolder *) [(MAPIStoreMailFolder *) container sogoObject]
|
||||
prefetchCoreInfosForMessageKeys: [self restrictedChildKeys]];
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef MAPISTOREMAILVOLATILEMESSAGE_H
|
||||
#define MAPISTOREMAILVOLATILEMESSAGE_H
|
||||
|
||||
#import "MAPIStoreVolatileMessage.h"
|
||||
#import "MAPIStoreMessage.h"
|
||||
|
||||
@interface MAPIStoreMailVolatileMessage : MAPIStoreVolatileMessage
|
||||
@interface MAPIStoreMailVolatileMessage : MAPIStoreMessage
|
||||
|
||||
- (int) submitWithFlags: (enum SubmitFlags) flags;
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#import <Mailer/NSString+Mail.h>
|
||||
|
||||
#import "MAPIStoreAttachment.h"
|
||||
#import "MAPIStoreAttachmentTable.h"
|
||||
#import "MAPIStoreContext.h"
|
||||
#import "MAPIStoreMailFolder.h"
|
||||
#import "MAPIStoreMIME.h"
|
||||
|
@ -60,7 +61,7 @@
|
|||
#import "NSData+MAPIStore.h"
|
||||
#import "NSObject+MAPIStore.h"
|
||||
#import "NSString+MAPIStore.h"
|
||||
#import "SOGoMAPIVolatileMessage.h"
|
||||
#import "SOGoMAPIObject.h"
|
||||
|
||||
#import "MAPIStoreMailVolatileMessage.h"
|
||||
|
||||
|
@ -68,6 +69,8 @@
|
|||
#include <mapistore/mapistore.h>
|
||||
#include <mapistore/mapistore_errors.h>
|
||||
|
||||
static Class NSNumberK = Nil;
|
||||
|
||||
static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
||||
|
||||
//
|
||||
|
@ -242,6 +245,106 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
|||
|
||||
@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
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
|
@ -258,9 +361,11 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
|||
|
||||
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,
|
||||
PR_OBJECT_TYPE,
|
||||
PR_DISPLAY_TYPE,
|
||||
|
@ -660,10 +765,13 @@ MakeTextPartBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
return textBody;
|
||||
}
|
||||
|
||||
// static id
|
||||
// MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||
// NSString **contentType)
|
||||
static id
|
||||
MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||
NSString **contentType)
|
||||
MakeMessageBody (NSDictionary *mailProperties, NSString **contentType)
|
||||
{
|
||||
NSDictionary *attachmentParts;
|
||||
id messageBody, textBody;
|
||||
NSString *textContentType;
|
||||
NSArray *parts;
|
||||
|
@ -671,6 +779,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
NGMutableHashMap *headers;
|
||||
NSUInteger count, max;
|
||||
|
||||
attachmentParts = [mailProperties objectForKey: @"attachments"];
|
||||
textBody = MakeTextPartBody (mailProperties, attachmentParts,
|
||||
&textContentType);
|
||||
|
||||
|
@ -707,22 +816,20 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
|
||||
- (NGMimeMessage *) _generateMessage
|
||||
{
|
||||
NSDictionary *mailProperties;
|
||||
NSString *contentType;
|
||||
NGMimeMessage *message;
|
||||
NGMutableHashMap *headers;
|
||||
id messageBody;
|
||||
|
||||
mailProperties = [sogoObject properties];
|
||||
|
||||
headers = [[NGMutableHashMap alloc] initWithCapacity: 16];
|
||||
FillMessageHeadersFromProperties (headers, mailProperties,
|
||||
FillMessageHeadersFromProperties (headers, properties,
|
||||
[[self context] connectionInfo]);
|
||||
message = [[NGMimeMessage alloc] initWithHeader: headers];
|
||||
[message autorelease];
|
||||
[headers release];
|
||||
|
||||
messageBody = MakeMessageBody (mailProperties, attachmentParts, &contentType);
|
||||
messageBody = MakeMessageBody (properties, &contentType);
|
||||
// messageBody = MakeMessageBody (mailProperties, attachmentParts, &contentType);
|
||||
if (messageBody)
|
||||
{
|
||||
[headers setObject: contentType forKey: @"content-type"];
|
||||
|
@ -775,7 +882,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
|
||||
- (int) submitWithFlags: (enum SubmitFlags) flags
|
||||
{
|
||||
NSDictionary *mailProperties, *recipients;
|
||||
NSDictionary *recipients;
|
||||
NSData *messageData;
|
||||
NSMutableArray *recipientEmails;
|
||||
NSArray *list;
|
||||
|
@ -785,19 +892,17 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
// SOGoMailFolder *sentFolder;
|
||||
SOGoDomainDefaults *dd;
|
||||
NSException *error;
|
||||
MAPIStoreMapping *mapping;
|
||||
// MAPIStoreMapping *mapping;
|
||||
|
||||
mailProperties = [sogoObject properties];
|
||||
msgClass = [mailProperties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
|
||||
msgClass = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
|
||||
if ([msgClass isEqualToString: @"IPM.Note"]) /* we skip invitation replies */
|
||||
{
|
||||
/* send mail */
|
||||
|
||||
messageData = [self _generateMailDataWithBcc: NO];
|
||||
|
||||
mailProperties = [sogoObject properties];
|
||||
recipientEmails = [NSMutableArray arrayWithCapacity: 32];
|
||||
recipients = [mailProperties objectForKey: @"recipients"];
|
||||
recipients = [properties objectForKey: @"recipients"];
|
||||
for (count = 0; count < 3; count++)
|
||||
{
|
||||
recId = recTypes[count];
|
||||
|
@ -819,11 +924,11 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
if (error)
|
||||
[self logWithFormat: @"an error occurred: '%@'", error];
|
||||
|
||||
mapping = [self mapping];
|
||||
[mapping unregisterURLWithID: [self objectId]];
|
||||
[self setIsNew: NO];
|
||||
[properties removeAllObjects];
|
||||
[[self container] cleanupCaches];
|
||||
// mapping = [self mapping];
|
||||
// [mapping unregisterURLWithID: [self objectId]];
|
||||
// [self setIsNew: NO];
|
||||
// [properties removeAllObjects];
|
||||
[(MAPIStoreMailFolder *) [self container] cleanupCaches];
|
||||
}
|
||||
else
|
||||
[self logWithFormat: @"skipping submit of message with class '%@'",
|
||||
|
@ -834,14 +939,14 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
|
||||
- (void) save
|
||||
{
|
||||
NSString *folderName, *flag, *newIdString;
|
||||
NSString *folderName, *flag, *newIdString, *messageKey;
|
||||
NSData *changeKey, *messageData;
|
||||
NGImap4Connection *connection;
|
||||
NGImap4Client *client;
|
||||
SOGoMailFolder *containerFolder;
|
||||
NSDictionary *result, *responseResult;
|
||||
MAPIStoreMapping *mapping;
|
||||
uint64_t mid;
|
||||
// MAPIStoreMapping *mapping;
|
||||
// uint64_t mid;
|
||||
|
||||
messageData = [self _generateMailDataWithBcc: YES];
|
||||
|
||||
|
@ -860,21 +965,24 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
|||
flag = [responseResult objectForKey: @"flag"];
|
||||
newIdString = [[flag componentsSeparatedByString: @" "]
|
||||
objectAtIndex: 2];
|
||||
mid = [self objectId];
|
||||
mapping = [self mapping];
|
||||
[mapping unregisterURLWithID: mid];
|
||||
[sogoObject setNameInContainer: [NSString stringWithFormat: @"%@.eml", newIdString]];
|
||||
[mapping registerURL: [self url] withID: mid];
|
||||
}
|
||||
// mid = [self objectId];
|
||||
// mapping = [self mapping];
|
||||
// [mapping unregisterURLWithID: mid];
|
||||
// [sogoObject setNameInContainer: ];
|
||||
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
|
||||
the client */
|
||||
/* synchronise the cache and update the change key with the one provided
|
||||
by the client */
|
||||
[(MAPIStoreMailFolder *) container synchroniseCache];
|
||||
changeKey = [[sogoObject properties]
|
||||
objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
|
||||
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
|
||||
if (changeKey)
|
||||
[(MAPIStoreMailFolder *) container
|
||||
setChangeKey: changeKey forMessageWithKey: [self nameInContainer]];
|
||||
setChangeKey: changeKey
|
||||
forMessageWithKey: messageKey];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
@class MAPIStoreAttachmentTable;
|
||||
@class MAPIStoreFolder;
|
||||
|
||||
#import "MAPIStoreObject.h"
|
||||
#import "MAPIStoreSOGoObject.h"
|
||||
|
||||
@interface MAPIStoreMessage : MAPIStoreObject
|
||||
@interface MAPIStoreMessage : MAPIStoreSOGoObject
|
||||
{
|
||||
NSArray *attachmentKeys;
|
||||
NSMutableDictionary *attachmentParts;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#import "MAPIStoreAttachmentTable.h"
|
||||
#import "MAPIStoreContext.h"
|
||||
#import "MAPIStoreFolder.h"
|
||||
#import "MAPIStoreMessageTable.h"
|
||||
#import "MAPIStorePropertySelectors.h"
|
||||
#import "MAPIStoreSamDBUtils.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
|
@ -116,7 +117,6 @@ rtf2html (NSData *compressedRTF)
|
|||
|
||||
@interface SOGoObject (MAPIStoreProtocol)
|
||||
|
||||
- (NSString *) davEntityTag;
|
||||
- (NSString *) davContentLength;
|
||||
|
||||
@end
|
||||
|
@ -304,6 +304,7 @@ rtf2html (NSData *compressedRTF)
|
|||
NSData *htmlData, *rtfData;
|
||||
static NSNumber *htmlKey = nil, *rtfKey = nil;
|
||||
|
||||
/* we intercept any RTF content and convert it to HTML */
|
||||
[super addProperties: newNewProperties];
|
||||
|
||||
if (!htmlKey)
|
||||
|
@ -339,10 +340,8 @@ rtf2html (NSData *compressedRTF)
|
|||
|
||||
newAid = [[self attachmentKeys] count];
|
||||
|
||||
newAttachment = [MAPIStoreAttachment
|
||||
mapiStoreObjectWithSOGoObject: nil
|
||||
inContainer: self];
|
||||
[newAttachment setIsNew: YES];
|
||||
newAttachment = [MAPIStoreAttachment mapiStoreObjectInContainer: self];
|
||||
// [newAttachment setIsNew: YES];
|
||||
[newAttachment setAID: newAid];
|
||||
newKey = [NSString stringWithFormat: @"%ul", newAid];
|
||||
[attachmentParts setObject: newAttachment
|
||||
|
@ -497,7 +496,6 @@ rtf2html (NSData *compressedRTF)
|
|||
[[containerTables objectAtIndex: count]
|
||||
notifyChangesForChild: self];
|
||||
[self setIsNew: NO];
|
||||
[properties removeAllObjects];
|
||||
[container cleanupCaches];
|
||||
rc = MAPISTORE_SUCCESS;
|
||||
}
|
||||
|
@ -792,7 +790,7 @@ rtf2html (NSData *compressedRTF)
|
|||
- (int) getPidTagOriginalMessageClass: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
return [self getPidTagMessageClass: data inMemCtx: memCtx];
|
||||
return [self getProperty: data withTag: PidTagMessageClass inMemCtx: memCtx];
|
||||
}
|
||||
|
||||
- (int) getPidTagHasAttachments: (void **) data
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
@interface MAPIStoreMessageTable : MAPIStoreTable
|
||||
|
||||
- (void) setSortOrder: (const struct SSortOrderSet *) set;
|
||||
- (void) notifyChangesForChild: (MAPIStoreMessage *) child;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#import <SOGo/SOGoFolder.h>
|
||||
#import <SOGo/SOGoObject.h>
|
||||
|
||||
#import "MAPIStoreContext.h"
|
||||
#import "MAPIStoreFolder.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
#import "NSData+MAPIStore.h"
|
||||
|
@ -83,4 +84,60 @@
|
|||
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,
|
||||
¬if_parameters);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newChildRow == NSNotFound)
|
||||
mapistore_push_notification (mstoreCtx,
|
||||
MAPISTORE_TABLE,
|
||||
MAPISTORE_OBJECT_DELETED,
|
||||
¬if_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,
|
||||
¬if_parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef MAPISTORENOTESCONTEXT_H
|
||||
#define MAPISTORENOTESCONTEXT_H
|
||||
|
||||
#import "MAPIStoreFSBaseContext.h"
|
||||
#import "MAPIStoreDBBaseContext.h"
|
||||
|
||||
@interface MAPIStoreNotesContext : MAPIStoreFSBaseContext
|
||||
@interface MAPIStoreNotesContext : MAPIStoreDBBaseContext
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef MAPISTORENOTESFOLDER_H
|
||||
#define MAPISTORENOTESFOLDER_H
|
||||
|
||||
#import "MAPIStoreFSFolder.h"
|
||||
#import "MAPIStoreDBFolder.h"
|
||||
|
||||
@interface MAPIStoreNotesFolder : MAPIStoreFSFolder
|
||||
@interface MAPIStoreNotesFolder : MAPIStoreDBFolder
|
||||
@end
|
||||
|
||||
#endif /* MAPISTORENOTESFOLDER_H */
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#ifndef MAPISTORENOTESMESSAGE_H
|
||||
#define MAPISTORENOTESMESSAGE_H
|
||||
|
||||
#import "MAPIStoreFSMessage.h"
|
||||
#import "MAPIStoreDBMessage.h"
|
||||
|
||||
@interface MAPIStoreNotesMessage : MAPIStoreFSMessage
|
||||
@interface MAPIStoreNotesMessage : MAPIStoreDBMessage
|
||||
@end
|
||||
|
||||
#endif /* MAPISTORENOTESMESSAGE_H */
|
||||
|
|
|
@ -53,21 +53,4 @@
|
|||
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
|
||||
|
|
|
@ -33,56 +33,38 @@
|
|||
@class NSMutableArray;
|
||||
@class NSMutableDictionary;
|
||||
|
||||
@class EOQualifier;
|
||||
|
||||
@class MAPIStoreContext;
|
||||
@class MAPIStoreFolder;
|
||||
@class MAPIStoreMapping;
|
||||
@class MAPIStoreTable;
|
||||
@class MAPIStoreUserContext;
|
||||
@class MAPIStoreSOGoObject;
|
||||
|
||||
@interface MAPIStoreObject : NSObject
|
||||
{
|
||||
const IMP *classGetters;
|
||||
|
||||
NSMutableArray *parentContainersBag;
|
||||
MAPIStoreObject *container;
|
||||
id sogoObject;
|
||||
id container;
|
||||
NSMutableDictionary *properties;
|
||||
BOOL isNew;
|
||||
}
|
||||
|
||||
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
|
||||
inContainer: (MAPIStoreObject *) newContainer;
|
||||
+ (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer;
|
||||
- (id) initInContainer: (MAPIStoreObject *) newContainer;
|
||||
|
||||
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
||||
- (id) initWithSOGoObject: (id) newSOGoObject
|
||||
inContainer: (MAPIStoreObject *) newFolder;
|
||||
|
||||
- (void) setIsNew: (BOOL) newIsNew;
|
||||
- (BOOL) isNew;
|
||||
|
||||
- (NSString *) nameInContainer;
|
||||
|
||||
- (id) sogoObject;
|
||||
- (MAPIStoreObject *) container;
|
||||
|
||||
- (MAPIStoreContext *) context;
|
||||
- (MAPIStoreUserContext *) userContext;
|
||||
- (MAPIStoreMapping *) mapping;
|
||||
|
||||
- (void) cleanupCaches;
|
||||
|
||||
- (uint64_t) objectId;
|
||||
- (NSString *) url;
|
||||
|
||||
/* properties */
|
||||
|
||||
- (BOOL) canGetProperty: (enum MAPITAGS) propTag;
|
||||
|
||||
- (void) addProperties: (NSDictionary *) newProperties;
|
||||
- (NSDictionary *) properties;
|
||||
- (NSMutableDictionary *) properties;
|
||||
|
||||
/* ops */
|
||||
- (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||
|
@ -104,26 +86,12 @@
|
|||
fromGlobCnt: (uint64_t) objectCnt
|
||||
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
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
- (int) getPidTagLastModificationTime: (void **) data
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
||||
/* subclasses */
|
||||
- (uint64_t) objectVersion;
|
||||
- (NSDate *) creationTime;
|
||||
- (NSDate *) lastModificationTime;
|
||||
|
||||
|
|
|
@ -58,13 +58,11 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
|||
MAPIStoreFolderK = [MAPIStoreFolder class];
|
||||
}
|
||||
|
||||
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
|
||||
inContainer: (MAPIStoreObject *) newContainer
|
||||
+ (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer
|
||||
{
|
||||
id newObject;
|
||||
|
||||
newObject = [[self alloc] initWithSOGoObject: newSOGoObject
|
||||
inContainer: newContainer];
|
||||
newObject = [[self alloc] initInContainer: newContainer];
|
||||
[newObject autorelease];
|
||||
|
||||
return newObject;
|
||||
|
@ -106,22 +104,18 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
|||
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
|
||||
parentContainersBag = [NSMutableArray new];
|
||||
container = nil;
|
||||
sogoObject = nil;
|
||||
properties = [NSMutableDictionary new];
|
||||
isNew = NO;
|
||||
}
|
||||
|
||||
[self logWithFormat: @"-init"];
|
||||
// [self logWithFormat: @"-init"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithSOGoObject: (id) newSOGoObject
|
||||
inContainer: (MAPIStoreObject *) newContainer
|
||||
- (id) initInContainer: (MAPIStoreObject *) newContainer
|
||||
{
|
||||
if ((self = [self init]))
|
||||
{
|
||||
ASSIGN (sogoObject, newSOGoObject);
|
||||
ASSIGN (container, newContainer);
|
||||
}
|
||||
|
||||
|
@ -130,42 +124,21 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self logWithFormat: @"-dealloc"];
|
||||
[sogoObject release];
|
||||
// [self logWithFormat: @"-dealloc"];
|
||||
[properties release];
|
||||
[parentContainersBag release];
|
||||
[container 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];
|
||||
}
|
||||
|
||||
- (MAPIStoreContext *) context
|
||||
{
|
||||
return [container context];
|
||||
return (MAPIStoreContext *) [container context];
|
||||
}
|
||||
|
||||
- (MAPIStoreUserContext *) userContext
|
||||
|
@ -178,47 +151,14 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
|||
return [[self userContext] mapping];
|
||||
}
|
||||
|
||||
- (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 = [container url];
|
||||
if ([containerURL hasSuffix: @"/"])
|
||||
format = @"%@%@";
|
||||
else
|
||||
format = @"%@/%@";
|
||||
|
||||
return [NSString stringWithFormat: format,
|
||||
containerURL, [self nameInContainer]];
|
||||
}
|
||||
|
||||
- (void) addProperties: (NSDictionary *) newNewProperties
|
||||
{
|
||||
[properties addEntriesFromDictionary: newNewProperties];
|
||||
}
|
||||
|
||||
- (NSDictionary *) properties
|
||||
- (NSMutableDictionary *) properties
|
||||
{
|
||||
return properties;
|
||||
}
|
||||
|
@ -248,122 +188,6 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
|||
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
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
|
@ -474,6 +298,38 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
|||
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 */
|
||||
- (NSDate *) creationTime
|
||||
{
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
andMemberId: (uint64_t) newMemberId
|
||||
forFolder: (MAPIStoreFolder *) newFolder
|
||||
{
|
||||
if ((self = [self initWithSOGoObject: nil inContainer: newFolder]))
|
||||
if ((self = [self initInContainer: newFolder]))
|
||||
{
|
||||
ASSIGN (userId, newUserId);
|
||||
memberId = newMemberId;
|
||||
|
|
|
@ -23,10 +23,14 @@
|
|||
#ifndef MAPISTORERECURRENCEUTILS_H
|
||||
#define MAPISTORERECURRENCEUTILS_H
|
||||
|
||||
#include <talloc.h>
|
||||
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
|
||||
@class NSCalendarDate;
|
||||
@class NSTimeZone;
|
||||
|
||||
@class iCalEvent;
|
||||
@class iCalRepeatableEntityObject;
|
||||
@class iCalRecurrenceRule;
|
||||
|
||||
|
@ -44,8 +48,9 @@
|
|||
@interface iCalRecurrenceRule (MAPIStoreRecurrence)
|
||||
|
||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||
withStartDate: (NSCalendarDate *) startDate
|
||||
andEndDate: (NSCalendarDate *) endDate;
|
||||
withEvent: (iCalEvent *) event
|
||||
inTimeZone: (NSTimeZone *) timeZone
|
||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -21,17 +21,22 @@
|
|||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGExtensions/NSCalendarDate+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import <NGCards/iCalByDayMask.h>
|
||||
#import <NGCards/iCalDateTime.h>
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalRepeatableEntityObject.h>
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
#import <NGCards/iCalByDayMask.h>
|
||||
#import <NGCards/iCalTimeZone.h>
|
||||
|
||||
#import "NSDate+MAPIStore.h"
|
||||
#import "MAPIStoreRecurrenceUtils.h"
|
||||
#import "MAPIStoreTypes.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <talloc.h>
|
||||
|
@ -43,7 +48,7 @@
|
|||
- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity
|
||||
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
||||
{
|
||||
NSCalendarDate *startDate, *olEndDate, *untilDate;
|
||||
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
|
||||
NSString *monthDay, *month;
|
||||
iCalRecurrenceRule *rule;
|
||||
iCalByDayMask *byDayMask;
|
||||
|
@ -203,6 +208,17 @@
|
|||
[self errorWithFormat: @"invalid value for EndType: %.4x",
|
||||
rp->EndType];
|
||||
}
|
||||
|
||||
/* exception dates */
|
||||
for (count = 0; count < rp->DeletedInstanceCount; count++)
|
||||
{
|
||||
exDate
|
||||
= [NSDate dateFromMinutesSince1601: rp->DeletedInstanceDates[count]];
|
||||
exDate = [exDate hour: [startDate hourOfDay]
|
||||
minute: [startDate minuteOfHour]
|
||||
second: [startDate secondOfMinute]];
|
||||
[entity addToExceptionDates: exDate];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -210,16 +226,23 @@
|
|||
@implementation iCalRecurrenceRule (MAPIStoreRecurrence)
|
||||
|
||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||
withStartDate: (NSCalendarDate *) startDate
|
||||
andEndDate: (NSCalendarDate *) endDate
|
||||
withEvent: (iCalEvent *) event
|
||||
inTimeZone: (NSTimeZone *) timeZone
|
||||
inMemCtx: (TALLOC_CTX *) memCtx
|
||||
{
|
||||
iCalRecurrenceFrequency freq;
|
||||
iCalByDayMask *byDayMask;
|
||||
NSString *byMonthDay, *bySetPos;
|
||||
NSCalendarDate *untilDate, *beginOfWeek, *minimumDate, *moduloDate, *midnight;
|
||||
NSCalendarDate *startDate, *endDate, *untilDate, *beginOfWeek, *minimumDate, *moduloDate, *midnight;
|
||||
iCalWeekOccurrences *days;
|
||||
NSInteger dayOfWeek, repeatInterval, repeatCount, count, firstOccurrence;
|
||||
NSInteger dayOfWeek, repeatInterval, repeatCount, count, firstOccurrence, max;
|
||||
uint32_t nbrMonths, mask;
|
||||
NSArray *exDates;
|
||||
|
||||
startDate = [event firstRecurrenceStartDate];
|
||||
[startDate setTimeZone: timeZone];
|
||||
endDate = [event lastPossibleRecurrenceStartDate];
|
||||
[endDate setTimeZone: timeZone];
|
||||
|
||||
rp->ReaderVersion = 0x3004;
|
||||
rp->WriterVersion = 0x3004;
|
||||
|
@ -370,6 +393,19 @@
|
|||
[self errorWithFormat: @"rule for an event that never occurs"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exDates = [[event exceptionDatesWithTimeZone: utcTZ]
|
||||
sortedArrayUsingFunction: NSDateCompare
|
||||
context: NULL];
|
||||
max = [exDates count];
|
||||
rp->DeletedInstanceCount = max;
|
||||
rp->DeletedInstanceDates = talloc_array (memCtx, uint32_t, max);
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
startDate = [[exDates objectAtIndex: count] hour: 0 minute: 0 second: 0];
|
||||
*(rp->DeletedInstanceDates + count) = [startDate asMinutesSince1601];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -273,7 +273,7 @@ sogo_context_get_path(void *backend_object, TALLOC_CTX *mem_ctx,
|
|||
if (backend_object)
|
||||
{
|
||||
wrapper = backend_object;
|
||||
context = wrapper->MAPIStoreSOGoObject;
|
||||
context = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx];
|
||||
|
@ -303,7 +303,7 @@ sogo_context_get_root_folder(void *backend_object, TALLOC_CTX *mem_ctx,
|
|||
if (backend_object)
|
||||
{
|
||||
wrapper = backend_object;
|
||||
context = wrapper->MAPIStoreSOGoObject;
|
||||
context = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [context getRootFolder: &folder withFID: fid];
|
||||
|
@ -342,7 +342,7 @@ sogo_folder_open_folder(void *folder_object, TALLOC_CTX *mem_ctx, uint64_t fid,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder openFolder: &childFolder withFID: fid];
|
||||
|
@ -382,7 +382,7 @@ sogo_folder_create_folder(void *folder_object, TALLOC_CTX *mem_ctx,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder createFolder: &childFolder withRow: aRow andFID: fid];
|
||||
|
@ -421,7 +421,7 @@ sogo_folder_delete(void *folder_object)
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder deleteFolder];
|
||||
|
@ -449,7 +449,7 @@ sogo_folder_get_child_count(void *folder_object, enum mapistore_table_type table
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder getChildCount: child_count ofTableType: table_type];
|
||||
|
@ -481,7 +481,7 @@ sogo_folder_open_message(void *folder_object,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder openMessage: &message
|
||||
|
@ -519,7 +519,7 @@ sogo_folder_create_message(void *folder_object,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder createMessage: &message
|
||||
|
@ -551,7 +551,7 @@ sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags)
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder deleteMessageWithMID: mid andFlags: flags];
|
||||
|
@ -584,10 +584,10 @@ sogo_folder_move_copy_messages(void *folder_object,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
targetFolder = wrapper->MAPIStoreSOGoObject;
|
||||
targetFolder = wrapper->instance;
|
||||
|
||||
wrapper = source_folder_object;
|
||||
sourceFolder = wrapper->MAPIStoreSOGoObject;
|
||||
sourceFolder = wrapper->instance;
|
||||
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
@ -623,7 +623,7 @@ sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder getDeletedFMIDs: fmidsp
|
||||
|
@ -658,7 +658,7 @@ sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder getTable: &table
|
||||
|
@ -693,7 +693,7 @@ sogo_folder_modify_permissions(void *folder_object, uint8_t flags,
|
|||
if (folder_object)
|
||||
{
|
||||
wrapper = folder_object;
|
||||
folder = wrapper->MAPIStoreSOGoObject;
|
||||
folder = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [folder modifyPermissions: permissions
|
||||
|
@ -725,7 +725,7 @@ sogo_message_get_message_data(void *message_object,
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
[message getMessageData: msg_dataP
|
||||
|
@ -756,7 +756,7 @@ sogo_message_create_attachment (void *message_object, TALLOC_CTX *mem_ctx, void
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message createAttachment: &attachment inAID: aidp];
|
||||
|
@ -789,7 +789,7 @@ sogo_message_open_attachment (void *message_object, TALLOC_CTX *mem_ctx,
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message getAttachment: &attachment withAID: aid];
|
||||
|
@ -821,7 +821,7 @@ sogo_message_get_attachment_table (void *message_object, TALLOC_CTX *mem_ctx, vo
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message getAttachmentTable: &table
|
||||
|
@ -856,7 +856,7 @@ sogo_message_modify_recipients (void *message_object,
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message modifyRecipientsWithRecipients: recipients
|
||||
|
@ -887,7 +887,7 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message setReadFlag: flag];
|
||||
|
@ -916,7 +916,7 @@ sogo_message_save (void *message_object)
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message saveMessage];
|
||||
|
@ -945,7 +945,7 @@ sogo_message_submit (void *message_object, enum SubmitFlags flags)
|
|||
if (message_object)
|
||||
{
|
||||
wrapper = message_object;
|
||||
message = wrapper->MAPIStoreSOGoObject;
|
||||
message = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [message submitWithFlags: flags];
|
||||
|
@ -963,9 +963,8 @@ sogo_message_submit (void *message_object, enum SubmitFlags flags)
|
|||
|
||||
static enum mapistore_error
|
||||
sogo_message_attachment_open_embedded_message
|
||||
(void *attachment_object,
|
||||
TALLOC_CTX *mem_ctx, void **message_object,
|
||||
uint64_t *midP,
|
||||
(void *attachment_object, enum OpenEmbeddedMessage_OpenModeFlags mode,
|
||||
TALLOC_CTX *mem_ctx, void **message_object, uint64_t *midP,
|
||||
struct mapistore_message **msg)
|
||||
{
|
||||
struct MAPIStoreTallocWrapper *wrapper;
|
||||
|
@ -979,10 +978,11 @@ sogo_message_attachment_open_embedded_message
|
|||
if (attachment_object)
|
||||
{
|
||||
wrapper = attachment_object;
|
||||
attachment = wrapper->MAPIStoreSOGoObject;
|
||||
attachment = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [attachment openEmbeddedMessage: &message
|
||||
inMode: mode
|
||||
withMID: midP
|
||||
withMAPIStoreMsg: msg
|
||||
inMemCtx: mem_ctx];
|
||||
|
@ -1012,7 +1012,7 @@ static enum mapistore_error sogo_table_get_available_properties(void *table_obje
|
|||
if (table_object)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->MAPIStoreSOGoObject;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
||||
|
@ -1040,7 +1040,7 @@ sogo_table_set_columns (void *table_object, uint16_t count, enum MAPITAGS *prope
|
|||
if (table_object)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->MAPIStoreSOGoObject;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [table setColumns: properties
|
||||
|
@ -1069,7 +1069,7 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr
|
|||
if (table_object)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->MAPIStoreSOGoObject;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
[table setRestrictions: restrictions];
|
||||
|
@ -1100,7 +1100,7 @@ sogo_table_set_sort_order (void *table_object, struct SSortOrderSet *sort_order,
|
|||
if (table_object)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->MAPIStoreSOGoObject;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
[table setSortOrder: sort_order];
|
||||
|
@ -1133,7 +1133,7 @@ sogo_table_get_row (void *table_object, TALLOC_CTX *mem_ctx,
|
|||
if (table_object)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->MAPIStoreSOGoObject;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [table getRow: data withRowID: row_id andQueryType: query_type
|
||||
|
@ -1164,7 +1164,7 @@ sogo_table_get_row_count (void *table_object,
|
|||
if (table_object)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->MAPIStoreSOGoObject;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [table getRowCount: row_countp
|
||||
|
@ -1193,7 +1193,7 @@ sogo_table_handle_destructor (void *table_object, uint32_t handle_id)
|
|||
if (table_object)
|
||||
{
|
||||
wrapper = table_object;
|
||||
table = wrapper->MAPIStoreSOGoObject;
|
||||
table = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
[table destroyHandle: handle_id];
|
||||
|
@ -1223,7 +1223,7 @@ static enum mapistore_error sogo_properties_get_available_properties(void *objec
|
|||
if (object)
|
||||
{
|
||||
wrapper = object;
|
||||
propObject = wrapper->MAPIStoreSOGoObject;
|
||||
propObject = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
||||
|
@ -1254,7 +1254,7 @@ sogo_properties_get_properties (void *object,
|
|||
if (object)
|
||||
{
|
||||
wrapper = object;
|
||||
propObject = wrapper->MAPIStoreSOGoObject;
|
||||
propObject = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [propObject getProperties: data withTags: properties
|
||||
|
@ -1284,7 +1284,7 @@ sogo_properties_set_properties (void *object, struct SRow *aRow)
|
|||
if (object)
|
||||
{
|
||||
wrapper = object;
|
||||
propObject = wrapper->MAPIStoreSOGoObject;
|
||||
propObject = wrapper->instance;
|
||||
GSRegisterCurrentThread ();
|
||||
pool = [NSAutoreleasePool new];
|
||||
rc = [propObject addPropertiesFromRow: aRow];
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -100,8 +100,6 @@ typedef enum {
|
|||
- (int) getRowCount: (uint32_t *) countP
|
||||
withQueryType: (enum mapistore_query_type) queryType;
|
||||
|
||||
- (void) notifyChangesForChild: (MAPIStoreObject *) child;
|
||||
|
||||
/* helpers */
|
||||
|
||||
- (SEL) operatorFromRestrictionOperator: (uint32_t) resOp;
|
||||
|
|
|
@ -874,61 +874,6 @@ static Class NSDataK, NSStringK;
|
|||
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,
|
||||
¬if_parameters);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newChildRow == NSNotFound)
|
||||
mapistore_push_notification (mstoreCtx,
|
||||
MAPISTORE_TABLE,
|
||||
MAPISTORE_OBJECT_DELETED,
|
||||
¬if_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,
|
||||
¬if_parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* subclasses */
|
||||
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
||||
{
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
@class NSMutableDictionary;
|
||||
@class NSString;
|
||||
@class NSTimeZone;
|
||||
@class NSURL;
|
||||
|
||||
@class WOContext;
|
||||
|
||||
|
@ -52,6 +53,9 @@
|
|||
|
||||
MAPIStoreMapping *mapping;
|
||||
|
||||
BOOL userDbTableExists;
|
||||
NSURL *folderTableURL;
|
||||
|
||||
WOContext *woContext;
|
||||
MAPIStoreAuthenticator *authenticator;
|
||||
}
|
||||
|
@ -71,8 +75,11 @@
|
|||
|
||||
- (NSDictionary *) rootFolders;
|
||||
|
||||
- (NSURL *) folderTableURL;
|
||||
- (MAPIStoreMapping *) mapping;
|
||||
|
||||
- (void) ensureFolderTableExists;
|
||||
|
||||
/* SOGo hacky magic */
|
||||
- (void) activateWithUser: (SOGoUser *) activeUser;
|
||||
- (MAPIStoreAuthenticator *) authenticator;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* 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)
|
||||
* 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,
|
||||
|
@ -23,17 +23,21 @@
|
|||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSMapTable.h>
|
||||
#import <Foundation/NSThread.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
|
||||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||
|
||||
#import <NGImap4/NGImap4Connection.h>
|
||||
|
||||
#import <GDLContentStore/GCSChannelManager.h>
|
||||
#import <SOGo/SOGoDomainDefaults.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserFolder.h>
|
||||
#import <Mailer/SOGoMailAccount.h>
|
||||
#import <Mailer/SOGoMailAccounts.h>
|
||||
|
||||
#import "GCSSpecialQueries+OpenChange.h"
|
||||
#import "MAPIApplication.h"
|
||||
#import "MAPIStoreAuthenticator.h"
|
||||
#import "MAPIStoreMapping.h"
|
||||
|
@ -80,6 +84,9 @@ static NSMapTable *contextsTable = nil;
|
|||
|
||||
mapping = nil;
|
||||
|
||||
userDbTableExists = NO;
|
||||
folderTableURL = nil;
|
||||
|
||||
authenticator = nil;
|
||||
woContext = [WOContext contextWithRequest: nil];
|
||||
[woContext retain];
|
||||
|
@ -117,6 +124,8 @@ static NSMapTable *contextsTable = nil;
|
|||
[authenticator release];
|
||||
[mapping release];
|
||||
|
||||
[folderTableURL release];
|
||||
|
||||
[sogoUser release];
|
||||
|
||||
[contextsTable removeObjectForKey: username];
|
||||
|
@ -213,6 +222,72 @@ static NSMapTable *contextsTable = nil;
|
|||
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
|
||||
{
|
||||
return woContext;
|
||||
|
|
|
@ -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
|
|
@ -25,9 +25,11 @@
|
|||
|
||||
#import <Foundation/NSDate.h>
|
||||
|
||||
@class NSCalendarDate;
|
||||
|
||||
@interface NSDate (MAPIStoreDataTypes)
|
||||
|
||||
+ (id) dateFromMinutesSince1601: (uint32_t) minutes;
|
||||
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes;
|
||||
- (uint32_t) asMinutesSince1601;
|
||||
|
||||
+ (id) dateFromFileTime: (const struct FILETIME *) timeValue;
|
||||
|
@ -37,4 +39,6 @@
|
|||
|
||||
@end
|
||||
|
||||
NSComparisonResult NSDateCompare (id date1, id date2, void *);
|
||||
|
||||
#endif /* NSCALENDARDATE+MAPISTORE_H */
|
||||
|
|
|
@ -51,7 +51,7 @@ _setupRefDate ()
|
|||
timeZone: [NSTimeZone timeZoneWithName: @"UTC"]];
|
||||
}
|
||||
|
||||
+ (id) dateFromMinutesSince1601: (uint32_t) minutes
|
||||
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes
|
||||
{
|
||||
NSCalendarDate *result;
|
||||
|
||||
|
@ -129,3 +129,22 @@ _setupRefDate ()
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
NSComparisonResult
|
||||
NSDateCompare (id date1, id date2, void *ctx)
|
||||
{
|
||||
NSTimeInterval secs1, secs2;
|
||||
NSComparisonResult result;
|
||||
|
||||
secs1 = [date1 timeIntervalSince1970];
|
||||
secs2 = [date2 timeIntervalSince1970];
|
||||
if (secs1 == secs2)
|
||||
result = NSOrderedSame;
|
||||
else if (secs1 < secs2)
|
||||
result = NSOrderedAscending;
|
||||
else
|
||||
result = NSOrderedDescending;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
struct MAPIStoreTallocWrapper
|
||||
{
|
||||
id MAPIStoreSOGoObject;
|
||||
id instance;
|
||||
};
|
||||
|
||||
@interface NSObject (MAPIStoreTallocHelpers)
|
||||
|
|
|
@ -50,7 +50,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
|||
pool = [NSAutoreleasePool new];
|
||||
wrapper = data;
|
||||
// NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject);
|
||||
[wrapper->MAPIStoreSOGoObject release];
|
||||
[wrapper->instance release];
|
||||
[pool release];
|
||||
GSUnregisterCurrentThread ();
|
||||
|
||||
|
@ -63,7 +63,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
|||
|
||||
wrapper = talloc_zero (tallocCtx, struct MAPIStoreTallocWrapper);
|
||||
talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy);
|
||||
wrapper->MAPIStoreSOGoObject = self;
|
||||
wrapper->instance = self;
|
||||
[self retain];
|
||||
// NSLog (@"returning wrapper: %p; object: %p", wrapper, self);
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
|
@ -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>
|
||||
*
|
||||
|
@ -20,41 +20,38 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef SOGOMAPIFSFOLDER_H
|
||||
#define SOGOMAPIFSFOLDER_H
|
||||
#ifndef SOGOMAPIDBFOLDER_H
|
||||
#define SOGOMAPIDBFOLDER_H
|
||||
|
||||
#import <SOGo/SOGoFolder.h>
|
||||
#import "SOGoMAPIDBObject.h"
|
||||
|
||||
@class NSArray;
|
||||
@class NSMutableString;
|
||||
@class NSString;
|
||||
@class NSURL;
|
||||
|
||||
@class EOQualifier;
|
||||
|
||||
@class SOGoMAPIFSMessage;
|
||||
@class SOGoMAPIDBMessage;
|
||||
|
||||
@interface SOGoMAPIFSFolder : SOGoFolder
|
||||
@interface SOGoMAPIDBFolder : SOGoMAPIDBObject
|
||||
{
|
||||
NSString *directory;
|
||||
BOOL directoryIsSane;
|
||||
NSString *pathPrefix; /* for root folders */
|
||||
SOGoMAPIDBObject *aclMessage;
|
||||
}
|
||||
|
||||
+ (id) folderWithURL: (NSURL *) url
|
||||
andTableType: (uint8_t) tableType;
|
||||
- (id) initWithURL: (NSURL *) url
|
||||
andTableType: (uint8_t) tableType;
|
||||
- (void) setPathPrefix: (NSString *) newPathPrefix;
|
||||
|
||||
- (NSString *) directory;
|
||||
- (NSMutableString *) pathForChild: (NSString *) childName;
|
||||
|
||||
- (SOGoMAPIFSMessage *) newMessage;
|
||||
- (void) ensureDirectory;
|
||||
- (NSArray *) toOneRelationshipKeys;
|
||||
- (NSArray *) toManyRelationshipKeys;
|
||||
|
||||
- (NSCalendarDate *) creationTime;
|
||||
- (NSCalendarDate *) lastModificationTime;
|
||||
|
||||
- (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
|
||||
- (NSArray *) childKeysOfType: (MAPIDBObjectType) type
|
||||
includeDeleted: (BOOL) includeDeleted
|
||||
matchingQualifier: (EOQualifier *) qualifier
|
||||
andSortOrderings: (NSArray *) sortOrderings;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOMAPIFSFOLDER_H */
|
||||
#endif /* SOGOMAPIDBFOLDER_H */
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
|||
/* MAPIStoreVolatileMessage.h - this file is part of SOGo
|
||||
/* SOGoMAPIDBMessage.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2011 Inverse inc
|
||||
* Copyright (C) 2012 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
|
@ -20,18 +20,15 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef MAPISTOREVOLATILEMESSAGE_H
|
||||
#define MAPISTOREVOLATILEMESSAGE_H
|
||||
#ifndef SOGOMAPIDBMESSAGE_H
|
||||
#define SOGOMAPIDBMESSAGE_H
|
||||
|
||||
#import "MAPIStoreMessage.h"
|
||||
#import "SOGoMAPIDBObject.h"
|
||||
|
||||
@interface MAPIStoreVolatileMessage : MAPIStoreMessage
|
||||
{
|
||||
BOOL fetchedAttachments;
|
||||
NSDate *creationTime;
|
||||
NSDate *lastModificationTime;
|
||||
}
|
||||
@class NSDate;
|
||||
@class NSString;
|
||||
|
||||
@interface SOGoMAPIDBMessage : SOGoMAPIDBObject
|
||||
@end
|
||||
|
||||
#endif /* MAPISTOREVOLATILEMESSAGE_H */
|
||||
#endif /* SOGOMAPIDBMESSAGE_H */
|
|
@ -0,0 +1,61 @@
|
|||
/* SOGoMAPIDBMessage.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/NSFileManager.h>
|
||||
#import <Foundation/NSException.h>
|
||||
#import <Foundation/NSPropertyList.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import "SOGoMAPIDBFolder.h"
|
||||
|
||||
#import "SOGoMAPIDBMessage.h"
|
||||
|
||||
@implementation SOGoMAPIDBMessage
|
||||
|
||||
- (Class) mapistoreMessageClass
|
||||
{
|
||||
// NSArray *dirMembers;
|
||||
NSString *className;
|
||||
|
||||
[NSException raise: @"whereisthisusedexception"
|
||||
format: @"this exception should be triggered only for tracing"];
|
||||
// /* 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 = @"MAPIStoreDBMessage";
|
||||
|
||||
className = @"nimportequoi";
|
||||
return NSClassFromString (className);
|
||||
}
|
||||
|
||||
@end
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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>
|
||||
*
|
||||
* 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)
|
||||
* 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,
|
||||
|
@ -20,22 +20,30 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef SOGOMAPIVOLATILEMESSAGE_H
|
||||
#define SOGOMAPIVOLATILEMESSAGE_H
|
||||
#ifndef SOGOMAPIOBJECT_H
|
||||
#define SOGOMAPIOBJECT_H
|
||||
|
||||
#import <SOGo/SOGoObject.h>
|
||||
|
||||
@class NSDictionary;
|
||||
@class NSMutableDictionary;
|
||||
|
||||
@interface SOGoMAPIVolatileMessage : SOGoObject
|
||||
@interface SOGoMAPIObject : SOGoObject
|
||||
{
|
||||
BOOL isNew;
|
||||
NSMutableDictionary *properties;
|
||||
NSCalendarDate *creationDate;
|
||||
NSCalendarDate *lastModified;
|
||||
}
|
||||
|
||||
- (void) setIsNew: (BOOL) newIsNew;
|
||||
- (BOOL) isNew;
|
||||
|
||||
- (void) adjustLastModified;
|
||||
|
||||
- (NSMutableDictionary *) properties;
|
||||
- (void) appendProperties: (NSDictionary *) newProperties;
|
||||
- (NSCalendarDate *) creationDate;
|
||||
- (NSCalendarDate *) lastModified;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOMAPIVOLATILEMESSAGE_H */
|
||||
#endif /* SOGOMAPIOBJECT_H */
|
|
@ -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>
|
||||
*
|
||||
|
@ -20,17 +20,19 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import "SOGoMAPIObject.h"
|
||||
|
||||
#import "SOGoMAPIVolatileMessage.h"
|
||||
|
||||
@implementation SOGoMAPIVolatileMessage
|
||||
@implementation SOGoMAPIObject
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
properties = nil;
|
||||
isNew = NO;
|
||||
creationDate = [NSCalendarDate date];
|
||||
[creationDate retain];
|
||||
lastModified = [creationDate copy];
|
||||
properties = [NSMutableDictionary new];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -38,21 +40,45 @@
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
[creationDate release];
|
||||
[lastModified release];
|
||||
[properties release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) setIsNew: (BOOL) newIsNew
|
||||
{
|
||||
isNew = newIsNew;
|
||||
}
|
||||
|
||||
- (BOOL) isNew
|
||||
{
|
||||
return isNew;
|
||||
}
|
||||
|
||||
- (void) adjustLastModified
|
||||
{
|
||||
ASSIGN (lastModified, [NSCalendarDate date]);
|
||||
}
|
||||
|
||||
- (BOOL) isFolderish
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *) properties
|
||||
{
|
||||
if (!properties)
|
||||
properties = [NSMutableDictionary new];
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
- (void) appendProperties: (NSDictionary *) newProperties
|
||||
- (NSCalendarDate *) creationDate
|
||||
{
|
||||
[[self properties] addEntriesFromDictionary: newProperties];
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) lastModified
|
||||
{
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,109 @@
|
|||
/* dbmsgreader.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 readerer.
|
||||
Usage: dbmsgreader [username] [filename] */
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSBundle.h>
|
||||
#import <Foundation/NSAutoreleasePool.h>
|
||||
#import <Foundation/NSProcessInfo.h>
|
||||
#import <Foundation/NSUserDefaults.h>
|
||||
#import <NGExtensions/NGBase64Coding.h>
|
||||
#import <NGObjWeb/SoProductRegistry.h>
|
||||
#import <SOGo/SOGoProductLoader.h>
|
||||
#import <SOGo/SOGoSystemDefaults.h>
|
||||
|
||||
#import "MAPIStoreUserContext.h"
|
||||
#import "SOGoMAPIDBObject.h"
|
||||
|
||||
#import "NSObject+PropertyList.m"
|
||||
|
||||
Class MAPIStoreUserContextK, SOGoMAPIDBObjectK;
|
||||
|
||||
static void
|
||||
DbDumpObject (NSString *username, NSString *path)
|
||||
{
|
||||
id ctx;
|
||||
NSData *content;
|
||||
id dbobject;
|
||||
NSDictionary *record;
|
||||
|
||||
ctx = [MAPIStoreUserContextK userContextWithUsername: username
|
||||
andTDBIndexing: NULL];
|
||||
dbobject = [SOGoMAPIDBObjectK new];
|
||||
[dbobject setTableUrl: [ctx folderTableURL]];
|
||||
record = [dbobject lookupRecord: path newerThanVersion: -1];
|
||||
if (record)
|
||||
{
|
||||
content = [[record objectForKey: @"c_content"] dataByDecodingBase64];
|
||||
OCDumpPListData (content);
|
||||
}
|
||||
else
|
||||
NSLog (@"record not found");
|
||||
|
||||
[dbobject release];
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[], char *envp[])
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
SOGoProductLoader *loader;
|
||||
NSUserDefaults *ud;
|
||||
SoProductRegistry *registry;
|
||||
NSArray *arguments;
|
||||
|
||||
/* Here we work around a bug in GNUstep which decodes XML user
|
||||
defaults using the system encoding rather than honouring
|
||||
the encoding specified in the file. */
|
||||
putenv ("GNUSTEP_STRING_ENCODING=NSUTF8StringEncoding");
|
||||
|
||||
pool = [NSAutoreleasePool new];
|
||||
|
||||
[SOGoSystemDefaults sharedSystemDefaults];
|
||||
|
||||
/* We force the plugin to base its configuration on the SOGo tree. */
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
[ud registerDefaults: [ud persistentDomainForName: @"sogod"]];
|
||||
|
||||
[NSProcessInfo initializeWithArguments: argv
|
||||
count: argc
|
||||
environment: envp];
|
||||
|
||||
registry = [SoProductRegistry sharedProductRegistry];
|
||||
[registry scanForProductsInDirectory: SOGO_BUNDLES_DIR];
|
||||
|
||||
loader = [SOGoProductLoader productLoader];
|
||||
[loader loadProducts: [NSArray arrayWithObject: BACKEND_BUNDLE_NAME]];
|
||||
|
||||
MAPIStoreUserContextK = NSClassFromString (@"MAPIStoreUserContext");
|
||||
SOGoMAPIDBObjectK = NSClassFromString (@"SOGoMAPIDBObject");
|
||||
|
||||
arguments = [[NSProcessInfo processInfo] arguments];
|
||||
if ([arguments count] > 2)
|
||||
DbDumpObject ([arguments objectAtIndex: 1],
|
||||
[arguments objectAtIndex: 2]);
|
||||
|
||||
[pool release];
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -23,164 +23,19 @@
|
|||
/* A format-agnostic property list dumper.
|
||||
Usage: plreader [filename] */
|
||||
|
||||
#import <Foundation/NSAutoreleasePool.h>
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSData.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSAutoreleasePool.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
|
||||
#import "NSObject+PropertyList.m"
|
||||
|
||||
static void
|
||||
PLReaderDumpPListFile (NSString *filename)
|
||||
{
|
||||
NSData *content;
|
||||
NSDictionary *d;
|
||||
NSPropertyListFormat format;
|
||||
NSString *error = nil;
|
||||
const char *formatName;
|
||||
|
||||
content = [NSData dataWithContentsOfFile: filename];
|
||||
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]);
|
||||
OCDumpPListData (content);
|
||||
}
|
||||
|
||||
int main()
|
||||
|
|
|
@ -48,4 +48,15 @@
|
|||
|
||||
@end
|
||||
|
||||
/* interfaces exposed so that categories can be created from them */
|
||||
@interface GCSPostgreSQLSpecialQueries : GCSSpecialQueries
|
||||
@end
|
||||
|
||||
@interface GCSMySQLSpecialQueries : GCSSpecialQueries
|
||||
@end
|
||||
|
||||
@interface GCSOracleSpecialQueries : GCSSpecialQueries
|
||||
@end
|
||||
|
||||
|
||||
#endif /* GCSSPECIALQUERIES_H */
|
||||
|
|
|
@ -27,15 +27,6 @@
|
|||
|
||||
#import "GCSSpecialQueries.h"
|
||||
|
||||
@interface GCSPostgreSQLSpecialQueries : GCSSpecialQueries
|
||||
@end
|
||||
|
||||
@interface GCSMySQLSpecialQueries : GCSSpecialQueries
|
||||
@end
|
||||
|
||||
@interface GCSOracleSpecialQueries : GCSSpecialQueries
|
||||
@end
|
||||
|
||||
@implementation EOAdaptorChannel (GCSSpecialQueries)
|
||||
|
||||
- (GCSSpecialQueries *) specialQueries
|
||||
|
@ -163,7 +154,7 @@
|
|||
{
|
||||
static NSString *sqlFolderFormat
|
||||
= (@"CREATE TABLE %@ (\n"
|
||||
@" c_name VARCHAR (255) NOT NULL PRIMARY KEY,\n"
|
||||
@" c_name VARCHAR (255) PRIMARY KEY,\n"
|
||||
@" c_content TEXT NOT NULL,\n"
|
||||
@" c_creationdate INT4 NOT NULL,\n"
|
||||
@" c_lastmodified INT4 NOT NULL,\n"
|
||||
|
@ -190,7 +181,7 @@
|
|||
{
|
||||
static NSString *sqlFolderFormat
|
||||
= (@"CREATE TABLE %@ ("
|
||||
@" c_id VARCHAR(255) NOT NULL PRIMARY KEY,"
|
||||
@" c_id VARCHAR(255) PRIMARY KEY,"
|
||||
@" c_value VARCHAR(255) NOT NULL,"
|
||||
@" c_creationdate INT4 NOT NULL,"
|
||||
@" c_lastseen INT4 NOT NULL)");
|
||||
|
@ -257,7 +248,7 @@
|
|||
{
|
||||
static NSString *sqlFolderFormat
|
||||
= (@"CREATE TABLE %@ (\n"
|
||||
@" c_name VARCHAR (255) NOT NULL PRIMARY KEY,\n"
|
||||
@" c_name VARCHAR (255) PRIMARY KEY,\n"
|
||||
@" c_content MEDIUMTEXT NOT NULL,\n"
|
||||
@" c_creationdate INT NOT NULL,\n"
|
||||
@" c_lastmodified INT NOT NULL,\n"
|
||||
|
@ -284,7 +275,7 @@
|
|||
{
|
||||
static NSString *sqlFolderFormat
|
||||
= (@"CREATE TABLE %@ ("
|
||||
@" c_id VARCHAR(255) NOT NULL PRIMARY KEY,"
|
||||
@" c_id VARCHAR(255) PRIMARY KEY,"
|
||||
@" c_value VARCHAR(255) NOT NULL,"
|
||||
@" c_creationdate INT NOT NULL,"
|
||||
@" c_lastseen INT NOT NULL)");
|
||||
|
@ -351,7 +342,7 @@
|
|||
{
|
||||
static NSString *sqlFolderFormat
|
||||
= (@"CREATE TABLE %@ (\n"
|
||||
@" c_name VARCHAR2 (255) NOT NULL PRIMARY KEY,\n"
|
||||
@" c_name VARCHAR2 (255) PRIMARY KEY,\n"
|
||||
@" c_content CLOB NOT NULL,\n"
|
||||
@" c_creationdate INTEGER NOT NULL,\n"
|
||||
@" c_lastmodified INTEGER NOT NULL,\n"
|
||||
|
@ -377,7 +368,7 @@
|
|||
{
|
||||
static NSString *sqlFolderFormat
|
||||
= (@"CREATE TABLE %@ ("
|
||||
@" c_id VARCHAR2(255) NOT NULL PRIMARY KEY,"
|
||||
@" c_id VARCHAR2(255) PRIMARY KEY,"
|
||||
@" c_value VARCHAR2(255) NOT NULL,"
|
||||
@" c_creationdate INTEGER NOT NULL,"
|
||||
@" c_lastseen INTEGER NOT NULL)");
|
||||
|
|
|
@ -178,6 +178,9 @@
|
|||
{
|
||||
if ((self = [self init]))
|
||||
{
|
||||
if ([_name length] == 0)
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"'_name' must not be an empty string"];
|
||||
context = [[WOApplication application] context];
|
||||
nameInContainer = [_name copy];
|
||||
container = _container;
|
||||
|
|
Loading…
Reference in New Issue