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

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

Monotone-Parent: 749811709acadced020a19e4ce7c00f07ac86e77
Monotone-Parent: b142d5d1ddfd110920b6b9d0c4efbba96c4ccedd
Monotone-Revision: cebb37d367ee5534f83da28bfdd4300b276e285d

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2012-08-29T12:56:04
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Francis Lachapelle 2012-08-29 12:56:04 +00:00
commit c13f9364ff
185 changed files with 7788 additions and 3372 deletions

452
ChangeLog
View File

@ -1,3 +1,8 @@
2012-08-28 Jean Raby <jraby@inverse.ca>
* Scripts/openchange_cleanup.py:
New script to clean an openchange user profile
2012-08-27 Francis Lachapelle <flachapelle@inverse.ca>
* SoObjects/Appointments/SOGoAptMailInvitation.m,
@ -31,6 +36,229 @@
* UI/MailPartViewers/UIxMailPartHTMLViewer.m (-_sanitizeContent):
fix invalid void tags to insure proper HTML decoding. Fixes #1581.
2012-08-23 Ludovic Marcotte <lmarcotte@inverse.ca>
* SoObjects/Mailer/SOGoMailFolder.m - added safety
checks around the ACL code so we don't crash if
we can't read the ACLs.
2012-08-21 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreFolder.m (-getPidTagAccessLevel)
(-getPidTagRights, -getPidTagAccessControlListData): fixed
methods.
* OpenChange/MAPIStoreMessage.m
(-getPidTagDeleteAfterSubmit:inMemCtx:): moved from
MAPIStoreMailMessage.
* OpenChange/MAPIStoreContactsMessage.m
(-getPidTagAlternateRecipientAllowed:inMemCtx:)
(-getPidTagMessageFlags:inMemCtx:)
(-getPidTagDeleteAfterSubmit:inMemCtx:): new getters.
* OpenChange/MAPIStoreGCSFolder.m
(-setChangeKey:forMessageWithKey:): removed useless method.
(-updateVersionsForMessageWithKey:withChangeKey:): set the change
key provided by the client as member of the predecessor
changelist, but never as the actual change key for the object.
This hopefully fixes the issue where Outlook deletes objects that
have a different change list than what they expect.
2012-08-17 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreCalendarMessage.m
(-getPidTagMessageClass:inMemCtx:): return
"IPM.Schedule.Meeting.Request" when the owner user is an attendee.
* OpenChange/MAPIStoreAppointmentWrapper.m
(-getPidLidAppointmentNotAllowPropose:inMemCtx): new getter that
always return "YES", in order to disallow counter proposals.
* OpenChange/MAPIStoreContext.m (-getPath:ofFMID:inMemCtx:):
properly escape urls containing non-ascii chars.
(-getRootFoldeR:withFID:): idem.
2012-08-16 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreCalendarMessage.m
(-getMessageData:inMemCtx:): when a "recipients" records is
available in the properties, we must return that list instead of
the list of attendees since it will be the most recent one.
(_fixupAppointmentObjectWithUID::): when an appointment had been
deleted, we first attempt to resurrect it from the database before
reinstantiating it, which allows the event synchronisation to
happen properly in [SOGoAppointmentObject
updateContentWithCalendar:fromRequest:].
* OpenChange/MAPIStoreMapping.m (_updateFolderWithURL:withURL:):
we retain and release "oldURL" to avoid releasing it when it
is replaced in the list of urls to modify.
* OpenChange/MAPIStoreAppointmentWrapper.m
(-getPidTagInternetCodepage:inMemCtx:): new getter for a property
that is sometimes requested.
(-getPidTagBody:inMemCtx:): we return an empty string when no
"description"/"comment" is actually present.
2012-08-15 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreMailFolder.m (-addProperties:): make use of
the new methods below when a mail folder has been renamed, as this
operation affects the url of mail objects.
* OpenChange/SOGoMAPIDBObject.m (-setNameInContainer): update the
object record in the database to reflect the change of folder
name.
* OpenChange/MAPIStoreMailContext.m (-updateURLWithFolderName):
change the folder name used in the context url to use the new
folder name after a rename operation, so that further invocations
of -url will return the right url.
* OpenChange/MAPIStoreMailFolder.m
(-moveCopyToFolder:withNewName:isMove:isRecursive:): implemented
IMAP-based copy operation, for speed.
(-addProperties): restored the ability to rename IMAP folders by
properly updating the fid/url mapping with our new methods.
2012-08-14 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreFolder.m (-moveToFolder:withNewName:):
renamed to "moveCopyToFolder:withNewName:isMove:isRecursive:",
with the ability to specify whether the operation is a move or
copy operation and whether it is recursive or not (for copy).
* OpenChange/MAPIStoreSOGo.m (sogo_folder_move_folder): if
"target_folder_object", we do not attempt to access the
corresponding instance member.
* OpenChange/MAPIStoreMailFolder.m (-
moveCopyMessagesWithMIDs:andCount:fromFolder:withMIDs:andChangeKeys:wantCopy:):
do not attempt to access targetChangeKeys when NULL, to avoid a
SEGFAULT.
2012-08-14 Jean Raby <jraby@inverse.ca>
* OpenChange/GNUmakefile: use version_info[{0,1}] instead of
version_info.{major,minor} when checking for legacy version
of python since these named attributes where added in python2.7
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
@ -38,10 +266,16 @@
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.
* 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.
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>
@ -54,6 +288,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
@ -71,6 +321,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):
@ -89,8 +348,113 @@
(_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.
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
@ -109,6 +473,50 @@
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.
2012-07-18 Ludovic Marcotte <lmarcotte@inverse.ca>
* SoObjects/Appointments/SOGoAppointmentObject.m
@ -286,6 +694,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]
@ -296,6 +723,23 @@
Let sogo append system sources if the request comes from an android
client even if its user agent matches the IPhoneAddressBook
2012-06-29 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreSOGo.m
(sogo_message_attachment_open_embedded_message): added the "mode"
parameter.
* OpenChange/SOGoMAPIDBObject.m: new class module that replaced
SOGoMAPIFSMessage.
* OpenChange/SOGoMAPIDBFolder.m: new class module that replaced
SOGoMAPIFSFolder.
2012-06-28 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoObject.m (-initWithName:inContainer:): make
sure that "_name" is neither nil nor empty.
2012-06-27 Jean Raby <jraby@inverse.ca>
* SoObjects/Appointments/SOGoAppointmentObject.m

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

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

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

View File

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

View File

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

@ -1,6 +1,6 @@
/* EOQualifier+MAPI.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2010-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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[0] == 2 and a[1] >= 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,18 @@ 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/SOGo.framework/ -lSOGo \
-L../OGoContentStore/obj/ -lOGoContentStore \
-L../SOPE/GDLContentStore/obj/ -lGDLContentStore \
-L../SOPE/NGCards/obj/ -lNGCards \
-lNGObjWeb
TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL)
### cflags and libs
LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags)
@ -160,7 +191,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 +207,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

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

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

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreActiveTables.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

@ -1,6 +1,6 @@
/* MAPIStoreAppointmentWrapper.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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
{
@ -718,17 +709,255 @@ static NSCharacterSet *hexCharacterSet = nil;
return MAPISTORE_SUCCESS;
}
- (int) getPidLidAppointmentNotAllowPropose: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
- (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 +1056,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 +1064,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 +1072,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 +1080,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 +1122,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 +1130,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 +1138,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 +1146,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 +1186,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 +1215,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 +1224,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 +1242,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 +1265,7 @@ static NSCharacterSet *hexCharacterSet = nil;
}
- (int) getPidTagBody: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
int rc = MAPISTORE_SUCCESS;
NSString *stringValue;
@ -1053,15 +1275,23 @@ static NSCharacterSet *hexCharacterSet = nil;
if ([stringValue length] > 0)
*data = [stringValue asUnicodeInMemCtx: memCtx];
else
rc = MAPISTORE_ERR_NOT_FOUND;
*data = [@"" asUnicodeInMemCtx: memCtx];
return rc;
}
- (int) getPidLidIsRecurring: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
- (int) getPidTagInternetCodepage: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPIBoolValue (memCtx, [event isRecurrent]);
/* ref:
http://msdn.microsoft.com/en-us/library/dd317756%28v=vs.85%29.aspx
minimal list that should be handled:
us-ascii: 20127
iso-8859-1: 28591
iso-8859-15: 28605
utf-8: 65001 */
*data = MAPILongValue(memCtx, 65001);
return MAPISTORE_SUCCESS;
}
@ -1074,37 +1304,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 +1450,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 +1499,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 +1972,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

@ -1,6 +1,6 @@
/* MAPIStoreAttachment.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -40,10 +40,16 @@
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;
/* move & copy operations */
- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment;
/* subclasses */
- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage;
- (MAPIStoreEmbeddedMessage *) createEmbeddedMessage;

View File

@ -1,6 +1,6 @@
/* MAPIStoreAttachment.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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);
}
@ -137,6 +158,30 @@
return ULLONG_MAX;
}
- (void) copyToAttachment: (MAPIStoreAttachment *) newAttachment
{
void *attachMethod;
enum mapistore_error error;
MAPIStoreEmbeddedMessage *embeddedMessage, *newEmbeddedMessage;
[self copyPropertiesToObject: newAttachment];
attachMethod = NULL;
error = [self getProperty: &attachMethod
withTag: PidTagAttachMethod
inMemCtx: NULL];
if (error == MAPISTORE_SUCCESS && attachMethod)
{
if (*(uint32_t *) attachMethod == afEmbeddedMessage)
{
embeddedMessage = [self openEmbeddedMessage];
newEmbeddedMessage = [newAttachment createEmbeddedMessage];
[embeddedMessage copyToMessage: newEmbeddedMessage];
}
talloc_free (attachMethod);
}
}
/* subclasses */
- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage
{

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreAttachmentTable.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

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

View File

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

View File

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

@ -1,6 +1,6 @@
/* MAPIStoreCalendarAttachment.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,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

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

View File

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

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

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

View File

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

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

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreContactsAttachment.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreContactsFolder.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreContactsMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
@ -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"
@ -109,6 +110,28 @@
return MAPISTORE_SUCCESS;
}
- (int) getPidTagAlternateRecipientAllowed: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getYes: data inMemCtx: memCtx];
}
- (int) getPidTagMessageFlags: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, MSGFLAG_READ);
return MAPISTORE_SUCCESS;
}
- (int) getPidTagDeleteAfterSubmit: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidTagMessageClass: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -179,8 +202,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];
}
@ -188,13 +211,34 @@
- (int) getPidLidFileUnder: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidTagDisplayName: data inMemCtx: memCtx];
NSString *surName, *givenName, *middleName;
NSMutableString *fileUnder;
CardElement *n;
n = [[sogoObject vCard] n];
surName = [n flattenedValueAtIndex: 0
forKey: @""];
fileUnder = [surName mutableCopy];
[fileUnder autorelease];
[fileUnder appendString: @","];
givenName = [n flattenedValueAtIndex: 1
forKey: @""];
if ([givenName length] > 0)
[fileUnder appendFormat: @" %@", givenName];
middleName = [n flattenedValueAtIndex: 2
forKey: @""];
if ([middleName length] > 0)
[fileUnder appendFormat: @" %@", middleName];
*data = [fileUnder asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
- (int) getPidLidFileUnderId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0xffffffff);
*data = MAPILongValue (memCtx, 0x00008017); /* what ol2003 sets */
return MAPISTORE_SUCCESS;
}
@ -208,7 +252,7 @@
vCard = [sogoObject vCard];
fn = [vCard fn];
email = [vCard preferredEMail];
*data = [[NSString stringWithFormat: @"%@ <%@>", fn, email]
*data = [[NSString stringWithFormat: @"%@ (%@)", fn, email]
asUnicodeInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
@ -217,7 +261,8 @@
- (int) getPidLidEmail1OriginalDisplayName: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getPidLidEmail1DisplayName: data inMemCtx: memCtx];
return [self getPidLidEmail1EmailAddress: data
inMemCtx: memCtx];
}
- (int) getPidLidEmail1EmailAddress: (void **) data
@ -767,8 +812,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

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

View File

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

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreContext.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2010-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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];
@ -363,7 +366,8 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
NSString *objectURL, *url;
// TDB_DATA key, dbuf;
url = [contextUrl absoluteString];
url = [[contextUrl absoluteString]
stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
objectURL = [[userContext mapping] urlFromID: fmid];
if (objectURL)
{
@ -414,39 +418,46 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
MAPIStoreFolder *baseFolder;
SOGoFolder *currentFolder;
WOContext *woContext;
NSString *path;
NSString *path, *urlString;
NSArray *pathComponents;
NSUInteger count, max;
mapping = [userContext mapping];
if (![mapping urlFromID: newFid])
[mapping registerURL: [contextUrl absoluteString]
withID: newFid];
{
urlString = [[contextUrl absoluteString]
stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
[mapping registerURL: urlString
withID: newFid];
}
[userContext activateWithUser: activeUser];
woContext = [userContext woContext];
[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 +466,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,6 +1,6 @@
/* MAPIStoreFSFolder.m - this file is part of SOGo
/* MAPIStoreDBFolder.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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,127 @@ 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) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
isMove: (BOOL) isMove
isRecursive: (BOOL) isRecursive
{
enum mapistore_error rc;
NSString *path, *pathComponent, *targetPath, *newPath;
NSString *newURL;
MAPIStoreMapping *mapping;
NSRange slashRange;
if (isMove && [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];
[targetFolder cleanupCaches];
rc = MAPISTORE_SUCCESS;
}
else
rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName
isMove: isMove
isRecursive: isRecursive];
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 +196,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 +209,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 +254,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,6 +1,6 @@
/* MAPIStoreFSMessage.m - this file is part of SOGo
/* MAPIStoreDBMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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

@ -1,6 +1,6 @@
/* MAPIStoreEmbeddedMessage.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -26,13 +26,6 @@
#import "MAPIStoreMessage.h"
@interface MAPIStoreEmbeddedMessage : MAPIStoreMessage
{
id attachment;
}
+ (id) embeddedMessageWithAttachment: (id) newAttachment;
- (id) initWithAttachment: (id) newAttachment;
@end

View File

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

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

@ -1,6 +1,6 @@
/* MAPIStoreFAIMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

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

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

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

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

@ -1,6 +1,6 @@
/* MAPIStoreFolder.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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,11 @@
andChangeKeys: (struct Binary_r **) targetChangeKeys
wantCopy: (uint8_t) want_copy;
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
isMove: (BOOL) isMove
isRecursive: (BOOL) isRecursive;
- (int) getDeletedFMIDs: (struct I8Array_r **) fmidsPtr
andCN: (uint64_t *) cnPtr
fromChangeNumber: (uint64_t) changeNum

View File

@ -1,6 +1,6 @@
/* MAPIStoreFolder.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -23,7 +23,9 @@
/* TODO: main key arrays must be initialized */
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSString.h>
@ -45,11 +47,12 @@
#import "MAPIStoreSamDBUtils.h"
#import "MAPIStoreTypes.h"
#import "MAPIStoreUserContext.h"
#import "NSData+MAPIStore.h"
#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 +82,69 @@ 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, *escapedURL, *folderName;
NSArray *parts;
NSUInteger lastPartIdx;
MAPIStoreUserContext *userContext;
escapedURL = [[self url]
stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
folderURL = [NSURL URLWithString: escapedURL];
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 +158,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
inContainer: newContainer])
&& newContainer)
{
[self _setupAuxiliaryObjects];
[self setupAuxiliaryObjects];
}
return self;
@ -129,13 +168,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 +184,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 +216,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 +227,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 +308,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 +404,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 +427,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (int) deleteFolder
{
[propsMessage delete];
[propsFolder delete];
[faiFolder delete];
// [propsMessage delete];
[dbFolder delete];
[self cleanupCaches];
@ -615,13 +658,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
int rc;
MAPIStoreMessage *sourceMsg, *destMsg;
TALLOC_CTX *memCtx;
struct SPropTagArray *availableProps;
bool *exclusions;
NSUInteger count;
enum MAPITAGS propTag;
struct SRow *aRow;
int error;
void *data;
struct SRow aRow;
struct SPropValue property;
memCtx = talloc_zero (NULL, TALLOC_CTX);
rc = [sourceFolder openMessage: &sourceMsg
@ -631,56 +669,23 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
if (rc != MAPISTORE_SUCCESS)
goto end;
rc = [sourceMsg getAvailableProperties: &availableProps
inMemCtx: memCtx];
if (rc != MAPISTORE_SUCCESS)
goto end;
exclusions = talloc_array(NULL, bool, 65536);
exclusions[PR_ROW_TYPE >> 16] = true;
exclusions[PR_INSTANCE_KEY >> 16] = true;
exclusions[PR_INSTANCE_NUM >> 16] = true;
exclusions[PR_INST_ID >> 16] = true;
exclusions[PR_FID >> 16] = true;
exclusions[PR_MID >> 16] = true;
exclusions[PR_SOURCE_KEY >> 16] = true;
exclusions[PR_PARENT_SOURCE_KEY >> 16] = true;
exclusions[PR_PARENT_FID >> 16] = true;
exclusions[PR_CHANGE_KEY >> 16] = true;
exclusions[PR_PREDECESSOR_CHANGE_LIST >> 16] = true;
aRow = talloc_zero (memCtx, struct SRow);
aRow->lpProps = talloc_array (aRow, struct SPropValue, 65535);
for (count = 0; count < availableProps->cValues; count++)
{
propTag = availableProps->aulPropTag[count];
if (!exclusions[propTag >> 16])
{
error = [sourceMsg getProperty: &data
withTag: propTag
inMemCtx: aRow];
if (error == MAPISTORE_SUCCESS && data)
{
set_SPropValue_proptag(&aRow->lpProps[aRow->cValues], propTag, data);
aRow->cValues++;
}
}
}
if (targetChangeKey)
{
set_SPropValue_proptag(&aRow->lpProps[aRow->cValues], PR_CHANGE_KEY, targetChangeKey);
aRow->cValues++;
}
rc = [self createMessage: &destMsg withMID: targetMid
isAssociated: [sourceMsg isKindOfClass: MAPIStoreFAIMessageK]];
if (rc != MAPISTORE_SUCCESS)
goto end;
rc = [destMsg addPropertiesFromRow: aRow];
if (rc != MAPISTORE_SUCCESS)
goto end;
[sourceMsg copyToMessage: destMsg];
if (targetChangeKey)
{
property.ulPropTag = PidTagChangeKey;
property.value.bin = *targetChangeKey;
aRow.cValues = 1;
aRow.lpProps = &property;
rc = [destMsg addPropertiesFromRow: &aRow];
if (rc != MAPISTORE_SUCCESS)
goto end;
}
[destMsg save];
if (!wantCopy)
rc = [sourceFolder deleteMessageWithMID: srcMid andFlags: 0];
@ -757,6 +762,122 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
return rc;
}
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
isMove: (BOOL) isMove
isRecursive: (BOOL) isRecursive
{
enum mapistore_error rc;
NSAutoreleasePool *pool;
struct SRow folderRow;
struct SPropValue nameProperty;
MAPIStoreFolder *subFolder, *newFolder;
NSArray *children;
MAPIStoreMapping *mapping;
MAPIStoreMessage *message, *targetMessage;
NSUInteger count, max;
NSString *childKey;
uint64_t fmid;
/* TODO: one possible issue with this algorithm is that moved messages will
lack a version number and will all be assigned a new one, even though
they have not changed. This also means that they will be transferred
again to the client during a sync operation. */
if ([targetFolder supportsSubFolders])
{
mapping = [self mapping];
if (!newFolderName)
newFolderName = [sogoObject displayName];
nameProperty.ulPropTag = PidTagDisplayName;
nameProperty.value.lpszW = [newFolderName UTF8String];
folderRow.lpProps = &nameProperty;
folderRow.cValues = 1;
rc = [targetFolder createFolder: &folderRow
withFID: [self objectId]
andKey: &childKey];
if (rc == MAPISTORE_SUCCESS)
{
newFolder = [targetFolder lookupFolder: childKey];
[self copyPropertiesToObject: newFolder];
pool = [NSAutoreleasePool new];
children = [self messageKeys];
max = [children count];
for (count = 0; count < max; count++)
{
childKey = [children objectAtIndex: count];
message = [self lookupMessage: childKey];
targetMessage = [newFolder createMessage: NO];
[targetMessage setIsNew: YES];
[message copyToMessage: targetMessage];
if (isMove)
{
fmid = [mapping idFromURL: [message url]];
[self deleteMessageWithMID: fmid andFlags: 0];
[mapping registerURL: [targetMessage url]
withID: fmid];
}
[targetMessage save];
}
[pool release];
pool = [NSAutoreleasePool new];
children = [self faiMessageKeys];
max = [children count];
for (count = 0; count < max; count++)
{
childKey = [children objectAtIndex: count];
message = [self lookupFAIMessage: childKey];
targetMessage = [newFolder createMessage: YES];
[targetMessage setIsNew: YES];
[message copyToMessage: targetMessage];
if (isMove)
{
fmid = [mapping idFromURL: [message url]];
[self deleteMessageWithMID: fmid andFlags: 0];
[mapping registerURL: [targetMessage url]
withID: fmid];
}
[targetMessage save];
}
[pool release];
if (isRecursive)
{
pool = [NSAutoreleasePool new];
children = [self folderKeys];
max = [children count];
for (count = 0; count < max; count++)
{
childKey = [children objectAtIndex: count];
subFolder = [self lookupFolder: childKey];
[subFolder moveCopyToFolder: newFolder withNewName: nil
isMove: isMove
isRecursive: isRecursive];
}
[pool release];
}
if (isMove)
{
fmid = [mapping idFromURL: [self url]];
[mapping unregisterURLWithID: fmid];
[self deleteFolder];
[mapping registerURL: [newFolder url]
withID: fmid];
}
[targetFolder cleanupCaches];
}
[self cleanupCaches];
}
else
rc = MAPISTORE_ERR_DENIED;
return rc;
}
- (SOGoFolder *) aclFolder
{
[self subclassResponsibility: _cmd];
@ -1004,7 +1125,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 +1137,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
currentProp++;
}
[propsMessage appendProperties: propsCopy];
[propsMessage save];
[propsCopy release];
[properties addEntriesFromDictionary: propsCopy];
[dbFolder save];
}
- (NSArray *) messageKeys
@ -1039,9 +1163,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
@ -1192,7 +1317,51 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
- (int) getPidTagAccessLevel: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = MAPILongValue (memCtx, 0x01);
SOGoUser *ownerUser;
BOOL userIsOwner;
ownerUser = [[self userContext] sogoUser];
userIsOwner = [[context activeUser] isEqual: ownerUser];
*data = MAPILongValue (memCtx, (userIsOwner) ? 0x01 : 0x00);
return MAPISTORE_SUCCESS;
}
- (int) getPidTagRights: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
uint32_t rights = 0;
SOGoUser *ownerUser;
BOOL userIsOwner;
ownerUser = [[self userContext] sogoUser];
userIsOwner = [[context activeUser] isEqual: ownerUser];
if (userIsOwner || [self subscriberCanReadMessages])
rights |= RightsReadItems;
if (userIsOwner || [self subscriberCanCreateMessages])
rights |= RightsCreateItems;
if (userIsOwner || [self subscriberCanModifyMessages])
rights |= RightsEditOwn | RightsEditAll;
if (userIsOwner || [self subscriberCanDeleteMessages])
rights |= RightsDeleteOwn | RightsDeleteAll;
if ((userIsOwner || [self subscriberCanCreateSubFolders])
&& [self supportsSubFolders])
rights |= RightsCreateSubfolders;
if (userIsOwner)
rights |= RightsFolderOwner | RightsFolderContact;
*data = MAPILongValue (memCtx, rights);
return MAPISTORE_SUCCESS;
}
- (int) getPidTagAccessControlListData: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
*data = [[NSData data] asBinaryInMemCtx: memCtx];
return MAPISTORE_SUCCESS;
}
@ -1287,6 +1456,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 +1476,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 +1488,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 +1511,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;
}
@ -1354,7 +1543,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
url = [NSString stringWithFormat: @"%@/", [super url]];
else
{
url = [[context url] absoluteString];
url = [[[context url] absoluteString]
stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
if (![url hasSuffix: @"/"])
url = [NSString stringWithFormat: @"%@/", url];
}
@ -1581,9 +1771,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 +1793,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

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreGCSFolder.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -34,7 +34,7 @@
@interface MAPIStoreGCSFolder : MAPIStoreFolder
{
SOGoMAPIFSMessage *versionsMessage;
SOGoMAPIDBMessage *versionsMessage;
NSArray *activeUserRoles;
EOQualifier *componentQualifier;
}
@ -45,11 +45,8 @@
withChangeKey: (NSData *) newChangeKey;
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSNumber *) changeNum;
- (NSNumber *) changeNumberForMessageWithKey: (NSString *) messageKey;
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey;
- (NSData *) predecessorChangeListForMessageWithKey: (NSString *) messageKey;
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey;
- (NSArray *) activeUserRoles;

View File

@ -1,6 +1,6 @@
/* MAPIStoreGCSFolder.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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
@ -260,6 +261,7 @@ static Class NSNumberK;
- (void) _setChangeKey: (NSData *) changeKey
forMessageEntry: (NSMutableDictionary *) messageEntry
inChangeListOnly: (BOOL) inChangeListOnly
{
struct XID *xid;
NSString *guid;
@ -272,12 +274,15 @@ static Class NSNumberK;
globCnt = [NSData dataWithBytes: xid->Data length: xid->Size];
talloc_free (xid);
/* 1. set change key association */
changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys:
guid, @"GUID",
globCnt, @"LocalId",
nil];
[messageEntry setObject: changeKeyDict forKey: @"ChangeKey"];
if (!inChangeListOnly)
{
/* 1. set change key association */
changeKeyDict = [NSDictionary dictionaryWithObjectsAndKeys:
guid, @"GUID",
globCnt, @"LocalId",
nil];
[messageEntry setObject: changeKeyDict forKey: @"ChangeKey"];
}
/* 2. append/update predecessor change list */
changeList = [messageEntry objectForKey: @"PredecessorChangeList"];
@ -285,7 +290,7 @@ static Class NSNumberK;
{
changeList = [NSMutableDictionary new];
[messageEntry setObject: changeList
forKey: @"PredecessorChangeList"];
forKey: @"PredecessorChangeList"];
[changeList release];
}
[changeList setObject: globCnt forKey: guid];
@ -349,6 +354,7 @@ static Class NSNumberK;
[sortOrdering retain];
}
[versionsMessage reloadIfNeeded];
currentProperties = [versionsMessage properties];
lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"];
@ -430,7 +436,8 @@ static Class NSNumberK;
[messageEntry setObject: changeNumber forKey: @"version"];
changeKey = [self getReplicaKeyFromGlobCnt: newChangeNum >> 16];
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
[self _setChangeKey: changeKey forMessageEntry: messageEntry
inChangeListOnly: NO];
[mapping setObject: cLastModified forKey: changeNumber];
@ -451,7 +458,6 @@ static Class NSNumberK;
forKey: @"SyncLastSynchronisationDate"];
[currentProperties setObject: lastModificationDate
forKey: @"SyncLastModificationDate"];
[versionsMessage appendProperties: currentProperties];
[versionsMessage save];
}
}
@ -462,10 +468,21 @@ static Class NSNumberK;
- (void) updateVersionsForMessageWithKey: (NSString *) messageKey
withChangeKey: (NSData *) newChangeKey
{
[self synchroniseCache];
NSMutableDictionary *messages, *messageEntry;
[self synchroniseCache];
if (newChangeKey)
[self setChangeKey: newChangeKey forMessageWithKey: messageKey];
{
messages = [[versionsMessage properties] objectForKey: @"Messages"];
messageEntry = [messages objectForKey: messageKey];
if (!messageEntry)
[NSException raise: @"MAPIStoreIOException"
format: @"no version record found for message '%@'",
messageKey];
[self _setChangeKey: newChangeKey forMessageEntry: messageEntry
inChangeListOnly: YES];
[versionsMessage save];
}
}
- (NSNumber *) lastModifiedFromMessageChangeNumber: (NSNumber *) changeNum
@ -491,26 +508,6 @@ static Class NSNumberK;
return changeNumber;
}
- (void) setChangeKey: (NSData *) changeKey
forMessageWithKey: (NSString *) messageKey
{
NSMutableDictionary *messages;
NSMutableDictionary *messageEntry;
messages = [[versionsMessage properties] objectForKey: @"Messages"];
messageEntry = [messages objectForKey: messageKey];
if (!messageEntry)
{
[self synchroniseCache];
messageEntry = [messages objectForKey: messageKey];
if (!messageEntry)
abort ();
}
[self _setChangeKey: changeKey forMessageEntry: messageEntry];
[versionsMessage save];
}
- (NSData *) changeKeyForMessageWithKey: (NSString *) messageKey
{
NSDictionary *messages, *changeKeyDict;

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreGCSMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreMIME.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*

View File

@ -1,6 +1,6 @@
/* MAPIStoreMailAttachment.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -30,9 +30,11 @@
@interface MAPIStoreMailAttachment : MAPIStoreAttachment
{
NSDictionary *bodyInfo;
SOGoMailBodyPart *bodyPart;
}
- (void) setBodyInfo: (NSDictionary *) newBodyInfo;
- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart;
@end

View File

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

@ -1,6 +1,6 @@
/* MAPIStoreMailContext.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2010-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -26,6 +26,9 @@
#import "MAPIStoreContext.h"
@interface MAPIStoreMailContext : MAPIStoreContext
- (void) updateURLWithFolderName: (NSString *) newFolderName;
@end
@interface MAPIStoreOutboxContext : MAPIStoreMailContext

View File

@ -1,6 +1,6 @@
/* MAPIStoreMailContext.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2010-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -23,7 +23,8 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <NGExtensions/NSString+misc.h>
#import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailFolder.h>
@ -203,6 +204,34 @@ MakeDisplayFolderName (NSString *folderName)
return [[userContext rootFolders] objectForKey: @"mail"];
}
- (void) updateURLWithFolderName: (NSString *) newFolderName
{
NSString *urlString, *escapedName;
NSMutableArray *pathComponents;
BOOL hasSlash;
NSUInteger max, folderNameIdx;
NSURL *newURL;
/* we do not need to unescape the url here as it will be reassembled later
in the method */
urlString = [contextUrl absoluteString];
hasSlash = [urlString hasSuffix: @"/"];
pathComponents = [[urlString componentsSeparatedByString: @"/"]
mutableCopy];
[pathComponents autorelease];
max = [pathComponents count];
if (hasSlash)
folderNameIdx = max - 2;
else
folderNameIdx = max - 1;
escapedName = [newFolderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
[pathComponents replaceObjectAtIndex: folderNameIdx
withObject: escapedName];
urlString = [pathComponents componentsJoinedByString: @"/"];
newURL = [NSURL URLWithString: urlString];
ASSIGN (contextUrl, newURL);
}
@end
@implementation MAPIStoreOutboxContext

View File

@ -1,6 +1,6 @@
/* MAPIStoreMailFolder.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -36,7 +36,7 @@
@interface MAPIStoreMailFolder : MAPIStoreFolder
{
SOGoMAPIFSMessage *versionsMessage;
SOGoMAPIDBMessage *versionsMessage;
}
- (BOOL) ensureFolderExists;

View File

@ -1,6 +1,6 @@
/* MAPIStoreMailFolder.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -49,19 +49,20 @@
#import "MAPIStoreAppointmentWrapper.h"
#import "MAPIStoreContext.h"
#import "MAPIStoreFAIMessage.h"
#import "MAPIStoreMailContext.h"
#import "MAPIStoreMailMessageTable.h"
#import "MAPIStoreMapping.h"
#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 +75,7 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
+ (void) initialize
{
SOGoMailFolderK = [SOGoMailFolder class];
MAPIStoreMailFolderK = [MAPIStoreMailFolder class];
MAPIStoreOutboxFolderK = [MAPIStoreOutboxFolder class];
[MAPIStoreAppointmentWrapper class];
}
@ -97,8 +99,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
@ -108,9 +111,10 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
- (void) addProperties: (NSDictionary *) newProperties
{
NSString *newDisplayName;
NSString *newDisplayName, *newNameInContainer;
NSMutableDictionary *propsCopy;
NSNumber *key;
uint64_t fid;
key = MAPIPropertyKey (PR_DISPLAY_NAME_UNICODE);
newDisplayName = [newProperties objectForKey: key];
@ -119,7 +123,16 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
&& ![[(SOGoMailFolder *) sogoObject displayName]
isEqualToString: newDisplayName])
{
fid = [self objectId];
[(SOGoMailFolder *) sogoObject renameTo: newDisplayName];
newNameInContainer = [sogoObject nameInContainer];
if (!container)
[(MAPIStoreMailContext *) context
updateURLWithFolderName: newNameInContainer];
[[self mapping] updateID: fid withURL: [self url]];
[dbFolder setNameInContainer: newNameInContainer];
[self cleanupCaches];
propsCopy = [newProperties mutableCopy];
[propsCopy removeObjectForKey: key];
[propsCopy autorelease];
@ -202,7 +215,7 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
}
- (int) getPidTagContentUnreadCount: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
inMemCtx: (TALLOC_CTX *) memCtx
{
EOQualifier *searchQualifier;
uint32_t longValue;
@ -393,6 +406,11 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
return permissionEntries;
}
- (BOOL) supportsSubFolders
{
return YES;
}
/* synchronisation */
/* Tree:
@ -489,10 +507,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 +629,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]];
[currentProperties setObject: ti
forKey: @"SyncLastSynchronisationDate"];
[versionsMessage appendProperties: currentProperties];
[versionsMessage save];
}
@ -978,14 +993,17 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
}
/* Update the change keys */
[self synchroniseCache];
for (count = 0; count < midCount; count++)
if (targetChangeKeys)
{
changeKey = [NSData dataWithBinary: targetChangeKeys[count]];
messageKey = [NSString stringWithFormat: @"%@.eml",
[destUIDs objectAtIndex: count]];
[self setChangeKey: changeKey
forMessageWithKey: messageKey];
[self synchroniseCache];
for (count = 0; count < midCount; count++)
{
changeKey = [NSData dataWithBinary: targetChangeKeys[count]];
messageKey = [NSString stringWithFormat: @"%@.eml",
[destUIDs objectAtIndex: count]];
[self setChangeKey: changeKey
forMessageWithKey: messageKey];
}
}
[self postNotificationsForMoveCopyMessagesWithMIDs: srcMids
@ -1002,21 +1020,133 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
return MAPISTORE_SUCCESS;
}
- (MAPIStoreMessage *) createMessage
- (enum mapistore_error) moveCopyToFolder: (MAPIStoreFolder *) targetFolder
withNewName: (NSString *) newFolderName
isMove: (BOOL) isMove
isRecursive: (BOOL) isRecursive
{
MAPIStoreMailVolatileMessage *newMessage;
SOGoMAPIVolatileMessage *newObject;
enum mapistore_error rc;
NSURL *folderURL, *newFolderURL;
struct SRow folderRow;
struct SPropValue nameProperty;
MAPIStoreMailFolder *newFolder;
SOGoMailFolder *targetSOGoFolder;
NSMutableArray *uids;
NSArray *childKeys;
NSUInteger count, max;
NGImap4Connection *connection;
NGImap4Client *client;
NSString *newURL, *parentDBFolderPath, *childKey, *folderIMAPName, *newFolderIMAPName;
NSException *error;
MAPIStoreMapping *mapping;
NSDictionary *result;
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 displayName];
targetSOGoFolder = [targetFolder sogoObject];
if (isMove)
{
newFolderURL = [NSURL
URLWithString: [newFolderName stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]
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
{
nameProperty.ulPropTag = PidTagDisplayName;
nameProperty.value.lpszW = [newFolderName UTF8String];
folderRow.lpProps = &nameProperty;
folderRow.cValues = 1;
rc = [targetFolder createFolder: &folderRow
withFID: -1
andKey: &childKey];
if (rc == MAPISTORE_SUCCESS)
{
newFolder = [targetFolder lookupFolder: childKey];
connection = [sogoObject imap4Connection];
folderIMAPName = [connection
imap4FolderNameForURL: [sogoObject imap4URL]];
newFolderIMAPName = [connection
imap4FolderNameForURL: [[newFolder sogoObject] imap4URL]];
client = [connection client];
[client select: folderIMAPName];
childKeys = [self messageKeys];
max = [childKeys count];
uids = [NSMutableArray arrayWithCapacity: max];
for (count = 0; count < max; count++)
{
childKey = [childKeys objectAtIndex: count];
[uids addObject: [self messageUIDFromMessageKey: childKey]];
}
result = [client copyUids: uids
toFolder: newFolderIMAPName];
if ([[result objectForKey: @"result"] boolValue])
{
if (isRecursive)
{
childKeys = [self folderKeys];
max = [childKeys count];
for (count = 0; count < max; count++)
{
childKey = [childKeys objectAtIndex: count];
[[self lookupFolder: childKey]
moveCopyToFolder: newFolder
withNewName: nil
isMove: NO
isRecursive: YES];
}
}
}
else
rc = MAPISTORE_ERROR;
}
}
[targetFolder cleanupCaches];
}
else
rc = [super moveCopyToFolder: targetFolder withNewName: newFolderName
isMove: isMove
isRecursive: isRecursive];
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 +1173,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 +1197,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

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

View File

@ -1,6 +1,6 @@
/* MAPIStoreMailMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Ludovic Marcotte <lmarcotte@inverse.ca>
@ -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
{
@ -1013,12 +1000,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidTagDeleteAfterSubmit: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidLidGlobalObjectId: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -1529,8 +1510,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

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

View File

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

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

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

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

@ -1,6 +1,6 @@
/* MAPIStoreMapping.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2010-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -30,6 +30,8 @@
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/NSString+Utilities.h>
#import "MAPIStoreTypes.h"
#import "MAPIStoreMapping.h"
@ -204,6 +206,91 @@ 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;
[oldURL retain];
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);
}
}
[oldURL release];
}
- (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

@ -1,6 +1,6 @@
/* MAPIStoreMessage.h - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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,13 +66,13 @@
- (int) setReadFlag: (uint8_t) flag;
- (enum mapistore_error) saveMessage;
/* helper getters */
- (int) getSMTPAddrType: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx;
- (NSArray *) activeContainerMessageTables;
- (NSArray *) activeUserRoles;
/* move & copy internal ops */
- (void) copyToMessage: (MAPIStoreMessage *) newMessage;
/* subclasses */
- (void) save;

View File

@ -1,6 +1,6 @@
/* MAPIStoreMessage.m - this file is part of SOGo
*
* Copyright (C) 2011 Inverse inc
* Copyright (C) 2011-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -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
@ -424,6 +425,41 @@ rtf2html (NSData *compressedRTF)
andType: MAPISTORE_MESSAGE_TABLE];
}
- (void) copyToMessage: (MAPIStoreMessage *) newMessage
{
TALLOC_CTX *memCtx;
struct mapistore_message *messageData;
NSArray *keys;
NSUInteger count, max;
NSString *key;
MAPIStoreAttachment *attachment, *newAttachment;
memCtx = talloc_zero (NULL, TALLOC_CTX);
/* message headers and recipients */
[self getMessageData: &messageData inMemCtx: memCtx];
[newMessage modifyRecipientsWithRecipients: messageData->recipients
andCount: messageData->recipients_count
andColumns: messageData->columns];
/* properties */
[self copyPropertiesToObject: newMessage];
/* attachments */
keys = [self attachmentKeys];
max = [keys count];
for (count = 0; count < max; count++)
{
key = [keys objectAtIndex: count];
attachment = [self lookupAttachment: key];
newAttachment = [newMessage createAttachment];
[attachment copyToAttachment: newAttachment];
}
talloc_free (memCtx);
}
- (enum mapistore_error) saveMessage
{
enum mapistore_error rc;
@ -443,62 +479,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 +554,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 +654,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 +695,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 +758,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
@ -737,6 +801,12 @@ rtf2html (NSData *compressedRTF)
return [self getEmptyString: data inMemCtx: memCtx];
}
- (int) getPidTagDeleteAfterSubmit: (void **) data // TODO
inMemCtx: (TALLOC_CTX *) memCtx
{
return [self getNo: data inMemCtx: memCtx];
}
- (int) getPidTagDisplayTo: (void **) data
inMemCtx: (TALLOC_CTX *) memCtx
{
@ -792,7 +862,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

@ -1,6 +1,6 @@
/* MAPIStoreMessageTable.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc
* Copyright (C) 2010-2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -28,6 +28,7 @@
@interface MAPIStoreMessageTable : MAPIStoreTable
- (void) setSortOrder: (const struct SSortOrderSet *) set;
- (void) notifyChangesForChild: (MAPIStoreMessage *) child;
@end

View File

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

@ -1,6 +1,6 @@
/* MAPIStoreNotesContext.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
* Copyright (C) 2010-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@ -23,9 +23,9 @@
#ifndef MAPISTORENOTESCONTEXT_H
#define MAPISTORENOTESCONTEXT_H
#import "MAPIStoreFSBaseContext.h"
#import "MAPIStoreDBBaseContext.h"
@interface MAPIStoreNotesContext : MAPIStoreFSBaseContext
@interface MAPIStoreNotesContext : MAPIStoreDBBaseContext
@end

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