propagate from branch 'ca.inverse.sogo.1_3_18' (head e85beb8f93ffc2c69838b75d3a43926981cbe855)

to branch 'ca.inverse.sogo' (head f418b89e20c4272dbbbddf4ef8ec5de8e414c52e)

Monotone-Parent: e85beb8f93ffc2c69838b75d3a43926981cbe855
Monotone-Parent: f418b89e20c4272dbbbddf4ef8ec5de8e414c52e
Monotone-Revision: abd34c5936406914d038a38374b7414d4b8435f2

Monotone-Author: jraby@inverse.ca
Monotone-Date: 2012-08-14T16:28:26
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Jean Raby 2012-08-14 16:28:26 +00:00
commit 55ac8077df
117 changed files with 6311 additions and 3035 deletions

341
ChangeLog
View File

@ -1,3 +1,118 @@
2012-08-13 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreSOGo.m (sogo_properties_get_uri): removed
useless backend method.
* OpenChange/MAPIStoreFolder.m (-createFolder:withRow:andFID:):
append a "/" to the new folder url when registering with the
url/id mapper.
* OpenChange/MAPIStoreDBFolder.m (-moveToFolder:withNewName:):
implemented method.
* OpenChange/MAPIStoreMailFolder.m (-moveToFolder:withNewName:):
invoke changePathTo: on the dbFolder.
* OpenChange/SOGoMAPIDBFolder.m (-changePathTo:): overriden method
in order to update children records too.
* OpenChange/SOGoMAPIDBObject.m (-performBatchSQLQueries:) new
method to perform void queries under a transaction.
(-changePathTo:) new method that updates the references for the
object record in the dbfs table.
* SoObjects/SOGo/NSString+Utilities.m
(-stringByReplacingPrefix:withPrefix:): new self-explicit method.
* OpenChange/SOGoMAPIDBFolder.m
(-childKeysOfType:includeDeleted:matchingQualifier:andSortOrderings:):
records now have a c_parent_path column in order to avoid fetch
the children of children due to the nature of our "LIKE" clause.
* OpenChange/SOGoMAPIDBObject.m (-save): records now have a
c_parent_path.
* OpenChange/MAPIStoreMailFolder.m (-supportsSubFolders):
overriden method to return YES.
2012-08-12 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreMailFolder.m (-moveToFolder:withName:): if
the new name is not provided (unlikely), the computed new name
must not have the "folder" prefix.
We now also make use of -[MAPIStoreMapping updateID:withURL:] to
change the references in the mapping database.
* OpenChange/MAPIStoreFolder.m (-objectId): folder keys always end
with a "/" by convention.
* OpenChange/MAPIStoreMapping.m (-updateID:withURL:): new method
that perform a change of url on container and leaf entries.
2012-08-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreSOGo.m (sogo_properties_get_uri): new
backend method.
2012-08-10 Ludovic Marcotte <lmarcotte@inverse.ca>
* Changed OpenChange/SOGoMAPIDBObject.m so we use
GNUstep's binary encoding - which is an order or
magnitude faster at encoding data than any other formats.
2012-08-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreSOGo.m (sogo_folder_move_folder)
(sogo_folder_copy_folder): the object on which the backend method
is invoked is now the folder being moved rather than its parent.
2012-08-09 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreMailFolder.m
(-moveFolderWithFID:fromFolder:withNewName:): first implementation
for IMAP folders.
* OpenChange/MAPIStoreSOGo.m (sogo_folder_move_folder)
(sogo_folder_copy_folder): new backend methods.
(sogo_folder_move_folder): do not instantiate an NSString from a
NULL "new_folder_name" parameter.
2012-08-08 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreCalendarMessage.m (-save): generate a
"nameInContainer" for the new object iif it is not set yet. If
set, we generate a new UID from it instead.
* OpenChange/MAPIStoreMessage.m (-saveMessage): make sure that the
PidTagChangeKey and PidTagChangeNumber props are no longer set in
the properties dict after the save occurred.
* OpenChange/MAPIApplication.m (-shouldSetupSignalHandlers):
overriden method by returning "NO".
2012-08-07 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/Appointments/SOGoAptMailNotification.m (-setupValues):
test whether each value is non-nil before adding it to the
dictionary.
* OpenChange/MAPIStoreMailVolatileMessage.m (-save): restored
registration of message url when saved.
2012-08-06 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreRecurrenceUtils.m (-[iCalRecurrenceRule
fillRecurrencePattern:withEvent:inTimeZone:inMemCtx:]): fixed a
crash occurring when the exception has no recurrence-id and
ignore the specific occurrence.
* OpenChange/MAPIStoreMailVolatileMessage.m (MakeMessageBody):
take "attachmentParts" parameter, deduced from the ivar with the
corresponding name.
* OpenChange/MAPIStoreSOGoObject.m (-objectId): force generation
of objectId by parent, whether it is a folder or not.
2012-08-07 Francis Lachapelle <flachapelle@inverse.ca>
* UI/Contacts/UIxListEditor.m (-setReferencesValue:): check for
@ -6,9 +121,15 @@
2012-08-03 Jean Raby <jraby@inverse.ca>
* SoObjects/SOGo/LDAPSource.m (changePasswordForLogin):
if userPasswordAlgorithm was not set or was set to "none",
use the plaintext password directly instead of using '{none}plaintext'
which isn't valid.
if userPasswordAlgorithm was not set or was set to "none",
use the plaintext password directly instead of using '{none}plaintext'
which isn't valid.
2012-08-02 Ludovic Marcotte <lmarcotte@inverse.ca>
* OpenChange/MAPIStoreUserContext.m (-_readUserPassword:)
We now read per-user passwords instead of relying on
a global file.
2012-07-31 Jean Raby <jraby@inverse.ca>
@ -21,6 +142,22 @@
(-sieveScriptWithRequirements:): filters must not be conditional
to each other.
2012-07-26 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/iCalTimeZone+MAPIStore.[hm]: new category module.
(-asTimeZoneStructInMemCtx:): new method that returns a struct
TimeZoneStruct as a binary blob from an iCalTimeZone object.
* OpenChange/MAPIStoreAppointmentWrapper.m
(-getPidLidTimeZoneStruct:inMemCtx:): new property getter that
returns the equivalent of the iCalTimeZone of the current event.
2012-07-25 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreDBFolder.m (-createFolder:withFID:andKey:):
invoke "reloadIfNeeded" on the created folder object in order to
initialize it.
2012-07-25 Francis Lachapelle <flachapelle@inverse.ca>
* SoObjects/Mailer/SOGoMailFolder.m
@ -38,6 +175,15 @@
* UI/WebServerResources/MailerUI.js (initMailer): define default
columns widths when not set.
2012-07-24 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreUserContext.m
(-initWithUsername:andTDBIndexing:): attempt to read the user
password from a property list.
* OpenChange/samba-get-config.py: new utility taking a samba
configuration variable and prints the value on stdout
2012-07-24 Francis Lachapelle <flachapelle@inverse.ca>
* UI/WebServerResources/UIxPreferences.js (savePreferences):
@ -56,8 +202,115 @@
(_shouldDisplayAsAttachment:): refactored to consider
the "bodyId" parameter only for non text/* parts.
2012-07-20 Francis Lachapelle <flachapelle@inverse.ca>
* UI/WebServerResources/MailerUI.js (onEmailTo): append the email
address from the href attribute if it doesn't appear in the link content.
* UI/MailPartViewers/UIxMailPartHTMLViewer.m
(-startElement:namespace:rawName:attributes:): don't skip "mailto:"
href.
* SoObjects/Appointments/SOGoAptMailReceipt.m (aptSummary-): new
method that returns a properly formatted string of the event title
with respect to the current operation (creation/deletion/update).
2012-07-20 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/NSObject+MAPIStore.m (-getSMTPAddrType:inMemCtx:):
new helper getter.
* OpenChange/MAPIStoreSOGo.m
(sogo_message_attachment_create_embedded_message): new backend method.
* OpenChange/NSObject+MAPIStore.m
(+fillAvailableProperties:withExclusions:): new method that fills
an existing array of properties with properties existing in
another class, as long as they are not listed in the array of
exclusions.
* OpenChange/MAPIStoreObject.m (-init): assigned a mutable array
to "proxies"
(-canGetProperty:): test the proxies for the availability of
properties so that -getAvailableProperties:inMemCtx: can return an
accurate result.
* OpenChange/MAPIStoreMessage.m (-getPidTagSubject:inMemCtx:): now
compute the return value based on PidTagNormalizedSubject and
PidTagSubjectPrefix as PidTagSubject is never actually set from
the client.
2012-07-19 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreObject.m (-nameInContainer): moved method
from MAPIStoreSOGoObject and made mandatory for subclasses.
(-url): new methed moved from MAPIStoreSOGoObject.
* OpenChange/MAPIStoreAppointmentWrapper.m: now a subclass of
MAPIStoreObjectProxy.
* OpenChange/MAPIStoreCalendarMessage.m
(-initWithSOGoObject:inContainer:): we now register our
appointment wrapper as a proxy.
* OpenChange/MAPIStoreObject.m (-addProxy:): new method that keeps
proxy objects in the new "proxies" ivar.
(-getProperty:withTag:inMemCtx:): added code that pass the request
to the available object proxies, when the property getters have
not been found in the local class.
* OpenChange/MAPIStoreObjectProxy.[hm]: new class module that
provide a facility for providing property getters in the name of
another class, working around the fact that Objective-C does not
provide multiple-inheritance.
* OpenChange/NSObject+MAPIStore.m
(+getAvailableProperties:inMemCtx:)
(-getAvailableProperties:inMemCtx:, canGetProperty:): methods
moved from MAPIStoreObject.m
2012-07-18 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreCalendarFolder.m (-createMessage): attach a
WOContext to the newEntry in order to enable page templates
resolution when notifications are sent.
* OpenChange/MAPIApplication.m (-init): a WEResourceManager is
setup for the application so that page templates can be properly
be initialized.
* OpenChange/MAPIStoreDBMessage.m (-objectVersion): shift the
version number by 16 bits, instead of doing it in -save.
(-save): don t swap the bytes of the version number as it would
return a wrong change number and a wrong change key for DB objects.
####### Ancestor
======= end
2012-07-20 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/NSObject+MAPIStore.m (-getSMTPAddrType:inMemCtx:):
new helper getter.
* OpenChange/MAPIStoreSOGo.m
(sogo_message_attachment_create_embedded_message): new backend method.
* OpenChange/NSObject+MAPIStore.m
(+fillAvailableProperties:withExclusions:): new method that fills
an existing array of properties with properties existing in
another class, as long as they are not listed in the array of
exclusions.
* OpenChange/MAPIStoreObject.m (-init): assigned a mutable array
to "proxies"
(-canGetProperty:): test the proxies for the availability of
properties so that -getAvailableProperties:inMemCtx: can return an
accurate result.
* OpenChange/MAPIStoreMessage.m (-getPidTagSubject:inMemCtx:): now
compute the return value based on PidTagNormalizedSubject and
PidTagSubjectPrefix as PidTagSubject is never actually set from
the client.
* SoObjects/Appointments/SOGoAppointmentFolder.m
(_appendCycleException:firstInstanceCalendarDateRange:fromRow:forRange:withTimeZone:toArray:):
return immediately if the occurrence does not have a valid
@ -76,6 +329,52 @@
method that returns a properly formatted string of the event title
with respect to the current operation (creation/deletion/update).
2012-07-19 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreObject.m (-nameInContainer): moved method
from MAPIStoreSOGoObject and made mandatory for subclasses.
(-url): new methed moved from MAPIStoreSOGoObject.
* OpenChange/MAPIStoreAppointmentWrapper.m: now a subclass of
MAPIStoreObjectProxy.
* OpenChange/MAPIStoreCalendarMessage.m
(-initWithSOGoObject:inContainer:): we now register our
appointment wrapper as a proxy.
* OpenChange/MAPIStoreObject.m (-addProxy:): new method that keeps
proxy objects in the new "proxies" ivar.
(-getProperty:withTag:inMemCtx:): added code that pass the request
to the available object proxies, when the property getters have
not been found in the local class.
* OpenChange/MAPIStoreObjectProxy.[hm]: new class module that
provide a facility for providing property getters in the name of
another class, working around the fact that Objective-C does not
provide multiple-inheritance.
* OpenChange/NSObject+MAPIStore.m
(+getAvailableProperties:inMemCtx:)
(-getAvailableProperties:inMemCtx:, canGetProperty:): methods
moved from MAPIStoreObject.m
2012-07-18 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreCalendarFolder.m (-createMessage): attach a
WOContext to the newEntry in order to enable page templates
resolution when notifications are sent.
* OpenChange/MAPIApplication.m (-init): a WEResourceManager is
setup for the application so that page templates can be properly
be initialized.
* OpenChange/MAPIStoreDBMessage.m (-objectVersion): shift the
version number by 16 bits, instead of doing it in -save.
(-save): don t swap the bytes of the version number as it would
return a wrong change number and a wrong change key for DB objects.
####### Ancestor
======= end
2012-07-18 Ludovic Marcotte <lmarcotte@inverse.ca>
* SoObjects/Appointments/SOGoAppointmentObject.m
@ -253,6 +552,25 @@
Show all addresses returned from secondaryEmails.
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]
@ -263,6 +581,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

View File

@ -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 %@",

View File

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

View File

@ -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;

View File

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

View File

@ -0,0 +1,107 @@
/* 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)
/* FIXME: c_parent_path should be indexed */
- (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_parent_path VARCHAR(255),"
@" 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_parent_path VARCHAR(255),"
@" 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_parent_path VARCHAR2(255),"
@" c_type SMALLINT NOT NULL,"
@" c_creationdate INT4 NOT NULL,"
@" c_lastmodified INT4 NOT NULL,"
@" c_version INT4 NOT NULL DEFAULT 0,"
@" c_deleted SMALLINT NOT NULL DEFAULT 0,"
@" c_content CLOB)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
@end

View File

@ -26,6 +26,17 @@ BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
UNRTF_DIR = unrtf-$(UNRTF_VERSION)
PYTHON = /usr/bin/python
PYTHON_IS_GOOD = $(shell $(PYTHON) -c 'from sys import version_info; a=version_info; print a.major == 2 and a.minor >= 6')
ifeq (${PYTHON_IS_GOOD},False)
PYTHON = /usr/bin/python2.6
endif
all::
@echo " Python executable: ${PYTHON}"
SAMBA_PRIVATE_DIR = $(shell $(PYTHON) ./samba-get-config.py "private dir")
$(SOGOBACKEND)_SUBPROJECTS += $(UNRTF_DIR)/src
$(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication
@ -41,9 +52,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 +66,18 @@ $(SOGOBACKEND)_OBJC_FILES += \
MAPIStoreFolder.m \
MAPIStoreMessage.m \
MAPIStoreObject.m \
MAPIStoreObjectProxy.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 \
@ -78,6 +91,7 @@ $(SOGOBACKEND)_OBJC_FILES += \
MAPIStoreCalendarContext.m \
MAPIStoreCalendarFolder.m \
MAPIStoreCalendarMessage.m \
MAPIStoreCalendarEmbeddedMessage.m \
MAPIStoreCalendarMessageTable.m \
MAPIStoreRecurrenceUtils.m \
\
@ -112,8 +126,14 @@ $(SOGOBACKEND)_OBJC_FILES += \
NSString+MAPIStore.m \
NSValue+MAPIStore.m \
\
EOBitmaskQualifier.m \
iCalEvent+MAPIStore.m \
iCalTimeZone+MAPIStore.m \
\
GCSSpecialQueries+OpenChange.m\
\
EOQualifier+MAPI.m \
\
EOBitmaskQualifier.m
$(SOGOBACKEND)_RESOURCE_FILES += \
@ -145,7 +165,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)
@ -160,7 +186,7 @@ SAMBA_LIB_DIR = $(shell pkg-config libmapistore --variable=libdir)
LIBMAPI_LIBS = $(shell pkg-config libmapi --libs)
LIBMAPISTORE_CFLAGS = $(shell pkg-config libmapistore --cflags) -DSAMBA_PREFIX="\"$(shell pkg-config libmapistore --variable=prefix)\""
LIBMAPISTORE_LIBS = $(shell pkg-config libmapistore --libs) -lmapiproxy
LIBMAPISTORE_LIBS = $(shell pkg-config libmapistore --libs) -lmapiproxy -lWEExtensions
$(MAPISTORESOGO)_INSTALL_DIR = $(DESTDIR)/$(SAMBA_LIB_DIR)/mapistore_backends
$(MAPISTORESOGO)_LIB_DIRS += \
@ -176,6 +202,7 @@ $(SOGOBACKEND)_LIB_DIRS += \
ADDITIONAL_INCLUDE_DIRS += \
-Werror -Wall \
-DSAMBA_PRIVATE_DIR=@"\"$(SAMBA_PRIVATE_DIR)\"" \
$(LIBMAPI_CFLAGS) \
$(LIBMAPISTORE_CFLAGS) \
-I$(UNRTF_DIR)/src \

View File

@ -2,4 +2,4 @@ all:: MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h
MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h: gen-property-selectors.py code-MAPIStorePropertySelectors.m code-MAPIStorePropertySelectors.h
@echo " Auto-generating MAPIStorePropertySelectors.[hm]..."
@./gen-property-selectors.py -o MAPIStorePropertySelectors $(LIBMAPISTORE_CFLAGS)
@$(PYTHON) ./gen-property-selectors.py -o MAPIStorePropertySelectors $(LIBMAPISTORE_CFLAGS)

View File

@ -22,6 +22,7 @@
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSTimeZone.h>
#import <WEExtensions/WEResourceManager.h>
#import <SOGo/SOGoProductLoader.h>
#import <SOGo/SOGoSystemDefaults.h>
@ -46,12 +47,18 @@ MAPIApplication *MAPIApp = nil;
{
if (!MAPIApp)
{
WEResourceManager *rm;
// TODO publish
[iCalEntityObject initializeSOGoExtensions];
MAPIApp = [super init];
[MAPIApp retain];
rm = [[WEResourceManager alloc] init];
[self setResourceManager:rm];
[rm release];
utcTZ = [NSTimeZone timeZoneWithName: @"UTC"];
[utcTZ retain];
}
@ -59,6 +66,11 @@ MAPIApplication *MAPIApp = nil;
return MAPIApp;
}
- (BOOL) shouldSetupSignalHandlers
{
return NO;
}
- (void) setUserContext: (MAPIStoreUserContext *) newContext
{
/* user contexts must not be retained here ad their holder (mapistore)

View File

@ -23,10 +23,11 @@
#ifndef MAPISTORECALENDARWRAPPER_H
#define MAPISTORECALENDARWRAPPER_H
#import <Foundation/NSObject.h>
#import <NGCards/iCalPerson.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import "MAPIStoreObjectProxy.h"
@class NSTimeZone;
@class iCalAlarm;
@ -35,10 +36,11 @@
@class SOGoUser;
@interface MAPIStoreAppointmentWrapper : NSObject
@interface MAPIStoreAppointmentWrapper : MAPIStoreObjectProxy
{
struct mapistore_connection_info *connInfo;
iCalCalendar *calendar;
iCalEvent *firstEvent;
iCalEvent *event;
NSTimeZone *timeZone;
SOGoUser *user;
@ -120,8 +122,8 @@
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidIndentedBusyStatus: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagNormalizedSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidLocation: (void **) data // LOCATION
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions

View File

@ -1,6 +1,6 @@
/* MAPIStoreAppointmentWrapper.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011, 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -20,24 +20,28 @@
* Boston, MA 02111-1307, USA.
*/
#include <talloc.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSCharacterSet.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGCards/iCalAlarm.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalEventChanges.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>
#import <SOGo/SOGoUserManager.h>
#import "iCalTimeZone+MAPIStore.h"
#import "MAPIStoreRecurrenceUtils.h"
#import "MAPIStoreSamDBUtils.h"
#import "MAPIStoreTypes.h"
@ -49,7 +53,6 @@
#import "MAPIStoreAppointmentWrapper.h"
#undef DEBUG
#include <talloc.h>
#include <stdbool.h>
#include <gen_ndr/exchange.h>
#include <gen_ndr/property.h>
@ -181,11 +184,15 @@ static NSCharacterSet *hexCharacterSet = nil;
inTimeZone: (NSTimeZone *) newTimeZone
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
{
NSArray *events;
if ((self = [self init]))
{
connInfo = newConnInfo;
ASSIGN (event, newEvent);
ASSIGN (calendar, [event parent]);
ASSIGN (calendar, [newEvent parent]);
event = newEvent;
events = [calendar events];
firstEvent = [events objectAtIndex: 0];
ASSIGN (timeZone, newTimeZone);
ASSIGN (user, newUser);
ASSIGN (senderEmail, newSenderEmail);
@ -198,7 +205,6 @@ static NSCharacterSet *hexCharacterSet = nil;
- (void) dealloc
{
[calendar release];
[event release];
[timeZone release];
[user release];
[senderEmail release];
@ -435,7 +441,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagIconIndex: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t longValue;
@ -580,7 +586,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
const char *className;
@ -626,35 +632,20 @@ static NSCharacterSet *hexCharacterSet = nil;
return MAPISTORE_SUCCESS;
}
- (int) getPidLidAppointmentMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = talloc_strdup (memCtx, "IPM.Appointment");
return MAPISTORE_SUCCESS;
}
- (int) getPidLidFInvited: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
- (int) getPidTagStartDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSCalendarDate *dateValue;
NSInteger offset;
if ([event isRecurrent])
dateValue = [event firstRecurrenceStartDate];
else
dateValue = [event startDate];
if ([event isAllDay])
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidLidAppointmentSequence: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -722,13 +713,245 @@ static NSCharacterSet *hexCharacterSet = nil;
- (int) getPidLidAppointmentStartWhole: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagStartDate: data inMemCtx: memCtx];
NSCalendarDate *dateValue;
NSInteger offset;
// if ([event isRecurrent])
// dateValue = [event firstRecurrenceStartDate];
// else
dateValue = [event startDate];
if ([event isAllDay])
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagStartDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
/* "The PidTagStartDate property ([MS-OXPROPS] section 2.1077) SHOULD be
set, and when set, it MUST be equal to the value of the
PidLidAppointmentStartWhole property (section 2.2.1.5).". Not true for
exceptions, where it is the normal start date for the day of the
exception. */
NSCalendarDate *dateValue;
NSInteger offset;
dateValue = [event recurrenceId];
if (!dateValue)
dateValue = [event startDate];
[dateValue setTimeZone: timeZone];
if ([event isAllDay])
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidLidCommonStart: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidLidAppointmentStartWhole: data inMemCtx: memCtx];
NSCalendarDate *dateValue;
NSInteger offset;
dateValue = [firstEvent startDate];
if ([firstEvent isAllDay])
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidLidClipStart: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
if ([event isRecurrent])
{
dateValue = [[event startDate] hour: 0 minute: 0 second: 0];
*data = [dateValue asFileTimeInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else if ([event recurrenceId] != nil)
rc = MAPISTORE_ERR_NOT_FOUND;
else
rc = [self getPidLidAppointmentStartWhole: data inMemCtx: memCtx];
return rc;
}
- (int) getPidTagExceptionStartTime: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
NSInteger offset;
if ([event recurrenceId] != nil)
{
dateValue = [event startDate];
[dateValue setTimeZone: timeZone];
if (![event isAllDay])
{
offset = [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
*data = [dateValue asFileTimeInMemCtx: localMemCtx];
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
- (int) getPidLidAppointmentEndWhole: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSCalendarDate *dateValue;
NSInteger offset;
// if ([event isRecurrent])
// dateValue = [event firstRecurrenceStartDate];
// else
dateValue = [event startDate];
offset = [event durationAsTimeInterval];
if ([event isAllDay])
offset -= [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagEndDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSCalendarDate *dateValue;
NSInteger offset;
dateValue = [event recurrenceId];
if (!dateValue)
dateValue = [event startDate];
[dateValue setTimeZone: timeZone];
offset = [firstEvent durationAsTimeInterval];
if ([firstEvent isAllDay])
offset -= [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidLidCommonEnd: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSCalendarDate *dateValue;
NSInteger offset;
// if ([event isRecurrent])
// dateValue = [event firstRecurrenceStartDate];
// else
dateValue = [firstEvent startDate];
offset = [firstEvent durationAsTimeInterval];
if ([event isAllDay])
offset -= [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidLidClipEnd: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
NSInteger offset;
iCalRecurrenceRule *rrule;
if ([event isRecurrent])
{
rrule = [[event recurrenceRules] objectAtIndex: 0];
dateValue = [rrule untilDate];
if (dateValue)
{
if ([event isAllDay])
offset = -[timeZone secondsFromGMTForDate: dateValue];
else
offset = 0;
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
else
dateValue = [NSCalendarDate dateWithYear: 4500 month: 8 day: 31
hour: 23 minute: 59 second: 59
timeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else if ([event recurrenceId] != nil)
rc = MAPISTORE_ERR_NOT_FOUND;
else
rc = [self getPidLidAppointmentEndWhole: data inMemCtx: memCtx];
return rc;
}
- (int) getPidTagExceptionEndTime: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
NSInteger offset;
if ([event recurrenceId] != nil)
{
dateValue = [event startDate];
[dateValue setTimeZone: timeZone];
offset = [event durationAsTimeInterval];
if (![event isAllDay])
offset += [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
*data = [dateValue asFileTimeInMemCtx: localMemCtx];
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
- (int) _getEntryIdFromCN: (NSString *) cn
@ -827,7 +1050,7 @@ static NSCharacterSet *hexCharacterSet = nil;
/* sender (organizer) */
- (int) getPidTagSenderEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getEmailAddress: data
forICalPerson: [event organizer]
@ -835,7 +1058,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagSenderAddressType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getAddrType: data
forICalPerson: [event organizer]
@ -843,7 +1066,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagSenderName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getName: data
forICalPerson: [event organizer]
@ -851,16 +1074,41 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagSenderEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getEntryId: data
forICalPerson: [event organizer]
inMemCtx: memCtx];
}
/* sender representing */
- (int) getPidTagSentRepresentingEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagSenderEmailAddress: data inMemCtx: memCtx];
}
- (int) getPidTagSentRepresentingAddressType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getSMTPAddrType: data inMemCtx: memCtx];
}
- (int) getPidTagSentRepresentingName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagSenderName: data inMemCtx: memCtx];
}
- (int) getPidTagSentRepresentingEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagSenderEntryId: data inMemCtx: memCtx];
}
/* attendee */
- (int) getPidTagReceivedByEmailAddress: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getEmailAddress: data
forICalPerson: [event userAsAttendee: user]
@ -868,7 +1116,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagReceivedByAddressType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getAddrType: data
forICalPerson: [event userAsAttendee: user]
@ -876,7 +1124,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagReceivedByName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getName: data
forICalPerson: [event userAsAttendee: user]
@ -884,7 +1132,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagReceivedByEntryId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self _getEntryId: data
forICalPerson: [event userAsAttendee: user]
@ -892,40 +1140,6 @@ static NSCharacterSet *hexCharacterSet = nil;
}
/* /attendee */
- (int) getPidTagEndDate: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSCalendarDate *dateValue;
NSInteger offset;
if ([event isRecurrent])
dateValue = [event firstRecurrenceStartDate];
else
dateValue = [event startDate];
offset = [event durationAsTimeInterval];
if ([event isAllDay])
offset -= [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidLidAppointmentEndWhole: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagEndDate: data inMemCtx: memCtx];
}
- (int) getPidLidCommonEnd: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidLidAppointmentEndWhole: data inMemCtx: memCtx];
}
- (int) getPidLidAppointmentDuration: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -966,8 +1180,8 @@ static NSCharacterSet *hexCharacterSet = nil;
return [self getPidLidBusyStatus: data inMemCtx: memCtx];
}
- (int) getPidTagSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagNormalizedSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[event summary] asUnicodeInMemCtx: memCtx];
@ -995,7 +1209,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 +1218,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 */
@ -1020,14 +1236,14 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagSensitivity: (void **) data // not implemented, depends on CLASS
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
// normal = 0, personal?? = 1, private = 2, confidential = 3
return [self getLongZero: data inMemCtx: memCtx];
}
- (int) getPidTagImportance: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t v;
if ([[event priority] isEqualToString: @"9"])
@ -1043,7 +1259,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagBody: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc = MAPISTORE_SUCCESS;
NSString *stringValue;
@ -1058,14 +1274,6 @@ static NSCharacterSet *hexCharacterSet = nil;
return rc;
}
- (int) getPidLidIsRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPIBoolValue (memCtx, [event isRecurrent]);
return MAPISTORE_SUCCESS;
}
- (int) getPidLidRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -1074,37 +1282,144 @@ static NSCharacterSet *hexCharacterSet = nil;
return MAPISTORE_SUCCESS;
}
static void
_fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
NSCalendarDate *startDate, NSTimeInterval duration,
NSCalendarDate * endDate, iCalRecurrenceRule *rule)
- (int) getPidLidIsRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t startMinutes;
*data = MAPIBoolValue (memCtx,
[event isRecurrent]
|| ([event recurrenceId] != nil));
[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; */
return MAPISTORE_SUCCESS;
}
- (struct SBinary_short *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidLidIsException: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPIBoolValue (memCtx, [event recurrenceId] != nil);
return MAPISTORE_SUCCESS;
}
- (int) getPidLidFExceptionalBody: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidLidExceptionReplaceTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSCalendarDate *dateValue;
NSInteger offset;
dateValue = [event recurrenceId];
if (dateValue)
{
rc = MAPISTORE_SUCCESS;
if ([event isAllDay])
{
offset = -[timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
}
[dateValue setTimeZone: utcTZ];
*data = [dateValue asFileTimeInMemCtx: memCtx];
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
- (void) _fillExceptionInfo: (struct ExceptionInfo *) exceptionInfo
andExtendedException: (struct ExtendedException *) extendedException
withException: (iCalEvent *) exceptionEvent
inMemCtx: (TALLOC_CTX *) memCtx
{
iCalEventChanges *changes;
NSArray *changedProperties;
NSCalendarDate *dateValue;
NSInteger offset;
changes = [iCalEventChanges changesFromEvent: event toEvent: exceptionEvent];
memset (exceptionInfo, 0, sizeof (struct ExceptionInfo));
memset (extendedException, 0, sizeof (struct ExtendedException));
extendedException->ChangeHighlight.Size = sizeof (uint32_t);
dateValue = [exceptionEvent startDate];
offset = [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
exceptionInfo->StartDateTime = [dateValue asMinutesSince1601];
extendedException->ChangeHighlight.Value = BIT_CH_START;
extendedException->StartDateTime = exceptionInfo->StartDateTime;
dateValue = [exceptionEvent endDate];
offset = [timeZone secondsFromGMTForDate: dateValue];
dateValue = [dateValue dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
exceptionInfo->EndDateTime = [dateValue asMinutesSince1601];
extendedException->ChangeHighlight.Value |= BIT_CH_END;
extendedException->EndDateTime = exceptionInfo->EndDateTime;
dateValue = [[exceptionEvent recurrenceId]
dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: offset];
exceptionInfo->OriginalStartDate = [dateValue asMinutesSince1601];
extendedException->OriginalStartDate = exceptionInfo->OriginalStartDate;
changedProperties = [changes updatedProperties];
if ([changedProperties containsObject: @"summary"])
{
extendedException->ChangeHighlight.Value |= BIT_CH_SUBJECT;
extendedException->Subject
= [[exceptionEvent summary] asUnicodeInMemCtx: memCtx];
exceptionInfo->OverrideFlags |= ARO_SUBJECT;
exceptionInfo->Subject.subjectMsg.msg
= (uint8_t *) extendedException->Subject;
/* FIXME: this will fail with non ascii chars */
exceptionInfo->Subject.subjectMsg.msgLength2 = [[exceptionEvent summary] length];
exceptionInfo->Subject.subjectMsg.msgLength = exceptionInfo->Subject.subjectMsg.msgLength2 + 1;
}
if ([changedProperties containsObject: @"location"])
{
extendedException->ChangeHighlight.Value |= BIT_CH_LOCATION;
extendedException->Location
= [[exceptionEvent location] asUnicodeInMemCtx: memCtx];
exceptionInfo->OverrideFlags |= ARO_LOCATION;
exceptionInfo->Location.locationMsg.msg
= (uint8_t *) extendedException->Location;
/* FIXME: this will fail with non ascii chars */
exceptionInfo->Location.locationMsg.msgLength2 = [[exceptionEvent location] length];
exceptionInfo->Location.locationMsg.msgLength = exceptionInfo->Location.locationMsg.msgLength2 + 1;
}
if ([event isAllDay] != [exceptionEvent isAllDay])
{
exceptionInfo->OverrideFlags |= ARO_SUBTYPE;
exceptionInfo->SubType.sType = [exceptionEvent isAllDay];
}
}
// - (struct SBinary_short *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx
- (struct Binary_r *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx
{
struct AppointmentRecurrencePattern *arp;
struct Binary_r *bin;
struct SBinary_short *sBin;
// struct SBinary_short *sBin;
NSCalendarDate *firstStartDate;
iCalRecurrenceRule *rule;
NSUInteger startMinutes;
NSArray *events, *exceptions;
iCalEvent *exceptionEvent;
NSUInteger count, max;
rule = [[event recurrenceRules] objectAtIndex: 0];
@ -1113,15 +1428,47 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
{
[firstStartDate setTimeZone: timeZone];
arp = talloc_zero (memCtx, struct AppointmentRecurrencePattern);
_fillAppointmentRecurrencePattern (arp, firstStartDate,
[event durationAsTimeInterval],
[event lastPossibleRecurrenceStartDate],
rule);
sBin = talloc_zero (memCtx, struct SBinary_short);
bin = set_AppointmentRecurrencePattern (sBin, arp);
sBin->cb = bin->cb;
sBin->lpb = bin->lpb;
arp = talloc_zero (NULL, struct AppointmentRecurrencePattern);
[rule fillRecurrencePattern: &arp->RecurrencePattern
withEvent: event
inTimeZone: timeZone
inMemCtx: arp];
arp->ReaderVersion2 = 0x00003006;
arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with
ol2003 */
startMinutes = ([firstStartDate hourOfDay] * 60
+ [firstStartDate minuteOfHour]);
arp->StartTimeOffset = startMinutes;
arp->EndTimeOffset = (startMinutes
+ (NSUInteger) ([event durationAsTimeInterval]
/ 60));
events = [[event parent] events];
exceptions
= [events subarrayWithRange: NSMakeRange (1, [events count] - 1)];
max = [exceptions count];
arp->ExceptionCount = max;
arp->ExceptionInfo = talloc_array (memCtx, struct ExceptionInfo, max);
arp->ExtendedException = talloc_array (memCtx, struct ExtendedException, max);
for (count = 0; count < max; count++)
{
exceptionEvent = [exceptions objectAtIndex: count];
[self _fillExceptionInfo: arp->ExceptionInfo + count
andExtendedException: arp->ExtendedException + count
withException: exceptionEvent
inMemCtx: arp];
}
arp->ReservedBlock1Size = 0;
arp->ReservedBlock2Size = 0;
/* Currently ignored in property.idl: arp->ReservedBlock2Size = 0; */
/* convert struct to blob */
// sBin = talloc_zero (memCtx, struct SBinary_short);
bin = set_AppointmentRecurrencePattern (memCtx, arp);
// sBin->cb = bin->cb;
// sBin->lpb = bin->lpb;
talloc_free (arp);
// DEBUG(5, ("To client:\n"));
@ -1130,12 +1477,100 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
else
{
[self errorWithFormat: @"no first occurrence found in rule: %@", rule];
sBin = NULL;
// bin = NULL;
bin = NULL;
}
return sBin;
return bin;
}
/* exception 12345 + 123456 (exchange):
81ad0102 (PT_BINARY):
named prop
guid: {00062002-0000-0000-c000-000000000046}
dispid: 0x00008216
(163 bytes)
04 30 04 30 0a 20 00 00 | \x04 0 \x04 0 \x0a \x00 \x00
00 00 00 00 00 00 a0 05 | \x00 \x00 \x00 \x00 \x00 \x00 \xa0 \x05
00 00 00 00 00 00 23 20 | \x00 \x00 \x00 \x00 \x00 \x00 #
00 00 0a 00 00 00 00 00 | \x00 \x00 \x0a \x00 \x00 \x00 \x00 \x00
00 00 01 00 00 00 a0 c6 | \x00 \x00 \x01 \x00 \x00 \x00 \xa0 \xc6
e6 0c 01 00 00 00 a0 c6 | \xe6 \x0c \x01 \x00 \x00 \x00 \xa0 \xc6
e6 0c 00 c1 e6 0c df 80 | \xe6 \x0c \x00 \xc1 \xe6 \x0c \xdf \x80
e9 5a 06 30 00 00 08 30 | \xe9 Z \x06 0 \x00 \x00 \x08 0
00 00 66 03 00 00 84 03 | \x00 \x00 f \x03 \x00 \x00 \x84 \x03
00 00 01 00 e8 c9 e6 0c | \x00 \x00 \x01 \x00 \xe8 \xc9 \xe6 \x0c
f6 ca e6 0c 06 ca e6 0c | \xf6 \xca \xe6 \x0c \x06 \xca \xe6 \x0c
11 00 06 00 05 00 31 32 | \x11 \x00 \x06 \x00 \x05 \x00 1 2
33 34 35 07 00 06 00 31 | 3 4 5 \x07 \x00 \x06 \x00 1
32 33 34 35 36 00 00 00 | 2 3 4 5 6 \x00 \x00 \x00
00 00 00 00 00 e8 c9 e6 | \x00 \x00 \x00 \x00 \x00 \xe8 \xc9 \xe6
0c f6 ca e6 0c 06 ca e6 | \x0c \xf6 \xca \xe6 \x0c \x06 \xca \xe6
0c 05 00 31 00 32 00 33 | \x0c \x05 \x00 1 \x00 2 \x00 3
00 34 00 35 00 06 00 31 | \x00 4 \x00 5 \x00 \x06 \x00 1
00 32 00 33 00 34 00 35 | \x00 2 \x00 3 \x00 4 \x00 5
00 36 00 00 00 00 00 00 | \x00 6 \x00 \x00 \x00 \x00 \x00 \x00
00 00 00 | \x00 \x00 \x00
openchange:
918b0102 (PT_BINARY):
named prop
guid: {00062002-0000-0000-c000-000000000046}
dispid: 0x00008216
(167 bytes)
recurrence pattern
readerversion: 04 30
writerversion: 04 30
recurfrequency: 0a 20 (daily)
patterntype: 00 00
calendartype: 00 00
firstdatetime: 00 00 00 00
period: a0 05 00 00 (1440 minutes)
slidingflag: 00 00 00 00
patterntypespecific: (0 bytes)
endtype: 23 20 00 00
occurrencecount: *00->0a 00 00 00 (meaningless since no enddate)
firstdow: 00 00 00 00
deletedicount: 01 00 00 00
deletedinstancedates: (1)
a0 c6 e6 0c
modifiedicount: 01 00 00 00
modifiedinstancedates: (1)
a0 c6 e6 0c
startdate: 00 c1 e6 0c
enddate: df 80 e9 5a
ReaderVersion2: 06 30 00 00
WriterVersion2: 08 30 00 00
StartTimeOffset: 66 03 00 00
EndTimeOffset: 84 03 00 00
ExceptionCount: 01 00
ExceptionInfos: (1)
StartDateTime: *e7->e8 *ca->c9 e6 0c
EndDateTime: *e6->f6 *cb->ca e6 0c
OriginalStartDate: *a0->06 *c6->ca e6 0c
OverrideFlags: 11 00
SubjectLength2: 06 00
SubjectLength: 05 00
Subject: 31 32 33 34 35
LocationLength2: 07 00
LocationLength: 06 00
Location: 31 32 33 34 35 36
ReservedBlock1Size: 00 00 00 00
ExtendedException: (1)
ReservedBlockEE1Size: 00 00 00 00
StartDateTime: *e7->e8 *ca->c9 e6 0c
EndDateTime: *e6->f6 *cb->ca e6 0c
OriginalStartDate: *a0->06 *c6->ca e6 0c
WideCharSubjectLength *06->05
WideCharSubject: 00 31 00 32 00 33 00 34 00 35 00 [2bytes sup: 00 00]
LocationLength: *07->06
Location 00 31 00 32 00 33 00 34 00 35 00 36 00 00
ReservedBlockEE2Size: 00 00 00 00
ReservedBlockEE2Size: 00 00 00 00
*/
- (int) getPidLidAppointmentRecur: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -1515,4 +1950,41 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidLidTimeZoneDescription: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
NSString *tzid;
tzid = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"]
value: 0 ofAttribute: @"tzid"];
if ([tzid length] > 0)
{
*data = [tzid asUnicodeInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
- (int) getPidLidTimeZoneStruct: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
enum mapistore_error rc;
iCalTimeZone *icalTZ;
icalTZ = [(iCalDateTime *) [event firstChildWithTag: @"dtstart"] timeZone];
if (icalTZ)
{
*data = [icalTZ asTimeZoneStructInMemCtx: memCtx];
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
@end

View File

@ -40,6 +40,9 @@
withMID: (uint64_t *) mid
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx;
/* helpers */
- (NSData *) mimeAttachTag;

View File

@ -28,6 +28,7 @@
#import "MAPIStoreMapping.h"
#import "MAPIStoreMessage.h"
#import "MAPIStoreTypes.h"
#import "NSObject+MAPIStore.h"
#undef DEBUG
#include <stdbool.h>
@ -90,6 +91,12 @@
return MAPISTORE_SUCCESS;
}
- (int) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getLongZero: data inMemCtx: memCtx];
}
- (int) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMID: (uint64_t *) mid
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
@ -103,20 +110,34 @@
mapping = [self mapping];
// if (attMessage)
attMessage = [self openEmbeddedMessage];
if (attMessage)
{
*mid = [mapping idFromURL: [attMessage url]];
[mapping registerURL: [attMessage url]
withID: *mid];
*messagePtr = attMessage;
*mapistoreMsgPtr = mapistoreMsg;
}
return (attMessage ? MAPISTORE_SUCCESS : MAPISTORE_ERROR);
}
- (int) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStoreEmbeddedMessage *attMessage;
struct mapistore_message *mapistoreMsg;
mapistoreMsg = talloc_zero (memCtx, struct mapistore_message);
attMessage = [self createEmbeddedMessage];
if (attMessage)
{
*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);
}

View File

@ -25,7 +25,15 @@
#import "MAPIStoreAttachment.h"
@interface MAPIStoreCalendarAttachment : MAPIStoreAttachment
@class iCalEvent;
@interface MAPIStoreCalendarAttachment : MAPIStoreAttachment
{
iCalEvent *event;
}
- (void) setEvent: (iCalEvent *) newEvent;
- (iCalEvent *) event;
@end

View File

@ -20,9 +20,22 @@
* Boston, MA 02111-1307, USA.
*/
#import "MAPIStoreTypes.h"
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSTimeZone.h>
#import "MAPIStoreEmbeddedMessage.h"
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGExtensions/NSObject+Logs.h>
#import "iCalEvent+MAPIStore.h"
#import "MAPIStoreCalendarEmbeddedMessage.h"
#import "MAPIStoreTypes.h"
#import "MAPIStoreUserContext.h"
#import "NSDate+MAPIStore.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "MAPIStoreCalendarAttachment.h"
@ -34,12 +47,42 @@
@implementation MAPIStoreCalendarAttachment
- (id) init
{
if ((self = [super init]))
{
event = nil;
}
return self;
}
- (void) dealloc
{
[event release];
[super dealloc];
}
- (void) setEvent: (iCalEvent *) newEvent
{
ASSIGN (event, newEvent);
}
- (iCalEvent *) event
{
return event;
}
- (NSString *) nameInContainer
{
return [[event uniqueChildWithTag: @"recurrence-id"]
flattenedValuesForKey: @""];
}
- (int) getPidTagAttachmentHidden: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = MAPIBoolValue (localMemCtx, YES);
return MAPISTORE_SUCCESS;
return [self getYes: data inMemCtx: localMemCtx];
}
- (int) getPidTagAttachmentFlags: (void **) data
@ -50,34 +93,69 @@
return MAPISTORE_SUCCESS;
}
- (int) getPidTagAttachmentLinkId: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
return [self getLongZero: data inMemCtx: localMemCtx];
}
- (int) getPidTagAttachFlags: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
return [self getLongZero: data inMemCtx: localMemCtx];
}
- (int) getPidTagAttachMethod: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = MAPILongValue (localMemCtx, 0x00000005); /* afEmbeddedMessage */
*data = MAPILongValue (localMemCtx, afEmbeddedMessage);
return MAPISTORE_SUCCESS;
}
// case PidTagExceptionStartTime:
// case PidTagExceptionEndTime:
- (int) getPidTagAttachEncoding: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = [[NSData data] asBinaryInMemCtx: localMemCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) localMemCtx
{
*data = "Untitled";
return MAPISTORE_SUCCESS;
}
- (int) getPidTagAttachmentContactPhoto: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
// case PidTagExceptionReplaceTime:
/* subclasses */
- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage
- (MAPIStoreCalendarEmbeddedMessage *) openEmbeddedMessage
{
MAPIStoreEmbeddedMessage *msg;
MAPIStoreCalendarEmbeddedMessage *msg;
if (isNew)
msg = nil;
else
msg = nil;
msg = [MAPIStoreCalendarEmbeddedMessage
mapiStoreObjectInContainer: self];
return msg;
}
- (MAPIStoreEmbeddedMessage *) createEmbeddedMessage
- (MAPIStoreCalendarEmbeddedMessage *) createEmbeddedMessage
{
return [MAPIStoreEmbeddedMessage embeddedMessageWithAttachment: self];
MAPIStoreCalendarEmbeddedMessage *msg;
msg = [self openEmbeddedMessage];
[msg setIsNew: YES];
return msg;
}
@end

View File

@ -0,0 +1,34 @@
/* MAPIStoreCalendarEmbeddedMessage.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 MAPISTORECALENDAREMBEDDEDMESSAGE_H
#define MAPISTORECALENDAREMBEDDEDMESSAGE_H
#import "MAPIStoreEmbeddedMessage.h"
@class MAPIStoreAppointmentWrapper;
@interface MAPIStoreCalendarEmbeddedMessage : MAPIStoreEmbeddedMessage
@end
#endif /* MAPISTORECALENDAREMBEDDEDMESSAGE_H */

View File

@ -0,0 +1,208 @@
/* MAPIStoreCalendarEmbeddedMessage.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 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.
*/
#include <talloc.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <SOGo/SOGoUser.h>
#import "iCalEvent+MAPIStore.h"
#import "MAPIStoreAppointmentWrapper.h"
#import "MAPIStoreCalendarAttachment.h"
#import "MAPIStoreContext.h"
#import "MAPIStoreUserContext.h"
#import "MAPIStoreTypes.h"
#import "NSObject+MAPIStore.h"
#import "MAPIStoreCalendarEmbeddedMessage.h"
#include <mapistore/mapistore_errors.h>
@implementation MAPIStoreCalendarEmbeddedMessage
- (id) initInContainer: (id) newContainer
{
MAPIStoreContext *context;
MAPIStoreUserContext *userContext;
MAPIStoreAppointmentWrapper *appointmentWrapper;
if ((self = [super initInContainer: newContainer]))
{
context = [self context];
userContext = [self userContext];
appointmentWrapper
= [MAPIStoreAppointmentWrapper
wrapperWithICalEvent: [newContainer event]
andUser: [userContext sogoUser]
andSenderEmail: nil
inTimeZone: [userContext timeZone]
withConnectionInfo: [context connectionInfo]];
[self addProxy: appointmentWrapper];
}
return self;
}
- (NSDate *) creationTime
{
return [[container event] created];
}
- (NSDate *) lastModificationTime
{
return [[container event] lastModified];
}
- (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx
{
struct mapistore_message *msgData;
[super getMessageData: &msgData inMemCtx: memCtx];
/* HACK: we know the first (and only) proxy is our appointment wrapper
instance, but this might not always be true */
[[proxies objectAtIndex: 0] fillMessageData: msgData
inMemCtx: memCtx];
*dataPtr = msgData;
}
- (int) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = talloc_strdup (memCtx, "IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}");
return MAPISTORE_SUCCESS;
}
- (int) getPidTagMessageFlags: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, MSGFLAG_UNMODIFIED);
return MAPISTORE_SUCCESS;
}
- (int) getPidTagProcessed: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
- (int) getPidTagResponseRequested: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
/* discarded properties */
- (int) getPidLidAppointmentLastSequence: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidLidMeetingWorkspaceUrl: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidLidContacts: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagSensitivity: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidLidPrivate: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidNameKeywords: (void **)
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (void) save
{
// (gdb) po embeddedMessage->properties
// 2442592320 = "2012-07-11 22:30:00 +0000";
// 2448359488 = "2012-07-11 22:30:00 +0000";
// 2442723392 = "2012-07-11 22:30:00 +0000";
// 2442068032 = "2012-07-11 22:30:00 +0000";
// 2441740352 = "2012-07-11 23:00:00 +0000";
// 131083 = 1; 2442330115 = 2;
// 235339779 = 9;
// 6291520 = "2012-07-11 16:00:00 +0000";
// 2442526784 = "2012-07-11 23:00:00 +0000";
// 2818059 = 0;
// 1703967 = "IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}";
// 3538947 = 0;
// 1071513603 = 28591; 805830720 = "2012-07-10 16:42:00 +0000";
// 2485977346 = <02013000 02001500 45006100 73007400
// 65007200 6e002000 53007400 61006e00 64006100 72006400 20005400 69006d00
// 65000200 02013e00 0000d607 00000000 00000000 00000000 00002c01 00000000
// 0000c4ff ffff0000 0a000000 05000200 00000000 00000000 04000000 01000200
// 00000000 00000201 3e000200 d7070000 00000000 00000000 00000000 2c010000
// 00000000 c4ffffff 00000b00 00000100 02000000 00000000 00000300 00000200
// 02000000 00000000>; 2454257728 = "2012-07-11 16:00:00 +0000"; 2442985475 =
// 118330; 1507331 = 1; 805765184 = "2012-07-09 18:32:00 +0000"; 2442657856 =
// "2012-07-11 23:00:00 +0000"; 2443051039 = "11.0"; 236912651 = 1; 2485911810 =
// <02013000 02001500 45006100 73007400 65007200 6e002000 53007400 61006e00
// 64006100 72006400 20005400 69006d00 65000200 02013e00 0000d607 00000000
// 00000000 00000000 00002c01 00000000 0000c4ff ffff0000 0a000000 05000200
// 00000000 00000000 04000000 01000200 00000000 00000201 3e000200 d7070000
// 00000000 00000000 00000000 2c010000 00000000 c4ffffff 00000b00 00000100
// 02000000 00000000 00000300 00000200 02000000 00000000>; 2441543683 = 30;
// 2442068032 = "2012-07-11 22:30:00 +0000";
// 1073348639 = "OpenChange User";
// 806027522 = <2d64f6f5 89a59243 992d29d1 49173b3a>; 6357056 = "2012-07-11
// 16:30:00 +0000";
// */
// // 0x92490040 = 2454257728
// }
SOGoUser *activeUser;
activeUser = [[self context] activeUser];
[[container event] updateFromMAPIProperties: properties
inUserContext: [self userContext]
withActiveUser: activeUser];
}
@end

View File

@ -35,6 +35,7 @@
#import "MAPIStoreCalendarContext.h"
#import "MAPIStoreCalendarMessage.h"
#import "MAPIStoreCalendarMessageTable.h"
#import "MAPIStoreUserContext.h"
#import "NSString+MAPIStore.h"
#import "MAPIStoreCalendarFolder.h"
@ -67,6 +68,8 @@
newEntry = [SOGoAppointmentObject objectWithName: name
inContainer: sogoObject];
[newEntry setIsNew: YES];
/* the WOContext is required here for resolving notification pages */
[newEntry setContext: [[self userContext] woContext]];
newMessage = [MAPIStoreCalendarMessage mapiStoreObjectWithSOGoObject: newEntry
inContainer: self];

View File

@ -25,11 +25,14 @@
#import "MAPIStoreGCSMessage.h"
@class iCalCalendar;
@class iCalEvent;
@class MAPIStoreAppointmentWrapper;
@interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage
{
MAPIStoreAppointmentWrapper *appointmentWrapper;
iCalCalendar *calendar;
iCalEvent *masterEvent;
}
@end

File diff suppressed because it is too large Load Diff

View File

@ -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"
@ -179,8 +180,8 @@
return MAPISTORE_SUCCESS;
}
- (int) getPidTagSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagNormalizedSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagDisplayName: data inMemCtx: memCtx];
}
@ -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"];

View File

@ -74,10 +74,12 @@ static Class MAPIStoreContactsMessageK, NGMailAddressK, NSDataK, NSStringK;
forKey: MAPIPropertyKey (PidLidEmail2EmailAddress)];
[knownProperties setObject: @"c_mail"
forKey: MAPIPropertyKey (PidLidEmail3EmailAddress)];
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PR_DISPLAY_NAME_UNICODE)];
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PidLidFileUnder)];
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PidTagDisplayName)];
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PidTagSubject)];
}
return [knownProperties objectForKey: MAPIPropertyKey (property)];
@ -213,7 +215,11 @@ static Class MAPIStoreContactsMessageK, NGMailAddressK, NSDataK, NSStringK;
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PidLidFileUnder)];
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PR_DISPLAY_NAME_UNICODE)];
forKey: MAPIPropertyKey (PidTagDisplayName)];
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PidTagSubject)];
[knownProperties setObject: @"c_cn"
forKey: MAPIPropertyKey (PidTagNormalizedSubject)];
}
return [knownProperties objectForKey: MAPIPropertyKey (property)];

View File

@ -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,25 +431,29 @@ 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];
pathComponents = [path componentsSeparatedByString: @"/"];
max = [pathComponents count];
for (count = 0; currentFolder && count < max; count++)
if ([path length] > 0)
{
[woContext setClientObject: currentFolder];
currentFolder
= [currentFolder lookupName: [pathComponents objectAtIndex: count]
inContext: woContext
pathComponents = [path componentsSeparatedByString: @"/"];
max = [pathComponents count];
for (count = 0; currentFolder && count < max; count++)
{
[woContext setClientObject: currentFolder];
currentFolder = [currentFolder
lookupName: [pathComponents objectAtIndex: count]
inContext: woContext
acquire: NO];
if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all
SOGo folder types */
[containersBag addObject: currentFolder];
else
currentFolder = nil;
if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all
SOGo folder types */
[containersBag addObject: currentFolder];
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;
}

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSBaseContext.h - this file is part of SOGo
/* MAPIStoreDBBaseContext.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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 */

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSFolder.h - this file is part of SOGo
/* MAPIStoreDBFolder.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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 */

View File

@ -1,4 +1,4 @@
/* MAPIStoreFSFolder.m - this file is part of SOGo
/* MAPIStoreDBFolder.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
*
@ -24,28 +24,32 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <NGExtensions/NSObject+Logs.h>
#import <EOControl/EOQualifier.h>
#import <SOGo/SOGoFolder.h>
#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 "MAPIStoreMapping.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>
#include <mapistore/mapistore_errors.h>
static Class EOKeyValueQualifierK;
static Class EOKeyValueQualifierK, SOGoMAPIDBFolderK, MAPIStoreDBFolderK;
static NSString *MAPIStoreRightReadItems = @"RightsReadItems";
static NSString *MAPIStoreRightCreateItems = @"RightsCreateItems";
@ -57,54 +61,121 @@ static NSString *MAPIStoreRightCreateSubfolders = @"RightsCreateSubfolders";
static NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner";
static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
@implementation MAPIStoreFSFolder
@implementation MAPIStoreDBFolder
+ (void) initialize
{
EOKeyValueQualifierK = [EOKeyValueQualifier class];
SOGoMAPIDBFolderK = [SOGoMAPIDBFolder class];
MAPIStoreDBFolderK = [MAPIStoreDBFolder 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;
enum mapistore_error rc;
NSString *folderName, *nameInContainer;
SOGoMAPIDBFolder *newFolder;
struct SPropValue *value;
newKey = [NSString stringWithFormat: @"0x%.16"PRIx64, (unsigned long long) newFID];
value = get_SPropValue_SRow (aRow, PidTagDisplayName);
if (value)
folderName = [NSString stringWithUTF8String: value->value.lpszW];
else
{
value = get_SPropValue_SRow (aRow, PidTagDisplayName_string8);
if (value)
folderName = [NSString stringWithUTF8String: value->value.lpszA];
else
folderName = nil;
}
urlString = [NSString stringWithFormat: @"%@/%@", [self url], newKey];
childURL = [NSURL URLWithString: [urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
childFolder = [SOGoMAPIFSFolder folderWithURL: childURL
andTableType: MAPISTORE_MESSAGE_TABLE];
[childFolder ensureDirectory];
*newKeyP = newKey;
if (folderName)
{
nameInContainer = [NSString stringWithFormat: @"0x%.16"PRIx64,
(unsigned long long) newFID];
newFolder = [SOGoMAPIDBFolderK objectWithName: nameInContainer
inContainer: sogoObject];
[newFolder reloadIfNeeded];
[[newFolder properties] setObject: folderName
forKey: MAPIPropertyKey (PidTagDisplayName)];
[newFolder save];
*newKeyP = nameInContainer;
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_INVALID_PARAMETER;
return MAPISTORE_SUCCESS;
return rc;
}
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
{
enum mapistore_error rc;
NSString *path, *pathComponent, *targetPath, *newPath;
NSString *newURL;
MAPIStoreMapping *mapping;
NSRange slashRange;
if ([targetFolder isKindOfClass: MAPIStoreDBFolderK])
{
path = [sogoObject path];
slashRange = [path rangeOfString: @"/" options: NSBackwardsSearch];
if (slashRange.location == NSNotFound)
[NSException raise: @"MAPIStoreIOException"
format: @"db folder path must start with a '/'"];
else
pathComponent = [path substringFromIndex: slashRange.location + 1];
targetPath = [[targetFolder sogoObject] path];
newPath = [NSString stringWithFormat: @"%@/%@",
targetPath, pathComponent];
[dbFolder changePathTo: newPath];
mapping = [self mapping];
newURL = [NSString stringWithFormat: @"%@%@/",
[targetFolder url], pathComponent];
[mapping updateID: [self objectId]
withURL: newURL];
rc = MAPISTORE_SUCCESS;
}
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
- (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];
[fsObject reloadIfNeeded];
newMessage = [MAPIStoreDBMessage mapiStoreObjectWithSOGoObject: fsObject
inContainer: self];
return newMessage;
@ -119,9 +190,10 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
ownerUser = [[self userContext] sogoUser];
if ([[context activeUser] isEqual: ownerUser]
|| [self subscriberCanReadMessages])
keys = [(SOGoMAPIFSFolder *) sogoObject
toOneRelationshipKeysMatchingQualifier: qualifier
andSortOrderings: sortOrderings];
keys = [(SOGoMAPIDBFolder *) sogoObject childKeysOfType: MAPIDBObjectTypeMessage
includeDeleted: NO
matchingQualifier: qualifier
andSortOrderings: sortOrderings];
else
keys = [NSArray array];
@ -131,39 +203,26 @@ 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];
}
/* TODO: now that we are DB-based, this method can easily be implemented
- (NSArray *) getDeletedKeysFromChangeNumber: (uint64_t) changeNum
andCN: (NSNumber **) cnNbrs
inTableType: (enum mapistore_table_type) tableType
{
}
*/
- (NSDate *) lastMessageModificationTime
{
NSUInteger count, max;
NSDate *date, *fileDate;
MAPIStoreFSMessage *msg;
MAPIStoreDBMessage *msg;
NSArray *messageKeys;
messageKeys = [self messageKeys];
@ -189,7 +248,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
- (SOGoFolder *) aclFolder
{
return propsFolder;
return sogoObject;
}
- (NSArray *) rolesForExchangeRights: (uint32_t) rights

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSFolderTable.h - this file is part of SOGo
/* MAPIStoreDBFolderTable.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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 */

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSMessage.h - this file is part of SOGo
/* MAPIStoreDBMessage.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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 */

View File

@ -1,4 +1,4 @@
/* MAPIStoreFSMessage.m - this file is part of SOGo
/* MAPIStoreDBMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
*
@ -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,79 @@
/* 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] >> 16;
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;
}
- (void) addProperties: (NSDictionary *) newNewProperties
{
[sogoObject reloadIfNeeded];
[super addProperties: newNewProperties];
}
- (void) save
{
uint64_t newVersion;
@ -74,15 +141,13 @@
if ([attachmentKeys count] > 0)
[properties setObject: attachmentParts forKey: @"attachments"];
newVersion = exchange_globcnt ([[self context] getNewChangeNumber] >> 16);
newVersion = [[self context] getNewChangeNumber];
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
forKey: @"version"];
forKey: @"version"];
[self logWithFormat: @"%d props in dict", [properties count]];
[sogoObject appendProperties: properties];
[sogoObject save];
[properties removeAllObjects];
}
- (BOOL) _messageIsFreeBusy
@ -91,7 +156,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 +180,12 @@
- (NSDate *) creationTime
{
return [sogoObject creationTime];
return [sogoObject creationDate];
}
- (NSDate *) lastModificationTime
{
return [sogoObject lastModificationTime];
return [sogoObject lastModified];
}
@end

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSMessageTable.h - this file is part of SOGo
/* MAPIStoreDBMessageTable.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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 */

View File

@ -1,6 +1,6 @@
/* MAPIStoreFSMessageTable.m - this file is part of SOGo
/* MAPIStoreDBMessageTable.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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

View File

@ -26,13 +26,6 @@
#import "MAPIStoreMessage.h"
@interface MAPIStoreEmbeddedMessage : MAPIStoreMessage
{
id attachment;
}
+ (id) embeddedMessageWithAttachment: (id) newAttachment;
- (id) initWithAttachment: (id) newAttachment;
@end

View File

@ -23,9 +23,13 @@
#import <Foundation/NSString.h>
#import "MAPIStoreAttachment.h"
#import "MAPIStoreFolder.h"
#import "NSObject+MAPIStore.h"
#import "MAPIStoreEmbeddedMessage.h"
#include <mapistore/mapistore_errors.h>
static Class MAPIStoreAttachmentK;
@implementation MAPIStoreEmbeddedMessage
@ -35,30 +39,116 @@ static Class MAPIStoreAttachmentK;
MAPIStoreAttachmentK = [MAPIStoreAttachment class];
}
+ (id) embeddedMessageWithAttachment: (id) newAttachment
- (uint64_t) objectId
{
MAPIStoreEmbeddedMessage *newMessage;
NSString *objectKey;
MAPIStoreMessage *grandParent;
newMessage = [[self alloc] initWithAttachment: newAttachment];
[newMessage autorelease];
grandParent = (MAPIStoreMessage *) [container container];
return newMessage;
/* FIXME: this is a hack */
objectKey = [NSString stringWithFormat: @"%@/%@/as-message",
[grandParent nameInContainer],
[container nameInContainer],
[self nameInContainer]];
return [(MAPIStoreFolder *) [grandParent container]
idForObjectWithKey: objectKey];
}
- (id) initWithAttachment: (id) newAttachment
- (int) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
if ((self = [self init]))
{
if ([newAttachment isKindOfClass: MAPIStoreAttachmentK])
ASSIGN (container, newAttachment);
}
return self;
return [self getLongZero: data inMemCtx: memCtx];
}
/* disabled properties */
- (int) getPidTagFolderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagChangeNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagInstID: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagInstanceNum: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagRowType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagDepth: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagIconIndex: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagOriginalMessageClass: (void **) dataa
inMemCtx: (TALLOC_CTX *) memCtx
{
return MAPISTORE_ERR_NOT_FOUND;
}
/* common methods */
- (NSString *) nameInContainer
{
return @"as-message";
}
- (uint64_t) objectVersion
{
return ULLONG_MAX;
}
- (void) save
{
[self subclassResponsibility: _cmd];
}
@end

View File

@ -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 */

View File

@ -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 */

View File

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

View File

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

View File

@ -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++)

View File

@ -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;
@ -118,6 +123,12 @@
andChangeKeys: (struct Binary_r **) targetChangeKeys
wantCopy: (uint8_t) want_copy;
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName;
- (enum mapistore_error) copyToFolder: (MAPIStoreFolder *) targetFolder
recursive: (BOOL) resursive
withNewName: (NSString *) newFolderName;
- (int) getDeletedFMIDs: (struct I8Array_r **) fmidsPtr
andCN: (uint64_t *) cnPtr
fromChangeNumber: (uint64_t) changeNum

View File

@ -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
forKey: MAPIPropertyKey (PidTagChangeNumber)];
[propsMessage appendProperties: props];
[propsMessage save];
[properties setObject: value
forKey: MAPIPropertyKey (PidTagChangeNumber)];
[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])
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder
inContainer: self];
{
[sogoFolder setContext: woContext];
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder
inContainer: self];
}
}
else
childFolder = nil;
return childFolder;
}
@ -264,9 +303,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
{
if ([[self faiMessageKeys] containsObject: messageKey])
{
msgObject = [faiFolder lookupName: messageKey
inContext: nil
acquire: NO];
msgObject = [dbFolder lookupName: messageKey
inContext: nil
acquire: NO];
childMessage
= [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: msgObject
inContainer: self];
@ -360,7 +399,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
baseURL = [self url];
if (![baseURL hasSuffix: @"/"])
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
childURL = [NSString stringWithFormat: @"%@%@",
childURL = [NSString stringWithFormat: @"%@%@/",
baseURL, folderKey];
[mapping registerURL: childURL withID: fid];
childFolder = [self lookupFolder: folderKey];
@ -383,9 +422,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (int) deleteFolder
{
[propsMessage delete];
[propsFolder delete];
[faiFolder delete];
// [propsMessage delete];
[dbFolder delete];
[self cleanupCaches];
@ -757,6 +795,19 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
return rc;
}
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
{
return MAPISTORE_ERR_DENIED;
}
- (enum mapistore_error) copyToFolder: (MAPIStoreFolder *) targetFolder
recursive: (BOOL) resursive
withNewName: (NSString *) newFolderName
{
return MAPISTORE_ERR_DENIED;
}
- (SOGoFolder *) aclFolder
{
[self subclassResponsibility: _cmd];
@ -1004,7 +1055,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 +1067,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
currentProp++;
}
[propsMessage appendProperties: propsCopy];
[propsMessage save];
[propsCopy release];
[properties addEntriesFromDictionary: propsCopy];
[dbFolder save];
}
- (NSArray *) messageKeys
@ -1039,9 +1093,10 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings
{
return [faiFolder
toOneRelationshipKeysMatchingQualifier: qualifier
andSortOrderings: sortOrderings];
return [dbFolder childKeysOfType: MAPIDBObjectTypeFAI
includeDeleted: NO
matchingQualifier: qualifier
andSortOrderings: sortOrderings];
}
- (NSArray *) faiMessageKeys
@ -1287,6 +1342,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 +1362,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 +1374,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,9 +1397,15 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
newMessage = [self _createAssociatedMessage];
else
newMessage = [self createMessage];
[newMessage setIsNew: YES];
/* FIXME: this is ugly as the specifics of message creation should all be
delegated to subclasses */
if ([newMessage respondsToSelector: @selector (setIsNew:)])
[newMessage setIsNew: YES];
woContext = [[self userContext] woContext];
[[newMessage sogoObject] setContext: woContext];
/* FIXME: this is ugly too as the specifics of message creation should all
be delegated to subclasses */
if ([newMessage respondsToSelector: @selector (sogoObject:)])
[[newMessage sogoObject] setContext: woContext];
return newMessage;
}
@ -1581,9 +1656,14 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (uint64_t) objectId
{
uint64_t objectId;
NSString *folderKey;
if (container)
objectId = [super objectId];
{
folderKey = [NSString stringWithFormat: @"%@/",
[sogoObject nameInContainer]];
objectId = [container idForObjectWithKey: folderKey];
}
else
objectId = [self idForObjectWithKey: nil];
@ -1598,12 +1678,12 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (NSDate *) creationTime
{
return [propsMessage creationTime];
return [dbFolder creationDate];
}
- (NSDate *) lastModificationTime
{
return [propsMessage lastModificationTime];
return [dbFolder lastModified];
}
/* subclasses */

View File

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

View File

@ -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];
}
}

View File

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

View File

@ -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;
}

View File

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

View File

@ -54,14 +54,14 @@
#import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "SOGoMAPIFSMessage.h"
#import "SOGoMAPIDBMessage.h"
#import "SOGoMAPIDBFolder.h"
#import "SOGoMAPIVolatileMessage.h"
#import "MAPIStoreMailVolatileMessage.h"
#import "MAPIStoreMailFolder.h"
static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
#undef DEBUG
#include <util/attr.h>
@ -74,6 +74,7 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
+ (void) initialize
{
SOGoMailFolderK = [SOGoMailFolder class];
MAPIStoreMailFolderK = [MAPIStoreMailFolder class];
MAPIStoreOutboxFolderK = [MAPIStoreOutboxFolder class];
[MAPIStoreAppointmentWrapper class];
}
@ -97,8 +98,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 +121,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];
@ -393,6 +398,11 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
return permissionEntries;
}
- (BOOL) supportsSubFolders
{
return YES;
}
/* synchronisation */
/* Tree:
@ -489,10 +499,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 +621,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]];
[currentProperties setObject: ti
forKey: @"SyncLastSynchronisationDate"];
[versionsMessage appendProperties: currentProperties];
[versionsMessage save];
}
@ -1002,21 +1009,65 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
return MAPISTORE_SUCCESS;
}
- (MAPIStoreMessage *) createMessage
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
{
MAPIStoreMailVolatileMessage *newMessage;
SOGoMAPIVolatileMessage *newObject;
enum mapistore_error rc;
NSURL *folderURL, *newFolderURL;
SOGoMailFolder *targetSOGoFolder;
NSString *newURL, *parentDBFolderPath;
NSException *error;
MAPIStoreMapping *mapping;
newObject = [SOGoMAPIVolatileMessage
objectWithName: [SOGoObject globallyUniqueObjectId]
inContainer: sogoObject];
newMessage
= [MAPIStoreMailVolatileMessage mapiStoreObjectWithSOGoObject: newObject
inContainer: self];
return newMessage;
if ([targetFolder isKindOfClass: MAPIStoreMailFolderK])
{
folderURL = [sogoObject imap4URL];
if (!newFolderName)
newFolderName = [[sogoObject nameInContainer]
substringFromIndex: 6]; /* length of "folder" */
newFolderName = [newFolderName stringByEscapingURL];
targetSOGoFolder = [targetFolder sogoObject];
newFolderURL = [NSURL URLWithString: newFolderName
relativeToURL: [targetSOGoFolder imap4URL]];
error = [[sogoObject imap4Connection]
moveMailboxAtURL: folderURL
toURL: newFolderURL];
if (error)
rc = MAPISTORE_ERR_DENIED;
else
{
rc = MAPISTORE_SUCCESS;
mapping = [self mapping];
newURL = [NSString stringWithFormat: @"%@folder%@/",
[targetFolder url], newFolderName];
[mapping updateID: [self objectId]
withURL: newURL];
parentDBFolderPath = [[targetFolder dbFolder] path];
if (!parentDBFolderPath)
parentDBFolderPath = @"";
[dbFolder changePathTo: [NSString stringWithFormat:
@"%@/folder%@",
parentDBFolderPath,
newFolderName]];
}
}
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
- (MAPIStoreMessage *) createMessage
{
SOGoMAPIObject *childObject;
childObject = [SOGoMAPIObject objectWithName: [SOGoMAPIObject
globallyUniqueObjectId]
inContainer: sogoObject];
return [MAPIStoreMailVolatileMessage
mapiStoreObjectWithSOGoObject: childObject
inContainer: self];
}
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
{
@ -1043,8 +1094,6 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
[roles addObject: SOGoRole_ObjectViewer];
if (rights & RightsCreateSubfolders)
[roles addObject: SOGoRole_FolderCreator];
if (rights & RightsCreateSubfolders)
[roles addObject: SOGoRole_FolderCreator];
// [self logWithFormat: @"roles for rights %.8x = (%@)", rights, roles];
@ -1069,8 +1118,6 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
rights |= RightsReadItems;
if ([roles containsObject: SOGoRole_FolderCreator])
rights |= RightsCreateSubfolders;
if ([roles containsObject: SOGoRole_FolderCreator])
rights |= RightsCreateSubfolders;
if (rights != 0)
rights |= RoleNone; /* actually "folder visible" */

View File

@ -373,7 +373,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
if (uid)
{
changeNumber = [(MAPIStoreMailFolder *) container
changeNumberForMessageUID: uid];
changeNumberForMessageUID: uid];
if (!changeNumber)
{
[self warnWithFormat: @"attempting to get change number"
@ -448,19 +448,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
return MAPISTORE_SUCCESS;
}
- (int) getPidTagSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *stringValue;
stringValue = [self subject];
if (!stringValue)
stringValue = @"";
*data = [stringValue asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagSubjectPrefix: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -1529,8 +1516,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]];
}

View File

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

View File

@ -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;

View File

@ -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,85 @@ 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) 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;
}
- (NSDate *) creationTime
{
return [sogoObject creationDate];
}
- (NSDate *) lastModificationTime
{
return [sogoObject lastModified];
}
- (id) lookupAttachment: (NSString *) childKey
{
return [attachmentParts objectForKey: childKey];
}
- (void) getMessageData: (struct mapistore_message **) dataPtr
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -258,9 +340,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,9 +744,11 @@ 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, NSDictionary *attachmentParts, NSString **contentType)
{
id messageBody, textBody;
NSString *textContentType;
@ -707,22 +793,19 @@ 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, attachmentParts, &contentType);
if (messageBody)
{
[headers setObject: contentType forKey: @"content-type"];
@ -775,7 +858,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
- (int) submitWithFlags: (enum SubmitFlags) flags
{
NSDictionary *mailProperties, *recipients;
NSDictionary *recipients;
NSData *messageData;
NSMutableArray *recipientEmails;
NSArray *list;
@ -785,19 +868,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 +900,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,7 +915,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
- (void) save
{
NSString *folderName, *flag, *newIdString;
NSString *folderName, *flag, *newIdString, *messageKey;
NSData *changeKey, *messageData;
NGImap4Connection *connection;
NGImap4Client *client;
@ -858,23 +939,27 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
responseResult = [[result objectForKey: @"RawResponse"]
objectForKey: @"ResponseResult"];
flag = [responseResult objectForKey: @"flag"];
newIdString = [[flag componentsSeparatedByString: @" "]
objectAtIndex: 2];
mid = [self objectId];
mapping = [self mapping];
mid = [self objectId];
[mapping unregisterURLWithID: mid];
[sogoObject setNameInContainer: [NSString stringWithFormat: @"%@.eml", newIdString]];
[mapping registerURL: [self url] withID: mid];
}
// [sogoObject setNameInContainer: ];
/* 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)];
if (changeKey)
[(MAPIStoreMailFolder *) container
setChangeKey: changeKey forMessageWithKey: [self nameInContainer]];
messageKey = [NSString stringWithFormat: @"%@.eml", newIdString];
[sogoObject setNameInContainer: messageKey];
[mapping registerURL: [self url] withID: mid];
/* synchronise the cache and update the change key with the one provided
by the client */
[(MAPIStoreMailFolder *) container synchroniseCache];
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
if (changeKey)
[(MAPIStoreMailFolder *) container
setChangeKey: changeKey
forMessageWithKey: messageKey];
}
}
@end

View File

@ -54,6 +54,8 @@
- (BOOL) registerURL: (NSString *) urlString
withID: (uint64_t) idNbr;
- (void) unregisterURLWithID: (uint64_t) idNbr;
- (void) updateID: (uint64_t) idNbr
withURL: (NSString *) urlString;
@end

View File

@ -30,6 +30,8 @@
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/NSString+Utilities.h>
#import "MAPIStoreTypes.h"
#import "MAPIStoreMapping.h"
@ -204,6 +206,87 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
return idNbr;
}
- (void) _updateFolderWithURL: (NSString *) oldURL
withURL: (NSString *) urlString
{
NSArray *allKeys;
NSUInteger count, max;
NSString *currentKey, *newKey;
NSNumber *idKey;
TDB_DATA key, dbuf;
allKeys = [reverseMapping allKeys];
max = [allKeys count];
for (count = 0; count < max; count++)
{
currentKey = [allKeys objectAtIndex: count];
if ([currentKey hasPrefix: oldURL])
{
newKey = [currentKey stringByReplacingPrefix: oldURL
withPrefix: urlString];
idKey = [reverseMapping objectForKey: currentKey];
[mapping setObject: newKey forKey: idKey];
[reverseMapping setObject: idKey forKey: newKey];
[reverseMapping removeObjectForKey: currentKey];
/* update the record in the indexing database */
key.dptr = (unsigned char *) talloc_asprintf (NULL, "0x%.16"PRIx64,
(uint64_t) [idKey unsignedLongLongValue]);
key.dsize = strlen ((const char *) key.dptr);
dbuf.dptr = (unsigned char *) talloc_strdup (NULL,
[newKey UTF8String]);
dbuf.dsize = strlen ((const char *) dbuf.dptr);
tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY);
talloc_free (key.dptr);
talloc_free (dbuf.dptr);
}
}
}
- (void) updateID: (uint64_t) idNbr
withURL: (NSString *) urlString
{
NSString *oldURL;
NSNumber *idKey;
TDB_DATA key, dbuf;
idKey = [NSNumber numberWithUnsignedLongLong: idNbr];
oldURL = [mapping objectForKey: idKey];
if (oldURL)
{
if ([oldURL hasSuffix: @"/"]) /* is container ? */
{
if (![urlString hasSuffix: @"/"])
[NSException raise: NSInvalidArgumentException
format: @"a container url must have an ending '/'"];
tdb_transaction_start (indexing->tdb);
[self _updateFolderWithURL: oldURL withURL: urlString];
tdb_transaction_commit (indexing->tdb);
}
else
{
if ([urlString hasSuffix: @"/"])
[NSException raise: NSInvalidArgumentException
format: @"a leaf url must not have an ending '/'"];
[mapping setObject: urlString forKey: idKey];
[reverseMapping setObject: idKey forKey: urlString];
[reverseMapping removeObjectForKey: oldURL];
/* update the record in the indexing database */
key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr);
key.dsize = strlen((const char *) key.dptr);
dbuf.dptr = (unsigned char *) talloc_strdup (NULL, [urlString UTF8String]);
dbuf.dsize = strlen((const char *) dbuf.dptr);
tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY);
talloc_free (key.dptr);
talloc_free (dbuf.dptr);
}
}
}
- (BOOL) registerURL: (NSString *) urlString
withID: (uint64_t) idNbr
{

View File

@ -35,9 +35,9 @@
@class MAPIStoreAttachmentTable;
@class MAPIStoreFolder;
#import "MAPIStoreObject.h"
#import "MAPIStoreSOGoObject.h"
@interface MAPIStoreMessage : MAPIStoreObject
@interface MAPIStoreMessage : MAPIStoreSOGoObject
{
NSArray *attachmentKeys;
NSMutableDictionary *attachmentParts;
@ -66,9 +66,6 @@
- (int) setReadFlag: (uint8_t) flag;
- (enum mapistore_error) saveMessage;
/* helper getters */
- (int) getSMTPAddrType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (NSArray *) activeContainerMessageTables;
- (NSArray *) activeUserRoles;

View File

@ -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"
@ -55,6 +56,7 @@
#include <mapistore/mapistore_errors.h>
static NSString *resourcesDir = nil;
static Class MAPIStoreFolderK = nil;
/* rtf conversion via unrtf */
static int
@ -116,7 +118,6 @@ rtf2html (NSData *compressedRTF)
@interface SOGoObject (MAPIStoreProtocol)
- (NSString *) davEntityTag;
- (NSString *) davContentLength;
@end
@ -130,6 +131,7 @@ rtf2html (NSData *compressedRTF)
resourcesDir = [[NSBundle bundleForClass: self] resourcePath];
[resourcesDir retain];
}
MAPIStoreFolderK = [MAPIStoreFolder class];
}
- (id) init
@ -304,6 +306,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 +342,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
@ -443,62 +444,73 @@ rtf2html (NSData *compressedRTF)
|| (!isNew && [self subscriberCanModifyMessage])))
{
/* notifications */
folderId = [(MAPIStoreFolder *) container objectId];
mstoreCtx = [[self context] connectionInfo]->mstore_ctx;
/* folder modified */
notif_parameters
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
notif_parameters->object_id = folderId;
if (isNew)
if ([container isKindOfClass: MAPIStoreFolderK])
{
notif_parameters->tag_count = 3;
notif_parameters->tags = talloc_array (notif_parameters,
enum MAPITAGS, 3);
notif_parameters->tags[0] = PR_CONTENT_COUNT;
notif_parameters->tags[1] = PR_MESSAGE_SIZE;
notif_parameters->tags[2] = PR_NORMAL_MESSAGE_SIZE;
notif_parameters->new_message_count = true;
notif_parameters->message_count
= [[(MAPIStoreFolder *) container messageKeys] count] + 1;
}
mapistore_push_notification (mstoreCtx,
MAPISTORE_FOLDER, MAPISTORE_OBJECT_MODIFIED,
notif_parameters);
talloc_free (notif_parameters);
folderId = [(MAPIStoreFolder *) container objectId];
mstoreCtx = [[self context] connectionInfo]->mstore_ctx;
/* message created */
if (isNew)
{
/* folder modified */
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->folder_id = folderId;
notif_parameters->tag_count = 0xffff;
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
notif_parameters->object_id = folderId;
if (isNew)
{
notif_parameters->tag_count = 3;
notif_parameters->tags = talloc_array (notif_parameters,
enum MAPITAGS, 3);
notif_parameters->tags[0] = PR_CONTENT_COUNT;
notif_parameters->tags[1] = PR_MESSAGE_SIZE;
notif_parameters->tags[2] = PR_NORMAL_MESSAGE_SIZE;
notif_parameters->new_message_count = true;
notif_parameters->message_count
= [[(MAPIStoreFolder *) container messageKeys] count] + 1;
}
mapistore_push_notification (mstoreCtx,
MAPISTORE_MESSAGE, MAPISTORE_OBJECT_CREATED,
MAPISTORE_FOLDER,
MAPISTORE_OBJECT_MODIFIED,
notif_parameters);
talloc_free (notif_parameters);
}
/* we ensure the table caches are loaded so that old and new state
can be compared */
containerTables = [self activeContainerMessageTables];
max = [containerTables count];
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count] restrictedChildKeys];
/* message created */
if (isNew)
{
notif_parameters
= talloc_zero(NULL,
struct mapistore_object_notification_parameters);
notif_parameters->object_id = [self objectId];
notif_parameters->folder_id = folderId;
notif_parameters->tag_count = 0xffff;
mapistore_push_notification (mstoreCtx,
MAPISTORE_MESSAGE, MAPISTORE_OBJECT_CREATED,
notif_parameters);
talloc_free (notif_parameters);
}
/* we ensure the table caches are loaded so that old and new state
can be compared */
containerTables = [self activeContainerMessageTables];
max = [containerTables count];
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count] restrictedChildKeys];
}
[self save];
/* We make sure that any change-related properties are removes from the
properties dictionary, to make sure that related methods will be
invoked the next time they are requested. */
[properties removeObjectForKey: MAPIPropertyKey (PidTagChangeKey)];
[properties removeObjectForKey: MAPIPropertyKey (PidTagChangeNumber)];
/* table modified */
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count]
notifyChangesForChild: self];
if ([container isKindOfClass: MAPIStoreFolderK])
{
/* table modified */
for (count = 0; count < max; count++)
[[containerTables objectAtIndex: count]
notifyChangesForChild: self];
[container cleanupCaches];
}
[self setIsNew: NO];
[properties removeAllObjects];
[container cleanupCaches];
rc = MAPISTORE_SUCCESS;
}
else
@ -507,14 +519,6 @@ rtf2html (NSData *compressedRTF)
return rc;
}
/* helper getters */
- (int) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"SMTP" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
/* getters */
- (int) getPidTagInstID: (void **) data // TODO: DOUBT
inMemCtx: (TALLOC_CTX *) memCtx
@ -615,7 +619,8 @@ rtf2html (NSData *compressedRTF)
- (int) getPidLidCurrentVersion: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 115608); // Outlook 11.5608
// *data = MAPILongValue (memCtx, 115608); // Outlook 11.5608
*data = MAPILongValue (memCtx, 0x1ce3a); // Outlook 11.8330
return MAPISTORE_SUCCESS;
}
@ -655,9 +660,19 @@ rtf2html (NSData *compressedRTF)
- (int) getPidTagMid: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongLongValue (memCtx, [self objectId]);
int rc;
uint64_t obId;
return MAPISTORE_SUCCESS;
obId = [self objectId];
if (obId == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
{
*data = MAPILongLongValue (memCtx, obId);
rc = MAPISTORE_SUCCESS;
}
return rc;
}
- (int) getPidTagMessageLocaleId: (void **) data
@ -708,21 +723,35 @@ rtf2html (NSData *compressedRTF)
- (int) getPidTagSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
[self subclassResponsibility: _cmd];
int rc;
TALLOC_CTX *localMemCtx;
char *prefix, *normalizedSubject;
return MAPISTORE_ERR_NOT_FOUND;
localMemCtx = talloc_zero (NULL, TALLOC_CTX);
if ([self getProperty: (void **) &prefix
withTag: PidTagSubjectPrefix
inMemCtx: localMemCtx]
!= MAPISTORE_SUCCESS)
prefix = "";
rc = [self getProperty: (void **) &normalizedSubject
withTag: PidTagNormalizedSubject
inMemCtx: localMemCtx];
if (rc == MAPISTORE_SUCCESS)
*data = talloc_asprintf (memCtx, "%s%s", prefix, normalizedSubject);
return rc;
}
- (int) getPidTagNormalizedSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagSubject: data inMemCtx: memCtx];
return MAPISTORE_ERR_NOT_FOUND;
}
- (int) getPidTagOriginalSubject: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagNormalizedSubject: data inMemCtx: memCtx];
return [self getPidTagSubject: data inMemCtx: memCtx];
}
- (int) getPidTagConversationTopic: (void **) data
@ -792,7 +821,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

View File

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

View File

@ -27,7 +27,9 @@
#import <SOGo/SOGoFolder.h>
#import <SOGo/SOGoObject.h>
#import "MAPIStoreContext.h"
#import "MAPIStoreFolder.h"
#import "MAPIStoreMessage.h"
#import "MAPIStoreTypes.h"
#import "NSData+MAPIStore.h"
#import "NSString+MAPIStore.h"
@ -83,4 +85,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,
&notif_parameters);
}
}
else
{
if (newChildRow == NSNotFound)
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_DELETED,
&notif_parameters);
else
{
/* the fact that the row order has changed has no impact here */
notif_parameters.row_id = newChildRow;
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_MODIFIED,
&notif_parameters);
}
}
}
@end

View File

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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -33,60 +33,41 @@
@class NSMutableArray;
@class NSMutableDictionary;
@class EOQualifier;
@class MAPIStoreContext;
@class MAPIStoreFolder;
@class MAPIStoreMapping;
@class MAPIStoreTable;
@class MAPIStoreObjectProxy;
@class MAPIStoreUserContext;
@class MAPIStoreSOGoObject;
@interface MAPIStoreObject : NSObject
{
const IMP *classGetters;
NSMutableArray *parentContainersBag;
MAPIStoreObject *container;
id sogoObject;
NSMutableArray *proxies;
id container;
NSMutableDictionary *properties;
BOOL isNew;
}
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newContainer;
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx;
+ (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer;
- (id) initInContainer: (MAPIStoreObject *) newContainer;
- (id) initWithSOGoObject: (id) newSOGoObject
inContainer: (MAPIStoreObject *) newFolder;
- (void) addProxy: (MAPIStoreObjectProxy *) newProxy;
- (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
inMemCtx: (TALLOC_CTX *) localMemCtx;
- (int) getProperties: (struct mapistore_property_data *) data
withTags: (enum MAPITAGS *) tags
andCount: (uint16_t) columnCount
@ -104,26 +85,13 @@
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;
- (NSString *) nameInContainer;
- (NSDate *) creationTime;
- (NSDate *) lastModificationTime;

View File

@ -58,47 +58,16 @@ 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;
}
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
struct SPropTagArray *properties;
const MAPIStorePropertyGetter *classGetters;
NSUInteger count;
enum MAPITAGS propTag;
uint16_t propValue;
properties = talloc_zero (memCtx, struct SPropTagArray);
properties->aulPropTag = talloc_array (properties, enum MAPITAGS,
MAPIStoreSupportedPropertiesCount);
classGetters = MAPIStorePropertyGettersForClass (self);
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
{
propTag = MAPIStoreSupportedProperties[count];
propValue = (propTag & 0xffff0000) >> 16;
if (classGetters[propValue])
{
properties->aulPropTag[properties->cValues] = propTag;
properties->cValues++;
}
}
*propertiesP = properties;
return MAPISTORE_SUCCESS;
}
- (id) init
{
if ((self = [super init]))
@ -106,22 +75,19 @@ static Class NSExceptionK, MAPIStoreFolderK;
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
parentContainersBag = [NSMutableArray new];
container = nil;
sogoObject = nil;
properties = [NSMutableDictionary new];
isNew = NO;
proxies = [NSMutableArray new];
}
[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 +96,22 @@ static Class NSExceptionK, MAPIStoreFolderK;
- (void) dealloc
{
[self logWithFormat: @"-dealloc"];
[sogoObject release];
// [self logWithFormat: @"-dealloc"];
[proxies release];
[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,32 +124,11 @@ 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];
containerURL = (NSString *) [container url];
if ([containerURL hasSuffix: @"/"])
format = @"%@%@";
else
@ -213,12 +138,14 @@ static Class NSExceptionK, MAPIStoreFolderK;
containerURL, [self nameInContainer]];
}
/* helpers */
- (void) addProperties: (NSDictionary *) newNewProperties
{
[properties addEntriesFromDictionary: newNewProperties];
}
- (NSDictionary *) properties
- (NSMutableDictionary *) properties
{
return properties;
}
@ -232,6 +159,7 @@ static Class NSExceptionK, MAPIStoreFolderK;
SEL methodSel;
id value;
int rc = MAPISTORE_ERR_NOT_FOUND;
NSUInteger count, max;
value = [properties objectForKey: MAPIPropertyKey (propTag)];
if (value)
@ -245,127 +173,21 @@ static Class NSExceptionK, MAPIStoreFolderK;
rc = method (self, methodSel, data, memCtx);
}
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++)
if (rc == MAPISTORE_ERR_NOT_FOUND)
{
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;
max = [proxies count];
for (count = 0; rc == MAPISTORE_ERR_NOT_FOUND && count < max; count++)
rc = [[proxies objectAtIndex: count]
getProperty: data
withTag: propTag
inMemCtx: memCtx];
}
return rc;
}
- (int) getPidTagCreationTime: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[self creationTime] asFileTimeInMemCtx: memCtx];
@ -380,39 +202,21 @@ static Class NSExceptionK, MAPIStoreFolderK;
return MAPISTORE_SUCCESS;
}
- (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
NSUInteger count;
struct SPropTagArray *availableProps;
enum MAPITAGS propTag;
availableProps = talloc_zero (memCtx, struct SPropTagArray);
availableProps->aulPropTag = talloc_array (availableProps, enum MAPITAGS,
MAPIStoreSupportedPropertiesCount);
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
{
propTag = MAPIStoreSupportedProperties[count];
if ([self canGetProperty: propTag])
{
availableProps->aulPropTag[availableProps->cValues] = propTag;
availableProps->cValues++;
}
}
*propertiesP = availableProps;
return MAPISTORE_SUCCESS;
}
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
{
uint16_t propValue;
BOOL canGetProperty;
NSUInteger count, max;
propValue = (propTag & 0xffff0000) >> 16;
return (classGetters[propValue]
|| [properties objectForKey: MAPIPropertyKey (propTag)]);
canGetProperty = (classGetters[propValue]
|| [properties objectForKey: MAPIPropertyKey (propTag)]);
max = [proxies count];
for (count = 0; !canGetProperty && count < max; count++)
canGetProperty = [[proxies objectAtIndex: count] canGetProperty: propTag];
return canGetProperty;
}
- (int) getProperties: (struct mapistore_property_data *) data
@ -430,6 +234,11 @@ static Class NSExceptionK, MAPIStoreFolderK;
return MAPISTORE_SUCCESS;
}
- (void) addProxy: (MAPIStoreObjectProxy *) newProxy
{
[proxies addObject: newProxy];
}
- (int) addPropertiesFromRow: (struct SRow *) aRow
{
struct SPropValue *cValue;
@ -474,7 +283,46 @@ 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 */
- (NSString *) nameInContainer
{
[self subclassResponsibility: _cmd];
return nil;
}
- (NSDate *) creationTime
{
[self subclassResponsibility: _cmd];

View File

@ -0,0 +1,41 @@
/* MAPIStoreObjectProxy.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 MAPISTOREOBJECTPROXY_H
#define MAPISTOREOBJECTPROXY_H
#include <talloc.h>
#import <Foundation/NSObject.h>
@interface MAPIStoreObjectProxy : NSObject
{
const IMP *classGetters;
}
- (enum mapistore_error) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) localMemCtx;
@end
#endif /* MAPISTOREOBJECTPROXY_H */

View File

@ -0,0 +1,67 @@
/* MAPIStoreObjectProxy.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 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.
*/
#import "MAPIStorePropertySelectors.h"
#import "NSString+MAPIStore.h"
#import "MAPIStoreObjectProxy.h"
#undef DEBUG
#include <stdbool.h>
#include <talloc.h>
#include <gen_ndr/exchange.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
@implementation MAPIStoreObjectProxy
- (id) init
{
if ((self = [super init]))
{
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
}
return self;
}
- (enum mapistore_error) getProperty: (void **) data
withTag: (enum MAPITAGS) propTag
inMemCtx: (TALLOC_CTX *) memCtx
{
MAPIStorePropertyGetter method;
uint16_t propValue;
SEL methodSel;
int rc;
propValue = (propTag & 0xffff0000) >> 16;
methodSel = MAPIStoreSelectorForPropertyGetter (propValue);
method = (MAPIStorePropertyGetter) classGetters[propValue];
if (method)
rc = method (self, methodSel, data, memCtx);
else
rc = MAPISTORE_ERR_NOT_FOUND;
return rc;
}
@end

View File

@ -23,7 +23,6 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <SOGo/SOGoFolder.h>
#import <SOGo/SOGoObject.h>
#import <SOGo/SOGoUser.h>
@ -50,7 +49,7 @@
MAPIStorePermissionEntry *newEntry;
newEntry = [[self alloc] initWithUserId: newUserId andMemberId: newMemberId
forFolder: newFolder];
forFolder: newFolder];
[newEntry autorelease];
return newEntry;
@ -60,7 +59,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;
@ -103,7 +102,7 @@
entryId = [NSData data];
else
{
connInfo = [[container context] connectionInfo];
connInfo = [(MAPIStoreContext *) [container context] connectionInfo];
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, userId);
}
*data = [entryId asBinaryInMemCtx: memCtx];

View File

@ -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

View File

@ -21,17 +21,23 @@
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSSet.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,13 +49,15 @@
- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity
fromRecurrencePattern: (struct RecurrencePattern *) rp
{
NSCalendarDate *startDate, *olEndDate, *untilDate;
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
NSString *monthDay, *month;
NSMutableSet *exceptionDates;
NSArray *realExDates;
iCalRecurrenceRule *rule;
iCalByDayMask *byDayMask;
iCalWeekOccurrence weekOccurrence;
iCalWeekOccurrences dayMaskDays;
NSUInteger count;
NSUInteger count, max;
NSInteger bySetPos;
unsigned char maskValue;
@ -203,6 +211,37 @@
[self errorWithFormat: @"invalid value for EndType: %.4x",
rp->EndType];
}
/* exception dates:
- take all deleted instances
- remove all modified instances from the above set
- add remaining instances, in chronological order
*/
exceptionDates = [NSMutableSet set];
for (count = 0; count < rp->DeletedInstanceCount; count++)
{
exDate
= [NSDate dateFromMinutesSince1601: rp->DeletedInstanceDates[count]];
exDate = [exDate hour: [startDate hourOfDay]
minute: [startDate minuteOfHour]
second: [startDate secondOfMinute]];
[exceptionDates addObject: exDate];
}
for (count = 0; count < rp->ModifiedInstanceCount; count++)
{
exDate
= [NSDate dateFromMinutesSince1601: rp->ModifiedInstanceDates[count]];
exDate = [exDate hour: [startDate hourOfDay]
minute: [startDate minuteOfHour]
second: [startDate secondOfMinute]];
[exceptionDates removeObject: exDate];
}
realExDates = [[exceptionDates allObjects]
sortedArrayUsingSelector: @selector (compare:)];
max = [realExDates count];
for (count = 0; count < max; count++)
[entity addToExceptionDates: [realExDates objectAtIndex: count]];
}
@end
@ -210,17 +249,27 @@
@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 *events;
NSMutableArray *deletedDates, *modifiedDates;
startDate = [event firstRecurrenceStartDate];
[startDate setTimeZone: timeZone];
endDate = [event lastPossibleRecurrenceStartDate];
[endDate setTimeZone: timeZone];
rp->ReaderVersion = 0x3004;
rp->WriterVersion = 0x3004;
@ -244,6 +293,7 @@
else
{
rp->EndDate = 0x5ae980df;
rp->OccurrenceCount = 0xa;
rp->EndType = END_NEVER_END;
}
}
@ -370,6 +420,43 @@
[self errorWithFormat: @"rule for an event that never occurs"];
}
}
events = [[event parent] events];
max = [events count];
modifiedDates = [NSMutableArray arrayWithCapacity: max];
for (count = 1; count < max; count++)
{
startDate = [[events objectAtIndex: count] recurrenceId];
if (startDate)
[modifiedDates addObject: startDate];
else
[self errorWithFormat: @"missing recurrence-id for event %d", count];
}
max = [modifiedDates count];
rp->ModifiedInstanceCount = max;
rp->ModifiedInstanceDates = talloc_array (memCtx, uint32_t, max);
for (count = 0; count < max; count++)
{
startDate = [[modifiedDates objectAtIndex: count]
hour: 0 minute: 0 second: 0];
*(rp->ModifiedInstanceDates + count) = [startDate asMinutesSince1601];
}
deletedDates = [modifiedDates mutableCopy];
[deletedDates autorelease];
[deletedDates
addObjectsFromArray: [event exceptionDatesWithTimeZone: utcTZ]];
[deletedDates sortUsingFunction: NSDateCompare context: NULL];
max = [deletedDates count];
rp->DeletedInstanceCount = max;
rp->DeletedInstanceDates = talloc_array (memCtx, uint32_t, max);
for (count = 0; count < max; count++)
{
startDate = [[deletedDates objectAtIndex: count]
hour: 0 minute: 0 second: 0];
*(rp->DeletedInstanceDates + count) = [startDate asMinutesSince1601];
}
}
@end

View File

@ -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];
@ -608,6 +608,86 @@ sogo_folder_move_copy_messages(void *folder_object,
return rc;
}
static enum mapistore_error
sogo_folder_move_folder(void *folder_object, void *target_folder_object,
const char *new_folder_name)
{
NSAutoreleasePool *pool;
MAPIStoreFolder *moveFolder, *targetFolder;
NSString *newFolderName;
struct MAPIStoreTallocWrapper *wrapper;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
moveFolder = wrapper->instance;
wrapper = target_folder_object;
targetFolder = wrapper->instance;
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
if (new_folder_name)
newFolderName = [NSString stringWithUTF8String: new_folder_name];
else
newFolderName = nil;
rc = [moveFolder moveToFolder: targetFolder
withNewName: newFolderName];
[pool release];
GSUnregisterCurrentThread ();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_copy_folder(void *folder_object, void *target_folder_object,
bool recursive, const char *new_folder_name)
{
NSAutoreleasePool *pool;
MAPIStoreFolder *copyFolder, *targetFolder;
NSString *newFolderName;
struct MAPIStoreTallocWrapper *wrapper;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (folder_object)
{
wrapper = folder_object;
copyFolder = wrapper->instance;
wrapper = target_folder_object;
targetFolder = wrapper->instance;
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
newFolderName = [NSString stringWithUTF8String: new_folder_name];
rc = [copyFolder copyToFolder: targetFolder
recursive: recursive
withNewName: newFolderName];
[pool release];
GSUnregisterCurrentThread ();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error
sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
enum mapistore_table_type table_type, uint64_t change_num,
@ -623,7 +703,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 +738,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 +773,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 +805,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 +836,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 +869,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 +901,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 +936,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 +967,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 +996,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 +1025,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];
@ -962,11 +1042,11 @@ 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,
struct mapistore_message **msg)
sogo_message_attachment_open_embedded_message (void *attachment_object,
TALLOC_CTX *mem_ctx,
void **message_object,
uint64_t *midP,
struct mapistore_message **msg)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
@ -979,7 +1059,7 @@ 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
@ -999,6 +1079,42 @@ sogo_message_attachment_open_embedded_message
return rc;
}
static enum mapistore_error
sogo_message_attachment_create_embedded_message (void *attachment_object,
TALLOC_CTX *mem_ctx,
void **message_object,
struct mapistore_message **msg)
{
struct MAPIStoreTallocWrapper *wrapper;
NSAutoreleasePool *pool;
MAPIStoreAttachment *attachment;
MAPIStoreEmbeddedMessage *message;
int rc;
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
if (attachment_object)
{
wrapper = attachment_object;
attachment = wrapper->instance;
GSRegisterCurrentThread ();
pool = [NSAutoreleasePool new];
rc = [attachment createEmbeddedMessage: &message
withMAPIStoreMsg: msg
inMemCtx: mem_ctx];
if (rc == MAPISTORE_SUCCESS)
*message_object = [message tallocWrapper: mem_ctx];
[pool release];
GSUnregisterCurrentThread ();
}
else
{
rc = sogo_backend_unexpected_error();
}
return rc;
}
static enum mapistore_error sogo_table_get_available_properties(void *table_object,
TALLOC_CTX *mem_ctx, struct SPropTagArray **propertiesP)
{
@ -1012,7 +1128,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 +1156,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 +1185,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 +1216,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 +1249,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 +1280,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 +1309,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 +1339,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 +1370,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 +1400,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];
@ -1378,6 +1494,8 @@ int mapistore_init_backend(void)
backend.folder.create_message = sogo_folder_create_message;
backend.folder.delete_message = sogo_folder_delete_message;
backend.folder.move_copy_messages = sogo_folder_move_copy_messages;
backend.folder.move_folder = sogo_folder_move_folder;
backend.folder.copy_folder = sogo_folder_copy_folder;
backend.folder.get_deleted_fmids = sogo_folder_get_deleted_fmids;
backend.folder.get_child_count = sogo_folder_get_child_count;
backend.folder.open_table = sogo_folder_open_table;
@ -1386,6 +1504,7 @@ int mapistore_init_backend(void)
backend.message.get_attachment_table = sogo_message_get_attachment_table;
backend.message.open_attachment = sogo_message_open_attachment;
backend.message.open_embedded_message = sogo_message_attachment_open_embedded_message;
backend.message.create_embedded_message = sogo_message_attachment_create_embedded_message;
backend.message.get_message_data = sogo_message_get_message_data;
backend.message.modify_recipients = sogo_message_modify_recipients;
backend.message.set_read_flag = sogo_message_set_read_flag;

View File

@ -0,0 +1,86 @@
/* 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;
- (MAPIStoreObject *) container;
- (void) cleanupCaches;
- (uint64_t) objectId;
/* implemented getters */
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSearchKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
/* subclasses */
- (uint64_t) objectVersion;
@end
#endif /* MAPISTORESOGOOBJECT_H */

View File

@ -0,0 +1,230 @@
/* 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
{
return [container idForObjectWithKey: [sogoObject nameInContainer]];
}
/* getters */
- (int) getPidTagDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagSearchKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
NSString *stringValue;
stringValue = [sogoObject nameInContainer];
*data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding]
asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidTagGenerateExchangeViews: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidTagParentSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getReplicaKey: data fromGlobCnt: [container objectId] >> 16
inMemCtx: memCtx];
}
- (int) getPidTagSourceKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getReplicaKey: data fromGlobCnt: [self objectId] >> 16
inMemCtx: memCtx];
}
/* helper getters */
- (int) getPidTagChangeKey: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
uint64_t obVersion;
obVersion = [self objectVersion];
if (obVersion == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
rc = [self getReplicaKey: data fromGlobCnt: obVersion
inMemCtx: memCtx];
return rc;
}
- (int) getPidTagChangeNumber: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc;
uint64_t obVersion;
obVersion = [self objectVersion];
if (obVersion == ULLONG_MAX)
rc = MAPISTORE_ERR_NOT_FOUND;
else
{
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
| 0x0001));
rc = MAPISTORE_SUCCESS;
}
return rc;
}
/* subclasses */
- (uint64_t) objectVersion
{
[self subclassResponsibility: _cmd];
return ULLONG_MAX;
}
/* logging */
- (NSString *) loggingPrefix
{
return [NSString stringWithFormat:@"<%@:%p:%@>",
NSStringFromClass (isa), self, [self nameInContainer]];
}
@end

View File

@ -25,7 +25,7 @@
#include <talloc.h>
#import <Foundation/NSObject.h>
#import "NSObject+MAPIStore.h"
#undef DEBUG
#include <mapistore/mapistore.h>
@ -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;

View File

@ -841,8 +841,7 @@ static Class NSDataK, NSStringK;
struct mapistore_property_data *rowData;
int rc;
child = [self childAtRowID: rowId
forQueryType: queryType];
child = [self childAtRowID: rowId forQueryType: queryType];
if (child)
{
rowData = talloc_array(memCtx, struct mapistore_property_data, columnsCount);
@ -874,61 +873,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,
&notif_parameters);
}
}
else
{
if (newChildRow == NSNotFound)
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_DELETED,
&notif_parameters);
else
{
/* the fact that the row order has changed has no impact here */
notif_parameters.row_id = newChildRow;
mapistore_push_notification (mstoreCtx,
MAPISTORE_TABLE,
MAPISTORE_OBJECT_MODIFIED,
&notif_parameters);
}
}
}
/* subclasses */
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
{

View File

@ -91,8 +91,8 @@
return MAPISTORE_SUCCESS;
}
- (int) getPidTagSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagNormalizedSubject: (void **) data // SUMMARY
inMemCtx: (TALLOC_CTX *) memCtx
{
iCalToDo *task;

View File

@ -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;

View File

@ -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,
@ -20,20 +20,27 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSMapTable.h>
#import <Foundation/NSPropertyList.h>
#import <Foundation/NSThread.h>
#import <Foundation/NSTimeZone.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 +87,9 @@ static NSMapTable *contextsTable = nil;
mapping = nil;
userDbTableExists = NO;
folderTableURL = nil;
authenticator = nil;
woContext = [WOContext contextWithRequest: nil];
[woContext retain];
@ -88,9 +98,33 @@ static NSMapTable *contextsTable = nil;
return self;
}
- (NSString *) _readUserPassword: (NSString *) newUsername
{
NSString *password, *path;
NSData *content;
password = nil;
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR
@"/mapistore/%@/password", newUsername];
content = [NSData dataWithContentsOfFile: path];
if (content)
{
password = [[NSString alloc] initWithData: content
encoding: NSUTF8StringEncoding];
[password autorelease];
}
return password;
}
- (id) initWithUsername: (NSString *) newUsername
andTDBIndexing: (struct tdb_wrap *) indexingTdb
{
NSString *userPassword;
if ((self = [self init]))
{
/* "username" will be retained by table */
@ -102,7 +136,10 @@ static NSMapTable *contextsTable = nil;
authenticator = [MAPIStoreAuthenticator new];
[authenticator setUsername: username];
/* TODO: very hackish (IMAP access) */
[authenticator setPassword: username];
userPassword = [self _readUserPassword: newUsername];
if ([userPassword length] == 0)
userPassword = username;
[authenticator setPassword: userPassword];
}
return self;
@ -117,6 +154,8 @@ static NSMapTable *contextsTable = nil;
[authenticator release];
[mapping release];
[folderTableURL release];
[sogoUser release];
[contextsTable removeObjectForKey: username];
@ -213,6 +252,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;

View File

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

View File

@ -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 */

View File

@ -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;
}

View File

@ -26,10 +26,11 @@
#import <Foundation/NSObject.h>
#include <talloc.h>
#include <mapistore/mapistore_errors.h>
struct MAPIStoreTallocWrapper
{
id MAPIStoreSOGoObject;
id instance;
};
@interface NSObject (MAPIStoreTallocHelpers)
@ -49,6 +50,7 @@ struct MAPIStoreTallocWrapper
- (int) getLongZero: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getYes: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getNo: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
- (int) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
@end
@ -58,4 +60,17 @@ struct MAPIStoreTallocWrapper
@end
@interface NSObject (MAPIStoreProperties)
+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx;
+ (void) fillAvailableProperties: (struct SPropTagArray *) properties
withExclusions: (BOOL *) exclusions;
- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx;
- (BOOL) canGetProperty: (enum MAPITAGS) propTag;
@end
#endif /* NSOBJECT_MAPISTORE_H */

View File

@ -25,6 +25,7 @@
#import <Foundation/NSThread.h>
#import <NGExtensions/NSObject+Logs.h>
#import "MAPIStorePropertySelectors.h"
#import "MAPIStoreTypes.h"
#import "NSArray+MAPIStore.h"
#import "NSData+MAPIStore.h"
@ -50,7 +51,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 +64,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);
@ -167,4 +168,104 @@ MAPIStoreTallocWrapperDestroy (void *data)
return MAPISTORE_SUCCESS;
}
- (int) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [@"SMTP" asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@end
@implementation NSObject (MAPIStoreProperties)
+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
struct SPropTagArray *properties;
const MAPIStorePropertyGetter *classGetters;
NSUInteger count;
enum MAPITAGS propTag;
uint16_t propValue;
properties = talloc_zero (memCtx, struct SPropTagArray);
properties->aulPropTag = talloc_array (properties, enum MAPITAGS,
MAPIStoreSupportedPropertiesCount);
classGetters = MAPIStorePropertyGettersForClass (self);
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
{
propTag = MAPIStoreSupportedProperties[count];
propValue = (propTag & 0xffff0000) >> 16;
if (classGetters[propValue])
{
properties->aulPropTag[properties->cValues] = propTag;
properties->cValues++;
}
}
*propertiesP = properties;
return MAPISTORE_SUCCESS;
}
+ (void) fillAvailableProperties: (struct SPropTagArray *) properties
withExclusions: (BOOL *) exclusions
{
TALLOC_CTX *localMemCtx;
struct SPropTagArray *subProperties;
uint16_t propId;
NSUInteger count;
localMemCtx = talloc_zero (NULL, TALLOC_CTX);
[self getAvailableProperties: &subProperties inMemCtx: localMemCtx];
for (count = 0; count < subProperties->cValues; count++)
{
propId = (subProperties->aulPropTag[count] >> 16);
if (!exclusions[propId])
{
properties->aulPropTag[properties->cValues]
= subProperties->aulPropTag[count];
properties->cValues++;
exclusions[propId] = YES;
}
}
talloc_free (localMemCtx);
}
- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
inMemCtx: (TALLOC_CTX *) memCtx
{
NSUInteger count;
struct SPropTagArray *availableProps;
enum MAPITAGS propTag;
availableProps = talloc_zero (memCtx, struct SPropTagArray);
availableProps->aulPropTag = talloc_array (availableProps, enum MAPITAGS,
MAPIStoreSupportedPropertiesCount);
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
{
propTag = MAPIStoreSupportedProperties[count];
if ([self canGetProperty: propTag])
{
availableProps->aulPropTag[availableProps->cValues] = propTag;
availableProps->cValues++;
}
}
*propertiesP = availableProps;
return MAPISTORE_SUCCESS;
}
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
{
uint16_t propValue;
const IMP *classGetters;
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
propValue = (propTag & 0xffff0000) >> 16;
return (classGetters[propValue] != NULL);
}
@end

View File

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

View File

@ -1,6 +1,6 @@
/* SOGoMAPIFSFolder.h - this file is part of SOGo
/* SOGoMAPIDBFolder.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -20,41 +20,40 @@
* 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 *) childKeysOfType: (MAPIDBObjectType) type
includeDeleted: (BOOL) includeDeleted
matchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings;
- (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
andSortOrderings: (NSArray *) sortOrderings;
- (void) changePathTo: (NSString *) newPath;
@end
#endif /* SOGOMAPIFSFOLDER_H */
#endif /* SOGOMAPIDBFOLDER_H */

View File

@ -0,0 +1,452 @@
/* 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 <NGExtensions/NSNull+misc.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLContentStore/GCSChannelManager.h>
// #import <GDLContentStore/EOQualifier+GCS.m>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSString+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];
[whereClause addObject: [NSString stringWithFormat: @"c_parent_path = '%@'",
[self path]]];
[whereClause addObject: [NSString stringWithFormat: @"c_type = %d", type]];
if (!includeDeleted)
[whereClause addObject: @"c_deleted = 0"];
[sql appendFormat: @" WHERE %@",
[whereClause componentsJoinedByString: @" AND "]];
childPathPrefix = [NSString stringWithFormat: @"%@/", [self path]];
/* 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];
}
- (void) changePathTo: (NSString *) newPath
{
NSMutableString *sql// , *qualifierClause
;
NSString *oldPath, *oldPathAsPrefix, *path, *parentPath;
NSMutableArray *queries;
NSArray *records;
NSDictionary *record;
NSUInteger count, max;
/* change the paths in children records */
oldPath = [self path];
oldPathAsPrefix = [NSString stringWithFormat: @"%@/", oldPath];
sql = [NSMutableString stringWithFormat:
@"SELECT c_path, c_parent_path FROM %@"
@" WHERE c_path LIKE '%@%%'",
[self tableName], oldPathAsPrefix];
records = [self performSQLQuery: sql];
max = [records count];
queries = [NSMutableArray arrayWithCapacity: max + 1];
if (max > 0)
{
for (count = 0; count < max; count++)
{
record = [records objectAtIndex: count];
path = [record objectForKey: @"c_path"];
sql = [NSMutableString stringWithFormat: @"UPDATE %@"
@" SET c_path = '%@'",
[self tableName],
[path stringByReplacingPrefix: oldPath
withPrefix: newPath]];
parentPath = [record objectForKey: @"c_parent_path"];
if ([parentPath isNotNull])
[sql appendFormat: @", c_parent_path = '%@'",
[parentPath stringByReplacingPrefix: oldPath
withPrefix: newPath]];
[sql appendFormat: @" WHERE c_path = '%@'", path];
[queries addObject: sql];
}
[self performBatchSQLQueries: queries];
}
/* change the path in this folder record */
[super changePathTo: newPath];
}
// - (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
// andSortOrderings: (NSArray *) sortOrderings
// {
// NSArray *allKeys;
// NSMutableArray *keys;
// NSUInteger count, max;
// NSString *messageKey;
// SOGoMAPIDBMessage *message;
// if (sortOrderings)
// [self warnWithFormat: @"sorting is not handled yet"];
// allKeys = [self toOneRelationshipKeys];
// if (qualifier)
// {
// [self logWithFormat: @"%s: getting restricted FAI keys", __PRETTY_FUNCTION__];
// max = [allKeys count];
// keys = [NSMutableArray arrayWithCapacity: max];
// for (count = 0; count < max; count++)
// {
// messageKey = [allKeys objectAtIndex: count];
// message = [self lookupName: messageKey
// inContext: nil
// acquire: NO];
// if ([qualifier evaluateMAPIVolatileMessage: message])
// [keys addObject: messageKey];
// }
// }
// else
// keys = (NSMutableArray *) allKeys;
// return keys;
// }
- (id) lookupName: (NSString *) childName
inContext: (WOContext *) woContext
acquire: (BOOL) acquire
{
id object;
Class objectClass;
NSString *childPath;
NSDictionary *record;
childPath = [self pathForChild: childName];
record = [self lookupRecord: childPath newerThanVersion: -1];
if (record)
{
if ([[record objectForKey: @"c_type"] intValue] == MAPIDBObjectTypeFolder)
objectClass = isa;
else
objectClass = SOGoMAPIDBObjectK;
object = [objectClass objectWithName: childName
inContainer: self];
[object setupFromRecord: record];
}
else
object = nil;
return object;
}
- (id) lookupFolder: (NSString *) folderName
inContext: (WOContext *) woContext
{
id object;
object = [SOGoMAPIDBFolder objectWithName: folderName
inContainer: self];
[object reloadIfNeeded];
return object;
}
// - (id) _fileAttributeForKey: (NSString *) key
// {
// NSDictionary *attributes;
// attributes = [[NSFileManager defaultManager]
// fileAttributesAtPath: directory
// traverseLink: NO];
// return [attributes objectForKey: key];
// }
// - (NSCalendarDate *) creationTime
// {
// return [self _fileAttributeForKey: NSFileCreationDate];
// }
// - (NSCalendarDate *) lastModificationTime
// {
// return [self _fileAttributeForKey: NSFileModificationDate];
// }
- (NSException *) delete
{
[self notImplemented: _cmd];
// NSFileManager *fm;
// NSException *error;
// fm = [NSFileManager defaultManager];
// if (![fm removeFileAtPath: directory handler: NULL])
// error = [NSException exceptionWithName: @"MAPIStoreIOException"
// reason: @"could not delete folder"
// userInfo: nil];
// else
// error = nil;
// return error;
return nil;
}
/* acl */
- (NSString *) defaultUserID
{
return @"default";
}
- (NSMutableDictionary *) _aclEntries
{
NSMutableDictionary *aclEntries;
[aclMessage reloadIfNeeded];
aclEntries = [aclMessage properties];
if (![aclEntries objectForKey: @"users"])
[aclEntries setObject: [NSMutableArray array] forKey: @"users"];
if (![aclEntries objectForKey: @"entries"])
[aclEntries setObject: [NSMutableDictionary dictionary]
forKey: @"entries"];
return aclEntries;
}
- (void) addUserInAcls: (NSString *) user
{
NSMutableDictionary *acl;
NSMutableArray *users;
acl = [self _aclEntries];
users = [acl objectForKey: @"users"];
[users addObjectUniquely: user];
[aclMessage save];
}
- (void) removeAclsForUsers: (NSArray *) oldUsers
{
NSDictionary *acl;
NSMutableDictionary *entries;
NSMutableArray *users;
acl = [self _aclEntries];
entries = [acl objectForKey: @"entries"];
[entries removeObjectsForKeys: oldUsers];
users = [acl objectForKey: @"users"];
[users removeObjectsInArray: oldUsers];
[aclMessage save];
}
- (NSArray *) aclUsers
{
return [[self _aclEntries] objectForKey: @"users"];
}
- (NSArray *) aclsForUser: (NSString *) uid
{
NSDictionary *entries;
entries = [[self _aclEntries] objectForKey: @"entries"];
return [entries objectForKey: uid];
}
- (void) setRoles: (NSArray *) roles
forUser: (NSString *) uid
{
NSMutableDictionary *acl;
NSMutableDictionary *entries;
acl = [self _aclEntries];
entries = [acl objectForKey: @"entries"];
[entries setObject: roles forKey: uid];
[aclMessage save];
}
@end

View File

@ -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 */

View File

@ -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

View File

@ -0,0 +1,85 @@
/* 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;
- (void) changePathTo: (NSString *) newPath;
/* db helpers */
- (EOAdaptor *) tableChannelAdaptor;
- (NSArray *) performSQLQuery: (NSString *) sql;
- (BOOL) performBatchSQLQueries: (NSArray *) queries;
@end
#endif /* SOGOMAPIDBOBJECT_H */

View File

@ -0,0 +1,546 @@
/* 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 */
- (void) changePathTo: (NSString *) newPath
{
NSMutableString *sql;
NSString *oldPath, *newParentPath;
NSRange slashRange;
oldPath = [self path];
slashRange = [newPath rangeOfString: @"/"
options: NSBackwardsSearch];
if (slashRange.location != NSNotFound)
newParentPath = [newPath substringToIndex: slashRange.location];
else
newParentPath = NULL;
sql = [NSMutableString stringWithFormat: @"UPDATE %@"
@" SET c_path = '%@'",
[self tableName],
newPath];
if (newParentPath)
[sql appendFormat: @", c_parent_path = '%@'", newParentPath];
else
[sql appendString: @", c_parent_path = NULL"];
[sql appendFormat: @" WHERE c_path = '%@'", oldPath];
[self performBatchSQLQueries: [NSArray arrayWithObject: sql]];
}
- (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;
}
- (BOOL) performBatchSQLQueries: (NSArray *) queries
{
GCSChannelManager *cm;
EOAdaptorChannel *channel;
EOAdaptorContext *dbContext;
NSException *error;
NSUInteger count, max;
NSString *sql;
cm = [GCSChannelManager defaultChannelManager];
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
dbContext = [channel adaptorContext];
[dbContext beginTransaction];
error = nil;
max = [queries count];
for (count = 0; error == nil && count < max; count++)
{
sql = [queries objectAtIndex: count];
error = [channel evaluateExpressionX: sql];
if (error)
[dbContext rollbackTransaction];
}
if (!error)
[dbContext commitTransaction];
[cm releaseChannel: channel];
return (error == nil);
}
- (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, *parentPathValue, *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: NSPropertyListGNUstepBinaryFormat
errorDescription: NULL];
propsValue = [adaptor formatValue: [content stringByEncodingBase64]
forAttribute: textColumn];
}
else
propsValue = @"NULL";
if (isNew)
{
ASSIGN (creationDate, now);
creationDateValue = (NSInteger) [creationDate timeIntervalSince1970];
parentPathValue = [adaptor formatValue: [container path]
forAttribute: textColumn];
if (!parentPathValue)
parentPathValue = @"NULL";
sql = [NSString stringWithFormat:
(@"INSERT INTO %@"
@" (c_path, c_parent_path, c_type, c_creationdate, c_lastmodified,"
@" c_deleted, c_version, c_content)"
@" VALUES (%@, %@, %d, %d, %d, 0, 0, %@"
@")"),
tableName,
pathValue, parentPathValue, objectType,
creationDateValue, lastModifiedValue,
propsValue];
isNew = NO;
}
else
{
version++;
deletedValue = (deleted ? 1 : 0);
sql = [NSString stringWithFormat:
(@"UPDATE %@"
@" SET c_lastmodified = %d, c_deleted = %d,"
@" c_version = %d, c_content = %@"
@" WHERE c_path = %@"),
tableName,
lastModifiedValue, deletedValue, version, propsValue,
pathValue];
}
result = [channel evaluateExpressionX: sql];
if (result)
[self errorWithFormat: @"could not insert/update record for record %@"
@" in %@: %@", pathValue, tableName, result];
// @" c_path VARCHAR(255) PRIMARY KEY,"
// @" c_type SMALLINT NOT NULL,"
// @" c_creationdate INT4 NOT NULL,"
// @" c_lastmodified INT4 NOT NULL,"
// @" c_deleted SMALLINT NOT NULL DEFAULT 0,"
// @" c_content BLOB");
[cm releaseChannel: channel];
}
@end

View File

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

View File

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

View File

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

View File

@ -1,12 +1,12 @@
/* SOGoMAPIVolatileMessage.h - this file is part of SOGo
/* SOGoMAPIObject.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* 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 */

View File

@ -1,6 +1,6 @@
/* SOGoMAPIVolatileMessage.m - this file is part of SOGo
/* SOGoMAPIObject.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -21,16 +21,21 @@
*/
#import <Foundation/NSDictionary.h>
#import <Foundation/NSCalendarDate.h>
#import "SOGoMAPIVolatileMessage.h"
#import "SOGoMAPIObject.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 +43,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

View File

@ -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;
}

View File

@ -0,0 +1,41 @@
/* iCalEvent+MAPIStore.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 ICALEVENT_MAPISTORE_H
#define ICALEVENT_MAPISTORE_H
#import <NGCards/iCalEvent.h>
@class MAPIStoreUserContext;
@class NSDictionary;
@class NSString;
@class SOGoUser;
@interface iCalEvent (MAPIStoreProperties)
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser;
@end
#endif /* ICALEVENT_MAPISTORE_H */

View File

@ -0,0 +1,522 @@
/* iCalEvent+MAPIStore.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 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.
*/
#include <talloc.h>
#include <util/attr.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSTimeZone.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGCards/iCalAlarm.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalDateTime.h>
#import <NGCards/iCalPerson.h>
#import <NGCards/iCalTimeZone.h>
#import <NGCards/iCalTrigger.h>
#import <SOGo/SOGoPermissions.h>
#import <SOGo/SOGoUser.h>
#import <Appointments/SOGoAppointmentFolder.h>
#import <Appointments/SOGoAppointmentObject.h>
#import <Appointments/iCalEntityObject+SOGo.h>
#import <Mailer/NSString+Mail.h>
#import "MAPIStoreAppointmentWrapper.h"
#import "MAPIStoreCalendarAttachment.h"
#import "MAPIStoreCalendarFolder.h"
#import "MAPIStoreContext.h"
#import "MAPIStoreMapping.h"
#import "MAPIStoreRecurrenceUtils.h"
#import "MAPIStoreTypes.h"
#import "MAPIStoreUserContext.h"
#import "NSDate+MAPIStore.h"
#import "NSData+MAPIStore.h"
#import "NSObject+MAPIStore.h"
#import "NSString+MAPIStore.h"
#import "NSValue+MAPIStore.h"
#import "MAPIStoreCalendarMessage.h"
#undef DEBUG
#include <stdbool.h>
#include <gen_ndr/exchange.h>
#include <gen_ndr/property.h>
#include <libmapi/libmapi.h>
#include <mapistore/mapistore.h>
#include <mapistore/mapistore_errors.h>
#include <mapistore/mapistore_nameid.h>
#import "iCalEvent+MAPIStore.h"
@implementation iCalEvent (MAPIStoreProperties)
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
{
struct Binary_r *blob;
struct AppointmentRecurrencePattern *pattern;
blob = [mapiRecurrenceData asBinaryInMemCtx: NULL];
pattern = get_AppointmentRecurrencePattern (blob, blob);
[(iCalCalendar *) parent
setupRecurrenceWithMasterEntity: self
fromRecurrencePattern: &pattern->RecurrencePattern];
talloc_free (blob);
}
- (void) _setupEventAlarmFromProperties: (NSDictionary *) properties
{
NSArray *alarms;
iCalAlarm *currentAlarm, *alarm = nil;
iCalTrigger *trigger;
NSNumber *delta;
NSString *action;
NSUInteger count, max;
/* find and remove first display alarm */
alarms = [self alarms];
max = [alarms count];
for (count = 0; !alarm && count < max; count++)
{
currentAlarm = [alarms objectAtIndex: count];
action = [[currentAlarm action] lowercaseString];
if (!action || [action isEqualToString: @"display"])
alarm = currentAlarm;
}
if (alarm)
[self removeChild: alarm];
if ([[properties objectForKey: MAPIPropertyKey (PidLidReminderSet)]
boolValue])
{
delta
= [properties objectForKey: MAPIPropertyKey (PidLidReminderDelta)];
if (delta)
{
alarm = [iCalAlarm new];
[alarm setAction: @"DISPLAY"];
trigger = [iCalTrigger elementWithTag: @"trigger"];
[trigger setValueType: @"DURATION"];
[trigger
setSingleValue: [NSString stringWithFormat: @"-PT%@M", delta]
forKey: @""];
[alarm setTrigger: trigger];
[self addToAlarms: alarm];
[alarm release];
}
}
}
- (void) updateFromMAPIProperties: (NSDictionary *) properties
inUserContext: (MAPIStoreUserContext *) userContext
withActiveUser: (SOGoUser *) activeUser
{
BOOL isAllDay;
iCalDateTime *start, *end;
iCalTimeZone *tz;
NSTimeZone *userTimeZone;
NSString *priority;
NSUInteger responseStatus = 0;
NSInteger tzOffset;
SOGoUser *ownerUser;
id value;
// value = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
// if (value)
// isException = [value isEqualToString: @"IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}"];
// else
// isException = NO;
userTimeZone = [userContext timeZone];
/* CREATED */
value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)];
if (value)
[self setCreated: value];
// LAST-MODIFIED = PidTagLastModificationTime
value = [properties objectForKey: MAPIPropertyKey (PidTagLastModificationTime)];
if (value)
[self setLastModified: value];
/* DTSTAMP = PidLidOwnerCriticalChange or PidLidAttendeeCriticalChange */
value = [properties objectForKey: MAPIPropertyKey (PidLidOwnerCriticalChange)];
if (value)
[self setTimeStampAsDate: value];
/* SUMMARY */
value = [properties objectForKey: MAPIPropertyKey (PidTagNormalizedSubject)];
if (value)
[self setSummary: value];
// Location
value = [properties objectForKey: MAPIPropertyKey (PidLidLocation)];
if (value)
[self setLocation: value];
isAllDay = [self isAllDay];
value = [properties
objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)];
if (value)
isAllDay = [value boolValue];
if (!isAllDay)
{
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
[(iCalCalendar *) parent addTimeZone: tz];
}
else
tz = nil;
// recurrence-id
value
= [properties objectForKey: MAPIPropertyKey (PidLidExceptionReplaceTime)];
if (value)
{
if (!isAllDay)
{
tzOffset = [userTimeZone secondsFromGMTForDate: value];
value = [value dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
}
[self setRecurrenceId: value];
}
// start
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentStartWhole)];
if (!value)
value = [properties objectForKey: MAPIPropertyKey (PR_START_DATE)];
if (value)
{
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
[start setTimeZone: tz];
if (isAllDay)
{
[start setDate: value];
[start setTimeZone: nil];
}
else
{
tzOffset = [userTimeZone secondsFromGMTForDate: value];
value = [value dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
[start setDateTime: value];
}
}
/* end */
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentEndWhole)];
if (!value)
value = [properties objectForKey: MAPIPropertyKey (PR_END_DATE)];
if (value)
{
end = (iCalDateTime *) [self uniqueChildWithTag: @"dtend"];
[end setTimeZone: tz];
if (isAllDay)
{
[end setDate: value];
[end setTimeZone: nil];
}
else
{
tzOffset = [[value timeZone] secondsFromGMTForDate: value];
value = [value dateByAddingYears: 0 months: 0 days: 0
hours: 0 minutes: 0
seconds: tzOffset];
[end setDateTime: value];
}
}
/* priority */
value = [properties objectForKey: MAPIPropertyKey(PR_IMPORTANCE)];
if (value)
{
switch ([value intValue])
{
case 0: // IMPORTANCE_LOW
priority = @"9";
break;
case 2: // IMPORTANCE_HIGH
priority = @"1";
break;
default: // IMPORTANCE_NORMAL
priority = @"5";
}
}
else
priority = @"0"; // None
[self setPriority: priority];
/* show time as free/busy/tentative/out of office. Possible values are:
0x00000000 - olFree
0x00000001 - olTentative
0x00000002 - olBusy
0x00000003 - olOutOfOffice */
value = [properties objectForKey: MAPIPropertyKey(PidLidBusyStatus)];
if (value)
{
switch ([value intValue])
{
case 0:
[self setTransparency: @"TRANSPARENT"];
break;
case 1:
case 2:
case 3:
default:
[self setTransparency: @"OPAQUE"];
}
}
/* Comment */
value = [properties objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)];
if (!value)
{
value = [properties objectForKey: MAPIPropertyKey (PR_HTML)];
if (value)
{
value = [[NSString alloc] initWithData: value
encoding: NSUTF8StringEncoding];
[value autorelease];
value = [value htmlToText];
}
}
if (value)
{
if ([value length] == 0 || [value isEqualToString: @"\\n"])
value = nil;
[self setComment: value];
}
/* recurrence */
value = [properties
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
if (value)
[self _setupEventRecurrence: value];
/* alarm */
[self _setupEventAlarmFromProperties: properties];
// Organizer
value = [properties objectForKey: @"recipients"];
if (value)
{
NSArray *recipients;
NSDictionary *dict;
NSString *orgEmail, *sentBy, *attEmail;
iCalPerson *person;
iCalPersonPartStat newPartStat;
NSNumber *flags, *trackStatus;
int i, effective;
BOOL organizerIsSet = NO;
[self setOrganizer: nil];
[self removeAllAttendees];
recipients = [value objectForKey: @"to"];
effective = 0;
for (i = 0; i < [recipients count]; i++)
{
dict = [recipients objectAtIndex: i];
person = [iCalPerson new];
[person setCn: [dict objectForKey: @"fullName"]];
attEmail = [dict objectForKey: @"email"];
[person setEmail: attEmail];
flags = [dict objectForKey: MAPIPropertyKey (PR_RECIPIENT_FLAGS)];
if (!flags)
{
[self logWithFormat:
@"no recipient flags specified: skipping recipient"];
continue;
}
if (([flags unsignedIntValue] & 0x0002)) /* recipOrganizer */
{
[self setOrganizer: person];
organizerIsSet = YES;
[self logWithFormat: @"organizer set via recipient flags"];
}
else
{
BOOL isOrganizer = NO;
// /* Work-around: it happens that Outlook still passes the
// organizer as a recipient, maybe because of a feature
// documented in a pre-mesozoic PDF still buried in a
// cavern... In that case we remove it, and we keep the
// number of effective recipients in "effective". If the
// total is 0, we remove the "ORGANIZER" too. */
// if ([attEmail isEqualToString: orgEmail])
// {
// [self logWithFormat:
// @"avoiding setting organizer as recipient"];
// continue;
// }
trackStatus = [dict objectForKey: MAPIPropertyKey (PidTagRecipientTrackStatus)];
if (trackStatus)
{
/* FIXME: we should provide a data converter between OL
partstats and SOGo */
switch ([trackStatus unsignedIntValue])
{
case 0x01: /* respOrganized */
isOrganizer = YES;
break;
case 0x02: /* respTentative */
newPartStat = iCalPersonPartStatTentative;
break;
case 0x03: /* respAccepted */
newPartStat = iCalPersonPartStatAccepted;
break;
case 0x04: /* respDeclined */
newPartStat = iCalPersonPartStatDeclined;
break;
default:
newPartStat = iCalPersonPartStatNeedsAction;
}
if (isOrganizer)
{
[self setOrganizer: person];
organizerIsSet = YES;
[self logWithFormat: @"organizer set via track status"];
}
else
{
[person setParticipationStatus: newPartStat];
[person setRsvp: @"TRUE"];
[person setRole: @"REQ-PARTICIPANT"];
[self addToAttendees: person];
effective++;
}
}
else
[self errorWithFormat: @"skipped recipient due"
@" to missing track status"];
}
[person release];
}
if (effective == 0) /* See work-around above */
[self setOrganizer: nil];
else
{
// SEQUENCE = PidLidAppointmentSequence
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentSequence)];
if (value)
[self setSequence: value];
ownerUser = [userContext sogoUser];
if (organizerIsSet)
{
/* We must reset the participation status to the value
obtained from PidLidResponseStatus as the value in
PidTagRecipientTrackStatus is not correct. Note (hack):
the method used here requires that the user directory
from LDAP and Samba matches perfectly. This can be solved
more appropriately by making use of the sender
properties... */
person = [self userAsAttendee: ownerUser];
if (person)
{
value
= [properties objectForKey: MAPIPropertyKey (PidLidResponseStatus)];
if (value)
responseStatus = [value unsignedLongValue];
/* FIXME: we should provide a data converter between OL partstats and
SOGo */
switch (responseStatus)
{
case 0x02: /* respTentative */
newPartStat = iCalPersonPartStatTentative;
break;
case 0x03: /* respAccepted */
newPartStat = iCalPersonPartStatAccepted;
break;
case 0x04: /* respDeclined */
newPartStat = iCalPersonPartStatDeclined;
break;
default:
newPartStat = iCalPersonPartStatNeedsAction;
}
[person setParticipationStatus: newPartStat];
value = [properties objectForKey: MAPIPropertyKey (PidLidAttendeeCriticalChange)];
if (value && ![value isNever])
[self setTimeStampAsDate: value];
// if (newPartStat // != iCalPersonPartStatUndefined
// )
// {
// // iCalPerson *participant;
// // participant = [self userAsAttendee: ownerUser];
// // [participant setParticipationStatus: newPartStat];
// // [sogoObject saveComponent: self];
// [sogoObject changeParticipationStatus: newPartStat
// withDelegate: nil];
// // [[self context] tearDownRequest];
// }
// // }1005
// // else
// // {
}
}
else
{
[self errorWithFormat: @"organizer was not set although a"
@" recipient list was specified"];
/* We must set the organizer preliminarily here because, unlike what
the doc states, Outlook does not always pass the real organizer
in the recipients list. */
dict = [ownerUser primaryIdentity];
person = [iCalPerson new];
[person setCn: [dict objectForKey: @"fullName"]];
orgEmail = [dict objectForKey: @"email"];
[person setEmail: orgEmail];
if (![activeUser isEqual: ownerUser])
{
dict = [activeUser primaryIdentity];
sentBy = [NSString stringWithFormat: @"mailto:%@",
[dict objectForKey: @"email"]];
[person setSentBy: sentBy];
}
[self setOrganizer: person];
[person release];
}
}
}
}
@end

View File

@ -0,0 +1,35 @@
/* iCalTimeZone+MAPIStore.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 ICALTIMEZONE_MAPISTORE_H
#define ICALTIMEZONE_MAPISTORE_H
#import <NGCards/iCalTimeZone.h>
@interface iCalTimeZone (MAPIStoreProperties)
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx;
@end
#endif /* ICALTIMEZONE_MAPISTORE_H */

View File

@ -0,0 +1,115 @@
/* iCalTimeZone+MAPIStore.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/NSString.h>
#import <NGCards/iCalByDayMask.h>
#import <NGCards/iCalTimeZonePeriod.h>
#import <NGCards/iCalRecurrenceRule.h>
#include <stdbool.h>
#include <stdint.h>
#include <talloc.h>
#undef DEBUG
#include <libmapi/libmapi.h>
#import "iCalTimeZone+MAPIStore.h"
@interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData;
@end
@implementation iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData
{
iCalRecurrenceRule *rrule;
NSArray *byMonth;
iCalByDayMask *mask;
NSCalendarDate *dateValue;
rrule = [self recurrenceRule];
byMonth = [rrule byMonth];
if ([byMonth count] > 0)
{
tzData->wMonth = [[byMonth objectAtIndex: 0] intValue];
mask = [rrule byDayMask];
tzData->wDayOfWeek = [mask firstDay];
tzData->wDay = [mask firstOccurrence];
dateValue = [self startDate];
tzData->wHour = [dateValue hourOfDay];
tzData->wMinute = [dateValue minuteOfHour];
tzData->wSecond = [dateValue secondOfMinute];
}
}
@end
@implementation iCalTimeZone (MAPIStoreProperties)
- (iCalTimeZonePeriod *) _mostRecentPeriodWithName: (NSString *) periodName
{
NSArray *periods;
iCalTimeZonePeriod *period;
NSUInteger max;
periods = [self childrenWithTag: periodName];
max = [periods count];
if (max > 0)
{
periods = [periods sortedArrayUsingSelector: @selector (compare:)];
period = (iCalTimeZonePeriod *) [periods objectAtIndex: (max - 1)];
}
else
period = nil;
return period;
}
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx
{
iCalTimeZonePeriod *period;
struct TimeZoneStruct tz;
int lBias, dlBias;
memset (&tz, 0, sizeof (struct TimeZoneStruct));
period = [self _mostRecentPeriodWithName: @"STANDARD"];
lBias = -[period secondsOffsetFromGMT] / 60;
tz.lBias = (uint32_t) lBias;
[period _fillTZDate: &tz.stStandardDate];
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
if (!period)
tz.stStandardDate.wMonth = 0;
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
tz.lDaylightBias = (uint32_t) (dlBias);
[period _fillTZDate: &tz.stDaylightDate];
tz.wStandardYear = tz.stStandardDate.wYear;
tz.wDaylightYear = tz.stDaylightDate.wYear;
return set_TimeZoneStruct (memCtx, &tz);
}
@end

Some files were not shown because too many files have changed in this diff Show More