Monotone-Parent: a8698cc119066cef660b176c3e956b5d0d843e7f
Monotone-Revision: f5b8996b9296ee950ea712c8de2c37e474163519 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2009-08-27T21:14:54 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
a38722d9cb
commit
06b296ddba
42
ChangeLog
42
ChangeLog
|
@ -1,5 +1,47 @@
|
||||||
2009-08-27 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
2009-08-27 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
|
||||||
|
* SoObjects/Appointments/SOGoCalendarProxy.[hm]: new class module
|
||||||
|
implementing the caldav proxy collections mentionned below. This
|
||||||
|
is a subclass of SOGoFolder.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/WORequest+SOGo.m (-isAppleDAVWithSubstring:): new
|
||||||
|
method.
|
||||||
|
(-isICal): new method.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/SOGoUserFolder.m
|
||||||
|
(-calendarProxy:withWriteAccess:): new method that instantiate a
|
||||||
|
proxy collections for read and write delegations.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/SOGoParentFolder.m (-initSubscribedFolders): we
|
||||||
|
now make use of appendSubcribedSources with which we shared code.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/SOGoGCSFolder.m (-subscribeUser:reallyDo:): new
|
||||||
|
simplified and published version of
|
||||||
|
subscribe:inTheNamesOf:fromMailInvitation:inContext:.
|
||||||
|
|
||||||
|
* SoObjects/SOGo/SOGoFolder.m (-davGroupMemberSet)
|
||||||
|
(davGroupMembership): new DAV accessors that return an empty
|
||||||
|
array.
|
||||||
|
|
||||||
|
* SoObjects/Appointments/SOGoUserFolder+Appointments.m
|
||||||
|
(-davGroupMembership): new DAV accessor.
|
||||||
|
|
||||||
|
* SoObjects/Appointments/SOGoAppointmentFolders.m
|
||||||
|
(-toManyRelationshipKeys): overriden method for iCal: we don't
|
||||||
|
list the folders to which the current user is subscribed to
|
||||||
|
(because the iCal paradigm now requires calendar proxying), we
|
||||||
|
don't list the folders to which a delegator has subscribed to
|
||||||
|
either nor any of his/her secondary calendars.
|
||||||
|
(-proxyFoldersWithWriteAccess:): new methods that returns the list
|
||||||
|
of personal folder on which we are allowed to act as a proxy.
|
||||||
|
|
||||||
|
* SoObjects/Appointments/SOGoAppointmentFolder.m
|
||||||
|
(-requiredProxyRolesWithWriteAccess:): new method that returnes
|
||||||
|
the roles required for read/write proxying of users.
|
||||||
|
(-proxySubscribersWithWriteAccess:)
|
||||||
|
(setProxySubscribers:withWriteAccess:): new accessors making use
|
||||||
|
of the new method above.
|
||||||
|
|
||||||
* Tests/test-caldav-scheduling.py: new set of tests for CalDAV
|
* Tests/test-caldav-scheduling.py: new set of tests for CalDAV
|
||||||
scheduling (iTIP-over-DAV) operations. Implemented 9 scenarios for
|
scheduling (iTIP-over-DAV) operations. Implemented 9 scenarios for
|
||||||
invitation delegation.
|
invitation delegation.
|
||||||
|
|
1
NEWS
1
NEWS
|
@ -8,6 +8,7 @@
|
||||||
- a context menu is now available for tasks
|
- a context menu is now available for tasks
|
||||||
- added the capability of creating and managing lists of contacts (same as in Thunderbird)
|
- added the capability of creating and managing lists of contacts (same as in Thunderbird)
|
||||||
- added support for short date format in the calendar views
|
- added support for short date format in the calendar views
|
||||||
|
- added support for iCal delegation
|
||||||
|
|
||||||
1.0-20090812 (1.0.4)
|
1.0-20090812 (1.0.4)
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
@ -28,6 +28,8 @@ Appointments_OBJC_FILES = \
|
||||||
SOGoFreeBusyObject.m \
|
SOGoFreeBusyObject.m \
|
||||||
SOGoUserFolder+Appointments.m \
|
SOGoUserFolder+Appointments.m \
|
||||||
\
|
\
|
||||||
|
SOGoCalendarProxy.m \
|
||||||
|
\
|
||||||
SOGoAptMailNotification.m \
|
SOGoAptMailNotification.m \
|
||||||
SOGoAptMailInvitation.m \
|
SOGoAptMailInvitation.m \
|
||||||
SOGoAptMailDeletion.m \
|
SOGoAptMailDeletion.m \
|
||||||
|
|
|
@ -140,6 +140,10 @@
|
||||||
- (BOOL) showCalendarTasks;
|
- (BOOL) showCalendarTasks;
|
||||||
- (void) setShowCalendarTasks: (BOOL) new;
|
- (void) setShowCalendarTasks: (BOOL) new;
|
||||||
|
|
||||||
|
- (NSArray *) proxySubscribersWithWriteAccess: (BOOL) hasWriteAccess;
|
||||||
|
- (NSException *) setProxySubscribers: (NSArray *) newSubscribers
|
||||||
|
withWriteAccess: (BOOL) hasWriteAccess;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* __Appointments_SOGoAppointmentFolder_H__ */
|
#endif /* __Appointments_SOGoAppointmentFolder_H__ */
|
||||||
|
|
|
@ -3055,4 +3055,122 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir
|
||||||
return (![inactiveFolders containsObject: nameInContainer]);
|
return (![inactiveFolders containsObject: nameInContainer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray *) requiredProxyRolesWithWriteAccess: (BOOL) hasWriteAccess
|
||||||
|
{
|
||||||
|
static NSArray *writeAccessRoles = nil;
|
||||||
|
static NSArray *readAccessRoles = nil;
|
||||||
|
|
||||||
|
if (!writeAccessRoles)
|
||||||
|
{
|
||||||
|
writeAccessRoles = [NSArray arrayWithObjects:
|
||||||
|
SOGoCalendarRole_ConfidentialModifier,
|
||||||
|
SOGoRole_ObjectCreator,
|
||||||
|
SOGoRole_ObjectEraser,
|
||||||
|
SOGoCalendarRole_PrivateModifier,
|
||||||
|
SOGoCalendarRole_PublicModifier,
|
||||||
|
nil];
|
||||||
|
[writeAccessRoles retain];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readAccessRoles)
|
||||||
|
{
|
||||||
|
readAccessRoles = [NSArray arrayWithObjects:
|
||||||
|
SOGoCalendarRole_ConfidentialViewer,
|
||||||
|
SOGoCalendarRole_PrivateViewer,
|
||||||
|
SOGoCalendarRole_PublicViewer,
|
||||||
|
nil];
|
||||||
|
[readAccessRoles retain];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (hasWriteAccess) ? writeAccessRoles : readAccessRoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) _user: (NSString *) user
|
||||||
|
isProxyWithWriteAccess: (BOOL) hasWriteAccess
|
||||||
|
{
|
||||||
|
NSArray *userRoles, *reqRoles;
|
||||||
|
BOOL isProxy;
|
||||||
|
|
||||||
|
if ([self userIsSubscriber: user])
|
||||||
|
{
|
||||||
|
userRoles = [[self aclsForUser: user]
|
||||||
|
sortedArrayUsingSelector: @selector (compare:)];
|
||||||
|
reqRoles = [self requiredProxyRolesWithWriteAccess: hasWriteAccess];
|
||||||
|
isProxy = [reqRoles isEqualToArray: userRoles];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
isProxy = NO;
|
||||||
|
|
||||||
|
return isProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) proxySubscribersWithWriteAccess: (BOOL) hasWriteAccess
|
||||||
|
{
|
||||||
|
NSMutableArray *subscribers;
|
||||||
|
NSEnumerator *aclUsers;
|
||||||
|
NSString *currentUser, *defaultUser;
|
||||||
|
|
||||||
|
subscribers = [NSMutableArray array];
|
||||||
|
|
||||||
|
defaultUser = [self defaultUserID];
|
||||||
|
aclUsers = [[self aclUsers] objectEnumerator];
|
||||||
|
while ((currentUser = [aclUsers nextObject]))
|
||||||
|
{
|
||||||
|
if (![currentUser isEqualToString: defaultUser]
|
||||||
|
&& [self _user: currentUser
|
||||||
|
isProxyWithWriteAccess: hasWriteAccess])
|
||||||
|
[subscribers addObject: currentUser];
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSException *) setProxySubscribers: (NSArray *) newSubscribers
|
||||||
|
withWriteAccess: (BOOL) hasWriteAccess
|
||||||
|
{
|
||||||
|
int count, max;
|
||||||
|
NSArray *oldSubscribers;
|
||||||
|
NSString *login, *reason;
|
||||||
|
NSException *error;
|
||||||
|
|
||||||
|
error = nil;
|
||||||
|
|
||||||
|
max = [newSubscribers count];
|
||||||
|
for (count = 0; !error && count < max; count++)
|
||||||
|
{
|
||||||
|
login = [newSubscribers objectAtIndex: count];
|
||||||
|
if (![SOGoUser userWithLogin: login roles: nil])
|
||||||
|
{
|
||||||
|
reason = [NSString stringWithFormat: @"User '%@' does not exist.", login];
|
||||||
|
error = [NSException exceptionWithHTTPStatus: 403 reason: reason];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
oldSubscribers = [self proxySubscribersWithWriteAccess: hasWriteAccess];
|
||||||
|
for (count = 0; !error && count < max; count++)
|
||||||
|
{
|
||||||
|
login = [newSubscribers objectAtIndex: count];
|
||||||
|
[self
|
||||||
|
setRoles: [self requiredProxyRolesWithWriteAccess: hasWriteAccess]
|
||||||
|
forUser: login];
|
||||||
|
[self subscribeUser: login reallyDo: YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
max = [oldSubscribers count];
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
login = [oldSubscribers objectAtIndex: count];
|
||||||
|
if (![newSubscribers containsObject: login])
|
||||||
|
{
|
||||||
|
[self subscribeUser: login reallyDo: NO];
|
||||||
|
[self removeAclsForUsers: [NSArray arrayWithObject: login]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
@end /* SOGoAppointmentFolder */
|
@end /* SOGoAppointmentFolder */
|
||||||
|
|
|
@ -25,8 +25,12 @@
|
||||||
|
|
||||||
#import <SOGo/SOGoParentFolder.h>
|
#import <SOGo/SOGoParentFolder.h>
|
||||||
|
|
||||||
|
@class NSArray;
|
||||||
|
|
||||||
@interface SOGoAppointmentFolders : SOGoParentFolder
|
@interface SOGoAppointmentFolders : SOGoParentFolder
|
||||||
|
|
||||||
|
- (NSArray *) proxyFoldersWithWriteAccess: (BOOL) hasWriteAccess;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif /* SOGOAPPOINTMENTFOLDERS_H */
|
#endif /* SOGOAPPOINTMENTFOLDERS_H */
|
||||||
|
|
|
@ -26,17 +26,26 @@
|
||||||
#import <Foundation/NSEnumerator.h>
|
#import <Foundation/NSEnumerator.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
#import <NGObjWeb/WOContext.h>
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
#import <NGObjWeb/WORequest+So.h>
|
#import <NGObjWeb/WORequest+So.h>
|
||||||
#import <NGObjWeb/NSException+HTTP.h>
|
#import <NGObjWeb/NSException+HTTP.h>
|
||||||
|
|
||||||
#import <SaxObjC/XMLNamespaces.h>
|
#import <SaxObjC/XMLNamespaces.h>
|
||||||
|
|
||||||
#import <SOGo/WORequest+SOGo.h>
|
#import <SOGo/WORequest+SOGo.h>
|
||||||
#import <SOGo/NSObject+DAV.h>
|
#import <SOGo/NSObject+DAV.h>
|
||||||
#import <SOGo/SOGoWebDAVValue.h>
|
#import <SOGo/SOGoWebDAVValue.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
#import "SOGoAppointmentFolder.h"
|
#import "SOGoAppointmentFolder.h"
|
||||||
|
|
||||||
#import "SOGoAppointmentFolders.h"
|
#import "SOGoAppointmentFolders.h"
|
||||||
|
|
||||||
|
@interface SOGoParentFolder (Private)
|
||||||
|
|
||||||
|
- (NSException *) initSubscribedSubFolders;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation SOGoAppointmentFolders
|
@implementation SOGoAppointmentFolders
|
||||||
|
|
||||||
+ (NSString *) gcsFolderType
|
+ (NSString *) gcsFolderType
|
||||||
|
@ -54,6 +63,36 @@
|
||||||
return [self labelForKey: @"Personal Calendar"];
|
return [self labelForKey: @"Personal Calendar"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray *) toManyRelationshipKeys
|
||||||
|
{
|
||||||
|
NSEnumerator *sortedSubFolders;
|
||||||
|
SOGoGCSFolder *currentFolder;
|
||||||
|
NSString *login;
|
||||||
|
NSMutableArray *keys;
|
||||||
|
|
||||||
|
login = [[context activeUser] login];
|
||||||
|
if ([[context request] isICal])
|
||||||
|
{
|
||||||
|
keys = [NSMutableArray array];
|
||||||
|
if ([owner isEqualToString: login])
|
||||||
|
{
|
||||||
|
sortedSubFolders = [[self subFolders] objectEnumerator];
|
||||||
|
while ((currentFolder = [sortedSubFolders nextObject]))
|
||||||
|
{
|
||||||
|
if ([[currentFolder ownerInContext: context]
|
||||||
|
isEqualToString: owner])
|
||||||
|
[keys addObject: [currentFolder nameInContainer]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[keys addObject: @"personal"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
keys = (NSMutableArray *) [super toManyRelationshipKeys];
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *) _fetchPropertyWithName: (NSString *) propertyName
|
- (NSString *) _fetchPropertyWithName: (NSString *) propertyName
|
||||||
inArray: (NSArray *) section
|
inArray: (NSArray *) section
|
||||||
{
|
{
|
||||||
|
@ -199,4 +238,35 @@
|
||||||
return componentSet;
|
return componentSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray *) proxyFoldersWithWriteAccess: (BOOL) hasWriteAccess
|
||||||
|
{
|
||||||
|
NSMutableArray *proxyFolders;
|
||||||
|
NSArray *proxySubscribers;
|
||||||
|
NSEnumerator *folders;
|
||||||
|
SOGoAppointmentFolder *currentFolder;
|
||||||
|
NSString *folderOwner, *currentUser;
|
||||||
|
|
||||||
|
proxyFolders = [NSMutableArray new];
|
||||||
|
|
||||||
|
currentUser = [[context activeUser] login];
|
||||||
|
|
||||||
|
[self initSubscribedSubFolders];
|
||||||
|
folders = [subscribedSubFolders objectEnumerator];
|
||||||
|
while ((currentFolder = [folders nextObject]))
|
||||||
|
{
|
||||||
|
folderOwner = [currentFolder ownerInContext: context];
|
||||||
|
/* we currently only list the users of which we have subscribed to the
|
||||||
|
personal folder */
|
||||||
|
if ([[currentFolder realNameInContainer] isEqualToString: @"personal"])
|
||||||
|
{
|
||||||
|
proxySubscribers
|
||||||
|
= [currentFolder proxySubscribersWithWriteAccess: hasWriteAccess];
|
||||||
|
if ([proxySubscribers containsObject: currentUser])
|
||||||
|
[proxyFolders addObject: currentFolder];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxyFolders;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* SOGoCalendarProxy.h - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Inverse inc.
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOGOCALENDARPROXY_H
|
||||||
|
#define SOGOCALENDARPROXY_H
|
||||||
|
|
||||||
|
#import <SOGo/SOGoFolder.h>
|
||||||
|
|
||||||
|
@interface SOGoCalendarProxy : SOGoFolder
|
||||||
|
{
|
||||||
|
BOOL hasWriteAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setWriteAccess: (BOOL) newHasWriteAccess;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* SOGOCALENDARPROXY_H */
|
|
@ -0,0 +1,156 @@
|
||||||
|
/* SOGoCalendarProxy.m - this file is part of SOGo
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Inverse inc.
|
||||||
|
*
|
||||||
|
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||||
|
*
|
||||||
|
* This file is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This file is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <Foundation/NSEnumerator.h>
|
||||||
|
#import <Foundation/NSString.h>
|
||||||
|
|
||||||
|
#import <SOGo/NSArray+Utilities.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
|
||||||
|
#import "SOGoAppointmentFolder.h"
|
||||||
|
#import "SOGoCalendarProxy.h"
|
||||||
|
|
||||||
|
@implementation SOGoCalendarProxy
|
||||||
|
|
||||||
|
#define XMLNS_CALENDARSERVER @"http://calendarserver.org/ns/"
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
hasWriteAccess = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setWriteAccess: (BOOL) newHasWriteAccess
|
||||||
|
{
|
||||||
|
hasWriteAccess = newHasWriteAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) davResourceType
|
||||||
|
{
|
||||||
|
NSString *proxyType;
|
||||||
|
NSMutableArray *rType;
|
||||||
|
|
||||||
|
rType = [NSMutableArray arrayWithArray: [super davResourceType]];
|
||||||
|
[rType addObject: @"principal"];
|
||||||
|
if (hasWriteAccess)
|
||||||
|
proxyType = @"calendar-proxy-write";
|
||||||
|
else
|
||||||
|
proxyType = @"calendar-proxy-read";
|
||||||
|
[rType addObject: [NSArray arrayWithObjects: proxyType,
|
||||||
|
XMLNS_CALENDARSERVER, nil]];
|
||||||
|
|
||||||
|
return rType;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) davGroupMemberSet
|
||||||
|
{
|
||||||
|
NSMutableArray *members;
|
||||||
|
NSEnumerator *subscribers;
|
||||||
|
NSArray *member;
|
||||||
|
SOGoUser *ownerUser;
|
||||||
|
SOGoAppointmentFolder *folder;
|
||||||
|
NSString *subscriber;
|
||||||
|
|
||||||
|
members = [NSMutableArray array];
|
||||||
|
|
||||||
|
ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context]
|
||||||
|
roles: nil];
|
||||||
|
folder = [ownerUser personalCalendarFolderInContext: context];
|
||||||
|
subscribers = [[folder proxySubscribersWithWriteAccess: hasWriteAccess]
|
||||||
|
objectEnumerator];
|
||||||
|
while ((subscriber = [subscribers nextObject]))
|
||||||
|
{
|
||||||
|
member = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
|
||||||
|
[NSString stringWithFormat: @"/SOGo/dav/%@/",
|
||||||
|
subscriber],
|
||||||
|
nil];
|
||||||
|
[members addObject: member];
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) davGroupMembership
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) _parseSubscriber: (NSString *) memberSet
|
||||||
|
until: (int) length
|
||||||
|
{
|
||||||
|
int begin, end;
|
||||||
|
NSRange beginRange;
|
||||||
|
|
||||||
|
end = length;
|
||||||
|
if ([memberSet characterAtIndex: end - 1] == '/')
|
||||||
|
end--;
|
||||||
|
beginRange = [memberSet rangeOfString: @"/"
|
||||||
|
options: NSBackwardsSearch
|
||||||
|
range: NSMakeRange (0, end)];
|
||||||
|
begin = NSMaxRange (beginRange);
|
||||||
|
|
||||||
|
return [memberSet substringWithRange: NSMakeRange (begin, end - begin)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) _parseSubscribers: (NSString *) memberSet
|
||||||
|
{
|
||||||
|
NSRange endRange;
|
||||||
|
NSMutableArray *subscribers;
|
||||||
|
NSMutableString *mMemberSet;
|
||||||
|
NSString *subscriber;
|
||||||
|
|
||||||
|
subscribers = [NSMutableArray array];
|
||||||
|
mMemberSet = [NSMutableString stringWithString: memberSet];
|
||||||
|
|
||||||
|
endRange = [mMemberSet rangeOfString: @"</"];
|
||||||
|
while (endRange.location != NSNotFound)
|
||||||
|
{
|
||||||
|
subscriber = [self _parseSubscriber: mMemberSet
|
||||||
|
until: endRange.location];
|
||||||
|
[subscribers addObjectUniquely: subscriber];
|
||||||
|
[mMemberSet
|
||||||
|
deleteCharactersInRange: NSMakeRange (0, endRange.location + 1)];
|
||||||
|
endRange = [mMemberSet rangeOfString: @"</"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSException *) setDavGroupMemberSet: (NSString *) memberSet
|
||||||
|
{
|
||||||
|
SOGoUser *ownerUser;
|
||||||
|
SOGoAppointmentFolder *folder;
|
||||||
|
|
||||||
|
ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context]
|
||||||
|
roles: nil];
|
||||||
|
folder = [ownerUser personalCalendarFolderInContext: context];
|
||||||
|
|
||||||
|
return [folder setProxySubscribers: [self _parseSubscribers: memberSet]
|
||||||
|
withWriteAccess: hasWriteAccess];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -30,10 +30,12 @@
|
||||||
#import <NGExtensions/NSString+misc.h>
|
#import <NGExtensions/NSString+misc.h>
|
||||||
#import <SaxObjC/XMLNamespaces.h>
|
#import <SaxObjC/XMLNamespaces.h>
|
||||||
|
|
||||||
|
#import <SOGo/SOGoGCSFolder.h>
|
||||||
#import <SOGo/SOGoUser.h>
|
#import <SOGo/SOGoUser.h>
|
||||||
#import <SOGo/NSObject+DAV.h>
|
#import <SOGo/NSObject+DAV.h>
|
||||||
#import <SOGo/NSString+DAV.h>
|
#import <SOGo/NSString+DAV.h>
|
||||||
|
|
||||||
|
#import "SOGoAppointmentFolders.h"
|
||||||
#import "SOGoUserFolder+Appointments.h"
|
#import "SOGoUserFolder+Appointments.h"
|
||||||
|
|
||||||
@interface SOGoUserFolder (private)
|
@interface SOGoUserFolder (private)
|
||||||
|
@ -431,4 +433,47 @@
|
||||||
// </D:prop>
|
// </D:prop>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) _addFolders: (NSEnumerator *) folders
|
||||||
|
withGroupTag: (NSString *) groupTag
|
||||||
|
toArray: (NSMutableArray *) groups
|
||||||
|
{
|
||||||
|
SOGoAppointmentFolder *currentFolder;
|
||||||
|
NSString *folderOwner;
|
||||||
|
NSArray *tag;
|
||||||
|
|
||||||
|
while ((currentFolder = [folders nextObject]))
|
||||||
|
{
|
||||||
|
folderOwner = [currentFolder ownerInContext: context];
|
||||||
|
tag = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
|
||||||
|
[NSString stringWithFormat: @"/SOGo/dav/%@/%@/",
|
||||||
|
folderOwner, groupTag],
|
||||||
|
nil];
|
||||||
|
[groups addObject: tag];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) davGroupMembership
|
||||||
|
{
|
||||||
|
SOGoAppointmentFolders *calendars;
|
||||||
|
NSArray *writeFolders, *readFolders;
|
||||||
|
NSMutableArray *groups;
|
||||||
|
|
||||||
|
groups = [NSMutableArray array];
|
||||||
|
|
||||||
|
[self ownerInContext: context];
|
||||||
|
|
||||||
|
calendars = [self privateCalendars: @"Calendar" inContext: context];
|
||||||
|
writeFolders = [calendars proxyFoldersWithWriteAccess: YES];
|
||||||
|
[self _addFolders: [writeFolders objectEnumerator]
|
||||||
|
withGroupTag: @"calendar-proxy-write"
|
||||||
|
toArray: groups];
|
||||||
|
|
||||||
|
readFolders = [calendars proxyFoldersWithWriteAccess: NO];
|
||||||
|
[self _addFolders: [readFolders objectEnumerator]
|
||||||
|
withGroupTag: @"calendar-proxy-read"
|
||||||
|
toArray: groups];
|
||||||
|
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -245,6 +245,11 @@
|
||||||
return rType;
|
return rType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) davIsCollection
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
/* web dav acl helper */
|
/* web dav acl helper */
|
||||||
- (void) _fillArrayWithPrincipalsOwnedBySelf: (NSMutableArray *) hrefs
|
- (void) _fillArrayWithPrincipalsOwnedBySelf: (NSMutableArray *) hrefs
|
||||||
{
|
{
|
||||||
|
@ -263,6 +268,17 @@
|
||||||
acquire: NO] _fillArrayWithPrincipalsOwnedBySelf: hrefs];
|
acquire: NO] _fillArrayWithPrincipalsOwnedBySelf: hrefs];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (NSArray *) davGroupMemberSet
|
||||||
|
{
|
||||||
|
return [NSArray array];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) davGroupMembership
|
||||||
|
{
|
||||||
|
return [NSArray array];
|
||||||
|
}
|
||||||
|
|
||||||
/* folder type */
|
/* folder type */
|
||||||
|
|
||||||
- (BOOL) isEqual: (id) otherFolder
|
- (BOOL) isEqual: (id) otherFolder
|
||||||
|
|
|
@ -87,10 +87,9 @@
|
||||||
- (NSException *) delete;
|
- (NSException *) delete;
|
||||||
- (void) renameTo: (NSString *) newName;
|
- (void) renameTo: (NSString *) newName;
|
||||||
|
|
||||||
- (WOResponse *) subscribe: (BOOL) reallyDo
|
- (BOOL) subscribeUser: (NSString *) subscribingUser
|
||||||
inTheNamesOf: (NSArray *) delegatedUsers
|
reallyDo: (BOOL) reallyDo;
|
||||||
fromMailInvitation: (BOOL) isMailInvitation
|
- (BOOL) userIsSubscriber: (NSString *) subscribingUser;
|
||||||
inContext: (WOContext *) localContext;
|
|
||||||
|
|
||||||
- (void) initializeQuickTablesAclsInContext: (WOContext *) localContext;
|
- (void) initializeQuickTablesAclsInContext: (WOContext *) localContext;
|
||||||
|
|
||||||
|
|
|
@ -650,26 +650,34 @@ static NSArray *childRecordFields = nil;
|
||||||
return cTag;
|
return cTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning this code should be cleaned up
|
- (BOOL) userIsSubscriber: (NSString *) subscribingUser
|
||||||
- (void) _subscribeUser: (SOGoUser *) subscribingUser
|
{
|
||||||
|
SOGoUser *sogoUser;
|
||||||
|
NSDictionary *moduleSettings;
|
||||||
|
NSArray *folderSubscription;
|
||||||
|
|
||||||
|
sogoUser = [SOGoUser userWithLogin: subscribingUser roles: nil];
|
||||||
|
moduleSettings = [[sogoUser userSettings]
|
||||||
|
objectForKey: [container nameInContainer]];
|
||||||
|
folderSubscription = [moduleSettings objectForKey: @"SubscribedFolders"];
|
||||||
|
|
||||||
|
return [folderSubscription containsObject: [self folderReference]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) subscribeUser: (NSString *) subscribingUser
|
||||||
reallyDo: (BOOL) reallyDo
|
reallyDo: (BOOL) reallyDo
|
||||||
fromMailInvitation: (BOOL) isMailInvitation
|
|
||||||
inResponse: (WOResponse *) response
|
|
||||||
{
|
{
|
||||||
NSMutableArray *folderSubscription, *tmpA;
|
NSMutableArray *folderSubscription, *tmpA;
|
||||||
NSString *subscriptionPointer, *mailInvitationURL;
|
NSString *subscriptionPointer;
|
||||||
NSUserDefaults *ud;
|
NSUserDefaults *ud;
|
||||||
NSMutableDictionary *moduleSettings, *tmpD;
|
NSMutableDictionary *moduleSettings, *tmpD;
|
||||||
|
SOGoUser *sogoUser;
|
||||||
|
BOOL rc;
|
||||||
|
|
||||||
if ([owner isEqualToString: [subscribingUser login]])
|
sogoUser = [SOGoUser userWithLogin: subscribingUser roles: nil];
|
||||||
|
if (sogoUser)
|
||||||
{
|
{
|
||||||
[response setStatus: 403];
|
ud = [sogoUser userSettings];
|
||||||
[response appendContentString:
|
|
||||||
@"You cannot (un)subscribe to a folder that you own!"];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ud = [subscribingUser userSettings];
|
|
||||||
moduleSettings = [ud objectForKey: [container nameInContainer]];
|
moduleSettings = [ud objectForKey: [container nameInContainer]];
|
||||||
if (!(moduleSettings
|
if (!(moduleSettings
|
||||||
&& [moduleSettings isKindOfClass: [NSMutableDictionary class]]))
|
&& [moduleSettings isKindOfClass: [NSMutableDictionary class]]))
|
||||||
|
@ -717,82 +725,21 @@ static NSArray *childRecordFields = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ud synchronize];
|
[ud synchronize];
|
||||||
|
rc = YES;
|
||||||
if (isMailInvitation)
|
|
||||||
{
|
|
||||||
mailInvitationURL = [[self soURLToBaseContainerForCurrentUser]
|
|
||||||
absoluteString];
|
|
||||||
[response setStatus: 302];
|
|
||||||
[response setHeader: mailInvitationURL
|
|
||||||
forKey: @"location"];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
[response setStatus: 204];
|
rc = NO;
|
||||||
}
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (WOResponse *) subscribe: (BOOL) reallyDo
|
- (NSArray *) _parseDAVDelegatedUsers
|
||||||
inTheNamesOf: (NSArray *) delegatedUsers
|
|
||||||
fromMailInvitation: (BOOL) isMailInvitation
|
|
||||||
inContext: (WOContext *) localContext
|
|
||||||
{
|
|
||||||
WOResponse *response;
|
|
||||||
SOGoUser *currentUser;
|
|
||||||
|
|
||||||
response = [localContext response];
|
|
||||||
[response setHeader: @"text/plain; charset=utf-8"
|
|
||||||
forKey: @"Content-Type"];
|
|
||||||
|
|
||||||
currentUser = [localContext activeUser];
|
|
||||||
|
|
||||||
if ([delegatedUsers count])
|
|
||||||
{
|
|
||||||
if (![currentUser isSuperUser])
|
|
||||||
{
|
|
||||||
[response setStatus: 403];
|
|
||||||
[response appendContentString:
|
|
||||||
@"You cannot subscribe another user to any folder"
|
|
||||||
@" unless you are a super-user."];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The current user is a superuser...
|
|
||||||
SOGoUser *subscriptionUser;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < [delegatedUsers count]; i++)
|
|
||||||
{
|
|
||||||
// We trust the passed user ID here as it might generate tons or LDAP
|
|
||||||
// call but more importantly, cache propagation calls that will create
|
|
||||||
// contention on GDNC.
|
|
||||||
subscriptionUser = [SOGoUser userWithLogin: [delegatedUsers objectAtIndex: i]
|
|
||||||
roles: nil
|
|
||||||
trust: YES];
|
|
||||||
|
|
||||||
[self _subscribeUser: subscriptionUser
|
|
||||||
reallyDo: reallyDo
|
|
||||||
fromMailInvitation: isMailInvitation
|
|
||||||
inResponse: response];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
[self _subscribeUser: currentUser
|
|
||||||
reallyDo: reallyDo
|
|
||||||
fromMailInvitation: isMailInvitation
|
|
||||||
inResponse: response];
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray *) _parseDAVDelegatedUser: (WOContext *) queryContext
|
|
||||||
{
|
{
|
||||||
id <DOMDocument> document;
|
id <DOMDocument> document;
|
||||||
id <DOMNamedNodeMap> attrs;
|
id <DOMNamedNodeMap> attrs;
|
||||||
id o;
|
id o;
|
||||||
document = [[queryContext request] contentAsDOMDocument];
|
|
||||||
|
document = [[context request] contentAsDOMDocument];
|
||||||
attrs = [[document documentElement] attributes];
|
attrs = [[document documentElement] attributes];
|
||||||
|
|
||||||
o = [attrs namedItem: @"users"];
|
o = [attrs namedItem: @"users"];
|
||||||
|
@ -802,20 +749,65 @@ static NSArray *childRecordFields = nil;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (WOResponse *) _davSubscribe: (BOOL) reallyDo
|
||||||
|
{
|
||||||
|
WOResponse *response;
|
||||||
|
SOGoUser *currentUser;
|
||||||
|
NSArray *delegatedUsers;
|
||||||
|
NSString *userLogin;
|
||||||
|
int count, max;
|
||||||
|
|
||||||
|
response = [context response];
|
||||||
|
[response setHeader: @"text/plain; charset=utf-8"
|
||||||
|
forKey: @"Content-Type"];
|
||||||
|
[response setStatus: 204];
|
||||||
|
|
||||||
|
currentUser = [context activeUser];
|
||||||
|
delegatedUsers = [self _parseDAVDelegatedUsers];
|
||||||
|
|
||||||
|
max = [delegatedUsers count];
|
||||||
|
if (max)
|
||||||
|
{
|
||||||
|
if ([currentUser isSuperUser])
|
||||||
|
{
|
||||||
|
/* We trust the passed user ID here as it might generate tons or
|
||||||
|
LDAP call but more importantly, cache propagation calls that will
|
||||||
|
create contention on GDNC. */
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
[self subscribeUser: [delegatedUsers objectAtIndex: count]
|
||||||
|
reallyDo: reallyDo];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[response setStatus: 403];
|
||||||
|
[response appendContentString: @"You cannot subscribe another user"
|
||||||
|
@" to any folder unless you are a super-user."];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
userLogin = [currentUser login];
|
||||||
|
if ([owner isEqualToString: userLogin])
|
||||||
|
{
|
||||||
|
[response setStatus: 403];
|
||||||
|
[response appendContentString:
|
||||||
|
@"You cannot (un)subscribe to a folder that you own!"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[self subscribeUser: userLogin reallyDo: reallyDo];
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
- (id <WOActionResults>) davSubscribe: (WOContext *) queryContext
|
- (id <WOActionResults>) davSubscribe: (WOContext *) queryContext
|
||||||
{
|
{
|
||||||
return [self subscribe: YES
|
return [self _davSubscribe: YES];
|
||||||
inTheNamesOf: [self _parseDAVDelegatedUser: queryContext]
|
|
||||||
fromMailInvitation: NO
|
|
||||||
inContext: queryContext];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id <WOActionResults>) davUnsubscribe: (WOContext *) queryContext
|
- (id <WOActionResults>) davUnsubscribe: (WOContext *) queryContext
|
||||||
{
|
{
|
||||||
return [self subscribe: NO
|
return [self _davSubscribe: NO];
|
||||||
inTheNamesOf: [self _parseDAVDelegatedUser: queryContext]
|
|
||||||
fromMailInvitation: NO
|
|
||||||
inContext: queryContext];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSDictionary *) davSQLFieldsTable
|
- (NSDictionary *) davSQLFieldsTable
|
||||||
|
|
|
@ -1653,7 +1653,7 @@ SEL SOGoSelectorForPropertySetter (NSString *property)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
exception
|
exception
|
||||||
= [NSException exceptionWithHTTPStatus: 404
|
= [NSException exceptionWithHTTPStatus: 403
|
||||||
reason: [NSString stringWithFormat:
|
reason: [NSString stringWithFormat:
|
||||||
@"Property '%@' cannot be set.",
|
@"Property '%@' cannot be set.",
|
||||||
currentProp]];
|
currentProp]];
|
||||||
|
|
|
@ -107,6 +107,7 @@ static SoSecurityManager *sm = nil;
|
||||||
{
|
{
|
||||||
subFolders = nil;
|
subFolders = nil;
|
||||||
OCSPath = nil;
|
OCSPath = nil;
|
||||||
|
subscribedSubFolders = nil;
|
||||||
subFolderClass = Nil;
|
subFolderClass = Nil;
|
||||||
// hasSubscribedSources = NO;
|
// hasSubscribedSources = NO;
|
||||||
}
|
}
|
||||||
|
@ -116,6 +117,7 @@ static SoSecurityManager *sm = nil;
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
{
|
{
|
||||||
|
[subscribedSubFolders release];
|
||||||
[subFolders release];
|
[subFolders release];
|
||||||
[OCSPath release];
|
[OCSPath release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
|
@ -353,27 +355,19 @@ static SoSecurityManager *sm = nil;
|
||||||
|
|
||||||
- (NSException *) initSubscribedSubFolders
|
- (NSException *) initSubscribedSubFolders
|
||||||
{
|
{
|
||||||
NSArray *subscribedReferences;
|
NSString *login;
|
||||||
NSUserDefaults *settings;
|
|
||||||
NSEnumerator *allKeys;
|
|
||||||
NSString *currentKey, *login;
|
|
||||||
NSException *error;
|
NSException *error;
|
||||||
|
|
||||||
|
if (!subFolderClass)
|
||||||
|
subFolderClass = [[self class] subFolderClass];
|
||||||
|
|
||||||
error = nil; /* we ignore non-DB errors at this time... */
|
error = nil; /* we ignore non-DB errors at this time... */
|
||||||
login = [[context activeUser] login];
|
login = [[context activeUser] login];
|
||||||
|
|
||||||
if (!subscribedSubFolders && [login isEqualToString: owner])
|
if (!subscribedSubFolders && [login isEqualToString: owner])
|
||||||
{
|
{
|
||||||
subscribedSubFolders = [NSMutableDictionary new];
|
subscribedSubFolders = [NSMutableDictionary new];
|
||||||
settings = [[context activeUser] userSettings];
|
error = [self appendSubscribedSources];
|
||||||
subscribedReferences = [[settings objectForKey: nameInContainer]
|
|
||||||
objectForKey: @"SubscribedFolders"];
|
|
||||||
if ([subscribedReferences isKindOfClass: [NSArray class]])
|
|
||||||
{
|
|
||||||
allKeys = [subscribedReferences objectEnumerator];
|
|
||||||
while ((currentKey = [allKeys nextObject]))
|
|
||||||
[self _appendSubscribedSource: currentKey];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
|
|
||||||
#import <Appointments/SOGoAppointmentFolders.h>
|
#import <Appointments/SOGoAppointmentFolders.h>
|
||||||
#import <Appointments/SOGoFreeBusyObject.h>
|
#import <Appointments/SOGoFreeBusyObject.h>
|
||||||
|
#import <Appointments/SOGoCalendarProxy.h>
|
||||||
#import <Contacts/SOGoContactFolders.h>
|
#import <Contacts/SOGoContactFolders.h>
|
||||||
#import <Mailer/SOGoMailAccounts.h>
|
#import <Mailer/SOGoMailAccounts.h>
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
#import "LDAPUserManager.h"
|
#import "LDAPUserManager.h"
|
||||||
#import "SOGoPermissions.h"
|
#import "SOGoPermissions.h"
|
||||||
#import "SOGoUser.h"
|
#import "SOGoUser.h"
|
||||||
|
#import "WORequest+SOGo.h"
|
||||||
|
|
||||||
#import "SOGoUserFolder.h"
|
#import "SOGoUserFolder.h"
|
||||||
|
|
||||||
|
@ -84,11 +86,21 @@ static NSString *LDAPContactInfoAttribute = nil;
|
||||||
|
|
||||||
currentUser = [context activeUser];
|
currentUser = [context activeUser];
|
||||||
if ([currentUser canAccessModule: @"Calendar"])
|
if ([currentUser canAccessModule: @"Calendar"])
|
||||||
|
{
|
||||||
[children addObject: @"Calendar"];
|
[children addObject: @"Calendar"];
|
||||||
|
/* support for caldav-proxy, which is currently limited to iCal but may
|
||||||
|
be enabled for others later, once we sort out the consistency between
|
||||||
|
subscribe folders and "proxy collections". */
|
||||||
|
if ([[context request] isICal])
|
||||||
|
{
|
||||||
|
[children addObject: @"calendar-proxy-write"];
|
||||||
|
[children addObject: @"calendar-proxy-read"];
|
||||||
|
}
|
||||||
|
}
|
||||||
[children addObject: @"Contacts"];
|
[children addObject: @"Contacts"];
|
||||||
if ([currentUser canAccessModule: @"Mail"])
|
if ([currentUser canAccessModule: @"Mail"])
|
||||||
[children addObject: @"Mail"];
|
[children addObject: @"Mail"];
|
||||||
[children addObject: @"Preferences"];
|
// [children addObject: @"Preferences"];
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
@ -529,6 +541,17 @@ static NSString *LDAPContactInfoAttribute = nil;
|
||||||
return [$(@"SOGoFreeBusyObject") objectWithName: _key inContainer: self];
|
return [$(@"SOGoFreeBusyObject") objectWithName: _key inContainer: self];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) calendarProxy: (NSString *) name withWriteAccess: (BOOL) hasWrite
|
||||||
|
{
|
||||||
|
id calendarProxy;
|
||||||
|
|
||||||
|
calendarProxy = [$(@"SOGoCalendarProxy") objectWithName: name
|
||||||
|
inContainer: self];
|
||||||
|
[calendarProxy setWriteAccess: hasWrite];
|
||||||
|
|
||||||
|
return calendarProxy;
|
||||||
|
}
|
||||||
|
|
||||||
- (id) lookupName: (NSString *) _key
|
- (id) lookupName: (NSString *) _key
|
||||||
inContext: (WOContext *) _ctx
|
inContext: (WOContext *) _ctx
|
||||||
acquire: (BOOL) _flag
|
acquire: (BOOL) _flag
|
||||||
|
@ -541,23 +564,29 @@ static NSString *LDAPContactInfoAttribute = nil;
|
||||||
if (!obj)
|
if (!obj)
|
||||||
{
|
{
|
||||||
currentUser = [_ctx activeUser];
|
currentUser = [_ctx activeUser];
|
||||||
|
if ([currentUser canAccessModule: @"Calendar"])
|
||||||
|
{
|
||||||
if ([_key isEqualToString: @"Calendar"])
|
if ([_key isEqualToString: @"Calendar"])
|
||||||
{
|
|
||||||
if ([currentUser canAccessModule: _key])
|
|
||||||
obj = [self privateCalendars: @"Calendar" inContext: _ctx];
|
obj = [self privateCalendars: @"Calendar" inContext: _ctx];
|
||||||
}
|
|
||||||
else if ([_key isEqualToString: @"Contacts"])
|
|
||||||
obj = [self privateContacts: _key inContext: _ctx];
|
|
||||||
else if ([_key isEqualToString: @"Mail"])
|
|
||||||
{
|
|
||||||
if ([currentUser canAccessModule: _key])
|
|
||||||
obj = [self mailAccountsFolder: _key inContext: _ctx];
|
|
||||||
}
|
|
||||||
else if ([_key isEqualToString: @"Preferences"])
|
|
||||||
obj = [$(@"SOGoPreferencesFolder") objectWithName: _key
|
|
||||||
inContainer: self];
|
|
||||||
else if ([_key isEqualToString: @"freebusy.ifb"])
|
else if ([_key isEqualToString: @"freebusy.ifb"])
|
||||||
obj = [self freeBusyObject:_key inContext: _ctx];
|
obj = [self freeBusyObject:_key inContext: _ctx];
|
||||||
|
else if ([_key isEqualToString: @"calendar-proxy-write"])
|
||||||
|
obj = [self calendarProxy: _key withWriteAccess: YES];
|
||||||
|
else if ([_key isEqualToString: @"calendar-proxy-read"])
|
||||||
|
obj = [self calendarProxy: _key withWriteAccess: NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obj
|
||||||
|
&& [_key isEqualToString: @"Mail"]
|
||||||
|
&& [currentUser canAccessModule: @"Mail"])
|
||||||
|
obj = [self mailAccountsFolder: _key inContext: _ctx];
|
||||||
|
|
||||||
|
if (!obj && [_key isEqualToString: @"Contacts"])
|
||||||
|
obj = [self privateContacts: _key inContext: _ctx];
|
||||||
|
|
||||||
|
// else if ([_key isEqualToString: @"Preferences"])
|
||||||
|
// obj = [$(@"SOGoPreferencesFolder") objectWithName: _key
|
||||||
|
// inContainer: self];
|
||||||
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
obj = [NSException exceptionWithHTTPStatus: 404 /* Not Found */];
|
obj = [NSException exceptionWithHTTPStatus: 404 /* Not Found */];
|
||||||
|
@ -584,9 +613,16 @@ static NSString *LDAPContactInfoAttribute = nil;
|
||||||
getCNForUID: nameInContainer];
|
getCNForUID: nameInContainer];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) davIsCollection
|
- (NSArray *) davPrincipalURL
|
||||||
{
|
{
|
||||||
return YES;
|
NSArray *principalURL;
|
||||||
|
NSString *selfDAVPath;
|
||||||
|
|
||||||
|
selfDAVPath = [[self davURL] path];
|
||||||
|
principalURL = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
|
||||||
|
selfDAVPath, nil];
|
||||||
|
|
||||||
|
return [NSArray arrayWithObject: principalURL];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end /* SOGoUserFolder */
|
@end /* SOGoUserFolder */
|
||||||
|
|
|
@ -29,7 +29,10 @@
|
||||||
|
|
||||||
- (BOOL) handledByDefaultHandler;
|
- (BOOL) handledByDefaultHandler;
|
||||||
- (NSDictionary *) davPatchedPropertiesWithTopTag: (NSString *) topTag;
|
- (NSDictionary *) davPatchedPropertiesWithTopTag: (NSString *) topTag;
|
||||||
|
|
||||||
|
- (BOOL) isAppleDAVWithSubstring: (NSString *) osSubstring;
|
||||||
- (BOOL) isIPhone;
|
- (BOOL) isIPhone;
|
||||||
|
- (BOOL) isICal;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -103,22 +103,32 @@
|
||||||
return patchedProperties;
|
return patchedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) isIPhone
|
- (BOOL) isAppleDAVWithSubstring: (NSString *) osSubstring
|
||||||
{
|
{
|
||||||
WEClientCapabilities *cc;
|
WEClientCapabilities *cc;
|
||||||
BOOL rc;
|
BOOL rc;
|
||||||
|
NSRange r;
|
||||||
|
|
||||||
rc = NO;
|
|
||||||
cc = [self clientCapabilities];
|
cc = [self clientCapabilities];
|
||||||
if ([[cc userAgentType] isEqualToString: @"AppleDAVAccess"])
|
if ([[cc userAgentType] isEqualToString: @"AppleDAVAccess"])
|
||||||
{
|
{
|
||||||
NSRange r = [[cc userAgent] rangeOfString: @"iPhone"];
|
r = [[cc userAgent] rangeOfString: osSubstring];
|
||||||
if (r.location != NSNotFound)
|
rc = (r.location != NSNotFound);
|
||||||
rc = YES;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
rc = NO;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) isIPhone
|
||||||
|
{
|
||||||
|
return [self isAppleDAVWithSubstring: @"iPhone/"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isICal
|
||||||
|
{
|
||||||
|
return [self isAppleDAVWithSubstring: @"Mac OS X/10."];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -76,24 +76,48 @@
|
||||||
isMailInvitation = [mailInvitationParam boolValue];
|
isMailInvitation = [mailInvitationParam boolValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (WOResponse *) _subscribeAction: (BOOL) reallyDo
|
||||||
|
{
|
||||||
|
WOResponse *response;
|
||||||
|
NSURL *mailInvitationURL;
|
||||||
|
|
||||||
|
response = [context response];
|
||||||
|
[response setHeader: @"text/plain; charset=utf-8"
|
||||||
|
forKey: @"Content-Type"];
|
||||||
|
|
||||||
|
[self _setupContext];
|
||||||
|
if ([owner isEqualToString: login])
|
||||||
|
{
|
||||||
|
[response setStatus: 403];
|
||||||
|
[response appendContentString:
|
||||||
|
@"You cannot (un)subscribe to a folder that you own!"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[clientObject subscribeUser: login reallyDo: reallyDo];
|
||||||
|
if (isMailInvitation)
|
||||||
|
{
|
||||||
|
mailInvitationURL
|
||||||
|
= [clientObject soURLToBaseContainerForCurrentUser];
|
||||||
|
[response setStatus: 302];
|
||||||
|
[response setHeader: [mailInvitationURL absoluteString]
|
||||||
|
forKey: @"location"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[response setStatus: 204];
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
- (WOResponse *) subscribeAction
|
- (WOResponse *) subscribeAction
|
||||||
{
|
{
|
||||||
[self _setupContext];
|
return [self _subscribeAction: YES];
|
||||||
|
|
||||||
return [clientObject subscribe: YES
|
|
||||||
inTheNamesOf: nil
|
|
||||||
fromMailInvitation: isMailInvitation
|
|
||||||
inContext: context];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (WOResponse *) unsubscribeAction
|
- (WOResponse *) unsubscribeAction
|
||||||
{
|
{
|
||||||
[self _setupContext];
|
return [self _subscribeAction: NO];
|
||||||
|
|
||||||
return [clientObject subscribe: NO
|
|
||||||
inTheNamesOf: nil
|
|
||||||
fromMailInvitation: isMailInvitation
|
|
||||||
inContext: context];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (WOResponse *) canAccessContentAction
|
- (WOResponse *) canAccessContentAction
|
||||||
|
|
Loading…
Reference in New Issue