propagate from branch 'ca.inverse.sogo.1_3_18' (head 1447a01e5c74f601142742ed11b455e307cc9051)
to branch 'ca.inverse.sogo' (head 22a3b958acddeb274e788d95f5da332880c64d78) Monotone-Parent: 1447a01e5c74f601142742ed11b455e307cc9051 Monotone-Parent: 22a3b958acddeb274e788d95f5da332880c64d78 Monotone-Revision: f418b89e20c4272dbbbddf4ef8ec5de8e414c52e Monotone-Author: jraby@inverse.ca Monotone-Date: 2012-08-14T14:42:37 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
commit
a01ddf2156
341
ChangeLog
341
ChangeLog
|
@ -1,3 +1,118 @@
|
||||||
|
2012-08-13 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreSOGo.m (sogo_properties_get_uri): removed
|
||||||
|
useless backend method.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreFolder.m (-createFolder:withRow:andFID:):
|
||||||
|
append a "/" to the new folder url when registering with the
|
||||||
|
url/id mapper.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreDBFolder.m (-moveToFolder:withNewName:):
|
||||||
|
implemented method.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMailFolder.m (-moveToFolder:withNewName:):
|
||||||
|
invoke changePathTo: on the dbFolder.
|
||||||
|
|
||||||
|
* OpenChange/SOGoMAPIDBFolder.m (-changePathTo:): overriden method
|
||||||
|
in order to update children records too.
|
||||||
|
|
||||||
|
* OpenChange/SOGoMAPIDBObject.m (-performBatchSQLQueries:) new
|
||||||
|
method to perform void queries under a transaction.
|
||||||
|
(-changePathTo:) new method that updates the references for the
|
||||||
|
object record in the dbfs table.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/NSString+Utilities.m
|
||||||
|
(-stringByReplacingPrefix:withPrefix:): new self-explicit method.
|
||||||
|
|
||||||
|
* OpenChange/SOGoMAPIDBFolder.m
|
||||||
|
(-childKeysOfType:includeDeleted:matchingQualifier:andSortOrderings:):
|
||||||
|
records now have a c_parent_path column in order to avoid fetch
|
||||||
|
the children of children due to the nature of our "LIKE" clause.
|
||||||
|
|
||||||
|
* OpenChange/SOGoMAPIDBObject.m (-save): records now have a
|
||||||
|
c_parent_path.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMailFolder.m (-supportsSubFolders):
|
||||||
|
overriden method to return YES.
|
||||||
|
|
||||||
|
2012-08-12 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMailFolder.m (-moveToFolder:withName:): if
|
||||||
|
the new name is not provided (unlikely), the computed new name
|
||||||
|
must not have the "folder" prefix.
|
||||||
|
We now also make use of -[MAPIStoreMapping updateID:withURL:] to
|
||||||
|
change the references in the mapping database.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreFolder.m (-objectId): folder keys always end
|
||||||
|
with a "/" by convention.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMapping.m (-updateID:withURL:): new method
|
||||||
|
that perform a change of url on container and leaf entries.
|
||||||
|
|
||||||
|
2012-08-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreSOGo.m (sogo_properties_get_uri): new
|
||||||
|
backend method.
|
||||||
|
|
||||||
|
2012-08-10 Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||||
|
|
||||||
|
* Changed OpenChange/SOGoMAPIDBObject.m so we use
|
||||||
|
GNUstep's binary encoding - which is an order or
|
||||||
|
magnitude faster at encoding data than any other formats.
|
||||||
|
|
||||||
|
2012-08-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreSOGo.m (sogo_folder_move_folder)
|
||||||
|
(sogo_folder_copy_folder): the object on which the backend method
|
||||||
|
is invoked is now the folder being moved rather than its parent.
|
||||||
|
|
||||||
|
2012-08-09 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMailFolder.m
|
||||||
|
(-moveFolderWithFID:fromFolder:withNewName:): first implementation
|
||||||
|
for IMAP folders.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreSOGo.m (sogo_folder_move_folder)
|
||||||
|
(sogo_folder_copy_folder): new backend methods.
|
||||||
|
(sogo_folder_move_folder): do not instantiate an NSString from a
|
||||||
|
NULL "new_folder_name" parameter.
|
||||||
|
|
||||||
|
2012-08-08 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreCalendarMessage.m (-save): generate a
|
||||||
|
"nameInContainer" for the new object iif it is not set yet. If
|
||||||
|
set, we generate a new UID from it instead.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMessage.m (-saveMessage): make sure that the
|
||||||
|
PidTagChangeKey and PidTagChangeNumber props are no longer set in
|
||||||
|
the properties dict after the save occurred.
|
||||||
|
|
||||||
|
* OpenChange/MAPIApplication.m (-shouldSetupSignalHandlers):
|
||||||
|
overriden method by returning "NO".
|
||||||
|
|
||||||
|
2012-08-07 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* SoObjects/Appointments/SOGoAptMailNotification.m (-setupValues):
|
||||||
|
test whether each value is non-nil before adding it to the
|
||||||
|
dictionary.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMailVolatileMessage.m (-save): restored
|
||||||
|
registration of message url when saved.
|
||||||
|
|
||||||
|
2012-08-06 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreRecurrenceUtils.m (-[iCalRecurrenceRule
|
||||||
|
fillRecurrencePattern:withEvent:inTimeZone:inMemCtx:]): fixed a
|
||||||
|
crash occurring when the exception has no recurrence-id and
|
||||||
|
ignore the specific occurrence.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMailVolatileMessage.m (MakeMessageBody):
|
||||||
|
take "attachmentParts" parameter, deduced from the ivar with the
|
||||||
|
corresponding name.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreSOGoObject.m (-objectId): force generation
|
||||||
|
of objectId by parent, whether it is a folder or not.
|
||||||
|
|
||||||
2012-08-07 Francis Lachapelle <flachapelle@inverse.ca>
|
2012-08-07 Francis Lachapelle <flachapelle@inverse.ca>
|
||||||
|
|
||||||
* UI/Contacts/UIxListEditor.m (-setReferencesValue:): check for
|
* UI/Contacts/UIxListEditor.m (-setReferencesValue:): check for
|
||||||
|
@ -6,9 +121,15 @@
|
||||||
2012-08-03 Jean Raby <jraby@inverse.ca>
|
2012-08-03 Jean Raby <jraby@inverse.ca>
|
||||||
|
|
||||||
* SoObjects/SOGo/LDAPSource.m (changePasswordForLogin):
|
* SoObjects/SOGo/LDAPSource.m (changePasswordForLogin):
|
||||||
if userPasswordAlgorithm was not set or was set to "none",
|
if userPasswordAlgorithm was not set or was set to "none",
|
||||||
use the plaintext password directly instead of using '{none}plaintext'
|
use the plaintext password directly instead of using '{none}plaintext'
|
||||||
which isn't valid.
|
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>
|
2012-07-31 Jean Raby <jraby@inverse.ca>
|
||||||
|
|
||||||
|
@ -21,6 +142,22 @@
|
||||||
(-sieveScriptWithRequirements:): filters must not be conditional
|
(-sieveScriptWithRequirements:): filters must not be conditional
|
||||||
to each other.
|
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>
|
2012-07-25 Francis Lachapelle <flachapelle@inverse.ca>
|
||||||
|
|
||||||
* SoObjects/Mailer/SOGoMailFolder.m
|
* SoObjects/Mailer/SOGoMailFolder.m
|
||||||
|
@ -38,6 +175,15 @@
|
||||||
* UI/WebServerResources/MailerUI.js (initMailer): define default
|
* UI/WebServerResources/MailerUI.js (initMailer): define default
|
||||||
columns widths when not set.
|
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>
|
2012-07-24 Francis Lachapelle <flachapelle@inverse.ca>
|
||||||
|
|
||||||
* UI/WebServerResources/UIxPreferences.js (savePreferences):
|
* UI/WebServerResources/UIxPreferences.js (savePreferences):
|
||||||
|
@ -56,8 +202,115 @@
|
||||||
(_shouldDisplayAsAttachment:): refactored to consider
|
(_shouldDisplayAsAttachment:): refactored to consider
|
||||||
the "bodyId" parameter only for non text/* parts.
|
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>
|
2012-07-20 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/NSObject+MAPIStore.m (-getSMTPAddrType:inMemCtx:):
|
||||||
|
new helper getter.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreSOGo.m
|
||||||
|
(sogo_message_attachment_create_embedded_message): new backend method.
|
||||||
|
|
||||||
|
* OpenChange/NSObject+MAPIStore.m
|
||||||
|
(+fillAvailableProperties:withExclusions:): new method that fills
|
||||||
|
an existing array of properties with properties existing in
|
||||||
|
another class, as long as they are not listed in the array of
|
||||||
|
exclusions.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObject.m (-init): assigned a mutable array
|
||||||
|
to "proxies"
|
||||||
|
(-canGetProperty:): test the proxies for the availability of
|
||||||
|
properties so that -getAvailableProperties:inMemCtx: can return an
|
||||||
|
accurate result.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMessage.m (-getPidTagSubject:inMemCtx:): now
|
||||||
|
compute the return value based on PidTagNormalizedSubject and
|
||||||
|
PidTagSubjectPrefix as PidTagSubject is never actually set from
|
||||||
|
the client.
|
||||||
|
|
||||||
|
2012-07-19 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObject.m (-nameInContainer): moved method
|
||||||
|
from MAPIStoreSOGoObject and made mandatory for subclasses.
|
||||||
|
(-url): new methed moved from MAPIStoreSOGoObject.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreAppointmentWrapper.m: now a subclass of
|
||||||
|
MAPIStoreObjectProxy.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreCalendarMessage.m
|
||||||
|
(-initWithSOGoObject:inContainer:): we now register our
|
||||||
|
appointment wrapper as a proxy.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObject.m (-addProxy:): new method that keeps
|
||||||
|
proxy objects in the new "proxies" ivar.
|
||||||
|
(-getProperty:withTag:inMemCtx:): added code that pass the request
|
||||||
|
to the available object proxies, when the property getters have
|
||||||
|
not been found in the local class.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObjectProxy.[hm]: new class module that
|
||||||
|
provide a facility for providing property getters in the name of
|
||||||
|
another class, working around the fact that Objective-C does not
|
||||||
|
provide multiple-inheritance.
|
||||||
|
|
||||||
|
* OpenChange/NSObject+MAPIStore.m
|
||||||
|
(+getAvailableProperties:inMemCtx:)
|
||||||
|
(-getAvailableProperties:inMemCtx:, canGetProperty:): methods
|
||||||
|
moved from MAPIStoreObject.m
|
||||||
|
|
||||||
|
2012-07-18 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreCalendarFolder.m (-createMessage): attach a
|
||||||
|
WOContext to the newEntry in order to enable page templates
|
||||||
|
resolution when notifications are sent.
|
||||||
|
|
||||||
|
* OpenChange/MAPIApplication.m (-init): a WEResourceManager is
|
||||||
|
setup for the application so that page templates can be properly
|
||||||
|
be initialized.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreDBMessage.m (-objectVersion): shift the
|
||||||
|
version number by 16 bits, instead of doing it in -save.
|
||||||
|
(-save): don t swap the bytes of the version number as it would
|
||||||
|
return a wrong change number and a wrong change key for DB objects.
|
||||||
|
|
||||||
|
####### Ancestor
|
||||||
|
======= end
|
||||||
|
2012-07-20 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/NSObject+MAPIStore.m (-getSMTPAddrType:inMemCtx:):
|
||||||
|
new helper getter.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreSOGo.m
|
||||||
|
(sogo_message_attachment_create_embedded_message): new backend method.
|
||||||
|
|
||||||
|
* OpenChange/NSObject+MAPIStore.m
|
||||||
|
(+fillAvailableProperties:withExclusions:): new method that fills
|
||||||
|
an existing array of properties with properties existing in
|
||||||
|
another class, as long as they are not listed in the array of
|
||||||
|
exclusions.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObject.m (-init): assigned a mutable array
|
||||||
|
to "proxies"
|
||||||
|
(-canGetProperty:): test the proxies for the availability of
|
||||||
|
properties so that -getAvailableProperties:inMemCtx: can return an
|
||||||
|
accurate result.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreMessage.m (-getPidTagSubject:inMemCtx:): now
|
||||||
|
compute the return value based on PidTagNormalizedSubject and
|
||||||
|
PidTagSubjectPrefix as PidTagSubject is never actually set from
|
||||||
|
the client.
|
||||||
|
|
||||||
* SoObjects/Appointments/SOGoAppointmentFolder.m
|
* SoObjects/Appointments/SOGoAppointmentFolder.m
|
||||||
(_appendCycleException:firstInstanceCalendarDateRange:fromRow:forRange:withTimeZone:toArray:):
|
(_appendCycleException:firstInstanceCalendarDateRange:fromRow:forRange:withTimeZone:toArray:):
|
||||||
return immediately if the occurrence does not have a valid
|
return immediately if the occurrence does not have a valid
|
||||||
|
@ -76,6 +329,52 @@
|
||||||
method that returns a properly formatted string of the event title
|
method that returns a properly formatted string of the event title
|
||||||
with respect to the current operation (creation/deletion/update).
|
with respect to the current operation (creation/deletion/update).
|
||||||
|
|
||||||
|
2012-07-19 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObject.m (-nameInContainer): moved method
|
||||||
|
from MAPIStoreSOGoObject and made mandatory for subclasses.
|
||||||
|
(-url): new methed moved from MAPIStoreSOGoObject.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreAppointmentWrapper.m: now a subclass of
|
||||||
|
MAPIStoreObjectProxy.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreCalendarMessage.m
|
||||||
|
(-initWithSOGoObject:inContainer:): we now register our
|
||||||
|
appointment wrapper as a proxy.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObject.m (-addProxy:): new method that keeps
|
||||||
|
proxy objects in the new "proxies" ivar.
|
||||||
|
(-getProperty:withTag:inMemCtx:): added code that pass the request
|
||||||
|
to the available object proxies, when the property getters have
|
||||||
|
not been found in the local class.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreObjectProxy.[hm]: new class module that
|
||||||
|
provide a facility for providing property getters in the name of
|
||||||
|
another class, working around the fact that Objective-C does not
|
||||||
|
provide multiple-inheritance.
|
||||||
|
|
||||||
|
* OpenChange/NSObject+MAPIStore.m
|
||||||
|
(+getAvailableProperties:inMemCtx:)
|
||||||
|
(-getAvailableProperties:inMemCtx:, canGetProperty:): methods
|
||||||
|
moved from MAPIStoreObject.m
|
||||||
|
|
||||||
|
2012-07-18 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreCalendarFolder.m (-createMessage): attach a
|
||||||
|
WOContext to the newEntry in order to enable page templates
|
||||||
|
resolution when notifications are sent.
|
||||||
|
|
||||||
|
* OpenChange/MAPIApplication.m (-init): a WEResourceManager is
|
||||||
|
setup for the application so that page templates can be properly
|
||||||
|
be initialized.
|
||||||
|
|
||||||
|
* OpenChange/MAPIStoreDBMessage.m (-objectVersion): shift the
|
||||||
|
version number by 16 bits, instead of doing it in -save.
|
||||||
|
(-save): don t swap the bytes of the version number as it would
|
||||||
|
return a wrong change number and a wrong change key for DB objects.
|
||||||
|
|
||||||
|
####### Ancestor
|
||||||
|
======= end
|
||||||
2012-07-18 Ludovic Marcotte <lmarcotte@inverse.ca>
|
2012-07-18 Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||||
|
|
||||||
* SoObjects/Appointments/SOGoAppointmentObject.m
|
* SoObjects/Appointments/SOGoAppointmentObject.m
|
||||||
|
@ -253,6 +552,25 @@
|
||||||
Show all addresses returned from secondaryEmails.
|
Show all addresses returned from secondaryEmails.
|
||||||
This still need some css tweaks.
|
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>
|
2012-06-29 Jean Raby <jraby@inverse.ca>
|
||||||
|
|
||||||
* SoObjects/SOGo/WORequest+SOGo.[mh]
|
* SoObjects/SOGo/WORequest+SOGo.[mh]
|
||||||
|
@ -263,6 +581,23 @@
|
||||||
Let sogo append system sources if the request comes from an android
|
Let sogo append system sources if the request comes from an android
|
||||||
client even if its user agent matches the IPhoneAddressBook
|
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>
|
2012-06-27 Jean Raby <jraby@inverse.ca>
|
||||||
|
|
||||||
* SoObjects/Appointments/SOGoAppointmentObject.m
|
* SoObjects/Appointments/SOGoAppointmentObject.m
|
||||||
|
|
Binary file not shown.
|
@ -201,6 +201,7 @@ static BOOL debugLeaks;
|
||||||
fileSuffix = [channelURL scheme];
|
fileSuffix = [channelURL scheme];
|
||||||
tc = [cm acquireOpenChannelForURL: channelURL];
|
tc = [cm acquireOpenChannelForURL: channelURL];
|
||||||
|
|
||||||
|
/* FIXME: make use of [EOChannelAdaptor describeTableNames] instead */
|
||||||
tableName = [url lastPathComponent];
|
tableName = [url lastPathComponent];
|
||||||
if ([tc evaluateExpressionX:
|
if ([tc evaluateExpressionX:
|
||||||
[NSString stringWithFormat: @"SELECT count(*) FROM %@",
|
[NSString stringWithFormat: @"SELECT count(*) FROM %@",
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
|
|
||||||
#import <EOControl/EOQualifier.h>
|
#import <EOControl/EOQualifier.h>
|
||||||
|
|
||||||
@class SOGoMAPIVolatileMessage;
|
@class SOGoMAPIDBObject;
|
||||||
|
|
||||||
@interface EOQualifier (MAPIStoreRestrictions)
|
@interface EOQualifier (MAPIStoreRestrictions)
|
||||||
|
|
||||||
- (BOOL) evaluateMAPIVolatileMessage: (SOGoMAPIVolatileMessage *) message;
|
- (BOOL) evaluateSOGoMAPIDBObject: (SOGoMAPIDBObject *) object;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -28,28 +28,28 @@
|
||||||
|
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
#import "SOGoMAPIVolatileMessage.h"
|
#import "EOBitmaskQualifier.h"
|
||||||
|
#import "SOGoMAPIDBObject.h"
|
||||||
|
|
||||||
#import "EOQualifier+MAPI.h"
|
#import "EOQualifier+MAPI.h"
|
||||||
#import "EOBitmaskQualifier.h"
|
|
||||||
|
|
||||||
@implementation EOQualifier (MAPIStoreRestrictions)
|
@implementation EOQualifier (MAPIStoreRestrictions)
|
||||||
|
|
||||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) evaluateMAPIVolatileMessage: (SOGoMAPIVolatileMessage *) message
|
- (BOOL) evaluateSOGoMAPIDBObject: (SOGoMAPIDBObject *) object
|
||||||
{
|
{
|
||||||
NSDictionary *properties;
|
NSDictionary *properties;
|
||||||
BOOL rc;
|
BOOL rc;
|
||||||
|
|
||||||
[self logWithFormat: @"evaluating message '%@'", message];
|
[self logWithFormat: @"evaluating object '%@'", object];
|
||||||
|
|
||||||
properties = [message properties];
|
properties = [object properties];
|
||||||
rc = [self _evaluateMAPIVolatileMessageProperties: properties];
|
rc = [self _evaluateSOGoMAPIDBObject: properties];
|
||||||
|
|
||||||
[self logWithFormat: @" evaluation result: %d", rc];
|
[self logWithFormat: @" evaluation result: %d", rc];
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
@implementation EOAndQualifier (MAPIStoreRestrictionsPrivate)
|
@implementation EOAndQualifier (MAPIStoreRestrictionsPrivate)
|
||||||
|
|
||||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||||
{
|
{
|
||||||
NSUInteger i;
|
NSUInteger i;
|
||||||
BOOL rc;
|
BOOL rc;
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
|
|
||||||
for (i = 0; rc && i < count; i++)
|
for (i = 0; rc && i < count; i++)
|
||||||
rc = [[qualifiers objectAtIndex: i]
|
rc = [[qualifiers objectAtIndex: i]
|
||||||
_evaluateMAPIVolatileMessageProperties: properties];
|
_evaluateSOGoMAPIDBObject: properties];
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
|
|
||||||
@implementation EOOrQualifier (MAPIStoreRestrictionsPrivate)
|
@implementation EOOrQualifier (MAPIStoreRestrictionsPrivate)
|
||||||
|
|
||||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||||
{
|
{
|
||||||
NSUInteger i;
|
NSUInteger i;
|
||||||
BOOL rc;
|
BOOL rc;
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
|
|
||||||
for (i = 0; !rc && i < count; i++)
|
for (i = 0; !rc && i < count; i++)
|
||||||
rc = [[qualifiers objectAtIndex: i]
|
rc = [[qualifiers objectAtIndex: i]
|
||||||
_evaluateMAPIVolatileMessageProperties: properties];
|
_evaluateSOGoMAPIDBObject: properties];
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -96,9 +96,9 @@
|
||||||
|
|
||||||
@implementation EONotQualifier (MAPIStoreRestrictionsPrivate)
|
@implementation EONotQualifier (MAPIStoreRestrictionsPrivate)
|
||||||
|
|
||||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||||
{
|
{
|
||||||
return ![qualifier _evaluateMAPIVolatileMessageProperties: properties];
|
return ![qualifier _evaluateSOGoMAPIDBObject: properties];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
|
|
||||||
typedef BOOL (*EOComparator) (id, SEL, id);
|
typedef BOOL (*EOComparator) (id, SEL, id);
|
||||||
|
|
||||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||||
{
|
{
|
||||||
id finalKey;
|
id finalKey;
|
||||||
id propValue;
|
id propValue;
|
||||||
|
@ -136,7 +136,7 @@ typedef BOOL (*EOComparator) (id, SEL, id);
|
||||||
|
|
||||||
@implementation EOBitmaskQualifier (MAPIStoreRestrictionsPrivate)
|
@implementation EOBitmaskQualifier (MAPIStoreRestrictionsPrivate)
|
||||||
|
|
||||||
- (BOOL) _evaluateMAPIVolatileMessageProperties: (NSDictionary *) properties
|
- (BOOL) _evaluateSOGoMAPIDBObject: (NSDictionary *) properties
|
||||||
{
|
{
|
||||||
NSNumber *propTag;
|
NSNumber *propTag;
|
||||||
id propValue;
|
id propValue;
|
||||||
|
|
34
OpenChange/GCSSpecialQueries+OpenChange.h
Normal file
34
OpenChange/GCSSpecialQueries+OpenChange.h
Normal 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 */
|
107
OpenChange/GCSSpecialQueries+OpenChange.m
Normal file
107
OpenChange/GCSSpecialQueries+OpenChange.m
Normal 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
|
|
@ -26,6 +26,17 @@ BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
|
||||||
|
|
||||||
UNRTF_DIR = unrtf-$(UNRTF_VERSION)
|
UNRTF_DIR = unrtf-$(UNRTF_VERSION)
|
||||||
|
|
||||||
|
PYTHON = /usr/bin/python
|
||||||
|
PYTHON_IS_GOOD = $(shell $(PYTHON) -c 'from sys import version_info; a=version_info; print a.major == 2 and a.minor >= 6')
|
||||||
|
ifeq (${PYTHON_IS_GOOD},False)
|
||||||
|
PYTHON = /usr/bin/python2.6
|
||||||
|
endif
|
||||||
|
|
||||||
|
all::
|
||||||
|
@echo " Python executable: ${PYTHON}"
|
||||||
|
|
||||||
|
SAMBA_PRIVATE_DIR = $(shell $(PYTHON) ./samba-get-config.py "private dir")
|
||||||
|
|
||||||
$(SOGOBACKEND)_SUBPROJECTS += $(UNRTF_DIR)/src
|
$(SOGOBACKEND)_SUBPROJECTS += $(UNRTF_DIR)/src
|
||||||
|
|
||||||
$(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication
|
$(SOGOBACKEND)_PRINCIPAL_CLASS = MAPIApplication
|
||||||
|
@ -41,9 +52,11 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
||||||
MAPIStoreSamDBUtils.m \
|
MAPIStoreSamDBUtils.m \
|
||||||
MAPIStoreUserContext.m \
|
MAPIStoreUserContext.m \
|
||||||
\
|
\
|
||||||
SOGoMAPIVolatileMessage.m \
|
SOGoMAPIObject.m \
|
||||||
SOGoMAPIFSFolder.m \
|
\
|
||||||
SOGoMAPIFSMessage.m \
|
SOGoMAPIDBObject.m \
|
||||||
|
SOGoMAPIDBMessage.m \
|
||||||
|
SOGoMAPIDBFolder.m \
|
||||||
\
|
\
|
||||||
MAPIStoreAppointmentWrapper.m \
|
MAPIStoreAppointmentWrapper.m \
|
||||||
MAPIStoreAttachment.m \
|
MAPIStoreAttachment.m \
|
||||||
|
@ -53,18 +66,18 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
||||||
MAPIStoreFolder.m \
|
MAPIStoreFolder.m \
|
||||||
MAPIStoreMessage.m \
|
MAPIStoreMessage.m \
|
||||||
MAPIStoreObject.m \
|
MAPIStoreObject.m \
|
||||||
|
MAPIStoreObjectProxy.m \
|
||||||
|
MAPIStoreSOGoObject.m \
|
||||||
MAPIStoreTable.m \
|
MAPIStoreTable.m \
|
||||||
MAPIStoreMessageTable.m \
|
MAPIStoreMessageTable.m \
|
||||||
MAPIStoreFolderTable.m \
|
MAPIStoreFolderTable.m \
|
||||||
MAPIStorePermissionsTable.m \
|
MAPIStorePermissionsTable.m \
|
||||||
\
|
\
|
||||||
MAPIStoreVolatileMessage.m \
|
MAPIStoreDBBaseContext.m \
|
||||||
\
|
MAPIStoreDBFolder.m \
|
||||||
MAPIStoreFSBaseContext.m \
|
MAPIStoreDBFolderTable.m \
|
||||||
MAPIStoreFSFolder.m \
|
MAPIStoreDBMessage.m \
|
||||||
MAPIStoreFSFolderTable.m \
|
MAPIStoreDBMessageTable.m \
|
||||||
MAPIStoreFSMessage.m \
|
|
||||||
MAPIStoreFSMessageTable.m \
|
|
||||||
\
|
\
|
||||||
MAPIStoreFAIMessage.m \
|
MAPIStoreFAIMessage.m \
|
||||||
MAPIStoreFAIMessageTable.m \
|
MAPIStoreFAIMessageTable.m \
|
||||||
|
@ -78,6 +91,7 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
||||||
MAPIStoreCalendarContext.m \
|
MAPIStoreCalendarContext.m \
|
||||||
MAPIStoreCalendarFolder.m \
|
MAPIStoreCalendarFolder.m \
|
||||||
MAPIStoreCalendarMessage.m \
|
MAPIStoreCalendarMessage.m \
|
||||||
|
MAPIStoreCalendarEmbeddedMessage.m \
|
||||||
MAPIStoreCalendarMessageTable.m \
|
MAPIStoreCalendarMessageTable.m \
|
||||||
MAPIStoreRecurrenceUtils.m \
|
MAPIStoreRecurrenceUtils.m \
|
||||||
\
|
\
|
||||||
|
@ -112,8 +126,14 @@ $(SOGOBACKEND)_OBJC_FILES += \
|
||||||
NSString+MAPIStore.m \
|
NSString+MAPIStore.m \
|
||||||
NSValue+MAPIStore.m \
|
NSValue+MAPIStore.m \
|
||||||
\
|
\
|
||||||
EOBitmaskQualifier.m \
|
iCalEvent+MAPIStore.m \
|
||||||
|
iCalTimeZone+MAPIStore.m \
|
||||||
|
\
|
||||||
|
GCSSpecialQueries+OpenChange.m\
|
||||||
|
\
|
||||||
EOQualifier+MAPI.m \
|
EOQualifier+MAPI.m \
|
||||||
|
\
|
||||||
|
EOBitmaskQualifier.m
|
||||||
|
|
||||||
|
|
||||||
$(SOGOBACKEND)_RESOURCE_FILES += \
|
$(SOGOBACKEND)_RESOURCE_FILES += \
|
||||||
|
@ -145,7 +165,13 @@ PLREADER_TOOL = plreader
|
||||||
$(PLREADER_TOOL)_OBJC_FILES += \
|
$(PLREADER_TOOL)_OBJC_FILES += \
|
||||||
plreader.m \
|
plreader.m \
|
||||||
|
|
||||||
TEST_TOOL_NAME += $(PLREADER_TOOL)
|
DBMSGREADER_TOOL = dbmsgreader
|
||||||
|
$(DBMSGREADER_TOOL)_OBJC_FILES += \
|
||||||
|
dbmsgreader.m
|
||||||
|
|
||||||
|
$(DBMSGREADER_TOOL)_LIB_DIRS += -L../SoObjects/SOGo/ -lSOGo -lNGObjWeb
|
||||||
|
|
||||||
|
TEST_TOOL_NAME += $(PLREADER_TOOL) $(DBMSGREADER_TOOL)
|
||||||
|
|
||||||
### cflags and libs
|
### cflags and libs
|
||||||
LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags)
|
LIBMAPI_CFLAGS = $(shell pkg-config libmapi --cflags)
|
||||||
|
@ -160,7 +186,7 @@ SAMBA_LIB_DIR = $(shell pkg-config libmapistore --variable=libdir)
|
||||||
LIBMAPI_LIBS = $(shell pkg-config libmapi --libs)
|
LIBMAPI_LIBS = $(shell pkg-config libmapi --libs)
|
||||||
|
|
||||||
LIBMAPISTORE_CFLAGS = $(shell pkg-config libmapistore --cflags) -DSAMBA_PREFIX="\"$(shell pkg-config libmapistore --variable=prefix)\""
|
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)_INSTALL_DIR = $(DESTDIR)/$(SAMBA_LIB_DIR)/mapistore_backends
|
||||||
$(MAPISTORESOGO)_LIB_DIRS += \
|
$(MAPISTORESOGO)_LIB_DIRS += \
|
||||||
|
@ -176,6 +202,7 @@ $(SOGOBACKEND)_LIB_DIRS += \
|
||||||
|
|
||||||
ADDITIONAL_INCLUDE_DIRS += \
|
ADDITIONAL_INCLUDE_DIRS += \
|
||||||
-Werror -Wall \
|
-Werror -Wall \
|
||||||
|
-DSAMBA_PRIVATE_DIR=@"\"$(SAMBA_PRIVATE_DIR)\"" \
|
||||||
$(LIBMAPI_CFLAGS) \
|
$(LIBMAPI_CFLAGS) \
|
||||||
$(LIBMAPISTORE_CFLAGS) \
|
$(LIBMAPISTORE_CFLAGS) \
|
||||||
-I$(UNRTF_DIR)/src \
|
-I$(UNRTF_DIR)/src \
|
||||||
|
|
|
@ -2,4 +2,4 @@ all:: MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h
|
||||||
|
|
||||||
MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h: gen-property-selectors.py code-MAPIStorePropertySelectors.m code-MAPIStorePropertySelectors.h
|
MAPIStorePropertySelectors.m MAPIStorePropertySelectors.h: gen-property-selectors.py code-MAPIStorePropertySelectors.m code-MAPIStorePropertySelectors.h
|
||||||
@echo " Auto-generating MAPIStorePropertySelectors.[hm]..."
|
@echo " Auto-generating MAPIStorePropertySelectors.[hm]..."
|
||||||
@./gen-property-selectors.py -o MAPIStorePropertySelectors $(LIBMAPISTORE_CFLAGS)
|
@$(PYTHON) ./gen-property-selectors.py -o MAPIStorePropertySelectors $(LIBMAPISTORE_CFLAGS)
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#import <Foundation/NSUserDefaults.h>
|
#import <Foundation/NSUserDefaults.h>
|
||||||
#import <Foundation/NSTimeZone.h>
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
#import <WEExtensions/WEResourceManager.h>
|
||||||
|
|
||||||
#import <SOGo/SOGoProductLoader.h>
|
#import <SOGo/SOGoProductLoader.h>
|
||||||
#import <SOGo/SOGoSystemDefaults.h>
|
#import <SOGo/SOGoSystemDefaults.h>
|
||||||
|
@ -46,12 +47,18 @@ MAPIApplication *MAPIApp = nil;
|
||||||
{
|
{
|
||||||
if (!MAPIApp)
|
if (!MAPIApp)
|
||||||
{
|
{
|
||||||
|
WEResourceManager *rm;
|
||||||
|
|
||||||
// TODO publish
|
// TODO publish
|
||||||
[iCalEntityObject initializeSOGoExtensions];
|
[iCalEntityObject initializeSOGoExtensions];
|
||||||
|
|
||||||
MAPIApp = [super init];
|
MAPIApp = [super init];
|
||||||
[MAPIApp retain];
|
[MAPIApp retain];
|
||||||
|
|
||||||
|
rm = [[WEResourceManager alloc] init];
|
||||||
|
[self setResourceManager:rm];
|
||||||
|
[rm release];
|
||||||
|
|
||||||
utcTZ = [NSTimeZone timeZoneWithName: @"UTC"];
|
utcTZ = [NSTimeZone timeZoneWithName: @"UTC"];
|
||||||
[utcTZ retain];
|
[utcTZ retain];
|
||||||
}
|
}
|
||||||
|
@ -59,6 +66,11 @@ MAPIApplication *MAPIApp = nil;
|
||||||
return MAPIApp;
|
return MAPIApp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) shouldSetupSignalHandlers
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setUserContext: (MAPIStoreUserContext *) newContext
|
- (void) setUserContext: (MAPIStoreUserContext *) newContext
|
||||||
{
|
{
|
||||||
/* user contexts must not be retained here ad their holder (mapistore)
|
/* user contexts must not be retained here ad their holder (mapistore)
|
||||||
|
|
|
@ -23,10 +23,11 @@
|
||||||
#ifndef MAPISTORECALENDARWRAPPER_H
|
#ifndef MAPISTORECALENDARWRAPPER_H
|
||||||
#define MAPISTORECALENDARWRAPPER_H
|
#define MAPISTORECALENDARWRAPPER_H
|
||||||
|
|
||||||
#import <Foundation/NSObject.h>
|
|
||||||
#import <NGCards/iCalPerson.h>
|
#import <NGCards/iCalPerson.h>
|
||||||
#import <Appointments/iCalEntityObject+SOGo.h>
|
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreObjectProxy.h"
|
||||||
|
|
||||||
@class NSTimeZone;
|
@class NSTimeZone;
|
||||||
|
|
||||||
@class iCalAlarm;
|
@class iCalAlarm;
|
||||||
|
@ -35,10 +36,11 @@
|
||||||
|
|
||||||
@class SOGoUser;
|
@class SOGoUser;
|
||||||
|
|
||||||
@interface MAPIStoreAppointmentWrapper : NSObject
|
@interface MAPIStoreAppointmentWrapper : MAPIStoreObjectProxy
|
||||||
{
|
{
|
||||||
struct mapistore_connection_info *connInfo;
|
struct mapistore_connection_info *connInfo;
|
||||||
iCalCalendar *calendar;
|
iCalCalendar *calendar;
|
||||||
|
iCalEvent *firstEvent;
|
||||||
iCalEvent *event;
|
iCalEvent *event;
|
||||||
NSTimeZone *timeZone;
|
NSTimeZone *timeZone;
|
||||||
SOGoUser *user;
|
SOGoUser *user;
|
||||||
|
@ -120,8 +122,8 @@
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (int) getPidLidIndentedBusyStatus: (void **) data // TODO
|
- (int) getPidLidIndentedBusyStatus: (void **) data // TODO
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (int) getPidTagSubject: (void **) data // SUMMARY
|
- (int) getPidTagNormalizedSubject: (void **) data // SUMMARY
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (int) getPidLidLocation: (void **) data // LOCATION
|
- (int) getPidLidLocation: (void **) data // LOCATION
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions
|
- (int) getPidLidPrivate: (void **) data // private (bool), should depend on CLASS and permissions
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreAppointmentWrapper.m - this file is part of SOGo
|
/* 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>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,24 +20,28 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <talloc.h>
|
||||||
|
|
||||||
#import <Foundation/NSArray.h>
|
#import <Foundation/NSArray.h>
|
||||||
#import <Foundation/NSCalendarDate.h>
|
#import <Foundation/NSCalendarDate.h>
|
||||||
#import <Foundation/NSCharacterSet.h>
|
#import <Foundation/NSCharacterSet.h>
|
||||||
#import <Foundation/NSData.h>
|
#import <Foundation/NSData.h>
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
#import <Foundation/NSTimeZone.h>
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
#import <NGExtensions/NSCalendarDate+misc.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
#import <NGCards/iCalAlarm.h>
|
#import <NGCards/iCalAlarm.h>
|
||||||
#import <NGCards/iCalDateTime.h>
|
#import <NGCards/iCalDateTime.h>
|
||||||
#import <NGCards/iCalEvent.h>
|
#import <NGCards/iCalEvent.h>
|
||||||
|
#import <NGCards/iCalEventChanges.h>
|
||||||
#import <NGCards/iCalPerson.h>
|
#import <NGCards/iCalPerson.h>
|
||||||
#import <NGCards/iCalRecurrenceRule.h>
|
|
||||||
#import <NGCards/iCalTimeZone.h>
|
|
||||||
#import <NGCards/iCalTrigger.h>
|
#import <NGCards/iCalTrigger.h>
|
||||||
#import <NGCards/NSString+NGCards.h>
|
#import <NGCards/NSString+NGCards.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import <SOGo/SOGoUserManager.h>
|
#import <SOGo/SOGoUserManager.h>
|
||||||
|
|
||||||
|
#import "iCalTimeZone+MAPIStore.h"
|
||||||
#import "MAPIStoreRecurrenceUtils.h"
|
#import "MAPIStoreRecurrenceUtils.h"
|
||||||
#import "MAPIStoreSamDBUtils.h"
|
#import "MAPIStoreSamDBUtils.h"
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
|
@ -49,7 +53,6 @@
|
||||||
#import "MAPIStoreAppointmentWrapper.h"
|
#import "MAPIStoreAppointmentWrapper.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <talloc.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <gen_ndr/exchange.h>
|
#include <gen_ndr/exchange.h>
|
||||||
#include <gen_ndr/property.h>
|
#include <gen_ndr/property.h>
|
||||||
|
@ -181,11 +184,15 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
inTimeZone: (NSTimeZone *) newTimeZone
|
inTimeZone: (NSTimeZone *) newTimeZone
|
||||||
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
withConnectionInfo: (struct mapistore_connection_info *) newConnInfo
|
||||||
{
|
{
|
||||||
|
NSArray *events;
|
||||||
|
|
||||||
if ((self = [self init]))
|
if ((self = [self init]))
|
||||||
{
|
{
|
||||||
connInfo = newConnInfo;
|
connInfo = newConnInfo;
|
||||||
ASSIGN (event, newEvent);
|
ASSIGN (calendar, [newEvent parent]);
|
||||||
ASSIGN (calendar, [event parent]);
|
event = newEvent;
|
||||||
|
events = [calendar events];
|
||||||
|
firstEvent = [events objectAtIndex: 0];
|
||||||
ASSIGN (timeZone, newTimeZone);
|
ASSIGN (timeZone, newTimeZone);
|
||||||
ASSIGN (user, newUser);
|
ASSIGN (user, newUser);
|
||||||
ASSIGN (senderEmail, newSenderEmail);
|
ASSIGN (senderEmail, newSenderEmail);
|
||||||
|
@ -198,7 +205,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
[calendar release];
|
[calendar release];
|
||||||
[event release];
|
|
||||||
[timeZone release];
|
[timeZone release];
|
||||||
[user release];
|
[user release];
|
||||||
[senderEmail release];
|
[senderEmail release];
|
||||||
|
@ -435,7 +441,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagIconIndex: (void **) data // TODO
|
- (int) getPidTagIconIndex: (void **) data // TODO
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
uint32_t longValue;
|
uint32_t longValue;
|
||||||
|
|
||||||
|
@ -580,7 +586,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagMessageClass: (void **) data
|
- (int) getPidTagMessageClass: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
const char *className;
|
const char *className;
|
||||||
|
|
||||||
|
@ -626,35 +632,20 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (int) getPidLidAppointmentMessageClass: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
*data = talloc_strdup (memCtx, "IPM.Appointment");
|
||||||
|
|
||||||
|
return MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
- (int) getPidLidFInvited: (void **) data
|
- (int) getPidLidFInvited: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self getYes: data inMemCtx: 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
|
- (int) getPidLidAppointmentSequence: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
|
@ -722,13 +713,245 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
- (int) getPidLidAppointmentStartWhole: (void **) data
|
- (int) getPidLidAppointmentStartWhole: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
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
|
- (int) getPidLidCommonStart: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
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
|
- (int) _getEntryIdFromCN: (NSString *) cn
|
||||||
|
@ -827,7 +1050,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
|
|
||||||
/* sender (organizer) */
|
/* sender (organizer) */
|
||||||
- (int) getPidTagSenderEmailAddress: (void **) data
|
- (int) getPidTagSenderEmailAddress: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getEmailAddress: data
|
return [self _getEmailAddress: data
|
||||||
forICalPerson: [event organizer]
|
forICalPerson: [event organizer]
|
||||||
|
@ -835,7 +1058,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSenderAddressType: (void **) data
|
- (int) getPidTagSenderAddressType: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getAddrType: data
|
return [self _getAddrType: data
|
||||||
forICalPerson: [event organizer]
|
forICalPerson: [event organizer]
|
||||||
|
@ -843,7 +1066,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSenderName: (void **) data
|
- (int) getPidTagSenderName: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getName: data
|
return [self _getName: data
|
||||||
forICalPerson: [event organizer]
|
forICalPerson: [event organizer]
|
||||||
|
@ -851,16 +1074,41 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSenderEntryId: (void **) data
|
- (int) getPidTagSenderEntryId: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getEntryId: data
|
return [self _getEntryId: data
|
||||||
forICalPerson: [event organizer]
|
forICalPerson: [event organizer]
|
||||||
inMemCtx: memCtx];
|
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 */
|
/* attendee */
|
||||||
- (int) getPidTagReceivedByEmailAddress: (void **) data
|
- (int) getPidTagReceivedByEmailAddress: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getEmailAddress: data
|
return [self _getEmailAddress: data
|
||||||
forICalPerson: [event userAsAttendee: user]
|
forICalPerson: [event userAsAttendee: user]
|
||||||
|
@ -868,7 +1116,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagReceivedByAddressType: (void **) data
|
- (int) getPidTagReceivedByAddressType: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getAddrType: data
|
return [self _getAddrType: data
|
||||||
forICalPerson: [event userAsAttendee: user]
|
forICalPerson: [event userAsAttendee: user]
|
||||||
|
@ -876,7 +1124,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagReceivedByName: (void **) data
|
- (int) getPidTagReceivedByName: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getName: data
|
return [self _getName: data
|
||||||
forICalPerson: [event userAsAttendee: user]
|
forICalPerson: [event userAsAttendee: user]
|
||||||
|
@ -884,7 +1132,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagReceivedByEntryId: (void **) data
|
- (int) getPidTagReceivedByEntryId: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self _getEntryId: data
|
return [self _getEntryId: data
|
||||||
forICalPerson: [event userAsAttendee: user]
|
forICalPerson: [event userAsAttendee: user]
|
||||||
|
@ -892,40 +1140,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
/* /attendee */
|
/* /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
|
- (int) getPidLidAppointmentDuration: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
|
@ -966,8 +1180,8 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
return [self getPidLidBusyStatus: data inMemCtx: memCtx];
|
return [self getPidLidBusyStatus: data inMemCtx: memCtx];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSubject: (void **) data // SUMMARY
|
- (int) getPidTagNormalizedSubject: (void **) data // SUMMARY
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
*data = [[event summary] asUnicodeInMemCtx: memCtx];
|
*data = [[event summary] asUnicodeInMemCtx: memCtx];
|
||||||
|
|
||||||
|
@ -995,7 +1209,8 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
return [self getPidLidLocation: data inMemCtx: memCtx];
|
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
|
/* 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
|
SOGo or if it was received only by mail. We only assume the SOGo case
|
||||||
|
@ -1003,7 +1218,8 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
return [self getYes: data inMemCtx: memCtx];
|
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,
|
*data = MAPILongValue (memCtx,
|
||||||
0x00000010 /* cpsCreatedOnPrincipal */
|
0x00000010 /* cpsCreatedOnPrincipal */
|
||||||
|
@ -1020,14 +1236,14 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSensitivity: (void **) data // not implemented, depends on CLASS
|
- (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
|
// normal = 0, personal?? = 1, private = 2, confidential = 3
|
||||||
return [self getLongZero: data inMemCtx: memCtx];
|
return [self getLongZero: data inMemCtx: memCtx];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagImportance: (void **) data
|
- (int) getPidTagImportance: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
uint32_t v;
|
uint32_t v;
|
||||||
if ([[event priority] isEqualToString: @"9"])
|
if ([[event priority] isEqualToString: @"9"])
|
||||||
|
@ -1043,7 +1259,7 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagBody: (void **) data
|
- (int) getPidTagBody: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
int rc = MAPISTORE_SUCCESS;
|
int rc = MAPISTORE_SUCCESS;
|
||||||
NSString *stringValue;
|
NSString *stringValue;
|
||||||
|
@ -1058,14 +1274,6 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidLidIsRecurring: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
*data = MAPIBoolValue (memCtx, [event isRecurrent]);
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidLidRecurring: (void **) data
|
- (int) getPidLidRecurring: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
|
@ -1074,37 +1282,144 @@ static NSCharacterSet *hexCharacterSet = nil;
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
- (int) getPidLidIsRecurring: (void **) data
|
||||||
_fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
NSCalendarDate *startDate, NSTimeInterval duration,
|
|
||||||
NSCalendarDate * endDate, iCalRecurrenceRule *rule)
|
|
||||||
{
|
{
|
||||||
uint32_t startMinutes;
|
*data = MAPIBoolValue (memCtx,
|
||||||
|
[event isRecurrent]
|
||||||
|
|| ([event recurrenceId] != nil));
|
||||||
|
|
||||||
[rule fillRecurrencePattern: &arp->RecurrencePattern
|
return MAPISTORE_SUCCESS;
|
||||||
withStartDate: startDate andEndDate: endDate];
|
|
||||||
arp->ReaderVersion2 = 0x00003006;
|
|
||||||
arp->WriterVersion2 = 0x00003009;
|
|
||||||
|
|
||||||
startMinutes = ([startDate hourOfDay] * 60 + [startDate minuteOfHour]);
|
|
||||||
arp->StartTimeOffset = startMinutes;
|
|
||||||
arp->EndTimeOffset = startMinutes + (uint32_t) (duration / 60);
|
|
||||||
|
|
||||||
arp->ExceptionCount = 0;
|
|
||||||
arp->ReservedBlock1Size = 0;
|
|
||||||
|
|
||||||
/* Currently ignored in property.idl:
|
|
||||||
arp->ReservedBlock2Size = 0; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (struct SBinary_short *) _computeAppointmentRecurInMemCtx: (TALLOC_CTX *) memCtx
|
- (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 AppointmentRecurrencePattern *arp;
|
||||||
struct Binary_r *bin;
|
struct Binary_r *bin;
|
||||||
struct SBinary_short *sBin;
|
// struct SBinary_short *sBin;
|
||||||
NSCalendarDate *firstStartDate;
|
NSCalendarDate *firstStartDate;
|
||||||
iCalRecurrenceRule *rule;
|
iCalRecurrenceRule *rule;
|
||||||
|
NSUInteger startMinutes;
|
||||||
|
NSArray *events, *exceptions;
|
||||||
|
iCalEvent *exceptionEvent;
|
||||||
|
NSUInteger count, max;
|
||||||
|
|
||||||
rule = [[event recurrenceRules] objectAtIndex: 0];
|
rule = [[event recurrenceRules] objectAtIndex: 0];
|
||||||
|
|
||||||
|
@ -1113,15 +1428,47 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
|
||||||
{
|
{
|
||||||
[firstStartDate setTimeZone: timeZone];
|
[firstStartDate setTimeZone: timeZone];
|
||||||
|
|
||||||
arp = talloc_zero (memCtx, struct AppointmentRecurrencePattern);
|
arp = talloc_zero (NULL, struct AppointmentRecurrencePattern);
|
||||||
_fillAppointmentRecurrencePattern (arp, firstStartDate,
|
[rule fillRecurrencePattern: &arp->RecurrencePattern
|
||||||
[event durationAsTimeInterval],
|
withEvent: event
|
||||||
[event lastPossibleRecurrenceStartDate],
|
inTimeZone: timeZone
|
||||||
rule);
|
inMemCtx: arp];
|
||||||
sBin = talloc_zero (memCtx, struct SBinary_short);
|
arp->ReaderVersion2 = 0x00003006;
|
||||||
bin = set_AppointmentRecurrencePattern (sBin, arp);
|
arp->WriterVersion2 = 0x00003008; /* 0x3008 for compatibility with
|
||||||
sBin->cb = bin->cb;
|
ol2003 */
|
||||||
sBin->lpb = bin->lpb;
|
|
||||||
|
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);
|
talloc_free (arp);
|
||||||
|
|
||||||
// DEBUG(5, ("To client:\n"));
|
// DEBUG(5, ("To client:\n"));
|
||||||
|
@ -1130,12 +1477,100 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[self errorWithFormat: @"no first occurrence found in rule: %@", rule];
|
[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
|
- (int) getPidLidAppointmentRecur: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
|
@ -1515,4 +1950,41 @@ _fillAppointmentRecurrencePattern (struct AppointmentRecurrencePattern *arp,
|
||||||
return MAPISTORE_ERR_NOT_FOUND;
|
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
|
@end
|
||||||
|
|
|
@ -40,6 +40,9 @@
|
||||||
withMID: (uint64_t *) mid
|
withMID: (uint64_t *) mid
|
||||||
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
|
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (int) createEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
|
||||||
|
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
/* helpers */
|
/* helpers */
|
||||||
- (NSData *) mimeAttachTag;
|
- (NSData *) mimeAttachTag;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#import "MAPIStoreMapping.h"
|
#import "MAPIStoreMapping.h"
|
||||||
#import "MAPIStoreMessage.h"
|
#import "MAPIStoreMessage.h"
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
|
#import "NSObject+MAPIStore.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -90,6 +91,12 @@
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (int) getPidTagAccessLevel: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
return [self getLongZero: data inMemCtx: memCtx];
|
||||||
|
}
|
||||||
|
|
||||||
- (int) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
|
- (int) openEmbeddedMessage: (MAPIStoreEmbeddedMessage **) messagePtr
|
||||||
withMID: (uint64_t *) mid
|
withMID: (uint64_t *) mid
|
||||||
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
|
withMAPIStoreMsg: (struct mapistore_message **) mapistoreMsgPtr
|
||||||
|
@ -103,20 +110,34 @@
|
||||||
|
|
||||||
mapping = [self mapping];
|
mapping = [self mapping];
|
||||||
|
|
||||||
|
// if (attMessage)
|
||||||
attMessage = [self openEmbeddedMessage];
|
attMessage = [self openEmbeddedMessage];
|
||||||
if (attMessage)
|
if (attMessage)
|
||||||
{
|
{
|
||||||
*mid = [mapping idFromURL: [attMessage url]];
|
*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;
|
*messagePtr = attMessage;
|
||||||
*mapistoreMsgPtr = mapistoreMsg;
|
*mapistoreMsgPtr = mapistoreMsg;
|
||||||
}
|
}
|
||||||
// else if (flags == MAPI_CREATE)
|
|
||||||
// {
|
|
||||||
// attMessage = [self createEmbeddedMessage];
|
|
||||||
// if (attMessage)
|
|
||||||
// [mapping registerURL: [attMessage url]
|
|
||||||
// withID: *mid];
|
|
||||||
// }
|
|
||||||
|
|
||||||
return (attMessage ? MAPISTORE_SUCCESS : MAPISTORE_ERROR);
|
return (attMessage ? MAPISTORE_SUCCESS : MAPISTORE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,15 @@
|
||||||
|
|
||||||
#import "MAPIStoreAttachment.h"
|
#import "MAPIStoreAttachment.h"
|
||||||
|
|
||||||
@interface MAPIStoreCalendarAttachment : MAPIStoreAttachment
|
@class iCalEvent;
|
||||||
|
|
||||||
|
@interface MAPIStoreCalendarAttachment : MAPIStoreAttachment
|
||||||
|
{
|
||||||
|
iCalEvent *event;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setEvent: (iCalEvent *) newEvent;
|
||||||
|
- (iCalEvent *) event;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,22 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* 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"
|
#import "MAPIStoreCalendarAttachment.h"
|
||||||
|
|
||||||
|
@ -34,12 +47,42 @@
|
||||||
|
|
||||||
@implementation MAPIStoreCalendarAttachment
|
@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
|
- (int) getPidTagAttachmentHidden: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) localMemCtx
|
inMemCtx: (TALLOC_CTX *) localMemCtx
|
||||||
{
|
{
|
||||||
*data = MAPIBoolValue (localMemCtx, YES);
|
return [self getYes: data inMemCtx: localMemCtx];
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagAttachmentFlags: (void **) data
|
- (int) getPidTagAttachmentFlags: (void **) data
|
||||||
|
@ -50,34 +93,69 @@
|
||||||
return MAPISTORE_SUCCESS;
|
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
|
- (int) getPidTagAttachMethod: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) localMemCtx
|
inMemCtx: (TALLOC_CTX *) localMemCtx
|
||||||
{
|
{
|
||||||
*data = MAPILongValue (localMemCtx, 0x00000005); /* afEmbeddedMessage */
|
*data = MAPILongValue (localMemCtx, afEmbeddedMessage);
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// case PidTagExceptionStartTime:
|
- (int) getPidTagAttachEncoding: (void **) data
|
||||||
// case PidTagExceptionEndTime:
|
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:
|
// case PidTagExceptionReplaceTime:
|
||||||
|
|
||||||
/* subclasses */
|
/* subclasses */
|
||||||
- (MAPIStoreEmbeddedMessage *) openEmbeddedMessage
|
- (MAPIStoreCalendarEmbeddedMessage *) openEmbeddedMessage
|
||||||
{
|
{
|
||||||
MAPIStoreEmbeddedMessage *msg;
|
MAPIStoreCalendarEmbeddedMessage *msg;
|
||||||
|
|
||||||
if (isNew)
|
msg = [MAPIStoreCalendarEmbeddedMessage
|
||||||
msg = nil;
|
mapiStoreObjectInContainer: self];
|
||||||
else
|
|
||||||
msg = nil;
|
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MAPIStoreEmbeddedMessage *) createEmbeddedMessage
|
- (MAPIStoreCalendarEmbeddedMessage *) createEmbeddedMessage
|
||||||
{
|
{
|
||||||
return [MAPIStoreEmbeddedMessage embeddedMessageWithAttachment: self];
|
MAPIStoreCalendarEmbeddedMessage *msg;
|
||||||
|
|
||||||
|
msg = [self openEmbeddedMessage];
|
||||||
|
[msg setIsNew: YES];
|
||||||
|
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
34
OpenChange/MAPIStoreCalendarEmbeddedMessage.h
Normal file
34
OpenChange/MAPIStoreCalendarEmbeddedMessage.h
Normal 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 */
|
208
OpenChange/MAPIStoreCalendarEmbeddedMessage.m
Normal file
208
OpenChange/MAPIStoreCalendarEmbeddedMessage.m
Normal 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
|
|
@ -35,6 +35,7 @@
|
||||||
#import "MAPIStoreCalendarContext.h"
|
#import "MAPIStoreCalendarContext.h"
|
||||||
#import "MAPIStoreCalendarMessage.h"
|
#import "MAPIStoreCalendarMessage.h"
|
||||||
#import "MAPIStoreCalendarMessageTable.h"
|
#import "MAPIStoreCalendarMessageTable.h"
|
||||||
|
#import "MAPIStoreUserContext.h"
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
|
|
||||||
#import "MAPIStoreCalendarFolder.h"
|
#import "MAPIStoreCalendarFolder.h"
|
||||||
|
@ -67,6 +68,8 @@
|
||||||
newEntry = [SOGoAppointmentObject objectWithName: name
|
newEntry = [SOGoAppointmentObject objectWithName: name
|
||||||
inContainer: sogoObject];
|
inContainer: sogoObject];
|
||||||
[newEntry setIsNew: YES];
|
[newEntry setIsNew: YES];
|
||||||
|
/* the WOContext is required here for resolving notification pages */
|
||||||
|
[newEntry setContext: [[self userContext] woContext]];
|
||||||
newMessage = [MAPIStoreCalendarMessage mapiStoreObjectWithSOGoObject: newEntry
|
newMessage = [MAPIStoreCalendarMessage mapiStoreObjectWithSOGoObject: newEntry
|
||||||
inContainer: self];
|
inContainer: self];
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,14 @@
|
||||||
|
|
||||||
#import "MAPIStoreGCSMessage.h"
|
#import "MAPIStoreGCSMessage.h"
|
||||||
|
|
||||||
|
@class iCalCalendar;
|
||||||
|
@class iCalEvent;
|
||||||
@class MAPIStoreAppointmentWrapper;
|
@class MAPIStoreAppointmentWrapper;
|
||||||
|
|
||||||
@interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage
|
@interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage
|
||||||
{
|
{
|
||||||
MAPIStoreAppointmentWrapper *appointmentWrapper;
|
iCalCalendar *calendar;
|
||||||
|
iCalEvent *masterEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,6 +35,7 @@
|
||||||
#import <Mailer/NSString+Mail.h>
|
#import <Mailer/NSString+Mail.h>
|
||||||
#import <SOGo/SOGoPermissions.h>
|
#import <SOGo/SOGoPermissions.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreAttachment.h"
|
||||||
#import "MAPIStoreContactsAttachment.h"
|
#import "MAPIStoreContactsAttachment.h"
|
||||||
#import "MAPIStoreContactsFolder.h"
|
#import "MAPIStoreContactsFolder.h"
|
||||||
#import "MAPIStorePropertySelectors.h"
|
#import "MAPIStorePropertySelectors.h"
|
||||||
|
@ -179,8 +180,8 @@
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSubject: (void **) data
|
- (int) getPidTagNormalizedSubject: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self getPidTagDisplayName: data inMemCtx: memCtx];
|
return [self getPidTagDisplayName: data inMemCtx: memCtx];
|
||||||
}
|
}
|
||||||
|
@ -767,8 +768,7 @@
|
||||||
|| [encoding isEqualToString: @"BASE64"])
|
|| [encoding isEqualToString: @"BASE64"])
|
||||||
{
|
{
|
||||||
attachment = [MAPIStoreContactsAttachment
|
attachment = [MAPIStoreContactsAttachment
|
||||||
mapiStoreObjectWithSOGoObject: nil
|
mapiStoreObjectInContainer: self];
|
||||||
inContainer: self];
|
|
||||||
[attachment setAID: 0];
|
[attachment setAID: 0];
|
||||||
[attachment setPhoto: photo];
|
[attachment setPhoto: photo];
|
||||||
[attachmentParts setObject: attachment forKey: @"photo"];
|
[attachmentParts setObject: attachment forKey: @"photo"];
|
||||||
|
|
|
@ -74,10 +74,12 @@ static Class MAPIStoreContactsMessageK, NGMailAddressK, NSDataK, NSStringK;
|
||||||
forKey: MAPIPropertyKey (PidLidEmail2EmailAddress)];
|
forKey: MAPIPropertyKey (PidLidEmail2EmailAddress)];
|
||||||
[knownProperties setObject: @"c_mail"
|
[knownProperties setObject: @"c_mail"
|
||||||
forKey: MAPIPropertyKey (PidLidEmail3EmailAddress)];
|
forKey: MAPIPropertyKey (PidLidEmail3EmailAddress)];
|
||||||
[knownProperties setObject: @"c_cn"
|
|
||||||
forKey: MAPIPropertyKey (PR_DISPLAY_NAME_UNICODE)];
|
|
||||||
[knownProperties setObject: @"c_cn"
|
[knownProperties setObject: @"c_cn"
|
||||||
forKey: MAPIPropertyKey (PidLidFileUnder)];
|
forKey: MAPIPropertyKey (PidLidFileUnder)];
|
||||||
|
[knownProperties setObject: @"c_cn"
|
||||||
|
forKey: MAPIPropertyKey (PidTagDisplayName)];
|
||||||
|
[knownProperties setObject: @"c_cn"
|
||||||
|
forKey: MAPIPropertyKey (PidTagSubject)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [knownProperties objectForKey: MAPIPropertyKey (property)];
|
return [knownProperties objectForKey: MAPIPropertyKey (property)];
|
||||||
|
@ -213,7 +215,11 @@ static Class MAPIStoreContactsMessageK, NGMailAddressK, NSDataK, NSStringK;
|
||||||
[knownProperties setObject: @"c_cn"
|
[knownProperties setObject: @"c_cn"
|
||||||
forKey: MAPIPropertyKey (PidLidFileUnder)];
|
forKey: MAPIPropertyKey (PidLidFileUnder)];
|
||||||
[knownProperties setObject: @"c_cn"
|
[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)];
|
return [knownProperties objectForKey: MAPIPropertyKey (property)];
|
||||||
|
|
|
@ -28,11 +28,9 @@
|
||||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
|
#import <SOGo/SOGoFolder.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
|
|
||||||
#import "SOGoMAPIFSFolder.h"
|
|
||||||
#import "SOGoMAPIFSMessage.h"
|
|
||||||
|
|
||||||
#import "MAPIStoreAttachment.h"
|
#import "MAPIStoreAttachment.h"
|
||||||
// #import "MAPIStoreAttachmentTable.h"
|
// #import "MAPIStoreAttachmentTable.h"
|
||||||
#import "MAPIStoreFallbackContext.h"
|
#import "MAPIStoreFallbackContext.h"
|
||||||
|
@ -294,9 +292,11 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||||
[MAPIStoreUserContext userContextWithUsername: username
|
[MAPIStoreUserContext userContextWithUsername: username
|
||||||
andTDBIndexing: indexingTdb]);
|
andTDBIndexing: indexingTdb]);
|
||||||
|
|
||||||
|
#if 0
|
||||||
mapistore_mgmt_backend_register_user (newConnInfo,
|
mapistore_mgmt_backend_register_user (newConnInfo,
|
||||||
"SOGo",
|
"SOGo",
|
||||||
[username UTF8String]);
|
[username UTF8String]);
|
||||||
|
#endif
|
||||||
|
|
||||||
connInfo = newConnInfo;
|
connInfo = newConnInfo;
|
||||||
username = [NSString stringWithUTF8String: newConnInfo->username];
|
username = [NSString stringWithUTF8String: newConnInfo->username];
|
||||||
|
@ -315,9 +315,12 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
mapistore_mgmt_backend_unregister_user ([self connectionInfo], "SOGo",
|
mapistore_mgmt_backend_unregister_user ([self connectionInfo], "SOGo",
|
||||||
[[userContext username]
|
[[userContext username]
|
||||||
UTF8String]);
|
UTF8String]);
|
||||||
|
#endif
|
||||||
|
|
||||||
[contextUrl release];
|
[contextUrl release];
|
||||||
[userContext release];
|
[userContext release];
|
||||||
[containersBag release];
|
[containersBag release];
|
||||||
|
@ -428,25 +431,29 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||||
|
|
||||||
[self ensureContextFolder];
|
[self ensureContextFolder];
|
||||||
currentFolder = [self rootSOGoFolder];
|
currentFolder = [self rootSOGoFolder];
|
||||||
|
[containersBag addObject: currentFolder];
|
||||||
path = [contextUrl path];
|
path = [contextUrl path];
|
||||||
if ([path hasPrefix: @"/"])
|
if ([path hasPrefix: @"/"])
|
||||||
path = [path substringFromIndex: 1];
|
path = [path substringFromIndex: 1];
|
||||||
if ([path hasSuffix: @"/"])
|
if ([path hasSuffix: @"/"])
|
||||||
path = [path substringToIndex: [path length] - 1];
|
path = [path substringToIndex: [path length] - 1];
|
||||||
pathComponents = [path componentsSeparatedByString: @"/"];
|
if ([path length] > 0)
|
||||||
max = [pathComponents count];
|
|
||||||
for (count = 0; currentFolder && count < max; count++)
|
|
||||||
{
|
{
|
||||||
[woContext setClientObject: currentFolder];
|
pathComponents = [path componentsSeparatedByString: @"/"];
|
||||||
currentFolder
|
max = [pathComponents count];
|
||||||
= [currentFolder lookupName: [pathComponents objectAtIndex: count]
|
for (count = 0; currentFolder && count < max; count++)
|
||||||
inContext: woContext
|
{
|
||||||
|
[woContext setClientObject: currentFolder];
|
||||||
|
currentFolder = [currentFolder
|
||||||
|
lookupName: [pathComponents objectAtIndex: count]
|
||||||
|
inContext: woContext
|
||||||
acquire: NO];
|
acquire: NO];
|
||||||
if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all
|
if ([currentFolder isKindOfClass: SOGoObjectK]) /* class common to all
|
||||||
SOGo folder types */
|
SOGo folder types */
|
||||||
[containersBag addObject: currentFolder];
|
[containersBag addObject: currentFolder];
|
||||||
else
|
else
|
||||||
currentFolder = nil;
|
currentFolder = nil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentFolder)
|
if (currentFolder)
|
||||||
|
@ -455,7 +462,6 @@ static inline NSURL *CompleteURLFromMapistoreURI (const char *uri)
|
||||||
mapiStoreObjectWithSOGoObject: currentFolder
|
mapiStoreObjectWithSOGoObject: currentFolder
|
||||||
inContainer: nil];
|
inContainer: nil];
|
||||||
[baseFolder setContext: self];
|
[baseFolder setContext: self];
|
||||||
|
|
||||||
*folderPtr = baseFolder;
|
*folderPtr = baseFolder;
|
||||||
rc = MAPISTORE_SUCCESS;
|
rc = MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreFSBaseContext.h - this file is part of SOGo
|
/* MAPIStoreDBBaseContext.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Inverse inc.
|
* Copyright (C) 2012 Inverse inc.
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,13 +20,13 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MAPISTOREFSBASECONTEXT_H
|
#ifndef MAPISTOREDBBASECONTEXT_H
|
||||||
#define MAPISTOREFSBASECONTEXT_H
|
#define MAPISTOREDBBASECONTEXT_H
|
||||||
|
|
||||||
#import "MAPIStoreContext.h"
|
#import "MAPIStoreContext.h"
|
||||||
|
|
||||||
@interface MAPIStoreFSBaseContext : MAPIStoreContext
|
@interface MAPIStoreDBBaseContext : MAPIStoreContext
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTOREFSBASECONTEXT_H */
|
#endif /* MAPISTOREDBBASECONTEXT_H */
|
116
OpenChange/MAPIStoreDBBaseContext.m
Normal file
116
OpenChange/MAPIStoreDBBaseContext.m
Normal 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
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreFSFolder.h - this file is part of SOGo
|
/* MAPIStoreDBFolder.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,14 +20,14 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MAPISTOREFSFOLDER_H
|
#ifndef MAPISTOREDBFOLDER_H
|
||||||
#define MAPISTOREFSFOLDER_H
|
#define MAPISTOREDBFOLDER_H
|
||||||
|
|
||||||
#import "MAPIStoreFolder.h"
|
#import "MAPIStoreFolder.h"
|
||||||
|
|
||||||
@interface MAPIStoreFSFolder : MAPIStoreFolder
|
@interface MAPIStoreDBFolder : MAPIStoreFolder
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
#endif /* MAPISTOREFSFOLDER_H */
|
#endif /* MAPISTOREDBFOLDER_H */
|
|
@ -1,4 +1,4 @@
|
||||||
/* MAPIStoreFSFolder.m - this file is part of SOGo
|
/* MAPIStoreDBFolder.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2011 Inverse inc
|
||||||
*
|
*
|
||||||
|
@ -24,28 +24,32 @@
|
||||||
|
|
||||||
#import <Foundation/NSArray.h>
|
#import <Foundation/NSArray.h>
|
||||||
#import <Foundation/NSCalendarDate.h>
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSException.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
#import <Foundation/NSURL.h>
|
#import <Foundation/NSURL.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
#import <EOControl/EOQualifier.h>
|
#import <EOControl/EOQualifier.h>
|
||||||
|
#import <SOGo/SOGoFolder.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import "EOQualifier+MAPI.h"
|
#import "EOQualifier+MAPI.h"
|
||||||
#import "MAPIStoreContext.h"
|
#import "MAPIStoreContext.h"
|
||||||
#import "MAPIStoreFSFolderTable.h"
|
#import "MAPIStoreDBFolderTable.h"
|
||||||
#import "MAPIStoreFSMessage.h"
|
#import "MAPIStoreDBMessage.h"
|
||||||
#import "MAPIStoreFSMessageTable.h"
|
#import "MAPIStoreDBMessageTable.h"
|
||||||
|
#import "MAPIStoreMapping.h"
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
#import "MAPIStoreUserContext.h"
|
#import "MAPIStoreUserContext.h"
|
||||||
#import "SOGoMAPIFSFolder.h"
|
#import "SOGoMAPIDBFolder.h"
|
||||||
#import "SOGoMAPIFSMessage.h"
|
#import "SOGoMAPIDBMessage.h"
|
||||||
|
|
||||||
#import "MAPIStoreFSFolder.h"
|
#import "MAPIStoreDBFolder.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <mapistore/mapistore.h>
|
#include <mapistore/mapistore.h>
|
||||||
#include <mapistore/mapistore_errors.h>
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
static Class EOKeyValueQualifierK;
|
static Class EOKeyValueQualifierK, SOGoMAPIDBFolderK, MAPIStoreDBFolderK;
|
||||||
|
|
||||||
static NSString *MAPIStoreRightReadItems = @"RightsReadItems";
|
static NSString *MAPIStoreRightReadItems = @"RightsReadItems";
|
||||||
static NSString *MAPIStoreRightCreateItems = @"RightsCreateItems";
|
static NSString *MAPIStoreRightCreateItems = @"RightsCreateItems";
|
||||||
|
@ -57,54 +61,121 @@ static NSString *MAPIStoreRightCreateSubfolders = @"RightsCreateSubfolders";
|
||||||
static NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner";
|
static NSString *MAPIStoreRightFolderOwner = @"RightsFolderOwner";
|
||||||
static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||||
|
|
||||||
@implementation MAPIStoreFSFolder
|
@implementation MAPIStoreDBFolder
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
EOKeyValueQualifierK = [EOKeyValueQualifier class];
|
EOKeyValueQualifierK = [EOKeyValueQualifier class];
|
||||||
|
SOGoMAPIDBFolderK = [SOGoMAPIDBFolder class];
|
||||||
|
MAPIStoreDBFolderK = [MAPIStoreDBFolder class];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setupAuxiliaryObjects
|
||||||
|
{
|
||||||
|
[super setupAuxiliaryObjects];
|
||||||
|
ASSIGN (sogoObject, dbFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MAPIStoreMessageTable *) messageTable
|
- (MAPIStoreMessageTable *) messageTable
|
||||||
{
|
{
|
||||||
return [MAPIStoreFSMessageTable tableForContainer: self];
|
return [MAPIStoreDBMessageTable tableForContainer: self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MAPIStoreFolderTable *) folderTable
|
- (MAPIStoreFolderTable *) folderTable
|
||||||
{
|
{
|
||||||
return [MAPIStoreFSFolderTable tableForContainer: self];
|
return [MAPIStoreDBFolderTable tableForContainer: self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (enum mapistore_error) createFolder: (struct SRow *) aRow
|
- (enum mapistore_error) createFolder: (struct SRow *) aRow
|
||||||
withFID: (uint64_t) newFID
|
withFID: (uint64_t) newFID
|
||||||
andKey: (NSString **) newKeyP
|
andKey: (NSString **) newKeyP
|
||||||
{
|
{
|
||||||
NSString *newKey, *urlString;
|
enum mapistore_error rc;
|
||||||
NSURL *childURL;
|
NSString *folderName, *nameInContainer;
|
||||||
SOGoMAPIFSFolder *childFolder;
|
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];
|
if (folderName)
|
||||||
childURL = [NSURL URLWithString: [urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
|
{
|
||||||
childFolder = [SOGoMAPIFSFolder folderWithURL: childURL
|
nameInContainer = [NSString stringWithFormat: @"0x%.16"PRIx64,
|
||||||
andTableType: MAPISTORE_MESSAGE_TABLE];
|
(unsigned long long) newFID];
|
||||||
[childFolder ensureDirectory];
|
newFolder = [SOGoMAPIDBFolderK objectWithName: nameInContainer
|
||||||
*newKeyP = newKey;
|
inContainer: sogoObject];
|
||||||
|
[newFolder reloadIfNeeded];
|
||||||
|
[[newFolder properties] setObject: folderName
|
||||||
|
forKey: MAPIPropertyKey (PidTagDisplayName)];
|
||||||
|
[newFolder save];
|
||||||
|
*newKeyP = nameInContainer;
|
||||||
|
rc = MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = MAPISTORE_ERR_INVALID_PARAMETER;
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||||
|
withNewName: (NSString *) newFolderName
|
||||||
|
{
|
||||||
|
enum mapistore_error rc;
|
||||||
|
NSString *path, *pathComponent, *targetPath, *newPath;
|
||||||
|
NSString *newURL;
|
||||||
|
MAPIStoreMapping *mapping;
|
||||||
|
NSRange slashRange;
|
||||||
|
|
||||||
|
if ([targetFolder isKindOfClass: MAPIStoreDBFolderK])
|
||||||
|
{
|
||||||
|
path = [sogoObject path];
|
||||||
|
slashRange = [path rangeOfString: @"/" options: NSBackwardsSearch];
|
||||||
|
if (slashRange.location == NSNotFound)
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"db folder path must start with a '/'"];
|
||||||
|
else
|
||||||
|
pathComponent = [path substringFromIndex: slashRange.location + 1];
|
||||||
|
targetPath = [[targetFolder sogoObject] path];
|
||||||
|
newPath = [NSString stringWithFormat: @"%@/%@",
|
||||||
|
targetPath, pathComponent];
|
||||||
|
[dbFolder changePathTo: newPath];
|
||||||
|
|
||||||
|
mapping = [self mapping];
|
||||||
|
newURL = [NSString stringWithFormat: @"%@%@/",
|
||||||
|
[targetFolder url], pathComponent];
|
||||||
|
[mapping updateID: [self objectId]
|
||||||
|
withURL: newURL];
|
||||||
|
|
||||||
|
rc = MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = MAPISTORE_ERR_DENIED;
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MAPIStoreMessage *) createMessage
|
- (MAPIStoreMessage *) createMessage
|
||||||
{
|
{
|
||||||
MAPIStoreMessage *newMessage;
|
MAPIStoreMessage *newMessage;
|
||||||
SOGoMAPIFSMessage *fsObject;
|
SOGoMAPIDBMessage *fsObject;
|
||||||
NSString *newKey;
|
NSString *newKey;
|
||||||
|
|
||||||
newKey = [NSString stringWithFormat: @"%@.plist",
|
newKey = [NSString stringWithFormat: @"%@.plist",
|
||||||
[SOGoObject globallyUniqueObjectId]];
|
[SOGoObject globallyUniqueObjectId]];
|
||||||
fsObject = [SOGoMAPIFSMessage objectWithName: newKey
|
fsObject = [SOGoMAPIDBMessage objectWithName: newKey
|
||||||
inContainer: sogoObject];
|
inContainer: sogoObject];
|
||||||
newMessage = [MAPIStoreFSMessage mapiStoreObjectWithSOGoObject: fsObject
|
[fsObject setObjectType: MAPIDBObjectTypeMessage];
|
||||||
|
[fsObject reloadIfNeeded];
|
||||||
|
newMessage = [MAPIStoreDBMessage mapiStoreObjectWithSOGoObject: fsObject
|
||||||
inContainer: self];
|
inContainer: self];
|
||||||
|
|
||||||
return newMessage;
|
return newMessage;
|
||||||
|
@ -119,9 +190,10 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||||
ownerUser = [[self userContext] sogoUser];
|
ownerUser = [[self userContext] sogoUser];
|
||||||
if ([[context activeUser] isEqual: ownerUser]
|
if ([[context activeUser] isEqual: ownerUser]
|
||||||
|| [self subscriberCanReadMessages])
|
|| [self subscriberCanReadMessages])
|
||||||
keys = [(SOGoMAPIFSFolder *) sogoObject
|
keys = [(SOGoMAPIDBFolder *) sogoObject childKeysOfType: MAPIDBObjectTypeMessage
|
||||||
toOneRelationshipKeysMatchingQualifier: qualifier
|
includeDeleted: NO
|
||||||
andSortOrderings: sortOrderings];
|
matchingQualifier: qualifier
|
||||||
|
andSortOrderings: sortOrderings];
|
||||||
else
|
else
|
||||||
keys = [NSArray array];
|
keys = [NSArray array];
|
||||||
|
|
||||||
|
@ -131,39 +203,26 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||||
- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier
|
- (NSArray *) folderKeysMatchingQualifier: (EOQualifier *) qualifier
|
||||||
andSortOrderings: (NSArray *) sortOrderings
|
andSortOrderings: (NSArray *) sortOrderings
|
||||||
{
|
{
|
||||||
NSArray *entries;
|
return [dbFolder childKeysOfType: MAPIDBObjectTypeFolder
|
||||||
NSMutableArray *filteredEntries;
|
includeDeleted: NO
|
||||||
NSUInteger count, max;
|
matchingQualifier: qualifier
|
||||||
MAPIStoreFSFolder *subfolder;
|
andSortOrderings: sortOrderings];
|
||||||
SOGoMAPIFSMessage *propertiesMessage;
|
|
||||||
NSString *subfolderKey;
|
|
||||||
|
|
||||||
entries = [(SOGoMAPIFSFolder *) sogoObject toManyRelationshipKeys];
|
|
||||||
if (qualifier)
|
|
||||||
{
|
|
||||||
max = [entries count];
|
|
||||||
filteredEntries = [NSMutableArray arrayWithCapacity: max];
|
|
||||||
for (count = 0; count < max; count++)
|
|
||||||
{
|
|
||||||
subfolderKey = [entries objectAtIndex: count];
|
|
||||||
subfolder = [self lookupFolder: subfolderKey];
|
|
||||||
propertiesMessage = [subfolder propertiesMessage];
|
|
||||||
if ([qualifier evaluateMAPIVolatileMessage: propertiesMessage])
|
|
||||||
[filteredEntries addObject: subfolderKey];
|
|
||||||
}
|
|
||||||
entries = filteredEntries;
|
|
||||||
}
|
|
||||||
if (sortOrderings)
|
|
||||||
[self errorWithFormat: @"sort orderings are not used for folders"];
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
- (NSDate *) lastMessageModificationTime
|
||||||
{
|
{
|
||||||
NSUInteger count, max;
|
NSUInteger count, max;
|
||||||
NSDate *date, *fileDate;
|
NSDate *date, *fileDate;
|
||||||
MAPIStoreFSMessage *msg;
|
MAPIStoreDBMessage *msg;
|
||||||
NSArray *messageKeys;
|
NSArray *messageKeys;
|
||||||
|
|
||||||
messageKeys = [self messageKeys];
|
messageKeys = [self messageKeys];
|
||||||
|
@ -189,7 +248,7 @@ static NSString *MAPIStoreRightFolderContact = @"RightsFolderContact";
|
||||||
|
|
||||||
- (SOGoFolder *) aclFolder
|
- (SOGoFolder *) aclFolder
|
||||||
{
|
{
|
||||||
return propsFolder;
|
return sogoObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
|
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreFSFolderTable.h - this file is part of SOGo
|
/* MAPIStoreDBFolderTable.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,12 +20,12 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MAPISTOREFSFOLDERTABLE_H
|
#ifndef MAPISTOREDBFOLDERTABLE_H
|
||||||
#define MAPISTOREFSFOLDERTABLE_H
|
#define MAPISTOREDBFOLDERTABLE_H
|
||||||
|
|
||||||
#import "MAPIStoreFolderTable.h"
|
#import "MAPIStoreFolderTable.h"
|
||||||
|
|
||||||
@interface MAPIStoreFSFolderTable : MAPIStoreFolderTable
|
@interface MAPIStoreDBFolderTable : MAPIStoreFolderTable
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTOREFSFOLDERTABLE_H */
|
#endif /* MAPISTOREDBFOLDERTABLE_H */
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreFSFolderTable.m - this file is part of SOGo
|
/* MAPIStoreDBFolderTable.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -24,9 +24,9 @@
|
||||||
|
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
|
|
||||||
#import "MAPIStoreFSFolderTable.h"
|
#import "MAPIStoreDBFolderTable.h"
|
||||||
|
|
||||||
@implementation MAPIStoreFSFolderTable
|
@implementation MAPIStoreDBFolderTable
|
||||||
|
|
||||||
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreFSMessage.h - this file is part of SOGo
|
/* MAPIStoreDBMessage.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,12 +20,12 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MAPISTOREFSMESSAGE_H
|
#ifndef MAPISTOREDBMESSAGE_H
|
||||||
#define MAPISTOREFSMESSAGE_H
|
#define MAPISTOREDBMESSAGE_H
|
||||||
|
|
||||||
#import "MAPIStoreVolatileMessage.h"
|
#import "MAPIStoreMessage.h"
|
||||||
|
|
||||||
@interface MAPIStoreFSMessage : MAPIStoreVolatileMessage
|
@interface MAPIStoreDBMessage : MAPIStoreMessage
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTOREFSMESSAGE_H */
|
#endif /* MAPISTOREDBMESSAGE_H */
|
|
@ -1,4 +1,4 @@
|
||||||
/* MAPIStoreFSMessage.m - this file is part of SOGo
|
/* MAPIStoreDBMessage.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2011 Inverse inc
|
||||||
*
|
*
|
||||||
|
@ -21,24 +21,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/NSArray.h>
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSValue.h>
|
#import <Foundation/NSValue.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
#import "MAPIStoreContext.h"
|
#import "MAPIStoreContext.h"
|
||||||
#import "MAPIStorePropertySelectors.h"
|
#import "MAPIStorePropertySelectors.h"
|
||||||
#import "SOGoMAPIFSMessage.h"
|
#import "SOGoMAPIDBMessage.h"
|
||||||
|
|
||||||
#import "MAPIStoreFSFolder.h"
|
#import "MAPIStoreDBFolder.h"
|
||||||
#import "MAPIStoreFSMessage.h"
|
#import "MAPIStoreDBMessage.h"
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
#import "NSData+MAPIStore.h"
|
#import "NSObject+MAPIStore.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <mapistore/mapistore.h>
|
#include <mapistore/mapistore.h>
|
||||||
#include <mapistore/mapistore_errors.h>
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
@implementation MAPIStoreFSMessage
|
@implementation MAPIStoreDBMessage
|
||||||
|
|
||||||
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
@ -60,13 +61,79 @@
|
||||||
/* FIXME (hack): append a few undocumented properties that can be added to
|
/* FIXME (hack): append a few undocumented properties that can be added to
|
||||||
FAI messages */
|
FAI messages */
|
||||||
for (count = 0; count < 8; count++)
|
for (count = 0; count < 8; count++)
|
||||||
properties->aulPropTag[MAPIStoreSupportedPropertiesCount+count] = faiProperties[count];
|
properties->aulPropTag[MAPIStoreSupportedPropertiesCount+count]
|
||||||
|
= faiProperties[count];
|
||||||
|
|
||||||
*propertiesP = properties;
|
*propertiesP = properties;
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) initWithSOGoObject: (id) newSOGoObject
|
||||||
|
inContainer: (MAPIStoreObject *) newContainer
|
||||||
|
{
|
||||||
|
if ((self = [super initWithSOGoObject: newSOGoObject
|
||||||
|
inContainer: newContainer]))
|
||||||
|
{
|
||||||
|
[properties release];
|
||||||
|
properties = [newSOGoObject properties];
|
||||||
|
[properties retain];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (uint64_t) objectVersion
|
||||||
|
{
|
||||||
|
NSNumber *versionNbr;
|
||||||
|
uint64_t objectVersion;
|
||||||
|
|
||||||
|
[(SOGoMAPIDBMessage *) sogoObject reloadIfNeeded];
|
||||||
|
versionNbr = [properties objectForKey: @"version"];
|
||||||
|
if (versionNbr)
|
||||||
|
objectVersion = [versionNbr unsignedLongLongValue] >> 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
|
- (void) save
|
||||||
{
|
{
|
||||||
uint64_t newVersion;
|
uint64_t newVersion;
|
||||||
|
@ -74,15 +141,13 @@
|
||||||
if ([attachmentKeys count] > 0)
|
if ([attachmentKeys count] > 0)
|
||||||
[properties setObject: attachmentParts forKey: @"attachments"];
|
[properties setObject: attachmentParts forKey: @"attachments"];
|
||||||
|
|
||||||
newVersion = exchange_globcnt ([[self context] getNewChangeNumber] >> 16);
|
newVersion = [[self context] getNewChangeNumber];
|
||||||
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
|
[properties setObject: [NSNumber numberWithUnsignedLongLong: newVersion]
|
||||||
forKey: @"version"];
|
forKey: @"version"];
|
||||||
|
|
||||||
[self logWithFormat: @"%d props in dict", [properties count]];
|
[self logWithFormat: @"%d props in dict", [properties count]];
|
||||||
|
|
||||||
[sogoObject appendProperties: properties];
|
|
||||||
[sogoObject save];
|
[sogoObject save];
|
||||||
[properties removeAllObjects];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) _messageIsFreeBusy
|
- (BOOL) _messageIsFreeBusy
|
||||||
|
@ -91,7 +156,7 @@
|
||||||
|
|
||||||
/* This is a HACK until we figure out how to determine a message position in
|
/* This is a HACK until we figure out how to determine a message position in
|
||||||
the mailbox hierarchy.... (missing: folderid and role) */
|
the mailbox hierarchy.... (missing: folderid and role) */
|
||||||
msgClass = [[sogoObject properties]
|
msgClass = [properties
|
||||||
objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)];
|
objectForKey: MAPIPropertyKey (PR_MESSAGE_CLASS_UNICODE)];
|
||||||
|
|
||||||
return [msgClass isEqualToString: @"IPM.Microsoft.ScheduleData.FreeBusy"];
|
return [msgClass isEqualToString: @"IPM.Microsoft.ScheduleData.FreeBusy"];
|
||||||
|
@ -115,12 +180,12 @@
|
||||||
|
|
||||||
- (NSDate *) creationTime
|
- (NSDate *) creationTime
|
||||||
{
|
{
|
||||||
return [sogoObject creationTime];
|
return [sogoObject creationDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDate *) lastModificationTime
|
- (NSDate *) lastModificationTime
|
||||||
{
|
{
|
||||||
return [sogoObject lastModificationTime];
|
return [sogoObject lastModified];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreFSMessageTable.h - this file is part of SOGo
|
/* MAPIStoreDBMessageTable.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,12 +20,12 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MAPISTOREFSMESSAGETABLE_H
|
#ifndef MAPISTOREDBMESSAGETABLE_H
|
||||||
#define MAPISTOREFSMESSAGETABLE_H
|
#define MAPISTOREDBMESSAGETABLE_H
|
||||||
|
|
||||||
#import "MAPIStoreMessageTable.h"
|
#import "MAPIStoreMessageTable.h"
|
||||||
|
|
||||||
@interface MAPIStoreFSMessageTable : MAPIStoreMessageTable
|
@interface MAPIStoreDBMessageTable : MAPIStoreMessageTable
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTOREFSMESSAGETABLE_H */
|
#endif /* MAPISTOREDBMESSAGETABLE_H */
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreFSMessageTable.m - this file is part of SOGo
|
/* MAPIStoreDBMessageTable.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -25,25 +25,25 @@
|
||||||
#import <EOControl/EOQualifier.h>
|
#import <EOControl/EOQualifier.h>
|
||||||
|
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
#import "MAPIStoreFSMessage.h"
|
#import "MAPIStoreDBMessage.h"
|
||||||
|
|
||||||
#import "MAPIStoreFSMessageTable.h"
|
#import "MAPIStoreDBMessageTable.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <mapistore/mapistore.h>
|
#include <mapistore/mapistore.h>
|
||||||
|
|
||||||
static Class MAPIStoreFSMessageK = Nil;
|
static Class MAPIStoreDBMessageK = Nil;
|
||||||
|
|
||||||
@implementation MAPIStoreFSMessageTable
|
@implementation MAPIStoreDBMessageTable
|
||||||
|
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
MAPIStoreFSMessageK = [MAPIStoreFSMessage class];
|
MAPIStoreDBMessageK = [MAPIStoreDBMessage class];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (Class) childObjectClass
|
+ (Class) childObjectClass
|
||||||
{
|
{
|
||||||
return MAPIStoreFSMessageK;
|
return MAPIStoreDBMessageK;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
|
@ -26,13 +26,6 @@
|
||||||
#import "MAPIStoreMessage.h"
|
#import "MAPIStoreMessage.h"
|
||||||
|
|
||||||
@interface MAPIStoreEmbeddedMessage : MAPIStoreMessage
|
@interface MAPIStoreEmbeddedMessage : MAPIStoreMessage
|
||||||
{
|
|
||||||
id attachment;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (id) embeddedMessageWithAttachment: (id) newAttachment;
|
|
||||||
|
|
||||||
- (id) initWithAttachment: (id) newAttachment;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,13 @@
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
#import "MAPIStoreAttachment.h"
|
#import "MAPIStoreAttachment.h"
|
||||||
|
#import "MAPIStoreFolder.h"
|
||||||
|
#import "NSObject+MAPIStore.h"
|
||||||
|
|
||||||
#import "MAPIStoreEmbeddedMessage.h"
|
#import "MAPIStoreEmbeddedMessage.h"
|
||||||
|
|
||||||
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
static Class MAPIStoreAttachmentK;
|
static Class MAPIStoreAttachmentK;
|
||||||
|
|
||||||
@implementation MAPIStoreEmbeddedMessage
|
@implementation MAPIStoreEmbeddedMessage
|
||||||
|
@ -35,30 +39,116 @@ static Class MAPIStoreAttachmentK;
|
||||||
MAPIStoreAttachmentK = [MAPIStoreAttachment class];
|
MAPIStoreAttachmentK = [MAPIStoreAttachment class];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) embeddedMessageWithAttachment: (id) newAttachment
|
- (uint64_t) objectId
|
||||||
{
|
{
|
||||||
MAPIStoreEmbeddedMessage *newMessage;
|
NSString *objectKey;
|
||||||
|
MAPIStoreMessage *grandParent;
|
||||||
|
|
||||||
newMessage = [[self alloc] initWithAttachment: newAttachment];
|
grandParent = (MAPIStoreMessage *) [container container];
|
||||||
[newMessage autorelease];
|
|
||||||
|
|
||||||
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]))
|
return [self getLongZero: data inMemCtx: memCtx];
|
||||||
{
|
|
||||||
if ([newAttachment isKindOfClass: MAPIStoreAttachmentK])
|
|
||||||
ASSIGN (container, newAttachment);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
- (NSString *) nameInContainer
|
||||||
{
|
{
|
||||||
return @"as-message";
|
return @"as-message";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (uint64_t) objectVersion
|
||||||
|
{
|
||||||
|
return ULLONG_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) save
|
||||||
|
{
|
||||||
|
[self subclassResponsibility: _cmd];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#ifndef MAPISTOREFAIMESSAGE_H
|
#ifndef MAPISTOREFAIMESSAGE_H
|
||||||
#define MAPISTOREFAIMESSAGE_H
|
#define MAPISTOREFAIMESSAGE_H
|
||||||
|
|
||||||
#import "MAPIStoreFSMessage.h"
|
#import "MAPIStoreDBMessage.h"
|
||||||
|
|
||||||
@interface MAPIStoreFAIMessage : MAPIStoreFSMessage
|
@interface MAPIStoreFAIMessage : MAPIStoreDBMessage
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTOREFAIMESSAGE_H */
|
#endif /* MAPISTOREFAIMESSAGE_H */
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#ifndef MAPISTOREFAIMESSAGETABLE_H
|
#ifndef MAPISTOREFAIMESSAGETABLE_H
|
||||||
#define MAPISTOREFAIMESSAGETABLE_H
|
#define MAPISTOREFAIMESSAGETABLE_H
|
||||||
|
|
||||||
#import "MAPIStoreFSMessageTable.h"
|
#import "MAPIStoreDBMessageTable.h"
|
||||||
|
|
||||||
@interface MAPIStoreFAIMessageTable : MAPIStoreFSMessageTable
|
@interface MAPIStoreFAIMessageTable : MAPIStoreDBMessageTable
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTOREFAIMESSAGETABLE_H */
|
#endif /* MAPISTOREFAIMESSAGETABLE_H */
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
/* MAPIStoreFSBaseContext.m - this file is part of SOGo
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Inverse inc.
|
|
||||||
*
|
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This file is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* A generic parent class for all context that will store their data on the
|
|
||||||
disk in the form of a plist. */
|
|
||||||
|
|
||||||
#import <Foundation/NSString.h>
|
|
||||||
#import <Foundation/NSURL.h>
|
|
||||||
|
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
|
||||||
|
|
||||||
#import "MAPIStoreFSFolder.h"
|
|
||||||
#import "MAPIStoreMapping.h"
|
|
||||||
#import "MAPIStoreUserContext.h"
|
|
||||||
#import "SOGoMAPIFSFolder.h"
|
|
||||||
|
|
||||||
#import "MAPIStoreFSBaseContext.h"
|
|
||||||
|
|
||||||
#undef DEBUG
|
|
||||||
#include <mapistore/mapistore.h>
|
|
||||||
|
|
||||||
static Class MAPIStoreFSFolderK;
|
|
||||||
|
|
||||||
@implementation MAPIStoreFSBaseContext
|
|
||||||
|
|
||||||
+ (void) initialize
|
|
||||||
{
|
|
||||||
MAPIStoreFSFolderK = [MAPIStoreFSFolder class];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSString *) MAPIModuleName
|
|
||||||
{
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (Class) MAPIStoreFolderClass
|
|
||||||
{
|
|
||||||
return MAPIStoreFSFolderK;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) ensureContextFolder
|
|
||||||
{
|
|
||||||
SOGoMAPIFSFolder *contextFolder;
|
|
||||||
|
|
||||||
contextFolder = [SOGoMAPIFSFolder folderWithURL: contextUrl
|
|
||||||
andTableType: MAPISTORE_MESSAGE_TABLE];
|
|
||||||
[contextFolder ensureDirectory];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) rootSOGoFolder
|
|
||||||
{
|
|
||||||
NSString *urlString;
|
|
||||||
|
|
||||||
urlString = [NSString stringWithFormat: @"sogo://%@@%@/",
|
|
||||||
[userContext username], [isa MAPIModuleName]];
|
|
||||||
return [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: urlString]
|
|
||||||
andTableType: MAPISTORE_MESSAGE_TABLE];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -23,9 +23,9 @@
|
||||||
#ifndef MAPISTOREFALLBACKCONTEXT_H
|
#ifndef MAPISTOREFALLBACKCONTEXT_H
|
||||||
#define MAPISTOREFALLBACKCONTEXT_H
|
#define MAPISTOREFALLBACKCONTEXT_H
|
||||||
|
|
||||||
#import "MAPIStoreFSBaseContext.h"
|
#import "MAPIStoreDBBaseContext.h"
|
||||||
|
|
||||||
@interface MAPIStoreFallbackContext : MAPIStoreFSBaseContext
|
@interface MAPIStoreFallbackContext : MAPIStoreDBBaseContext
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#import "MAPIStoreUserContext.h"
|
#import "MAPIStoreUserContext.h"
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
#import "SOGoMAPIFSFolder.h"
|
#import "SOGoMAPIDBFolder.h"
|
||||||
|
|
||||||
#import "MAPIStoreFallbackContext.h"
|
#import "MAPIStoreFallbackContext.h"
|
||||||
|
|
||||||
|
@ -51,10 +51,11 @@
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
struct mapistore_contexts_list *firstContext = NULL, *context;
|
struct mapistore_contexts_list *firstContext = NULL, *context;
|
||||||
SOGoMAPIFSFolder *root;
|
SOGoMAPIDBFolder *root;
|
||||||
NSArray *names;
|
NSArray *names;
|
||||||
NSUInteger count, max;
|
NSUInteger count, max;
|
||||||
NSString *baseURL, *url, *name;
|
NSString *baseURL, *url, *name;
|
||||||
|
MAPIStoreUserContext *userContext;
|
||||||
|
|
||||||
baseURL = [NSString stringWithFormat: @"sogo://%@@fallback/", userName];
|
baseURL = [NSString stringWithFormat: @"sogo://%@@fallback/", userName];
|
||||||
|
|
||||||
|
@ -67,11 +68,15 @@
|
||||||
|
|
||||||
DLIST_ADD_END (firstContext, context, void);
|
DLIST_ADD_END (firstContext, context, void);
|
||||||
|
|
||||||
|
|
||||||
/* Maybe emsmdbp_provisioning should be fixed in order to only take the uri
|
/* Maybe emsmdbp_provisioning should be fixed in order to only take the uri
|
||||||
returned above to avoid deleting its entries... */
|
returned above to avoid deleting its entries... */
|
||||||
root = [SOGoMAPIFSFolder folderWithURL: [NSURL URLWithString: baseURL]
|
root = [SOGoMAPIDBFolder objectWithName: [self MAPIModuleName]
|
||||||
andTableType: MAPISTORE_MESSAGE_TABLE];
|
inContainer: nil];
|
||||||
|
[root setOwner: userName];
|
||||||
|
userContext = [MAPIStoreUserContext userContextWithUsername: userName
|
||||||
|
andTDBIndexing: indexingTdb];
|
||||||
|
[userContext ensureFolderTableExists];
|
||||||
|
[root setTableUrl: [userContext folderTableURL]];
|
||||||
names = [root toManyRelationshipKeys];
|
names = [root toManyRelationshipKeys];
|
||||||
max = [names count];
|
max = [names count];
|
||||||
for (count = 0; count < max; count++)
|
for (count = 0; count < max; count++)
|
||||||
|
|
|
@ -38,29 +38,34 @@
|
||||||
@class MAPIStoreMessageTable;
|
@class MAPIStoreMessageTable;
|
||||||
@class MAPIStorePermissionsTable;
|
@class MAPIStorePermissionsTable;
|
||||||
@class SOGoFolder;
|
@class SOGoFolder;
|
||||||
@class SOGoMAPIFSFolder;
|
@class SOGoMAPIDBFolder;
|
||||||
@class SOGoMAPIFSMessage;
|
@class SOGoMAPIDBMessage;
|
||||||
|
|
||||||
#import "MAPIStoreObject.h"
|
#import "MAPIStoreSOGoObject.h"
|
||||||
|
|
||||||
@interface MAPIStoreFolder : MAPIStoreObject
|
@interface MAPIStoreFolder : MAPIStoreSOGoObject
|
||||||
{
|
{
|
||||||
MAPIStoreContext *context;
|
MAPIStoreContext *context;
|
||||||
// NSArray *messageKeys;
|
// NSArray *messageKeys;
|
||||||
// NSArray *faiMessageKeys;
|
// NSArray *faiMessageKeys;
|
||||||
// NSArray *folderKeys;
|
// NSArray *folderKeys;
|
||||||
|
|
||||||
SOGoMAPIFSFolder *faiFolder;
|
SOGoMAPIDBFolder *dbFolder;
|
||||||
SOGoMAPIFSFolder *propsFolder;
|
// SOGoMAPIDBFolder *faiFolder;
|
||||||
SOGoMAPIFSMessage *propsMessage;
|
// SOGoMAPIDBFolder *propsFolder;
|
||||||
|
// SOGoMAPIDBMessage *propsMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setContext: (MAPIStoreContext *) newContext;
|
- (void) setContext: (MAPIStoreContext *) newContext;
|
||||||
|
|
||||||
|
- (void) setupAuxiliaryObjects;
|
||||||
|
|
||||||
|
- (SOGoMAPIDBFolder *) dbFolder;
|
||||||
|
|
||||||
- (NSArray *) activeMessageTables;
|
- (NSArray *) activeMessageTables;
|
||||||
- (NSArray *) activeFAIMessageTables;
|
- (NSArray *) activeFAIMessageTables;
|
||||||
|
|
||||||
- (SOGoMAPIFSMessage *) propertiesMessage;
|
// - (SOGoMAPIDBMessage *) propertiesMessage;
|
||||||
|
|
||||||
- (id) lookupMessageByURL: (NSString *) messageURL;
|
- (id) lookupMessageByURL: (NSString *) messageURL;
|
||||||
- (id) lookupFolderByURL: (NSString *) folderURL;
|
- (id) lookupFolderByURL: (NSString *) folderURL;
|
||||||
|
@ -118,6 +123,12 @@
|
||||||
andChangeKeys: (struct Binary_r **) targetChangeKeys
|
andChangeKeys: (struct Binary_r **) targetChangeKeys
|
||||||
wantCopy: (uint8_t) want_copy;
|
wantCopy: (uint8_t) want_copy;
|
||||||
|
|
||||||
|
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||||
|
withNewName: (NSString *) newFolderName;
|
||||||
|
- (enum mapistore_error) copyToFolder: (MAPIStoreFolder *) targetFolder
|
||||||
|
recursive: (BOOL) resursive
|
||||||
|
withNewName: (NSString *) newFolderName;
|
||||||
|
|
||||||
- (int) getDeletedFMIDs: (struct I8Array_r **) fmidsPtr
|
- (int) getDeletedFMIDs: (struct I8Array_r **) fmidsPtr
|
||||||
andCN: (uint64_t *) cnPtr
|
andCN: (uint64_t *) cnPtr
|
||||||
fromChangeNumber: (uint64_t) changeNum
|
fromChangeNumber: (uint64_t) changeNum
|
||||||
|
|
|
@ -48,8 +48,8 @@
|
||||||
#import "NSDate+MAPIStore.h"
|
#import "NSDate+MAPIStore.h"
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
#import "NSObject+MAPIStore.h"
|
#import "NSObject+MAPIStore.h"
|
||||||
#import "SOGoMAPIFSFolder.h"
|
#import "SOGoMAPIDBFolder.h"
|
||||||
#import "SOGoMAPIFSMessage.h"
|
#import "SOGoMAPIDBMessage.h"
|
||||||
|
|
||||||
#include <gen_ndr/exchange.h>
|
#include <gen_ndr/exchange.h>
|
||||||
|
|
||||||
|
@ -79,33 +79,67 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
// messageKeys = nil;
|
// messageKeys = nil;
|
||||||
// faiMessageKeys = nil;
|
// faiMessageKeys = nil;
|
||||||
// folderKeys = nil;
|
// folderKeys = nil;
|
||||||
faiFolder = nil;
|
dbFolder = nil;
|
||||||
context = nil;
|
context = nil;
|
||||||
|
|
||||||
propsFolder = nil;
|
// propsFolder = nil;
|
||||||
propsMessage = nil;
|
// propsMessage = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _setupAuxiliaryObjects
|
- (void) setupAuxiliaryObjects
|
||||||
{
|
{
|
||||||
NSURL *propsURL;
|
NSURL *folderURL;
|
||||||
NSString *urlString;
|
NSMutableString *pathPrefix;
|
||||||
|
NSString *path, *folderName;
|
||||||
|
NSArray *parts;
|
||||||
|
NSUInteger lastPartIdx;
|
||||||
|
MAPIStoreUserContext *userContext;
|
||||||
|
|
||||||
|
folderURL = [NSURL URLWithString: [self url]];
|
||||||
|
path = [folderURL path];
|
||||||
|
path = [path substringFromIndex: 1];
|
||||||
|
if ([path length] > 0)
|
||||||
|
{
|
||||||
|
parts = [path componentsSeparatedByString: @"/"];
|
||||||
|
lastPartIdx = [parts count] - 1;
|
||||||
|
if ([path hasSuffix: @"/"])
|
||||||
|
lastPartIdx--;
|
||||||
|
folderName = [parts objectAtIndex: lastPartIdx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
folderName = [folderURL host];
|
||||||
|
|
||||||
|
userContext = [self userContext];
|
||||||
|
[userContext ensureFolderTableExists];
|
||||||
|
|
||||||
|
ASSIGN (dbFolder,
|
||||||
|
[SOGoMAPIDBFolder objectWithName: folderName
|
||||||
|
inContainer: [container dbFolder]]);
|
||||||
|
[dbFolder setTableUrl: [userContext folderTableURL]];
|
||||||
|
if (!container && [path length] > 0)
|
||||||
|
{
|
||||||
|
pathPrefix = [NSMutableString stringWithCapacity: 64];
|
||||||
|
[pathPrefix appendFormat: @"/%@", [folderURL host]];
|
||||||
|
parts = [parts subarrayWithRange: NSMakeRange (0, lastPartIdx)];
|
||||||
|
if ([parts count] > 0)
|
||||||
|
[pathPrefix appendFormat: @"/%@", [parts componentsJoinedByString: @"/"]];
|
||||||
|
[dbFolder setPathPrefix: pathPrefix];
|
||||||
|
}
|
||||||
|
[dbFolder reloadIfNeeded];
|
||||||
|
|
||||||
|
/* propsMessage and self share the same properties dictionary */
|
||||||
|
// ASSIGN (propsMessage,
|
||||||
|
// [SOGoMAPIDBMessage objectWithName: @"properties.plist"
|
||||||
|
// inContainer: dbFolder]);
|
||||||
|
// [propsMessage setObjectType: MAPIDBObjectTypeInternal];
|
||||||
|
// [propsMessage reloadIfNeeded];
|
||||||
|
[properties release];
|
||||||
|
properties = [dbFolder properties];
|
||||||
|
[properties retain];
|
||||||
|
|
||||||
urlString = [[self url] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
|
|
||||||
propsURL = [NSURL URLWithString: urlString];
|
|
||||||
[self logWithFormat: @"_setupAuxiliaryObjects: %@", propsURL];
|
|
||||||
ASSIGN (faiFolder,
|
|
||||||
[SOGoMAPIFSFolder folderWithURL: propsURL
|
|
||||||
andTableType: MAPISTORE_FAI_TABLE]);
|
|
||||||
ASSIGN (propsFolder,
|
|
||||||
[SOGoMAPIFSFolder folderWithURL: propsURL
|
|
||||||
andTableType: MAPISTORE_FOLDER_TABLE]);
|
|
||||||
ASSIGN (propsMessage,
|
|
||||||
[SOGoMAPIFSMessage objectWithName: @"properties.plist"
|
|
||||||
inContainer: propsFolder]);
|
|
||||||
[self setupVersionsMessage];
|
[self setupVersionsMessage];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +153,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
inContainer: newContainer])
|
inContainer: newContainer])
|
||||||
&& newContainer)
|
&& newContainer)
|
||||||
{
|
{
|
||||||
[self _setupAuxiliaryObjects];
|
[self setupAuxiliaryObjects];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -129,13 +163,13 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
{
|
{
|
||||||
ASSIGN (context, newContext);
|
ASSIGN (context, newContext);
|
||||||
if (newContext)
|
if (newContext)
|
||||||
[self _setupAuxiliaryObjects];
|
[self setupAuxiliaryObjects];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MAPIStoreContext *) context
|
- (MAPIStoreContext *) context
|
||||||
{
|
{
|
||||||
if (!context)
|
if (!context)
|
||||||
[self setContext: [container context]];
|
[self setContext: (MAPIStoreContext *) [container context]];
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
@ -145,29 +179,31 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
// [messageKeys release];
|
// [messageKeys release];
|
||||||
// [faiMessageKeys release];
|
// [faiMessageKeys release];
|
||||||
// [folderKeys release];
|
// [folderKeys release];
|
||||||
[propsMessage release];
|
// [propsMessage release];
|
||||||
[propsFolder release];
|
[dbFolder release];
|
||||||
[faiFolder release];
|
|
||||||
[context release];
|
[context release];
|
||||||
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (SOGoMAPIDBFolder *) dbFolder
|
||||||
|
{
|
||||||
|
return dbFolder;
|
||||||
|
}
|
||||||
|
|
||||||
/* backend interface */
|
/* backend interface */
|
||||||
|
|
||||||
- (SOGoMAPIFSMessage *) propertiesMessage
|
// - (SOGoMAPIDBMessage *) propertiesMessage
|
||||||
{
|
// {
|
||||||
return propsMessage;
|
// return propsMessage;
|
||||||
}
|
// }
|
||||||
|
|
||||||
- (uint64_t) objectVersion
|
- (uint64_t) objectVersion
|
||||||
{
|
{
|
||||||
NSNumber *value;
|
NSNumber *value;
|
||||||
NSDictionary *props;
|
|
||||||
uint64_t cn;
|
uint64_t cn;
|
||||||
|
|
||||||
props = [propsMessage properties];
|
value = [properties objectForKey: MAPIPropertyKey (PidTagChangeNumber)];
|
||||||
value = [props objectForKey: MAPIPropertyKey (PidTagChangeNumber)];
|
|
||||||
if (value)
|
if (value)
|
||||||
cn = [value unsignedLongLongValue];
|
cn = [value unsignedLongLongValue];
|
||||||
else
|
else
|
||||||
|
@ -175,10 +211,10 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
[self logWithFormat: @"no value for PidTagChangeNumber, adding one now"];
|
[self logWithFormat: @"no value for PidTagChangeNumber, adding one now"];
|
||||||
cn = [[self context] getNewChangeNumber];
|
cn = [[self context] getNewChangeNumber];
|
||||||
value = [NSNumber numberWithUnsignedLongLong: cn];
|
value = [NSNumber numberWithUnsignedLongLong: cn];
|
||||||
props = [NSDictionary dictionaryWithObject: value
|
|
||||||
forKey: MAPIPropertyKey (PidTagChangeNumber)];
|
[properties setObject: value
|
||||||
[propsMessage appendProperties: props];
|
forKey: MAPIPropertyKey (PidTagChangeNumber)];
|
||||||
[propsMessage save];
|
[dbFolder save];
|
||||||
}
|
}
|
||||||
|
|
||||||
return cn >> 16;
|
return cn >> 16;
|
||||||
|
@ -186,21 +222,24 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
|
|
||||||
- (id) lookupFolder: (NSString *) folderKey
|
- (id) lookupFolder: (NSString *) folderKey
|
||||||
{
|
{
|
||||||
MAPIStoreFolder *childFolder = nil;
|
MAPIStoreFolder *childFolder;
|
||||||
SOGoFolder *sogoFolder;
|
SOGoFolder *sogoFolder;
|
||||||
WOContext *woContext;
|
WOContext *woContext;
|
||||||
|
|
||||||
if ([[self folderKeys] containsObject: folderKey])
|
if ([[self folderKeys] containsObject: folderKey])
|
||||||
{
|
{
|
||||||
woContext = [[self userContext] woContext];
|
woContext = [[self userContext] woContext];
|
||||||
sogoFolder = [sogoObject lookupName: folderKey
|
sogoFolder = [sogoObject lookupName: folderKey inContext: woContext
|
||||||
inContext: woContext
|
|
||||||
acquire: NO];
|
acquire: NO];
|
||||||
[sogoFolder setContext: woContext];
|
|
||||||
if (sogoFolder && ![sogoFolder isKindOfClass: NSExceptionK])
|
if (sogoFolder && ![sogoFolder isKindOfClass: NSExceptionK])
|
||||||
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder
|
{
|
||||||
inContainer: self];
|
[sogoFolder setContext: woContext];
|
||||||
|
childFolder = [isa mapiStoreObjectWithSOGoObject: sogoFolder
|
||||||
|
inContainer: self];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
childFolder = nil;
|
||||||
|
|
||||||
return childFolder;
|
return childFolder;
|
||||||
}
|
}
|
||||||
|
@ -264,9 +303,9 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
{
|
{
|
||||||
if ([[self faiMessageKeys] containsObject: messageKey])
|
if ([[self faiMessageKeys] containsObject: messageKey])
|
||||||
{
|
{
|
||||||
msgObject = [faiFolder lookupName: messageKey
|
msgObject = [dbFolder lookupName: messageKey
|
||||||
inContext: nil
|
inContext: nil
|
||||||
acquire: NO];
|
acquire: NO];
|
||||||
childMessage
|
childMessage
|
||||||
= [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: msgObject
|
= [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: msgObject
|
||||||
inContainer: self];
|
inContainer: self];
|
||||||
|
@ -360,7 +399,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
baseURL = [self url];
|
baseURL = [self url];
|
||||||
if (![baseURL hasSuffix: @"/"])
|
if (![baseURL hasSuffix: @"/"])
|
||||||
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
|
baseURL = [NSString stringWithFormat: @"%@/", baseURL];
|
||||||
childURL = [NSString stringWithFormat: @"%@%@",
|
childURL = [NSString stringWithFormat: @"%@%@/",
|
||||||
baseURL, folderKey];
|
baseURL, folderKey];
|
||||||
[mapping registerURL: childURL withID: fid];
|
[mapping registerURL: childURL withID: fid];
|
||||||
childFolder = [self lookupFolder: folderKey];
|
childFolder = [self lookupFolder: folderKey];
|
||||||
|
@ -383,9 +422,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
|
|
||||||
- (int) deleteFolder
|
- (int) deleteFolder
|
||||||
{
|
{
|
||||||
[propsMessage delete];
|
// [propsMessage delete];
|
||||||
[propsFolder delete];
|
[dbFolder delete];
|
||||||
[faiFolder delete];
|
|
||||||
|
|
||||||
[self cleanupCaches];
|
[self cleanupCaches];
|
||||||
|
|
||||||
|
@ -757,6 +795,19 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||||
|
withNewName: (NSString *) newFolderName
|
||||||
|
{
|
||||||
|
return MAPISTORE_ERR_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (enum mapistore_error) copyToFolder: (MAPIStoreFolder *) targetFolder
|
||||||
|
recursive: (BOOL) resursive
|
||||||
|
withNewName: (NSString *) newFolderName
|
||||||
|
{
|
||||||
|
return MAPISTORE_ERR_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
- (SOGoFolder *) aclFolder
|
- (SOGoFolder *) aclFolder
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
|
@ -1004,7 +1055,11 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
/* TODO: this should no longer be required once mapistore v2 API is in
|
/* TODO: this should no longer be required once mapistore v2 API is in
|
||||||
place, when we can then do this from -dealloc below */
|
place, when we can then do this from -dealloc below */
|
||||||
|
|
||||||
|
[dbFolder reloadIfNeeded];
|
||||||
|
|
||||||
propsCopy = [newProperties mutableCopy];
|
propsCopy = [newProperties mutableCopy];
|
||||||
|
[propsCopy autorelease];
|
||||||
|
|
||||||
currentProp = bannedProps;
|
currentProp = bannedProps;
|
||||||
while (*currentProp)
|
while (*currentProp)
|
||||||
{
|
{
|
||||||
|
@ -1012,9 +1067,8 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
currentProp++;
|
currentProp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
[propsMessage appendProperties: propsCopy];
|
[properties addEntriesFromDictionary: propsCopy];
|
||||||
[propsMessage save];
|
[dbFolder save];
|
||||||
[propsCopy release];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) messageKeys
|
- (NSArray *) messageKeys
|
||||||
|
@ -1039,9 +1093,10 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier
|
- (NSArray *) faiMessageKeysMatchingQualifier: (EOQualifier *) qualifier
|
||||||
andSortOrderings: (NSArray *) sortOrderings
|
andSortOrderings: (NSArray *) sortOrderings
|
||||||
{
|
{
|
||||||
return [faiFolder
|
return [dbFolder childKeysOfType: MAPIDBObjectTypeFAI
|
||||||
toOneRelationshipKeysMatchingQualifier: qualifier
|
includeDeleted: NO
|
||||||
andSortOrderings: sortOrderings];
|
matchingQualifier: qualifier
|
||||||
|
andSortOrderings: sortOrderings];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) faiMessageKeys
|
- (NSArray *) faiMessageKeys
|
||||||
|
@ -1287,6 +1342,19 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (int) getProperties: (struct mapistore_property_data *) data
|
||||||
|
withTags: (enum MAPITAGS *) tags
|
||||||
|
andCount: (uint16_t) columnCount
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
[dbFolder reloadIfNeeded];
|
||||||
|
|
||||||
|
return [super getProperties: data
|
||||||
|
withTags: tags
|
||||||
|
andCount: columnCount
|
||||||
|
inMemCtx: memCtx];
|
||||||
|
}
|
||||||
|
|
||||||
- (int) getProperty: (void **) data
|
- (int) getProperty: (void **) data
|
||||||
withTag: (enum MAPITAGS) propTag
|
withTag: (enum MAPITAGS) propTag
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
@ -1294,8 +1362,7 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
int rc;
|
int rc;
|
||||||
id value;
|
id value;
|
||||||
|
|
||||||
value = [[propsMessage properties]
|
value = [properties objectForKey: MAPIPropertyKey (propTag)];
|
||||||
objectForKey: MAPIPropertyKey (propTag)];
|
|
||||||
if (value)
|
if (value)
|
||||||
rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
|
rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
|
||||||
else
|
else
|
||||||
|
@ -1307,13 +1374,15 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
- (MAPIStoreMessage *) _createAssociatedMessage
|
- (MAPIStoreMessage *) _createAssociatedMessage
|
||||||
{
|
{
|
||||||
MAPIStoreMessage *newMessage;
|
MAPIStoreMessage *newMessage;
|
||||||
SOGoMAPIFSMessage *fsObject;
|
SOGoMAPIDBMessage *dbObject;
|
||||||
NSString *newKey;
|
NSString *newKey;
|
||||||
|
|
||||||
newKey = [NSString stringWithFormat: @"%@.plist",
|
newKey = [NSString stringWithFormat: @"%@.plist",
|
||||||
[SOGoObject globallyUniqueObjectId]];
|
[SOGoObject globallyUniqueObjectId]];
|
||||||
fsObject = [SOGoMAPIFSMessage objectWithName: newKey inContainer: faiFolder];
|
dbObject = [SOGoMAPIDBMessage objectWithName: newKey inContainer: dbFolder];
|
||||||
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: fsObject
|
[dbObject setObjectType: MAPIDBObjectTypeFAI];
|
||||||
|
[dbObject setIsNew: YES];
|
||||||
|
newMessage = [MAPIStoreFAIMessageK mapiStoreObjectWithSOGoObject: dbObject
|
||||||
inContainer: self];
|
inContainer: self];
|
||||||
|
|
||||||
return newMessage;
|
return newMessage;
|
||||||
|
@ -1328,9 +1397,15 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
newMessage = [self _createAssociatedMessage];
|
newMessage = [self _createAssociatedMessage];
|
||||||
else
|
else
|
||||||
newMessage = [self createMessage];
|
newMessage = [self createMessage];
|
||||||
[newMessage setIsNew: YES];
|
/* FIXME: this is ugly as the specifics of message creation should all be
|
||||||
|
delegated to subclasses */
|
||||||
|
if ([newMessage respondsToSelector: @selector (setIsNew:)])
|
||||||
|
[newMessage setIsNew: YES];
|
||||||
woContext = [[self userContext] woContext];
|
woContext = [[self userContext] woContext];
|
||||||
[[newMessage sogoObject] setContext: woContext];
|
/* FIXME: this is ugly too as the specifics of message creation should all
|
||||||
|
be delegated to subclasses */
|
||||||
|
if ([newMessage respondsToSelector: @selector (sogoObject:)])
|
||||||
|
[[newMessage sogoObject] setContext: woContext];
|
||||||
|
|
||||||
return newMessage;
|
return newMessage;
|
||||||
}
|
}
|
||||||
|
@ -1581,9 +1656,14 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
- (uint64_t) objectId
|
- (uint64_t) objectId
|
||||||
{
|
{
|
||||||
uint64_t objectId;
|
uint64_t objectId;
|
||||||
|
NSString *folderKey;
|
||||||
|
|
||||||
if (container)
|
if (container)
|
||||||
objectId = [super objectId];
|
{
|
||||||
|
folderKey = [NSString stringWithFormat: @"%@/",
|
||||||
|
[sogoObject nameInContainer]];
|
||||||
|
objectId = [container idForObjectWithKey: folderKey];
|
||||||
|
}
|
||||||
else
|
else
|
||||||
objectId = [self idForObjectWithKey: nil];
|
objectId = [self idForObjectWithKey: nil];
|
||||||
|
|
||||||
|
@ -1598,12 +1678,12 @@ Class NSExceptionK, MAPIStoreFAIMessageK, MAPIStoreMessageTableK, MAPIStoreFAIMe
|
||||||
|
|
||||||
- (NSDate *) creationTime
|
- (NSDate *) creationTime
|
||||||
{
|
{
|
||||||
return [propsMessage creationTime];
|
return [dbFolder creationDate];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDate *) lastModificationTime
|
- (NSDate *) lastModificationTime
|
||||||
{
|
{
|
||||||
return [propsMessage lastModificationTime];
|
return [dbFolder lastModified];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* subclasses */
|
/* subclasses */
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
@interface MAPIStoreGCSFolder : MAPIStoreFolder
|
@interface MAPIStoreGCSFolder : MAPIStoreFolder
|
||||||
{
|
{
|
||||||
SOGoMAPIFSMessage *versionsMessage;
|
SOGoMAPIDBMessage *versionsMessage;
|
||||||
NSArray *activeUserRoles;
|
NSArray *activeUserRoles;
|
||||||
EOQualifier *componentQualifier;
|
EOQualifier *componentQualifier;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
#import "NSData+MAPIStore.h"
|
#import "NSData+MAPIStore.h"
|
||||||
#import "NSDate+MAPIStore.h"
|
#import "NSDate+MAPIStore.h"
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
#import "SOGoMAPIFSMessage.h"
|
#import "SOGoMAPIDBMessage.h"
|
||||||
|
|
||||||
#import "MAPIStoreGCSFolder.h"
|
#import "MAPIStoreGCSFolder.h"
|
||||||
|
|
||||||
|
@ -71,8 +71,9 @@ static Class NSNumberK;
|
||||||
- (void) setupVersionsMessage
|
- (void) setupVersionsMessage
|
||||||
{
|
{
|
||||||
ASSIGN (versionsMessage,
|
ASSIGN (versionsMessage,
|
||||||
[SOGoMAPIFSMessage objectWithName: @"versions.plist"
|
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
|
||||||
inContainer: propsFolder]);
|
inContainer: dbFolder]);
|
||||||
|
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
|
@ -288,7 +289,8 @@ static Class NSNumberK;
|
||||||
forKey: @"PredecessorChangeList"];
|
forKey: @"PredecessorChangeList"];
|
||||||
[changeList release];
|
[changeList release];
|
||||||
}
|
}
|
||||||
[changeList setObject: globCnt forKey: guid];
|
[changeList setObject: globCnt
|
||||||
|
forKey: guid];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (EOQualifier *) componentQualifier
|
- (EOQualifier *) componentQualifier
|
||||||
|
@ -349,6 +351,7 @@ static Class NSNumberK;
|
||||||
[sortOrdering retain];
|
[sortOrdering retain];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[versionsMessage reloadIfNeeded];
|
||||||
currentProperties = [versionsMessage properties];
|
currentProperties = [versionsMessage properties];
|
||||||
|
|
||||||
lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"];
|
lastModificationDate = [currentProperties objectForKey: @"SyncLastModificationDate"];
|
||||||
|
@ -451,7 +454,6 @@ static Class NSNumberK;
|
||||||
forKey: @"SyncLastSynchronisationDate"];
|
forKey: @"SyncLastSynchronisationDate"];
|
||||||
[currentProperties setObject: lastModificationDate
|
[currentProperties setObject: lastModificationDate
|
||||||
forKey: @"SyncLastModificationDate"];
|
forKey: @"SyncLastModificationDate"];
|
||||||
[versionsMessage appendProperties: currentProperties];
|
|
||||||
[versionsMessage save];
|
[versionsMessage save];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,11 @@
|
||||||
@interface MAPIStoreMailAttachment : MAPIStoreAttachment
|
@interface MAPIStoreMailAttachment : MAPIStoreAttachment
|
||||||
{
|
{
|
||||||
NSDictionary *bodyInfo;
|
NSDictionary *bodyInfo;
|
||||||
|
SOGoMailBodyPart *bodyPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setBodyInfo: (NSDictionary *) newBodyInfo;
|
- (void) setBodyInfo: (NSDictionary *) newBodyInfo;
|
||||||
|
- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
if ((self = [super init]))
|
if ((self = [super init]))
|
||||||
{
|
{
|
||||||
bodyInfo = nil;
|
bodyInfo = nil;
|
||||||
|
bodyPart = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -60,6 +61,7 @@
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
[bodyInfo release];
|
[bodyInfo release];
|
||||||
|
[bodyPart release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +70,11 @@
|
||||||
ASSIGN (bodyInfo, newBodyInfo);
|
ASSIGN (bodyInfo, newBodyInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setBodyPart: (SOGoMailBodyPart *) newBodyPart
|
||||||
|
{
|
||||||
|
ASSIGN (bodyPart, newBodyPart);
|
||||||
|
}
|
||||||
|
|
||||||
- (int) getPidTagAttachMethod: (void **) data
|
- (int) getPidTagAttachMethod: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
|
@ -187,7 +194,7 @@
|
||||||
- (int) getPidTagAttachDataBinary: (void **) data
|
- (int) getPidTagAttachDataBinary: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
*data = [[sogoObject fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx];
|
*data = [[bodyPart fetchBLOBWithPeek: YES] asBinaryInMemCtx: memCtx];
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
@interface MAPIStoreMailFolder : MAPIStoreFolder
|
@interface MAPIStoreMailFolder : MAPIStoreFolder
|
||||||
{
|
{
|
||||||
SOGoMAPIFSMessage *versionsMessage;
|
SOGoMAPIDBMessage *versionsMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) ensureFolderExists;
|
- (BOOL) ensureFolderExists;
|
||||||
|
|
|
@ -54,14 +54,14 @@
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
#import "NSData+MAPIStore.h"
|
#import "NSData+MAPIStore.h"
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
#import "SOGoMAPIFSMessage.h"
|
#import "SOGoMAPIDBMessage.h"
|
||||||
|
#import "SOGoMAPIDBFolder.h"
|
||||||
|
|
||||||
#import "SOGoMAPIVolatileMessage.h"
|
|
||||||
#import "MAPIStoreMailVolatileMessage.h"
|
#import "MAPIStoreMailVolatileMessage.h"
|
||||||
|
|
||||||
#import "MAPIStoreMailFolder.h"
|
#import "MAPIStoreMailFolder.h"
|
||||||
|
|
||||||
static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
|
static Class SOGoMailFolderK, MAPIStoreMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <util/attr.h>
|
#include <util/attr.h>
|
||||||
|
@ -74,6 +74,7 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
+ (void) initialize
|
+ (void) initialize
|
||||||
{
|
{
|
||||||
SOGoMailFolderK = [SOGoMailFolder class];
|
SOGoMailFolderK = [SOGoMailFolder class];
|
||||||
|
MAPIStoreMailFolderK = [MAPIStoreMailFolder class];
|
||||||
MAPIStoreOutboxFolderK = [MAPIStoreOutboxFolder class];
|
MAPIStoreOutboxFolderK = [MAPIStoreOutboxFolder class];
|
||||||
[MAPIStoreAppointmentWrapper class];
|
[MAPIStoreAppointmentWrapper class];
|
||||||
}
|
}
|
||||||
|
@ -97,8 +98,9 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
- (void) setupVersionsMessage
|
- (void) setupVersionsMessage
|
||||||
{
|
{
|
||||||
ASSIGN (versionsMessage,
|
ASSIGN (versionsMessage,
|
||||||
[SOGoMAPIFSMessage objectWithName: @"versions.plist"
|
[SOGoMAPIDBMessage objectWithName: @"versions.plist"
|
||||||
inContainer: propsFolder]);
|
inContainer: dbFolder]);
|
||||||
|
[versionsMessage setObjectType: MAPIDBObjectTypeInternal];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) ensureFolderExists
|
- (BOOL) ensureFolderExists
|
||||||
|
@ -119,6 +121,9 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
&& ![[(SOGoMailFolder *) sogoObject displayName]
|
&& ![[(SOGoMailFolder *) sogoObject displayName]
|
||||||
isEqualToString: newDisplayName])
|
isEqualToString: newDisplayName])
|
||||||
{
|
{
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"renaming a mail folder via OpenChange is"
|
||||||
|
@" currently a bad idea"];
|
||||||
[(SOGoMailFolder *) sogoObject renameTo: newDisplayName];
|
[(SOGoMailFolder *) sogoObject renameTo: newDisplayName];
|
||||||
propsCopy = [newProperties mutableCopy];
|
propsCopy = [newProperties mutableCopy];
|
||||||
[propsCopy removeObjectForKey: key];
|
[propsCopy removeObjectForKey: key];
|
||||||
|
@ -393,6 +398,11 @@ static Class SOGoMailFolderK, MAPIStoreOutboxFolderK;
|
||||||
return permissionEntries;
|
return permissionEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) supportsSubFolders
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
/* synchronisation */
|
/* synchronisation */
|
||||||
|
|
||||||
/* Tree:
|
/* Tree:
|
||||||
|
@ -489,10 +499,8 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
||||||
now = [NSCalendarDate date];
|
now = [NSCalendarDate date];
|
||||||
[now setTimeZone: utcTZ];
|
[now setTimeZone: utcTZ];
|
||||||
|
|
||||||
currentProperties = [[versionsMessage properties] mutableCopy];
|
[versionsMessage reloadIfNeeded];
|
||||||
if (!currentProperties)
|
currentProperties = [versionsMessage properties];
|
||||||
currentProperties = [NSMutableDictionary new];
|
|
||||||
[currentProperties autorelease];
|
|
||||||
messages = [currentProperties objectForKey: @"Messages"];
|
messages = [currentProperties objectForKey: @"Messages"];
|
||||||
if (!messages)
|
if (!messages)
|
||||||
{
|
{
|
||||||
|
@ -613,7 +621,6 @@ _compareFetchResultsByMODSEQ (id entry1, id entry2, void *data)
|
||||||
ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]];
|
ti = [NSNumber numberWithDouble: [now timeIntervalSince1970]];
|
||||||
[currentProperties setObject: ti
|
[currentProperties setObject: ti
|
||||||
forKey: @"SyncLastSynchronisationDate"];
|
forKey: @"SyncLastSynchronisationDate"];
|
||||||
[versionsMessage appendProperties: currentProperties];
|
|
||||||
[versionsMessage save];
|
[versionsMessage save];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,21 +1009,65 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MAPIStoreMessage *) createMessage
|
- (enum mapistore_error) moveToFolder: (MAPIStoreFolder *) targetFolder
|
||||||
|
withNewName: (NSString *) newFolderName
|
||||||
{
|
{
|
||||||
MAPIStoreMailVolatileMessage *newMessage;
|
enum mapistore_error rc;
|
||||||
SOGoMAPIVolatileMessage *newObject;
|
NSURL *folderURL, *newFolderURL;
|
||||||
|
SOGoMailFolder *targetSOGoFolder;
|
||||||
|
NSString *newURL, *parentDBFolderPath;
|
||||||
|
NSException *error;
|
||||||
|
MAPIStoreMapping *mapping;
|
||||||
|
|
||||||
newObject = [SOGoMAPIVolatileMessage
|
if ([targetFolder isKindOfClass: MAPIStoreMailFolderK])
|
||||||
objectWithName: [SOGoObject globallyUniqueObjectId]
|
{
|
||||||
inContainer: sogoObject];
|
folderURL = [sogoObject imap4URL];
|
||||||
newMessage
|
if (!newFolderName)
|
||||||
= [MAPIStoreMailVolatileMessage mapiStoreObjectWithSOGoObject: newObject
|
newFolderName = [[sogoObject nameInContainer]
|
||||||
inContainer: self];
|
substringFromIndex: 6]; /* length of "folder" */
|
||||||
|
newFolderName = [newFolderName stringByEscapingURL];
|
||||||
|
targetSOGoFolder = [targetFolder sogoObject];
|
||||||
|
newFolderURL = [NSURL URLWithString: newFolderName
|
||||||
|
relativeToURL: [targetSOGoFolder imap4URL]];
|
||||||
|
error = [[sogoObject imap4Connection]
|
||||||
|
moveMailboxAtURL: folderURL
|
||||||
|
toURL: newFolderURL];
|
||||||
|
if (error)
|
||||||
|
rc = MAPISTORE_ERR_DENIED;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = MAPISTORE_SUCCESS;
|
||||||
|
mapping = [self mapping];
|
||||||
|
newURL = [NSString stringWithFormat: @"%@folder%@/",
|
||||||
|
[targetFolder url], newFolderName];
|
||||||
|
[mapping updateID: [self objectId]
|
||||||
|
withURL: newURL];
|
||||||
|
parentDBFolderPath = [[targetFolder dbFolder] path];
|
||||||
|
if (!parentDBFolderPath)
|
||||||
|
parentDBFolderPath = @"";
|
||||||
|
[dbFolder changePathTo: [NSString stringWithFormat:
|
||||||
|
@"%@/folder%@",
|
||||||
|
parentDBFolderPath,
|
||||||
|
newFolderName]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
rc = MAPISTORE_ERR_DENIED;
|
||||||
|
|
||||||
return newMessage;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (MAPIStoreMessage *) createMessage
|
||||||
|
{
|
||||||
|
SOGoMAPIObject *childObject;
|
||||||
|
|
||||||
|
childObject = [SOGoMAPIObject objectWithName: [SOGoMAPIObject
|
||||||
|
globallyUniqueObjectId]
|
||||||
|
inContainer: sogoObject];
|
||||||
|
return [MAPIStoreMailVolatileMessage
|
||||||
|
mapiStoreObjectWithSOGoObject: childObject
|
||||||
|
inContainer: self];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
|
- (NSArray *) rolesForExchangeRights: (uint32_t) rights
|
||||||
{
|
{
|
||||||
|
@ -1043,8 +1094,6 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
||||||
[roles addObject: SOGoRole_ObjectViewer];
|
[roles addObject: SOGoRole_ObjectViewer];
|
||||||
if (rights & RightsCreateSubfolders)
|
if (rights & RightsCreateSubfolders)
|
||||||
[roles addObject: SOGoRole_FolderCreator];
|
[roles addObject: SOGoRole_FolderCreator];
|
||||||
if (rights & RightsCreateSubfolders)
|
|
||||||
[roles addObject: SOGoRole_FolderCreator];
|
|
||||||
|
|
||||||
// [self logWithFormat: @"roles for rights %.8x = (%@)", rights, roles];
|
// [self logWithFormat: @"roles for rights %.8x = (%@)", rights, roles];
|
||||||
|
|
||||||
|
@ -1069,8 +1118,6 @@ _parseCOPYUID (NSString *line, NSArray **destUIDsP)
|
||||||
rights |= RightsReadItems;
|
rights |= RightsReadItems;
|
||||||
if ([roles containsObject: SOGoRole_FolderCreator])
|
if ([roles containsObject: SOGoRole_FolderCreator])
|
||||||
rights |= RightsCreateSubfolders;
|
rights |= RightsCreateSubfolders;
|
||||||
if ([roles containsObject: SOGoRole_FolderCreator])
|
|
||||||
rights |= RightsCreateSubfolders;
|
|
||||||
|
|
||||||
if (rights != 0)
|
if (rights != 0)
|
||||||
rights |= RoleNone; /* actually "folder visible" */
|
rights |= RoleNone; /* actually "folder visible" */
|
||||||
|
|
|
@ -373,7 +373,7 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
if (uid)
|
if (uid)
|
||||||
{
|
{
|
||||||
changeNumber = [(MAPIStoreMailFolder *) container
|
changeNumber = [(MAPIStoreMailFolder *) container
|
||||||
changeNumberForMessageUID: uid];
|
changeNumberForMessageUID: uid];
|
||||||
if (!changeNumber)
|
if (!changeNumber)
|
||||||
{
|
{
|
||||||
[self warnWithFormat: @"attempting to get change number"
|
[self warnWithFormat: @"attempting to get change number"
|
||||||
|
@ -448,19 +448,6 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
return MAPISTORE_SUCCESS;
|
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
|
- (int) getPidTagSubjectPrefix: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
|
@ -1529,8 +1516,8 @@ _compareBodyKeysByPriority (id entry1, id entry2, void *data)
|
||||||
if (currentPart)
|
if (currentPart)
|
||||||
{
|
{
|
||||||
attachment = [MAPIStoreMailAttachment
|
attachment = [MAPIStoreMailAttachment
|
||||||
mapiStoreObjectWithSOGoObject: currentPart
|
mapiStoreObjectInContainer: self];
|
||||||
inContainer: self];
|
[attachment setBodyPart: currentPart];
|
||||||
[attachment setBodyInfo: [attachmentParts objectForKey: childKey]];
|
[attachment setBodyInfo: [attachmentParts objectForKey: childKey]];
|
||||||
[attachment setAID: [[self attachmentKeys] indexOfObject: childKey]];
|
[attachment setAID: [[self attachmentKeys] indexOfObject: childKey]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,7 +332,7 @@ static Class MAPIStoreMailMessageK, NSDataK, NSStringK;
|
||||||
if (!fetchedCoreInfos)
|
if (!fetchedCoreInfos)
|
||||||
{
|
{
|
||||||
fetchedCoreInfos = YES;
|
fetchedCoreInfos = YES;
|
||||||
[(SOGoMailFolder *) [container sogoObject]
|
[(SOGoMailFolder *) [(MAPIStoreMailFolder *) container sogoObject]
|
||||||
prefetchCoreInfosForMessageKeys: [self restrictedChildKeys]];
|
prefetchCoreInfosForMessageKeys: [self restrictedChildKeys]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#ifndef MAPISTOREMAILVOLATILEMESSAGE_H
|
#ifndef MAPISTOREMAILVOLATILEMESSAGE_H
|
||||||
#define MAPISTOREMAILVOLATILEMESSAGE_H
|
#define MAPISTOREMAILVOLATILEMESSAGE_H
|
||||||
|
|
||||||
#import "MAPIStoreVolatileMessage.h"
|
#import "MAPIStoreMessage.h"
|
||||||
|
|
||||||
@interface MAPIStoreMailVolatileMessage : MAPIStoreVolatileMessage
|
@interface MAPIStoreMailVolatileMessage : MAPIStoreMessage
|
||||||
|
|
||||||
- (int) submitWithFlags: (enum SubmitFlags) flags;
|
- (int) submitWithFlags: (enum SubmitFlags) flags;
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#import <Mailer/NSString+Mail.h>
|
#import <Mailer/NSString+Mail.h>
|
||||||
|
|
||||||
#import "MAPIStoreAttachment.h"
|
#import "MAPIStoreAttachment.h"
|
||||||
|
#import "MAPIStoreAttachmentTable.h"
|
||||||
#import "MAPIStoreContext.h"
|
#import "MAPIStoreContext.h"
|
||||||
#import "MAPIStoreMailFolder.h"
|
#import "MAPIStoreMailFolder.h"
|
||||||
#import "MAPIStoreMIME.h"
|
#import "MAPIStoreMIME.h"
|
||||||
|
@ -60,7 +61,7 @@
|
||||||
#import "NSData+MAPIStore.h"
|
#import "NSData+MAPIStore.h"
|
||||||
#import "NSObject+MAPIStore.h"
|
#import "NSObject+MAPIStore.h"
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
#import "SOGoMAPIVolatileMessage.h"
|
#import "SOGoMAPIObject.h"
|
||||||
|
|
||||||
#import "MAPIStoreMailVolatileMessage.h"
|
#import "MAPIStoreMailVolatileMessage.h"
|
||||||
|
|
||||||
|
@ -68,6 +69,8 @@
|
||||||
#include <mapistore/mapistore.h>
|
#include <mapistore/mapistore.h>
|
||||||
#include <mapistore/mapistore_errors.h>
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
|
static Class NSNumberK = Nil;
|
||||||
|
|
||||||
static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -242,6 +245,85 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
||||||
|
|
||||||
@implementation MAPIStoreMailVolatileMessage
|
@implementation MAPIStoreMailVolatileMessage
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
NSNumberK = [NSNumber class];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithSOGoObject: (id) newSOGoObject
|
||||||
|
inContainer: (MAPIStoreObject *) newContainer
|
||||||
|
{
|
||||||
|
if ((self = [super initWithSOGoObject: newSOGoObject
|
||||||
|
inContainer: newContainer]))
|
||||||
|
{
|
||||||
|
ASSIGN (properties, [sogoObject properties]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) addProperties: (NSDictionary *) newProperties
|
||||||
|
{
|
||||||
|
[super addProperties: newProperties];
|
||||||
|
[sogoObject adjustLastModified];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
|
||||||
|
{
|
||||||
|
return ([super canGetProperty: propTag]
|
||||||
|
|| [properties objectForKey: MAPIPropertyKey (propTag)] != nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (uint64_t) objectVersion
|
||||||
|
{
|
||||||
|
NSNumber *version;
|
||||||
|
|
||||||
|
version = [properties objectForKey: @"version"];
|
||||||
|
|
||||||
|
return (version
|
||||||
|
? exchange_globcnt ([version unsignedLongLongValue])
|
||||||
|
: ULLONG_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) 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
|
- (void) getMessageData: (struct mapistore_message **) dataPtr
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
|
@ -258,9 +340,11 @@ static NSString *recTypes[] = { @"orig", @"to", @"cc", @"bcc" };
|
||||||
|
|
||||||
samCtx = [[self context] connectionInfo]->sam_ctx;
|
samCtx = [[self context] connectionInfo]->sam_ctx;
|
||||||
|
|
||||||
[super getMessageData: &msgData inMemCtx: memCtx];
|
// [super getMessageData: &msgData inMemCtx: memCtx];
|
||||||
|
|
||||||
allRecipients = [[sogoObject properties] objectForKey: @"recipients"];
|
msgData = talloc_zero (memCtx, struct mapistore_message);
|
||||||
|
|
||||||
|
allRecipients = [properties objectForKey: @"recipients"];
|
||||||
msgData->columns = set_SPropTagArray (msgData, 9,
|
msgData->columns = set_SPropTagArray (msgData, 9,
|
||||||
PR_OBJECT_TYPE,
|
PR_OBJECT_TYPE,
|
||||||
PR_DISPLAY_TYPE,
|
PR_DISPLAY_TYPE,
|
||||||
|
@ -660,9 +744,11 @@ MakeTextPartBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
return textBody;
|
return textBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static id
|
||||||
|
// MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
|
// NSString **contentType)
|
||||||
static id
|
static id
|
||||||
MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts, NSString **contentType)
|
||||||
NSString **contentType)
|
|
||||||
{
|
{
|
||||||
id messageBody, textBody;
|
id messageBody, textBody;
|
||||||
NSString *textContentType;
|
NSString *textContentType;
|
||||||
|
@ -707,22 +793,19 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
|
|
||||||
- (NGMimeMessage *) _generateMessage
|
- (NGMimeMessage *) _generateMessage
|
||||||
{
|
{
|
||||||
NSDictionary *mailProperties;
|
|
||||||
NSString *contentType;
|
NSString *contentType;
|
||||||
NGMimeMessage *message;
|
NGMimeMessage *message;
|
||||||
NGMutableHashMap *headers;
|
NGMutableHashMap *headers;
|
||||||
id messageBody;
|
id messageBody;
|
||||||
|
|
||||||
mailProperties = [sogoObject properties];
|
|
||||||
|
|
||||||
headers = [[NGMutableHashMap alloc] initWithCapacity: 16];
|
headers = [[NGMutableHashMap alloc] initWithCapacity: 16];
|
||||||
FillMessageHeadersFromProperties (headers, mailProperties,
|
FillMessageHeadersFromProperties (headers, properties,
|
||||||
[[self context] connectionInfo]);
|
[[self context] connectionInfo]);
|
||||||
message = [[NGMimeMessage alloc] initWithHeader: headers];
|
message = [[NGMimeMessage alloc] initWithHeader: headers];
|
||||||
[message autorelease];
|
[message autorelease];
|
||||||
[headers release];
|
[headers release];
|
||||||
|
|
||||||
messageBody = MakeMessageBody (mailProperties, attachmentParts, &contentType);
|
messageBody = MakeMessageBody (properties, attachmentParts, &contentType);
|
||||||
if (messageBody)
|
if (messageBody)
|
||||||
{
|
{
|
||||||
[headers setObject: contentType forKey: @"content-type"];
|
[headers setObject: contentType forKey: @"content-type"];
|
||||||
|
@ -775,7 +858,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
|
|
||||||
- (int) submitWithFlags: (enum SubmitFlags) flags
|
- (int) submitWithFlags: (enum SubmitFlags) flags
|
||||||
{
|
{
|
||||||
NSDictionary *mailProperties, *recipients;
|
NSDictionary *recipients;
|
||||||
NSData *messageData;
|
NSData *messageData;
|
||||||
NSMutableArray *recipientEmails;
|
NSMutableArray *recipientEmails;
|
||||||
NSArray *list;
|
NSArray *list;
|
||||||
|
@ -785,19 +868,17 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
// SOGoMailFolder *sentFolder;
|
// SOGoMailFolder *sentFolder;
|
||||||
SOGoDomainDefaults *dd;
|
SOGoDomainDefaults *dd;
|
||||||
NSException *error;
|
NSException *error;
|
||||||
MAPIStoreMapping *mapping;
|
// MAPIStoreMapping *mapping;
|
||||||
|
|
||||||
mailProperties = [sogoObject properties];
|
msgClass = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
|
||||||
msgClass = [mailProperties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
|
|
||||||
if ([msgClass isEqualToString: @"IPM.Note"]) /* we skip invitation replies */
|
if ([msgClass isEqualToString: @"IPM.Note"]) /* we skip invitation replies */
|
||||||
{
|
{
|
||||||
/* send mail */
|
/* send mail */
|
||||||
|
|
||||||
messageData = [self _generateMailDataWithBcc: NO];
|
messageData = [self _generateMailDataWithBcc: NO];
|
||||||
|
|
||||||
mailProperties = [sogoObject properties];
|
|
||||||
recipientEmails = [NSMutableArray arrayWithCapacity: 32];
|
recipientEmails = [NSMutableArray arrayWithCapacity: 32];
|
||||||
recipients = [mailProperties objectForKey: @"recipients"];
|
recipients = [properties objectForKey: @"recipients"];
|
||||||
for (count = 0; count < 3; count++)
|
for (count = 0; count < 3; count++)
|
||||||
{
|
{
|
||||||
recId = recTypes[count];
|
recId = recTypes[count];
|
||||||
|
@ -819,11 +900,11 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
if (error)
|
if (error)
|
||||||
[self logWithFormat: @"an error occurred: '%@'", error];
|
[self logWithFormat: @"an error occurred: '%@'", error];
|
||||||
|
|
||||||
mapping = [self mapping];
|
// mapping = [self mapping];
|
||||||
[mapping unregisterURLWithID: [self objectId]];
|
// [mapping unregisterURLWithID: [self objectId]];
|
||||||
[self setIsNew: NO];
|
// [self setIsNew: NO];
|
||||||
[properties removeAllObjects];
|
// [properties removeAllObjects];
|
||||||
[[self container] cleanupCaches];
|
[(MAPIStoreMailFolder *) [self container] cleanupCaches];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[self logWithFormat: @"skipping submit of message with class '%@'",
|
[self logWithFormat: @"skipping submit of message with class '%@'",
|
||||||
|
@ -834,7 +915,7 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
|
|
||||||
- (void) save
|
- (void) save
|
||||||
{
|
{
|
||||||
NSString *folderName, *flag, *newIdString;
|
NSString *folderName, *flag, *newIdString, *messageKey;
|
||||||
NSData *changeKey, *messageData;
|
NSData *changeKey, *messageData;
|
||||||
NGImap4Connection *connection;
|
NGImap4Connection *connection;
|
||||||
NGImap4Client *client;
|
NGImap4Client *client;
|
||||||
|
@ -858,23 +939,27 @@ MakeMessageBody (NSDictionary *mailProperties, NSDictionary *attachmentParts,
|
||||||
responseResult = [[result objectForKey: @"RawResponse"]
|
responseResult = [[result objectForKey: @"RawResponse"]
|
||||||
objectForKey: @"ResponseResult"];
|
objectForKey: @"ResponseResult"];
|
||||||
flag = [responseResult objectForKey: @"flag"];
|
flag = [responseResult objectForKey: @"flag"];
|
||||||
|
|
||||||
newIdString = [[flag componentsSeparatedByString: @" "]
|
newIdString = [[flag componentsSeparatedByString: @" "]
|
||||||
objectAtIndex: 2];
|
objectAtIndex: 2];
|
||||||
mid = [self objectId];
|
|
||||||
mapping = [self mapping];
|
mapping = [self mapping];
|
||||||
|
mid = [self objectId];
|
||||||
[mapping unregisterURLWithID: mid];
|
[mapping unregisterURLWithID: mid];
|
||||||
[sogoObject setNameInContainer: [NSString stringWithFormat: @"%@.eml", newIdString]];
|
// [sogoObject setNameInContainer: ];
|
||||||
[mapping registerURL: [self url] withID: mid];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* synchronise the cache and update the change key with the one provided by
|
messageKey = [NSString stringWithFormat: @"%@.eml", newIdString];
|
||||||
the client */
|
[sogoObject setNameInContainer: messageKey];
|
||||||
[(MAPIStoreMailFolder *) container synchroniseCache];
|
[mapping registerURL: [self url] withID: mid];
|
||||||
changeKey = [[sogoObject properties]
|
|
||||||
objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
|
/* synchronise the cache and update the change key with the one provided
|
||||||
if (changeKey)
|
by the client */
|
||||||
[(MAPIStoreMailFolder *) container
|
[(MAPIStoreMailFolder *) container synchroniseCache];
|
||||||
setChangeKey: changeKey forMessageWithKey: [self nameInContainer]];
|
changeKey = [properties objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
|
||||||
|
if (changeKey)
|
||||||
|
[(MAPIStoreMailFolder *) container
|
||||||
|
setChangeKey: changeKey
|
||||||
|
forMessageWithKey: messageKey];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -54,6 +54,8 @@
|
||||||
- (BOOL) registerURL: (NSString *) urlString
|
- (BOOL) registerURL: (NSString *) urlString
|
||||||
withID: (uint64_t) idNbr;
|
withID: (uint64_t) idNbr;
|
||||||
- (void) unregisterURLWithID: (uint64_t) idNbr;
|
- (void) unregisterURLWithID: (uint64_t) idNbr;
|
||||||
|
- (void) updateID: (uint64_t) idNbr
|
||||||
|
withURL: (NSString *) urlString;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
|
#import <SOGo/NSString+Utilities.h>
|
||||||
|
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
|
|
||||||
#import "MAPIStoreMapping.h"
|
#import "MAPIStoreMapping.h"
|
||||||
|
@ -204,6 +206,87 @@ MAPIStoreMappingTDBTraverse (TDB_CONTEXT *ctx, TDB_DATA data1, TDB_DATA data2,
|
||||||
return idNbr;
|
return idNbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) _updateFolderWithURL: (NSString *) oldURL
|
||||||
|
withURL: (NSString *) urlString
|
||||||
|
{
|
||||||
|
NSArray *allKeys;
|
||||||
|
NSUInteger count, max;
|
||||||
|
NSString *currentKey, *newKey;
|
||||||
|
NSNumber *idKey;
|
||||||
|
TDB_DATA key, dbuf;
|
||||||
|
|
||||||
|
allKeys = [reverseMapping allKeys];
|
||||||
|
max = [allKeys count];
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
currentKey = [allKeys objectAtIndex: count];
|
||||||
|
if ([currentKey hasPrefix: oldURL])
|
||||||
|
{
|
||||||
|
newKey = [currentKey stringByReplacingPrefix: oldURL
|
||||||
|
withPrefix: urlString];
|
||||||
|
|
||||||
|
idKey = [reverseMapping objectForKey: currentKey];
|
||||||
|
[mapping setObject: newKey forKey: idKey];
|
||||||
|
[reverseMapping setObject: idKey forKey: newKey];
|
||||||
|
[reverseMapping removeObjectForKey: currentKey];
|
||||||
|
|
||||||
|
/* update the record in the indexing database */
|
||||||
|
key.dptr = (unsigned char *) talloc_asprintf (NULL, "0x%.16"PRIx64,
|
||||||
|
(uint64_t) [idKey unsignedLongLongValue]);
|
||||||
|
key.dsize = strlen ((const char *) key.dptr);
|
||||||
|
|
||||||
|
dbuf.dptr = (unsigned char *) talloc_strdup (NULL,
|
||||||
|
[newKey UTF8String]);
|
||||||
|
dbuf.dsize = strlen ((const char *) dbuf.dptr);
|
||||||
|
tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY);
|
||||||
|
talloc_free (key.dptr);
|
||||||
|
talloc_free (dbuf.dptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) updateID: (uint64_t) idNbr
|
||||||
|
withURL: (NSString *) urlString
|
||||||
|
{
|
||||||
|
NSString *oldURL;
|
||||||
|
NSNumber *idKey;
|
||||||
|
TDB_DATA key, dbuf;
|
||||||
|
|
||||||
|
idKey = [NSNumber numberWithUnsignedLongLong: idNbr];
|
||||||
|
oldURL = [mapping objectForKey: idKey];
|
||||||
|
if (oldURL)
|
||||||
|
{
|
||||||
|
if ([oldURL hasSuffix: @"/"]) /* is container ? */
|
||||||
|
{
|
||||||
|
if (![urlString hasSuffix: @"/"])
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"a container url must have an ending '/'"];
|
||||||
|
tdb_transaction_start (indexing->tdb);
|
||||||
|
[self _updateFolderWithURL: oldURL withURL: urlString];
|
||||||
|
tdb_transaction_commit (indexing->tdb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ([urlString hasSuffix: @"/"])
|
||||||
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
format: @"a leaf url must not have an ending '/'"];
|
||||||
|
[mapping setObject: urlString forKey: idKey];
|
||||||
|
[reverseMapping setObject: idKey forKey: urlString];
|
||||||
|
[reverseMapping removeObjectForKey: oldURL];
|
||||||
|
|
||||||
|
/* update the record in the indexing database */
|
||||||
|
key.dptr = (unsigned char *) talloc_asprintf(NULL, "0x%.16"PRIx64, idNbr);
|
||||||
|
key.dsize = strlen((const char *) key.dptr);
|
||||||
|
|
||||||
|
dbuf.dptr = (unsigned char *) talloc_strdup (NULL, [urlString UTF8String]);
|
||||||
|
dbuf.dsize = strlen((const char *) dbuf.dptr);
|
||||||
|
tdb_store (indexing->tdb, key, dbuf, TDB_MODIFY);
|
||||||
|
talloc_free (key.dptr);
|
||||||
|
talloc_free (dbuf.dptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL) registerURL: (NSString *) urlString
|
- (BOOL) registerURL: (NSString *) urlString
|
||||||
withID: (uint64_t) idNbr
|
withID: (uint64_t) idNbr
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,9 +35,9 @@
|
||||||
@class MAPIStoreAttachmentTable;
|
@class MAPIStoreAttachmentTable;
|
||||||
@class MAPIStoreFolder;
|
@class MAPIStoreFolder;
|
||||||
|
|
||||||
#import "MAPIStoreObject.h"
|
#import "MAPIStoreSOGoObject.h"
|
||||||
|
|
||||||
@interface MAPIStoreMessage : MAPIStoreObject
|
@interface MAPIStoreMessage : MAPIStoreSOGoObject
|
||||||
{
|
{
|
||||||
NSArray *attachmentKeys;
|
NSArray *attachmentKeys;
|
||||||
NSMutableDictionary *attachmentParts;
|
NSMutableDictionary *attachmentParts;
|
||||||
|
@ -66,9 +66,6 @@
|
||||||
- (int) setReadFlag: (uint8_t) flag;
|
- (int) setReadFlag: (uint8_t) flag;
|
||||||
- (enum mapistore_error) saveMessage;
|
- (enum mapistore_error) saveMessage;
|
||||||
|
|
||||||
/* helper getters */
|
|
||||||
- (int) getSMTPAddrType: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
- (NSArray *) activeContainerMessageTables;
|
- (NSArray *) activeContainerMessageTables;
|
||||||
|
|
||||||
- (NSArray *) activeUserRoles;
|
- (NSArray *) activeUserRoles;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#import "MAPIStoreAttachmentTable.h"
|
#import "MAPIStoreAttachmentTable.h"
|
||||||
#import "MAPIStoreContext.h"
|
#import "MAPIStoreContext.h"
|
||||||
#import "MAPIStoreFolder.h"
|
#import "MAPIStoreFolder.h"
|
||||||
|
#import "MAPIStoreMessageTable.h"
|
||||||
#import "MAPIStorePropertySelectors.h"
|
#import "MAPIStorePropertySelectors.h"
|
||||||
#import "MAPIStoreSamDBUtils.h"
|
#import "MAPIStoreSamDBUtils.h"
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
|
@ -55,6 +56,7 @@
|
||||||
#include <mapistore/mapistore_errors.h>
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
static NSString *resourcesDir = nil;
|
static NSString *resourcesDir = nil;
|
||||||
|
static Class MAPIStoreFolderK = nil;
|
||||||
|
|
||||||
/* rtf conversion via unrtf */
|
/* rtf conversion via unrtf */
|
||||||
static int
|
static int
|
||||||
|
@ -116,7 +118,6 @@ rtf2html (NSData *compressedRTF)
|
||||||
|
|
||||||
@interface SOGoObject (MAPIStoreProtocol)
|
@interface SOGoObject (MAPIStoreProtocol)
|
||||||
|
|
||||||
- (NSString *) davEntityTag;
|
|
||||||
- (NSString *) davContentLength;
|
- (NSString *) davContentLength;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -130,6 +131,7 @@ rtf2html (NSData *compressedRTF)
|
||||||
resourcesDir = [[NSBundle bundleForClass: self] resourcePath];
|
resourcesDir = [[NSBundle bundleForClass: self] resourcePath];
|
||||||
[resourcesDir retain];
|
[resourcesDir retain];
|
||||||
}
|
}
|
||||||
|
MAPIStoreFolderK = [MAPIStoreFolder class];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) init
|
- (id) init
|
||||||
|
@ -304,6 +306,7 @@ rtf2html (NSData *compressedRTF)
|
||||||
NSData *htmlData, *rtfData;
|
NSData *htmlData, *rtfData;
|
||||||
static NSNumber *htmlKey = nil, *rtfKey = nil;
|
static NSNumber *htmlKey = nil, *rtfKey = nil;
|
||||||
|
|
||||||
|
/* we intercept any RTF content and convert it to HTML */
|
||||||
[super addProperties: newNewProperties];
|
[super addProperties: newNewProperties];
|
||||||
|
|
||||||
if (!htmlKey)
|
if (!htmlKey)
|
||||||
|
@ -339,10 +342,8 @@ rtf2html (NSData *compressedRTF)
|
||||||
|
|
||||||
newAid = [[self attachmentKeys] count];
|
newAid = [[self attachmentKeys] count];
|
||||||
|
|
||||||
newAttachment = [MAPIStoreAttachment
|
newAttachment = [MAPIStoreAttachment mapiStoreObjectInContainer: self];
|
||||||
mapiStoreObjectWithSOGoObject: nil
|
// [newAttachment setIsNew: YES];
|
||||||
inContainer: self];
|
|
||||||
[newAttachment setIsNew: YES];
|
|
||||||
[newAttachment setAID: newAid];
|
[newAttachment setAID: newAid];
|
||||||
newKey = [NSString stringWithFormat: @"%ul", newAid];
|
newKey = [NSString stringWithFormat: @"%ul", newAid];
|
||||||
[attachmentParts setObject: newAttachment
|
[attachmentParts setObject: newAttachment
|
||||||
|
@ -443,62 +444,73 @@ rtf2html (NSData *compressedRTF)
|
||||||
|| (!isNew && [self subscriberCanModifyMessage])))
|
|| (!isNew && [self subscriberCanModifyMessage])))
|
||||||
{
|
{
|
||||||
/* notifications */
|
/* notifications */
|
||||||
folderId = [(MAPIStoreFolder *) container objectId];
|
if ([container isKindOfClass: MAPIStoreFolderK])
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
notif_parameters->tag_count = 3;
|
folderId = [(MAPIStoreFolder *) container objectId];
|
||||||
notif_parameters->tags = talloc_array (notif_parameters,
|
mstoreCtx = [[self context] connectionInfo]->mstore_ctx;
|
||||||
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);
|
|
||||||
|
|
||||||
/* message created */
|
/* folder modified */
|
||||||
if (isNew)
|
|
||||||
{
|
|
||||||
notif_parameters
|
notif_parameters
|
||||||
= talloc_zero(NULL,
|
= talloc_zero(NULL, struct mapistore_object_notification_parameters);
|
||||||
struct mapistore_object_notification_parameters);
|
notif_parameters->object_id = folderId;
|
||||||
notif_parameters->object_id = [self objectId];
|
if (isNew)
|
||||||
notif_parameters->folder_id = folderId;
|
{
|
||||||
|
notif_parameters->tag_count = 3;
|
||||||
notif_parameters->tag_count = 0xffff;
|
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_push_notification (mstoreCtx,
|
||||||
MAPISTORE_MESSAGE, MAPISTORE_OBJECT_CREATED,
|
MAPISTORE_FOLDER,
|
||||||
|
MAPISTORE_OBJECT_MODIFIED,
|
||||||
notif_parameters);
|
notif_parameters);
|
||||||
talloc_free (notif_parameters);
|
talloc_free (notif_parameters);
|
||||||
|
|
||||||
|
/* 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];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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];
|
[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 */
|
if ([container isKindOfClass: MAPIStoreFolderK])
|
||||||
for (count = 0; count < max; count++)
|
{
|
||||||
[[containerTables objectAtIndex: count]
|
/* table modified */
|
||||||
notifyChangesForChild: self];
|
for (count = 0; count < max; count++)
|
||||||
|
[[containerTables objectAtIndex: count]
|
||||||
|
notifyChangesForChild: self];
|
||||||
|
[container cleanupCaches];
|
||||||
|
}
|
||||||
[self setIsNew: NO];
|
[self setIsNew: NO];
|
||||||
[properties removeAllObjects];
|
|
||||||
[container cleanupCaches];
|
|
||||||
rc = MAPISTORE_SUCCESS;
|
rc = MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -507,14 +519,6 @@ rtf2html (NSData *compressedRTF)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* helper getters */
|
|
||||||
- (int) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
*data = [@"SMTP" asUnicodeInMemCtx: memCtx];
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* getters */
|
/* getters */
|
||||||
- (int) getPidTagInstID: (void **) data // TODO: DOUBT
|
- (int) getPidTagInstID: (void **) data // TODO: DOUBT
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
@ -615,7 +619,8 @@ rtf2html (NSData *compressedRTF)
|
||||||
- (int) getPidLidCurrentVersion: (void **) data
|
- (int) getPidLidCurrentVersion: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
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;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -655,9 +660,19 @@ rtf2html (NSData *compressedRTF)
|
||||||
- (int) getPidTagMid: (void **) data
|
- (int) getPidTagMid: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
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
|
- (int) getPidTagMessageLocaleId: (void **) data
|
||||||
|
@ -708,21 +723,35 @@ rtf2html (NSData *compressedRTF)
|
||||||
- (int) getPidTagSubject: (void **) data
|
- (int) getPidTagSubject: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
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
|
- (int) getPidTagNormalizedSubject: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self getPidTagSubject: data inMemCtx: memCtx];
|
return MAPISTORE_ERR_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagOriginalSubject: (void **) data
|
- (int) getPidTagOriginalSubject: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self getPidTagNormalizedSubject: data inMemCtx: memCtx];
|
return [self getPidTagSubject: data inMemCtx: memCtx];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagConversationTopic: (void **) data
|
- (int) getPidTagConversationTopic: (void **) data
|
||||||
|
@ -792,7 +821,7 @@ rtf2html (NSData *compressedRTF)
|
||||||
- (int) getPidTagOriginalMessageClass: (void **) data
|
- (int) getPidTagOriginalMessageClass: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
return [self getPidTagMessageClass: data inMemCtx: memCtx];
|
return [self getProperty: data withTag: PidTagMessageClass inMemCtx: memCtx];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagHasAttachments: (void **) data
|
- (int) getPidTagHasAttachments: (void **) data
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
@interface MAPIStoreMessageTable : MAPIStoreTable
|
@interface MAPIStoreMessageTable : MAPIStoreTable
|
||||||
|
|
||||||
- (void) setSortOrder: (const struct SSortOrderSet *) set;
|
- (void) setSortOrder: (const struct SSortOrderSet *) set;
|
||||||
|
- (void) notifyChangesForChild: (MAPIStoreMessage *) child;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
#import <SOGo/SOGoFolder.h>
|
#import <SOGo/SOGoFolder.h>
|
||||||
#import <SOGo/SOGoObject.h>
|
#import <SOGo/SOGoObject.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreContext.h"
|
||||||
#import "MAPIStoreFolder.h"
|
#import "MAPIStoreFolder.h"
|
||||||
|
#import "MAPIStoreMessage.h"
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
#import "NSData+MAPIStore.h"
|
#import "NSData+MAPIStore.h"
|
||||||
#import "NSString+MAPIStore.h"
|
#import "NSString+MAPIStore.h"
|
||||||
|
@ -83,4 +85,60 @@
|
||||||
return [(MAPIStoreFolder *) container lookupMessage: childKey];
|
return [(MAPIStoreFolder *) container lookupMessage: childKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) notifyChangesForChild: (MAPIStoreMessage *) child
|
||||||
|
{
|
||||||
|
NSUInteger currentChildRow, newChildRow;
|
||||||
|
NSArray *list;
|
||||||
|
NSString *childName;
|
||||||
|
struct mapistore_table_notification_parameters notif_parameters;
|
||||||
|
struct mapistore_context *mstoreCtx;
|
||||||
|
|
||||||
|
mstoreCtx = [[(MAPIStoreFolder *) container context]
|
||||||
|
connectionInfo]->mstore_ctx;
|
||||||
|
|
||||||
|
notif_parameters.table_type = tableType;
|
||||||
|
notif_parameters.handle = handleId;
|
||||||
|
notif_parameters.folder_id = [(MAPIStoreFolder *) container objectId];
|
||||||
|
notif_parameters.object_id = [child objectId];
|
||||||
|
notif_parameters.instance_id = 0; /* TODO: always 0 ? */
|
||||||
|
|
||||||
|
childName = [child nameInContainer];
|
||||||
|
list = [self restrictedChildKeys];
|
||||||
|
currentChildRow = [list indexOfObject: childName];
|
||||||
|
notif_parameters.row_id = currentChildRow;
|
||||||
|
|
||||||
|
[self cleanupCaches];
|
||||||
|
list = [self restrictedChildKeys];
|
||||||
|
newChildRow = [list indexOfObject: childName];
|
||||||
|
|
||||||
|
if (currentChildRow == NSNotFound)
|
||||||
|
{
|
||||||
|
if (newChildRow != NSNotFound)
|
||||||
|
{
|
||||||
|
notif_parameters.row_id = newChildRow;
|
||||||
|
mapistore_push_notification (mstoreCtx,
|
||||||
|
MAPISTORE_TABLE,
|
||||||
|
MAPISTORE_OBJECT_CREATED,
|
||||||
|
¬if_parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (newChildRow == NSNotFound)
|
||||||
|
mapistore_push_notification (mstoreCtx,
|
||||||
|
MAPISTORE_TABLE,
|
||||||
|
MAPISTORE_OBJECT_DELETED,
|
||||||
|
¬if_parameters);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the fact that the row order has changed has no impact here */
|
||||||
|
notif_parameters.row_id = newChildRow;
|
||||||
|
mapistore_push_notification (mstoreCtx,
|
||||||
|
MAPISTORE_TABLE,
|
||||||
|
MAPISTORE_OBJECT_MODIFIED,
|
||||||
|
¬if_parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#ifndef MAPISTORENOTESCONTEXT_H
|
#ifndef MAPISTORENOTESCONTEXT_H
|
||||||
#define MAPISTORENOTESCONTEXT_H
|
#define MAPISTORENOTESCONTEXT_H
|
||||||
|
|
||||||
#import "MAPIStoreFSBaseContext.h"
|
#import "MAPIStoreDBBaseContext.h"
|
||||||
|
|
||||||
@interface MAPIStoreNotesContext : MAPIStoreFSBaseContext
|
@interface MAPIStoreNotesContext : MAPIStoreDBBaseContext
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#ifndef MAPISTORENOTESFOLDER_H
|
#ifndef MAPISTORENOTESFOLDER_H
|
||||||
#define MAPISTORENOTESFOLDER_H
|
#define MAPISTORENOTESFOLDER_H
|
||||||
|
|
||||||
#import "MAPIStoreFSFolder.h"
|
#import "MAPIStoreDBFolder.h"
|
||||||
|
|
||||||
@interface MAPIStoreNotesFolder : MAPIStoreFSFolder
|
@interface MAPIStoreNotesFolder : MAPIStoreDBFolder
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTORENOTESFOLDER_H */
|
#endif /* MAPISTORENOTESFOLDER_H */
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#ifndef MAPISTORENOTESMESSAGE_H
|
#ifndef MAPISTORENOTESMESSAGE_H
|
||||||
#define MAPISTORENOTESMESSAGE_H
|
#define MAPISTORENOTESMESSAGE_H
|
||||||
|
|
||||||
#import "MAPIStoreFSMessage.h"
|
#import "MAPIStoreDBMessage.h"
|
||||||
|
|
||||||
@interface MAPIStoreNotesMessage : MAPIStoreFSMessage
|
@interface MAPIStoreNotesMessage : MAPIStoreDBMessage
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTORENOTESMESSAGE_H */
|
#endif /* MAPISTORENOTESMESSAGE_H */
|
||||||
|
|
|
@ -53,21 +53,4 @@
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSubject: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
id value;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
value = [[sogoObject properties]
|
|
||||||
objectForKey: MAPIPropertyKey (PidTagNormalizedSubject)];
|
|
||||||
if (value)
|
|
||||||
rc = [value getValue: data forTag: PidTagNormalizedSubject
|
|
||||||
inMemCtx: memCtx];
|
|
||||||
else
|
|
||||||
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -33,60 +33,41 @@
|
||||||
@class NSMutableArray;
|
@class NSMutableArray;
|
||||||
@class NSMutableDictionary;
|
@class NSMutableDictionary;
|
||||||
|
|
||||||
@class EOQualifier;
|
|
||||||
|
|
||||||
@class MAPIStoreContext;
|
@class MAPIStoreContext;
|
||||||
@class MAPIStoreFolder;
|
|
||||||
@class MAPIStoreMapping;
|
@class MAPIStoreMapping;
|
||||||
@class MAPIStoreTable;
|
@class MAPIStoreObjectProxy;
|
||||||
@class MAPIStoreUserContext;
|
@class MAPIStoreUserContext;
|
||||||
|
@class MAPIStoreSOGoObject;
|
||||||
|
|
||||||
@interface MAPIStoreObject : NSObject
|
@interface MAPIStoreObject : NSObject
|
||||||
{
|
{
|
||||||
const IMP *classGetters;
|
const IMP *classGetters;
|
||||||
|
|
||||||
NSMutableArray *parentContainersBag;
|
NSMutableArray *parentContainersBag;
|
||||||
MAPIStoreObject *container;
|
NSMutableArray *proxies;
|
||||||
id sogoObject;
|
id container;
|
||||||
NSMutableDictionary *properties;
|
NSMutableDictionary *properties;
|
||||||
BOOL isNew;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
|
+ (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer;
|
||||||
inContainer: (MAPIStoreObject *) newContainer;
|
- (id) initInContainer: (MAPIStoreObject *) newContainer;
|
||||||
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
|
|
||||||
- (id) initWithSOGoObject: (id) newSOGoObject
|
- (void) addProxy: (MAPIStoreObjectProxy *) newProxy;
|
||||||
inContainer: (MAPIStoreObject *) newFolder;
|
|
||||||
|
|
||||||
- (void) setIsNew: (BOOL) newIsNew;
|
|
||||||
- (BOOL) isNew;
|
|
||||||
|
|
||||||
- (NSString *) nameInContainer;
|
|
||||||
|
|
||||||
- (id) sogoObject;
|
|
||||||
- (MAPIStoreObject *) container;
|
- (MAPIStoreObject *) container;
|
||||||
|
|
||||||
- (MAPIStoreContext *) context;
|
- (MAPIStoreContext *) context;
|
||||||
- (MAPIStoreUserContext *) userContext;
|
- (MAPIStoreUserContext *) userContext;
|
||||||
- (MAPIStoreMapping *) mapping;
|
- (MAPIStoreMapping *) mapping;
|
||||||
|
|
||||||
- (void) cleanupCaches;
|
|
||||||
|
|
||||||
- (uint64_t) objectId;
|
|
||||||
- (NSString *) url;
|
- (NSString *) url;
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
|
|
||||||
- (BOOL) canGetProperty: (enum MAPITAGS) propTag;
|
|
||||||
|
|
||||||
- (void) addProperties: (NSDictionary *) newProperties;
|
- (void) addProperties: (NSDictionary *) newProperties;
|
||||||
- (NSDictionary *) properties;
|
- (NSMutableDictionary *) properties;
|
||||||
|
|
||||||
/* ops */
|
/* ops */
|
||||||
- (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
|
||||||
inMemCtx: (TALLOC_CTX *) localMemCtx;
|
|
||||||
- (int) getProperties: (struct mapistore_property_data *) data
|
- (int) getProperties: (struct mapistore_property_data *) data
|
||||||
withTags: (enum MAPITAGS *) tags
|
withTags: (enum MAPITAGS *) tags
|
||||||
andCount: (uint16_t) columnCount
|
andCount: (uint16_t) columnCount
|
||||||
|
@ -104,26 +85,13 @@
|
||||||
fromGlobCnt: (uint64_t) objectCnt
|
fromGlobCnt: (uint64_t) objectCnt
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
/* implemented getters */
|
|
||||||
- (int) getPidTagDisplayName: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
- (int) getPidTagSearchKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
- (int) getPidTagGenerateExchangeViews: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
- (int) getPidTagParentSourceKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
- (int) getPidTagSourceKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
- (int) getPidTagChangeKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
|
||||||
- (int) getPidTagCreationTime: (void **) data
|
- (int) getPidTagCreationTime: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (int) getPidTagLastModificationTime: (void **) data
|
- (int) getPidTagLastModificationTime: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx;
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
/* subclasses */
|
/* subclasses */
|
||||||
- (uint64_t) objectVersion;
|
- (NSString *) nameInContainer;
|
||||||
- (NSDate *) creationTime;
|
- (NSDate *) creationTime;
|
||||||
- (NSDate *) lastModificationTime;
|
- (NSDate *) lastModificationTime;
|
||||||
|
|
||||||
|
|
|
@ -58,47 +58,16 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
MAPIStoreFolderK = [MAPIStoreFolder class];
|
MAPIStoreFolderK = [MAPIStoreFolder class];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
|
+ (id) mapiStoreObjectInContainer: (MAPIStoreObject *) newContainer
|
||||||
inContainer: (MAPIStoreObject *) newContainer
|
|
||||||
{
|
{
|
||||||
id newObject;
|
id newObject;
|
||||||
|
|
||||||
newObject = [[self alloc] initWithSOGoObject: newSOGoObject
|
newObject = [[self alloc] initInContainer: newContainer];
|
||||||
inContainer: newContainer];
|
|
||||||
[newObject autorelease];
|
[newObject autorelease];
|
||||||
|
|
||||||
return newObject;
|
return newObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
struct SPropTagArray *properties;
|
|
||||||
const MAPIStorePropertyGetter *classGetters;
|
|
||||||
NSUInteger count;
|
|
||||||
enum MAPITAGS propTag;
|
|
||||||
uint16_t propValue;
|
|
||||||
|
|
||||||
properties = talloc_zero (memCtx, struct SPropTagArray);
|
|
||||||
properties->aulPropTag = talloc_array (properties, enum MAPITAGS,
|
|
||||||
MAPIStoreSupportedPropertiesCount);
|
|
||||||
classGetters = MAPIStorePropertyGettersForClass (self);
|
|
||||||
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
|
|
||||||
{
|
|
||||||
propTag = MAPIStoreSupportedProperties[count];
|
|
||||||
propValue = (propTag & 0xffff0000) >> 16;
|
|
||||||
if (classGetters[propValue])
|
|
||||||
{
|
|
||||||
properties->aulPropTag[properties->cValues] = propTag;
|
|
||||||
properties->cValues++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*propertiesP = properties;
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
if ((self = [super init]))
|
if ((self = [super init]))
|
||||||
|
@ -106,22 +75,19 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
|
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
|
||||||
parentContainersBag = [NSMutableArray new];
|
parentContainersBag = [NSMutableArray new];
|
||||||
container = nil;
|
container = nil;
|
||||||
sogoObject = nil;
|
|
||||||
properties = [NSMutableDictionary new];
|
properties = [NSMutableDictionary new];
|
||||||
isNew = NO;
|
proxies = [NSMutableArray new];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self logWithFormat: @"-init"];
|
// [self logWithFormat: @"-init"];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initWithSOGoObject: (id) newSOGoObject
|
- (id) initInContainer: (MAPIStoreObject *) newContainer
|
||||||
inContainer: (MAPIStoreObject *) newContainer
|
|
||||||
{
|
{
|
||||||
if ((self = [self init]))
|
if ((self = [self init]))
|
||||||
{
|
{
|
||||||
ASSIGN (sogoObject, newSOGoObject);
|
|
||||||
ASSIGN (container, newContainer);
|
ASSIGN (container, newContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,42 +96,22 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
[self logWithFormat: @"-dealloc"];
|
// [self logWithFormat: @"-dealloc"];
|
||||||
[sogoObject release];
|
[proxies release];
|
||||||
[properties release];
|
[properties release];
|
||||||
[parentContainersBag release];
|
[parentContainersBag release];
|
||||||
[container release];
|
[container release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setIsNew: (BOOL) newIsNew
|
|
||||||
{
|
|
||||||
isNew = newIsNew;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) isNew
|
|
||||||
{
|
|
||||||
return isNew;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) sogoObject
|
|
||||||
{
|
|
||||||
return sogoObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (MAPIStoreObject *) container
|
- (MAPIStoreObject *) container
|
||||||
{
|
{
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) nameInContainer
|
|
||||||
{
|
|
||||||
return [sogoObject nameInContainer];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (MAPIStoreContext *) context
|
- (MAPIStoreContext *) context
|
||||||
{
|
{
|
||||||
return [container context];
|
return (MAPIStoreContext *) [container context];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MAPIStoreUserContext *) userContext
|
- (MAPIStoreUserContext *) userContext
|
||||||
|
@ -178,32 +124,11 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
return [[self userContext] mapping];
|
return [[self userContext] mapping];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) cleanupCaches
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* helpers */
|
|
||||||
- (uint64_t) objectId
|
|
||||||
{
|
|
||||||
uint64_t objectId;
|
|
||||||
|
|
||||||
if ([container isKindOfClass: MAPIStoreFolderK])
|
|
||||||
objectId = [(MAPIStoreFolder *) container
|
|
||||||
idForObjectWithKey: [sogoObject nameInContainer]];
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[self errorWithFormat: @"%s: container is not a folder", __PRETTY_FUNCTION__];
|
|
||||||
objectId = (uint64_t) -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return objectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) url
|
- (NSString *) url
|
||||||
{
|
{
|
||||||
NSString *containerURL, *format;
|
NSString *containerURL, *format;
|
||||||
|
|
||||||
containerURL = [container url];
|
containerURL = (NSString *) [container url];
|
||||||
if ([containerURL hasSuffix: @"/"])
|
if ([containerURL hasSuffix: @"/"])
|
||||||
format = @"%@%@";
|
format = @"%@%@";
|
||||||
else
|
else
|
||||||
|
@ -213,12 +138,14 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
containerURL, [self nameInContainer]];
|
containerURL, [self nameInContainer]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* helpers */
|
||||||
|
|
||||||
- (void) addProperties: (NSDictionary *) newNewProperties
|
- (void) addProperties: (NSDictionary *) newNewProperties
|
||||||
{
|
{
|
||||||
[properties addEntriesFromDictionary: newNewProperties];
|
[properties addEntriesFromDictionary: newNewProperties];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *) properties
|
- (NSMutableDictionary *) properties
|
||||||
{
|
{
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -232,6 +159,7 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
SEL methodSel;
|
SEL methodSel;
|
||||||
id value;
|
id value;
|
||||||
int rc = MAPISTORE_ERR_NOT_FOUND;
|
int rc = MAPISTORE_ERR_NOT_FOUND;
|
||||||
|
NSUInteger count, max;
|
||||||
|
|
||||||
value = [properties objectForKey: MAPIPropertyKey (propTag)];
|
value = [properties objectForKey: MAPIPropertyKey (propTag)];
|
||||||
if (value)
|
if (value)
|
||||||
|
@ -245,127 +173,21 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
rc = method (self, methodSel, data, memCtx);
|
rc = method (self, methodSel, data, memCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
if (rc == MAPISTORE_ERR_NOT_FOUND)
|
||||||
}
|
|
||||||
|
|
||||||
/* helper getters */
|
|
||||||
- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt
|
|
||||||
{
|
|
||||||
struct mapistore_connection_info *connInfo;
|
|
||||||
NSMutableData *replicaKey;
|
|
||||||
char buffer[6];
|
|
||||||
NSUInteger count;
|
|
||||||
|
|
||||||
connInfo = [[self context] connectionInfo];
|
|
||||||
|
|
||||||
for (count = 0; count < 6; count++)
|
|
||||||
{
|
{
|
||||||
buffer[count] = objectCnt & 0xff;
|
max = [proxies count];
|
||||||
objectCnt >>= 8;
|
for (count = 0; rc == MAPISTORE_ERR_NOT_FOUND && count < max; count++)
|
||||||
}
|
rc = [[proxies objectAtIndex: count]
|
||||||
|
getProperty: data
|
||||||
replicaKey = [NSMutableData dataWithCapacity: 22];
|
withTag: propTag
|
||||||
[replicaKey appendBytes: &connInfo->replica_guid
|
inMemCtx: memCtx];
|
||||||
length: sizeof (struct GUID)];
|
|
||||||
[replicaKey appendBytes: buffer length: 6];
|
|
||||||
|
|
||||||
return replicaKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getReplicaKey: (void **) data
|
|
||||||
fromGlobCnt: (uint64_t) objectCnt
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
*data = [[self getReplicaKeyFromGlobCnt: objectCnt] asBinaryInMemCtx: memCtx];
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* getters */
|
|
||||||
- (int) getPidTagDisplayName: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
*data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx];
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagSearchKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
NSString *stringValue;
|
|
||||||
|
|
||||||
stringValue = [sogoObject nameInContainer];
|
|
||||||
*data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding]
|
|
||||||
asBinaryInMemCtx: memCtx];
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagGenerateExchangeViews: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
return [self getNo: data inMemCtx: memCtx];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagParentSourceKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
return [self getReplicaKey: data fromGlobCnt: [container objectId] >> 16
|
|
||||||
inMemCtx: memCtx];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagSourceKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
return [self getReplicaKey: data fromGlobCnt: [self objectId] >> 16
|
|
||||||
inMemCtx: memCtx];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (uint64_t) objectVersion
|
|
||||||
{
|
|
||||||
[self subclassResponsibility: _cmd];
|
|
||||||
|
|
||||||
return ULLONG_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagChangeKey: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
uint64_t obVersion;
|
|
||||||
|
|
||||||
obVersion = [self objectVersion];
|
|
||||||
if (obVersion == ULLONG_MAX)
|
|
||||||
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
||||||
else
|
|
||||||
rc = [self getReplicaKey: data fromGlobCnt: obVersion
|
|
||||||
inMemCtx: memCtx];
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagChangeNumber: (void **) data
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
uint64_t obVersion;
|
|
||||||
|
|
||||||
obVersion = [self objectVersion];
|
|
||||||
if (obVersion == ULLONG_MAX)
|
|
||||||
rc = MAPISTORE_ERR_NOT_FOUND;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
|
|
||||||
| 0x0001));
|
|
||||||
rc = MAPISTORE_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagCreationTime: (void **) data
|
- (int) getPidTagCreationTime: (void **) data
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
*data = [[self creationTime] asFileTimeInMemCtx: memCtx];
|
*data = [[self creationTime] asFileTimeInMemCtx: memCtx];
|
||||||
|
|
||||||
|
@ -380,39 +202,21 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
NSUInteger count;
|
|
||||||
struct SPropTagArray *availableProps;
|
|
||||||
enum MAPITAGS propTag;
|
|
||||||
|
|
||||||
availableProps = talloc_zero (memCtx, struct SPropTagArray);
|
|
||||||
availableProps->aulPropTag = talloc_array (availableProps, enum MAPITAGS,
|
|
||||||
MAPIStoreSupportedPropertiesCount);
|
|
||||||
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
|
|
||||||
{
|
|
||||||
propTag = MAPIStoreSupportedProperties[count];
|
|
||||||
if ([self canGetProperty: propTag])
|
|
||||||
{
|
|
||||||
availableProps->aulPropTag[availableProps->cValues] = propTag;
|
|
||||||
availableProps->cValues++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*propertiesP = availableProps;
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
|
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
|
||||||
{
|
{
|
||||||
uint16_t propValue;
|
uint16_t propValue;
|
||||||
|
BOOL canGetProperty;
|
||||||
|
NSUInteger count, max;
|
||||||
|
|
||||||
propValue = (propTag & 0xffff0000) >> 16;
|
propValue = (propTag & 0xffff0000) >> 16;
|
||||||
|
|
||||||
return (classGetters[propValue]
|
canGetProperty = (classGetters[propValue]
|
||||||
|| [properties objectForKey: MAPIPropertyKey (propTag)]);
|
|| [properties objectForKey: MAPIPropertyKey (propTag)]);
|
||||||
|
max = [proxies count];
|
||||||
|
for (count = 0; !canGetProperty && count < max; count++)
|
||||||
|
canGetProperty = [[proxies objectAtIndex: count] canGetProperty: propTag];
|
||||||
|
|
||||||
|
return canGetProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getProperties: (struct mapistore_property_data *) data
|
- (int) getProperties: (struct mapistore_property_data *) data
|
||||||
|
@ -430,6 +234,11 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) addProxy: (MAPIStoreObjectProxy *) newProxy
|
||||||
|
{
|
||||||
|
[proxies addObject: newProxy];
|
||||||
|
}
|
||||||
|
|
||||||
- (int) addPropertiesFromRow: (struct SRow *) aRow
|
- (int) addPropertiesFromRow: (struct SRow *) aRow
|
||||||
{
|
{
|
||||||
struct SPropValue *cValue;
|
struct SPropValue *cValue;
|
||||||
|
@ -474,7 +283,46 @@ static Class NSExceptionK, MAPIStoreFolderK;
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSData *) getReplicaKeyFromGlobCnt: (uint64_t) objectCnt
|
||||||
|
{
|
||||||
|
struct mapistore_connection_info *connInfo;
|
||||||
|
NSMutableData *replicaKey;
|
||||||
|
char buffer[6];
|
||||||
|
NSUInteger count;
|
||||||
|
|
||||||
|
connInfo = [[self context] connectionInfo];
|
||||||
|
|
||||||
|
for (count = 0; count < 6; count++)
|
||||||
|
{
|
||||||
|
buffer[count] = objectCnt & 0xff;
|
||||||
|
objectCnt >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
replicaKey = [NSMutableData dataWithCapacity: 22];
|
||||||
|
[replicaKey appendBytes: &connInfo->replica_guid
|
||||||
|
length: sizeof (struct GUID)];
|
||||||
|
[replicaKey appendBytes: buffer length: 6];
|
||||||
|
|
||||||
|
return replicaKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getReplicaKey: (void **) data
|
||||||
|
fromGlobCnt: (uint64_t) objectCnt
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
*data = [[self getReplicaKeyFromGlobCnt: objectCnt] asBinaryInMemCtx: memCtx];
|
||||||
|
|
||||||
|
return MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* subclasses */
|
/* subclasses */
|
||||||
|
- (NSString *) nameInContainer
|
||||||
|
{
|
||||||
|
[self subclassResponsibility: _cmd];
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSDate *) creationTime
|
- (NSDate *) creationTime
|
||||||
{
|
{
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
|
|
41
OpenChange/MAPIStoreObjectProxy.h
Normal file
41
OpenChange/MAPIStoreObjectProxy.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* MAPIStoreObjectProxy.h - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAPISTOREOBJECTPROXY_H
|
||||||
|
#define MAPISTOREOBJECTPROXY_H
|
||||||
|
|
||||||
|
#include <talloc.h>
|
||||||
|
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
|
||||||
|
@interface MAPIStoreObjectProxy : NSObject
|
||||||
|
{
|
||||||
|
const IMP *classGetters;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (enum mapistore_error) getProperty: (void **) data
|
||||||
|
withTag: (enum MAPITAGS) propTag
|
||||||
|
inMemCtx: (TALLOC_CTX *) localMemCtx;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* MAPISTOREOBJECTPROXY_H */
|
67
OpenChange/MAPIStoreObjectProxy.m
Normal file
67
OpenChange/MAPIStoreObjectProxy.m
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* MAPIStoreObjectProxy.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import "MAPIStorePropertySelectors.h"
|
||||||
|
#import "NSString+MAPIStore.h"
|
||||||
|
|
||||||
|
#import "MAPIStoreObjectProxy.h"
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <talloc.h>
|
||||||
|
#include <gen_ndr/exchange.h>
|
||||||
|
#include <mapistore/mapistore.h>
|
||||||
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
|
@implementation MAPIStoreObjectProxy
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (enum mapistore_error) getProperty: (void **) data
|
||||||
|
withTag: (enum MAPITAGS) propTag
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
MAPIStorePropertyGetter method;
|
||||||
|
uint16_t propValue;
|
||||||
|
SEL methodSel;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
propValue = (propTag & 0xffff0000) >> 16;
|
||||||
|
methodSel = MAPIStoreSelectorForPropertyGetter (propValue);
|
||||||
|
method = (MAPIStorePropertyGetter) classGetters[propValue];
|
||||||
|
if (method)
|
||||||
|
rc = method (self, methodSel, data, memCtx);
|
||||||
|
else
|
||||||
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -23,7 +23,6 @@
|
||||||
#import <Foundation/NSArray.h>
|
#import <Foundation/NSArray.h>
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
#import <SOGo/SOGoFolder.h>
|
#import <SOGo/SOGoFolder.h>
|
||||||
#import <SOGo/SOGoObject.h>
|
#import <SOGo/SOGoObject.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
|
@ -50,7 +49,7 @@
|
||||||
MAPIStorePermissionEntry *newEntry;
|
MAPIStorePermissionEntry *newEntry;
|
||||||
|
|
||||||
newEntry = [[self alloc] initWithUserId: newUserId andMemberId: newMemberId
|
newEntry = [[self alloc] initWithUserId: newUserId andMemberId: newMemberId
|
||||||
forFolder: newFolder];
|
forFolder: newFolder];
|
||||||
[newEntry autorelease];
|
[newEntry autorelease];
|
||||||
|
|
||||||
return newEntry;
|
return newEntry;
|
||||||
|
@ -60,7 +59,7 @@
|
||||||
andMemberId: (uint64_t) newMemberId
|
andMemberId: (uint64_t) newMemberId
|
||||||
forFolder: (MAPIStoreFolder *) newFolder
|
forFolder: (MAPIStoreFolder *) newFolder
|
||||||
{
|
{
|
||||||
if ((self = [self initWithSOGoObject: nil inContainer: newFolder]))
|
if ((self = [self initInContainer: newFolder]))
|
||||||
{
|
{
|
||||||
ASSIGN (userId, newUserId);
|
ASSIGN (userId, newUserId);
|
||||||
memberId = newMemberId;
|
memberId = newMemberId;
|
||||||
|
@ -103,7 +102,7 @@
|
||||||
entryId = [NSData data];
|
entryId = [NSData data];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
connInfo = [[container context] connectionInfo];
|
connInfo = [(MAPIStoreContext *) [container context] connectionInfo];
|
||||||
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, userId);
|
entryId = MAPIStoreInternalEntryId (connInfo->sam_ctx, userId);
|
||||||
}
|
}
|
||||||
*data = [entryId asBinaryInMemCtx: memCtx];
|
*data = [entryId asBinaryInMemCtx: memCtx];
|
||||||
|
|
|
@ -23,10 +23,14 @@
|
||||||
#ifndef MAPISTORERECURRENCEUTILS_H
|
#ifndef MAPISTORERECURRENCEUTILS_H
|
||||||
#define MAPISTORERECURRENCEUTILS_H
|
#define MAPISTORERECURRENCEUTILS_H
|
||||||
|
|
||||||
|
#include <talloc.h>
|
||||||
|
|
||||||
#import <NGCards/iCalCalendar.h>
|
#import <NGCards/iCalCalendar.h>
|
||||||
#import <NGCards/iCalRecurrenceRule.h>
|
#import <NGCards/iCalRecurrenceRule.h>
|
||||||
|
|
||||||
@class NSCalendarDate;
|
@class NSTimeZone;
|
||||||
|
|
||||||
|
@class iCalEvent;
|
||||||
@class iCalRepeatableEntityObject;
|
@class iCalRepeatableEntityObject;
|
||||||
@class iCalRecurrenceRule;
|
@class iCalRecurrenceRule;
|
||||||
|
|
||||||
|
@ -44,8 +48,9 @@
|
||||||
@interface iCalRecurrenceRule (MAPIStoreRecurrence)
|
@interface iCalRecurrenceRule (MAPIStoreRecurrence)
|
||||||
|
|
||||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||||
withStartDate: (NSCalendarDate *) startDate
|
withEvent: (iCalEvent *) event
|
||||||
andEndDate: (NSCalendarDate *) endDate;
|
inTimeZone: (NSTimeZone *) timeZone
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -21,17 +21,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/NSArray.h>
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSSet.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
#import <NGExtensions/NSCalendarDate+misc.h>
|
#import <NGExtensions/NSCalendarDate+misc.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
|
#import <NGCards/iCalByDayMask.h>
|
||||||
|
#import <NGCards/iCalDateTime.h>
|
||||||
|
#import <NGCards/iCalEvent.h>
|
||||||
#import <NGCards/iCalRepeatableEntityObject.h>
|
#import <NGCards/iCalRepeatableEntityObject.h>
|
||||||
#import <NGCards/iCalRecurrenceRule.h>
|
#import <NGCards/iCalRecurrenceRule.h>
|
||||||
#import <NGCards/iCalByDayMask.h>
|
#import <NGCards/iCalTimeZone.h>
|
||||||
|
|
||||||
#import "NSDate+MAPIStore.h"
|
#import "NSDate+MAPIStore.h"
|
||||||
#import "MAPIStoreRecurrenceUtils.h"
|
#import "MAPIStoreRecurrenceUtils.h"
|
||||||
|
#import "MAPIStoreTypes.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <talloc.h>
|
#include <talloc.h>
|
||||||
|
@ -43,13 +49,15 @@
|
||||||
- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity
|
- (void) setupRecurrenceWithMasterEntity: (iCalRepeatableEntityObject *) entity
|
||||||
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
fromRecurrencePattern: (struct RecurrencePattern *) rp
|
||||||
{
|
{
|
||||||
NSCalendarDate *startDate, *olEndDate, *untilDate;
|
NSCalendarDate *startDate, *olEndDate, *untilDate, *exDate;
|
||||||
NSString *monthDay, *month;
|
NSString *monthDay, *month;
|
||||||
|
NSMutableSet *exceptionDates;
|
||||||
|
NSArray *realExDates;
|
||||||
iCalRecurrenceRule *rule;
|
iCalRecurrenceRule *rule;
|
||||||
iCalByDayMask *byDayMask;
|
iCalByDayMask *byDayMask;
|
||||||
iCalWeekOccurrence weekOccurrence;
|
iCalWeekOccurrence weekOccurrence;
|
||||||
iCalWeekOccurrences dayMaskDays;
|
iCalWeekOccurrences dayMaskDays;
|
||||||
NSUInteger count;
|
NSUInteger count, max;
|
||||||
NSInteger bySetPos;
|
NSInteger bySetPos;
|
||||||
unsigned char maskValue;
|
unsigned char maskValue;
|
||||||
|
|
||||||
|
@ -203,6 +211,37 @@
|
||||||
[self errorWithFormat: @"invalid value for EndType: %.4x",
|
[self errorWithFormat: @"invalid value for EndType: %.4x",
|
||||||
rp->EndType];
|
rp->EndType];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* exception dates:
|
||||||
|
- take all deleted instances
|
||||||
|
- remove all modified instances from the above set
|
||||||
|
- add remaining instances, in chronological order
|
||||||
|
*/
|
||||||
|
exceptionDates = [NSMutableSet set];
|
||||||
|
for (count = 0; count < rp->DeletedInstanceCount; count++)
|
||||||
|
{
|
||||||
|
exDate
|
||||||
|
= [NSDate dateFromMinutesSince1601: rp->DeletedInstanceDates[count]];
|
||||||
|
exDate = [exDate hour: [startDate hourOfDay]
|
||||||
|
minute: [startDate minuteOfHour]
|
||||||
|
second: [startDate secondOfMinute]];
|
||||||
|
[exceptionDates addObject: exDate];
|
||||||
|
}
|
||||||
|
for (count = 0; count < rp->ModifiedInstanceCount; count++)
|
||||||
|
{
|
||||||
|
exDate
|
||||||
|
= [NSDate dateFromMinutesSince1601: rp->ModifiedInstanceDates[count]];
|
||||||
|
exDate = [exDate hour: [startDate hourOfDay]
|
||||||
|
minute: [startDate minuteOfHour]
|
||||||
|
second: [startDate secondOfMinute]];
|
||||||
|
[exceptionDates removeObject: exDate];
|
||||||
|
}
|
||||||
|
|
||||||
|
realExDates = [[exceptionDates allObjects]
|
||||||
|
sortedArrayUsingSelector: @selector (compare:)];
|
||||||
|
max = [realExDates count];
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
[entity addToExceptionDates: [realExDates objectAtIndex: count]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -210,16 +249,26 @@
|
||||||
@implementation iCalRecurrenceRule (MAPIStoreRecurrence)
|
@implementation iCalRecurrenceRule (MAPIStoreRecurrence)
|
||||||
|
|
||||||
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
- (void) fillRecurrencePattern: (struct RecurrencePattern *) rp
|
||||||
withStartDate: (NSCalendarDate *) startDate
|
withEvent: (iCalEvent *) event
|
||||||
andEndDate: (NSCalendarDate *) endDate
|
inTimeZone: (NSTimeZone *) timeZone
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
iCalRecurrenceFrequency freq;
|
iCalRecurrenceFrequency freq;
|
||||||
iCalByDayMask *byDayMask;
|
iCalByDayMask *byDayMask;
|
||||||
NSString *byMonthDay, *bySetPos;
|
NSString *byMonthDay, *bySetPos;
|
||||||
NSCalendarDate *untilDate, *beginOfWeek, *minimumDate, *moduloDate, *midnight;
|
NSCalendarDate *startDate, *endDate, *untilDate, *beginOfWeek, *minimumDate,
|
||||||
|
*moduloDate, *midnight;
|
||||||
iCalWeekOccurrences *days;
|
iCalWeekOccurrences *days;
|
||||||
NSInteger dayOfWeek, repeatInterval, repeatCount, count, firstOccurrence;
|
NSInteger dayOfWeek, repeatInterval, repeatCount, count, firstOccurrence,
|
||||||
|
max;
|
||||||
uint32_t nbrMonths, mask;
|
uint32_t nbrMonths, mask;
|
||||||
|
NSArray *events;
|
||||||
|
NSMutableArray *deletedDates, *modifiedDates;
|
||||||
|
|
||||||
|
startDate = [event firstRecurrenceStartDate];
|
||||||
|
[startDate setTimeZone: timeZone];
|
||||||
|
endDate = [event lastPossibleRecurrenceStartDate];
|
||||||
|
[endDate setTimeZone: timeZone];
|
||||||
|
|
||||||
rp->ReaderVersion = 0x3004;
|
rp->ReaderVersion = 0x3004;
|
||||||
rp->WriterVersion = 0x3004;
|
rp->WriterVersion = 0x3004;
|
||||||
|
@ -244,6 +293,7 @@
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rp->EndDate = 0x5ae980df;
|
rp->EndDate = 0x5ae980df;
|
||||||
|
rp->OccurrenceCount = 0xa;
|
||||||
rp->EndType = END_NEVER_END;
|
rp->EndType = END_NEVER_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,6 +420,43 @@
|
||||||
[self errorWithFormat: @"rule for an event that never occurs"];
|
[self errorWithFormat: @"rule for an event that never occurs"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
events = [[event parent] events];
|
||||||
|
max = [events count];
|
||||||
|
modifiedDates = [NSMutableArray arrayWithCapacity: max];
|
||||||
|
for (count = 1; count < max; count++)
|
||||||
|
{
|
||||||
|
startDate = [[events objectAtIndex: count] recurrenceId];
|
||||||
|
if (startDate)
|
||||||
|
[modifiedDates addObject: startDate];
|
||||||
|
else
|
||||||
|
[self errorWithFormat: @"missing recurrence-id for event %d", count];
|
||||||
|
}
|
||||||
|
max = [modifiedDates count];
|
||||||
|
rp->ModifiedInstanceCount = max;
|
||||||
|
rp->ModifiedInstanceDates = talloc_array (memCtx, uint32_t, max);
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
startDate = [[modifiedDates objectAtIndex: count]
|
||||||
|
hour: 0 minute: 0 second: 0];
|
||||||
|
*(rp->ModifiedInstanceDates + count) = [startDate asMinutesSince1601];
|
||||||
|
}
|
||||||
|
|
||||||
|
deletedDates = [modifiedDates mutableCopy];
|
||||||
|
[deletedDates autorelease];
|
||||||
|
[deletedDates
|
||||||
|
addObjectsFromArray: [event exceptionDatesWithTimeZone: utcTZ]];
|
||||||
|
[deletedDates sortUsingFunction: NSDateCompare context: NULL];
|
||||||
|
|
||||||
|
max = [deletedDates count];
|
||||||
|
rp->DeletedInstanceCount = max;
|
||||||
|
rp->DeletedInstanceDates = talloc_array (memCtx, uint32_t, max);
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
startDate = [[deletedDates objectAtIndex: count]
|
||||||
|
hour: 0 minute: 0 second: 0];
|
||||||
|
*(rp->DeletedInstanceDates + count) = [startDate asMinutesSince1601];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -273,7 +273,7 @@ sogo_context_get_path(void *backend_object, TALLOC_CTX *mem_ctx,
|
||||||
if (backend_object)
|
if (backend_object)
|
||||||
{
|
{
|
||||||
wrapper = backend_object;
|
wrapper = backend_object;
|
||||||
context = wrapper->MAPIStoreSOGoObject;
|
context = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx];
|
rc = [context getPath: path ofFMID: fmid inMemCtx: mem_ctx];
|
||||||
|
@ -303,7 +303,7 @@ sogo_context_get_root_folder(void *backend_object, TALLOC_CTX *mem_ctx,
|
||||||
if (backend_object)
|
if (backend_object)
|
||||||
{
|
{
|
||||||
wrapper = backend_object;
|
wrapper = backend_object;
|
||||||
context = wrapper->MAPIStoreSOGoObject;
|
context = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [context getRootFolder: &folder withFID: fid];
|
rc = [context getRootFolder: &folder withFID: fid];
|
||||||
|
@ -342,7 +342,7 @@ sogo_folder_open_folder(void *folder_object, TALLOC_CTX *mem_ctx, uint64_t fid,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder openFolder: &childFolder withFID: fid];
|
rc = [folder openFolder: &childFolder withFID: fid];
|
||||||
|
@ -382,7 +382,7 @@ sogo_folder_create_folder(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder createFolder: &childFolder withRow: aRow andFID: fid];
|
rc = [folder createFolder: &childFolder withRow: aRow andFID: fid];
|
||||||
|
@ -421,7 +421,7 @@ sogo_folder_delete(void *folder_object)
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder deleteFolder];
|
rc = [folder deleteFolder];
|
||||||
|
@ -449,7 +449,7 @@ sogo_folder_get_child_count(void *folder_object, enum mapistore_table_type table
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder getChildCount: child_count ofTableType: table_type];
|
rc = [folder getChildCount: child_count ofTableType: table_type];
|
||||||
|
@ -481,7 +481,7 @@ sogo_folder_open_message(void *folder_object,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder openMessage: &message
|
rc = [folder openMessage: &message
|
||||||
|
@ -519,7 +519,7 @@ sogo_folder_create_message(void *folder_object,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder createMessage: &message
|
rc = [folder createMessage: &message
|
||||||
|
@ -551,7 +551,7 @@ sogo_folder_delete_message(void *folder_object, uint64_t mid, uint8_t flags)
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder deleteMessageWithMID: mid andFlags: flags];
|
rc = [folder deleteMessageWithMID: mid andFlags: flags];
|
||||||
|
@ -584,10 +584,10 @@ sogo_folder_move_copy_messages(void *folder_object,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
targetFolder = wrapper->MAPIStoreSOGoObject;
|
targetFolder = wrapper->instance;
|
||||||
|
|
||||||
wrapper = source_folder_object;
|
wrapper = source_folder_object;
|
||||||
sourceFolder = wrapper->MAPIStoreSOGoObject;
|
sourceFolder = wrapper->instance;
|
||||||
|
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
|
@ -608,6 +608,86 @@ sogo_folder_move_copy_messages(void *folder_object,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum mapistore_error
|
||||||
|
sogo_folder_move_folder(void *folder_object, void *target_folder_object,
|
||||||
|
const char *new_folder_name)
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool;
|
||||||
|
MAPIStoreFolder *moveFolder, *targetFolder;
|
||||||
|
NSString *newFolderName;
|
||||||
|
struct MAPIStoreTallocWrapper *wrapper;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
|
||||||
|
|
||||||
|
if (folder_object)
|
||||||
|
{
|
||||||
|
wrapper = folder_object;
|
||||||
|
moveFolder = wrapper->instance;
|
||||||
|
|
||||||
|
wrapper = target_folder_object;
|
||||||
|
targetFolder = wrapper->instance;
|
||||||
|
|
||||||
|
GSRegisterCurrentThread ();
|
||||||
|
pool = [NSAutoreleasePool new];
|
||||||
|
|
||||||
|
if (new_folder_name)
|
||||||
|
newFolderName = [NSString stringWithUTF8String: new_folder_name];
|
||||||
|
else
|
||||||
|
newFolderName = nil;
|
||||||
|
|
||||||
|
rc = [moveFolder moveToFolder: targetFolder
|
||||||
|
withNewName: newFolderName];
|
||||||
|
[pool release];
|
||||||
|
GSUnregisterCurrentThread ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = sogo_backend_unexpected_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum mapistore_error
|
||||||
|
sogo_folder_copy_folder(void *folder_object, void *target_folder_object,
|
||||||
|
bool recursive, const char *new_folder_name)
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool;
|
||||||
|
MAPIStoreFolder *copyFolder, *targetFolder;
|
||||||
|
NSString *newFolderName;
|
||||||
|
struct MAPIStoreTallocWrapper *wrapper;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
|
||||||
|
|
||||||
|
if (folder_object)
|
||||||
|
{
|
||||||
|
wrapper = folder_object;
|
||||||
|
copyFolder = wrapper->instance;
|
||||||
|
|
||||||
|
wrapper = target_folder_object;
|
||||||
|
targetFolder = wrapper->instance;
|
||||||
|
|
||||||
|
GSRegisterCurrentThread ();
|
||||||
|
pool = [NSAutoreleasePool new];
|
||||||
|
|
||||||
|
newFolderName = [NSString stringWithUTF8String: new_folder_name];
|
||||||
|
|
||||||
|
rc = [copyFolder copyToFolder: targetFolder
|
||||||
|
recursive: recursive
|
||||||
|
withNewName: newFolderName];
|
||||||
|
[pool release];
|
||||||
|
GSUnregisterCurrentThread ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = sogo_backend_unexpected_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static enum mapistore_error
|
static enum mapistore_error
|
||||||
sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
|
sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||||
enum mapistore_table_type table_type, uint64_t change_num,
|
enum mapistore_table_type table_type, uint64_t change_num,
|
||||||
|
@ -623,7 +703,7 @@ sogo_folder_get_deleted_fmids(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder getDeletedFMIDs: fmidsp
|
rc = [folder getDeletedFMIDs: fmidsp
|
||||||
|
@ -658,7 +738,7 @@ sogo_folder_open_table(void *folder_object, TALLOC_CTX *mem_ctx,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder getTable: &table
|
rc = [folder getTable: &table
|
||||||
|
@ -693,7 +773,7 @@ sogo_folder_modify_permissions(void *folder_object, uint8_t flags,
|
||||||
if (folder_object)
|
if (folder_object)
|
||||||
{
|
{
|
||||||
wrapper = folder_object;
|
wrapper = folder_object;
|
||||||
folder = wrapper->MAPIStoreSOGoObject;
|
folder = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [folder modifyPermissions: permissions
|
rc = [folder modifyPermissions: permissions
|
||||||
|
@ -725,7 +805,7 @@ sogo_message_get_message_data(void *message_object,
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
[message getMessageData: msg_dataP
|
[message getMessageData: msg_dataP
|
||||||
|
@ -756,7 +836,7 @@ sogo_message_create_attachment (void *message_object, TALLOC_CTX *mem_ctx, void
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [message createAttachment: &attachment inAID: aidp];
|
rc = [message createAttachment: &attachment inAID: aidp];
|
||||||
|
@ -789,7 +869,7 @@ sogo_message_open_attachment (void *message_object, TALLOC_CTX *mem_ctx,
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [message getAttachment: &attachment withAID: aid];
|
rc = [message getAttachment: &attachment withAID: aid];
|
||||||
|
@ -821,7 +901,7 @@ sogo_message_get_attachment_table (void *message_object, TALLOC_CTX *mem_ctx, vo
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [message getAttachmentTable: &table
|
rc = [message getAttachmentTable: &table
|
||||||
|
@ -856,7 +936,7 @@ sogo_message_modify_recipients (void *message_object,
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [message modifyRecipientsWithRecipients: recipients
|
rc = [message modifyRecipientsWithRecipients: recipients
|
||||||
|
@ -887,7 +967,7 @@ sogo_message_set_read_flag (void *message_object, uint8_t flag)
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [message setReadFlag: flag];
|
rc = [message setReadFlag: flag];
|
||||||
|
@ -916,7 +996,7 @@ sogo_message_save (void *message_object)
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [message saveMessage];
|
rc = [message saveMessage];
|
||||||
|
@ -945,7 +1025,7 @@ sogo_message_submit (void *message_object, enum SubmitFlags flags)
|
||||||
if (message_object)
|
if (message_object)
|
||||||
{
|
{
|
||||||
wrapper = message_object;
|
wrapper = message_object;
|
||||||
message = wrapper->MAPIStoreSOGoObject;
|
message = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [message submitWithFlags: flags];
|
rc = [message submitWithFlags: flags];
|
||||||
|
@ -962,11 +1042,11 @@ sogo_message_submit (void *message_object, enum SubmitFlags flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum mapistore_error
|
static enum mapistore_error
|
||||||
sogo_message_attachment_open_embedded_message
|
sogo_message_attachment_open_embedded_message (void *attachment_object,
|
||||||
(void *attachment_object,
|
TALLOC_CTX *mem_ctx,
|
||||||
TALLOC_CTX *mem_ctx, void **message_object,
|
void **message_object,
|
||||||
uint64_t *midP,
|
uint64_t *midP,
|
||||||
struct mapistore_message **msg)
|
struct mapistore_message **msg)
|
||||||
{
|
{
|
||||||
struct MAPIStoreTallocWrapper *wrapper;
|
struct MAPIStoreTallocWrapper *wrapper;
|
||||||
NSAutoreleasePool *pool;
|
NSAutoreleasePool *pool;
|
||||||
|
@ -979,7 +1059,7 @@ sogo_message_attachment_open_embedded_message
|
||||||
if (attachment_object)
|
if (attachment_object)
|
||||||
{
|
{
|
||||||
wrapper = attachment_object;
|
wrapper = attachment_object;
|
||||||
attachment = wrapper->MAPIStoreSOGoObject;
|
attachment = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [attachment openEmbeddedMessage: &message
|
rc = [attachment openEmbeddedMessage: &message
|
||||||
|
@ -999,6 +1079,42 @@ sogo_message_attachment_open_embedded_message
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum mapistore_error
|
||||||
|
sogo_message_attachment_create_embedded_message (void *attachment_object,
|
||||||
|
TALLOC_CTX *mem_ctx,
|
||||||
|
void **message_object,
|
||||||
|
struct mapistore_message **msg)
|
||||||
|
{
|
||||||
|
struct MAPIStoreTallocWrapper *wrapper;
|
||||||
|
NSAutoreleasePool *pool;
|
||||||
|
MAPIStoreAttachment *attachment;
|
||||||
|
MAPIStoreEmbeddedMessage *message;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
DEBUG (5, ("[SOGo: %s:%d]\n", __FUNCTION__, __LINE__));
|
||||||
|
|
||||||
|
if (attachment_object)
|
||||||
|
{
|
||||||
|
wrapper = attachment_object;
|
||||||
|
attachment = wrapper->instance;
|
||||||
|
GSRegisterCurrentThread ();
|
||||||
|
pool = [NSAutoreleasePool new];
|
||||||
|
rc = [attachment createEmbeddedMessage: &message
|
||||||
|
withMAPIStoreMsg: msg
|
||||||
|
inMemCtx: mem_ctx];
|
||||||
|
if (rc == MAPISTORE_SUCCESS)
|
||||||
|
*message_object = [message tallocWrapper: mem_ctx];
|
||||||
|
[pool release];
|
||||||
|
GSUnregisterCurrentThread ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = sogo_backend_unexpected_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static enum mapistore_error sogo_table_get_available_properties(void *table_object,
|
static enum mapistore_error sogo_table_get_available_properties(void *table_object,
|
||||||
TALLOC_CTX *mem_ctx, struct SPropTagArray **propertiesP)
|
TALLOC_CTX *mem_ctx, struct SPropTagArray **propertiesP)
|
||||||
{
|
{
|
||||||
|
@ -1012,7 +1128,7 @@ static enum mapistore_error sogo_table_get_available_properties(void *table_obje
|
||||||
if (table_object)
|
if (table_object)
|
||||||
{
|
{
|
||||||
wrapper = table_object;
|
wrapper = table_object;
|
||||||
table = wrapper->MAPIStoreSOGoObject;
|
table = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
rc = [table getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
||||||
|
@ -1040,7 +1156,7 @@ sogo_table_set_columns (void *table_object, uint16_t count, enum MAPITAGS *prope
|
||||||
if (table_object)
|
if (table_object)
|
||||||
{
|
{
|
||||||
wrapper = table_object;
|
wrapper = table_object;
|
||||||
table = wrapper->MAPIStoreSOGoObject;
|
table = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [table setColumns: properties
|
rc = [table setColumns: properties
|
||||||
|
@ -1069,7 +1185,7 @@ sogo_table_set_restrictions (void *table_object, struct mapi_SRestriction *restr
|
||||||
if (table_object)
|
if (table_object)
|
||||||
{
|
{
|
||||||
wrapper = table_object;
|
wrapper = table_object;
|
||||||
table = wrapper->MAPIStoreSOGoObject;
|
table = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
[table setRestrictions: restrictions];
|
[table setRestrictions: restrictions];
|
||||||
|
@ -1100,7 +1216,7 @@ sogo_table_set_sort_order (void *table_object, struct SSortOrderSet *sort_order,
|
||||||
if (table_object)
|
if (table_object)
|
||||||
{
|
{
|
||||||
wrapper = table_object;
|
wrapper = table_object;
|
||||||
table = wrapper->MAPIStoreSOGoObject;
|
table = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
[table setSortOrder: sort_order];
|
[table setSortOrder: sort_order];
|
||||||
|
@ -1133,7 +1249,7 @@ sogo_table_get_row (void *table_object, TALLOC_CTX *mem_ctx,
|
||||||
if (table_object)
|
if (table_object)
|
||||||
{
|
{
|
||||||
wrapper = table_object;
|
wrapper = table_object;
|
||||||
table = wrapper->MAPIStoreSOGoObject;
|
table = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [table getRow: data withRowID: row_id andQueryType: query_type
|
rc = [table getRow: data withRowID: row_id andQueryType: query_type
|
||||||
|
@ -1164,7 +1280,7 @@ sogo_table_get_row_count (void *table_object,
|
||||||
if (table_object)
|
if (table_object)
|
||||||
{
|
{
|
||||||
wrapper = table_object;
|
wrapper = table_object;
|
||||||
table = wrapper->MAPIStoreSOGoObject;
|
table = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [table getRowCount: row_countp
|
rc = [table getRowCount: row_countp
|
||||||
|
@ -1193,7 +1309,7 @@ sogo_table_handle_destructor (void *table_object, uint32_t handle_id)
|
||||||
if (table_object)
|
if (table_object)
|
||||||
{
|
{
|
||||||
wrapper = table_object;
|
wrapper = table_object;
|
||||||
table = wrapper->MAPIStoreSOGoObject;
|
table = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
[table destroyHandle: handle_id];
|
[table destroyHandle: handle_id];
|
||||||
|
@ -1223,7 +1339,7 @@ static enum mapistore_error sogo_properties_get_available_properties(void *objec
|
||||||
if (object)
|
if (object)
|
||||||
{
|
{
|
||||||
wrapper = object;
|
wrapper = object;
|
||||||
propObject = wrapper->MAPIStoreSOGoObject;
|
propObject = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
rc = [propObject getAvailableProperties: propertiesP inMemCtx: mem_ctx];
|
||||||
|
@ -1254,7 +1370,7 @@ sogo_properties_get_properties (void *object,
|
||||||
if (object)
|
if (object)
|
||||||
{
|
{
|
||||||
wrapper = object;
|
wrapper = object;
|
||||||
propObject = wrapper->MAPIStoreSOGoObject;
|
propObject = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [propObject getProperties: data withTags: properties
|
rc = [propObject getProperties: data withTags: properties
|
||||||
|
@ -1284,7 +1400,7 @@ sogo_properties_set_properties (void *object, struct SRow *aRow)
|
||||||
if (object)
|
if (object)
|
||||||
{
|
{
|
||||||
wrapper = object;
|
wrapper = object;
|
||||||
propObject = wrapper->MAPIStoreSOGoObject;
|
propObject = wrapper->instance;
|
||||||
GSRegisterCurrentThread ();
|
GSRegisterCurrentThread ();
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
rc = [propObject addPropertiesFromRow: aRow];
|
rc = [propObject addPropertiesFromRow: aRow];
|
||||||
|
@ -1378,6 +1494,8 @@ int mapistore_init_backend(void)
|
||||||
backend.folder.create_message = sogo_folder_create_message;
|
backend.folder.create_message = sogo_folder_create_message;
|
||||||
backend.folder.delete_message = sogo_folder_delete_message;
|
backend.folder.delete_message = sogo_folder_delete_message;
|
||||||
backend.folder.move_copy_messages = sogo_folder_move_copy_messages;
|
backend.folder.move_copy_messages = sogo_folder_move_copy_messages;
|
||||||
|
backend.folder.move_folder = sogo_folder_move_folder;
|
||||||
|
backend.folder.copy_folder = sogo_folder_copy_folder;
|
||||||
backend.folder.get_deleted_fmids = sogo_folder_get_deleted_fmids;
|
backend.folder.get_deleted_fmids = sogo_folder_get_deleted_fmids;
|
||||||
backend.folder.get_child_count = sogo_folder_get_child_count;
|
backend.folder.get_child_count = sogo_folder_get_child_count;
|
||||||
backend.folder.open_table = sogo_folder_open_table;
|
backend.folder.open_table = sogo_folder_open_table;
|
||||||
|
@ -1386,6 +1504,7 @@ int mapistore_init_backend(void)
|
||||||
backend.message.get_attachment_table = sogo_message_get_attachment_table;
|
backend.message.get_attachment_table = sogo_message_get_attachment_table;
|
||||||
backend.message.open_attachment = sogo_message_open_attachment;
|
backend.message.open_attachment = sogo_message_open_attachment;
|
||||||
backend.message.open_embedded_message = sogo_message_attachment_open_embedded_message;
|
backend.message.open_embedded_message = sogo_message_attachment_open_embedded_message;
|
||||||
|
backend.message.create_embedded_message = sogo_message_attachment_create_embedded_message;
|
||||||
backend.message.get_message_data = sogo_message_get_message_data;
|
backend.message.get_message_data = sogo_message_get_message_data;
|
||||||
backend.message.modify_recipients = sogo_message_modify_recipients;
|
backend.message.modify_recipients = sogo_message_modify_recipients;
|
||||||
backend.message.set_read_flag = sogo_message_set_read_flag;
|
backend.message.set_read_flag = sogo_message_set_read_flag;
|
||||||
|
|
86
OpenChange/MAPIStoreSOGoObject.h
Normal file
86
OpenChange/MAPIStoreSOGoObject.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/* MAPIStoreObject.h - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAPISTORESOGOOBJECT_H
|
||||||
|
#define MAPISTORESOGOOBJECT_H
|
||||||
|
|
||||||
|
#include <talloc.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreObject.h"
|
||||||
|
|
||||||
|
@class NSDate;
|
||||||
|
@class NSData;
|
||||||
|
@class NSString;
|
||||||
|
@class NSMutableArray;
|
||||||
|
@class NSMutableDictionary;
|
||||||
|
|
||||||
|
@class EOQualifier;
|
||||||
|
|
||||||
|
@class MAPIStoreContext;
|
||||||
|
@class MAPIStoreFolder;
|
||||||
|
@class MAPIStoreMapping;
|
||||||
|
@class MAPIStoreTable;
|
||||||
|
@class MAPIStoreUserContext;
|
||||||
|
|
||||||
|
@interface MAPIStoreSOGoObject : MAPIStoreObject
|
||||||
|
{
|
||||||
|
id sogoObject;
|
||||||
|
BOOL isNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
|
||||||
|
inContainer: (MAPIStoreObject *) newContainer;
|
||||||
|
|
||||||
|
- (id) initWithSOGoObject: (id) newSOGoObject
|
||||||
|
inContainer: (MAPIStoreObject *) newFolder;
|
||||||
|
|
||||||
|
- (void) setIsNew: (BOOL) newIsNew;
|
||||||
|
- (BOOL) isNew;
|
||||||
|
|
||||||
|
- (id) sogoObject;
|
||||||
|
|
||||||
|
- (MAPIStoreObject *) container;
|
||||||
|
|
||||||
|
- (void) cleanupCaches;
|
||||||
|
|
||||||
|
- (uint64_t) objectId;
|
||||||
|
|
||||||
|
/* implemented getters */
|
||||||
|
- (int) getPidTagDisplayName: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (int) getPidTagSearchKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (int) getPidTagGenerateExchangeViews: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (int) getPidTagParentSourceKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (int) getPidTagSourceKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (int) getPidTagChangeKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
|
/* subclasses */
|
||||||
|
- (uint64_t) objectVersion;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* MAPISTORESOGOOBJECT_H */
|
230
OpenChange/MAPIStoreSOGoObject.m
Normal file
230
OpenChange/MAPIStoreSOGoObject.m
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
/* MAPIStoreObject.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <SOGo/SOGoObject.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
#import <SOGo/SOGoUserDefaults.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreContext.h"
|
||||||
|
#import "MAPIStoreFolder.h"
|
||||||
|
#import "MAPIStorePropertySelectors.h"
|
||||||
|
#import "MAPIStoreTypes.h"
|
||||||
|
#import "MAPIStoreUserContext.h"
|
||||||
|
#import "NSDate+MAPIStore.h"
|
||||||
|
#import "NSData+MAPIStore.h"
|
||||||
|
#import "NSObject+MAPIStore.h"
|
||||||
|
#import "NSString+MAPIStore.h"
|
||||||
|
|
||||||
|
#import "MAPIStoreSOGoObject.h"
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <talloc.h>
|
||||||
|
#include <gen_ndr/exchange.h>
|
||||||
|
#include <mapistore/mapistore.h>
|
||||||
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
|
@implementation MAPIStoreSOGoObject
|
||||||
|
|
||||||
|
static Class MAPIStoreFolderK;
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
MAPIStoreFolderK = [MAPIStoreFolder class];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id) mapiStoreObjectWithSOGoObject: (id) newSOGoObject
|
||||||
|
inContainer: (MAPIStoreObject *) newContainer
|
||||||
|
{
|
||||||
|
id newObject;
|
||||||
|
|
||||||
|
newObject = [[self alloc] initWithSOGoObject: newSOGoObject
|
||||||
|
inContainer: newContainer];
|
||||||
|
[newObject autorelease];
|
||||||
|
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
sogoObject = nil;
|
||||||
|
isNew = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self logWithFormat: @"-init"];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithSOGoObject: (id) newSOGoObject
|
||||||
|
inContainer: (MAPIStoreObject *) newContainer
|
||||||
|
{
|
||||||
|
if ((self = [self initInContainer: newContainer]))
|
||||||
|
{
|
||||||
|
ASSIGN (sogoObject, newSOGoObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
// [self logWithFormat: @"-dealloc"];
|
||||||
|
[sogoObject release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setIsNew: (BOOL) newIsNew
|
||||||
|
{
|
||||||
|
isNew = newIsNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isNew
|
||||||
|
{
|
||||||
|
return isNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) sogoObject
|
||||||
|
{
|
||||||
|
return sogoObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MAPIStoreObject *) container
|
||||||
|
{
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) nameInContainer
|
||||||
|
{
|
||||||
|
return [sogoObject nameInContainer];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) cleanupCaches
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* helpers */
|
||||||
|
- (uint64_t) objectId
|
||||||
|
{
|
||||||
|
return [container idForObjectWithKey: [sogoObject nameInContainer]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* getters */
|
||||||
|
- (int) getPidTagDisplayName: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
*data = [[sogoObject displayName] asUnicodeInMemCtx: memCtx];
|
||||||
|
|
||||||
|
return MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getPidTagSearchKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
NSString *stringValue;
|
||||||
|
|
||||||
|
stringValue = [sogoObject nameInContainer];
|
||||||
|
*data = [[stringValue dataUsingEncoding: NSASCIIStringEncoding]
|
||||||
|
asBinaryInMemCtx: memCtx];
|
||||||
|
|
||||||
|
return MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getPidTagGenerateExchangeViews: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
return [self getNo: data inMemCtx: memCtx];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getPidTagParentSourceKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
return [self getReplicaKey: data fromGlobCnt: [container objectId] >> 16
|
||||||
|
inMemCtx: memCtx];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getPidTagSourceKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
return [self getReplicaKey: data fromGlobCnt: [self objectId] >> 16
|
||||||
|
inMemCtx: memCtx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* helper getters */
|
||||||
|
- (int) getPidTagChangeKey: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
uint64_t obVersion;
|
||||||
|
|
||||||
|
obVersion = [self objectVersion];
|
||||||
|
if (obVersion == ULLONG_MAX)
|
||||||
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
||||||
|
else
|
||||||
|
rc = [self getReplicaKey: data fromGlobCnt: obVersion
|
||||||
|
inMemCtx: memCtx];
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getPidTagChangeNumber: (void **) data
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
uint64_t obVersion;
|
||||||
|
|
||||||
|
obVersion = [self objectVersion];
|
||||||
|
if (obVersion == ULLONG_MAX)
|
||||||
|
rc = MAPISTORE_ERR_NOT_FOUND;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*data = MAPILongLongValue (memCtx, ((obVersion << 16)
|
||||||
|
| 0x0001));
|
||||||
|
rc = MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* subclasses */
|
||||||
|
- (uint64_t) objectVersion
|
||||||
|
{
|
||||||
|
[self subclassResponsibility: _cmd];
|
||||||
|
|
||||||
|
return ULLONG_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* logging */
|
||||||
|
- (NSString *) loggingPrefix
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat:@"<%@:%p:%@>",
|
||||||
|
NSStringFromClass (isa), self, [self nameInContainer]];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <talloc.h>
|
#include <talloc.h>
|
||||||
|
|
||||||
#import <Foundation/NSObject.h>
|
#import "NSObject+MAPIStore.h"
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
#include <mapistore/mapistore.h>
|
#include <mapistore/mapistore.h>
|
||||||
|
@ -100,8 +100,6 @@ typedef enum {
|
||||||
- (int) getRowCount: (uint32_t *) countP
|
- (int) getRowCount: (uint32_t *) countP
|
||||||
withQueryType: (enum mapistore_query_type) queryType;
|
withQueryType: (enum mapistore_query_type) queryType;
|
||||||
|
|
||||||
- (void) notifyChangesForChild: (MAPIStoreObject *) child;
|
|
||||||
|
|
||||||
/* helpers */
|
/* helpers */
|
||||||
|
|
||||||
- (SEL) operatorFromRestrictionOperator: (uint32_t) resOp;
|
- (SEL) operatorFromRestrictionOperator: (uint32_t) resOp;
|
||||||
|
|
|
@ -841,8 +841,7 @@ static Class NSDataK, NSStringK;
|
||||||
struct mapistore_property_data *rowData;
|
struct mapistore_property_data *rowData;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
child = [self childAtRowID: rowId
|
child = [self childAtRowID: rowId forQueryType: queryType];
|
||||||
forQueryType: queryType];
|
|
||||||
if (child)
|
if (child)
|
||||||
{
|
{
|
||||||
rowData = talloc_array(memCtx, struct mapistore_property_data, columnsCount);
|
rowData = talloc_array(memCtx, struct mapistore_property_data, columnsCount);
|
||||||
|
@ -874,61 +873,6 @@ static Class NSDataK, NSStringK;
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) notifyChangesForChild: (MAPIStoreObject *) child
|
|
||||||
{
|
|
||||||
NSUInteger currentChildRow, newChildRow;
|
|
||||||
NSArray *list;
|
|
||||||
NSString *childName;
|
|
||||||
struct mapistore_table_notification_parameters notif_parameters;
|
|
||||||
struct mapistore_context *mstoreCtx;
|
|
||||||
|
|
||||||
mstoreCtx = [[container context] connectionInfo]->mstore_ctx;
|
|
||||||
|
|
||||||
notif_parameters.table_type = tableType;
|
|
||||||
notif_parameters.handle = handleId;
|
|
||||||
notif_parameters.folder_id = [container objectId];
|
|
||||||
notif_parameters.object_id = [child objectId];
|
|
||||||
notif_parameters.instance_id = 0; /* TODO: always 0 ? */
|
|
||||||
|
|
||||||
childName = [child nameInContainer];
|
|
||||||
list = [self restrictedChildKeys];
|
|
||||||
currentChildRow = [list indexOfObject: childName];
|
|
||||||
notif_parameters.row_id = currentChildRow;
|
|
||||||
|
|
||||||
[self cleanupCaches];
|
|
||||||
list = [self restrictedChildKeys];
|
|
||||||
newChildRow = [list indexOfObject: childName];
|
|
||||||
|
|
||||||
if (currentChildRow == NSNotFound)
|
|
||||||
{
|
|
||||||
if (newChildRow != NSNotFound)
|
|
||||||
{
|
|
||||||
notif_parameters.row_id = newChildRow;
|
|
||||||
mapistore_push_notification (mstoreCtx,
|
|
||||||
MAPISTORE_TABLE,
|
|
||||||
MAPISTORE_OBJECT_CREATED,
|
|
||||||
¬if_parameters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (newChildRow == NSNotFound)
|
|
||||||
mapistore_push_notification (mstoreCtx,
|
|
||||||
MAPISTORE_TABLE,
|
|
||||||
MAPISTORE_OBJECT_DELETED,
|
|
||||||
¬if_parameters);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* the fact that the row order has changed has no impact here */
|
|
||||||
notif_parameters.row_id = newChildRow;
|
|
||||||
mapistore_push_notification (mstoreCtx,
|
|
||||||
MAPISTORE_TABLE,
|
|
||||||
MAPISTORE_OBJECT_MODIFIED,
|
|
||||||
¬if_parameters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* subclasses */
|
/* subclasses */
|
||||||
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
- (NSString *) backendIdentifierForProperty: (enum MAPITAGS) property
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,8 +91,8 @@
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) getPidTagSubject: (void **) data // SUMMARY
|
- (int) getPidTagNormalizedSubject: (void **) data // SUMMARY
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
{
|
{
|
||||||
iCalToDo *task;
|
iCalToDo *task;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
@class NSMutableDictionary;
|
@class NSMutableDictionary;
|
||||||
@class NSString;
|
@class NSString;
|
||||||
@class NSTimeZone;
|
@class NSTimeZone;
|
||||||
|
@class NSURL;
|
||||||
|
|
||||||
@class WOContext;
|
@class WOContext;
|
||||||
|
|
||||||
|
@ -52,6 +53,9 @@
|
||||||
|
|
||||||
MAPIStoreMapping *mapping;
|
MAPIStoreMapping *mapping;
|
||||||
|
|
||||||
|
BOOL userDbTableExists;
|
||||||
|
NSURL *folderTableURL;
|
||||||
|
|
||||||
WOContext *woContext;
|
WOContext *woContext;
|
||||||
MAPIStoreAuthenticator *authenticator;
|
MAPIStoreAuthenticator *authenticator;
|
||||||
}
|
}
|
||||||
|
@ -71,8 +75,11 @@
|
||||||
|
|
||||||
- (NSDictionary *) rootFolders;
|
- (NSDictionary *) rootFolders;
|
||||||
|
|
||||||
|
- (NSURL *) folderTableURL;
|
||||||
- (MAPIStoreMapping *) mapping;
|
- (MAPIStoreMapping *) mapping;
|
||||||
|
|
||||||
|
- (void) ensureFolderTableExists;
|
||||||
|
|
||||||
/* SOGo hacky magic */
|
/* SOGo hacky magic */
|
||||||
- (void) activateWithUser: (SOGoUser *) activeUser;
|
- (void) activateWithUser: (SOGoUser *) activeUser;
|
||||||
- (MAPIStoreAuthenticator *) authenticator;
|
- (MAPIStoreAuthenticator *) authenticator;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
*
|
||||||
* This file is distributed in the hope that it will be useful,
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
@ -20,20 +20,27 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSData.h>
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSMapTable.h>
|
#import <Foundation/NSMapTable.h>
|
||||||
|
#import <Foundation/NSPropertyList.h>
|
||||||
#import <Foundation/NSThread.h>
|
#import <Foundation/NSThread.h>
|
||||||
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
#import <Foundation/NSURL.h>
|
||||||
|
|
||||||
#import <NGObjWeb/WOContext.h>
|
#import <NGObjWeb/WOContext.h>
|
||||||
#import <NGObjWeb/WOContext+SoObjects.h>
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
|
|
||||||
#import <NGImap4/NGImap4Connection.h>
|
#import <NGImap4/NGImap4Connection.h>
|
||||||
|
|
||||||
|
#import <GDLContentStore/GCSChannelManager.h>
|
||||||
|
#import <SOGo/SOGoDomainDefaults.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import <SOGo/SOGoUserFolder.h>
|
#import <SOGo/SOGoUserFolder.h>
|
||||||
#import <Mailer/SOGoMailAccount.h>
|
#import <Mailer/SOGoMailAccount.h>
|
||||||
#import <Mailer/SOGoMailAccounts.h>
|
#import <Mailer/SOGoMailAccounts.h>
|
||||||
|
|
||||||
|
#import "GCSSpecialQueries+OpenChange.h"
|
||||||
#import "MAPIApplication.h"
|
#import "MAPIApplication.h"
|
||||||
#import "MAPIStoreAuthenticator.h"
|
#import "MAPIStoreAuthenticator.h"
|
||||||
#import "MAPIStoreMapping.h"
|
#import "MAPIStoreMapping.h"
|
||||||
|
@ -80,6 +87,9 @@ static NSMapTable *contextsTable = nil;
|
||||||
|
|
||||||
mapping = nil;
|
mapping = nil;
|
||||||
|
|
||||||
|
userDbTableExists = NO;
|
||||||
|
folderTableURL = nil;
|
||||||
|
|
||||||
authenticator = nil;
|
authenticator = nil;
|
||||||
woContext = [WOContext contextWithRequest: nil];
|
woContext = [WOContext contextWithRequest: nil];
|
||||||
[woContext retain];
|
[woContext retain];
|
||||||
|
@ -88,9 +98,33 @@ static NSMapTable *contextsTable = nil;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *) _readUserPassword: (NSString *) newUsername
|
||||||
|
{
|
||||||
|
NSString *password, *path;
|
||||||
|
NSData *content;
|
||||||
|
|
||||||
|
password = nil;
|
||||||
|
|
||||||
|
path = [NSString stringWithFormat: SAMBA_PRIVATE_DIR
|
||||||
|
@"/mapistore/%@/password", newUsername];
|
||||||
|
|
||||||
|
content = [NSData dataWithContentsOfFile: path];
|
||||||
|
|
||||||
|
if (content)
|
||||||
|
{
|
||||||
|
password = [[NSString alloc] initWithData: content
|
||||||
|
encoding: NSUTF8StringEncoding];
|
||||||
|
[password autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
- (id) initWithUsername: (NSString *) newUsername
|
- (id) initWithUsername: (NSString *) newUsername
|
||||||
andTDBIndexing: (struct tdb_wrap *) indexingTdb
|
andTDBIndexing: (struct tdb_wrap *) indexingTdb
|
||||||
{
|
{
|
||||||
|
NSString *userPassword;
|
||||||
|
|
||||||
if ((self = [self init]))
|
if ((self = [self init]))
|
||||||
{
|
{
|
||||||
/* "username" will be retained by table */
|
/* "username" will be retained by table */
|
||||||
|
@ -102,7 +136,10 @@ static NSMapTable *contextsTable = nil;
|
||||||
authenticator = [MAPIStoreAuthenticator new];
|
authenticator = [MAPIStoreAuthenticator new];
|
||||||
[authenticator setUsername: username];
|
[authenticator setUsername: username];
|
||||||
/* TODO: very hackish (IMAP access) */
|
/* TODO: very hackish (IMAP access) */
|
||||||
[authenticator setPassword: username];
|
userPassword = [self _readUserPassword: newUsername];
|
||||||
|
if ([userPassword length] == 0)
|
||||||
|
userPassword = username;
|
||||||
|
[authenticator setPassword: userPassword];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -117,6 +154,8 @@ static NSMapTable *contextsTable = nil;
|
||||||
[authenticator release];
|
[authenticator release];
|
||||||
[mapping release];
|
[mapping release];
|
||||||
|
|
||||||
|
[folderTableURL release];
|
||||||
|
|
||||||
[sogoUser release];
|
[sogoUser release];
|
||||||
|
|
||||||
[contextsTable removeObjectForKey: username];
|
[contextsTable removeObjectForKey: username];
|
||||||
|
@ -213,6 +252,72 @@ static NSMapTable *contextsTable = nil;
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* OpenChange db table */
|
||||||
|
|
||||||
|
- (NSURL *) folderTableURL
|
||||||
|
{
|
||||||
|
NSString *urlString, *ocFSTableName;
|
||||||
|
NSMutableArray *parts;
|
||||||
|
SOGoUser *user;
|
||||||
|
|
||||||
|
if (!folderTableURL)
|
||||||
|
{
|
||||||
|
user = [self sogoUser];
|
||||||
|
urlString = [[user domainDefaults] folderInfoURL];
|
||||||
|
parts = [[urlString componentsSeparatedByString: @"/"]
|
||||||
|
mutableCopy];
|
||||||
|
[parts autorelease];
|
||||||
|
if ([parts count] == 5)
|
||||||
|
{
|
||||||
|
/* If "OCSFolderInfoURL" is properly configured, we must have 5
|
||||||
|
parts in this url. */
|
||||||
|
ocFSTableName = [NSString stringWithFormat: @"socfs_%@", username];
|
||||||
|
[parts replaceObjectAtIndex: 4 withObject: ocFSTableName];
|
||||||
|
folderTableURL
|
||||||
|
= [NSURL URLWithString: [parts componentsJoinedByString: @"/"]];
|
||||||
|
[folderTableURL retain];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"'OCSFolderInfoURL' is not set"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return folderTableURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) ensureFolderTableExists
|
||||||
|
{
|
||||||
|
GCSChannelManager *cm;
|
||||||
|
EOAdaptorChannel *channel;
|
||||||
|
NSString *tableName, *query;
|
||||||
|
GCSSpecialQueries *queries;
|
||||||
|
|
||||||
|
[self folderTableURL];
|
||||||
|
|
||||||
|
cm = [GCSChannelManager defaultChannelManager];
|
||||||
|
channel = [cm acquireOpenChannelForURL: folderTableURL];
|
||||||
|
|
||||||
|
/* FIXME: make use of [EOChannelAdaptor describeTableNames] instead */
|
||||||
|
tableName = [[folderTableURL path] lastPathComponent];
|
||||||
|
if ([channel evaluateExpressionX:
|
||||||
|
[NSString stringWithFormat: @"SELECT count(*) FROM %@",
|
||||||
|
tableName]])
|
||||||
|
{
|
||||||
|
queries = [channel specialQueries];
|
||||||
|
query = [queries createOpenChangeFSTableWithName: tableName];
|
||||||
|
if ([channel evaluateExpressionX: query])
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"could not create special table '%@'", tableName];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[channel cancelFetch];
|
||||||
|
|
||||||
|
|
||||||
|
[cm releaseChannel: channel];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SOGo context objects */
|
||||||
- (WOContext *) woContext
|
- (WOContext *) woContext
|
||||||
{
|
{
|
||||||
return woContext;
|
return woContext;
|
||||||
|
|
|
@ -1,208 +0,0 @@
|
||||||
/* MAPIStoreVolatileMessage.m - this file is part of SOGo
|
|
||||||
*
|
|
||||||
* Copyright (C) 2011 Inverse inc
|
|
||||||
*
|
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This file is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <Foundation/NSArray.h>
|
|
||||||
#import <Foundation/NSDictionary.h>
|
|
||||||
#import <Foundation/NSString.h>
|
|
||||||
#import <Foundation/NSValue.h>
|
|
||||||
#import <NGExtensions/NGHashMap.h>
|
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
|
||||||
#import <NGExtensions/NSString+Encoding.h>
|
|
||||||
#import <NGMail/NGMimeMessage.h>
|
|
||||||
#import <NGMail/NGMimeMessageGenerator.h>
|
|
||||||
#import <NGImap4/NGImap4Client.h>
|
|
||||||
#import <NGImap4/NGImap4Connection.h>
|
|
||||||
#import <SOGo/NSArray+Utilities.h>
|
|
||||||
#import <SOGo/NSCalendarDate+SOGo.h>
|
|
||||||
#import <SOGo/NSString+Utilities.h>
|
|
||||||
#import <Mailer/SOGoMailFolder.h>
|
|
||||||
#import <Mailer/NSString+Mail.h>
|
|
||||||
|
|
||||||
#import "MAPIStoreContext.h"
|
|
||||||
#import "MAPIStoreMailFolder.h"
|
|
||||||
#import "MAPIStoreMapping.h"
|
|
||||||
#import "MAPIStoreTypes.h"
|
|
||||||
#import "NSData+MAPIStore.h"
|
|
||||||
#import "NSObject+MAPIStore.h"
|
|
||||||
#import "NSString+MAPIStore.h"
|
|
||||||
#import "SOGoMAPIVolatileMessage.h"
|
|
||||||
|
|
||||||
#import "MAPIStoreVolatileMessage.h"
|
|
||||||
|
|
||||||
#undef DEBUG
|
|
||||||
#include <mapistore/mapistore.h>
|
|
||||||
#include <mapistore/mapistore_errors.h>
|
|
||||||
|
|
||||||
Class NSNumberK;
|
|
||||||
|
|
||||||
@implementation MAPIStoreVolatileMessage
|
|
||||||
|
|
||||||
+ (void) initialize
|
|
||||||
{
|
|
||||||
NSNumberK = [NSNumber class];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) init
|
|
||||||
{
|
|
||||||
if ((self = [super init]))
|
|
||||||
{
|
|
||||||
fetchedAttachments = NO;
|
|
||||||
ASSIGN (creationTime, [NSDate date]);
|
|
||||||
lastModificationTime = [creationTime copy];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
[creationTime release];
|
|
||||||
[lastModificationTime release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) addProperties: (NSDictionary *) newProperties
|
|
||||||
{
|
|
||||||
[super addProperties: newProperties];
|
|
||||||
[sogoObject appendProperties: properties];
|
|
||||||
[properties removeAllObjects];
|
|
||||||
ASSIGN (lastModificationTime, [NSDate date]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
|
|
||||||
{
|
|
||||||
return ([super canGetProperty: propTag]
|
|
||||||
|| [[sogoObject properties] objectForKey: MAPIPropertyKey (propTag)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (uint64_t) objectVersion
|
|
||||||
{
|
|
||||||
NSNumber *version;
|
|
||||||
|
|
||||||
version = [[sogoObject properties] objectForKey: @"version"];
|
|
||||||
|
|
||||||
return (version
|
|
||||||
? exchange_globcnt ([version unsignedLongLongValue])
|
|
||||||
: ULLONG_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getProperty: (void **) data
|
|
||||||
withTag: (enum MAPITAGS) propTag
|
|
||||||
inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
id value;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
value = [[sogoObject properties] objectForKey: MAPIPropertyKey (propTag)];
|
|
||||||
if (value)
|
|
||||||
rc = [value getValue: data forTag: propTag inMemCtx: memCtx];
|
|
||||||
else
|
|
||||||
rc = [super getProperty: data withTag: propTag inMemCtx: memCtx];
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagSubject: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
/* if we get here, it means that the properties file didn't contain a
|
|
||||||
relevant value */
|
|
||||||
return [self getEmptyString: data inMemCtx: memCtx];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagMessageClass: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
*data = [@"IPM.Note" asUnicodeInMemCtx: memCtx];
|
|
||||||
|
|
||||||
return MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (int) getPidTagChangeKey: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
|
||||||
{
|
|
||||||
NSData *changeKey;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
changeKey = [[sogoObject properties]
|
|
||||||
objectForKey: MAPIPropertyKey (PR_CHANGE_KEY)];
|
|
||||||
if (changeKey)
|
|
||||||
{
|
|
||||||
*data = [changeKey asBinaryInMemCtx: memCtx];
|
|
||||||
rc = MAPISTORE_SUCCESS;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = [super getPidTagChangeKey: data inMemCtx: memCtx];
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) attachmentsKeysMatchingQualifier: (EOQualifier *) qualifier
|
|
||||||
andSortOrderings: (NSArray *) sortOrderings
|
|
||||||
{
|
|
||||||
NSDictionary *attachments;
|
|
||||||
NSArray *keys;
|
|
||||||
NSString *key, *newKey;
|
|
||||||
NSUInteger count, max, aid;
|
|
||||||
MAPIStoreAttachment *attachment;
|
|
||||||
|
|
||||||
if (!fetchedAttachments)
|
|
||||||
{
|
|
||||||
attachments = [[sogoObject properties] objectForKey: @"attachments"];
|
|
||||||
keys = [attachments allKeys];
|
|
||||||
max = [keys count];
|
|
||||||
if (max > 0)
|
|
||||||
{
|
|
||||||
aid = [keys count];
|
|
||||||
for (count = 0; count < max; count++)
|
|
||||||
{
|
|
||||||
key = [keys objectAtIndex: count];
|
|
||||||
attachment = [attachments objectForKey: key];
|
|
||||||
newKey = [NSString stringWithFormat: @"%ul", (aid + count)];
|
|
||||||
[attachmentParts setObject: attachment forKey: newKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fetchedAttachments = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [super attachmentKeysMatchingQualifier: qualifier
|
|
||||||
andSortOrderings: sortOrderings];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSDate *) creationTime
|
|
||||||
{
|
|
||||||
return creationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSDate *) lastModificationTime
|
|
||||||
{
|
|
||||||
return lastModificationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) lookupAttachment: (NSString *) childKey
|
|
||||||
{
|
|
||||||
return [attachmentParts objectForKey: childKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) save
|
|
||||||
{
|
|
||||||
[self subclassResponsibility: _cmd];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -25,9 +25,11 @@
|
||||||
|
|
||||||
#import <Foundation/NSDate.h>
|
#import <Foundation/NSDate.h>
|
||||||
|
|
||||||
|
@class NSCalendarDate;
|
||||||
|
|
||||||
@interface NSDate (MAPIStoreDataTypes)
|
@interface NSDate (MAPIStoreDataTypes)
|
||||||
|
|
||||||
+ (id) dateFromMinutesSince1601: (uint32_t) minutes;
|
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes;
|
||||||
- (uint32_t) asMinutesSince1601;
|
- (uint32_t) asMinutesSince1601;
|
||||||
|
|
||||||
+ (id) dateFromFileTime: (const struct FILETIME *) timeValue;
|
+ (id) dateFromFileTime: (const struct FILETIME *) timeValue;
|
||||||
|
@ -37,4 +39,6 @@
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NSComparisonResult NSDateCompare (id date1, id date2, void *);
|
||||||
|
|
||||||
#endif /* NSCALENDARDATE+MAPISTORE_H */
|
#endif /* NSCALENDARDATE+MAPISTORE_H */
|
||||||
|
|
|
@ -51,7 +51,7 @@ _setupRefDate ()
|
||||||
timeZone: [NSTimeZone timeZoneWithName: @"UTC"]];
|
timeZone: [NSTimeZone timeZoneWithName: @"UTC"]];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) dateFromMinutesSince1601: (uint32_t) minutes
|
+ (NSCalendarDate *) dateFromMinutesSince1601: (uint32_t) minutes
|
||||||
{
|
{
|
||||||
NSCalendarDate *result;
|
NSCalendarDate *result;
|
||||||
|
|
||||||
|
@ -129,3 +129,22 @@ _setupRefDate ()
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NSComparisonResult
|
||||||
|
NSDateCompare (id date1, id date2, void *ctx)
|
||||||
|
{
|
||||||
|
NSTimeInterval secs1, secs2;
|
||||||
|
NSComparisonResult result;
|
||||||
|
|
||||||
|
secs1 = [date1 timeIntervalSince1970];
|
||||||
|
secs2 = [date2 timeIntervalSince1970];
|
||||||
|
if (secs1 == secs2)
|
||||||
|
result = NSOrderedSame;
|
||||||
|
else if (secs1 < secs2)
|
||||||
|
result = NSOrderedAscending;
|
||||||
|
else
|
||||||
|
result = NSOrderedDescending;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,11 @@
|
||||||
#import <Foundation/NSObject.h>
|
#import <Foundation/NSObject.h>
|
||||||
|
|
||||||
#include <talloc.h>
|
#include <talloc.h>
|
||||||
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
|
||||||
struct MAPIStoreTallocWrapper
|
struct MAPIStoreTallocWrapper
|
||||||
{
|
{
|
||||||
id MAPIStoreSOGoObject;
|
id instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
@interface NSObject (MAPIStoreTallocHelpers)
|
@interface NSObject (MAPIStoreTallocHelpers)
|
||||||
|
@ -49,6 +50,7 @@ struct MAPIStoreTallocWrapper
|
||||||
- (int) getLongZero: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
|
- (int) getLongZero: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (int) getYes: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
|
- (int) getYes: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
- (int) getNo: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
|
- (int) getNo: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (int) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -58,4 +60,17 @@ struct MAPIStoreTallocWrapper
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface NSObject (MAPIStoreProperties)
|
||||||
|
|
||||||
|
+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
+ (void) fillAvailableProperties: (struct SPropTagArray *) properties
|
||||||
|
withExclusions: (BOOL *) exclusions;
|
||||||
|
|
||||||
|
- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
- (BOOL) canGetProperty: (enum MAPITAGS) propTag;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
#endif /* NSOBJECT_MAPISTORE_H */
|
#endif /* NSOBJECT_MAPISTORE_H */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#import <Foundation/NSThread.h>
|
#import <Foundation/NSThread.h>
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
|
#import "MAPIStorePropertySelectors.h"
|
||||||
#import "MAPIStoreTypes.h"
|
#import "MAPIStoreTypes.h"
|
||||||
#import "NSArray+MAPIStore.h"
|
#import "NSArray+MAPIStore.h"
|
||||||
#import "NSData+MAPIStore.h"
|
#import "NSData+MAPIStore.h"
|
||||||
|
@ -50,7 +51,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
wrapper = data;
|
wrapper = data;
|
||||||
// NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject);
|
// NSLog (@"destroying wrapped object (wrapper: %p; object: %p)...\n", wrapper, wrapper->MAPIStoreSOGoObject);
|
||||||
[wrapper->MAPIStoreSOGoObject release];
|
[wrapper->instance release];
|
||||||
[pool release];
|
[pool release];
|
||||||
GSUnregisterCurrentThread ();
|
GSUnregisterCurrentThread ();
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
||||||
|
|
||||||
wrapper = talloc_zero (tallocCtx, struct MAPIStoreTallocWrapper);
|
wrapper = talloc_zero (tallocCtx, struct MAPIStoreTallocWrapper);
|
||||||
talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy);
|
talloc_set_destructor ((void *) wrapper, MAPIStoreTallocWrapperDestroy);
|
||||||
wrapper->MAPIStoreSOGoObject = self;
|
wrapper->instance = self;
|
||||||
[self retain];
|
[self retain];
|
||||||
// NSLog (@"returning wrapper: %p; object: %p", wrapper, self);
|
// NSLog (@"returning wrapper: %p; object: %p", wrapper, self);
|
||||||
|
|
||||||
|
@ -167,4 +168,104 @@ MAPIStoreTallocWrapperDestroy (void *data)
|
||||||
return MAPISTORE_SUCCESS;
|
return MAPISTORE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (int) getSMTPAddrType: (void **) data inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
*data = [@"SMTP" asUnicodeInMemCtx: memCtx];
|
||||||
|
|
||||||
|
return MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSObject (MAPIStoreProperties)
|
||||||
|
|
||||||
|
+ (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
struct SPropTagArray *properties;
|
||||||
|
const MAPIStorePropertyGetter *classGetters;
|
||||||
|
NSUInteger count;
|
||||||
|
enum MAPITAGS propTag;
|
||||||
|
uint16_t propValue;
|
||||||
|
|
||||||
|
properties = talloc_zero (memCtx, struct SPropTagArray);
|
||||||
|
properties->aulPropTag = talloc_array (properties, enum MAPITAGS,
|
||||||
|
MAPIStoreSupportedPropertiesCount);
|
||||||
|
classGetters = MAPIStorePropertyGettersForClass (self);
|
||||||
|
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
|
||||||
|
{
|
||||||
|
propTag = MAPIStoreSupportedProperties[count];
|
||||||
|
propValue = (propTag & 0xffff0000) >> 16;
|
||||||
|
if (classGetters[propValue])
|
||||||
|
{
|
||||||
|
properties->aulPropTag[properties->cValues] = propTag;
|
||||||
|
properties->cValues++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*propertiesP = properties;
|
||||||
|
|
||||||
|
return MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void) fillAvailableProperties: (struct SPropTagArray *) properties
|
||||||
|
withExclusions: (BOOL *) exclusions
|
||||||
|
{
|
||||||
|
TALLOC_CTX *localMemCtx;
|
||||||
|
struct SPropTagArray *subProperties;
|
||||||
|
uint16_t propId;
|
||||||
|
NSUInteger count;
|
||||||
|
|
||||||
|
localMemCtx = talloc_zero (NULL, TALLOC_CTX);
|
||||||
|
[self getAvailableProperties: &subProperties inMemCtx: localMemCtx];
|
||||||
|
for (count = 0; count < subProperties->cValues; count++)
|
||||||
|
{
|
||||||
|
propId = (subProperties->aulPropTag[count] >> 16);
|
||||||
|
if (!exclusions[propId])
|
||||||
|
{
|
||||||
|
properties->aulPropTag[properties->cValues]
|
||||||
|
= subProperties->aulPropTag[count];
|
||||||
|
properties->cValues++;
|
||||||
|
exclusions[propId] = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
talloc_free (localMemCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (enum mapistore_error) getAvailableProperties: (struct SPropTagArray **) propertiesP
|
||||||
|
inMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
NSUInteger count;
|
||||||
|
struct SPropTagArray *availableProps;
|
||||||
|
enum MAPITAGS propTag;
|
||||||
|
|
||||||
|
availableProps = talloc_zero (memCtx, struct SPropTagArray);
|
||||||
|
availableProps->aulPropTag = talloc_array (availableProps, enum MAPITAGS,
|
||||||
|
MAPIStoreSupportedPropertiesCount);
|
||||||
|
for (count = 0; count < MAPIStoreSupportedPropertiesCount; count++)
|
||||||
|
{
|
||||||
|
propTag = MAPIStoreSupportedProperties[count];
|
||||||
|
if ([self canGetProperty: propTag])
|
||||||
|
{
|
||||||
|
availableProps->aulPropTag[availableProps->cValues] = propTag;
|
||||||
|
availableProps->cValues++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*propertiesP = availableProps;
|
||||||
|
|
||||||
|
return MAPISTORE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) canGetProperty: (enum MAPITAGS) propTag
|
||||||
|
{
|
||||||
|
uint16_t propValue;
|
||||||
|
const IMP *classGetters;
|
||||||
|
|
||||||
|
classGetters = (IMP *) MAPIStorePropertyGettersForClass (isa);
|
||||||
|
propValue = (propTag & 0xffff0000) >> 16;
|
||||||
|
|
||||||
|
return (classGetters[propValue] != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
182
OpenChange/NSObject+PropertyList.m
Normal file
182
OpenChange/NSObject+PropertyList.m
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
/* dbmsgdump.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* A format-agnostic property list dumper.
|
||||||
|
Usage: dbmsgdump [filename] */
|
||||||
|
|
||||||
|
#import <Foundation/NSAutoreleasePool.h>
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSData.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSProcessInfo.h>
|
||||||
|
#import <Foundation/NSPropertyList.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
#import <Foundation/NSValue.h>
|
||||||
|
#import <NGExtensions/NSNull+misc.h>
|
||||||
|
|
||||||
|
const char *indentationStep = " ";
|
||||||
|
|
||||||
|
@interface NSObject (plext)
|
||||||
|
|
||||||
|
- (void) displayWithIndentation: (NSInteger) anInt;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSObject (plext)
|
||||||
|
|
||||||
|
- (void) _outputIndentation: (NSInteger) anInt
|
||||||
|
{
|
||||||
|
NSInteger i;
|
||||||
|
|
||||||
|
for (i = 0; i < anInt; i++)
|
||||||
|
printf ("%s", indentationStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) displayWithIndentation: (NSInteger) anInt
|
||||||
|
{
|
||||||
|
printf ("(%s) %s",
|
||||||
|
[NSStringFromClass (isa) UTF8String],
|
||||||
|
[[self description] UTF8String]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSDictionary (plext)
|
||||||
|
|
||||||
|
- (void) displayKey: (NSString *) key
|
||||||
|
withIndentation: (NSInteger) anInt
|
||||||
|
{
|
||||||
|
[self _outputIndentation: anInt];
|
||||||
|
|
||||||
|
printf ("%s ", [[key description] UTF8String]);
|
||||||
|
if ([key isKindOfClass: [NSValue class]])
|
||||||
|
printf ("(%s: 0x%.8x) ", [(NSValue *) key objCType], [key intValue]);
|
||||||
|
|
||||||
|
printf ("= ");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) displayWithIndentation: (NSInteger) anInt
|
||||||
|
{
|
||||||
|
NSUInteger i, max;
|
||||||
|
NSArray *keys;
|
||||||
|
NSInteger subIndent;
|
||||||
|
NSString *key;
|
||||||
|
|
||||||
|
keys = [self allKeys];
|
||||||
|
max = [keys count];
|
||||||
|
|
||||||
|
printf ("{ (%ld) items\n", (long) max);
|
||||||
|
|
||||||
|
subIndent = anInt + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
key = [keys objectAtIndex: i];
|
||||||
|
[self displayKey: key withIndentation: subIndent];
|
||||||
|
[[self objectForKey: key] displayWithIndentation: subIndent];
|
||||||
|
if (i < (max - 1))
|
||||||
|
printf (",");
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
[self _outputIndentation: anInt];
|
||||||
|
printf ("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSArray (plext)
|
||||||
|
|
||||||
|
- (void) displayCount: (NSUInteger) count
|
||||||
|
withIndentation: (NSInteger) anInt
|
||||||
|
{
|
||||||
|
[self _outputIndentation: anInt];
|
||||||
|
printf ("%lu = ", (unsigned long) count);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) displayWithIndentation: (NSInteger) anInt
|
||||||
|
{
|
||||||
|
NSUInteger i, max;
|
||||||
|
NSInteger subIndent;
|
||||||
|
|
||||||
|
max = [self count];
|
||||||
|
|
||||||
|
printf ("[ (%ld) items\n", (long) max);
|
||||||
|
|
||||||
|
subIndent = anInt + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
[self displayCount: i withIndentation: subIndent];
|
||||||
|
[[self objectAtIndex: i] displayWithIndentation: subIndent];
|
||||||
|
if (i < (max - 1))
|
||||||
|
printf (",");
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
[self _outputIndentation: anInt];
|
||||||
|
printf ("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
static void
|
||||||
|
OCDumpPListData (NSData *content)
|
||||||
|
{
|
||||||
|
NSDictionary *d;
|
||||||
|
NSPropertyListFormat format;
|
||||||
|
NSString *error = nil;
|
||||||
|
const char *formatName;
|
||||||
|
|
||||||
|
d = [NSPropertyListSerialization propertyListFromData: content
|
||||||
|
mutabilityOption: NSPropertyListImmutable
|
||||||
|
format: &format
|
||||||
|
errorDescription: &error];
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case NSPropertyListOpenStepFormat:
|
||||||
|
formatName = "OpenStep";
|
||||||
|
break;
|
||||||
|
case NSPropertyListXMLFormat_v1_0:
|
||||||
|
formatName = "XML";
|
||||||
|
break;
|
||||||
|
case NSPropertyListBinaryFormat_v1_0:
|
||||||
|
formatName = "Binary";
|
||||||
|
break;
|
||||||
|
case NSPropertyListGNUstepFormat:
|
||||||
|
formatName = "GNUstep";
|
||||||
|
break;
|
||||||
|
case NSPropertyListGNUstepBinaryFormat:
|
||||||
|
formatName = "GNUstep binary";
|
||||||
|
break;
|
||||||
|
default: formatName = "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("File format is: %s\n", formatName);
|
||||||
|
[d displayWithIndentation: 0];
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf ("an error occurred: %s\n", [error UTF8String]);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/* SOGoMAPIFSFolder.h - this file is part of SOGo
|
/* SOGoMAPIDBFolder.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Inverse inc.
|
* Copyright (C) 2012 Inverse inc.
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,41 +20,40 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SOGOMAPIFSFOLDER_H
|
#ifndef SOGOMAPIDBFOLDER_H
|
||||||
#define SOGOMAPIFSFOLDER_H
|
#define SOGOMAPIDBFOLDER_H
|
||||||
|
|
||||||
#import <SOGo/SOGoFolder.h>
|
#import "SOGoMAPIDBObject.h"
|
||||||
|
|
||||||
@class NSArray;
|
@class NSArray;
|
||||||
|
@class NSMutableString;
|
||||||
@class NSString;
|
@class NSString;
|
||||||
@class NSURL;
|
@class NSURL;
|
||||||
|
|
||||||
@class EOQualifier;
|
@class EOQualifier;
|
||||||
|
|
||||||
@class SOGoMAPIFSMessage;
|
@class SOGoMAPIDBMessage;
|
||||||
|
|
||||||
@interface SOGoMAPIFSFolder : SOGoFolder
|
@interface SOGoMAPIDBFolder : SOGoMAPIDBObject
|
||||||
{
|
{
|
||||||
NSString *directory;
|
NSString *pathPrefix; /* for root folders */
|
||||||
BOOL directoryIsSane;
|
SOGoMAPIDBObject *aclMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id) folderWithURL: (NSURL *) url
|
- (void) setPathPrefix: (NSString *) newPathPrefix;
|
||||||
andTableType: (uint8_t) tableType;
|
|
||||||
- (id) initWithURL: (NSURL *) url
|
|
||||||
andTableType: (uint8_t) tableType;
|
|
||||||
|
|
||||||
- (NSString *) directory;
|
- (NSMutableString *) pathForChild: (NSString *) childName;
|
||||||
|
|
||||||
- (SOGoMAPIFSMessage *) newMessage;
|
- (NSArray *) toOneRelationshipKeys;
|
||||||
- (void) ensureDirectory;
|
- (NSArray *) toManyRelationshipKeys;
|
||||||
|
|
||||||
- (NSCalendarDate *) creationTime;
|
- (NSArray *) childKeysOfType: (MAPIDBObjectType) type
|
||||||
- (NSCalendarDate *) lastModificationTime;
|
includeDeleted: (BOOL) includeDeleted
|
||||||
|
matchingQualifier: (EOQualifier *) qualifier
|
||||||
|
andSortOrderings: (NSArray *) sortOrderings;
|
||||||
|
|
||||||
- (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
|
- (void) changePathTo: (NSString *) newPath;
|
||||||
andSortOrderings: (NSArray *) sortOrderings;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* SOGOMAPIFSFOLDER_H */
|
#endif /* SOGOMAPIDBFOLDER_H */
|
452
OpenChange/SOGoMAPIDBFolder.m
Normal file
452
OpenChange/SOGoMAPIDBFolder.m
Normal file
|
@ -0,0 +1,452 @@
|
||||||
|
/* SOGoMAPIDBFolder.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc.
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSData.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSException.h>
|
||||||
|
#import <Foundation/NSPropertyList.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
#import <Foundation/NSValue.h>
|
||||||
|
#import <Foundation/NSURL.h>
|
||||||
|
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <NGExtensions/NSNull+misc.h>
|
||||||
|
#import <GDLAccess/EOAdaptorChannel.h>
|
||||||
|
#import <GDLContentStore/GCSChannelManager.h>
|
||||||
|
// #import <GDLContentStore/EOQualifier+GCS.m>
|
||||||
|
|
||||||
|
#import <SOGo/NSArray+Utilities.h>
|
||||||
|
#import <SOGo/NSString+Utilities.h>
|
||||||
|
#import <SOGo/SOGoDomainDefaults.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
#import "EOQualifier+MAPI.h"
|
||||||
|
#import "GCSSpecialQueries+OpenChange.h"
|
||||||
|
#import "SOGoMAPIDBMessage.h"
|
||||||
|
|
||||||
|
#import "SOGoMAPIDBFolder.h"
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <talloc.h>
|
||||||
|
#include <util/time.h>
|
||||||
|
#include <mapistore/mapistore.h>
|
||||||
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
#include <libmapiproxy.h>
|
||||||
|
#include <param.h>
|
||||||
|
|
||||||
|
Class SOGoMAPIDBObjectK = Nil;
|
||||||
|
|
||||||
|
@implementation SOGoMAPIDBFolder
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
SOGoMAPIDBObjectK = [SOGoMAPIDBObject class];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
pathPrefix = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initWithName: (NSString *) name inContainer: (id) newContainer
|
||||||
|
{
|
||||||
|
if ((self = [super initWithName: name inContainer: newContainer]))
|
||||||
|
{
|
||||||
|
objectType = MAPIDBObjectTypeFolder;
|
||||||
|
aclMessage = [SOGoMAPIDBObject objectWithName: @"permissions"
|
||||||
|
inContainer: self];
|
||||||
|
[aclMessage setObjectType: MAPIDBObjectTypeInternal];
|
||||||
|
[aclMessage retain];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[aclMessage release];
|
||||||
|
[pathPrefix release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isFolderish
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setPathPrefix: (NSString *) newPathPrefix
|
||||||
|
{
|
||||||
|
ASSIGN (pathPrefix, newPathPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableString *) pathForChild: (NSString *) childName
|
||||||
|
{
|
||||||
|
NSMutableString *path;
|
||||||
|
|
||||||
|
path = [self path];
|
||||||
|
[path appendFormat: @"/%@", childName];
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableString *) path
|
||||||
|
{
|
||||||
|
NSMutableString *path;
|
||||||
|
|
||||||
|
path = [super path];
|
||||||
|
if (pathPrefix)
|
||||||
|
[path insertString: pathPrefix atIndex: 0];
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - (SOGoMAPIDBMessage *) newMessage
|
||||||
|
// {
|
||||||
|
// NSString *newFilename;
|
||||||
|
|
||||||
|
// newFilename = [NSString stringWithFormat: @"%@.plist",
|
||||||
|
// [SOGoObject globallyUniqueObjectId]];
|
||||||
|
|
||||||
|
// return [SOGoMAPIDBMessage objectWithName: filename inContainer: self];
|
||||||
|
// }
|
||||||
|
|
||||||
|
- (NSArray *) childKeysOfType: (MAPIDBObjectType) type
|
||||||
|
includeDeleted: (BOOL) includeDeleted
|
||||||
|
matchingQualifier: (EOQualifier *) qualifier
|
||||||
|
andSortOrderings: (NSArray *) sortOrderings
|
||||||
|
{
|
||||||
|
NSMutableArray *childKeys;
|
||||||
|
NSMutableString *sql// , *qualifierClause
|
||||||
|
;
|
||||||
|
NSString *childPathPrefix, *childPath, *childKey;
|
||||||
|
NSMutableArray *whereClause;
|
||||||
|
NSArray *records;
|
||||||
|
NSDictionary *record;
|
||||||
|
NSUInteger childPathPrefixLen, count, max;
|
||||||
|
SOGoMAPIDBObject *currentChild;
|
||||||
|
|
||||||
|
/* query construction */
|
||||||
|
sql = [NSMutableString stringWithCapacity: 256];
|
||||||
|
[sql appendFormat: @"SELECT * FROM %@", [self tableName]];
|
||||||
|
|
||||||
|
whereClause = [NSMutableArray arrayWithCapacity: 2];
|
||||||
|
[whereClause addObject: [NSString stringWithFormat: @"c_parent_path = '%@'",
|
||||||
|
[self path]]];
|
||||||
|
[whereClause addObject: [NSString stringWithFormat: @"c_type = %d", type]];
|
||||||
|
if (!includeDeleted)
|
||||||
|
[whereClause addObject: @"c_deleted = 0"];
|
||||||
|
|
||||||
|
[sql appendFormat: @" WHERE %@",
|
||||||
|
[whereClause componentsJoinedByString: @" AND "]];
|
||||||
|
|
||||||
|
childPathPrefix = [NSString stringWithFormat: @"%@/", [self path]];
|
||||||
|
|
||||||
|
/* results */
|
||||||
|
records = [self performSQLQuery: sql];
|
||||||
|
if (records)
|
||||||
|
{
|
||||||
|
max = [records count];
|
||||||
|
childKeys = [NSMutableArray arrayWithCapacity: max];
|
||||||
|
childPathPrefixLen = [childPathPrefix length];
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
record = [records objectAtIndex: count];
|
||||||
|
childPath = [record objectForKey: @"c_path"];
|
||||||
|
childKey = [childPath substringFromIndex: childPathPrefixLen];
|
||||||
|
if ([childKey rangeOfString: @"/"].location == NSNotFound)
|
||||||
|
{
|
||||||
|
if (qualifier)
|
||||||
|
{
|
||||||
|
currentChild = [SOGoMAPIDBObject objectWithName: childKey
|
||||||
|
inContainer: self];
|
||||||
|
[currentChild setupFromRecord: record];
|
||||||
|
if ([qualifier evaluateSOGoMAPIDBObject: currentChild])
|
||||||
|
[childKeys addObject: childKey];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[childKeys addObject: childKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
childKeys = nil;
|
||||||
|
|
||||||
|
return childKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) toManyRelationshipKeys
|
||||||
|
{
|
||||||
|
return [self childKeysOfType: MAPIDBObjectTypeFolder
|
||||||
|
includeDeleted: NO
|
||||||
|
matchingQualifier: nil
|
||||||
|
andSortOrderings: nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) toOneRelationshipKeys
|
||||||
|
{
|
||||||
|
return [self childKeysOfType: MAPIDBObjectTypeMessage
|
||||||
|
includeDeleted: NO
|
||||||
|
matchingQualifier: nil
|
||||||
|
andSortOrderings: nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) changePathTo: (NSString *) newPath
|
||||||
|
{
|
||||||
|
NSMutableString *sql// , *qualifierClause
|
||||||
|
;
|
||||||
|
NSString *oldPath, *oldPathAsPrefix, *path, *parentPath;
|
||||||
|
NSMutableArray *queries;
|
||||||
|
NSArray *records;
|
||||||
|
NSDictionary *record;
|
||||||
|
NSUInteger count, max;
|
||||||
|
|
||||||
|
/* change the paths in children records */
|
||||||
|
oldPath = [self path];
|
||||||
|
oldPathAsPrefix = [NSString stringWithFormat: @"%@/", oldPath];
|
||||||
|
|
||||||
|
sql = [NSMutableString stringWithFormat:
|
||||||
|
@"SELECT c_path, c_parent_path FROM %@"
|
||||||
|
@" WHERE c_path LIKE '%@%%'",
|
||||||
|
[self tableName], oldPathAsPrefix];
|
||||||
|
records = [self performSQLQuery: sql];
|
||||||
|
max = [records count];
|
||||||
|
queries = [NSMutableArray arrayWithCapacity: max + 1];
|
||||||
|
if (max > 0)
|
||||||
|
{
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
record = [records objectAtIndex: count];
|
||||||
|
path = [record objectForKey: @"c_path"];
|
||||||
|
sql = [NSMutableString stringWithFormat: @"UPDATE %@"
|
||||||
|
@" SET c_path = '%@'",
|
||||||
|
[self tableName],
|
||||||
|
[path stringByReplacingPrefix: oldPath
|
||||||
|
withPrefix: newPath]];
|
||||||
|
parentPath = [record objectForKey: @"c_parent_path"];
|
||||||
|
if ([parentPath isNotNull])
|
||||||
|
[sql appendFormat: @", c_parent_path = '%@'",
|
||||||
|
[parentPath stringByReplacingPrefix: oldPath
|
||||||
|
withPrefix: newPath]];
|
||||||
|
[sql appendFormat: @" WHERE c_path = '%@'", path];
|
||||||
|
[queries addObject: sql];
|
||||||
|
}
|
||||||
|
[self performBatchSQLQueries: queries];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* change the path in this folder record */
|
||||||
|
[super changePathTo: newPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
// - (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
|
||||||
|
// andSortOrderings: (NSArray *) sortOrderings
|
||||||
|
// {
|
||||||
|
// NSArray *allKeys;
|
||||||
|
// NSMutableArray *keys;
|
||||||
|
// NSUInteger count, max;
|
||||||
|
// NSString *messageKey;
|
||||||
|
// SOGoMAPIDBMessage *message;
|
||||||
|
|
||||||
|
// if (sortOrderings)
|
||||||
|
// [self warnWithFormat: @"sorting is not handled yet"];
|
||||||
|
|
||||||
|
// allKeys = [self toOneRelationshipKeys];
|
||||||
|
// if (qualifier)
|
||||||
|
// {
|
||||||
|
// [self logWithFormat: @"%s: getting restricted FAI keys", __PRETTY_FUNCTION__];
|
||||||
|
// max = [allKeys count];
|
||||||
|
// keys = [NSMutableArray arrayWithCapacity: max];
|
||||||
|
// for (count = 0; count < max; count++)
|
||||||
|
// {
|
||||||
|
// messageKey = [allKeys objectAtIndex: count];
|
||||||
|
// message = [self lookupName: messageKey
|
||||||
|
// inContext: nil
|
||||||
|
// acquire: NO];
|
||||||
|
// if ([qualifier evaluateMAPIVolatileMessage: message])
|
||||||
|
// [keys addObject: messageKey];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// keys = (NSMutableArray *) allKeys;
|
||||||
|
|
||||||
|
// return keys;
|
||||||
|
// }
|
||||||
|
|
||||||
|
- (id) lookupName: (NSString *) childName
|
||||||
|
inContext: (WOContext *) woContext
|
||||||
|
acquire: (BOOL) acquire
|
||||||
|
{
|
||||||
|
id object;
|
||||||
|
Class objectClass;
|
||||||
|
NSString *childPath;
|
||||||
|
NSDictionary *record;
|
||||||
|
|
||||||
|
childPath = [self pathForChild: childName];
|
||||||
|
record = [self lookupRecord: childPath newerThanVersion: -1];
|
||||||
|
if (record)
|
||||||
|
{
|
||||||
|
if ([[record objectForKey: @"c_type"] intValue] == MAPIDBObjectTypeFolder)
|
||||||
|
objectClass = isa;
|
||||||
|
else
|
||||||
|
objectClass = SOGoMAPIDBObjectK;
|
||||||
|
|
||||||
|
object = [objectClass objectWithName: childName
|
||||||
|
inContainer: self];
|
||||||
|
[object setupFromRecord: record];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
object = nil;
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) lookupFolder: (NSString *) folderName
|
||||||
|
inContext: (WOContext *) woContext
|
||||||
|
{
|
||||||
|
id object;
|
||||||
|
|
||||||
|
object = [SOGoMAPIDBFolder objectWithName: folderName
|
||||||
|
inContainer: self];
|
||||||
|
[object reloadIfNeeded];
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - (id) _fileAttributeForKey: (NSString *) key
|
||||||
|
// {
|
||||||
|
// NSDictionary *attributes;
|
||||||
|
|
||||||
|
// attributes = [[NSFileManager defaultManager]
|
||||||
|
// fileAttributesAtPath: directory
|
||||||
|
// traverseLink: NO];
|
||||||
|
|
||||||
|
// return [attributes objectForKey: key];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// - (NSCalendarDate *) creationTime
|
||||||
|
// {
|
||||||
|
// return [self _fileAttributeForKey: NSFileCreationDate];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// - (NSCalendarDate *) lastModificationTime
|
||||||
|
// {
|
||||||
|
// return [self _fileAttributeForKey: NSFileModificationDate];
|
||||||
|
// }
|
||||||
|
|
||||||
|
- (NSException *) delete
|
||||||
|
{
|
||||||
|
[self notImplemented: _cmd];
|
||||||
|
|
||||||
|
// NSFileManager *fm;
|
||||||
|
// NSException *error;
|
||||||
|
|
||||||
|
// fm = [NSFileManager defaultManager];
|
||||||
|
|
||||||
|
// if (![fm removeFileAtPath: directory handler: NULL])
|
||||||
|
// error = [NSException exceptionWithName: @"MAPIStoreIOException"
|
||||||
|
// reason: @"could not delete folder"
|
||||||
|
// userInfo: nil];
|
||||||
|
// else
|
||||||
|
// error = nil;
|
||||||
|
|
||||||
|
// return error;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* acl */
|
||||||
|
- (NSString *) defaultUserID
|
||||||
|
{
|
||||||
|
return @"default";
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableDictionary *) _aclEntries
|
||||||
|
{
|
||||||
|
NSMutableDictionary *aclEntries;
|
||||||
|
|
||||||
|
[aclMessage reloadIfNeeded];
|
||||||
|
aclEntries = [aclMessage properties];
|
||||||
|
if (![aclEntries objectForKey: @"users"])
|
||||||
|
[aclEntries setObject: [NSMutableArray array] forKey: @"users"];
|
||||||
|
if (![aclEntries objectForKey: @"entries"])
|
||||||
|
[aclEntries setObject: [NSMutableDictionary dictionary]
|
||||||
|
forKey: @"entries"];
|
||||||
|
|
||||||
|
return aclEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) addUserInAcls: (NSString *) user
|
||||||
|
{
|
||||||
|
NSMutableDictionary *acl;
|
||||||
|
NSMutableArray *users;
|
||||||
|
|
||||||
|
acl = [self _aclEntries];
|
||||||
|
users = [acl objectForKey: @"users"];
|
||||||
|
[users addObjectUniquely: user];
|
||||||
|
[aclMessage save];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) removeAclsForUsers: (NSArray *) oldUsers
|
||||||
|
{
|
||||||
|
NSDictionary *acl;
|
||||||
|
NSMutableDictionary *entries;
|
||||||
|
NSMutableArray *users;
|
||||||
|
|
||||||
|
acl = [self _aclEntries];
|
||||||
|
entries = [acl objectForKey: @"entries"];
|
||||||
|
[entries removeObjectsForKeys: oldUsers];
|
||||||
|
users = [acl objectForKey: @"users"];
|
||||||
|
[users removeObjectsInArray: oldUsers];
|
||||||
|
[aclMessage save];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) aclUsers
|
||||||
|
{
|
||||||
|
return [[self _aclEntries] objectForKey: @"users"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) aclsForUser: (NSString *) uid
|
||||||
|
{
|
||||||
|
NSDictionary *entries;
|
||||||
|
|
||||||
|
entries = [[self _aclEntries] objectForKey: @"entries"];
|
||||||
|
|
||||||
|
return [entries objectForKey: uid];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setRoles: (NSArray *) roles
|
||||||
|
forUser: (NSString *) uid
|
||||||
|
{
|
||||||
|
NSMutableDictionary *acl;
|
||||||
|
NSMutableDictionary *entries;
|
||||||
|
|
||||||
|
acl = [self _aclEntries];
|
||||||
|
entries = [acl objectForKey: @"entries"];
|
||||||
|
[entries setObject: roles forKey: uid];
|
||||||
|
[aclMessage save];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -1,6 +1,6 @@
|
||||||
/* MAPIStoreVolatileMessage.h - this file is part of SOGo
|
/* SOGoMAPIDBMessage.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2012 Inverse inc.
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -20,18 +20,15 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MAPISTOREVOLATILEMESSAGE_H
|
#ifndef SOGOMAPIDBMESSAGE_H
|
||||||
#define MAPISTOREVOLATILEMESSAGE_H
|
#define SOGOMAPIDBMESSAGE_H
|
||||||
|
|
||||||
#import "MAPIStoreMessage.h"
|
#import "SOGoMAPIDBObject.h"
|
||||||
|
|
||||||
@interface MAPIStoreVolatileMessage : MAPIStoreMessage
|
@class NSDate;
|
||||||
{
|
@class NSString;
|
||||||
BOOL fetchedAttachments;
|
|
||||||
NSDate *creationTime;
|
|
||||||
NSDate *lastModificationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@interface SOGoMAPIDBMessage : SOGoMAPIDBObject
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* MAPISTOREVOLATILEMESSAGE_H */
|
#endif /* SOGOMAPIDBMESSAGE_H */
|
61
OpenChange/SOGoMAPIDBMessage.m
Normal file
61
OpenChange/SOGoMAPIDBMessage.m
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* SOGoMAPIDBMessage.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc.
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSData.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSFileManager.h>
|
||||||
|
#import <Foundation/NSException.h>
|
||||||
|
#import <Foundation/NSPropertyList.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
|
||||||
|
#import "SOGoMAPIDBFolder.h"
|
||||||
|
|
||||||
|
#import "SOGoMAPIDBMessage.h"
|
||||||
|
|
||||||
|
@implementation SOGoMAPIDBMessage
|
||||||
|
|
||||||
|
- (Class) mapistoreMessageClass
|
||||||
|
{
|
||||||
|
// NSArray *dirMembers;
|
||||||
|
NSString *className;
|
||||||
|
|
||||||
|
[NSException raise: @"whereisthisusedexception"
|
||||||
|
format: @"this exception should be triggered only for tracing"];
|
||||||
|
// /* FIXME: this method is a bit dirty */
|
||||||
|
// dirMembers = [[container directory] componentsSeparatedByString: @"/"];
|
||||||
|
// if ([dirMembers containsObject: @"fai"]) /* should not occur as FAI message
|
||||||
|
// are instantiated directly in
|
||||||
|
// MAPIStoreFolder */
|
||||||
|
// className = @"MAPIStoreFAIMessage";
|
||||||
|
// else if ([dirMembers containsObject: @"notes"])
|
||||||
|
// className = @"MAPIStoreNotesMessage";
|
||||||
|
// else
|
||||||
|
// className = @"MAPIStoreDBMessage";
|
||||||
|
|
||||||
|
className = @"nimportequoi";
|
||||||
|
return NSClassFromString (className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
85
OpenChange/SOGoMAPIDBObject.h
Normal file
85
OpenChange/SOGoMAPIDBObject.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* SOGoMAPIDBObject.h - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOGOMAPIDBOBJECT_H
|
||||||
|
#define SOGOMAPIDBOBJECT_H
|
||||||
|
|
||||||
|
#import "SOGoMAPIObject.h"
|
||||||
|
|
||||||
|
@class NSArray;
|
||||||
|
@class NSMutableDictionary;
|
||||||
|
@class NSMutableString;
|
||||||
|
@class NSString;
|
||||||
|
@class NSURL;
|
||||||
|
|
||||||
|
@class EOAdaptor;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MAPIDBObjectTypeFolder = 1,
|
||||||
|
MAPIDBObjectTypeMessage = 2,
|
||||||
|
MAPIDBObjectTypeFAI = 3,
|
||||||
|
MAPIDBObjectTypeInternal = 99 /* object = property list */
|
||||||
|
} MAPIDBObjectType;
|
||||||
|
|
||||||
|
@interface SOGoMAPIDBObject : SOGoMAPIObject
|
||||||
|
{
|
||||||
|
NSURL *tableUrl;
|
||||||
|
|
||||||
|
BOOL initialized; /* safe guard */
|
||||||
|
MAPIDBObjectType objectType;
|
||||||
|
NSInteger version;
|
||||||
|
BOOL deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* actions */
|
||||||
|
- (void) setupFromRecord: (NSDictionary *) record;
|
||||||
|
|
||||||
|
- (void) reloadIfNeeded;
|
||||||
|
- (void) save;
|
||||||
|
|
||||||
|
/* accessors */
|
||||||
|
- (NSMutableString *) path; /* full filename */
|
||||||
|
|
||||||
|
- (void) setTableUrl: (NSURL *) newTableUrl;
|
||||||
|
- (NSURL *) tableUrl;
|
||||||
|
- (NSString *) tableName;
|
||||||
|
|
||||||
|
- (NSArray *) performSQLQuery: (NSString *) sql;
|
||||||
|
- (NSDictionary *) lookupRecord: (NSString *) path
|
||||||
|
newerThanVersion: (NSInteger) startVersion;
|
||||||
|
|
||||||
|
- (void) setObjectType: (MAPIDBObjectType) newObjectType;
|
||||||
|
- (MAPIDBObjectType) objectType; /* message, fai, folder */
|
||||||
|
|
||||||
|
/* automatically set from actions */
|
||||||
|
- (BOOL) deleted;
|
||||||
|
|
||||||
|
- (void) changePathTo: (NSString *) newPath;
|
||||||
|
|
||||||
|
/* db helpers */
|
||||||
|
- (EOAdaptor *) tableChannelAdaptor;
|
||||||
|
- (NSArray *) performSQLQuery: (NSString *) sql;
|
||||||
|
- (BOOL) performBatchSQLQueries: (NSArray *) queries;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* SOGOMAPIDBOBJECT_H */
|
546
OpenChange/SOGoMAPIDBObject.m
Normal file
546
OpenChange/SOGoMAPIDBObject.m
Normal file
|
@ -0,0 +1,546 @@
|
||||||
|
/* SOGoMAPIDBObject.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSException.h>
|
||||||
|
#import <Foundation/NSNull.h>
|
||||||
|
#import <Foundation/NSPropertyList.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
#import <Foundation/NSURL.h>
|
||||||
|
#import <Foundation/NSValue.h>
|
||||||
|
#import <GDLAccess/EOAdaptor.h>
|
||||||
|
#import <GDLAccess/EOAdaptorChannel.h>
|
||||||
|
#import <GDLAccess/EOAdaptorContext.h>
|
||||||
|
#import <GDLAccess/EOAttribute.h>
|
||||||
|
#import <GDLContentStore/GCSChannelManager.h>
|
||||||
|
#import <NGExtensions/NGBase64Coding.h>
|
||||||
|
#import <NGExtensions/NSNull+misc.h>
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <SOGo/NSObject+Utilities.h>
|
||||||
|
#import <SOGo/NSString+Utilities.h>
|
||||||
|
#import <SOGo/SOGoDomainDefaults.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
|
||||||
|
#import "GCSSpecialQueries+OpenChange.h"
|
||||||
|
#import "MAPIStoreTypes.h"
|
||||||
|
#import "SOGoMAPIDBFolder.h"
|
||||||
|
|
||||||
|
#import "SOGoMAPIDBObject.h"
|
||||||
|
|
||||||
|
static EOAttribute *textColumn = nil;
|
||||||
|
|
||||||
|
@implementation SOGoMAPIDBObject
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
NSDictionary *description;
|
||||||
|
|
||||||
|
if (!textColumn)
|
||||||
|
{
|
||||||
|
/* TODO: this is a hack for providing an EOAttribute definition that is
|
||||||
|
compatible with all the backends that we support. We should make use
|
||||||
|
of EOModel instead. */
|
||||||
|
description = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
@"c_textfield", @"columnName",
|
||||||
|
@"VARCHAR", @"externalType",
|
||||||
|
nil];
|
||||||
|
textColumn = [EOAttribute attributeFromPropertyList: description];
|
||||||
|
[textColumn retain];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
= (@"CREATE TABLE %@ ("
|
||||||
|
@" c_path VARCHAR(255) PRIMARY KEY,"
|
||||||
|
@" c_type VARCHAR(20) NOT NULL,"
|
||||||
|
@" c_creationdate INT4 NOT NULL,"
|
||||||
|
@" c_lastmodified INT4 NOT NULL,"
|
||||||
|
@" c_version INT4 NOT NULL DEFAULT 0,"
|
||||||
|
@" c_deleted SMALLINT NOT NULL DEFAULT 0,"
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* indexes:
|
||||||
|
c_path (primary key)
|
||||||
|
c_counter
|
||||||
|
c_path, c_type
|
||||||
|
c_path, c_creationdate */
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
tableUrl = nil;
|
||||||
|
initialized = NO;
|
||||||
|
objectType = -1;
|
||||||
|
deleted = NO;
|
||||||
|
version = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[tableUrl release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setTableUrl: (NSURL *) newTableUrl
|
||||||
|
{
|
||||||
|
ASSIGN (tableUrl, newTableUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURL *) tableUrl
|
||||||
|
{
|
||||||
|
if (!tableUrl)
|
||||||
|
{
|
||||||
|
tableUrl = [container tableUrl];
|
||||||
|
[tableUrl retain];
|
||||||
|
if (!tableUrl)
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"table url is not set for object '%@'", self];
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) tableName
|
||||||
|
{
|
||||||
|
NSArray *parts;
|
||||||
|
|
||||||
|
[self tableUrl];
|
||||||
|
parts = [[tableUrl path] componentsSeparatedByString: @"/"];
|
||||||
|
|
||||||
|
return [parts lastObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setupFromRecord: (NSDictionary *) record
|
||||||
|
{
|
||||||
|
NSInteger intValue;
|
||||||
|
NSString *propsValue, *error;
|
||||||
|
NSDictionary *newValues;
|
||||||
|
NSPropertyListFormat format;
|
||||||
|
|
||||||
|
objectType = [[record objectForKey: @"c_type"] intValue];
|
||||||
|
intValue = [[record objectForKey: @"c_creationdate"] intValue];
|
||||||
|
ASSIGN (creationDate,
|
||||||
|
[NSCalendarDate
|
||||||
|
dateWithTimeIntervalSince1970: (NSTimeInterval) intValue]);
|
||||||
|
intValue = [[record objectForKey: @"c_lastmodified"] intValue];
|
||||||
|
ASSIGN (lastModified,
|
||||||
|
[NSCalendarDate
|
||||||
|
dateWithTimeIntervalSince1970: (NSTimeInterval) intValue]);
|
||||||
|
deleted = ([[record objectForKey: @"c_deleted"] intValue] > 0);
|
||||||
|
version = [[record objectForKey: @"c_version"] intValue];
|
||||||
|
propsValue = [record objectForKey: @"c_content"];
|
||||||
|
if ([propsValue isNotNull])
|
||||||
|
{
|
||||||
|
newValues = [NSPropertyListSerialization propertyListFromData: [propsValue dataByDecodingBase64]
|
||||||
|
mutabilityOption: NSPropertyListMutableContainers
|
||||||
|
format: &format
|
||||||
|
errorDescription: &error];
|
||||||
|
[properties addEntriesFromDictionary: newValues];
|
||||||
|
// [properties addEntriesFromDictionary: [propsValue
|
||||||
|
// objectFromJSONString]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[properties removeAllObjects];
|
||||||
|
|
||||||
|
initialized = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* accessors */
|
||||||
|
- (NSMutableString *) path
|
||||||
|
{
|
||||||
|
NSMutableString *path;
|
||||||
|
|
||||||
|
if (container)
|
||||||
|
path = [container pathForChild: nameInContainer];
|
||||||
|
else
|
||||||
|
path = [NSMutableString stringWithFormat: @"/%@", nameInContainer];
|
||||||
|
|
||||||
|
if ([path rangeOfString: @"//"].location != NSNotFound)
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"object path has not been properly set for"
|
||||||
|
" folder '%@' (%@)",
|
||||||
|
self, path];
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setObjectType: (MAPIDBObjectType) newObjectType
|
||||||
|
{
|
||||||
|
objectType = newObjectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MAPIDBObjectType) objectType /* message, fai, folder */
|
||||||
|
{
|
||||||
|
return objectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSCalendarDate *) creationDate
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"record has not been initialized: %@", self];
|
||||||
|
|
||||||
|
return creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSCalendarDate *) lastModified
|
||||||
|
{
|
||||||
|
if (!initialized)
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"record has not been initialized: %@", self];
|
||||||
|
|
||||||
|
return lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) deleted
|
||||||
|
{
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (Class) mapistoreMessageClass
|
||||||
|
{
|
||||||
|
NSString *className, *mapiMsgClass;
|
||||||
|
|
||||||
|
switch (objectType)
|
||||||
|
{
|
||||||
|
case MAPIDBObjectTypeMessage:
|
||||||
|
mapiMsgClass = [properties
|
||||||
|
objectForKey: MAPIPropertyKey (PidTagMessageClass)];
|
||||||
|
if (mapiMsgClass)
|
||||||
|
{
|
||||||
|
if ([mapiMsgClass isEqualToString: @"IPM.StickyNote"])
|
||||||
|
className = @"MAPIStoreNotesMessage";
|
||||||
|
else
|
||||||
|
className = @"MAPIStoreDBMessage";
|
||||||
|
[self logWithFormat: @"PidTagMessageClass = '%@', returning '%@'",
|
||||||
|
mapiMsgClass, className];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self warnWithFormat: @"PidTagMessageClass is not set, falling back"
|
||||||
|
@" to 'MAPIStoreDBMessage'"];
|
||||||
|
className = @"MAPIStoreDBMessage";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MAPIDBObjectTypeFAI:
|
||||||
|
className = @"MAPIStoreFAIMessage";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"message class should not be queried for objects"
|
||||||
|
@" of type '%d'", objectType];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NSClassFromString (className);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* actions */
|
||||||
|
- (void) changePathTo: (NSString *) newPath
|
||||||
|
{
|
||||||
|
NSMutableString *sql;
|
||||||
|
NSString *oldPath, *newParentPath;
|
||||||
|
NSRange slashRange;
|
||||||
|
|
||||||
|
oldPath = [self path];
|
||||||
|
|
||||||
|
slashRange = [newPath rangeOfString: @"/"
|
||||||
|
options: NSBackwardsSearch];
|
||||||
|
if (slashRange.location != NSNotFound)
|
||||||
|
newParentPath = [newPath substringToIndex: slashRange.location];
|
||||||
|
else
|
||||||
|
newParentPath = NULL;
|
||||||
|
|
||||||
|
sql = [NSMutableString stringWithFormat: @"UPDATE %@"
|
||||||
|
@" SET c_path = '%@'",
|
||||||
|
[self tableName],
|
||||||
|
newPath];
|
||||||
|
if (newParentPath)
|
||||||
|
[sql appendFormat: @", c_parent_path = '%@'", newParentPath];
|
||||||
|
else
|
||||||
|
[sql appendString: @", c_parent_path = NULL"];
|
||||||
|
[sql appendFormat: @" WHERE c_path = '%@'", oldPath];
|
||||||
|
[self performBatchSQLQueries: [NSArray arrayWithObject: sql]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (EOAdaptor *) tableChannelAdaptor
|
||||||
|
{
|
||||||
|
GCSChannelManager *cm;
|
||||||
|
EOAdaptor *adaptor;
|
||||||
|
EOAdaptorChannel *channel;
|
||||||
|
|
||||||
|
cm = [GCSChannelManager defaultChannelManager];
|
||||||
|
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
|
||||||
|
adaptor = [[channel adaptorContext] adaptor];
|
||||||
|
[cm releaseChannel: channel];
|
||||||
|
|
||||||
|
return adaptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) performSQLQuery: (NSString *) sql
|
||||||
|
{
|
||||||
|
NSMutableArray *records;
|
||||||
|
GCSChannelManager *cm;
|
||||||
|
EOAdaptorChannel *channel;
|
||||||
|
NSException *error;
|
||||||
|
NSArray *attrs;
|
||||||
|
NSDictionary *record;
|
||||||
|
|
||||||
|
cm = [GCSChannelManager defaultChannelManager];
|
||||||
|
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
|
||||||
|
|
||||||
|
error = [channel evaluateExpressionX: sql];
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
records = nil;
|
||||||
|
[self logWithFormat:
|
||||||
|
@"an exception occurred when executing query '%@'",
|
||||||
|
sql];
|
||||||
|
[self logWithFormat: @"exception is '%@'", error];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
records = [NSMutableArray arrayWithCapacity: 256];
|
||||||
|
attrs = [channel describeResults: NO];
|
||||||
|
while ((record = [channel fetchAttributes: attrs withZone: NULL]))
|
||||||
|
[records addObject: record];
|
||||||
|
}
|
||||||
|
[cm releaseChannel: channel];
|
||||||
|
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) performBatchSQLQueries: (NSArray *) queries
|
||||||
|
{
|
||||||
|
GCSChannelManager *cm;
|
||||||
|
EOAdaptorChannel *channel;
|
||||||
|
EOAdaptorContext *dbContext;
|
||||||
|
NSException *error;
|
||||||
|
NSUInteger count, max;
|
||||||
|
NSString *sql;
|
||||||
|
|
||||||
|
cm = [GCSChannelManager defaultChannelManager];
|
||||||
|
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
|
||||||
|
dbContext = [channel adaptorContext];
|
||||||
|
|
||||||
|
[dbContext beginTransaction];
|
||||||
|
|
||||||
|
error = nil;
|
||||||
|
|
||||||
|
max = [queries count];
|
||||||
|
for (count = 0; error == nil && count < max; count++)
|
||||||
|
{
|
||||||
|
sql = [queries objectAtIndex: count];
|
||||||
|
error = [channel evaluateExpressionX: sql];
|
||||||
|
if (error)
|
||||||
|
[dbContext rollbackTransaction];
|
||||||
|
}
|
||||||
|
if (!error)
|
||||||
|
[dbContext commitTransaction];
|
||||||
|
[cm releaseChannel: channel];
|
||||||
|
|
||||||
|
return (error == nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *) lookupRecord: (NSString *) path
|
||||||
|
newerThanVersion: (NSInteger) startVersion
|
||||||
|
{
|
||||||
|
NSDictionary *record;
|
||||||
|
NSArray *records;
|
||||||
|
NSString *tableName, *pathValue;
|
||||||
|
NSMutableString *sql;
|
||||||
|
EOAdaptor *adaptor;
|
||||||
|
|
||||||
|
if ([path hasSuffix: @"/"])
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"path ends with a slash: %@", path];
|
||||||
|
|
||||||
|
tableName = [self tableName];
|
||||||
|
adaptor = [self tableChannelAdaptor];
|
||||||
|
pathValue = [adaptor formatValue: path
|
||||||
|
forAttribute: textColumn];
|
||||||
|
|
||||||
|
/* query */
|
||||||
|
sql = [NSMutableString stringWithFormat:
|
||||||
|
@"SELECT * FROM %@ WHERE c_path = %@",
|
||||||
|
tableName, pathValue];
|
||||||
|
if (startVersion > -1)
|
||||||
|
[sql appendFormat: @" AND c_version > %d", startVersion];
|
||||||
|
|
||||||
|
/* execution */
|
||||||
|
records = [self performSQLQuery: sql];
|
||||||
|
if ([records count] > 0)
|
||||||
|
record = [records objectAtIndex: 0];
|
||||||
|
else
|
||||||
|
record = nil;
|
||||||
|
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) reloadIfNeeded
|
||||||
|
{
|
||||||
|
/* if object is uninitialized: reload without condition, otherwise, load if
|
||||||
|
c_version > :version */
|
||||||
|
NSDictionary *record;
|
||||||
|
|
||||||
|
if (initialized)
|
||||||
|
{
|
||||||
|
if (!isNew)
|
||||||
|
{
|
||||||
|
record = [self lookupRecord: [self path]
|
||||||
|
newerThanVersion: version];
|
||||||
|
if (record)
|
||||||
|
[self setupFromRecord: record];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
record = [self lookupRecord: [self path]
|
||||||
|
newerThanVersion: -1];
|
||||||
|
if (record)
|
||||||
|
{
|
||||||
|
[self setupFromRecord: record];
|
||||||
|
isNew = NO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
isNew = YES;
|
||||||
|
initialized = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSException *) delete
|
||||||
|
{
|
||||||
|
deleted = YES;
|
||||||
|
[properties removeAllObjects];
|
||||||
|
[self save];
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) save
|
||||||
|
{
|
||||||
|
NSString *sql;
|
||||||
|
NSData *content;
|
||||||
|
NSCalendarDate *now;
|
||||||
|
GCSChannelManager *cm;
|
||||||
|
EOAdaptor *adaptor;
|
||||||
|
EOAdaptorChannel *channel;
|
||||||
|
NSInteger creationDateValue, lastModifiedValue, deletedValue;
|
||||||
|
NSString *tableName, *pathValue, *parentPathValue, *propsValue;
|
||||||
|
NSException *result;
|
||||||
|
|
||||||
|
if (!initialized)
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"record has not been initialized: %@", self];
|
||||||
|
|
||||||
|
cm = [GCSChannelManager defaultChannelManager];
|
||||||
|
|
||||||
|
channel = [cm acquireOpenChannelForURL: [self tableUrl]];
|
||||||
|
|
||||||
|
tableName = [self tableName];
|
||||||
|
|
||||||
|
now = [NSCalendarDate date];
|
||||||
|
ASSIGN (lastModified, now);
|
||||||
|
|
||||||
|
/*
|
||||||
|
- (NSException *)insertRowX:(NSDictionary *)_row forEntity:(EOEntity *)_entity;
|
||||||
|
- (NSException *)updateRowX:(NSDictionary*)aRow
|
||||||
|
describedByQualifier:(EOSQLQualifier*)aQualifier;
|
||||||
|
*/
|
||||||
|
|
||||||
|
adaptor = [[channel adaptorContext] adaptor];
|
||||||
|
pathValue = [adaptor formatValue: [self path]
|
||||||
|
forAttribute: textColumn];
|
||||||
|
|
||||||
|
lastModifiedValue = (NSInteger) [lastModified timeIntervalSince1970];
|
||||||
|
|
||||||
|
if (objectType == -1)
|
||||||
|
[NSException raise: @"MAPIStoreIOException"
|
||||||
|
format: @"object type has not been set for object '%@'",
|
||||||
|
self];
|
||||||
|
|
||||||
|
if ([properties count] > 0)
|
||||||
|
{
|
||||||
|
content = [NSPropertyListSerialization
|
||||||
|
dataFromPropertyList: properties
|
||||||
|
format: NSPropertyListGNUstepBinaryFormat
|
||||||
|
errorDescription: NULL];
|
||||||
|
propsValue = [adaptor formatValue: [content stringByEncodingBase64]
|
||||||
|
forAttribute: textColumn];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
propsValue = @"NULL";
|
||||||
|
|
||||||
|
if (isNew)
|
||||||
|
{
|
||||||
|
ASSIGN (creationDate, now);
|
||||||
|
creationDateValue = (NSInteger) [creationDate timeIntervalSince1970];
|
||||||
|
parentPathValue = [adaptor formatValue: [container path]
|
||||||
|
forAttribute: textColumn];
|
||||||
|
if (!parentPathValue)
|
||||||
|
parentPathValue = @"NULL";
|
||||||
|
sql = [NSString stringWithFormat:
|
||||||
|
(@"INSERT INTO %@"
|
||||||
|
@" (c_path, c_parent_path, c_type, c_creationdate, c_lastmodified,"
|
||||||
|
@" c_deleted, c_version, c_content)"
|
||||||
|
@" VALUES (%@, %@, %d, %d, %d, 0, 0, %@"
|
||||||
|
@")"),
|
||||||
|
tableName,
|
||||||
|
pathValue, parentPathValue, objectType,
|
||||||
|
creationDateValue, lastModifiedValue,
|
||||||
|
propsValue];
|
||||||
|
isNew = NO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
version++;
|
||||||
|
deletedValue = (deleted ? 1 : 0);
|
||||||
|
sql = [NSString stringWithFormat:
|
||||||
|
(@"UPDATE %@"
|
||||||
|
@" SET c_lastmodified = %d, c_deleted = %d,"
|
||||||
|
@" c_version = %d, c_content = %@"
|
||||||
|
@" WHERE c_path = %@"),
|
||||||
|
tableName,
|
||||||
|
lastModifiedValue, deletedValue, version, propsValue,
|
||||||
|
pathValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
result = [channel evaluateExpressionX: sql];
|
||||||
|
if (result)
|
||||||
|
[self errorWithFormat: @"could not insert/update record for record %@"
|
||||||
|
@" in %@: %@", pathValue, tableName, result];
|
||||||
|
// @" c_path VARCHAR(255) PRIMARY KEY,"
|
||||||
|
// @" c_type SMALLINT NOT NULL,"
|
||||||
|
// @" c_creationdate INT4 NOT NULL,"
|
||||||
|
// @" c_lastmodified INT4 NOT NULL,"
|
||||||
|
// @" c_deleted SMALLINT NOT NULL DEFAULT 0,"
|
||||||
|
// @" c_content BLOB");
|
||||||
|
|
||||||
|
[cm releaseChannel: channel];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -1,439 +0,0 @@
|
||||||
/* SOGoMAPIFSFolder.m - this file is part of SOGo
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Inverse inc.
|
|
||||||
*
|
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This file is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <Foundation/NSArray.h>
|
|
||||||
#import <Foundation/NSData.h>
|
|
||||||
#import <Foundation/NSDictionary.h>
|
|
||||||
#import <Foundation/NSException.h>
|
|
||||||
#import <Foundation/NSFileManager.h>
|
|
||||||
#import <Foundation/NSPropertyList.h>
|
|
||||||
#import <Foundation/NSString.h>
|
|
||||||
#import <Foundation/NSValue.h>
|
|
||||||
#import <Foundation/NSURL.h>
|
|
||||||
|
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
|
||||||
#import <SOGo/NSArray+Utilities.h>
|
|
||||||
|
|
||||||
#import "EOQualifier+MAPI.h"
|
|
||||||
#import "SOGoMAPIFSMessage.h"
|
|
||||||
|
|
||||||
#import "SOGoMAPIFSFolder.h"
|
|
||||||
|
|
||||||
#undef DEBUG
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <talloc.h>
|
|
||||||
#include <util/time.h>
|
|
||||||
#include <mapistore/mapistore.h>
|
|
||||||
#include <mapistore/mapistore_errors.h>
|
|
||||||
#include <libmapiproxy.h>
|
|
||||||
#include <param.h>
|
|
||||||
|
|
||||||
static NSString *privateDir = nil;
|
|
||||||
|
|
||||||
@implementation SOGoMAPIFSFolder
|
|
||||||
|
|
||||||
+ (void) initialize
|
|
||||||
{
|
|
||||||
struct loadparm_context *lpCtx;
|
|
||||||
const char *cPrivateDir;
|
|
||||||
|
|
||||||
if (!privateDir)
|
|
||||||
{
|
|
||||||
lpCtx = loadparm_init_global (true);
|
|
||||||
cPrivateDir = lpcfg_private_dir (lpCtx);
|
|
||||||
privateDir = [NSString stringWithUTF8String: cPrivateDir];
|
|
||||||
[privateDir retain];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (id) folderWithURL: (NSURL *) url
|
|
||||||
andTableType: (uint8_t) tableType
|
|
||||||
{
|
|
||||||
SOGoMAPIFSFolder *newFolder;
|
|
||||||
|
|
||||||
newFolder = [[self alloc] initWithURL: url
|
|
||||||
andTableType: tableType];
|
|
||||||
[newFolder autorelease];
|
|
||||||
|
|
||||||
return newFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) init
|
|
||||||
{
|
|
||||||
if ((self = [super init]))
|
|
||||||
{
|
|
||||||
directory = nil;
|
|
||||||
directoryIsSane = NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
[directory release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithURL: (NSURL *) url
|
|
||||||
andTableType: (uint8_t) tableType
|
|
||||||
{
|
|
||||||
NSString *path, *username, *tableParticle;
|
|
||||||
|
|
||||||
if ((self = [self init]))
|
|
||||||
{
|
|
||||||
if (tableType == MAPISTORE_MESSAGE_TABLE)
|
|
||||||
tableParticle = @"message";
|
|
||||||
else if (tableType == MAPISTORE_FAI_TABLE)
|
|
||||||
tableParticle = @"fai";
|
|
||||||
else if (tableType == MAPISTORE_FOLDER_TABLE)
|
|
||||||
tableParticle = @"folder";
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[NSException raise: @"MAPIStoreIOException"
|
|
||||||
format: @"unsupported table type: %d", tableType];
|
|
||||||
tableParticle = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = [url path];
|
|
||||||
if (![path hasSuffix: @"/"])
|
|
||||||
path = [NSString stringWithFormat: @"%@/", path];
|
|
||||||
username = [url user];
|
|
||||||
directory = [NSString stringWithFormat: @"%@/mapistore/SOGo/%@/%@/%@%@",
|
|
||||||
privateDir, username, tableParticle,
|
|
||||||
[url host], path];
|
|
||||||
[self setOwner: username];
|
|
||||||
[self logWithFormat: @"directory: %@", directory];
|
|
||||||
[directory retain];
|
|
||||||
ASSIGN (nameInContainer, [path stringByDeletingLastPathComponent]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) initWithName: (NSString *) newName
|
|
||||||
inContainer: (id) newContainer
|
|
||||||
{
|
|
||||||
if ((self = [super initWithName: newName inContainer: newContainer]))
|
|
||||||
{
|
|
||||||
directory = [[newContainer directory]
|
|
||||||
stringByAppendingPathComponent: newName];
|
|
||||||
[directory retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) directory
|
|
||||||
{
|
|
||||||
return directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (SOGoMAPIFSMessage *) newMessage
|
|
||||||
{
|
|
||||||
NSString *filename;
|
|
||||||
|
|
||||||
filename = [NSString stringWithFormat: @"%@.plist",
|
|
||||||
[SOGoObject globallyUniqueObjectId]];
|
|
||||||
|
|
||||||
return [SOGoMAPIFSMessage objectWithName: filename inContainer: self];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) ensureDirectory
|
|
||||||
{
|
|
||||||
NSFileManager *fm;
|
|
||||||
NSDictionary *attributes;
|
|
||||||
BOOL isDir;
|
|
||||||
|
|
||||||
if (!directory)
|
|
||||||
[NSException raise: @"MAPIStoreIOException"
|
|
||||||
format: @"directory is nil"];
|
|
||||||
|
|
||||||
fm = [NSFileManager defaultManager];
|
|
||||||
if ([fm fileExistsAtPath: directory isDirectory: &isDir])
|
|
||||||
{
|
|
||||||
if (!isDir)
|
|
||||||
[NSException raise: @"MAPIStoreIOException"
|
|
||||||
format: @"object at path '%@' is not a directory",
|
|
||||||
directory];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
attributes
|
|
||||||
= [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: 0700]
|
|
||||||
forKey: NSFilePosixPermissions];
|
|
||||||
[fm createDirectoryAtPath: directory
|
|
||||||
attributes: attributes];
|
|
||||||
}
|
|
||||||
|
|
||||||
directoryIsSane = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) _objectsInDirectory: (BOOL) dirs
|
|
||||||
{
|
|
||||||
NSFileManager *fm;
|
|
||||||
NSArray *contents;
|
|
||||||
NSMutableArray *files;
|
|
||||||
NSUInteger count, max;
|
|
||||||
NSString *file, *fullName;
|
|
||||||
BOOL isDir;
|
|
||||||
|
|
||||||
if (!directoryIsSane)
|
|
||||||
[self ensureDirectory];
|
|
||||||
|
|
||||||
fm = [NSFileManager defaultManager];
|
|
||||||
contents = [fm directoryContentsAtPath: directory];
|
|
||||||
max = [contents count];
|
|
||||||
files = [NSMutableArray arrayWithCapacity: max];
|
|
||||||
for (count = 0; count < max; count++)
|
|
||||||
{
|
|
||||||
file = [contents objectAtIndex: count];
|
|
||||||
if (![file isEqualToString: @"permissions.plist"])
|
|
||||||
{
|
|
||||||
fullName = [directory stringByAppendingPathComponent: file];
|
|
||||||
if ([fm fileExistsAtPath: fullName
|
|
||||||
isDirectory: &isDir]
|
|
||||||
&& dirs == isDir)
|
|
||||||
[files addObject: file];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) toManyRelationshipKeys
|
|
||||||
{
|
|
||||||
return [self _objectsInDirectory: YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) toOneRelationshipKeys
|
|
||||||
{
|
|
||||||
return [self _objectsInDirectory: NO];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) toOneRelationshipKeysMatchingQualifier: (EOQualifier *) qualifier
|
|
||||||
andSortOrderings: (NSArray *) sortOrderings
|
|
||||||
{
|
|
||||||
NSArray *allKeys;
|
|
||||||
NSMutableArray *keys;
|
|
||||||
NSUInteger count, max;
|
|
||||||
NSString *messageKey;
|
|
||||||
SOGoMAPIFSMessage *message;
|
|
||||||
|
|
||||||
if (sortOrderings)
|
|
||||||
[self warnWithFormat: @"sorting is not handled yet"];
|
|
||||||
|
|
||||||
allKeys = [self toOneRelationshipKeys];
|
|
||||||
if (qualifier)
|
|
||||||
{
|
|
||||||
[self logWithFormat: @"%s: getting restricted FAI keys", __PRETTY_FUNCTION__];
|
|
||||||
max = [allKeys count];
|
|
||||||
keys = [NSMutableArray arrayWithCapacity: max];
|
|
||||||
for (count = 0; count < max; count++)
|
|
||||||
{
|
|
||||||
messageKey = [allKeys objectAtIndex: count];
|
|
||||||
message = [self lookupName: messageKey
|
|
||||||
inContext: nil
|
|
||||||
acquire: NO];
|
|
||||||
if ([qualifier evaluateMAPIVolatileMessage: message])
|
|
||||||
[keys addObject: messageKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
keys = (NSMutableArray *) allKeys;
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) lookupName: (NSString *) fileName
|
|
||||||
inContext: (WOContext *) woContext
|
|
||||||
acquire: (BOOL) acquire
|
|
||||||
{
|
|
||||||
NSFileManager *fm;
|
|
||||||
NSString *fullName;
|
|
||||||
id object;
|
|
||||||
BOOL isDir;
|
|
||||||
|
|
||||||
if (!directoryIsSane)
|
|
||||||
[self ensureDirectory];
|
|
||||||
|
|
||||||
fm = [NSFileManager defaultManager];
|
|
||||||
fullName = [directory stringByAppendingPathComponent: fileName];
|
|
||||||
if ([fm fileExistsAtPath: fullName
|
|
||||||
isDirectory: &isDir])
|
|
||||||
{
|
|
||||||
if (isDir)
|
|
||||||
object = [isa objectWithName: fileName
|
|
||||||
inContainer: self];
|
|
||||||
else
|
|
||||||
object = [SOGoMAPIFSMessage objectWithName: fileName
|
|
||||||
inContainer: self];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
object = nil;
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) _fileAttributeForKey: (NSString *) key
|
|
||||||
{
|
|
||||||
NSDictionary *attributes;
|
|
||||||
|
|
||||||
attributes = [[NSFileManager defaultManager]
|
|
||||||
fileAttributesAtPath: directory
|
|
||||||
traverseLink: NO];
|
|
||||||
|
|
||||||
return [attributes objectForKey: key];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSCalendarDate *) creationTime
|
|
||||||
{
|
|
||||||
return [self _fileAttributeForKey: NSFileCreationDate];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSCalendarDate *) lastModificationTime
|
|
||||||
{
|
|
||||||
return [self _fileAttributeForKey: NSFileModificationDate];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSException *) delete
|
|
||||||
{
|
|
||||||
NSFileManager *fm;
|
|
||||||
NSException *error;
|
|
||||||
|
|
||||||
fm = [NSFileManager defaultManager];
|
|
||||||
|
|
||||||
if (![fm removeFileAtPath: directory handler: NULL])
|
|
||||||
error = [NSException exceptionWithName: @"MAPIStoreIOException"
|
|
||||||
reason: @"could not delete folder"
|
|
||||||
userInfo: nil];
|
|
||||||
else
|
|
||||||
error = nil;
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* acl */
|
|
||||||
- (NSString *) defaultUserID
|
|
||||||
{
|
|
||||||
return @"default";
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSMutableDictionary *) _aclEntries
|
|
||||||
{
|
|
||||||
NSMutableDictionary *aclEntries;
|
|
||||||
NSData *content;
|
|
||||||
NSString *error, *filename;
|
|
||||||
NSPropertyListFormat format;
|
|
||||||
|
|
||||||
filename = [directory stringByAppendingPathComponent: @"permissions.plist"];
|
|
||||||
content = [NSData dataWithContentsOfFile: filename];
|
|
||||||
if (content)
|
|
||||||
aclEntries = [NSPropertyListSerialization propertyListFromData: content
|
|
||||||
mutabilityOption: NSPropertyListMutableContainers
|
|
||||||
format: &format
|
|
||||||
errorDescription: &error];
|
|
||||||
else
|
|
||||||
aclEntries = nil;
|
|
||||||
if (!aclEntries)
|
|
||||||
{
|
|
||||||
aclEntries = [NSMutableDictionary dictionary];
|
|
||||||
[aclEntries setObject: [NSMutableArray array] forKey: @"users"];
|
|
||||||
[aclEntries setObject: [NSMutableDictionary dictionary]
|
|
||||||
forKey: @"entries"];
|
|
||||||
}
|
|
||||||
|
|
||||||
return aclEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) _saveAcl: (NSDictionary *) acl
|
|
||||||
{
|
|
||||||
NSString *filename;
|
|
||||||
NSData *content;
|
|
||||||
|
|
||||||
filename = [directory stringByAppendingPathComponent: @"permissions.plist"];
|
|
||||||
[self ensureDirectory];
|
|
||||||
|
|
||||||
if (acl)
|
|
||||||
content = [NSPropertyListSerialization
|
|
||||||
dataFromPropertyList: acl
|
|
||||||
format: NSPropertyListBinaryFormat_v1_0
|
|
||||||
errorDescription: NULL];
|
|
||||||
else
|
|
||||||
content = [NSData data];
|
|
||||||
if (![content writeToFile: filename atomically: NO])
|
|
||||||
[NSException raise: @"MAPIStoreIOException"
|
|
||||||
format: @"could not save acl"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) addUserInAcls: (NSString *) user
|
|
||||||
{
|
|
||||||
NSMutableDictionary *acl;
|
|
||||||
NSMutableArray *users;
|
|
||||||
|
|
||||||
acl = [self _aclEntries];
|
|
||||||
users = [acl objectForKey: @"users"];
|
|
||||||
[users addObjectUniquely: user];
|
|
||||||
[self _saveAcl: acl];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) removeAclsForUsers: (NSArray *) oldUsers
|
|
||||||
{
|
|
||||||
NSDictionary *acl;
|
|
||||||
NSMutableDictionary *entries;
|
|
||||||
NSMutableArray *users;
|
|
||||||
|
|
||||||
acl = [self _aclEntries];
|
|
||||||
entries = [acl objectForKey: @"entries"];
|
|
||||||
[entries removeObjectsForKeys: oldUsers];
|
|
||||||
users = [acl objectForKey: @"users"];
|
|
||||||
[users removeObjectsInArray: oldUsers];
|
|
||||||
[self _saveAcl: acl];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) aclUsers
|
|
||||||
{
|
|
||||||
return [[self _aclEntries] objectForKey: @"users"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) aclsForUser: (NSString *) uid
|
|
||||||
{
|
|
||||||
NSDictionary *entries;
|
|
||||||
|
|
||||||
entries = [[self _aclEntries] objectForKey: @"entries"];
|
|
||||||
|
|
||||||
return [entries objectForKey: uid];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) setRoles: (NSArray *) roles
|
|
||||||
forUser: (NSString *) uid
|
|
||||||
{
|
|
||||||
NSMutableDictionary *acl;
|
|
||||||
NSMutableDictionary *entries;
|
|
||||||
|
|
||||||
acl = [self _aclEntries];
|
|
||||||
entries = [acl objectForKey: @"entries"];
|
|
||||||
[entries setObject: roles forKey: uid];
|
|
||||||
[self _saveAcl: acl];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,47 +0,0 @@
|
||||||
/* SOGoMAPIFSMessage.h - this file is part of SOGo
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Inverse inc.
|
|
||||||
*
|
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This file is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SOGOMAPIFSMESSAGE_H
|
|
||||||
#define SOGOMAPIFSMESSAGE_H
|
|
||||||
|
|
||||||
#import "SOGoMAPIVolatileMessage.h"
|
|
||||||
|
|
||||||
@class NSDate;
|
|
||||||
@class NSString;
|
|
||||||
|
|
||||||
@interface SOGoMAPIFSMessage : SOGoMAPIVolatileMessage
|
|
||||||
{
|
|
||||||
NSString *completeFilename;
|
|
||||||
NSUInteger inode;
|
|
||||||
NSData *lastModificationTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) save;
|
|
||||||
|
|
||||||
- (NSString *) completeFilename;
|
|
||||||
|
|
||||||
- (NSDate *) creationTime;
|
|
||||||
- (NSDate *) lastModificationTime;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
#endif /* SOGOMAPIFSMESSAGE_H */
|
|
|
@ -1,238 +0,0 @@
|
||||||
/* SOGoMAPIFSMessage.m - this file is part of SOGo
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Inverse inc.
|
|
||||||
*
|
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
|
||||||
*
|
|
||||||
* This file is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 3, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This file is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; see the file COPYING. If not, write to
|
|
||||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <Foundation/NSArray.h>
|
|
||||||
#import <Foundation/NSData.h>
|
|
||||||
#import <Foundation/NSDictionary.h>
|
|
||||||
#import <Foundation/NSFileManager.h>
|
|
||||||
#import <Foundation/NSException.h>
|
|
||||||
#import <Foundation/NSPropertyList.h>
|
|
||||||
#import <Foundation/NSString.h>
|
|
||||||
|
|
||||||
#import <NGExtensions/NSObject+Logs.h>
|
|
||||||
|
|
||||||
#import "SOGoMAPIFSFolder.h"
|
|
||||||
|
|
||||||
#import "SOGoMAPIFSMessage.h"
|
|
||||||
|
|
||||||
@implementation SOGoMAPIFSMessage
|
|
||||||
|
|
||||||
- (id) init
|
|
||||||
{
|
|
||||||
if ((self = [super init]))
|
|
||||||
{
|
|
||||||
completeFilename = nil;
|
|
||||||
inode = 0;
|
|
||||||
lastModificationTime = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) dealloc
|
|
||||||
{
|
|
||||||
[completeFilename release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (Class) mapistoreMessageClass
|
|
||||||
{
|
|
||||||
NSArray *dirMembers;
|
|
||||||
NSString *className;
|
|
||||||
|
|
||||||
/* FIXME: this method is a bit dirty */
|
|
||||||
dirMembers = [[container directory] componentsSeparatedByString: @"/"];
|
|
||||||
if ([dirMembers containsObject: @"fai"]) /* should not occur as FAI message
|
|
||||||
are instantiated directly in
|
|
||||||
MAPIStoreFolder */
|
|
||||||
className = @"MAPIStoreFAIMessage";
|
|
||||||
else if ([dirMembers containsObject: @"notes"])
|
|
||||||
className = @"MAPIStoreNotesMessage";
|
|
||||||
else
|
|
||||||
className = @"MAPIStoreFSMessage";
|
|
||||||
|
|
||||||
return NSClassFromString (className);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) completeFilename
|
|
||||||
{
|
|
||||||
if (!completeFilename)
|
|
||||||
{
|
|
||||||
completeFilename = [[container directory]
|
|
||||||
stringByAppendingPathComponent: nameInContainer];
|
|
||||||
[completeFilename retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
return completeFilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) _readFileChangesDataWithDate: (NSDate **) newLMTime
|
|
||||||
andInode: (NSUInteger *) newInode
|
|
||||||
{
|
|
||||||
BOOL rc;
|
|
||||||
NSDictionary *attributes;
|
|
||||||
|
|
||||||
attributes = [[NSFileManager defaultManager]
|
|
||||||
fileAttributesAtPath: [self completeFilename]
|
|
||||||
traverseLink: NO];
|
|
||||||
if (attributes)
|
|
||||||
{
|
|
||||||
*newLMTime = [attributes fileModificationDate];
|
|
||||||
*newInode = [attributes fileSystemFileNumber];
|
|
||||||
rc = YES;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rc = NO;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) _checkFileChangesDataWithDate: (NSDate **) newLMTime
|
|
||||||
andInode: (NSUInteger *) newInode
|
|
||||||
{
|
|
||||||
BOOL hasChanged = NO;
|
|
||||||
NSDate *lastLMTime;
|
|
||||||
NSUInteger lastInode;
|
|
||||||
|
|
||||||
if ([self _readFileChangesDataWithDate: &lastLMTime
|
|
||||||
andInode: &lastInode])
|
|
||||||
{
|
|
||||||
if (inode != lastInode
|
|
||||||
|| ![lastModificationTime isEqual: lastLMTime])
|
|
||||||
{
|
|
||||||
if (lastLMTime)
|
|
||||||
*newLMTime = lastLMTime;
|
|
||||||
if (newInode)
|
|
||||||
*newInode = lastInode;
|
|
||||||
hasChanged = YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSMutableDictionary *) properties
|
|
||||||
{
|
|
||||||
NSData *content;
|
|
||||||
NSString *error;
|
|
||||||
NSPropertyListFormat format;
|
|
||||||
NSDate *lastLMTime;
|
|
||||||
NSUInteger lastInode;
|
|
||||||
|
|
||||||
if ([self _checkFileChangesDataWithDate: &lastLMTime
|
|
||||||
andInode: &lastInode])
|
|
||||||
{
|
|
||||||
[self logWithFormat: @"file '%@' new or modified: rereading properties",
|
|
||||||
[self completeFilename]];
|
|
||||||
[properties release];
|
|
||||||
properties = nil;
|
|
||||||
content = [NSData dataWithContentsOfFile: [self completeFilename]];
|
|
||||||
if (content)
|
|
||||||
{
|
|
||||||
properties = [NSPropertyListSerialization propertyListFromData: content
|
|
||||||
mutabilityOption: NSPropertyListMutableContainers
|
|
||||||
format: &format
|
|
||||||
errorDescription: &error];
|
|
||||||
[properties retain];
|
|
||||||
if (!properties)
|
|
||||||
[self logWithFormat: @"an error occurred during deserialization"
|
|
||||||
@" of message: '%@'", error];
|
|
||||||
}
|
|
||||||
ASSIGN (lastModificationTime, lastLMTime);
|
|
||||||
inode = lastInode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [super properties];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) save
|
|
||||||
{
|
|
||||||
NSData *content;
|
|
||||||
NSDate *lastLMTime;
|
|
||||||
NSUInteger lastInode;
|
|
||||||
|
|
||||||
[container ensureDirectory];
|
|
||||||
|
|
||||||
// [self logWithFormat: @"%d props in whole dict", [properties count]];
|
|
||||||
|
|
||||||
content = [NSPropertyListSerialization
|
|
||||||
dataFromPropertyList: [self properties]
|
|
||||||
format: NSPropertyListBinaryFormat_v1_0
|
|
||||||
errorDescription: NULL];
|
|
||||||
if (![content writeToFile: [self completeFilename] atomically: YES])
|
|
||||||
[NSException raise: @"MAPIStoreIOException"
|
|
||||||
format: @"could not save message"];
|
|
||||||
|
|
||||||
[self _readFileChangesDataWithDate: &lastLMTime andInode: &lastInode];
|
|
||||||
ASSIGN (lastModificationTime, lastLMTime);
|
|
||||||
inode = lastInode;
|
|
||||||
// [self logWithFormat: @"fs message written to '%@'", [self completeFilename]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) davEntityTag
|
|
||||||
{
|
|
||||||
NSDate *lm;
|
|
||||||
|
|
||||||
lm = [self lastModificationTime];
|
|
||||||
|
|
||||||
return [NSString stringWithFormat: @"%d", (int) [lm timeIntervalSince1970]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSException *) delete
|
|
||||||
{
|
|
||||||
NSFileManager *fm;
|
|
||||||
NSException *error;
|
|
||||||
|
|
||||||
fm = [NSFileManager defaultManager];
|
|
||||||
|
|
||||||
if (![fm removeFileAtPath: [self completeFilename] handler: NULL])
|
|
||||||
error = [NSException exceptionWithName: @"MAPIStoreIOException"
|
|
||||||
reason: @"could not delete message"
|
|
||||||
userInfo: nil];
|
|
||||||
else
|
|
||||||
error = nil;
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id) _fileAttributeForKey: (NSString *) key
|
|
||||||
{
|
|
||||||
NSDictionary *attributes;
|
|
||||||
|
|
||||||
attributes = [[NSFileManager defaultManager]
|
|
||||||
fileAttributesAtPath: [self completeFilename]
|
|
||||||
traverseLink: NO];
|
|
||||||
|
|
||||||
return [attributes objectForKey: key];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSDate *) creationTime
|
|
||||||
{
|
|
||||||
return [self _fileAttributeForKey: NSFileCreationDate];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSDate *) lastModificationTime
|
|
||||||
{
|
|
||||||
return [self _fileAttributeForKey: NSFileModificationDate];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
|
@ -1,12 +1,12 @@
|
||||||
/* SOGoMAPIVolatileMessage.h - this file is part of SOGo
|
/* SOGoMAPIObject.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 3, or (at your option)
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
*
|
||||||
* This file is distributed in the hope that it will be useful,
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
@ -20,22 +20,30 @@
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SOGOMAPIVOLATILEMESSAGE_H
|
#ifndef SOGOMAPIOBJECT_H
|
||||||
#define SOGOMAPIVOLATILEMESSAGE_H
|
#define SOGOMAPIOBJECT_H
|
||||||
|
|
||||||
#import <SOGo/SOGoObject.h>
|
#import <SOGo/SOGoObject.h>
|
||||||
|
|
||||||
@class NSDictionary;
|
|
||||||
@class NSMutableDictionary;
|
@class NSMutableDictionary;
|
||||||
|
|
||||||
@interface SOGoMAPIVolatileMessage : SOGoObject
|
@interface SOGoMAPIObject : SOGoObject
|
||||||
{
|
{
|
||||||
|
BOOL isNew;
|
||||||
NSMutableDictionary *properties;
|
NSMutableDictionary *properties;
|
||||||
|
NSCalendarDate *creationDate;
|
||||||
|
NSCalendarDate *lastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setIsNew: (BOOL) newIsNew;
|
||||||
|
- (BOOL) isNew;
|
||||||
|
|
||||||
|
- (void) adjustLastModified;
|
||||||
|
|
||||||
- (NSMutableDictionary *) properties;
|
- (NSMutableDictionary *) properties;
|
||||||
- (void) appendProperties: (NSDictionary *) newProperties;
|
- (NSCalendarDate *) creationDate;
|
||||||
|
- (NSCalendarDate *) lastModified;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* SOGOMAPIVOLATILEMESSAGE_H */
|
#endif /* SOGOMAPIOBJECT_H */
|
|
@ -1,6 +1,6 @@
|
||||||
/* SOGoMAPIVolatileMessage.m - this file is part of SOGo
|
/* SOGoMAPIObject.m - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Inverse inc
|
* Copyright (C) 2012 Inverse inc
|
||||||
*
|
*
|
||||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
*
|
*
|
||||||
|
@ -21,16 +21,21 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
|
||||||
#import "SOGoMAPIVolatileMessage.h"
|
#import "SOGoMAPIObject.h"
|
||||||
|
|
||||||
@implementation SOGoMAPIVolatileMessage
|
@implementation SOGoMAPIObject
|
||||||
|
|
||||||
- (id) init
|
- (id) init
|
||||||
{
|
{
|
||||||
if ((self = [super init]))
|
if ((self = [super init]))
|
||||||
{
|
{
|
||||||
properties = nil;
|
isNew = NO;
|
||||||
|
creationDate = [NSCalendarDate date];
|
||||||
|
[creationDate retain];
|
||||||
|
lastModified = [creationDate copy];
|
||||||
|
properties = [NSMutableDictionary new];
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -38,21 +43,45 @@
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
[creationDate release];
|
||||||
|
[lastModified release];
|
||||||
[properties release];
|
[properties release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setIsNew: (BOOL) newIsNew
|
||||||
|
{
|
||||||
|
isNew = newIsNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isNew
|
||||||
|
{
|
||||||
|
return isNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) adjustLastModified
|
||||||
|
{
|
||||||
|
ASSIGN (lastModified, [NSCalendarDate date]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isFolderish
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSMutableDictionary *) properties
|
- (NSMutableDictionary *) properties
|
||||||
{
|
{
|
||||||
if (!properties)
|
|
||||||
properties = [NSMutableDictionary new];
|
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) appendProperties: (NSDictionary *) newProperties
|
- (NSCalendarDate *) creationDate
|
||||||
{
|
{
|
||||||
[[self properties] addEntriesFromDictionary: newProperties];
|
return creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSCalendarDate *) lastModified
|
||||||
|
{
|
||||||
|
return lastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
109
OpenChange/dbmsgreader.m
Normal file
109
OpenChange/dbmsgreader.m
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/* dbmsgreader.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* A format-agnostic property list readerer.
|
||||||
|
Usage: dbmsgreader [username] [filename] */
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSBundle.h>
|
||||||
|
#import <Foundation/NSAutoreleasePool.h>
|
||||||
|
#import <Foundation/NSProcessInfo.h>
|
||||||
|
#import <Foundation/NSUserDefaults.h>
|
||||||
|
#import <NGExtensions/NGBase64Coding.h>
|
||||||
|
#import <NGObjWeb/SoProductRegistry.h>
|
||||||
|
#import <SOGo/SOGoProductLoader.h>
|
||||||
|
#import <SOGo/SOGoSystemDefaults.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreUserContext.h"
|
||||||
|
#import "SOGoMAPIDBObject.h"
|
||||||
|
|
||||||
|
#import "NSObject+PropertyList.m"
|
||||||
|
|
||||||
|
Class MAPIStoreUserContextK, SOGoMAPIDBObjectK;
|
||||||
|
|
||||||
|
static void
|
||||||
|
DbDumpObject (NSString *username, NSString *path)
|
||||||
|
{
|
||||||
|
id ctx;
|
||||||
|
NSData *content;
|
||||||
|
id dbobject;
|
||||||
|
NSDictionary *record;
|
||||||
|
|
||||||
|
ctx = [MAPIStoreUserContextK userContextWithUsername: username
|
||||||
|
andTDBIndexing: NULL];
|
||||||
|
dbobject = [SOGoMAPIDBObjectK new];
|
||||||
|
[dbobject setTableUrl: [ctx folderTableURL]];
|
||||||
|
record = [dbobject lookupRecord: path newerThanVersion: -1];
|
||||||
|
if (record)
|
||||||
|
{
|
||||||
|
content = [[record objectForKey: @"c_content"] dataByDecodingBase64];
|
||||||
|
OCDumpPListData (content);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NSLog (@"record not found");
|
||||||
|
|
||||||
|
[dbobject release];
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char *argv[], char *envp[])
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool;
|
||||||
|
SOGoProductLoader *loader;
|
||||||
|
NSUserDefaults *ud;
|
||||||
|
SoProductRegistry *registry;
|
||||||
|
NSArray *arguments;
|
||||||
|
|
||||||
|
/* Here we work around a bug in GNUstep which decodes XML user
|
||||||
|
defaults using the system encoding rather than honouring
|
||||||
|
the encoding specified in the file. */
|
||||||
|
putenv ("GNUSTEP_STRING_ENCODING=NSUTF8StringEncoding");
|
||||||
|
|
||||||
|
pool = [NSAutoreleasePool new];
|
||||||
|
|
||||||
|
[SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
|
||||||
|
/* We force the plugin to base its configuration on the SOGo tree. */
|
||||||
|
ud = [NSUserDefaults standardUserDefaults];
|
||||||
|
[ud registerDefaults: [ud persistentDomainForName: @"sogod"]];
|
||||||
|
|
||||||
|
[NSProcessInfo initializeWithArguments: argv
|
||||||
|
count: argc
|
||||||
|
environment: envp];
|
||||||
|
|
||||||
|
registry = [SoProductRegistry sharedProductRegistry];
|
||||||
|
[registry scanForProductsInDirectory: SOGO_BUNDLES_DIR];
|
||||||
|
|
||||||
|
loader = [SOGoProductLoader productLoader];
|
||||||
|
[loader loadProducts: [NSArray arrayWithObject: BACKEND_BUNDLE_NAME]];
|
||||||
|
|
||||||
|
MAPIStoreUserContextK = NSClassFromString (@"MAPIStoreUserContext");
|
||||||
|
SOGoMAPIDBObjectK = NSClassFromString (@"SOGoMAPIDBObject");
|
||||||
|
|
||||||
|
arguments = [[NSProcessInfo processInfo] arguments];
|
||||||
|
if ([arguments count] > 2)
|
||||||
|
DbDumpObject ([arguments objectAtIndex: 1],
|
||||||
|
[arguments objectAtIndex: 2]);
|
||||||
|
|
||||||
|
[pool release];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
41
OpenChange/iCalEvent+MAPIStore.h
Normal file
41
OpenChange/iCalEvent+MAPIStore.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* iCalEvent+MAPIStore.h - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ICALEVENT_MAPISTORE_H
|
||||||
|
#define ICALEVENT_MAPISTORE_H
|
||||||
|
|
||||||
|
#import <NGCards/iCalEvent.h>
|
||||||
|
|
||||||
|
@class MAPIStoreUserContext;
|
||||||
|
@class NSDictionary;
|
||||||
|
@class NSString;
|
||||||
|
@class SOGoUser;
|
||||||
|
|
||||||
|
@interface iCalEvent (MAPIStoreProperties)
|
||||||
|
|
||||||
|
- (void) updateFromMAPIProperties: (NSDictionary *) properties
|
||||||
|
inUserContext: (MAPIStoreUserContext *) userContext
|
||||||
|
withActiveUser: (SOGoUser *) activeUser;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* ICALEVENT_MAPISTORE_H */
|
522
OpenChange/iCalEvent+MAPIStore.m
Normal file
522
OpenChange/iCalEvent+MAPIStore.m
Normal file
|
@ -0,0 +1,522 @@
|
||||||
|
/* iCalEvent+MAPIStore.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <talloc.h>
|
||||||
|
#include <util/attr.h>
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSData.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <NGCards/iCalAlarm.h>
|
||||||
|
#import <NGCards/iCalCalendar.h>
|
||||||
|
#import <NGCards/iCalEvent.h>
|
||||||
|
#import <NGCards/iCalDateTime.h>
|
||||||
|
#import <NGCards/iCalPerson.h>
|
||||||
|
#import <NGCards/iCalTimeZone.h>
|
||||||
|
#import <NGCards/iCalTrigger.h>
|
||||||
|
#import <SOGo/SOGoPermissions.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
#import <Appointments/SOGoAppointmentFolder.h>
|
||||||
|
#import <Appointments/SOGoAppointmentObject.h>
|
||||||
|
#import <Appointments/iCalEntityObject+SOGo.h>
|
||||||
|
#import <Mailer/NSString+Mail.h>
|
||||||
|
|
||||||
|
#import "MAPIStoreAppointmentWrapper.h"
|
||||||
|
#import "MAPIStoreCalendarAttachment.h"
|
||||||
|
#import "MAPIStoreCalendarFolder.h"
|
||||||
|
#import "MAPIStoreContext.h"
|
||||||
|
#import "MAPIStoreMapping.h"
|
||||||
|
#import "MAPIStoreRecurrenceUtils.h"
|
||||||
|
#import "MAPIStoreTypes.h"
|
||||||
|
#import "MAPIStoreUserContext.h"
|
||||||
|
#import "NSDate+MAPIStore.h"
|
||||||
|
#import "NSData+MAPIStore.h"
|
||||||
|
#import "NSObject+MAPIStore.h"
|
||||||
|
#import "NSString+MAPIStore.h"
|
||||||
|
#import "NSValue+MAPIStore.h"
|
||||||
|
|
||||||
|
#import "MAPIStoreCalendarMessage.h"
|
||||||
|
|
||||||
|
#undef DEBUG
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <gen_ndr/exchange.h>
|
||||||
|
#include <gen_ndr/property.h>
|
||||||
|
#include <libmapi/libmapi.h>
|
||||||
|
#include <mapistore/mapistore.h>
|
||||||
|
#include <mapistore/mapistore_errors.h>
|
||||||
|
#include <mapistore/mapistore_nameid.h>
|
||||||
|
|
||||||
|
#import "iCalEvent+MAPIStore.h"
|
||||||
|
|
||||||
|
@implementation iCalEvent (MAPIStoreProperties)
|
||||||
|
|
||||||
|
- (void) _setupEventRecurrence: (NSData *) mapiRecurrenceData
|
||||||
|
{
|
||||||
|
struct Binary_r *blob;
|
||||||
|
struct AppointmentRecurrencePattern *pattern;
|
||||||
|
|
||||||
|
blob = [mapiRecurrenceData asBinaryInMemCtx: NULL];
|
||||||
|
pattern = get_AppointmentRecurrencePattern (blob, blob);
|
||||||
|
[(iCalCalendar *) parent
|
||||||
|
setupRecurrenceWithMasterEntity: self
|
||||||
|
fromRecurrencePattern: &pattern->RecurrencePattern];
|
||||||
|
talloc_free (blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) _setupEventAlarmFromProperties: (NSDictionary *) properties
|
||||||
|
{
|
||||||
|
NSArray *alarms;
|
||||||
|
iCalAlarm *currentAlarm, *alarm = nil;
|
||||||
|
iCalTrigger *trigger;
|
||||||
|
NSNumber *delta;
|
||||||
|
NSString *action;
|
||||||
|
NSUInteger count, max;
|
||||||
|
|
||||||
|
/* find and remove first display alarm */
|
||||||
|
alarms = [self alarms];
|
||||||
|
max = [alarms count];
|
||||||
|
for (count = 0; !alarm && count < max; count++)
|
||||||
|
{
|
||||||
|
currentAlarm = [alarms objectAtIndex: count];
|
||||||
|
action = [[currentAlarm action] lowercaseString];
|
||||||
|
if (!action || [action isEqualToString: @"display"])
|
||||||
|
alarm = currentAlarm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alarm)
|
||||||
|
[self removeChild: alarm];
|
||||||
|
|
||||||
|
if ([[properties objectForKey: MAPIPropertyKey (PidLidReminderSet)]
|
||||||
|
boolValue])
|
||||||
|
{
|
||||||
|
delta
|
||||||
|
= [properties objectForKey: MAPIPropertyKey (PidLidReminderDelta)];
|
||||||
|
if (delta)
|
||||||
|
{
|
||||||
|
alarm = [iCalAlarm new];
|
||||||
|
[alarm setAction: @"DISPLAY"];
|
||||||
|
trigger = [iCalTrigger elementWithTag: @"trigger"];
|
||||||
|
[trigger setValueType: @"DURATION"];
|
||||||
|
[trigger
|
||||||
|
setSingleValue: [NSString stringWithFormat: @"-PT%@M", delta]
|
||||||
|
forKey: @""];
|
||||||
|
[alarm setTrigger: trigger];
|
||||||
|
[self addToAlarms: alarm];
|
||||||
|
[alarm release];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) updateFromMAPIProperties: (NSDictionary *) properties
|
||||||
|
inUserContext: (MAPIStoreUserContext *) userContext
|
||||||
|
withActiveUser: (SOGoUser *) activeUser
|
||||||
|
{
|
||||||
|
BOOL isAllDay;
|
||||||
|
iCalDateTime *start, *end;
|
||||||
|
iCalTimeZone *tz;
|
||||||
|
NSTimeZone *userTimeZone;
|
||||||
|
NSString *priority;
|
||||||
|
NSUInteger responseStatus = 0;
|
||||||
|
NSInteger tzOffset;
|
||||||
|
SOGoUser *ownerUser;
|
||||||
|
id value;
|
||||||
|
|
||||||
|
// value = [properties objectForKey: MAPIPropertyKey (PidTagMessageClass)];
|
||||||
|
// if (value)
|
||||||
|
// isException = [value isEqualToString: @"IPM.OLE.CLASS.{00061055-0000-0000-C000-000000000046}"];
|
||||||
|
// else
|
||||||
|
// isException = NO;
|
||||||
|
|
||||||
|
userTimeZone = [userContext timeZone];
|
||||||
|
|
||||||
|
/* CREATED */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidTagCreationTime)];
|
||||||
|
if (value)
|
||||||
|
[self setCreated: value];
|
||||||
|
|
||||||
|
// LAST-MODIFIED = PidTagLastModificationTime
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidTagLastModificationTime)];
|
||||||
|
if (value)
|
||||||
|
[self setLastModified: value];
|
||||||
|
|
||||||
|
/* DTSTAMP = PidLidOwnerCriticalChange or PidLidAttendeeCriticalChange */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidOwnerCriticalChange)];
|
||||||
|
if (value)
|
||||||
|
[self setTimeStampAsDate: value];
|
||||||
|
|
||||||
|
/* SUMMARY */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidTagNormalizedSubject)];
|
||||||
|
if (value)
|
||||||
|
[self setSummary: value];
|
||||||
|
|
||||||
|
// Location
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidLocation)];
|
||||||
|
if (value)
|
||||||
|
[self setLocation: value];
|
||||||
|
|
||||||
|
isAllDay = [self isAllDay];
|
||||||
|
value = [properties
|
||||||
|
objectForKey: MAPIPropertyKey (PidLidAppointmentSubType)];
|
||||||
|
if (value)
|
||||||
|
isAllDay = [value boolValue];
|
||||||
|
if (!isAllDay)
|
||||||
|
{
|
||||||
|
tz = [iCalTimeZone timeZoneForName: [userTimeZone name]];
|
||||||
|
[(iCalCalendar *) parent addTimeZone: tz];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tz = nil;
|
||||||
|
|
||||||
|
// recurrence-id
|
||||||
|
value
|
||||||
|
= [properties objectForKey: MAPIPropertyKey (PidLidExceptionReplaceTime)];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
if (!isAllDay)
|
||||||
|
{
|
||||||
|
tzOffset = [userTimeZone secondsFromGMTForDate: value];
|
||||||
|
value = [value dateByAddingYears: 0 months: 0 days: 0
|
||||||
|
hours: 0 minutes: 0
|
||||||
|
seconds: tzOffset];
|
||||||
|
}
|
||||||
|
[self setRecurrenceId: value];
|
||||||
|
}
|
||||||
|
|
||||||
|
// start
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentStartWhole)];
|
||||||
|
if (!value)
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PR_START_DATE)];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
start = (iCalDateTime *) [self uniqueChildWithTag: @"dtstart"];
|
||||||
|
[start setTimeZone: tz];
|
||||||
|
if (isAllDay)
|
||||||
|
{
|
||||||
|
[start setDate: value];
|
||||||
|
[start setTimeZone: nil];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tzOffset = [userTimeZone secondsFromGMTForDate: value];
|
||||||
|
value = [value dateByAddingYears: 0 months: 0 days: 0
|
||||||
|
hours: 0 minutes: 0
|
||||||
|
seconds: tzOffset];
|
||||||
|
[start setDateTime: value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentEndWhole)];
|
||||||
|
if (!value)
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PR_END_DATE)];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
end = (iCalDateTime *) [self uniqueChildWithTag: @"dtend"];
|
||||||
|
[end setTimeZone: tz];
|
||||||
|
if (isAllDay)
|
||||||
|
{
|
||||||
|
[end setDate: value];
|
||||||
|
[end setTimeZone: nil];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tzOffset = [[value timeZone] secondsFromGMTForDate: value];
|
||||||
|
value = [value dateByAddingYears: 0 months: 0 days: 0
|
||||||
|
hours: 0 minutes: 0
|
||||||
|
seconds: tzOffset];
|
||||||
|
[end setDateTime: value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* priority */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey(PR_IMPORTANCE)];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
switch ([value intValue])
|
||||||
|
{
|
||||||
|
case 0: // IMPORTANCE_LOW
|
||||||
|
priority = @"9";
|
||||||
|
break;
|
||||||
|
case 2: // IMPORTANCE_HIGH
|
||||||
|
priority = @"1";
|
||||||
|
break;
|
||||||
|
default: // IMPORTANCE_NORMAL
|
||||||
|
priority = @"5";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
priority = @"0"; // None
|
||||||
|
[self setPriority: priority];
|
||||||
|
|
||||||
|
/* show time as free/busy/tentative/out of office. Possible values are:
|
||||||
|
0x00000000 - olFree
|
||||||
|
0x00000001 - olTentative
|
||||||
|
0x00000002 - olBusy
|
||||||
|
0x00000003 - olOutOfOffice */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey(PidLidBusyStatus)];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
switch ([value intValue])
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
[self setTransparency: @"TRANSPARENT"];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
default:
|
||||||
|
[self setTransparency: @"OPAQUE"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comment */
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PR_BODY_UNICODE)];
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PR_HTML)];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
value = [[NSString alloc] initWithData: value
|
||||||
|
encoding: NSUTF8StringEncoding];
|
||||||
|
[value autorelease];
|
||||||
|
value = [value htmlToText];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
if ([value length] == 0 || [value isEqualToString: @"\\n"])
|
||||||
|
value = nil;
|
||||||
|
[self setComment: value];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* recurrence */
|
||||||
|
value = [properties
|
||||||
|
objectForKey: MAPIPropertyKey (PidLidAppointmentRecur)];
|
||||||
|
if (value)
|
||||||
|
[self _setupEventRecurrence: value];
|
||||||
|
|
||||||
|
/* alarm */
|
||||||
|
[self _setupEventAlarmFromProperties: properties];
|
||||||
|
|
||||||
|
// Organizer
|
||||||
|
value = [properties objectForKey: @"recipients"];
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
NSArray *recipients;
|
||||||
|
NSDictionary *dict;
|
||||||
|
NSString *orgEmail, *sentBy, *attEmail;
|
||||||
|
iCalPerson *person;
|
||||||
|
iCalPersonPartStat newPartStat;
|
||||||
|
NSNumber *flags, *trackStatus;
|
||||||
|
int i, effective;
|
||||||
|
BOOL organizerIsSet = NO;
|
||||||
|
|
||||||
|
[self setOrganizer: nil];
|
||||||
|
[self removeAllAttendees];
|
||||||
|
|
||||||
|
recipients = [value objectForKey: @"to"];
|
||||||
|
effective = 0;
|
||||||
|
for (i = 0; i < [recipients count]; i++)
|
||||||
|
{
|
||||||
|
dict = [recipients objectAtIndex: i];
|
||||||
|
person = [iCalPerson new];
|
||||||
|
[person setCn: [dict objectForKey: @"fullName"]];
|
||||||
|
attEmail = [dict objectForKey: @"email"];
|
||||||
|
[person setEmail: attEmail];
|
||||||
|
|
||||||
|
flags = [dict objectForKey: MAPIPropertyKey (PR_RECIPIENT_FLAGS)];
|
||||||
|
if (!flags)
|
||||||
|
{
|
||||||
|
[self logWithFormat:
|
||||||
|
@"no recipient flags specified: skipping recipient"];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (([flags unsignedIntValue] & 0x0002)) /* recipOrganizer */
|
||||||
|
{
|
||||||
|
[self setOrganizer: person];
|
||||||
|
organizerIsSet = YES;
|
||||||
|
[self logWithFormat: @"organizer set via recipient flags"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOL isOrganizer = NO;
|
||||||
|
|
||||||
|
// /* Work-around: it happens that Outlook still passes the
|
||||||
|
// organizer as a recipient, maybe because of a feature
|
||||||
|
// documented in a pre-mesozoic PDF still buried in a
|
||||||
|
// cavern... In that case we remove it, and we keep the
|
||||||
|
// number of effective recipients in "effective". If the
|
||||||
|
// total is 0, we remove the "ORGANIZER" too. */
|
||||||
|
// if ([attEmail isEqualToString: orgEmail])
|
||||||
|
// {
|
||||||
|
// [self logWithFormat:
|
||||||
|
// @"avoiding setting organizer as recipient"];
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
trackStatus = [dict objectForKey: MAPIPropertyKey (PidTagRecipientTrackStatus)];
|
||||||
|
if (trackStatus)
|
||||||
|
{
|
||||||
|
/* FIXME: we should provide a data converter between OL
|
||||||
|
partstats and SOGo */
|
||||||
|
switch ([trackStatus unsignedIntValue])
|
||||||
|
{
|
||||||
|
case 0x01: /* respOrganized */
|
||||||
|
isOrganizer = YES;
|
||||||
|
break;
|
||||||
|
case 0x02: /* respTentative */
|
||||||
|
newPartStat = iCalPersonPartStatTentative;
|
||||||
|
break;
|
||||||
|
case 0x03: /* respAccepted */
|
||||||
|
newPartStat = iCalPersonPartStatAccepted;
|
||||||
|
break;
|
||||||
|
case 0x04: /* respDeclined */
|
||||||
|
newPartStat = iCalPersonPartStatDeclined;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newPartStat = iCalPersonPartStatNeedsAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOrganizer)
|
||||||
|
{
|
||||||
|
[self setOrganizer: person];
|
||||||
|
organizerIsSet = YES;
|
||||||
|
[self logWithFormat: @"organizer set via track status"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[person setParticipationStatus: newPartStat];
|
||||||
|
[person setRsvp: @"TRUE"];
|
||||||
|
[person setRole: @"REQ-PARTICIPANT"];
|
||||||
|
[self addToAttendees: person];
|
||||||
|
effective++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[self errorWithFormat: @"skipped recipient due"
|
||||||
|
@" to missing track status"];
|
||||||
|
}
|
||||||
|
|
||||||
|
[person release];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effective == 0) /* See work-around above */
|
||||||
|
[self setOrganizer: nil];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// SEQUENCE = PidLidAppointmentSequence
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidAppointmentSequence)];
|
||||||
|
if (value)
|
||||||
|
[self setSequence: value];
|
||||||
|
|
||||||
|
ownerUser = [userContext sogoUser];
|
||||||
|
if (organizerIsSet)
|
||||||
|
{
|
||||||
|
/* We must reset the participation status to the value
|
||||||
|
obtained from PidLidResponseStatus as the value in
|
||||||
|
PidTagRecipientTrackStatus is not correct. Note (hack):
|
||||||
|
the method used here requires that the user directory
|
||||||
|
from LDAP and Samba matches perfectly. This can be solved
|
||||||
|
more appropriately by making use of the sender
|
||||||
|
properties... */
|
||||||
|
person = [self userAsAttendee: ownerUser];
|
||||||
|
if (person)
|
||||||
|
{
|
||||||
|
value
|
||||||
|
= [properties objectForKey: MAPIPropertyKey (PidLidResponseStatus)];
|
||||||
|
if (value)
|
||||||
|
responseStatus = [value unsignedLongValue];
|
||||||
|
|
||||||
|
/* FIXME: we should provide a data converter between OL partstats and
|
||||||
|
SOGo */
|
||||||
|
switch (responseStatus)
|
||||||
|
{
|
||||||
|
case 0x02: /* respTentative */
|
||||||
|
newPartStat = iCalPersonPartStatTentative;
|
||||||
|
break;
|
||||||
|
case 0x03: /* respAccepted */
|
||||||
|
newPartStat = iCalPersonPartStatAccepted;
|
||||||
|
break;
|
||||||
|
case 0x04: /* respDeclined */
|
||||||
|
newPartStat = iCalPersonPartStatDeclined;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newPartStat = iCalPersonPartStatNeedsAction;
|
||||||
|
}
|
||||||
|
[person setParticipationStatus: newPartStat];
|
||||||
|
|
||||||
|
value = [properties objectForKey: MAPIPropertyKey (PidLidAttendeeCriticalChange)];
|
||||||
|
if (value && ![value isNever])
|
||||||
|
[self setTimeStampAsDate: value];
|
||||||
|
// if (newPartStat // != iCalPersonPartStatUndefined
|
||||||
|
// )
|
||||||
|
// {
|
||||||
|
// // iCalPerson *participant;
|
||||||
|
|
||||||
|
// // participant = [self userAsAttendee: ownerUser];
|
||||||
|
// // [participant setParticipationStatus: newPartStat];
|
||||||
|
// // [sogoObject saveComponent: self];
|
||||||
|
|
||||||
|
// [sogoObject changeParticipationStatus: newPartStat
|
||||||
|
// withDelegate: nil];
|
||||||
|
// // [[self context] tearDownRequest];
|
||||||
|
// }
|
||||||
|
// // }1005
|
||||||
|
|
||||||
|
// // else
|
||||||
|
// // {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self errorWithFormat: @"organizer was not set although a"
|
||||||
|
@" recipient list was specified"];
|
||||||
|
/* We must set the organizer preliminarily here because, unlike what
|
||||||
|
the doc states, Outlook does not always pass the real organizer
|
||||||
|
in the recipients list. */
|
||||||
|
dict = [ownerUser primaryIdentity];
|
||||||
|
person = [iCalPerson new];
|
||||||
|
[person setCn: [dict objectForKey: @"fullName"]];
|
||||||
|
orgEmail = [dict objectForKey: @"email"];
|
||||||
|
[person setEmail: orgEmail];
|
||||||
|
|
||||||
|
if (![activeUser isEqual: ownerUser])
|
||||||
|
{
|
||||||
|
dict = [activeUser primaryIdentity];
|
||||||
|
sentBy = [NSString stringWithFormat: @"mailto:%@",
|
||||||
|
[dict objectForKey: @"email"]];
|
||||||
|
[person setSentBy: sentBy];
|
||||||
|
}
|
||||||
|
[self setOrganizer: person];
|
||||||
|
[person release];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
35
OpenChange/iCalTimeZone+MAPIStore.h
Normal file
35
OpenChange/iCalTimeZone+MAPIStore.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* iCalTimeZone+MAPIStore.h - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ICALTIMEZONE_MAPISTORE_H
|
||||||
|
#define ICALTIMEZONE_MAPISTORE_H
|
||||||
|
|
||||||
|
#import <NGCards/iCalTimeZone.h>
|
||||||
|
|
||||||
|
@interface iCalTimeZone (MAPIStoreProperties)
|
||||||
|
|
||||||
|
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ICALTIMEZONE_MAPISTORE_H */
|
115
OpenChange/iCalTimeZone+MAPIStore.m
Normal file
115
OpenChange/iCalTimeZone+MAPIStore.m
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/* iCalTimeZone+MAPIStore.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Inverse inc
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSCalendarDate.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
#import <NGCards/iCalByDayMask.h>
|
||||||
|
#import <NGCards/iCalTimeZonePeriod.h>
|
||||||
|
#import <NGCards/iCalRecurrenceRule.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <talloc.h>
|
||||||
|
#undef DEBUG
|
||||||
|
#include <libmapi/libmapi.h>
|
||||||
|
|
||||||
|
#import "iCalTimeZone+MAPIStore.h"
|
||||||
|
|
||||||
|
@interface iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
|
||||||
|
|
||||||
|
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation iCalTimeZonePeriod (MAPIStorePropertiesPrivate)
|
||||||
|
|
||||||
|
- (void) _fillTZDate: (struct SYSTEMTIME *) tzData
|
||||||
|
{
|
||||||
|
iCalRecurrenceRule *rrule;
|
||||||
|
NSArray *byMonth;
|
||||||
|
iCalByDayMask *mask;
|
||||||
|
NSCalendarDate *dateValue;
|
||||||
|
|
||||||
|
rrule = [self recurrenceRule];
|
||||||
|
byMonth = [rrule byMonth];
|
||||||
|
if ([byMonth count] > 0)
|
||||||
|
{
|
||||||
|
tzData->wMonth = [[byMonth objectAtIndex: 0] intValue];
|
||||||
|
mask = [rrule byDayMask];
|
||||||
|
tzData->wDayOfWeek = [mask firstDay];
|
||||||
|
tzData->wDay = [mask firstOccurrence];
|
||||||
|
|
||||||
|
dateValue = [self startDate];
|
||||||
|
tzData->wHour = [dateValue hourOfDay];
|
||||||
|
tzData->wMinute = [dateValue minuteOfHour];
|
||||||
|
tzData->wSecond = [dateValue secondOfMinute];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation iCalTimeZone (MAPIStoreProperties)
|
||||||
|
|
||||||
|
- (iCalTimeZonePeriod *) _mostRecentPeriodWithName: (NSString *) periodName
|
||||||
|
{
|
||||||
|
NSArray *periods;
|
||||||
|
iCalTimeZonePeriod *period;
|
||||||
|
NSUInteger max;
|
||||||
|
|
||||||
|
periods = [self childrenWithTag: periodName];
|
||||||
|
max = [periods count];
|
||||||
|
if (max > 0)
|
||||||
|
{
|
||||||
|
periods = [periods sortedArrayUsingSelector: @selector (compare:)];
|
||||||
|
period = (iCalTimeZonePeriod *) [periods objectAtIndex: (max - 1)];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
period = nil;
|
||||||
|
|
||||||
|
return period;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (struct Binary_r *) asTimeZoneStructInMemCtx: (TALLOC_CTX *) memCtx
|
||||||
|
{
|
||||||
|
iCalTimeZonePeriod *period;
|
||||||
|
struct TimeZoneStruct tz;
|
||||||
|
int lBias, dlBias;
|
||||||
|
|
||||||
|
memset (&tz, 0, sizeof (struct TimeZoneStruct));
|
||||||
|
period = [self _mostRecentPeriodWithName: @"STANDARD"];
|
||||||
|
lBias = -[period secondsOffsetFromGMT] / 60;
|
||||||
|
tz.lBias = (uint32_t) lBias;
|
||||||
|
[period _fillTZDate: &tz.stStandardDate];
|
||||||
|
period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];
|
||||||
|
if (!period)
|
||||||
|
tz.stStandardDate.wMonth = 0;
|
||||||
|
dlBias = -([period secondsOffsetFromGMT] / 60) - lBias;
|
||||||
|
tz.lDaylightBias = (uint32_t) (dlBias);
|
||||||
|
[period _fillTZDate: &tz.stDaylightDate];
|
||||||
|
tz.wStandardYear = tz.stStandardDate.wYear;
|
||||||
|
tz.wDaylightYear = tz.stDaylightDate.wYear;
|
||||||
|
|
||||||
|
return set_TimeZoneStruct (memCtx, &tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue