2006-12-14 22:15:05 +01:00
/ * SOGoCalendarComponent . m - this file is part of SOGo
*
2019-02-04 17:52:26 +01:00
* Copyright ( C ) 2006 -2019 Inverse inc .
2006-12-14 22:15:05 +01:00
*
* 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 .
* /
2014-02-14 22:39:26 +01:00
# import < Foundation / NSAutoreleasePool . h >
2011-10-03 21:32:37 +02:00
# import < Foundation / NSValue . h >
2007-01-31 21:15:28 +01:00
2007-08-07 20:37:31 +02:00
# import < NGObjWeb / NSException + HTTP . h >
# import < NGObjWeb / SoSecurityManager . h >
# import < NGObjWeb / WOApplication . h >
# import < NGObjWeb / WOContext + SoObjects . h >
2007-12-06 23:54:01 +01:00
# import < NGObjWeb / WORequest + So . h >
2007-08-09 22:58:01 +02:00
# import < NGExtensions / NSObject + Logs . h >
# import < NGExtensions / NGHashMap . h >
2010-04-09 20:45:14 +02:00
# import < NGExtensions / NGQuotedPrintableCoding . h >
2006-12-14 22:15:05 +01:00
# import < NGCards / iCalCalendar . h >
2008-12-05 17:11:41 +01:00
# import < NGCards / iCalDateTime . h >
2007-11-18 11:16:25 +01:00
# import < NGCards / iCalEvent . h >
2016-07-20 19:31:15 +02:00
# import < NGCards / iCalToDo . h >
2007-08-09 22:58:01 +02:00
# import < NGMime / NGMimeBodyPart . h >
# import < NGMime / NGMimeMultipartBody . h >
# import < NGMail / NGMimeMessage . h >
2011-10-03 21:32:37 +02:00
# import < GDLContentStore / GCSFolder . h >
2007-01-31 21:15:28 +01:00
2009-08-25 23:28:24 +02:00
# import < SOGo / NSCalendarDate + SOGo . h >
# import < SOGo / NSDictionary + Utilities . h >
2010-02-02 22:42:17 +01:00
# import < SOGo / NSObject + DAV . h >
2010-04-09 20:45:14 +02:00
# import < SOGo / NSObject + Utilities . h >
2016-05-27 16:53:16 +02:00
# import < SOGo / NSString + Crypto . h >
2010-04-09 20:45:14 +02:00
# import < SOGo / NSString + Utilities . h >
2011-03-30 17:01:55 +02:00
# import < SOGo / SOGoBuild . h >
2009-08-25 23:28:24 +02:00
# import < SOGo / SOGoMailer . h >
2019-11-26 15:29:02 +01:00
# import < SOGo / SOGoSource . h >
2009-08-25 23:28:24 +02:00
# import < SOGo / SOGoPermissions . h >
# import < SOGo / SOGoUser . h >
2016-05-27 16:53:16 +02:00
# import < SOGo / SOGoUserSettings . h >
2011-02-15 20:00:40 +01:00
# import < SOGo / SOGoSystemDefaults . h >
2010-02-02 22:42:17 +01:00
# import < SOGo / SOGoUserManager . h >
# import < SOGo / SOGoWebDAVAclManager . h >
2009-08-25 23:28:24 +02:00
# import < SOGo / WORequest + SOGo . h >
# import < Appointments / SOGoAppointmentFolder . h >
2014-02-07 16:51:42 +01:00
# import < Mailer / NSString + Mail . h >
2007-01-31 21:15:28 +01:00
2007-11-18 11:16:25 +01:00
# import "SOGoAptMailICalReply.h"
2009-08-25 23:28:24 +02:00
# import "SOGoAptMailReceipt.h"
2010-08-19 19:40:28 +02:00
# import "SOGoEMailAlarmsManager.h"
2007-06-01 22:42:39 +02:00
# import "iCalEntityObject+SOGo.h"
2007-11-18 11:16:25 +01:00
# import "iCalPerson+SOGo.h"
2008-07-17 23:12:43 +02:00
# import "iCalRepeatableEntityObject+SOGo.h"
2006-12-14 22:15:05 +01:00
# import "SOGoCalendarComponent.h"
@ implementation SOGoCalendarComponent
2010-02-02 22:42:17 +01:00
+ ( SOGoWebDAVAclManager * ) webdavAclManager
{
static SOGoWebDAVAclManager * aclManager = nil ;
NSString * nsD , * nsI ;
if ( ! aclManager )
{
nsD = @ "DAV:" ;
nsI = @ "urn:inverse:params:xml:ns:inverse-dav" ;
aclManager = [ SOGoWebDAVAclManager new ] ;
[ aclManager registerDAVPermission : davElement ( @ "read" , nsD )
abstract : NO
withEquivalent : @ "SOGoDAVReadPermission" / * hackish * /
asChildOf : davElement ( @ "all" , nsD ) ] ;
[ aclManager registerDAVPermission : davElement ( @ "view-whole-component" , nsI )
abstract : NO
withEquivalent : SOGoCalendarPerm_ViewAllComponent
asChildOf : davElement ( @ "all" , nsD ) ] ;
[ aclManager registerDAVPermission : davElement ( @ "view-date-and-time" , nsI )
abstract : NO
withEquivalent : SOGoCalendarPerm_ViewDAndT
asChildOf : davElement ( @ "all" , nsD ) ] ;
[ aclManager registerDAVPermission : davElement ( @ "read-current-user-privilege-set" , nsD )
abstract : NO
withEquivalent : SoPerm_WebDAVAccess
asChildOf : davElement ( @ "all" , nsD ) ] ;
[ aclManager registerDAVPermission : davElement ( @ "write" , nsD )
abstract : NO
withEquivalent : SOGoCalendarPerm_ModifyComponent
asChildOf : davElement ( @ "all" , nsD ) ] ;
[ aclManager
registerDAVPermission : davElement ( @ "write-properties" , nsD )
abstract : YES
withEquivalent : SoPerm_ChangePermissions / * hackish * /
asChildOf : davElement ( @ "write" , nsD ) ] ;
[ aclManager
registerDAVPermission : davElement ( @ "write-content" , nsD )
abstract : YES
withEquivalent : nil
asChildOf : davElement ( @ "write" , nsD ) ] ;
[ aclManager
registerDAVPermission : davElement ( @ "respond-to-component" , nsI )
abstract : NO
withEquivalent : SOGoCalendarPerm_RespondToComponent
asChildOf : davElement ( @ "write-content" , nsD ) ] ;
[ aclManager registerDAVPermission : davElement ( @ "admin" , nsI )
abstract : YES
withEquivalent : nil
asChildOf : davElement ( @ "all" , nsD ) ] ;
[ aclManager
registerDAVPermission : davElement ( @ "read-acl" , nsD )
abstract : YES
withEquivalent : SOGoPerm_ReadAcls
asChildOf : davElement ( @ "admin" , nsI ) ] ;
[ aclManager
registerDAVPermission : davElement ( @ "write-acl" , nsD )
abstract : YES
withEquivalent : nil
asChildOf : davElement ( @ "admin" , nsI ) ] ;
}
return aclManager ;
}
2016-02-17 17:04:28 +01:00
- ( void ) setIsNew : ( BOOL ) newIsNew
{
2016-03-07 16:46:40 +01:00
[ super setIsNew : newIsNew ] ;
2016-02-17 17:04:28 +01:00
}
- ( BOOL ) isNew
{
2016-03-07 16:46:40 +01:00
return [ super isNew ] ;
2016-02-17 17:04:28 +01:00
}
2015-11-03 22:37:39 +01:00
- ( NSException * ) changeParticipationStatus : ( NSString * ) newPartStat
withDelegate : ( iCalPerson * ) delegate
2015-11-04 01:18:23 +01:00
alarm : ( iCalAlarm * ) alarm
2015-11-03 22:37:39 +01:00
{
2015-11-04 01:18:23 +01:00
// Required for protocol < SOGoComponentOccurence >
2015-11-03 22:37:39 +01:00
return nil ;
}
2008-07-17 23:12:43 +02:00
- ( id ) init
{
if ( ( self = [ super init ] ) )
{
fullCalendar = nil ;
safeCalendar = nil ;
originalCalendar = nil ;
2008-11-18 01:06:37 +01:00
componentTag = nil ;
2008-07-17 23:12:43 +02:00
}
return self ;
}
- ( void ) dealloc
{
[ fullCalendar release ] ;
[ safeCalendar release ] ;
[ originalCalendar release ] ;
2008-11-18 01:06:37 +01:00
[ componentTag release ] ;
2008-07-17 23:12:43 +02:00
[ super dealloc ] ;
}
2011-07-05 15:24:25 +02:00
- ( void ) flush
{
DESTROY ( fullCalendar ) ;
DESTROY ( safeCalendar ) ;
DESTROY ( originalCalendar ) ;
}
2014-07-30 20:51:00 +02:00
- ( Class * ) parsingClass
{
2015-10-31 07:10:03 +01:00
return ( Class * ) [ iCalCalendar class ] ;
2014-07-30 20:51:00 +02:00
}
2007-01-31 21:15:28 +01:00
- ( NSString * ) davContentType
2006-12-14 22:15:05 +01:00
{
2007-01-31 21:15:28 +01:00
return @ "text/calendar" ;
2006-12-14 22:15:05 +01:00
}
2007-02-15 21:59:02 +01:00
- ( NSString * ) componentTag
{
2008-11-18 01:06:37 +01:00
if ( ! componentTag )
[ self subclassResponsibility : _cmd ] ;
2008-11-22 22:52:40 +01:00
2008-11-18 01:06:37 +01:00
return componentTag ;
}
- ( void ) setComponentTag : ( NSString * ) theTag
{
ASSIGN ( componentTag , theTag ) ;
2007-02-15 21:59:02 +01:00
}
2007-04-26 03:16:19 +02:00
- ( void ) _filterComponent : ( iCalEntityObject * ) component
2007-03-07 22:33:13 +01:00
{
2016-05-27 16:53:16 +02:00
NSString * type , * summary , * tag , * uid ;
SOGoUserSettings * settings ;
SOGoUser * calendarOwner ;
NSEnumerator * children ;
CardElement * element ;
NSArray * tags ;
2016-05-26 20:42:13 +02:00
2016-05-27 16:53:16 +02:00
int classification ;
2009-01-06 16:40:27 +01:00
type = @ "vtodo" ;
classification = 0 ;
2016-05-27 16:53:16 +02:00
calendarOwner = [ SOGoUser userWithLogin : [ self ownerInContext : context ] ] ;
settings = [ calendarOwner userSettings ] ;
2009-01-06 16:40:27 +01:00
if ( [ component isKindOfClass : [ iCalEvent class ] ] )
type = @ "vevent" ;
if ( [ component symbolicAccessClass ] = = iCalAccessPrivate )
classification = 1 ;
2009-01-20 20:23:09 +01:00
else if ( [ component symbolicAccessClass ] = = iCalAccessConfidential )
2009-01-06 16:40:27 +01:00
classification = 2 ;
2010-04-09 20:45:14 +02:00
summary = [ self labelForKey : [ NSString stringWithFormat : @ "%@_class%d" ,
type , classification ]
inContext : context ] ;
2016-05-27 16:53:16 +02:00
2016-11-24 21:43:37 +01:00
tags = [ NSArray arrayWithObjects : @ "DTSTAMP" , @ "DTSTART" , @ "DTEND" , @ "DUE" , @ "EXDATE" , @ "EXRULE" , @ "RRULE" , @ "RECURRENCE-ID" , nil ] ;
2016-05-27 16:53:16 +02:00
uid = [ [ component uid ] asCryptedPassUsingScheme : @ "ssha256"
withSalt : [ [ settings userSalt ] dataUsingEncoding : NSASCIIStringEncoding ]
2020-01-06 21:47:47 +01:00
andEncoding : encHex
keyPath : nil ] ;
2016-05-27 16:53:16 +02:00
children = [ [ [ [ component children ] copy ] autorelease ] objectEnumerator ] ;
while ( ( element = [ children nextObject ] ) )
2016-05-26 20:42:13 +02:00
{
2016-05-27 16:53:16 +02:00
tag = [ element tag ] ;
if ( ! [ tags containsObject : [ tag uppercaseString ] ] )
[ component removeChild : element ] ;
2016-05-26 20:42:13 +02:00
}
2016-05-27 16:53:16 +02:00
[ component setSummary : summary ] ;
[ component setUid : uid ] ;
2007-03-07 22:33:13 +01:00
}
2007-11-18 11:16:25 +01:00
- ( NSString * ) secureContentAsString
2007-03-07 22:33:13 +01:00
{
iCalRepeatableEntityObject * tmpComponent ;
2014-02-05 23:30:34 +01:00
iCalCalendar * tmpCalendar ;
NSArray * allComponents ;
2007-07-04 22:12:28 +02:00
SoSecurityManager * sm ;
2007-11-18 11:16:25 +01:00
NSString * iCalString ;
2007-03-07 22:33:13 +01:00
2014-02-05 23:30:34 +01:00
int i ;
2007-07-04 22:12:28 +02:00
2007-11-18 11:16:25 +01:00
sm = [ SoSecurityManager sharedSecurityManager ] ;
2008-06-13 22:22:51 +02:00
if ( activeUserIsOwner
|| [ [ self ownerInContext : context ] isEqualToString : [ [ context activeUser ] login ] ]
|| ! [ sm validatePermission : SOGoCalendarPerm_ViewAllComponent
onObject : self inContext : context ] )
iCalString = content ;
2007-11-18 11:16:25 +01:00
else if ( ! [ sm validatePermission : SOGoCalendarPerm_ViewDAndT
onObject : self inContext : context ] )
{
2008-07-23 19:40:51 +02:00
tmpCalendar = [ [ self calendar : NO secure : NO ] mutableCopy ] ;
2014-02-05 23:30:34 +01:00
// We filter all components , in case we have RECURRENCE - ID
allComponents = [ tmpCalendar childrenWithTag : [ self componentTag ] ] ;
for ( i = 0 ; i < [ allComponents count ] ; i + + )
{
tmpComponent = ( iCalRepeatableEntityObject * ) [ allComponents objectAtIndex : i ] ;
[ self _filterComponent : tmpComponent ] ;
2009-01-06 16:40:27 +01:00
2014-02-05 23:30:34 +01:00
// We add an additional header here to inform clients ( if necessary ) that
// we churned the content of the calendar .
[ tmpComponent addChild : [ CardElement simpleElementWithTag : @ "X-SOGo-Secure"
value : @ "YES" ] ] ;
}
2007-11-18 11:16:25 +01:00
iCalString = [ tmpCalendar versitString ] ;
[ tmpCalendar release ] ;
2007-03-07 22:33:13 +01:00
}
2007-11-18 11:16:25 +01:00
else
iCalString = nil ;
2007-03-07 22:33:13 +01:00
2007-11-18 11:16:25 +01:00
return iCalString ;
2007-11-13 23:38:05 +01:00
}
2007-03-07 22:33:13 +01:00
2012-07-13 22:31:41 +02:00
- ( iCalRepeatableEntityObject * ) lookupOccurrence : ( NSString * ) recID
2008-07-17 23:12:43 +02:00
{
2012-07-13 22:31:41 +02:00
[ self subclassResponsibility : _cmd ] ;
2008-07-17 23:12:43 +02:00
2012-07-13 22:31:41 +02:00
return nil ;
2008-07-17 23:12:43 +02:00
}
- ( SOGoComponentOccurence * ) occurence : ( iCalRepeatableEntityObject * ) component
{
[ self subclassResponsibility : _cmd ] ;
return nil ;
}
- ( iCalRepeatableEntityObject * ) newOccurenceWithID : ( NSString * ) recID
{
iCalRepeatableEntityObject * masterOccurence , * newOccurence ;
iCalCalendar * calendar ;
NSCalendarDate * recDate ;
2011-02-23 17:26:57 +01:00
NSTimeZone * timeZone ;
2012-07-24 15:58:47 +02:00
iCalPerson * organizer ;
2008-07-17 23:12:43 +02:00
recDate = [ NSCalendarDate dateWithTimeIntervalSince1970 : [ recID intValue ] ] ;
masterOccurence = [ self component : NO secure : NO ] ;
2011-02-23 17:26:57 +01:00
timeZone = [ [ [ context activeUser ] userDefaults ] timeZone ] ;
[ recDate setTimeZone : timeZone ] ;
2008-07-17 23:12:43 +02:00
if ( [ masterOccurence doesOccurOnDate : recDate ] )
{
newOccurence = [ masterOccurence mutableCopy ] ;
2012-07-24 15:58:47 +02:00
organizer = [ masterOccurence organizer ] ;
2008-07-17 23:12:43 +02:00
[ newOccurence autorelease ] ;
[ newOccurence removeAllRecurrenceRules ] ;
[ newOccurence removeAllExceptionRules ] ;
2017-12-15 22:17:51 +01:00
[ newOccurence removeAllRecurrenceDates ] ;
2008-07-17 23:12:43 +02:00
[ newOccurence removeAllExceptionDates ] ;
2012-07-24 16:08:56 +02:00
// It is important to set the organizer as some DAV clients ( iCal
// and Thunderbird 10 / Lightning 1.2 ) will prompt the event "edition"
// dialog instead of the event "invitation" ( for accept / decline / tentative )
// if the organizer isn ' t found in a specific recurrence
2012-07-24 15:58:47 +02:00
[ newOccurence setOrganizer : organizer ] ;
2008-07-17 23:12:43 +02:00
[ newOccurence setRecurrenceId : recDate ] ;
2008-11-03 15:16:32 +01:00
calendar = [ masterOccurence parent ] ;
2008-07-17 23:12:43 +02:00
[ calendar addChild : newOccurence ] ;
}
else
newOccurence = nil ;
return newOccurence ;
}
- ( id ) toManyRelationshipKeys
{
return nil ;
}
- ( id ) toOneRelationshipKeys
{
NSMutableArray * keys ;
NSArray * occurences ;
NSCalendarDate * recID ;
unsigned int count , max , seconds ;
keys = [ NSMutableArray array ] ;
[ keys addObject : @ "master" ] ;
occurences = [ [ self calendar : NO secure : NO ] allObjects ] ;
max = [ occurences count ] ;
for ( count = 1 ; count < max ; count + + )
{
recID = [ [ occurences objectAtIndex : count ] recurrenceId ] ;
if ( recID )
{
seconds = [ recID timeIntervalSince1970 ] ;
[ keys addObject : [ NSString stringWithFormat : @ "occurence%d" ,
seconds ] ] ;
}
}
return keys ;
}
- ( id ) lookupName : ( NSString * ) lookupName
inContext : ( id ) localContext
acquire : ( BOOL ) acquire
{
id obj ;
iCalRepeatableEntityObject * occurence ;
NSString * recID ;
BOOL isNewOccurence ;
obj = [ super lookupName : lookupName
inContext : localContext
acquire : acquire ] ;
if ( ! obj )
{
if ( [ lookupName isEqualToString : @ "master" ] )
obj = [ self occurence : [ self component : NO secure : NO ] ] ;
else if ( [ lookupName hasPrefix : @ "occurence" ] )
{
recID = [ lookupName substringFromIndex : 9 ] ;
2012-07-13 22:31:41 +02:00
occurence = [ self lookupOccurrence : recID ] ;
2009-03-16 22:02:59 +01:00
if ( occurence )
2012-06-04 17:29:38 +02:00
isNewOccurence = NO ;
else
2008-07-17 23:12:43 +02:00
{
occurence = [ self newOccurenceWithID : recID ] ;
isNewOccurence = YES ;
}
if ( occurence )
{
obj = [ self occurence : occurence ] ;
if ( isNewOccurence )
[ obj setIsNew : isNewOccurence ] ;
}
}
}
return obj ;
}
2011-04-01 19:54:23 +02:00
- ( NSString * ) _secureContentWithoutAlarms
{
iCalCalendar * calendar ;
NSArray * allComponents ;
iCalEntityObject * currentComponent ;
NSUInteger count , max ;
calendar = [ self calendar : NO secure : YES ] ;
allComponents = [ calendar childrenWithTag : [ self componentTag ] ] ;
max = [ allComponents count ] ;
for ( count = 0 ; count < max ; count + + )
{
currentComponent = [ allComponents objectAtIndex : count ] ;
[ currentComponent removeAllAlarms ] ;
}
return [ calendar versitString ] ;
}
2007-12-06 23:54:01 +01:00
- ( NSString * ) contentAsString
{
NSString * secureContent ;
if ( [ [ context request ] isSoWebDAVRequest ] )
2011-04-01 19:54:23 +02:00
{
if ( [ container showCalendarAlarms ] )
secureContent = [ self secureContentAsString ] ;
else
secureContent = [ self _secureContentWithoutAlarms ] ;
}
2007-12-06 23:54:01 +01:00
else
secureContent = [ super contentAsString ] ;
return secureContent ;
}
2008-03-18 18:26:34 +01:00
- ( NSString * ) davCalendarData
{
return [ self contentAsString ] ;
}
2007-11-18 11:16:25 +01:00
- ( iCalCalendar * ) calendar : ( BOOL ) create secure : ( BOOL ) secure
2006-12-14 22:15:05 +01:00
{
2008-07-17 23:12:43 +02:00
iCalRepeatableEntityObject * newComponent ;
2008-08-05 03:53:01 +02:00
iCalCalendar * * calendar , * returnedCopy ;
2011-03-30 17:01:55 +02:00
NSString * iCalString , * tag , * prodID ;
2007-11-18 11:16:25 +01:00
if ( secure )
2008-07-17 23:12:43 +02:00
calendar = & safeCalendar ;
2007-11-18 11:16:25 +01:00
else
2008-07-17 23:12:43 +02:00
calendar = & fullCalendar ;
2006-12-14 22:15:05 +01:00
2008-07-17 23:12:43 +02:00
if ( ! * calendar )
2006-12-14 22:15:05 +01:00
{
2008-07-17 23:12:43 +02:00
if ( secure )
iCalString = [ self secureContentAsString ] ;
else
iCalString = content ;
if ( [ iCalString length ] > 0 )
2007-11-18 11:16:25 +01:00
{
2008-07-17 23:12:43 +02:00
ASSIGN ( * calendar , [ iCalCalendar parseSingleFromSource : iCalString ] ) ;
if ( ! secure )
originalCalendar = [ * calendar copy ] ;
2007-11-18 11:16:25 +01:00
}
2007-03-18 16:08:41 +01:00
else
2008-07-17 23:12:43 +02:00
{
if ( create )
{
ASSIGN ( * calendar , [ iCalCalendar groupWithTag : @ "vcalendar" ] ) ;
[ * calendar setVersion : @ "2.0" ] ;
2011-03-30 17:01:55 +02:00
prodID = [ NSString stringWithFormat :
@ "-//Inverse inc./SOGo %@//EN" ,
SOGoVersion ] ;
[ * calendar setProdID : prodID ] ;
2008-11-18 01:06:37 +01:00
tag = [ [ self componentTag ] uppercaseString ] ;
newComponent = [ [ * calendar classForTag : tag ]
groupWithTag : tag ] ;
2008-07-17 23:12:43 +02:00
[ newComponent setUid : [ self globallyUniqueObjectId ] ] ;
[ * calendar addChild : newComponent ] ;
}
}
2006-12-14 22:15:05 +01:00
}
2008-08-05 03:53:01 +02:00
returnedCopy = [ * calendar mutableCopy ] ;
[ returnedCopy autorelease ] ;
return returnedCopy ;
2006-12-14 22:15:05 +01:00
}
2007-11-18 11:16:25 +01:00
- ( id ) component : ( BOOL ) create secure : ( BOOL ) secure
2007-01-31 19:43:15 +01:00
{
2007-11-18 11:16:25 +01:00
return [ [ self calendar : create secure : secure ]
firstChildWithTag : [ self componentTag ] ] ;
2007-01-04 16:18:30 +01:00
}
2009-05-06 23:57:21 +02:00
//
// Returs "YES" if a a group was decomposed among attendees .
//
2012-06-19 15:17:48 +02:00
// It can also return yes if an attendee was found in the list
// matching the organizer . In which case , it was removed .
//
2009-05-06 23:57:21 +02:00
- ( BOOL ) expandGroupsInEvent : ( iCalEvent * ) theEvent
{
2009-11-29 05:19:32 +01:00
NSString * organizerEmail , * domain ;
2012-06-19 15:17:48 +02:00
NSMutableArray * allAttendees ;
2009-05-06 23:57:21 +02:00
iCalPerson * currentAttendee ;
2012-06-19 15:17:48 +02:00
NSEnumerator * enumerator ;
2014-02-14 22:39:26 +01:00
NSAutoreleasePool * pool ;
2019-11-26 15:29:02 +01:00
NSDictionary * dict ;
2012-06-19 15:17:48 +02:00
BOOL eventWasModified ;
2014-02-14 22:39:26 +01:00
unsigned int i , j ;
2009-05-06 23:57:21 +02:00
2009-11-29 05:19:32 +01:00
domain = [ [ context activeUser ] domain ] ;
2009-05-06 23:57:21 +02:00
organizerEmail = [ [ theEvent organizer ] rfc822Email ] ;
2012-06-19 15:17:48 +02:00
eventWasModified = NO ;
2009-05-06 23:57:21 +02:00
allAttendees = [ NSMutableArray arrayWithArray : [ theEvent attendees ] ] ;
enumerator = [ [ theEvent attendees ] objectEnumerator ] ;
2014-02-14 22:39:26 +01:00
j = 0 ;
pool = [ [ NSAutoreleasePool alloc ] init ] ;
2009-05-06 23:57:21 +02:00
while ( ( currentAttendee = [ enumerator nextObject ] ) )
{
2014-02-14 22:39:26 +01:00
if ( j % 5 = = 0 )
{
RELEASE ( pool ) ;
pool = [ [ NSAutoreleasePool alloc ] init ] ;
}
2019-12-04 10:37:08 +01:00
dict = [ [ SOGoUserManager sharedUserManager ] contactInfosForUserWithUIDorEmail : [ currentAttendee rfc822Email ]
inDomain : domain ] ;
2019-11-26 15:29:02 +01:00
if ( dict && [ [ dict objectForKey : @ "isGroup" ] boolValue ] )
{
2009-05-06 23:57:21 +02:00
iCalPerson * person ;
NSArray * members ;
2019-11-26 22:20:28 +01:00
NSDictionary * user ;
2019-11-26 15:29:02 +01:00
id < SOGoSource > source ;
2009-05-06 23:57:21 +02:00
// We did decompose a group . . .
[ allAttendees removeObject : currentAttendee ] ;
2019-11-26 15:29:02 +01:00
source = [ [ SOGoUserManager sharedUserManager ] sourceWithID : [ dict objectForKey : @ "SOGoSource" ] ] ;
2019-12-04 10:37:08 +01:00
if ( [ source conformsToProtocol : @ protocol ( SOGoMembershipSource ) ] )
2019-11-26 15:29:02 +01:00
{
2019-12-04 10:37:08 +01:00
members = [ ( id < SOGoMembershipSource > ) ( source ) membersForGroupWithUID : [ dict objectForKey : @ "c_uid" ] ] ;
2019-11-26 15:29:02 +01:00
for ( i = 0 ; i < [ members count ] ; i + + )
{
user = [ members objectAtIndex : i ] ;
eventWasModified = YES ;
// If the organizer is part of the group , we skip it from
// the addition to the attendees ' list
2019-11-26 22:20:28 +01:00
if ( [ [ user objectForKey : @ "c_emails" ] containsObject : organizerEmail ] )
2019-11-26 15:29:02 +01:00
continue ;
2019-11-26 22:20:28 +01:00
person = [ self iCalPersonWithUID : [ user objectForKey : @ "c_uid" ] ] ;
2019-11-26 15:29:02 +01:00
[ person setTag : @ "ATTENDEE" ] ;
[ person setParticipationStatus : [ currentAttendee participationStatus ] ] ;
[ person setRsvp : [ currentAttendee rsvp ] ] ;
[ person setRole : [ currentAttendee role ] ] ;
if ( ! [ allAttendees containsObject : person ] )
[ allAttendees addObject : person ] ;
}
}
2020-05-26 15:25:25 +02:00
else
{
[ self errorWithFormat : @ "Inconsistency error - got group identifier (%@) from a source (%@) that does not support groups." , [ currentAttendee rfc822Email ] , [ dict objectForKey : @ "SOGoSource" ] ] ;
RELEASE ( pool ) ;
return NO ;
}
2009-05-06 23:57:21 +02:00
}
2014-02-14 22:39:26 +01:00
j + + ;
2012-06-19 15:17:48 +02:00
} // while ( currentAttendee . . .
2009-05-06 23:57:21 +02:00
2012-06-19 15:17:48 +02:00
if ( eventWasModified )
2009-05-06 23:57:21 +02:00
[ theEvent setAttendees : allAttendees ] ;
2014-02-14 22:39:26 +01:00
RELEASE ( pool ) ;
2012-06-19 15:17:48 +02:00
return eventWasModified ;
2009-05-06 23:57:21 +02:00
}
2008-12-05 17:11:41 +01:00
- ( void ) _updateRecurrenceIDsWithEvent : ( iCalRepeatableEntityObject * ) newEvent
2008-07-17 23:12:43 +02:00
{
2008-12-05 17:11:41 +01:00
iCalRepeatableEntityObject * oldMaster , * currentComponent ;
iCalDateTime * currentDate ;
2008-07-17 23:12:43 +02:00
int deltaSecs ;
2008-12-05 17:11:41 +01:00
NSArray * components , * dates ;
NSMutableArray * newDates ;
2008-07-17 23:12:43 +02:00
unsigned int count , max ;
2008-12-05 17:11:41 +01:00
NSCalendarDate * recID , * newDate ;
2008-07-17 23:12:43 +02:00
2008-12-05 17:11:41 +01:00
// Compute time interval from previous event definition .
2009-07-14 16:55:59 +02:00
if ( ! originalCalendar )
{
if ( content )
ASSIGN ( originalCalendar , [ iCalCalendar parseSingleFromSource : content ] ) ;
else
2017-01-13 19:16:01 +01:00
{
[ self warnWithFormat : @ "content not available, we don't update the event" ] ;
return ;
}
2009-07-14 16:55:59 +02:00
}
2008-07-17 23:12:43 +02:00
oldMaster = ( iCalRepeatableEntityObject * )
[ originalCalendar firstChildWithTag : [ self componentTag ] ] ;
2008-12-05 17:11:41 +01:00
deltaSecs = [ [ newEvent startDate ]
2008-07-17 23:12:43 +02:00
timeIntervalSinceDate : [ oldMaster startDate ] ] ;
2008-12-05 17:11:41 +01:00
components = [ [ newEvent parent ] events ] ;
2008-07-17 23:12:43 +02:00
max = [ components count ] ;
2008-12-05 17:11:41 +01:00
if ( max > 0 )
2008-07-17 23:12:43 +02:00
{
2008-12-05 17:11:41 +01:00
// Update recurrence - id attribute of occurences .
for ( count = 1 ; count < max ; count + + )
{
currentComponent = [ components objectAtIndex : count ] ;
recID = [ [ currentComponent recurrenceId ] addTimeInterval : deltaSecs ] ;
[ currentComponent setRecurrenceId : recID ] ;
}
// Update exception dates in master vEvent .
currentComponent = [ components objectAtIndex : 0 ] ;
dates = [ currentComponent childrenWithTag : @ "exdate" ] ;
max = [ dates count ] ;
if ( max > 0 )
{
newDates = [ NSMutableArray arrayWithCapacity : max ] ;
for ( count = 0 ; count < max ; count + + )
{
currentDate = [ dates objectAtIndex : count ] ;
newDate = [ [ currentDate dateTime ] addTimeInterval : deltaSecs ] ;
[ newDates addObject : newDate ] ;
}
[ currentComponent removeAllExceptionDates ] ;
for ( count = 0 ; count < max ; count + + )
[ currentComponent addToExceptionDates : [ newDates objectAtIndex : count ] ] ;
2008-12-31 03:57:54 +01:00
}
2008-07-17 23:12:43 +02:00
}
}
2011-03-30 01:25:40 +02:00
- ( void ) updateComponent : ( iCalRepeatableEntityObject * ) newObject
2007-01-31 19:43:15 +01:00
{
2011-03-30 01:25:40 +02:00
NSString * newUid ;
2007-01-04 16:18:30 +01:00
2008-07-17 23:12:43 +02:00
if ( ! isNew
&& [ newObject isRecurrent ] )
2008-12-05 17:11:41 +01:00
// We update an repeating event - - update exception dates
// and recurrence - ids .
[ self _updateRecurrenceIDsWithEvent : newObject ] ;
2008-12-01 20:20:25 +01:00
// As much as we can , we try to use c_name = = c_uid in order
// to avoid tricky scenarios with some CalDAV clients . For example ,
// if Alice invites Bob ( both use SOGo ) and Bob accepts the invitation
2014-12-19 01:34:05 +01:00
// using Lightning before having refreshed their calendar , they ' ll end up
// with a duplicate of the event in their database tables .
2008-12-01 20:20:25 +01:00
if ( isNew )
{
newUid = nameInContainer ;
if ( [ newUid hasSuffix : @ ".ics" ] )
newUid = [ newUid substringToIndex : [ newUid length ] -4 ] ;
[ newObject setUid : newUid ] ;
}
2011-03-30 01:25:40 +02:00
}
2012-07-13 22:36:19 +02:00
- ( NSException * ) saveCalendar : ( iCalCalendar * ) newCalendar
2011-03-30 01:25:40 +02:00
{
2014-07-30 20:51:00 +02:00
[ super saveComponent : newCalendar ] ;
2011-04-25 12:31:08 +02:00
return nil ;
2007-01-04 16:18:30 +01:00
}
2012-07-13 22:36:19 +02:00
- ( NSException * ) saveComponent : ( iCalRepeatableEntityObject * ) newObject
{
2018-03-15 20:43:26 +01:00
[ newObject setLastModified : [ NSCalendarDate calendarDate ] ] ;
2012-07-13 22:36:19 +02:00
return [ self saveCalendar : [ newObject parent ] ] ;
}
2016-02-11 16:54:07 +01:00
- ( NSException * ) saveComponent : ( iCalRepeatableEntityObject * ) newEvent
force : ( BOOL ) forceSave
{
return [ self saveComponent : newEvent ] ;
}
2007-11-18 11:16:25 +01:00
/ * raw saving * /
2006-12-14 22:15:05 +01:00
2007-01-31 21:15:28 +01:00
/ * EMail Notifications * /
- ( NSString * ) homePageURLForPerson : ( iCalPerson * ) _person
{
NSString * baseURL ;
NSString * uid ;
NSArray * traversalObjects ;
/ * generate URL from traversal stack * /
2007-04-11 20:57:54 +02:00
traversalObjects = [ context objectTraversalStack ] ;
2007-01-31 21:15:28 +01:00
if ( [ traversalObjects count ] > 0 )
2007-04-11 20:57:54 +02:00
baseURL = [ [ traversalObjects objectAtIndex : 0 ] baseURLInContext : context ] ;
2007-01-31 21:15:28 +01:00
else
{
baseURL = @ "http://localhost/" ;
[ self warnWithFormat : @ "Unable to create baseURL from context!" ] ;
}
2007-11-18 11:16:25 +01:00
uid = [ _person uid ] ;
2007-01-31 21:15:28 +01:00
return ( ( uid )
? [ NSString stringWithFormat : @ "%@%@" , baseURL , uid ]
: nil ) ;
}
2007-04-11 20:57:54 +02:00
- ( NSTimeZone * ) timeZoneForUser : ( NSString * ) email
{
NSString * uid ;
2009-11-29 05:19:32 +01:00
SOGoUserDefaults * ud ;
2007-04-11 20:57:54 +02:00
2009-09-25 16:42:33 +02:00
uid = [ [ SOGoUserManager sharedUserManager ] getUIDForEmail : email ] ;
2009-11-29 05:19:32 +01:00
ud = [ [ SOGoUser userWithLogin : uid ] userDefaults ] ;
2007-04-11 20:57:54 +02:00
2009-11-29 05:19:32 +01:00
return [ ud timeZone ] ;
2007-04-11 20:57:54 +02:00
}
2010-05-25 22:55:38 +02:00
- ( NGMimeBodyPart * ) _bodyPartForICalObject : ( iCalRepeatableEntityObject * ) object
{
NGMimeBodyPart * bodyPart ;
NGMutableHashMap * headerMap ;
NSString * iCalString , * header , * charset ;
NSData * objectData ;
iCalCalendar * parent ;
parent = [ object parent ] ;
iCalString = [ NSString stringWithFormat : @ "%@\r\n" , [ parent versitString ] ] ;
2016-11-08 14:49:23 +01:00
objectData = [ iCalString dataUsingEncoding : NSUTF8StringEncoding ] ;
charset = @ "UTF-8" ;
2010-05-25 22:55:38 +02:00
header = [ NSString stringWithFormat : @ "text/calendar; method=%@;"
@ " charset=\" % @ \ "" ,
[ ( iCalCalendar * ) [ object parent ] method ] , charset ] ;
2012-11-21 17:56:24 +01:00
headerMap = [ NGMutableHashMap hashMapWithCapacity : 3 ] ;
[ headerMap setObject : @ "urn:content-classes:calendarmessage" forKey : @ "Content-Class" ] ;
2010-05-25 22:55:38 +02:00
[ headerMap setObject : header forKey : @ "content-type" ] ;
[ headerMap setObject : @ "quoted-printable"
forKey : @ "content-transfer-encoding" ] ;
bodyPart = [ NGMimeBodyPart bodyPartWithHeader : headerMap ] ;
[ bodyPart setBody : [ objectData dataByEncodingQuotedPrintable ] ] ;
return bodyPart ;
}
2012-07-10 02:29:13 +02:00
//
//
//
2008-10-01 21:32:14 +02:00
- ( void ) sendEMailUsingTemplateNamed : ( NSString * ) newPageName
forObject : ( iCalRepeatableEntityObject * ) object
2008-11-18 01:06:37 +01:00
previousObject : ( iCalRepeatableEntityObject * ) previousObject
2008-10-01 21:32:14 +02:00
toAttendees : ( NSArray * ) attendees
2012-02-24 00:27:59 +01:00
withType : ( NSString * ) msgType
2007-01-31 21:15:28 +01:00
{
NSString * pageName ;
2010-05-25 22:55:38 +02:00
NSString * senderEmail , * shortSenderEmail , * email ;
2007-01-31 21:15:28 +01:00
WOApplication * app ;
unsigned i , count ;
iCalPerson * attendee ;
2010-04-09 20:45:14 +02:00
NSString * recipient ;
2007-01-31 21:15:28 +01:00
SOGoAptMailNotification * p ;
2010-05-25 22:55:38 +02:00
NSString * mailDate , * subject , * text ;
2007-01-31 21:15:28 +01:00
NGMutableHashMap * headerMap ;
NGMimeMessage * msg ;
2010-05-25 22:55:38 +02:00
NGMimeBodyPart * bodyPart , * eventBodyPart ;
2007-01-31 21:15:28 +01:00
NGMimeMultipartBody * body ;
2008-11-18 01:06:37 +01:00
SOGoUser * ownerUser ;
2009-11-29 05:19:32 +01:00
SOGoDomainDefaults * dd ;
2007-01-31 21:15:28 +01:00
2013-06-18 20:14:42 +02:00
// If defined , we return immediately . When not defined , we send the notifications correctly
if ( [ object firstChildWithTag : @ "X-SOGo-Send-Appointment-Notifications" ] )
return ;
2017-04-12 19:01:01 +02:00
// We never send IMIP inivitaton / deletion / update when the "initiator" is an EAS client .
2017-04-12 22:13:40 +02:00
// That is because Outlook , iOS and Android will always issue a SendMail command
2017-01-17 18:40:41 +01:00
// with the meeting details ( ie . , IMIP message with METHOD : REQUEST ) so there ' s
// no need to send it twice . Moreover , Outlook users can also choose to NOT send
// the IMIP messsage at all , so SOGo won ' t send one without user ' s consent
2017-04-12 19:01:01 +02:00
if ( [ [ [ context request ] requestHandlerKey ] isEqualToString : @ "Microsoft-Server-ActiveSync" ] )
2017-01-17 18:40:41 +01:00
return ;
2009-11-29 05:19:32 +01:00
ownerUser = [ SOGoUser userWithLogin : owner ] ;
dd = [ ownerUser domainDefaults ] ;
if ( [ dd appointmentSendEMailNotifications ] && [ object isStillRelevant ] )
2007-01-31 21:15:28 +01:00
{
2008-10-01 21:32:14 +02:00
count = [ attendees count ] ;
2007-11-18 11:16:25 +01:00
if ( count )
{
/ * sender * /
2008-11-05 22:04:16 +01:00
shortSenderEmail = [ [ object organizer ] rfc822Email ] ;
2012-07-25 16:03:37 +02:00
if ( [ shortSenderEmail length ] )
2017-07-19 17:05:16 +02:00
senderEmail = [ [ object organizer ] mailAddress ] ;
2012-07-25 16:03:37 +02:00
else
{
shortSenderEmail = [ [ previousObject organizer ] rfc822Email ] ;
senderEmail = [ [ previousObject organizer ] mailAddress ] ;
}
2010-05-25 22:55:38 +02:00
2017-07-19 17:05:16 +02:00
// No organizer , grab the event ' s owner
if ( ! [ senderEmail length ] )
senderEmail = shortSenderEmail = [ [ ownerUser defaultIdentity ] objectForKey : @ "email" ] ;
2010-05-25 22:55:38 +02:00
/ * calendar part * /
eventBodyPart = [ self _bodyPartForICalObject : object ] ;
2008-08-09 17:20:56 +02:00
2007-11-18 11:16:25 +01:00
/ * get WOApplication instance * /
app = [ WOApplication application ] ;
2007-01-31 21:15:28 +01:00
2007-11-18 11:16:25 +01:00
/ * generate dynamic message content * /
for ( i = 0 ; i < count ; i + + )
{
2008-10-01 21:32:14 +02:00
attendee = [ attendees objectAtIndex : i ] ;
2009-03-24 16:34:15 +01:00
// Don ' t send a notification to the event organizer nor a deletion
// notification to an attendee who already declined the invitation .
if ( ! [ [ attendee uid ] isEqualToString : owner ] &&
! ( [ [ attendee partStat ] compare : @ "DECLINED" ] = = NSOrderedSame &&
[ newPageName compare : @ "Deletion" ] = = NSOrderedSame ) )
2007-11-18 11:16:25 +01:00
{
/ * construct recipient * /
recipient = [ attendee mailAddress ] ;
email = [ attendee rfc822Email ] ;
2007-11-07 16:40:23 +01:00
# warning this could be optimized in a class hierarchy common with the \
2007-11-18 11:16:25 +01:00
SOGoObject acl notification mechanism
/ * create page name * /
2010-04-09 20:45:14 +02:00
pageName = [ NSString stringWithFormat : @ "SOGoAptMail%@" ,
newPageName ] ;
2007-11-18 11:16:25 +01:00
/ * construct message content * /
p = [ app pageWithName : pageName inContext : context ] ;
2010-04-09 20:45:14 +02:00
[ p setApt : ( iCalEvent * ) object ] ;
[ p setPreviousApt : ( iCalEvent * ) previousObject ] ;
2019-02-04 17:52:26 +01:00
[ p setCurrentAttendee : attendee ] ;
2008-10-24 18:12:21 +02:00
if ( [ [ object organizer ] cn ] && [ [ [ object organizer ] cn ] length ] )
{
[ p setOrganizerName : [ [ object organizer ] cn ] ] ;
}
else
{
[ p setOrganizerName : [ ownerUser cn ] ] ;
}
2010-05-25 22:55:38 +02:00
subject = [ [ p getSubject ] asQPSubjectString : @ "UTF-8" ] ;
2007-11-18 11:16:25 +01:00
text = [ p getBody ] ;
/ * construct message * /
headerMap = [ NGMutableHashMap hashMapWithCapacity : 5 ] ;
2007-02-15 21:59:02 +01:00
2007-11-18 11:16:25 +01:00
/ * NOTE : multipart / alternative seems like the correct choice but
* unfortunately Thunderbird doesn ' t offer the rich content alternative
* at all . Mail . app shows the rich content alternative _only _
* so we ' ll stick with multipart / mixed for the time being .
* /
2009-11-07 23:33:25 +01:00
# warning SOPE is just plain stupid here - if you change the case of keys , it will break the encoding of fields
2007-11-18 11:16:25 +01:00
[ headerMap setObject : @ "multipart/mixed" forKey : @ "content-type" ] ;
2009-05-30 20:47:24 +02:00
[ headerMap setObject : @ "1.0" forKey : @ "MIME-Version" ] ;
2008-07-08 17:40:47 +02:00
[ headerMap setObject : senderEmail forKey : @ "from" ] ;
2007-12-14 21:02:51 +01:00
[ headerMap setObject : recipient forKey : @ "to" ] ;
2007-11-18 11:16:25 +01:00
mailDate = [ [ NSCalendarDate date ] rfc822DateString ] ;
[ headerMap setObject : mailDate forKey : @ "date" ] ;
2007-12-14 21:02:51 +01:00
[ headerMap setObject : subject forKey : @ "subject" ] ;
2014-02-07 16:51:42 +01:00
[ headerMap setObject : [ NSString generateMessageID ] forKey : @ "message-id" ] ;
2012-02-24 00:27:59 +01:00
if ( [ msgType length ] > 0 )
[ headerMap setObject : msgType forKey : @ "x-sogo-message-type" ] ;
2007-11-18 11:16:25 +01:00
msg = [ NGMimeMessage messageWithHeader : headerMap ] ;
/ * multipart body * /
body = [ [ NGMimeMultipartBody alloc ] initWithPart : msg ] ;
/ * text part * /
headerMap = [ NGMutableHashMap hashMapWithCapacity : 1 ] ;
2012-08-27 22:35:10 +02:00
[ headerMap setObject : @ "text/html; charset=utf-8"
forKey : @ "content-type" ] ;
2007-11-18 11:16:25 +01:00
bodyPart = [ NGMimeBodyPart bodyPartWithHeader : headerMap ] ;
[ bodyPart setBody : [ text dataUsingEncoding : NSUTF8StringEncoding ] ] ;
/ * attach text part to multipart body * /
[ body addBodyPart : bodyPart ] ;
2007-01-31 21:15:28 +01:00
2019-02-04 17:52:26 +01:00
/ * attach calendar part to multipart body only if the participation role is not NON - PARTICIPANT * /
if ( [ [ attendee role ] caseInsensitiveCompare : @ "NON-PARTICIPANT" ] ! = NSOrderedSame )
[ body addBodyPart : eventBodyPart ] ;
2007-11-18 11:16:25 +01:00
/ * attach multipart body to message * /
[ msg setBody : body ] ;
[ body release ] ;
/ * send the damn thing * /
2009-11-29 05:19:32 +01:00
[ [ SOGoMailer mailerWithDomainDefaults : dd ]
2012-10-16 22:56:48 +02:00
sendMimePart : msg
toRecipients : [ NSArray arrayWithObject : email ]
sender : shortSenderEmail
2014-02-07 16:51:42 +01:00
withAuthenticator : [ self authenticatorInContext : context ]
2012-10-16 22:56:48 +02:00
inContext : context ] ;
2007-11-18 11:16:25 +01:00
}
}
}
2007-01-31 21:15:28 +01:00
}
}
2016-03-22 18:08:38 +01:00
//
//
//
- ( void ) _sendIMIPReplyForEvent : ( iCalRepeatableEntityObject * ) event
from : ( SOGoUser * ) from
to : ( iCalPerson * ) recipient
textOnly : ( BOOL ) textOnly
2007-11-13 23:38:05 +01:00
{
2016-03-22 18:08:38 +01:00
NSString * mailDate , * email ;
2007-11-18 11:16:25 +01:00
WOApplication * app ;
2008-07-10 17:26:41 +02:00
iCalPerson * attendee ;
2007-11-18 11:16:25 +01:00
SOGoAptMailICalReply * p ;
NGMutableHashMap * headerMap ;
NGMimeMessage * msg ;
NGMimeBodyPart * bodyPart ;
NGMimeMultipartBody * body ;
NSData * bodyData ;
2009-11-29 05:19:32 +01:00
SOGoDomainDefaults * dd ;
2007-11-18 11:16:25 +01:00
2009-11-29 05:19:32 +01:00
dd = [ from domainDefaults ] ;
2016-03-22 18:08:38 +01:00
/ * get WOApplication instance * /
app = [ WOApplication application ] ;
2017-01-12 21:23:09 +01:00
/ * remove all alarms to avoid bug #3925 * /
[ event removeAllAlarms ] ;
2016-03-22 18:08:38 +01:00
/ * construct message content * /
p = [ app pageWithName : @ "SOGoAptMailICalReply" inContext : context ] ;
[ p setApt : ( iCalEvent * ) event ] ;
attendee = [ event userAsAttendee : from ] ;
[ p setAttendee : attendee ] ;
/ * construct message * /
headerMap = [ NGMutableHashMap hashMapWithCapacity : 5 ] ;
/ * NOTE : multipart / alternative seems like the correct choice but
* unfortunately Thunderbird doesn ' t offer the rich content alternative
* at all . Mail . app shows the rich content alternative _only _
* so we ' ll stick with multipart / mixed for the time being .
* /
2009-11-07 23:33:25 +01:00
# warning SOPE is just plain stupid here - if you change the case of keys , it will break the encoding of fields
2016-03-22 18:08:38 +01:00
[ headerMap setObject : [ attendee mailAddress ] forKey : @ "from" ] ;
[ headerMap setObject : [ recipient mailAddress ] forKey : @ "to" ] ;
mailDate = [ [ NSCalendarDate date ] rfc822DateString ] ;
[ headerMap setObject : mailDate forKey : @ "date" ] ;
[ headerMap setObject : [ [ p getSubject ] asQPSubjectString : @ "UTF-8" ]
forKey : @ "subject" ] ;
[ headerMap setObject : [ NSString generateMessageID ] forKey : @ "message-id" ] ;
[ headerMap setObject : @ "1.0" forKey : @ "MIME-Version" ] ;
if ( textOnly )
2020-06-12 14:42:00 +02:00
[ headerMap setObject : @ "text/html; charset=utf-8"
forKey : @ "content-type" ] ;
2016-03-22 18:08:38 +01:00
else
[ headerMap setObject : @ "multipart/mixed" forKey : @ "content-type" ] ;
[ headerMap setObject : @ "calendar:invitation-reply" forKey : @ "x-sogo-message-type" ] ;
msg = [ NGMimeMessage messageWithHeader : headerMap ] ;
2008-07-10 17:26:41 +02:00
2016-03-22 18:08:38 +01:00
/ * text part * /
headerMap = [ NGMutableHashMap hashMapWithCapacity : 1 ] ;
[ headerMap setObject : @ "text/html; charset=utf-8"
forKey : @ "content-type" ] ;
bodyPart = [ NGMimeBodyPart bodyPartWithHeader : headerMap ] ;
bodyData = [ [ p getBody ] dataUsingEncoding : NSUTF8StringEncoding ] ;
if ( textOnly )
{
[ msg setBody : bodyData ] ;
}
else
{
2008-07-10 17:26:41 +02:00
/ * multipart body * /
body = [ [ NGMimeMultipartBody alloc ] initWithPart : msg ] ;
[ bodyPart setBody : bodyData ] ;
/ * attach text part to multipart body * /
[ body addBodyPart : bodyPart ] ;
/ * attach calendar part to multipart body * /
2010-05-25 22:55:38 +02:00
[ body addBodyPart : [ self _bodyPartForICalObject : event ] ] ;
2008-07-10 17:26:41 +02:00
/ * attach multipart body to message * /
[ msg setBody : body ] ;
[ body release ] ;
2016-03-22 18:08:38 +01:00
}
2008-07-10 17:26:41 +02:00
2016-03-22 18:08:38 +01:00
/ * send the damn thing * /
email = [ recipient rfc822Email ] ;
[ [ SOGoMailer mailerWithDomainDefaults : dd ]
2012-10-16 22:56:48 +02:00
sendMimePart : msg
toRecipients : [ NSArray arrayWithObject : email ]
sender : [ attendee rfc822Email ]
withAuthenticator : [ self authenticatorInContext : context ]
inContext : context ] ;
2016-03-22 18:08:38 +01:00
}
//
//
//
- ( void ) sendIMIPReplyForEvent : ( iCalRepeatableEntityObject * ) event
from : ( SOGoUser * ) from
to : ( iCalPerson * ) recipient
{
SOGoDomainDefaults * dd ;
2016-10-19 21:13:28 +02:00
// We never send IMIP reply when the "initiator" is Outlook 2013 / 2016 over
// the EAS protocol . That is because Outlook will always issue a SendMail command
// with the meeting ' s response ( ie . , IMIP message with METHOD : REPLY ) so there ' s
// no need to send it twice . Moreover , Outlook users can also choose to NOT send
// the IMIP messsage at all , so SOGo won ' t send one without user ' s consent
if ( [ [ context objectForKey : @ "DeviceType" ] isEqualToString : @ "WindowsOutlook15" ] )
return ;
2016-03-22 18:08:38 +01:00
dd = [ from domainDefaults ] ;
if ( [ dd appointmentSendEMailNotifications ] && [ event isStillRelevant ] )
{
// We first send to the real recipient ( organizer )
[ self _sendIMIPReplyForEvent : event
from : from
to : recipient
textOnly : NO ] ;
// If we have a sent - by , we send it to it also . This is useful since
// if Alice is Bob ' s asssitant and invites Tony , when Tony accepts / declines
// the event , Alice will also be informed about this . See #3195 for details .
if ( [ recipient hasSentBy ] )
{
iCalPerson * sentBy ;
sentBy = [ [ [ iCalPerson alloc ] init ] autorelease ] ;
[ sentBy setEmail : [ recipient sentBy ] ] ;
[ self _sendIMIPReplyForEvent : event
from : from
to : sentBy
textOnly : YES ] ;
}
2008-07-10 17:26:41 +02:00
}
}
2008-07-10 17:11:01 +02:00
2012-08-27 11:40:18 +02:00
//
//
//
2008-08-14 00:40:05 +02:00
- ( void ) sendResponseToOrganizer : ( iCalRepeatableEntityObject * ) newComponent
2008-11-10 16:38:05 +01:00
from : ( SOGoUser * ) from
2008-07-10 17:26:41 +02:00
{
iCalPerson * organizer , * attendee ;
iCalEvent * event ;
SOGoUser * ownerUser ;
2008-07-10 17:11:01 +02:00
2008-08-14 00:40:05 +02:00
event = [ newComponent itipEntryWithMethod : @ "reply" ] ;
2009-08-25 23:28:24 +02:00
ownerUser = [ SOGoUser userWithLogin : owner ] ;
2008-07-10 17:26:41 +02:00
if ( ! [ event userIsOrganizer : ownerUser ] )
{
organizer = [ event organizer ] ;
2010-05-05 15:56:19 +02:00
attendee = [ event userAsAttendee : ownerUser ] ;
2008-07-10 17:26:41 +02:00
[ event setAttendees : [ NSArray arrayWithObject : attendee ] ] ;
2008-11-10 16:38:05 +01:00
[ self sendIMIPReplyForEvent : event from : from to : organizer ] ;
2007-11-18 11:16:25 +01:00
}
2007-11-13 23:38:05 +01:00
}
2012-08-27 11:40:18 +02:00
//
//
//
2012-07-10 02:29:13 +02:00
- ( void ) sendReceiptEmailForObject : ( iCalRepeatableEntityObject * ) object
addedAttendees : ( NSArray * ) theAddedAttendees
deletedAttendees : ( NSArray * ) theDeletedAttendees
updatedAttendees : ( NSArray * ) theUpdatedAttendees
operation : ( SOGoEventOperation ) theOperation
2009-08-25 23:28:24 +02:00
{
2012-09-19 15:18:00 +02:00
NSString * calendarName , * mailDate , * mailText , * fullSenderEmail , * senderEmail , * fullRecipientEmail , * recipientEmail ;
2012-07-10 02:29:13 +02:00
NSDictionary * senderIdentity , * recipientIdentity ;
2013-01-18 15:38:27 +01:00
id < SOGoAuthenticator > authenticator ;
2013-01-18 15:18:10 +01:00
SOGoUser * currentUser , * ownerUser ;
2009-08-25 23:28:24 +02:00
NGMutableHashMap * headerMap ;
2013-01-18 15:18:10 +01:00
SOGoAptMailReceipt * page ;
2009-11-29 05:19:32 +01:00
SOGoDomainDefaults * dd ;
2013-01-18 15:18:10 +01:00
NGMimeMessage * msg ;
2009-08-25 23:28:24 +02:00
2012-09-19 15:18:00 +02:00
calendarName = [ [ self container ] displayName ] ;
2012-07-10 02:29:13 +02:00
// We must handle three cases here :
// - Receive a mail when I modify my calendar
// - Receive a mail when someone else modifies my calendar
// - When I modify my calendar , send a mail to : < foo @ bar . com >
// We first built the template that we ' ll slightly adjust for our three use - cases
page = [ [ WOApplication application ] pageWithName : @ "SOGoAptMailReceipt"
inContext : context ] ;
[ page setApt : ( iCalEvent * ) object ] ;
[ page setAddedAttendees : theAddedAttendees ] ;
[ page setDeletedAttendees : theDeletedAttendees ] ;
[ page setUpdatedAttendees : theUpdatedAttendees ] ;
[ page setOperation : theOperation ] ;
2012-09-19 15:18:00 +02:00
[ page setCalendarName : calendarName ] ;
2012-07-10 02:29:13 +02:00
2009-11-29 05:19:32 +01:00
currentUser = [ context activeUser ] ;
2012-07-10 02:29:13 +02:00
senderIdentity = [ currentUser primaryIdentity ] ;
2009-08-25 23:28:24 +02:00
2012-07-10 02:29:13 +02:00
dd = [ currentUser domainDefaults ] ;
2009-08-25 23:28:24 +02:00
2009-11-07 23:33:25 +01:00
# warning SOPE is just plain stupid here - if you change the case of keys , it will break the encoding of fields
2012-07-10 02:29:13 +02:00
headerMap = [ NGMutableHashMap hashMapWithCapacity : 5 ] ;
// Sender can vary , base on whom modifies the actual event ( owner vs . someone else )
senderEmail = [ senderIdentity objectForKey : @ "email" ] ;
fullSenderEmail = [ senderIdentity keysWithFormat : @ "%{fullName} <%{email}>" ] ;
[ headerMap setObject : fullSenderEmail forKey : @ "from" ] ;
// Recipient is fixed , which is the calendar owner
2013-01-18 15:18:10 +01:00
ownerUser = [ SOGoUser userWithLogin : self -> owner ] ;
recipientIdentity = [ ownerUser primaryIdentity ] ;
2014-01-21 22:40:57 +01:00
// Safety net for broken configurations
if ( ! recipientIdentity )
return ;
2012-07-10 02:29:13 +02:00
recipientEmail = [ recipientIdentity objectForKey : @ "email" ] ;
fullRecipientEmail = [ recipientIdentity keysWithFormat : @ "%{fullName} <%{email}>" ] ;
[ headerMap setObject : fullRecipientEmail forKey : @ "to" ] ;
mailDate = [ [ NSCalendarDate date ] rfc822DateString ] ;
[ headerMap setObject : mailDate forKey : @ "date" ] ;
2012-07-20 20:34:59 +02:00
[ headerMap setObject : [ page getSubject ] forKey : @ "subject" ] ;
2014-02-07 16:51:42 +01:00
[ headerMap setObject : [ NSString generateMessageID ] forKey : @ "message-id" ] ;
2012-07-10 02:29:13 +02:00
[ headerMap setObject : @ "1.0" forKey : @ "MIME-Version" ] ;
2012-07-11 20:57:27 +02:00
[ headerMap setObject : @ "text/html; charset=utf-8"
2012-07-10 02:29:13 +02:00
forKey : @ "content-type" ] ;
msg = [ NGMimeMessage messageWithHeader : headerMap ] ;
/ * text part * /
mailText = [ page getBody ] ;
[ msg setBody : [ mailText dataUsingEncoding : NSUTF8StringEncoding ] ] ;
2012-10-16 22:56:48 +02:00
authenticator = [ self authenticatorInContext : context ] ;
2012-07-10 02:29:13 +02:00
if ( [ self -> owner isEqualToString : [ currentUser login ] ] )
{
if ( [ [ self container ] notifyOnPersonalModifications ] )
{
[ [ SOGoMailer mailerWithDomainDefaults : dd ]
sendMimePart : msg
toRecipients : [ NSArray arrayWithObject : recipientEmail ]
2012-10-16 22:56:48 +02:00
sender : senderEmail
withAuthenticator : authenticator
inContext : context ] ;
2012-07-10 02:29:13 +02:00
}
2017-09-18 20:22:29 +02:00
if ( [ [ self container ] notifyUserOnPersonalModifications ] &&
[ [ self container ] notifiedUserOnPersonalModifications ] )
2012-07-10 02:29:13 +02:00
{
2012-07-11 16:06:41 +02:00
id o ;
o = [ headerMap objectForKey : @ "to" ] ;
2012-07-10 02:29:13 +02:00
recipientEmail = [ [ self container ] notifiedUserOnPersonalModifications ] ;
2012-07-11 16:06:41 +02:00
[ headerMap setObject : recipientEmail forKey : @ "to" ] ;
2012-07-10 02:29:13 +02:00
[ [ SOGoMailer mailerWithDomainDefaults : dd ]
sendMimePart : msg
toRecipients : [ NSArray arrayWithObject : recipientEmail ]
2012-10-16 22:56:48 +02:00
sender : senderEmail
withAuthenticator : authenticator
inContext : context ] ;
2012-07-11 16:06:41 +02:00
[ headerMap setObject : o forKey : @ "to" ] ;
2012-07-10 02:29:13 +02:00
}
}
2009-08-25 23:28:24 +02:00
2012-07-10 02:29:13 +02:00
if ( [ [ self container ] notifyOnExternalModifications ] &&
! [ self -> owner isEqualToString : [ currentUser login ] ] )
{
2009-11-29 05:19:32 +01:00
[ [ SOGoMailer mailerWithDomainDefaults : dd ]
2009-08-25 23:28:24 +02:00
sendMimePart : msg
2012-07-10 02:29:13 +02:00
toRecipients : [ NSArray arrayWithObject : recipientEmail ]
2012-10-16 22:56:48 +02:00
sender : senderEmail
withAuthenticator : authenticator
inContext : context ] ;
2009-08-25 23:28:24 +02:00
}
2012-07-10 02:29:13 +02:00
}
2007-06-01 22:42:39 +02:00
2012-08-27 11:40:18 +02:00
//
//
//
2007-06-01 22:42:39 +02:00
- ( iCalPerson * ) findParticipantWithUID : ( NSString * ) uid
2007-03-18 16:08:41 +01:00
{
2007-11-13 23:38:05 +01:00
iCalEntityObject * component ;
2007-06-01 22:42:39 +02:00
SOGoUser * user ;
2007-03-18 16:08:41 +01:00
2009-08-25 23:28:24 +02:00
user = [ SOGoUser userWithLogin : uid ] ;
2007-11-18 11:16:25 +01:00
component = [ self component : NO secure : NO ] ;
2007-03-18 16:08:41 +01:00
2010-05-05 15:56:19 +02:00
return [ component userAsAttendee : user ] ;
2007-03-18 16:08:41 +01:00
}
2012-08-27 11:40:18 +02:00
//
//
//
2007-05-09 21:11:32 +02:00
- ( iCalPerson * ) iCalPersonWithUID : ( NSString * ) uid
{
iCalPerson * person ;
2009-09-25 16:42:33 +02:00
SOGoUserManager * um ;
2007-05-09 21:11:32 +02:00
NSDictionary * contactInfos ;
2009-09-25 16:42:33 +02:00
um = [ SOGoUserManager sharedUserManager ] ;
2007-05-09 21:11:32 +02:00
contactInfos = [ um contactInfosForUserWithUIDorEmail : uid ] ;
person = [ iCalPerson new ] ;
[ person autorelease ] ;
[ person setCn : [ contactInfos objectForKey : @ "cn" ] ] ;
[ person setEmail : [ contactInfos objectForKey : @ "c_email" ] ] ;
return person ;
}
2012-08-27 11:40:18 +02:00
//
//
//
2007-05-09 21:11:32 +02:00
- ( NSArray * ) getUIDsForICalPersons : ( NSArray * ) iCalPersons
{
iCalPerson * currentPerson ;
NSEnumerator * persons ;
NSMutableArray * uids ;
2007-05-28 18:02:19 +02:00
NSString * uid ;
2007-05-09 21:11:32 +02:00
uids = [ NSMutableArray array ] ;
persons = [ iCalPersons objectEnumerator ] ;
2008-08-10 23:44:25 +02:00
while ( ( currentPerson = [ persons nextObject ] ) )
2007-05-09 21:11:32 +02:00
{
2007-11-18 11:16:25 +01:00
uid = [ currentPerson uid ] ;
2007-05-23 07:29:54 +02:00
if ( uid )
[ uids addObject : uid ] ;
2007-05-09 21:11:32 +02:00
}
return uids ;
}
2016-03-24 19:53:27 +01:00
- ( NSException * ) _copyComponent : ( iCalCalendar * ) calendar
toFolder : ( SOGoGCSFolder * ) newFolder
updateUID : ( BOOL ) updateUID
2010-08-26 16:14:10 +02:00
{
2008-08-10 23:44:25 +02:00
NSString * newUID ;
SOGoCalendarComponent * newComponent ;
2016-03-24 19:53:27 +01:00
if ( updateUID )
{
NSArray * elements ;
unsigned int count , max ;
newUID = [ self globallyUniqueObjectId ] ;
elements = [ calendar allObjects ] ;
max = [ elements count ] ;
for ( count = 0 ; count < max ; count + + )
[ [ elements objectAtIndex : count ] setUid : newUID ] ;
}
else
{
2016-07-20 19:31:15 +02:00
newUID = [ [ [ calendar allObjects ] objectAtIndex : 0 ] uid ] ;
2016-03-24 19:53:27 +01:00
}
2008-08-10 23:44:25 +02:00
newComponent = [ [ self class ] objectWithName :
[ NSString stringWithFormat : @ "%@.ics" , newUID ]
inContainer : newFolder ] ;
2014-07-30 20:51:00 +02:00
return [ newComponent saveCalendar : calendar ] ;
}
2016-03-24 19:53:27 +01:00
- ( NSException * ) copyToFolder : ( SOGoGCSFolder * ) newFolder
{
return [ self copyComponent : [ self calendar : NO secure : NO ]
toFolder : newFolder ] ;
}
- ( NSException * ) copyComponent : ( iCalCalendar * ) calendar
toFolder : ( SOGoGCSFolder * ) newFolder
{
return [ self _copyComponent : calendar
toFolder : newFolder
updateUID : YES ] ;
}
2014-07-30 20:51:00 +02:00
- ( NSException * ) moveToFolder : ( SOGoGCSFolder * ) newFolder
{
NSException * ex ;
2016-03-24 19:53:27 +01:00
ex = [ self _copyComponent : [ self calendar : NO secure : NO ]
toFolder : newFolder
updateUID : NO ] ;
2014-07-30 20:51:00 +02:00
if ( ! ex )
ex = [ self delete ] ;
return ex ;
2008-08-10 23:44:25 +02:00
}
2009-08-06 23:40:48 +02:00
# warning Should we not remove the concept of Organizer and Participant roles ?
2007-06-01 22:42:39 +02:00
- ( NSString * ) _roleOfOwner : ( iCalRepeatableEntityObject * ) component
{
NSString * role ;
iCalPerson * organizer ;
SOGoUser * ownerUser ;
2009-08-06 23:40:48 +02:00
if ( isNew )
role = SOGoCalendarRole_Organizer ;
else
2007-06-01 22:42:39 +02:00
{
organizer = [ component organizer ] ;
if ( [ [ organizer rfc822Email ] length ] > 0 )
{
2009-08-25 23:28:24 +02:00
ownerUser = [ SOGoUser userWithLogin : owner ] ;
2007-06-01 22:42:39 +02:00
if ( [ component userIsOrganizer : ownerUser ] )
role = SOGoCalendarRole_Organizer ;
2010-05-05 15:56:19 +02:00
else if ( [ component userIsAttendee : ownerUser ] )
2007-06-01 22:42:39 +02:00
role = SOGoCalendarRole_Participant ;
else
role = SOGoRole_None ;
}
else
role = SOGoCalendarRole_Organizer ;
}
2007-09-04 17:03:10 +02:00
2007-06-01 22:42:39 +02:00
return role ;
}
- ( NSString * ) _compiledRoleForOwner : ( NSString * ) ownerRole
andUser : ( NSString * ) userRole
{
NSString * role ;
if ( [ userRole isEqualToString : SOGoCalendarRole_ComponentModifier ]
|| ( [ userRole isEqualToString : SOGoCalendarRole_ComponentResponder ]
&& [ ownerRole isEqualToString : SOGoCalendarRole_Participant ] ) )
role = ownerRole ;
else
role = SOGoRole_None ;
return role ;
}
2007-04-26 03:16:19 +02:00
- ( NSArray * ) aclsForUser : ( NSString * ) uid
{
NSMutableArray * roles ;
NSArray * superAcls ;
iCalRepeatableEntityObject * component ;
2007-06-01 22:42:39 +02:00
NSString * accessRole , * ownerRole ;
2007-12-06 23:54:01 +01:00
SOGoUser * aclUser ;
2007-04-26 03:16:19 +02:00
roles = [ NSMutableArray array ] ;
2007-06-01 22:42:39 +02:00
superAcls = [ super aclsForUser : uid ] ;
if ( [ superAcls count ] > 0 )
[ roles addObjectsFromArray : superAcls ] ;
2007-11-18 11:16:25 +01:00
component = [ self component : NO secure : NO ] ;
2007-06-01 22:42:39 +02:00
ownerRole = [ self _roleOfOwner : component ] ;
if ( [ owner isEqualToString : uid ] )
[ roles addObject : ownerRole ] ;
else
2007-04-26 03:16:19 +02:00
{
2009-08-06 23:40:48 +02:00
if ( isNew )
{
if ( [ roles containsObject : SOGoRole_ObjectCreator ] )
[ roles addObject : SOGoCalendarRole_Organizer ] ;
}
else
{
if ( component )
{
2009-08-25 23:28:24 +02:00
aclUser = [ SOGoUser userWithLogin : uid ] ;
2009-08-06 23:40:48 +02:00
if ( [ component userIsOrganizer : aclUser ] )
[ roles addObject : SOGoCalendarRole_Organizer ] ;
2010-05-05 15:56:19 +02:00
else if ( [ component userIsAttendee : aclUser ] )
2009-08-06 23:40:48 +02:00
[ roles addObject : SOGoCalendarRole_Participant ] ;
accessRole
= [ container roleForComponentsWithAccessClass : [ component symbolicAccessClass ]
forUser : uid ] ;
if ( [ accessRole length ] > 0 )
{
[ roles addObject : accessRole ] ;
[ roles addObject : [ self _compiledRoleForOwner : ownerRole
andUser : accessRole ] ] ;
}
}
}
2007-04-26 03:16:19 +02:00
}
return roles ;
}
2011-10-03 21:32:37 +02:00
- ( void ) snoozeAlarm : ( unsigned int ) minutes
{
NSDictionary * quickFields ;
GCSFolder * folder ;
unsigned int nextAlarm ;
folder = [ [ self container ] ocsFolder ] ;
if ( ! folder )
{
2012-01-30 20:43:38 +01:00
[ self errorWithFormat : @ "(%s): missing folder for update!" ,
2011-10-03 21:32:37 +02:00
__PRETTY _FUNCTION __ ] ;
return ;
}
nextAlarm = [ [ NSCalendarDate calendarDate ] timeIntervalSince1970 ] + minutes * 60 ;
quickFields = [ NSDictionary dictionaryWithObject : [ NSNumber numberWithInt : nextAlarm ]
forKey : @ "c_nextalarm" ] ;
[ folder updateQuickFields : quickFields
whereColumn : @ "c_name"
isEqualTo : nameInContainer ] ;
}
2008-07-17 23:12:43 +02:00
/ * SOGoComponentOccurence protocol * /
- ( iCalRepeatableEntityObject * ) occurence
{
return [ self component : YES secure : NO ] ;
}
2011-07-08 02:22:10 +02:00
# warning alarms : we do not handle occurrences
2010-08-19 19:40:28 +02:00
- ( NSException * ) prepareDelete
{
2011-02-15 20:00:40 +01:00
if ( [ [ SOGoSystemDefaults sharedSystemDefaults ] enableEMailAlarms ] )
{
SOGoEMailAlarmsManager * eaMgr ;
eaMgr = [ SOGoEMailAlarmsManager sharedEMailAlarmsManager ] ;
[ eaMgr deleteAlarmsFromComponent : self ] ;
}
2010-08-19 19:40:28 +02:00
return nil ;
}
2009-06-26 19:30:34 +02:00
// / * Overriding this method dramatically speeds up PROPFIND request , but may
// otherwise be a bad idea . . . Wait and see . * /
// - ( NSDictionary * ) valuesForKeys : ( NSArray * ) keys
// {
// NSMutableDictionary * values ;
2009-06-16 23:30:46 +02:00
2009-06-26 19:30:34 +02:00
// values = [ NSMutableDictionary dictionaryWithCapacity : [ keys count ] ] ;
// [ values setObject : [ self davCreationDate ] forKey : @ "davCreationDate" ] ;
// [ values setObject : [ self davContentLength ] forKey : @ "davContentLength" ] ;
// [ values setObject : [ self davLastModified ] forKey : @ "davLastModified" ] ;
// [ values setObject : @ "text/calendar" forKey : @ "davContentType" ] ;
// [ values setObject : [ self baseURL ] forKey : @ "davURL" ] ;
2009-06-16 23:30:46 +02:00
2009-06-26 19:30:34 +02:00
// return values ;
// }
2009-06-16 23:30:46 +02:00
2016-03-23 18:41:08 +01:00
- ( void ) adjustClassificationInRequestCalendar : ( iCalCalendar * ) rqCalendar
{
SOGoUserDefaults * userDefaults ;
NSString * accessClass ;
NSArray * allObjects ;
id entity ;
int i ;
userDefaults = [ [ context activeUser ] userDefaults ] ;
allObjects = [ rqCalendar allObjects ] ;
for ( i = 0 ; i < [ allObjects count ] ; i + + )
{
entity = [ allObjects objectAtIndex : i ] ;
if ( [ entity respondsToSelector : @ selector ( accessClass ) ] )
{
accessClass = [ entity accessClass ] ;
if ( ! accessClass || [ accessClass length ] = = 0 )
{
if ( [ entity isKindOfClass : [ iCalEvent class ] ] )
[ entity setAccessClass : [ userDefaults calendarEventsDefaultClassification ] ] ;
else if ( [ entity isKindOfClass : [ iCalToDo class ] ] )
[ entity setAccessClass : [ userDefaults calendarTasksDefaultClassification ] ] ;
}
}
}
}
2006-12-14 22:15:05 +01:00
@ end