]> err.no Git - scalable-opengroupware.org/commitdiff
removal/deletion notifications
authorznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 15 Jul 2005 12:02:21 +0000 (12:02 +0000)
committerznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Fri, 15 Jul 2005 12:02:21 +0000 (12:02 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@777 d1b88da0-ebda-0310-925b-ed51d893ca5b

15 files changed:
SOGo/SOGo.xcodeproj/project.pbxproj
SOGo/SoObjects/Appointments/ChangeLog
SOGo/SoObjects/Appointments/GNUmakefile
SOGo/SoObjects/Appointments/SOGoAppointmentObject.m
SOGo/SoObjects/Appointments/SOGoAptMailDeletion.m [new file with mode: 0644]
SOGo/SoObjects/Appointments/SOGoAptMailDeletion.wo/SOGoAptMailDeletion.html [new file with mode: 0644]
SOGo/SoObjects/Appointments/SOGoAptMailDeletion.wo/SOGoAptMailDeletion.wod [new file with mode: 0644]
SOGo/SoObjects/Appointments/SOGoAptMailRemoval.m [new file with mode: 0644]
SOGo/SoObjects/Appointments/SOGoAptMailRemoval.wo/SOGoAptMailRemoval.html [new file with mode: 0644]
SOGo/SoObjects/Appointments/SOGoAptMailRemoval.wo/SOGoAptMailRemoval.wod [new file with mode: 0644]
SOGo/SoObjects/Appointments/Version
SOGo/SoObjects/SOGo/ChangeLog
SOGo/SoObjects/SOGo/SOGoAppointment.h
SOGo/SoObjects/SOGo/SOGoAppointment.m
SOGo/SoObjects/SOGo/Version

index 06854919c821d847590a64c223a6ec3cbdecd809..832ca1532bc9610d85ccc9a8b5613d8ada8db4f0 100644 (file)
                AD85C72807C4E8740036AC7A /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 8; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
                AD85C72907C4E8740036AC7A /* NSString+iCal.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = "NSString+iCal.h"; sourceTree = "<group>"; };
                AD85C72A07C4E8740036AC7A /* SOGoAppointment.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = SOGoAppointment.h; sourceTree = "<group>"; };
-               AD85C72B07C4E8740036AC7A /* SOGoAppointment.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = SOGoAppointment.m; sourceTree = "<group>"; };
+               AD85C72B07C4E8740036AC7A /* SOGoAppointment.m */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = SOGoAppointment.m; sourceTree = "<group>"; tabWidth = 2; };
                AD85C72C07C4E8740036AC7A /* SOGoAppointmentICalRenderer.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = SOGoAppointmentICalRenderer.h; sourceTree = "<group>"; };
                AD85C72D07C4E8740036AC7A /* SOGoAppointmentICalRenderer.m */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.objc; path = SOGoAppointmentICalRenderer.m; sourceTree = "<group>"; };
                AD85C72E07C4E8740036AC7A /* SOGoCustomGroupFolder.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = SOGoCustomGroupFolder.h; sourceTree = "<group>"; };
                ADA63205071330AE0058C21C /* SOGoAppointment+UIx.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = "SOGoAppointment+UIx.h"; sourceTree = "<group>"; };
                ADA63206071330AE0058C21C /* SOGoAppointment+UIx.m */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = "SOGoAppointment+UIx.m"; sourceTree = "<group>"; };
                ADAD40CA0769FFD000AAD24E /* UIxCalInlineAptView.m */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = UIxCalInlineAptView.m; sourceTree = "<group>"; };
+               ADB742000887C90200AC849E /* SOGoAptMailRemoval.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOGoAptMailRemoval.m; sourceTree = "<group>"; };
+               ADB742040887C93100AC849E /* SOGoAptMailRemoval.wo */ = {isa = PBXFileReference; lastKnownFileType = folder; path = SOGoAptMailRemoval.wo; sourceTree = "<group>"; };
+               ADB7420B0887C94C00AC849E /* SOGoAptMailDeletion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SOGoAptMailDeletion.m; sourceTree = "<group>"; };
+               ADB7420C0887C95A00AC849E /* SOGoAptMailDeletion.wo */ = {isa = PBXFileReference; lastKnownFileType = folder; path = SOGoAptMailDeletion.wo; sourceTree = "<group>"; };
                ADB79CAD07D4BF1600CA782A /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 8; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; tabWidth = 8; usesTabs = 1; };
                ADB7A0FC07D6389500CA782A /* NSObject+AptComparison.h */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = "NSObject+AptComparison.h"; sourceTree = "<group>"; };
                ADB7A0FD07D6389500CA782A /* NSObject+AptComparison.m */ = {isa = PBXFileReference; fileEncoding = 5; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = "NSObject+AptComparison.m"; sourceTree = "<group>"; };
                                AD2FA8720883B9FE009A91E7 /* SOGoAptMailNotification */,
                                AD2FA8DA0883CCF0009A91E7 /* SOGoAptMailInvitation */,
                                AD2FA9C40883F922009A91E7 /* SOGoAptMailUpdate */,
+                               ADB741FF0887C90200AC849E /* SOGoAptMailRemoval */,
+                               ADB7420A0887C94C00AC849E /* SOGoAptMailDeletion */,
                        );
                        name = "Mail Components";
                        sourceTree = "<group>";
                        name = Contacts;
                        sourceTree = "<group>";
                };
+               ADB741FF0887C90200AC849E /* SOGoAptMailRemoval */ = {
+                       isa = PBXGroup;
+                       children = (
+                               ADB742000887C90200AC849E /* SOGoAptMailRemoval.m */,
+                               ADB742040887C93100AC849E /* SOGoAptMailRemoval.wo */,
+                       );
+                       name = SOGoAptMailRemoval;
+                       sourceTree = "<group>";
+               };
+               ADB7420A0887C94C00AC849E /* SOGoAptMailDeletion */ = {
+                       isa = PBXGroup;
+                       children = (
+                               ADB7420B0887C94C00AC849E /* SOGoAptMailDeletion.m */,
+                               ADB7420C0887C95A00AC849E /* SOGoAptMailDeletion.wo */,
+                       );
+                       name = SOGoAptMailDeletion;
+                       sourceTree = "<group>";
+               };
                ADDF4B3006DCEAC800C4E7F8 /* Contacts */ = {
                        isa = PBXGroup;
                        children = (
index 83c0dea58945b894d098c13ccfab9bb4cad2e884..808afb038b2d95dbf974ed7cad99a02f91805d99 100644 (file)
@@ -1,3 +1,16 @@
+2005-07-15  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * v0.9.47
+
+       * SOGoAptMailDeletion.[wo,m]: new template being used when appointment
+         is deleted
+
+       * SOGoAptMailRemoval.[wo,m]: new template being used when attendee is
+         removed from appointment
+
+       * SOGoAppointmentObject.m: now sends emails for removal of attendees
+         and deletion of appointment
+
 2005-07-15  Helge Hess  <helge.hess@opengroupware.org>
 
        * SOGoAppointmentFolder.m: fixed Cocoa warnings (v0.9.46)
index 041ee251603bf9cd85f78cf5cc11b8a96433c952..ec0e8ad059c22b597124a4ae930641e473417b0d 100644 (file)
@@ -17,6 +17,8 @@ Appointments_OBJC_FILES = \
        SOGoAptMailNotification.m       \
        SOGoAptMailInvitation.m         \
        SOGoAptMailUpdate.m             \
+       SOGoAptMailRemoval.m            \
+       SOGoAptMailDeletion.m           \
 
 Appointments_RESOURCE_FILES +=         \
        Version                         \
@@ -25,6 +27,8 @@ Appointments_RESOURCE_FILES +=                \
 Appointments_COMPONENTS +=             \
        SOGoAptMailInvitation.wo        \
        SOGoAptMailUpdate.wo            \
+       SOGoAptMailRemoval.wo           \
+       SOGoAptMailDeletion.wo          \
 
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/wobundle.make
index b26772e638bad7f773e18042cb927086bd6422d4..f250fe8bec7555f69d6a4a66a8ba00dcd0a16323 100644 (file)
@@ -48,7 +48,9 @@
 - (void)sendAppointmentUpdateEMailForOldAppointment:(SOGoAppointment *)_oldApt
   newAppointment:(SOGoAppointment *)_newApt
   toAttendees:(NSArray *)_attendees;
-- (void)sendRemovalEMailForAppointment:(SOGoAppointment *)_apt
+- (void)sendAttendeeRemovalEMailForAppointment:(SOGoAppointment *)_apt
+  toAttendees:(NSArray *)_attendees;
+- (void)sendAppointmentDeletionEMailForAppointment:(SOGoAppointment *)_apt
   toAttendees:(NSArray *)_attendees;
 @end
 
@@ -277,9 +279,9 @@ static NSTimeZone                *MET    = nil;
   NSArray           *uids, *props;
   NSMutableArray    *attendees, *storeUIDs, *removedUIDs;
   NSException       *storeError, *delError;
-  BOOL              didChangeAppointmentTime;
+  BOOL              updateForcesReconsider;
   
-  didChangeAppointmentTime = NO;
+  updateForcesReconsider = NO;
 
   if ([_iCal length] == 0) {
     return [NSException exceptionWithHTTPStatus:400 /* Bad Request */
@@ -330,6 +332,10 @@ static NSTimeZone                *MET    = nil;
   storeUIDs   = [NSMutableArray arrayWithArray:uids];
   props       = [changes updatedProperties];
 
+  /* detect whether sequence has to be increased */
+  if ([changes hasChanges])
+    [newApt increaseSequence];
+
   /* preserve organizer */
 
   organizer = [[newApt event] organizer];
@@ -378,7 +384,7 @@ static NSTimeZone                *MET    = nil;
         [p setParticipationStatus:iCalPersonPartStatNeedsAction];
     }
     _iCal = [newApt iCalString];
-    didChangeAppointmentTime = YES;
+    updateForcesReconsider = YES;
   }
 
   /* perform storing */
@@ -397,7 +403,7 @@ static NSTimeZone                *MET    = nil;
   [self sendInvitationEMailForAppointment:newApt
         toAttendees:attendees];
 
-  if (didChangeAppointmentTime) {
+  if (updateForcesReconsider) {
     attendees = [NSMutableArray arrayWithArray:[[newApt event] attendees]];
     [attendees removeObjectsInArray:[changes insertedAttendees]];
     [attendees removePerson:organizer];
@@ -408,9 +414,15 @@ static NSTimeZone                *MET    = nil;
 
   attendees = [NSMutableArray arrayWithArray:[changes deletedAttendees]];
   [attendees removePerson:organizer];
-  [self sendRemovalEMailForAppointment:newApt
-        toAttendees:attendees];
-
+  if ([attendees count]) {
+    SOGoAppointment *canceledApt;
+    
+    canceledApt = [newApt copy];
+    [canceledApt cancelWithoutIncreasingSequence];
+    [self sendAttendeeRemovalEMailForAppointment:canceledApt
+          toAttendees:attendees];
+    [canceledApt release];
+  }
   return nil;
 }
 
@@ -432,7 +444,8 @@ static NSTimeZone                *MET    = nil;
   SOGoAppointment *apt;
   NSString        *econtent;
   NSArray         *removedUIDs;
-  
+  NSMutableArray  *attendees;
+
   /* load existing content */
   
   econtent = [self iCalString]; /* if nil, this is a new appointment */
@@ -445,7 +458,20 @@ static NSTimeZone                *MET    = nil;
   }
   
   removedUIDs = [self attendeeUIDsFromAppointment:apt];
+
+  /* send notification email to attendees excluding organizer */
+  attendees = [NSMutableArray arrayWithArray:[[apt event] attendees]];
+  [attendees removePerson:[apt organizer]];
   
+  /* flag appointment as being canceled */
+  [apt cancelAndIncreaseSequence];
+  /* remove all attendees to signal complete removal */
+  [apt removeAllAttendees];
+
+  /* send notification email */
+  [self sendAppointmentDeletionEMailForAppointment:apt
+        toAttendees:attendees];
+
   /* perform */
   
   return [self deleteInUIDs:removedUIDs];
@@ -548,7 +574,7 @@ static NSTimeZone                *MET    = nil;
     iCalPerson              *attendee;
     NSString                *recipient;
     SOGoAptMailNotification *p;
-    NSString                *subject, *text;
+    NSString                *subject, *text, *header;
     NGMutableHashMap        *headerMap;
     NGMimeMessage           *msg;
     NGMimeBodyPart          *bodyPart;
@@ -604,8 +630,11 @@ static NSTimeZone                *MET    = nil;
     [body addBodyPart:bodyPart];
     
     /* calendar part */
+    header     = [NSString stringWithFormat:@"text/calendar; method=%@;"
+                                            @" charset=utf-8",
+                                            [_newApt method]];
     headerMap  = [NGMutableHashMap hashMapWithCapacity:1];
-    [headerMap setObject:@"text/calendar; charset=utf-8" forKey:@"content-type"];
+    [headerMap setObject:header forKey:@"content-type"];
     bodyPart   = [NGMimeBodyPart bodyPartWithHeader:headerMap];
     [bodyPart setBody:[iCalString dataUsingEncoding:NSUTF8StringEncoding]];
     
@@ -646,10 +675,26 @@ static NSTimeZone                *MET    = nil;
         toAttendees:_attendees];
 }
 
-- (void)sendRemovalEMailForAppointment:(SOGoAppointment *)_apt
+- (void)sendAttendeeRemovalEMailForAppointment:(SOGoAppointment *)_apt
   toAttendees:(NSArray *)_attendees
 {
   if (![_attendees count]) return;
+
+  [self sendEMailUsingTemplateNamed:@"Removal"
+        forOldAppointment:nil
+        andNewAppointment:_apt
+        toAttendees:_attendees];
+}
+
+- (void)sendAppointmentDeletionEMailForAppointment:(SOGoAppointment *)_apt
+  toAttendees:(NSArray *)_attendees
+{
+  if (![_attendees count]) return;
+
+  [self sendEMailUsingTemplateNamed:@"Deletion"
+        forOldAppointment:nil
+        andNewAppointment:_apt
+        toAttendees:_attendees];
 }
 
 @end /* SOGoAppointmentObject */
diff --git a/SOGo/SoObjects/Appointments/SOGoAptMailDeletion.m b/SOGo/SoObjects/Appointments/SOGoAptMailDeletion.m
new file mode 100644 (file)
index 0000000..c422c94
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2000-2005 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo 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 Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "SOGoAptMailNotification.h"
+
+@interface SOGoAptMailDeletion : SOGoAptMailNotification
+{
+
+}
+
+@end
+
+@implementation SOGoAptMailDeletion
+
+@end
diff --git a/SOGo/SoObjects/Appointments/SOGoAptMailDeletion.wo/SOGoAptMailDeletion.html b/SOGo/SoObjects/Appointments/SOGoAptMailDeletion.wo/SOGoAptMailDeletion.html
new file mode 100644 (file)
index 0000000..cea93f0
--- /dev/null
@@ -0,0 +1,4 @@
+<#IsSubject>Appointment <#AptStartDate /> at <#AptStartTime /> has been canceled</#IsSubject>
+<#IsBody>
+The appointment at <#AptStartDate /> <#AptStartTime /> has been cancelled by <#Organizer />.
+</#IsBody>
\ No newline at end of file
diff --git a/SOGo/SoObjects/Appointments/SOGoAptMailDeletion.wo/SOGoAptMailDeletion.wod b/SOGo/SoObjects/Appointments/SOGoAptMailDeletion.wo/SOGoAptMailDeletion.wod
new file mode 100644 (file)
index 0000000..3e37496
--- /dev/null
@@ -0,0 +1,34 @@
+AptStartDate: WOString {
+  value      = newStartDate;
+  dateformat = "%d/%m/%y";
+  escapeHTML = NO;
+}
+
+AptStartTime: WOString {
+  value      = newStartDate;
+  dateformat = "%H:%M";
+  escapeHTML = NO;
+}
+
+Organizer: WOString {
+  value      = newApt.organizer.cnWithoutQuotes;
+  escapeHTML = NO;
+}
+
+HasHomePageURL: WOConditional {
+  condition = homePageURL.length;
+}
+
+HomePageURL: WOString {
+  value      = appointmentURL;
+  escapeHTML = NO;
+}
+
+IsSubject: WOConditional {
+  condition = isSubject;
+}
+
+IsBody: WOConditional {
+  condition = isSubject;
+  negate    = YES;
+}
diff --git a/SOGo/SoObjects/Appointments/SOGoAptMailRemoval.m b/SOGo/SoObjects/Appointments/SOGoAptMailRemoval.m
new file mode 100644 (file)
index 0000000..0401937
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2000-2005 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo 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 Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "SOGoAptMailNotification.h"
+
+@interface SOGoAptMailRemoval : SOGoAptMailNotification
+{
+
+}
+
+@end
+
+@implementation SOGoAptMailRemoval
+
+@end
diff --git a/SOGo/SoObjects/Appointments/SOGoAptMailRemoval.wo/SOGoAptMailRemoval.html b/SOGo/SoObjects/Appointments/SOGoAptMailRemoval.wo/SOGoAptMailRemoval.html
new file mode 100644 (file)
index 0000000..32fdc26
--- /dev/null
@@ -0,0 +1,4 @@
+<#IsSubject>Removed from appointment <#AptStartDate /> at <#AptStartTime /></#IsSubject>
+<#IsBody>
+You have been removed by <#Organizer /> from the appointment scheduled at <#AptStartDate /> <#AptStartTime />.
+</#IsBody>
\ No newline at end of file
diff --git a/SOGo/SoObjects/Appointments/SOGoAptMailRemoval.wo/SOGoAptMailRemoval.wod b/SOGo/SoObjects/Appointments/SOGoAptMailRemoval.wo/SOGoAptMailRemoval.wod
new file mode 100644 (file)
index 0000000..3e37496
--- /dev/null
@@ -0,0 +1,34 @@
+AptStartDate: WOString {
+  value      = newStartDate;
+  dateformat = "%d/%m/%y";
+  escapeHTML = NO;
+}
+
+AptStartTime: WOString {
+  value      = newStartDate;
+  dateformat = "%H:%M";
+  escapeHTML = NO;
+}
+
+Organizer: WOString {
+  value      = newApt.organizer.cnWithoutQuotes;
+  escapeHTML = NO;
+}
+
+HasHomePageURL: WOConditional {
+  condition = homePageURL.length;
+}
+
+HomePageURL: WOString {
+  value      = appointmentURL;
+  escapeHTML = NO;
+}
+
+IsSubject: WOConditional {
+  condition = isSubject;
+}
+
+IsBody: WOConditional {
+  condition = isSubject;
+  negate    = YES;
+}
index 55414ff4ea913b2a8ae2eda2d168e9df366074e3..3ffdde307ac6dd6c3af1360a49895cf750423d53 100644 (file)
@@ -1,6 +1,6 @@
 # Version file
 
-SUBMINOR_VERSION:=46
+SUBMINOR_VERSION:=47
 
 # v0.9.42 requires libSOGo            v0.9.54
 # v0.9.32 requires libGDLContentStore v4.5.26
index 7bd4ecadd4e99c4ebb57c25e668289ebd26e95c3..cdb10a19a9526390daf607911fef4289976d1a62 100644 (file)
@@ -1,3 +1,10 @@
+2005-07-14  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * v0.9.63
+
+       * SOGoAppointment.[hm]: new API to cancel appointments, NSCopying
+         support
+
 2005-07-15  Helge Hess  <helge.hess@opengroupware.org>
 
        * v0.9.62
index 9afcf23a07f59ac34f278e180c7746946ad6c257..e43218974bff6a2bb5b2875fbc0b3076e36533ab 100644 (file)
@@ -35,7 +35,7 @@
 @class NSString, NSArray, NSCalendarDate, NGCalendarDateRange;
 @class iCalPerson, iCalEvent, iCalRecurrenceRule;
 
-@interface SOGoAppointment : NSObject
+@interface SOGoAppointment : NSObject <NSCopying>
 {
   id        calendar;
   iCalEvent *event;
 
 - (iCalPerson *)findParticipantWithEmail:(id)_email;
 
+/* actions */
+
+- (void)increaseSequence;
+- (void)cancelWithoutIncreasingSequence;
+- (void)cancelAndIncreaseSequence;
+    
 @end
 
 #endif /* __SOGoAppointment_H_ */
index 335c6e7d1117217698237820bb54a272394df0fb..ca48a32c2856c1b6b74663bcea1e57e3f8f0ef07 100644 (file)
@@ -112,11 +112,26 @@ static NGLogger                  *logger = nil;
 }
 
 - (void)dealloc {
-  [self->calendar release];
-  [self->event    release];
+  [self->calendar     release];
+  [self->event        release];
+  [self->participants release];
   [super dealloc];
 }
 
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)_zone {
+  SOGoAppointment *new;
+  
+  new = [[[self class] allocWithZone:_zone] init];
+  
+  new->calendar      = [self->calendar     copyWithZone:_zone];
+  new->event         = [self->event        copyWithZone:_zone];
+  new->participants  = [self->participants copyWithZone:_zone];
+
+  return new;
+}
+
 /* accessors */
 
 - (id)calendar {
@@ -129,11 +144,11 @@ static NGLogger                  *logger = nil;
 
 - (NSString *)iCalString {
   return [[SOGoAppointmentICalRenderer sharedAppointmentRenderer]
-                                      stringForAppointment:self];
+                                            stringForAppointment:self];
 }
 - (NSString *)vEventString {
   return [[SOGoAppointmentICalRenderer sharedAppointmentRenderer]
-                                      vEventStringForAppointment:self];
+                                            vEventStringForAppointment:self];
 }
 
 /* forwarded methods */
@@ -381,7 +396,9 @@ static NGLogger                  *logger = nil;
 - (BOOL)isParticipant:(id)_email {
   NSArray *partEmails;
   
+  _email     = [_email lowercaseString];
   partEmails = [[self participants] valueForKey:@"rfc822Email"];
+  partEmails = [partEmails valueForKey:@"lowercaseString"];
   return [partEmails containsObject:_email];
 }
 
@@ -389,14 +406,15 @@ static NGLogger                  *logger = nil;
   NSArray  *ps;
   unsigned i, count;
   
-  ps    = [self participants];
-  count = [ps count];
+  _email = [_email lowercaseString];
+  ps     = [self participants];
+  count  = [ps count];
   
   for (i = 0; i < count; i++) {
     iCalPerson *p;
     
     p = [ps objectAtIndex:i];
-    if ([[p rfc822Email] isEqualToString:_email])
+    if ([[[p rfc822Email] lowercaseString] isEqualToString:_email])
       return p;
   }
   return nil; /* not found */
@@ -428,6 +446,19 @@ static NGLogger                  *logger = nil;
   return [self->event recurrenceRangesWithinCalendarDateRange:_r];
 }
 
+/* actions */
+
+- (void)increaseSequence {
+  [self->event increaseSequence];
+}
+
+- (void)cancelWithoutIncreasingSequence {
+  [self setMethod:@"CANCEL"];
+}
+- (void)cancelAndIncreaseSequence {
+  [self cancelWithoutIncreasingSequence];
+  [self increaseSequence];
+}
 
 /* description */
 
index a5eb45d13c8b95b25ecc511662bca2a2e236355c..d937b34747c5b5859a488418b6d92ddc295c9e7e 100644 (file)
@@ -1,7 +1,8 @@
 # version file
 
-SUBMINOR_VERSION:=62
+SUBMINOR_VERSION:=63
 
+# v0.9.63 requires libNGiCal          v4.5.54
 # v0.9.60 requires libNGiCal          v4.5.49
 # v0.9.50 requires libGDLContentStore v4.5.30
 # v0.9.34 requires libGDLContentStore v4.5.26