diff --git a/OpenChange/GNUmakefile b/OpenChange/GNUmakefile index 4fc207904..739fbd95b 100644 --- a/OpenChange/GNUmakefile +++ b/OpenChange/GNUmakefile @@ -78,6 +78,9 @@ $(SOGOBACKEND)_OBJC_FILES += \ MAPIStoreGCSMessage.m \ MAPIStoreGCSMessageTable.m \ \ + MAPIStoreCalTaskFolder.m \ + MAPIStoreCalTaskMessage.m \ + \ MAPIStoreCalendarAttachment.m \ MAPIStoreCalendarContext.m \ MAPIStoreCalendarFolder.m \ diff --git a/OpenChange/MAPIStoreAppointmentWrapper.h b/OpenChange/MAPIStoreAppointmentWrapper.h index ac96dccc2..5ed4c83ff 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.h +++ b/OpenChange/MAPIStoreAppointmentWrapper.h @@ -70,6 +70,7 @@ - (NSString *) creator; - (NSString *) owner; +- (NSUInteger) sensitivity; - (enum mapistore_error) getPidTagSenderEmailAddress: (void **) data inMemCtx: (TALLOC_CTX *) memCtx; diff --git a/OpenChange/MAPIStoreAppointmentWrapper.m b/OpenChange/MAPIStoreAppointmentWrapper.m index 7c16cf6b1..1881a16a5 100644 --- a/OpenChange/MAPIStoreAppointmentWrapper.m +++ b/OpenChange/MAPIStoreAppointmentWrapper.m @@ -1080,6 +1080,29 @@ static NSCharacterSet *hexCharacterSet = nil; return owner; } +- (NSUInteger) sensitivity +{ + NSString *accessClass = nil; + NSUInteger v; + + accessClass = [event accessClass]; + if (accessClass) + { + if ([accessClass isEqualToString: @"X-PERSONAL"]) + v = 0x1; + else if ([accessClass isEqualToString: @"PRIVATE"]) + v = 0x2; + else if ([accessClass isEqualToString: @"CONFIDENTIAL"]) + v = 0x3; + else + v = 0x0; /* PUBLIC */ + } + else + v = 0x0; /* PUBLIC */ + + return v; +} + /* sender representing */ - (enum mapistore_error) getPidTagSentRepresentingEmailAddress: (void **) data inMemCtx: (TALLOC_CTX *) memCtx @@ -1242,23 +1265,8 @@ static NSCharacterSet *hexCharacterSet = nil; { /* See [MS-OXCICAL] Section 2.1.3.11.20.4 */ uint32_t v; - NSString *accessClass; - - accessClass = [event accessClass]; - if (accessClass) - { - if ([accessClass isEqualToString: @"X-PERSONAL"]) - v = 0x1; - else if ([accessClass isEqualToString: @"PRIVATE"]) - v = 0x2; - else if ([accessClass isEqualToString: @"CONFIDENTIAL"]) - v = 0x3; - else - v = 0x0; /* PUBLIC */ - } - else - v = 0x0; /* PUBLIC */ + v = (uint32_t) [self sensitivity]; *data = MAPILongValue (memCtx, v); return MAPISTORE_SUCCESS; diff --git a/OpenChange/MAPIStoreCalTaskFolder.h b/OpenChange/MAPIStoreCalTaskFolder.h new file mode 100644 index 000000000..92b75e463 --- /dev/null +++ b/OpenChange/MAPIStoreCalTaskFolder.h @@ -0,0 +1,35 @@ +/* MAPIStoreCalTaskFolder.h - this file is part of SOGo + * + * Copyright (C) 2016 Enrique J. Hernandez + * + * Author: Enrique J. Hernandez + * + * 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 MAPISTORECALTASKFOLDER_H +#define MAPISTORECALTASKFOLDER_H + +#import "MAPIStoreGCSFolder.h" + +/* This class is intended to share code between Calendar and Tasks as + of nowadays share the table */ + +@interface MAPIStoreCalTaskFolder : MAPIStoreGCSFolder + +@end + +#endif /* MAPISTORECALTASKFOLDER_H */ diff --git a/OpenChange/MAPIStoreCalTaskFolder.m b/OpenChange/MAPIStoreCalTaskFolder.m new file mode 100644 index 000000000..8876c77e5 --- /dev/null +++ b/OpenChange/MAPIStoreCalTaskFolder.m @@ -0,0 +1,101 @@ +/* MAPIStoreCalTaskFolder.m - this file is part of SOGo + * + * Copyright (C) 2016 Enrique J. Hernandez + * + * Author: Enrique J. Hernandez + * + * 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 +#import +#import +#import + +#import + +#import "MAPIStoreCalTaskFolder.h" + +@implementation MAPIStoreCalTaskFolder + +- (NSArray *) expandRoles: (NSArray *) roles +{ + static NSDictionary *rolesMap = nil; + NSArray *subRoles; + NSMutableSet *expandedRoles; + NSString *role, *subRole; + NSUInteger i, max, j; + + if (!rolesMap) + { + /* Build the map of array permissions */ + rolesMap = [[NSDictionary alloc] initWithObjects: [NSArray arrayWithObjects: + [NSArray arrayWithObjects: SOGoCalendarRole_PublicDAndTViewer, + SOGoCalendarRole_PublicViewer, + SOGoCalendarRole_PublicResponder, + SOGoCalendarRole_PublicModifier, nil], + [NSArray arrayWithObjects: SOGoCalendarRole_ConfidentialDAndTViewer, + SOGoCalendarRole_ConfidentialViewer, + SOGoCalendarRole_ConfidentialResponder, + SOGoCalendarRole_ConfidentialModifier, nil], + [NSArray arrayWithObjects: SOGoCalendarRole_PrivateDAndTViewer, + SOGoCalendarRole_PrivateViewer, + SOGoCalendarRole_PrivateResponder, + SOGoCalendarRole_PrivateModifier, nil], + [NSArray arrayWithObjects: SOGoCalendarRole_ComponentDAndTViewer, + SOGoCalendarRole_ComponentViewer, + SOGoCalendarRole_ComponentResponder, + SOGoCalendarRole_ComponentModifier, nil], + nil] + forKeys: [NSArray arrayWithObjects: @"Public", @"Confidential", @"Private", + @"Component", nil]]; + } + + max = [roles count]; + expandedRoles = [NSMutableSet set]; + for (i = 0; i < max; i++) + { + role = [roles objectAtIndex: i]; + subRoles = nil; + if ([role hasPrefix: @"Public"]) + subRoles = [rolesMap objectForKey: @"Public"]; + else if ([role hasPrefix: @"Confidential"]) + subRoles = [rolesMap objectForKey: @"Confidential"]; + else if ([role hasPrefix: @"Private"]) + subRoles = [rolesMap objectForKey: @"Private"]; + else if ([role hasPrefix: @"Component"]) + subRoles = [rolesMap objectForKey: @"Component"]; + + if (subRoles) + { + for (j = 0; j < [subRoles count]; j++) + { + subRole = [subRoles objectAtIndex: j]; + [expandedRoles addObject: subRole]; + + if ([subRole isEqualToString: role]) + break; + } + } + else + { + [expandedRoles addObject: role]; + } + } + + return [expandedRoles allObjects]; +} + +@end diff --git a/OpenChange/MAPIStoreCalTaskMessage.h b/OpenChange/MAPIStoreCalTaskMessage.h new file mode 100644 index 000000000..8e284b414 --- /dev/null +++ b/OpenChange/MAPIStoreCalTaskMessage.h @@ -0,0 +1,40 @@ +/* MAPIStoreCalTaskMessage.h - this file is part of SOGo + * + * Copyright (C) 2016 Enrique J. Hernandez + * + * Author: Enrique J. Hernandez + * + * 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 MAPISTORECALTASKMESSAGE_H +#define MAPISTORECALTASKMESSAGE_H + +#import "MAPIStoreGCSMessage.h" + +/* This class is intended to share common logic for Calendar and Tasks + as of today they are stored in the same table. This is relevant for + permissions */ +@interface MAPIStoreCalTaskMessage : MAPIStoreGCSMessage +{ +} + +/* Get the sensitivity (access class) from a message */ +- (NSUInteger) sensitivity; + +@end + +#endif /* MAPISTORECALTASKMESSAGE_H */ diff --git a/OpenChange/MAPIStoreCalTaskMessage.m b/OpenChange/MAPIStoreCalTaskMessage.m new file mode 100644 index 000000000..b88e9c2ef --- /dev/null +++ b/OpenChange/MAPIStoreCalTaskMessage.m @@ -0,0 +1,107 @@ +/* MAPIStoreCalTaskMessage.h - this file is part of SOGo + * + * Copyright (C) 2016 Enrique J. Hernandez + * + * Author: Enrique J. Hernandez + * + * 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 +#import + +#import + +#import + +#import "MAPIStoreFolder.h" +#import "MAPIStoreCalTaskMessage.h" + +@implementation MAPIStoreCalTaskMessage + +/* It must be implemented by subclasses */ +- (NSUInteger) sensitivity +{ + [self subclassResponsibility: _cmd]; + + return 0; +} + +- (NSArray *) expandRoles: (NSArray *) roles +{ + return [container expandRoles: roles]; +} + +- (BOOL) subscriberCanModifyMessage +{ + BOOL rc; + NSArray *roles; + + roles = [self activeUserRoles]; + + if (isNew) + rc = [roles containsObject: SOGoRole_ObjectCreator]; + else + rc = ([roles containsObject: SOGoCalendarRole_ComponentModifier] + || [roles containsObject: SOGoCalendarRole_ComponentResponder]); + + /* Check if the message is owned and it has permission to edit it */ + if (!rc && [roles containsObject: MAPIStoreRightEditOwn]) + { + NSString *currentUser; + + currentUser = [[container context] activeUser]; + rc = [currentUser isEqual: [self ownerUser]]; + } + + if (!rc) + { + NSUInteger sensitivity; + + /* Get sensitivity of the message to check if the user can + modify the message */ + sensitivity = [self sensitivity]; + /* FIXME: Use OpenChange constant names */ + switch (sensitivity) + { + case 0: /* PUBLIC */ + rc = [roles containsObject: SOGoCalendarRole_PublicModifier] + || [roles containsObject: SOGoCalendarRole_PublicResponder]; + break; + case 1: /* PERSONAL */ + case 2: /* PRIVATE */ + rc = [roles containsObject: SOGoCalendarRole_PrivateModifier] + || [roles containsObject: SOGoCalendarRole_PrivateResponder]; + break; + case 3: /* CONFIDENTIAL */ + rc = [roles containsObject: SOGoCalendarRole_ConfidentialModifier] + || [roles containsObject: SOGoCalendarRole_ConfidentialResponder]; + } + } + return rc; +} + +- (BOOL) subscriberCanReadMessage +{ + NSArray *roles; + + roles = [self activeUserRoles]; + + return ([roles containsObject: SOGoCalendarRole_ComponentViewer] + || [roles containsObject: SOGoCalendarRole_ComponentDAndTViewer] + || [self subscriberCanModifyMessage]); +} + +@end diff --git a/OpenChange/MAPIStoreCalendarFolder.h b/OpenChange/MAPIStoreCalendarFolder.h index fd6c5d20f..9b3a4cf5c 100644 --- a/OpenChange/MAPIStoreCalendarFolder.h +++ b/OpenChange/MAPIStoreCalendarFolder.h @@ -23,9 +23,9 @@ #ifndef MAPISTORECALENDARFOLDER_H #define MAPISTORECALENDARFOLDER_H -#import "MAPIStoreGCSFolder.h" +#import "MAPIStoreCalTaskFolder.h" -@interface MAPIStoreCalendarFolder : MAPIStoreGCSFolder +@interface MAPIStoreCalendarFolder : MAPIStoreCalTaskFolder @end diff --git a/OpenChange/MAPIStoreCalendarMessage.h b/OpenChange/MAPIStoreCalendarMessage.h index 8b2de759d..99e286073 100644 --- a/OpenChange/MAPIStoreCalendarMessage.h +++ b/OpenChange/MAPIStoreCalendarMessage.h @@ -23,13 +23,13 @@ #ifndef MAPISTORECALENDARMESSAGE_H #define MAPISTORECALENDARMESSAGE_H -#import "MAPIStoreGCSMessage.h" +#import "MAPIStoreCalTaskMessage.h" @class iCalCalendar; @class iCalEvent; @class MAPIStoreAppointmentWrapper; -@interface MAPIStoreCalendarMessage : MAPIStoreGCSMessage +@interface MAPIStoreCalendarMessage : MAPIStoreCalTaskMessage { iCalCalendar *calendar; iCalEvent *masterEvent; diff --git a/OpenChange/MAPIStoreCalendarMessage.m b/OpenChange/MAPIStoreCalendarMessage.m index de1675045..5ec92d07f 100644 --- a/OpenChange/MAPIStoreCalendarMessage.m +++ b/OpenChange/MAPIStoreCalendarMessage.m @@ -528,6 +528,11 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK; ASSIGN (sogoObject, newObject); } +- (NSUInteger) sensitivity +{ + return [[self _appointmentWrapper] sensitivity]; +} + - (NSString *) creator { return [[self _appointmentWrapper] creator]; @@ -538,17 +543,6 @@ static Class NSArrayK, MAPIStoreAppointmentWrapperK; return [[self _appointmentWrapper] owner]; } -- (BOOL) subscriberCanReadMessage -{ - NSArray *roles; - - roles = [self activeUserRoles]; - - return ([roles containsObject: SOGoCalendarRole_ComponentViewer] - || [roles containsObject: SOGoCalendarRole_ComponentDAndTViewer] - || [self subscriberCanModifyMessage]); -} - - (void) _updateAttachedEvents { NSArray *allAttachments; diff --git a/OpenChange/MAPIStoreFolder.h b/OpenChange/MAPIStoreFolder.h index a6a591ec2..46e13d235 100644 --- a/OpenChange/MAPIStoreFolder.h +++ b/OpenChange/MAPIStoreFolder.h @@ -89,6 +89,8 @@ extern NSString *MAPIStoreRightFolderContact; - (MAPIStorePermissionsTable *) permissionsTable; - (NSArray *) permissionEntries; +- (NSArray *) expandRoles: (NSArray *) roles; + /* message objects and tables */ - (id) lookupMessage: (NSString *) messageKey; - (NSArray *) messageKeys; diff --git a/OpenChange/MAPIStoreFolder.m b/OpenChange/MAPIStoreFolder.m index a1ef53f94..43efcaff9 100644 --- a/OpenChange/MAPIStoreFolder.m +++ b/OpenChange/MAPIStoreFolder.m @@ -919,6 +919,11 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact"; return nil; } +- (NSArray *) expandRoles: (NSArray *) roles +{ + return roles; +} + - (void) _modifyPermissionEntryForUser: (NSString *) user withRoles: (NSArray *) roles isAddition: (BOOL) isAddition @@ -1053,6 +1058,7 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact"; NSArray *roles; roles = [[self aclFolder] aclsForUser: [activeUser login]]; + roles = [self expandRoles: roles]; // Not required here /* Check FolderVisible right to return the table */ access = ([self exchangeRightsForRoles: roles] & RoleNone) != 0; } @@ -1307,6 +1313,7 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact"; NSArray *roles; roles = [[self aclFolder] aclsForUser: [activeUser login]]; + roles = [self expandRoles: roles]; rights = [self exchangeRightsForRoles: roles]; /* FreeBusySimple and FreeBusyDetailed does not apply here [MS-OXCFOLD] Section 2.2.2.2.2.8 */ @@ -1664,6 +1671,7 @@ NSString *MAPIStoreRightFolderContact = @"RightsFolderContact"; NSArray *roles; roles = [[self aclFolder] aclsForUser: [activeUser login]]; + roles = [self expandRoles: roles]; // Not required if (([self exchangeRightsForRoles: roles] & RightsFolderOwner) == 0) return MAPISTORE_ERR_DENIED; } diff --git a/OpenChange/MAPIStoreGCSFolder.m b/OpenChange/MAPIStoreGCSFolder.m index c70e1f1c3..9b269df35 100644 --- a/OpenChange/MAPIStoreGCSFolder.m +++ b/OpenChange/MAPIStoreGCSFolder.m @@ -859,6 +859,7 @@ static Class NSNumberK; woContext = [[self userContext] woContext]; activeUserRoles = [activeUser rolesForObject: sogoObject inContext: woContext]; + activeUserRoles = [self expandRoles: activeUserRoles]; [activeUserRoles retain]; } diff --git a/OpenChange/MAPIStoreMessage.h b/OpenChange/MAPIStoreMessage.h index 2f059733e..b7441a74c 100644 --- a/OpenChange/MAPIStoreMessage.h +++ b/OpenChange/MAPIStoreMessage.h @@ -69,6 +69,7 @@ - (NSArray *) activeContainerMessageTables; - (NSArray *) activeUserRoles; +- (NSArray *) expandRoles: (NSArray *) roles; /* move & copy internal ops */ - (void) copyToMessage: (MAPIStoreMessage *) newMessage inMemCtx: (TALLOC_CTX *) memCtx; diff --git a/OpenChange/MAPIStoreMessage.m b/OpenChange/MAPIStoreMessage.m index 5f341f600..3e303e5a3 100644 --- a/OpenChange/MAPIStoreMessage.m +++ b/OpenChange/MAPIStoreMessage.m @@ -981,12 +981,22 @@ rtf2html (NSData *compressedRTF) activeUserRoles = [[context activeUser] rolesForObject: sogoObject inContext: [userContext woContext]]; + /* We use in this library the roles as flags, so we expand high + access rights with the lower ones */ + activeUserRoles = [self expandRoles: activeUserRoles]; [activeUserRoles retain]; } return activeUserRoles; } +/* Expand current roles with lower access roles to transform them to + flags */ +- (NSArray *) expandRoles: (NSArray *) roles +{ + return roles; +} + /* Can the current active user read the message? */ - (BOOL) subscriberCanReadMessage { diff --git a/OpenChange/MAPIStorePermissionsTable.m b/OpenChange/MAPIStorePermissionsTable.m index 193ef9a77..3bd2f84b7 100644 --- a/OpenChange/MAPIStorePermissionsTable.m +++ b/OpenChange/MAPIStorePermissionsTable.m @@ -134,6 +134,7 @@ NSArray *roles; roles = [[(MAPIStoreFolder *) container aclFolder] aclsForUser: userId]; + roles = [(MAPIStoreFolder *) container expandRoles: roles]; rights = [(MAPIStoreFolder *) container exchangeRightsForRoles: roles]; *data = MAPILongValue (memCtx, rights); diff --git a/OpenChange/MAPIStoreTasksFolder.h b/OpenChange/MAPIStoreTasksFolder.h index dc9b6791a..3d16a44ae 100644 --- a/OpenChange/MAPIStoreTasksFolder.h +++ b/OpenChange/MAPIStoreTasksFolder.h @@ -23,9 +23,9 @@ #ifndef MAPISTORETASKSFOLDER_H #define MAPISTORETASKSFOLDER_H -#import "MAPIStoreGCSFolder.h" +#import "MAPIStoreCalTaskFolder.h" -@interface MAPIStoreTasksFolder : MAPIStoreGCSFolder +@interface MAPIStoreTasksFolder : MAPIStoreCalTaskFolder @end diff --git a/OpenChange/MAPIStoreTasksMessage.h b/OpenChange/MAPIStoreTasksMessage.h index 3130b72a5..360c516ad 100644 --- a/OpenChange/MAPIStoreTasksMessage.h +++ b/OpenChange/MAPIStoreTasksMessage.h @@ -23,9 +23,9 @@ #ifndef MAPISTORETASKSMESSAGE_H #define MAPISTORETASKSMESSAGE_H -#import "MAPIStoreGCSMessage.h" +#import "MAPIStoreCalTaskMessage.h" -@interface MAPIStoreTasksMessage : MAPIStoreGCSMessage +@interface MAPIStoreTasksMessage : MAPIStoreCalTaskMessage @end diff --git a/OpenChange/MAPIStoreTasksMessage.m b/OpenChange/MAPIStoreTasksMessage.m index 382c61fa0..3cd3f1bfd 100644 --- a/OpenChange/MAPIStoreTasksMessage.m +++ b/OpenChange/MAPIStoreTasksMessage.m @@ -129,12 +129,23 @@ task = [sogoObject component: NO secure: YES]; - if ([task symbolicAccessClass] == iCalAccessPublic) + if ([task isPublic]) return [self getNo: data inMemCtx: memCtx]; return [self getYes: data inMemCtx: memCtx]; } +- (enum mapistore_error) getPidTagSensitivity: (void **) data + inMemCtx: (TALLOC_CTX *) memCtx +{ + uint32_t v; + + v = (uint32_t) [self sensitivity]; + + *data = MAPILongValue (memCtx, v); + return MAPISTORE_SUCCESS; +} + - (enum mapistore_error) getPidTagImportance: (void **) data inMemCtx: (TALLOC_CTX *) memCtx { @@ -343,6 +354,28 @@ // ---------------------------------- // Sharing // ---------------------------------- +- (NSUInteger) sensitivity +{ + iCalToDo *task; + NSUInteger v; + + task = [sogoObject component: NO secure: YES]; + /* FIXME: Use OpenChange constants names */ + switch ([task symbolicAccessClass]) + { + case iCalAccessPrivate: + v = 0x2; + break; + case iCalAccessConfidential: + v = 0x3; + break; + default: + v = 0x0; + break; + } + return v; +} + - (NSString *) creator { iCalToDo *task; @@ -359,36 +392,6 @@ return [self creator]; } -- (BOOL) subscriberCanReadMessage -{ - return ([[self activeUserRoles] - containsObject: SOGoCalendarRole_ComponentViewer] - || [self subscriberCanModifyMessage]); -} - -- (BOOL) subscriberCanModifyMessage -{ - BOOL rc; - NSArray *roles = [self activeUserRoles]; - - if (isNew) - rc = [roles containsObject: SOGoRole_ObjectCreator]; - else - rc = ([roles containsObject: SOGoCalendarRole_ComponentModifier] - || [roles containsObject: SOGoCalendarRole_ComponentResponder]); - - /* Check if the message is owned and it has permission to edit it */ - if (!rc && [roles containsObject: MAPIStoreRightEditOwn]) - { - NSString *currentUser; - - currentUser = [[container context] activeUser]; - rc = [currentUser isEqual: [self ownerUser]]; - } - - return rc; -} - - (void) save:(TALLOC_CTX *) memCtx { iCalCalendar *vCalendar;