Monotone-Parent: a084cda52b54dea2be32b37d71aefe6f27b1af33

Monotone-Revision: 8e81030e83aa6ed594c40a5f56274b5ba292f47c

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-05-02T23:08:15
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Wolfgang Sourdeau
2008-05-02 23:08:15 +00:00
parent 4f76b2ee5f
commit 5c2c26e0db
12 changed files with 1286 additions and 423 deletions
+46
View File
@@ -1,5 +1,51 @@
2008-05-02 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/Contacts/SOGoContactLDAPFolder.m ([-davNamespaces]):
removed method.
* SoObjects/Contacts/SOGoContactGCSFolder.m ([-davNamespaces]):
removed method.
* SoObjects/SOGo/SOGoGCSFolder.m ([SOGoGCSFolder
+webdavAclManager]): new overriden method.
* SoObjects/SOGo/SOGoFolder.m ([SOGoFolder +webdavAclManager]):
new overriden method.
* SoObjects/Appointments/SOGoAppointmentObject.m
([SOGoAppointmentObject +webdavAclManager]): new overriden method.
* SoObjects/Appointments/SOGoAppointmentFolder.m
([SOGoAppointmentFolder +webdavAclManager]): new overriden method.
([-davNamespaces]): removed method.
([-lookupGroupFolderForUIDs:_uidsinContext:])
([-lookupGroupCalendarFolderForUIDs:_uidsinContext:_ctx]):
disabled methods.
* SoObjects/SOGo/SOGoWebDAVAclManager.[hm]: new class module that
implements the rendering of DAV acl trees as well as their mapping
from SOGo permissions.
* SoObjects/SOGo/SOGoObject.m ([SOGoObject +initialize]): libSOGo
is now a framework, so we can simplify the loading of the DAVReportMap.
([-lookupGroupsFolder]): disabled method.
([SOGoObject -davOwner], [SOGoObject -davAclRestrictions])
([SOGoObject -davPrincipalCollectionSet])
([SOGoObject -davCurrentUserPrivilegeSet])
([SOGoObject -davSupportedPrivilegeSet], [SOGoObject -davAcl])
([SOGoObject -davPrincipalMatch:localContext])
([SOGoObject -davSupportedReportSet]): (re-)implemented dav
methods with our new dav rendering paradigm.
([-davNamespaces]): removed method.
([SOGoObject -domNode:nodegetChildNodesByType:type]): new helper
method to help subclass with parsing dav requests, especially wrt
REPORT ones.
([SOGoObject +webdavAclManager]): new overridable method that
returns a properly configured DAV acl manager (see above).
* SoObjects/Appointments/SOGoUserFolder+Appointments.[hm]: new
category module that implements DAV methods required by CalDAV.
* UI/SOGoUI/UIxComponent.m ([UIxComponent -applicationPath]):
disabled all mentions of "SOGoGroupFolder*".
+163 -38
View File
@@ -49,13 +49,15 @@
#import <SaxObjC/XMLNamespaces.h>
// #import <NGObjWeb/SoClassSecurityInfo.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSObject+DAV.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoCustomGroupFolder.h>
// #import <SOGo/SOGoCustomGroupFolder.h>
#import <SOGo/LDAPUserManager.h>
#import <SOGo/SOGoPermissions.h>
#import <SOGo/NSArray+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoWebDAVAclManager.h>
#import "SOGoAppointmentObject.h"
#import "SOGoAppointmentFolders.h"
@@ -110,6 +112,139 @@ static NSNumber *sharedYes = nil;
sharedYes = [[NSNumber numberWithBool: YES] retain];
}
+ (SOGoWebDAVAclManager *) webdavAclManager
{
SOGoWebDAVAclManager *webdavAclManager = nil;
NSString *nsCD, *nsD, *nsI;
if (!webdavAclManager)
{
nsD = @"DAV:";
nsCD = @"urn:ietf:params:xml:ns:caldav";
nsI = @"urn:inverse:params:xml:ns:inverse-dav";
webdavAclManager = [SOGoWebDAVAclManager new];
[webdavAclManager registerDAVPermission: davElement (@"read", nsD)
abstract: YES
withEquivalent: SoPerm_WebDAVAccess
asChildOf: davElement (@"all", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"read-current-user-privilege-set", nsD)
abstract: YES
withEquivalent: SoPerm_WebDAVAccess
asChildOf: davElement (@"read", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"read-free-busy", nsD)
abstract: NO
withEquivalent: SoPerm_AccessContentsInformation
asChildOf: davElement (@"read", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"write", nsD)
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"all", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"bind", nsD)
abstract: NO
withEquivalent: SoPerm_AddDocumentsImagesAndFiles
asChildOf: davElement (@"write", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"schedule",
nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"bind", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"schedule-post",
nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-post-vevent", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-post", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-post-vtodo", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-post", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-post-vjournal", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-post", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-post-vfreebusy", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-post", nsCD)];
[webdavAclManager registerDAVPermission: davElement (@"schedule-deliver",
nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-deliver-vevent", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-deliver", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-deliver-vtodo", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-deliver", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-deliver-vjournal", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-deliver", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-deliver-vfreebusy", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-deliver", nsCD)];
[webdavAclManager registerDAVPermission: davElement (@"schedule-respond",
nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-respond-vevent", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-respond", nsCD)];
[webdavAclManager registerDAVPermission:
davElement (@"schedule-respond-vtodo", nsCD)
abstract: NO
withEquivalent: nil
asChildOf: davElement (@"schedule-respond", nsCD)];
[webdavAclManager registerDAVPermission: davElement (@"unbind", nsD)
abstract: NO
withEquivalent: SoPerm_DeleteObjects
asChildOf: davElement (@"write", nsD)];
[webdavAclManager
registerDAVPermission: davElement (@"write-properties", nsD)
abstract: YES
withEquivalent: SoPerm_ChangePermissions /* hackish */
asChildOf: davElement (@"write", nsD)];
[webdavAclManager
registerDAVPermission: davElement (@"write-content", nsD)
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"write", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"admin", nsI)
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"all", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"read-acl", nsD)
abstract: YES
withEquivalent: SOGoPerm_ReadAcls
asChildOf: davElement (@"admin", nsI)];
[webdavAclManager registerDAVPermission: davElement (@"write-acl", nsD)
abstract: YES
withEquivalent: SoPerm_ChangePermissions
asChildOf: davElement (@"admin", nsI)];
}
return webdavAclManager;
}
- (id) initWithName: (NSString *) name
inContainer: (id) newContainer
{
@@ -593,16 +728,6 @@ static NSNumber *sharedYes = nil;
}
}
- (NSArray *) davNamespaces
{
NSMutableArray *ns;
ns = [NSMutableArray arrayWithArray: [super davNamespaces]];
[ns addObjectUniquely: @"urn:ietf:params:xml:ns:caldav"];
return ns;
}
- (NSString *) davCalendarColor
{
NSString *color;
@@ -1649,37 +1774,37 @@ static NSNumber *sharedYes = nil;
return [self lookupCalendarFoldersForUIDs:uids inContext:_ctx];
}
- (id) lookupGroupFolderForUIDs: (NSArray *) _uids
inContext: (id)_ctx
{
SOGoCustomGroupFolder *folder;
// - (id) lookupGroupFolderForUIDs: (NSArray *) _uids
// inContext: (id)_ctx
// {
// SOGoCustomGroupFolder *folder;
if (_uids == nil)
return nil;
// if (_uids == nil)
// return nil;
folder = [[SOGoCustomGroupFolder alloc] initWithUIDs:_uids inContainer:self];
return [folder autorelease];
}
// folder = [[SOGoCustomGroupFolder alloc] initWithUIDs:_uids inContainer:self];
// return [folder autorelease];
// }
- (id) lookupGroupCalendarFolderForUIDs: (NSArray *) _uids
inContext: (id) _ctx
{
SOGoCustomGroupFolder *folder;
// - (id) lookupGroupCalendarFolderForUIDs: (NSArray *) _uids
// inContext: (id) _ctx
// {
// SOGoCustomGroupFolder *folder;
if ((folder = [self lookupGroupFolderForUIDs:_uids inContext:_ctx]) == nil)
return nil;
// if ((folder = [self lookupGroupFolderForUIDs:_uids inContext:_ctx]) == nil)
// return nil;
folder = [folder lookupName:@"Calendar" inContext:_ctx acquire:NO];
if (![folder isNotNull])
return nil;
if ([folder isKindOfClass:[NSException class]]) {
[self debugWithFormat:@"Note: could not lookup 'Calendar' in folder: %@",
folder];
return nil;
}
// folder = [folder lookupName:@"Calendar" inContext:_ctx acquire:NO];
// if (![folder isNotNull])
// return nil;
// if ([folder isKindOfClass:[NSException class]]) {
// [self debugWithFormat:@"Note: could not lookup 'Calendar' in folder: %@",
// folder];
// return nil;
// }
return folder;
}
// return folder;
// }
/* bulk fetches */
@@ -33,9 +33,12 @@
#import <SoObjects/SOGo/iCalEntityObject+Utilities.h>
#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/NSArray+Utilities.h>
#import <SoObjects/SOGo/NSObject+DAV.h>
#import <SoObjects/SOGo/SOGoObject.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoWebDAVAclManager.h>
#import <SoObjects/SOGo/SOGoWebDAVValue.h>
#import <SoObjects/SOGo/WORequest+SOGo.h>
#import "NSArray+Appointments.h"
@@ -48,6 +51,76 @@
@implementation SOGoAppointmentObject
+ (SOGoWebDAVAclManager *) webdavAclManager
{
SOGoWebDAVAclManager *webdavAclManager = nil;
NSString *nsD, *nsI;
if (!webdavAclManager)
{
nsD = @"DAV:";
nsI = @"urn:inverse:params:xml:ns:inverse-dav";
// extern NSString *SOGoCalendarPerm_ViewAllComponent;
// extern NSString *SOGoCalendarPerm_ViewDAndT;
// extern NSString *SOGoCalendarPerm_ModifyComponent;
// extern NSString *SOGoCalendarPerm_RespondToComponent;
webdavAclManager = [SOGoWebDAVAclManager new];
[webdavAclManager registerDAVPermission: davElement (@"read", nsD)
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"all", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"read-current-user-privilege-set", nsD)
abstract: YES
withEquivalent: SoPerm_WebDAVAccess
asChildOf: davElement (@"read", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"view-whole-component", nsI)
abstract: NO
withEquivalent: SOGoCalendarPerm_ViewAllComponent
asChildOf: davElement (@"read", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"view-date-and-time", nsI)
abstract: NO
withEquivalent: SOGoCalendarPerm_ViewDAndT
asChildOf: davElement (@"view-whole-component", nsI)];
[webdavAclManager registerDAVPermission: davElement (@"write", nsD)
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"all", nsD)];
[webdavAclManager
registerDAVPermission: davElement (@"write-properties", nsD)
abstract: YES
withEquivalent: SoPerm_ChangePermissions /* hackish */
asChildOf: davElement (@"write", nsD)];
[webdavAclManager
registerDAVPermission: davElement (@"write-content", nsD)
abstract: YES
withEquivalent: SOGoCalendarPerm_ModifyComponent
asChildOf: davElement (@"write", nsD)];
[webdavAclManager
registerDAVPermission: davElement (@"respond-to-component", nsI)
abstract: YES
withEquivalent: SOGoCalendarPerm_RespondToComponent
asChildOf: davElement (@"write-content", nsD)];
[webdavAclManager registerDAVPermission: davElement (@"admin", nsI)
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"all", nsD)];
[webdavAclManager
registerDAVPermission: davElement (@"read-acl", nsD)
abstract: YES
withEquivalent: SOGoPerm_ReadAcls
asChildOf: davElement (@"admin", nsI)];
[webdavAclManager
registerDAVPermission: davElement (@"write-acl", nsD)
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"admin", nsI)];
}
return webdavAclManager;
}
- (NSString *) componentTag
{
return @"vevent";
@@ -0,0 +1,42 @@
/* SOGoUserFolder+Appointments.h - this file is part of SOGo
*
* Copyright (C) 2008 Inverse groupe conseil
*
* 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 SOGOUSERFOLDER_APPOINTMENTS_H
#define SOGOUSERFOLDER_APPOINTMENTS_H
@class NSArray;
#import <SOGo/SOGoUserFolder.h>
@interface SOGoUserFolder (SOGoCalDAVSupport)
- (NSArray *) davCalendarUserAddressSet;
// - (NSArray *) davCalendarHomeSet
// - (NSArray *) davCalendarScheduleInboxURL
// - (NSString *) davCalendarScheduleOutboxURL
// - (NSString *) davDropboxHomeURL
// - (NSString *) davNotificationsURL
@end
#endif /* SOGOUSERFOLDER_APPOINTMENTS_H */
@@ -0,0 +1,130 @@
/* SOGoUserFolder+Appointments.m - this file is part of SOGo
*
* Copyright (C) 2008 Inverse groupe conseil
*
* 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 <NGObjWeb/WOContext+SoObjects.h>
#import <SOGo/SOGoUser.h>
#import "SOGoUserFolder+Appointments.h"
@implementation SOGoUserFolder (SOGoCalDAVSupport)
- (NSArray *) davCalendarUserAddressSet
{
NSArray *tag, *allEmails;
NSMutableArray *addresses;
NSEnumerator *emails;
NSString *currentEmail;
addresses = [NSMutableArray array];
allEmails = [[context activeUser] allEmails];
emails = [allEmails objectEnumerator];
while ((currentEmail = [emails nextObject]))
{
tag = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
[NSString stringWithFormat: @"MAILTO:%@", currentEmail],
nil];
[addresses addObject: tag];
}
return addresses;
}
// /* CalDAV support */
// - (NSArray *) davCalendarHomeSet
// {
// /*
// <C:calendar-home-set xmlns:D="DAV:"
// xmlns:C="urn:ietf:params:xml:ns:caldav">
// <D:href>http://cal.example.com/home/bernard/calendars/</D:href>
// </C:calendar-home-set>
// Note: this is the *container* for calendar collections, not the
// collections itself. So for use its the home folder, the
// public folder and the groups folder.
// */
// NSArray *tag;
// SOGoAppointmentFolders *parent;
// parent = [self privateCalendars: @"Calendar" inContext: context];
// tag = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
// [parent davURL], nil];
// return [NSArray arrayWithObject: tag];
// }
// - (NSArray *) davCalendarScheduleInboxURL
// {
// NSArray *tag;
// SOGoAppointmentFolders *parent;
// parent = [self privateCalendars: @"Calendar" inContext: context];
// tag = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
// [NSString stringWithFormat: @"%@personal/", [parent davURL]],
// nil];
// return [NSArray arrayWithObject: tag];
// }
// - (NSString *) davCalendarScheduleOutboxURL
// {
// NSArray *tag;
// SOGoAppointmentFolders *parent;
// parent = [self privateCalendars: @"Calendar" inContext: context];
// tag = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
// [NSString stringWithFormat: @"%@personal/", [parent davURL]],
// nil];
// return [NSArray arrayWithObject: tag];
// }
// - (NSString *) davDropboxHomeURL
// {
// NSArray *tag;
// SOGoAppointmentFolders *parent;
// parent = [self privateCalendars: @"Calendar" inContext: context];
// tag = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
// [NSString stringWithFormat: @"%@personal/", [parent davURL]],
// nil];
// return [NSArray arrayWithObject: tag];
// }
// - (NSString *) davNotificationsURL
// {
// NSArray *tag;
// SOGoAppointmentFolders *parent;
// parent = [self privateCalendars: @"Calendar" inContext: context];
// tag = [NSArray arrayWithObjects: @"href", @"DAV:", @"D",
// [NSString stringWithFormat: @"%@personal/", [parent davURL]],
// nil];
// return [NSArray arrayWithObject: tag];
// }
@end
-10
View File
@@ -384,16 +384,6 @@
return classes;
}
- (NSArray *) davNamespaces
{
NSMutableArray *ns;
ns = [NSMutableArray arrayWithArray: [super davNamespaces]];
[ns addObjectUniquely: @"urn:ietf:params:xml:ns:carddav"];
return ns;
}
- (NSString *) groupDavResourceType
{
return @"vcard-collection";
@@ -130,11 +130,6 @@
ASSIGN (ldapSource, newLDAPSource);
}
- (NSArray *) davNamespaces
{
return [NSArray arrayWithObject: @"urn:ietf:params:xml:ns:carddav"];
}
- (NSString *) groupDavResourceType
{
return @"vcard-collection";
+62
View File
@@ -26,13 +26,42 @@
#import <SaxObjC/XMLNamespaces.h>
#import "NSObject+DAV.h"
#import "NSString+Utilities.h"
#import "SOGoPermissions.h"
#import "SOGoWebDAVAclManager.h"
#import "SOGoFolder.h"
@interface SOGoObject (SOGoDAVHelpers)
- (void) _fillArrayWithPrincipalsOwnedBySelf: (NSMutableArray *) hrefs;
@end
@implementation SOGoFolder
+ (SOGoWebDAVAclManager *) webdavAclManager
{
SOGoWebDAVAclManager *webdavAclManager = nil;
if (!webdavAclManager)
{
webdavAclManager = [SOGoWebDAVAclManager new];
[webdavAclManager registerDAVPermission: davElement (@"read", @"DAV:")
abstract: YES
withEquivalent: SoPerm_WebDAVAccess
asChildOf: davElement (@"all", @"DAV:")];
[webdavAclManager registerDAVPermission: davElement (@"read-current-user-privilege-set", @"DAV:")
abstract: YES
withEquivalent: nil
asChildOf: davElement (@"read", @"DAV:")];
}
return webdavAclManager;
}
- (id) init
{
if ((self = [super init]))
@@ -75,6 +104,11 @@
return [NSArray array];
}
- (NSArray *) toManyRelationshipKeys
{
return nil;
}
- (BOOL) isValidContentName: (NSString *) name
{
return ([name length] > 0);
@@ -192,6 +226,24 @@
return rType;
}
/* web dav acl helper */
- (void) _fillArrayWithPrincipalsOwnedBySelf: (NSMutableArray *) hrefs
{
NSEnumerator *children;
NSString *currentKey;
[super _fillArrayWithPrincipalsOwnedBySelf: hrefs];
children = [[self toOneRelationshipKeys] objectEnumerator];
while ((currentKey = [children nextObject]))
[[self lookupName: currentKey inContext: context
acquire: NO] _fillArrayWithPrincipalsOwnedBySelf: hrefs];
children = [[self toManyRelationshipKeys] objectEnumerator];
while ((currentKey = [children nextObject]))
[[self lookupName: currentKey inContext: context
acquire: NO] _fillArrayWithPrincipalsOwnedBySelf: hrefs];
}
/* folder type */
- (BOOL) isEqual: (id) otherFolder
@@ -211,6 +263,11 @@
/* acls */
- (NSString *) defaultUserID
{
return nil;
}
- (NSArray *) subscriptionRoles
{
return [NSArray arrayWithObjects: SoRole_Owner, SOGoRole_ObjectViewer,
@@ -223,4 +280,9 @@
return nil;
}
- (NSArray *) aclUsers
{
return nil;
}
@end
+28 -7
View File
@@ -24,6 +24,14 @@
#import <Foundation/NSObject.h>
#import <DOM/DOMProtocols.h>
#if LIB_FOUNDATION_LIBRARY
#error SOGo will not work properly with libFoundation.
#error Please use gnustep-base instead.
#endif
/*
SOGoObject
@@ -48,8 +56,8 @@
@class GCSFolder;
@class SOGoUserFolder;
@class SOGoGroupsFolder;
@class SOGoDAVSet;
@class SOGoWebDAVValue;
@class SOGoWebDAVAclManager;
#define $(class) NSClassFromString(class)
@@ -58,6 +66,7 @@
WOContext *context;
NSString *nameInContainer;
NSString *owner;
SOGoWebDAVAclManager *webdavAclManager;
id container;
}
@@ -90,7 +99,6 @@
/* looking up shared objects */
- (SOGoUserFolder *) lookupUserFolder;
- (SOGoGroupsFolder *) lookupGroupsFolder;
- (void) sleep;
@@ -103,8 +111,6 @@
- (NSException *)delete;
- (id)GETAction:(id)_ctx;
- (SOGoDAVSet *) davCurrentUserPrivilegeSet;
/* etag support */
- (NSException *) matchesRequestConditionInContext:(id)_ctx;
@@ -129,8 +135,10 @@
- (NSString *) httpURLForAdvisoryToUser: (NSString *) uid;
- (NSString *) resourceURLForAdvisoryToUser: (NSString *) uid;
/* dav */
- (NSArray *) davNamespaces;
/* dav acls */
- (SOGoWebDAVValue *) davCurrentUserPrivilegeSet;
/* inverse dav extensions for acls */
- (NSString *) davRecordForUser: (NSString *) user;
/* description */
@@ -139,4 +147,17 @@
@end
@interface SOGoObject (SOGo)
- (NSString *) contentAsString;
@end
@interface SOGoObject (SOGoDomHelpers)
- (NSArray *) domNode: (id <DOMNode>) node
getChildNodesByType: (DOMNodeType) type;
@end
#endif /* __SoObjects_SOGoObject_H__ */
+427 -363
View File
@@ -1,28 +1,25 @@
/*
Copyright (C) 2004-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.
*/
#if LIB_FOUNDATION_LIBRARY
#error SOGo will not work properly with libFoundation.
#error Please use gnustep-base instead.
#endif
/* SOGoGCSFolder.m - this file is part of SOGo
*
* Copyright (C) 2004-2005 SKYRIX Software AG
* Copyright (C) 2006-2008 Inverse groupe conseil
*
* 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 <unistd.h>
@@ -36,10 +33,8 @@
#import <Foundation/NSValue.h>
#import <NGObjWeb/SoClass.h>
#import <NGObjWeb/SoClassSecurityInfo.h>
#import <NGObjWeb/SoObject+SoDAV.h>
#import <NGObjWeb/SoSelectorInvocation.h>
#import <NGObjWeb/SoWebDAVValue.h>
#import <NGObjWeb/WEClientCapabilities.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WOContext.h>
@@ -60,14 +55,15 @@
#import "NSArray+Utilities.h"
#import "NSCalendarDate+SOGo.h"
#import "NSDictionary+Utilities.h"
#import "NSObject+DAV.h"
#import "NSObject+Utilities.h"
#import "NSString+Utilities.h"
#import "SOGoCache.h"
#import "SOGoDAVAuthenticator.h"
#import "SOGoDAVRendererTypes.h"
#import "SOGoPermissions.h"
#import "SOGoUser.h"
#import "SOGoUserFolder.h"
#import "SOGoWebDAVAclManager.h"
#import "SOGoWebDAVValue.h"
#import "SOGoObject.h"
@@ -76,136 +72,62 @@ static BOOL sendACLAdvisories = NO;
static NSDictionary *reportMap = nil;
@interface SOGoObject(Content)
- (NSString *) contentAsString;
@end
@interface SoClassSecurityInfo (SOGoAcls)
+ (id) defaultWebDAVPermissionsMap;
- (NSArray *) allPermissions;
- (NSArray *) allDAVPermissions;
- (NSArray *) DAVPermissionsForRole: (NSString *) role;
- (NSArray *) DAVPermissionsForRoles: (NSArray *) roles;
@end
@implementation SoClassSecurityInfo (SOGoAcls)
+ (id) defaultWebDAVPermissionsMap
{
return [NSDictionary dictionaryWithObjectsAndKeys:
@"read", SoPerm_AccessContentsInformation,
@"bind", SoPerm_AddDocumentsImagesAndFiles,
@"unbind", SoPerm_DeleteObjects,
@"write-acl", SoPerm_ChangePermissions,
@"write-content", SoPerm_ChangeImagesAndFiles,
@"read-free-busy", SOGoPerm_FreeBusyLookup,
NULL];
}
- (NSArray *) allPermissions
{
return [defRoles allKeys];
}
- (NSArray *) allDAVPermissions
{
NSEnumerator *allPermissions;
NSMutableArray *davPermissions;
NSDictionary *davPermissionsMap;
NSString *sopePermission, *davPermission;
davPermissions = [NSMutableArray array];
davPermissionsMap = [[self class] defaultWebDAVPermissionsMap];
allPermissions = [[self allPermissions] objectEnumerator];
sopePermission = [allPermissions nextObject];
while (sopePermission)
{
davPermission = [davPermissionsMap objectForCaseInsensitiveKey: sopePermission];
if (davPermission && ![davPermissions containsObject: davPermission])
[davPermissions addObject: davPermission];
sopePermission = [allPermissions nextObject];
}
return davPermissions;
}
- (NSArray *) DAVPermissionsForRole: (NSString *) role
{
return [self DAVPermissionsForRoles: [NSArray arrayWithObject: role]];
}
- (NSArray *) DAVPermissionsForRoles: (NSArray *) roles
{
NSEnumerator *allPermissions;
NSMutableArray *davPermissions;
NSDictionary *davPermissionsMap;
NSString *sopePermission, *davPermission;
davPermissions = [NSMutableArray array];
davPermissionsMap = [[self class] defaultWebDAVPermissionsMap];
allPermissions = [[self allPermissions] objectEnumerator];
sopePermission = [allPermissions nextObject];
while (sopePermission)
{
if ([[defRoles objectForCaseInsensitiveKey: sopePermission]
firstObjectCommonWithArray: roles])
{
davPermission
= [davPermissionsMap objectForCaseInsensitiveKey: sopePermission];
if (davPermission
&& ![davPermissions containsObject: davPermission])
[davPermissions addObject: davPermission];
}
sopePermission = [allPermissions nextObject];
}
return davPermissions;
}
@end
@implementation SOGoObject
+ (void) _loadReportMap
+ (SOGoWebDAVAclManager *) webdavAclManager
{
NSFileManager *fm;
NSEnumerator *paths;
NSString *currentPath, *filename;
SOGoWebDAVAclManager *webdavAclManager = nil;
[self logWithFormat: @"Loading DAV REPORT map:"];
if (!webdavAclManager)
webdavAclManager = [SOGoWebDAVAclManager new];
fm = [NSFileManager defaultManager];
paths = [NSStandardLibraryPaths() objectEnumerator];
while (!reportMap && (currentPath = [paths nextObject]))
{
filename = [NSString stringWithFormat: @"%@/SOGo-%s.%s/SOGo.framework"
@"/Resources/DAVReportMap.plist",
currentPath,
SOGO_MAJOR_VERSION, SOGO_MINOR_VERSION];
[self logWithFormat: @" %@", filename];
if ([fm fileExistsAtPath: filename])
{
reportMap = [[NSDictionary alloc] initWithContentsOfFile: filename];
[self logWithFormat: @"found!"];
}
}
return webdavAclManager;
}
/*
+ (id) WebDAVPermissionsMap
{
static NSDictionary *permissions = nil;
if (!permissions)
{
permissions = [NSDictionary dictionaryWithObjectsAndKeys:
davElement (@"read", @"DAV:"),
SoPerm_AccessContentsInformation,
davElement (@"bind", @"DAV:"),
SoPerm_AddDocumentsImagesAndFiles,
davElement (@"unbind", @"DAV:"),
SoPerm_DeleteObjects,
davElement (@"write-acl", @"DAV:"),
SoPerm_ChangePermissions,
davElement (@"write-content", @"DAV:"),
SoPerm_ChangeImagesAndFiles, NULL];
[permissions retain];
}
return permissions;
} */
+ (void) initialize
{
NSUserDefaults *ud;
NSString *filename;
NSBundle *bundle;
ud = [NSUserDefaults standardUserDefaults];
kontactGroupDAV = ![ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"];
sendACLAdvisories = [ud boolForKey: @"SOGoACLsSendEMailNotifications"];
if (!reportMap)
[self _loadReportMap];
{
bundle = [NSBundle bundleForClass: self];
filename = [bundle pathForResource: @"DAVReportMap" ofType: @"plist"];
if (filename
&& [[NSFileManager defaultManager] fileExistsAtPath: filename])
reportMap = [[NSDictionary alloc] initWithContentsOfFile: filename];
else
[self logWithFormat: @"DAV REPORT map not found!"];
}
// SoClass security declarations
// require View permission to access the root (bound to authenticated ...)
@@ -250,51 +172,6 @@ static NSDictionary *reportMap = nil;
return [[self class] globallyUniqueObjectId];
}
+ (void) _fillDictionary: (NSMutableDictionary *) dictionary
withDAVMethods: (NSString *) firstMethod, ...
{
va_list ap;
NSString *aclMethodName;
NSString *methodName;
SEL methodSel;
va_start (ap, firstMethod);
aclMethodName = firstMethod;
while (aclMethodName)
{
methodName = [aclMethodName davMethodToObjC];
methodSel = NSSelectorFromString (methodName);
if (methodSel && [self instancesRespondToSelector: methodSel])
[dictionary setObject: methodName
forKey: [NSString stringWithFormat: @"{DAV:}%@",
aclMethodName]];
else
NSLog(@"************ method '%@' is still unimplemented!",
methodName);
aclMethodName = va_arg (ap, NSString *);
}
va_end (ap);
}
+ (NSDictionary *) defaultWebDAVAttributeMap
{
static NSMutableDictionary *map = nil;
if (!map)
{
map = [NSMutableDictionary
dictionaryWithDictionary: [super defaultWebDAVAttributeMap]];
[map retain];
[self _fillDictionary: map
withDAVMethods: @"owner", @"group", @"supported-privilege-set",
@"current-user-privilege-set", @"acl", @"acl-restrictions",
@"inherited-acl-set", @"principal-collection-set", nil];
}
return map;
}
/* containment */
+ (id) objectWithName: (NSString *)_name inContainer:(id)_container
@@ -307,156 +184,6 @@ static NSDictionary *reportMap = nil;
return object;
}
/* DAV ACL properties */
- (NSString *) davOwner
{
return [NSString stringWithFormat: @"%@%@",
[WOApplication davURL],
[self ownerInContext: nil]];
}
- (NSString *) davAclRestrictions
{
NSMutableString *restrictions;
restrictions = [NSMutableString string];
[restrictions appendString: @"<D:grant-only/>"];
[restrictions appendString: @"<D:no-invert/>"];
return restrictions;
}
- (SOGoDAVSet *) davPrincipalCollectionSet
{
NSString *usersUrl;
usersUrl = [NSString stringWithFormat: @"%@users",
[self rootURLInContext: context]];
return [SOGoDAVSet davSetWithArray: [NSArray arrayWithObject: usersUrl]
ofValuesTaggedAs: @"D:href"];
}
- (SOGoDAVSet *) davCurrentUserPrivilegeSet
{
SOGoDAVAuthenticator *sAuth;
SoUser *user;
NSArray *roles;
SoClassSecurityInfo *sInfo;
NSArray *davPermissions;
sAuth = [SOGoDAVAuthenticator sharedSOGoDAVAuthenticator];
user = [sAuth userInContext: context];
roles = [user rolesForObject: self inContext: context];
sInfo = [[self class] soClassSecurityInfo];
davPermissions
= [[sInfo DAVPermissionsForRoles: roles] stringsWithFormat: @"<D:%@/>"];
return [SOGoDAVSet davSetWithArray: davPermissions
ofValuesTaggedAs: @"D:privilege"];
}
- (SOGoDAVSet *) davSupportedPrivilegeSet
{
SoClassSecurityInfo *sInfo;
NSArray *allPermissions;
sInfo = [[self class] soClassSecurityInfo];
allPermissions = [[sInfo allDAVPermissions] stringsWithFormat: @"<D:%@/>"];
return [SOGoDAVSet davSetWithArray: allPermissions
ofValuesTaggedAs: @"D:privilege"];
}
- (NSArray *) _davAcesFromAclsDictionary: (NSDictionary *) aclsDictionary
{
NSEnumerator *keys;
NSArray *privileges;
NSMutableString *currentAce;
NSMutableArray *davAces;
NSString *currentKey, *principal;
SOGoDAVSet *privilegesDS;
davAces = [NSMutableArray array];
keys = [[aclsDictionary allKeys] objectEnumerator];
currentKey = [keys nextObject];
while (currentKey)
{
currentAce = [NSMutableString string];
if ([currentKey hasPrefix: @":"])
[currentAce
appendFormat: @"<D:principal><D:property><D:%@/></D:property></D:principal>",
[currentKey substringFromIndex: 1]];
else
{
principal = [NSString stringWithFormat: @"%@users/%@",
[self rootURLInContext: context],
currentKey];
[currentAce
appendFormat: @"<D:principal><D:href>%@</D:href></D:principal>",
principal];
}
privileges = [[aclsDictionary objectForKey: currentKey]
stringsWithFormat: @"<D:%@/>"];
privilegesDS = [SOGoDAVSet davSetWithArray: privileges
ofValuesTaggedAs: @"privilege"];
[currentAce appendString: [privilegesDS stringForTag: @"{DAV:}grant"
rawName: @"grant"
inContext: nil prefixes: nil]];
[davAces addObject: currentAce];
currentKey = [keys nextObject];
}
return davAces;
}
- (void) _appendRolesForPseudoPrincipals: (NSMutableDictionary *) aclsDictionary
withClassSecurityInfo: (SoClassSecurityInfo *) sInfo
{
NSArray *perms;
perms = [sInfo DAVPermissionsForRole: SoRole_Owner];
if ([perms count])
[aclsDictionary setObject: perms forKey: @":owner"];
perms = [sInfo DAVPermissionsForRole: SoRole_Authenticated];
if ([perms count])
[aclsDictionary setObject: perms forKey: @":authenticated"];
perms = [sInfo DAVPermissionsForRole: SoRole_Anonymous];
if ([perms count])
[aclsDictionary setObject: perms forKey: @":unauthenticated"];
}
- (SOGoDAVSet *) davAcl
{
NSArray *roles;
NSEnumerator *uids;
NSMutableDictionary *aclsDictionary;
NSString *currentUID;
SoClassSecurityInfo *sInfo;
aclsDictionary = [NSMutableDictionary dictionary];
uids = [[self aclUsers] objectEnumerator];
sInfo = [[self class] soClassSecurityInfo];
currentUID = [uids nextObject];
while (currentUID)
{
roles = [self aclsForUser: currentUID];
[aclsDictionary setObject: [sInfo DAVPermissionsForRoles: roles]
forKey: currentUID];
currentUID = [uids nextObject];
}
[self _appendRolesForPseudoPrincipals: aclsDictionary
withClassSecurityInfo: sInfo];
return [SOGoDAVSet davSetWithArray:
[self _davAcesFromAclsDictionary: aclsDictionary]
ofValuesTaggedAs: @"D:ace"];
}
/* end of properties */
- (BOOL) doesRetainContainer
@@ -472,6 +199,7 @@ static NSDictionary *reportMap = nil;
nameInContainer = nil;
container = nil;
owner = nil;
webdavAclManager = [[self class] webdavAclManager];
}
return self;
@@ -614,16 +342,14 @@ static NSDictionary *reportMap = nil;
{
id obj;
SOGoCache *cache;
NSString *objcMethod;
NSString *objcMethod, *httpMethod;
cache = [SOGoCache sharedCache];
obj = [cache objectNamed: lookupName inContainer: self];
if (!obj)
{
obj = [[self soClass] lookupKey: lookupName inContext: localContext];
if (obj)
[obj bindToObject: self inContext: localContext];
else
httpMethod = [[localContext request] method];
if ([httpMethod isEqualToString: @"REPORT"])
{
objcMethod = [self _reportSelector: lookupName];
if (objcMethod)
@@ -634,6 +360,12 @@ static NSDictionary *reportMap = nil;
[obj autorelease];
}
}
else
{
obj = [[self soClass] lookupKey: lookupName inContext: localContext];
if (obj)
[obj bindToObject: self inContext: localContext];
}
if (obj)
[cache registerObject: obj withName: lookupName inContainer: self];
@@ -652,10 +384,10 @@ static NSDictionary *reportMap = nil;
return [container lookupUserFolder];
}
- (SOGoGroupsFolder *) lookupGroupsFolder
{
return [[self lookupUserFolder] lookupGroupsFolder];
}
// - (SOGoGroupsFolder *) lookupGroupsFolder
// {
// return [[self lookupUserFolder] lookupGroupsFolder];
// }
- (void) sleep
{
@@ -686,6 +418,316 @@ static NSDictionary *reportMap = nil;
return [self nameInContainer];
}
/* DAV ACL properties */
- (SOGoWebDAVValue *) davOwner
{
NSDictionary *ownerHREF;
NSString *usersUrl;
usersUrl = [NSString stringWithFormat: @"%@%@/",
[[WOApplication application] davURL], owner];
ownerHREF = davElementWithContent (@"href", @"DAV:", usersUrl);
return [davElementWithContent (@"owner", @"DAV:", ownerHREF)
asWebDAVValue];
}
- (SOGoWebDAVValue *) davAclRestrictions
{
NSArray *restrictions;
restrictions = [NSArray arrayWithObjects:
davElement (@"grant-only", @"DAV:"),
davElement (@"no-invert", @"DAV:"),
nil];
return [davElementWithContent (@"acl-restrictions", @"DAV:", restrictions)
asWebDAVValue];
}
- (SOGoWebDAVValue *) davPrincipalCollectionSet
{
NSString *usersUrl;
NSDictionary *collectionHREF;
/* WOApplication has no support for the DAV methods we define here so we
use the user's principal object as a reference */
usersUrl = [NSString stringWithFormat: @"%@%@/",
[[WOApplication application] davURL], owner];
collectionHREF = davElementWithContent (@"href", @"DAV:", usersUrl);
return [davElementWithContent (@"principal-collection-set",
@"DAV:",
[NSArray arrayWithObject: collectionHREF])
asWebDAVValue];
}
- (NSArray *) _davPrivilegesFromRoles: (NSArray *) roles
{
NSEnumerator *privileges;
NSDictionary *privilege;
NSMutableArray *davPrivileges;
davPrivileges = [NSMutableArray array];
privileges = [[webdavAclManager davPermissionsForRoles: roles
onObject: self] objectEnumerator];
while ((privilege = [privileges nextObject]))
[davPrivileges addObject: davElementWithContent (@"privilege", @"DAV:",
privilege)];
return davPrivileges;
}
- (SOGoWebDAVValue *) davCurrentUserPrivilegeSet
{
NSArray *userRoles;
userRoles = [[context activeUser] rolesForObject: self inContext: context];
return [davElementWithContent (@"current-user-privilege-set",
@"DAV:",
[self _davPrivilegesFromRoles: userRoles])
asWebDAVValue];
}
- (SOGoWebDAVValue *) davSupportedPrivilegeSet
{
return [davElementWithContent (@"supported-privilege-set",
@"DAV:",
[webdavAclManager treeAsWebDAVValue])
asWebDAVValue];
}
#warning this method has probably some code shared with its pseudo principal equivalent
- (void) _fillAces: (NSMutableArray *) aces
withRolesForUID: (NSString *) currentUID
{
NSMutableArray *currentAce;
NSArray *roles;
NSDictionary *currentGrant, *userHREF;
NSString *principalURL;
currentAce = [NSMutableArray new];
roles = [[SOGoUser userWithLogin: currentUID roles: nil]
rolesForObject: self
inContext: context];
if ([roles count])
{
principalURL = [NSString stringWithFormat: @"%@%@/",
[[WOApplication application] davURL],
currentUID];
userHREF = davElementWithContent (@"href", @"DAV:", principalURL);
[currentAce addObject: davElementWithContent (@"principal", @"DAV:",
userHREF)];
currentGrant
= davElementWithContent (@"grant", @"DAV:",
[self _davPrivilegesFromRoles: roles]);
[currentAce addObject: currentGrant];
[aces addObject: davElementWithContent (@"ace", @"DAV:", currentAce)];
[currentAce release];
}
}
- (void) _fillAcesWithRolesForPseudoPrincipals: (NSMutableArray *) aces
{
NSArray *roles, *currentAce;
NSDictionary *principal, *currentGrant;
SOGoUser *user;
// DAV:self, DAV:property(owner), DAV:authenticated
user = [context activeUser];
roles = [user rolesForObject: self inContext: context];
if ([roles count])
{
principal = davElement (@"self", @"DAV:");
currentGrant
= davElementWithContent (@"grant", @"DAV:",
[self _davPrivilegesFromRoles: roles]);
currentAce = [NSArray arrayWithObjects:
davElementWithContent (@"principal", @"DAV:",
principal),
currentGrant, nil];
[aces addObject: davElementWithContent (@"ace", @"DAV:", currentAce)];
}
user = [SOGoUser userWithLogin: [self ownerInContext: context] roles: nil];
roles = [user rolesForObject: self inContext: context];
if ([roles count])
{
principal = davElementWithContent (@"property", @"DAV:",
davElement (@"owner", @"DAV:"));
currentGrant
= davElementWithContent (@"grant", @"DAV:",
[self _davPrivilegesFromRoles: roles]);
currentAce = [NSArray arrayWithObjects:
davElementWithContent (@"principal", @"DAV:",
principal),
currentGrant, nil];
[aces addObject: davElementWithContent (@"ace", @"DAV:", currentAce)];
}
roles = [self aclsForUser: [self defaultUserID]];
if ([roles count])
{
principal = davElement (@"authenticated", @"DAV:");
currentGrant
= davElementWithContent (@"grant", @"DAV:",
[self _davPrivilegesFromRoles: roles]);
currentAce = [NSArray arrayWithObjects:
davElementWithContent (@"principal", @"DAV:",
principal),
currentGrant, nil];
[aces addObject: davElementWithContent (@"ace", @"DAV:", currentAce)];
}
}
- (SOGoWebDAVValue *) davAcl
{
NSEnumerator *uids;
NSMutableArray *aces;
NSString *currentUID;
aces = [NSMutableArray array];
[self _fillAcesWithRolesForPseudoPrincipals: aces];
uids = [[self aclUsers] objectEnumerator];
while ((currentUID = [uids nextObject]))
[self _fillAces: aces withRolesForUID: currentUID];
return [davElementWithContent (@"acl", @"DAV:", aces)
asWebDAVValue];
}
#warning all REPORT method should be standardized...
- (NSDictionary *) _formalizePrincipalMatchResponse: (NSArray *) hrefs
{
NSDictionary *multiStatus;
NSEnumerator *hrefList;
NSString *currentHref;
NSMutableArray *responses;
NSArray *responseElements;
responses = [NSMutableArray new];
hrefList = [hrefs objectEnumerator];
while ((currentHref = [hrefList nextObject]))
{
responseElements
= [NSArray arrayWithObjects: davElementWithContent (@"href", @"DAV:",
currentHref),
davElementWithContent (@"status", @"DAV:",
@"HTTP/1.1 200 OK"),
nil];
[responses addObject: davElementWithContent (@"response", @"DAV:",
responseElements)];
}
multiStatus = davElementWithContent (@"multistatus", @"DAV:", responses);
[responses release];
return multiStatus;
}
- (NSDictionary *) _handlePrincipalMatchSelf
{
NSString *davURL, *userLogin;
NSArray *principalURL;
davURL = [[WOApplication application] davURL];
userLogin = [[context activeUser] login];
principalURL
= [NSArray arrayWithObject: [NSString stringWithFormat: @"%@%@/", davURL,
userLogin]];
return [self _formalizePrincipalMatchResponse: principalURL];
}
- (void) _fillArrayWithPrincipalsOwnedBySelf: (NSMutableArray *) hrefs
{
NSString *url;
NSArray *roles;
roles = [[context activeUser] rolesForObject: self inContext: context];
if ([roles containsObject: SoRole_Owner])
{
url = [[self davURL] absoluteString];
[hrefs addObject: url];
}
}
- (NSDictionary *)
_handlePrincipalMatchPrincipalProperty: (id <DOMElement>) child
{
NSMutableArray *hrefs;
NSDictionary *response;
hrefs = [NSMutableArray new];
[self _fillArrayWithPrincipalsOwnedBySelf: hrefs];
response = [self _formalizePrincipalMatchResponse: hrefs];
[hrefs release];
return response;
}
- (NSDictionary *) _handlePrincipalMatchReport: (id <DOMDocument>) document
{
NSDictionary *response;
id <DOMElement> documentElement, queryChild;
NSArray *children;
NSString *queryTag;
documentElement = [document documentElement];
children = [self domNode: documentElement
getChildNodesByType: DOM_ELEMENT_NODE];
if ([children count] == 1)
{
queryChild = [children objectAtIndex: 0];
queryTag = [queryChild tagName];
if ([queryTag isEqualToString: @"self"])
response = [self _handlePrincipalMatchSelf];
else if ([queryTag isEqualToString: @"principal-property"])
response = [self _handlePrincipalMatchPrincipalProperty: queryChild];
else
response = [NSException exceptionWithHTTPStatus: 400
reason: @"Query element must be either "
@" '{DAV:}principal-property' or '{DAV:}self'"];
}
else
response = [NSException exceptionWithHTTPStatus: 400
reason: @"Query must have one element:"
@" '{DAV:}principal-property' or '{DAV:}self'"];
return response;
}
- (WOResponse *) davPrincipalMatch: (WOContext *) localContext
{
WOResponse *r;
id <DOMDocument> document;
NSDictionary *xmlResponse;
r = [context response];
document = [[context request] contentAsDOMDocument];
xmlResponse = [self _handlePrincipalMatchReport: document];
if ([xmlResponse isKindOfClass: [NSException class]])
r = (WOResponse *) xmlResponse;
else
{
[r setStatus: 207];
[r setContentEncoding: NSUTF8StringEncoding];
[r setHeader: @"text/xml; charset=\"utf-8\"" forKey: @"content-type"];
[r setHeader: @"no-cache" forKey: @"pragma"];
[r setHeader: @"no-cache" forKey: @"cache-control"];
[r appendContentString:
@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"];
[r appendContentString: [xmlResponse asWebDavStringWithNamespaces: nil]];
}
return r;
}
/* actions */
- (id) DELETEAction: (id) _ctx
@@ -763,7 +805,8 @@ static NSDictionary *reportMap = nil;
if ([rq isSoWebDAVRequest])
{
cType = [rq headerForKey: @"content-type"];
if ([cType isEqualToString: @"application/xml"])
if ([cType hasPrefix: @"application/xml"]
|| [cType hasPrefix: @"text/xml"])
{
document = [rq contentAsDOMDocument];
command = [[self _parseXMLCommand: document] davMethodToObjC];
@@ -1188,7 +1231,8 @@ static NSDictionary *reportMap = nil;
/* description */
- (void)appendAttributesToDescription:(NSMutableString *)_ms {
- (void) appendAttributesToDescription: (NSMutableString *) _ms
{
if (nameInContainer)
[_ms appendFormat:@" name=%@", nameInContainer];
if (container)
@@ -1196,7 +1240,8 @@ static NSDictionary *reportMap = nil;
container, [container valueForKey:@"nameInContainer"]];
}
- (NSString *)description {
- (NSString *) description
{
NSMutableString *ms;
ms = [NSMutableString stringWithCapacity:64];
@@ -1227,12 +1272,6 @@ static NSDictionary *reportMap = nil;
}
/* dav acls */
- (NSArray *) davNamespaces
{
return [NSArray arrayWithObject:
@"urn:inverse:params:xml:ns:inverse-dav"];
}
- (NSString *) davRecordForUser: (NSString *) user
{
NSMutableString *userRecord;
@@ -1443,11 +1482,12 @@ static NSDictionary *reportMap = nil;
return exception;
}
- (NSArray *) davSupportedReportSet
- (SOGoWebDAVValue *) davSupportedReportSet
{
NSDictionary *currentValue;
NSEnumerator *reportKeys;
NSMutableArray *reportSet;
NSString *currentKey, *currentValue;
NSString *currentKey;
reportSet = [NSMutableArray array];
@@ -1455,13 +1495,37 @@ static NSDictionary *reportMap = nil;
while ((currentKey = [reportKeys nextObject]))
if ([self _reportSelector: currentKey])
{
currentValue = [[currentKey asDavInvocation]
keysWithFormat: @"<%{method} xmlns=\"%{ns}\"/>"];
[reportSet addObject: [SoWebDAVValue valueForObject: currentValue
attributes: nil]];
currentValue = [currentKey asDavInvocation];
[reportSet addObject: davElementWithContent(@"report",
@"DAV:",
currentValue)];
}
return [SOGoDAVSet davSetWithArray: reportSet ofValuesTaggedAs: @"report"];
return [davElementWithContent (@"supported-report-set", @"DAV:", reportSet)
asWebDAVValue];
}
@end /* SOGoObject */
@implementation SOGoObject (SOGoDomHelpers)
- (NSArray *) domNode: (id <DOMNode>) node
getChildNodesByType: (DOMNodeType ) type
{
NSMutableArray *nodes;
id <DOMNode> currentChild;
nodes = [NSMutableArray array];
currentChild = [node firstChild];
while (currentChild)
{
if ([currentChild nodeType] == type)
[nodes addObject: currentChild];
currentChild = [currentChild nextSibling];
}
return nodes;
}
@end
+53
View File
@@ -0,0 +1,53 @@
/* SOGoWebDAVAclManager.h - this file is part of SOGo
*
* Copyright (C) 2008 Inverse groupe conseil
*
* 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 SOGOWEBDAVACLMANAGER_H
#define SOGOWEBDAVACLMANAGER_H
#import <Foundation/NSObject.h>
@class NSDictionary;
@class NSMutableDictionary;
@class NSString;
@class SOGoObject;
@class SOGoUser;
@class SOGoWebDAVValue;
@interface SOGoWebDAVAclManager : NSObject
{
NSMutableDictionary *aclTree;
}
- (void) registerDAVPermission: (NSDictionary *) davPermission
abstract: (BOOL) abstract
withEquivalent: (NSString *) sogoPermission
asChildOf: (NSDictionary *) otherDAVPermission;
- (NSArray *) davPermissionsForRoles: (NSArray *) roles
onObject: (SOGoObject *) object;
- (SOGoWebDAVValue *) treeAsWebDAVValue;
@end
#endif /* SOGOWEBDAVACLMANAGER_H */
+262
View File
@@ -0,0 +1,262 @@
/* SOGoWebDAVAclManager.m - this file is part of SOGo
*
* Copyright (C) 2008 Inverse groupe conseil
*
* 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/NSString.h>
#import <Foundation/NSValue.h>
#import <NGObjWeb/SoClass.h>
#import <NGObjWeb/SoClassSecurityInfo.h>
#import <NGExtensions/NSObject+Logs.h>
#import "NSDictionary+Utilities.h"
#import "NSObject+DAV.h"
#import "SOGoObject.h"
#import "SOGoUser.h"
#import "SOGoWebDAVValue.h"
#import "SOGoWebDAVAclManager.h"
static NSNumber *yesObject = nil;
@interface SoClass (SOGoDAVPermissions)
- (BOOL) userRoles: (NSArray *) userRoles
havePermission: (NSString *) permission;
@end
@implementation SoClass (SOGoDAVPermissions)
- (BOOL) userRoles: (NSArray *) userRoles
havePermission: (NSString *) permission
{
BOOL result;
SoClass *currentClass;
NSArray *roles;
result = NO;
currentClass = self;
while (!result && currentClass)
{
roles = [[currentClass soClassSecurityInfo]
defaultRolesForPermission: permission];
if ([roles firstObjectCommonWithArray: userRoles])
{
NSLog (@"matched '%@': %@", permission, roles);
result = YES;
}
else
currentClass = [currentClass soSuperClass];
}
return result;
}
@end
@implementation SOGoWebDAVAclManager
+ (void) initialize
{
if (!yesObject)
{
yesObject = [NSNumber numberWithBool: YES];
[yesObject retain];
}
}
- (id) init
{
if ((self = [super init]))
{
aclTree = [NSMutableDictionary new];
[self registerDAVPermission: davElement (@"all", @"DAV:")
abstract: YES
withEquivalent: nil
asChildOf: nil];
}
return self;
}
- (void) dealloc
{
[aclTree release];
[super dealloc];
}
- (void) _registerChild: (NSMutableDictionary *) newEntry
of: (NSDictionary *) parentPermission
{
NSString *identifier;
NSMutableDictionary *parentEntry;
NSMutableArray *children;
identifier = [parentPermission keysWithFormat: @"{%{ns}}%{method}"];
parentEntry = [aclTree objectForKey: identifier];
if (!parentEntry)
[self warnWithFormat: @"parent entry '%@' does not exist in DAV"
@" permissions table", identifier];
children = [parentEntry objectForKey: @"children"];
if (!children)
{
children = [NSMutableArray new];
[parentEntry setObject: children forKey: @"children"];
[children release];
}
[children addObject: newEntry];
[newEntry setObject: parentEntry forKey: @"parent"];
}
- (void) registerDAVPermission: (NSDictionary *) davPermission
abstract: (BOOL) abstract
withEquivalent: (NSString *) sogoPermission
asChildOf: (NSDictionary *) otherDAVPermission
{
NSMutableDictionary *newEntry;
NSString *identifier;
newEntry = [NSMutableDictionary new];
identifier = [davPermission keysWithFormat: @"{%{ns}}%{method}"];
if ([aclTree objectForKey: identifier])
[self warnWithFormat:
@"entry '%@' already exists in DAV permissions table",
identifier];
[aclTree setObject: newEntry forKey: identifier];
[newEntry setObject: davPermission forKey: @"permission"];
if (abstract)
[newEntry setObject: yesObject forKey: @"abstract"];
if (sogoPermission)
[newEntry setObject: sogoPermission forKey: @"equivalent"];
if (otherDAVPermission)
[self _registerChild: newEntry of: otherDAVPermission];
[newEntry release];
}
#warning this method should be simplified!
/* We add the permissions that fill those conditions:
- should match the sogo permissions implied by the user roles
If all the child permissions of a permission are included, then this
permission will be included too. Conversely, if a permission is included,
all the child permissions will be included too. */
- (BOOL) _fillArray: (NSMutableArray *) davPermissions
withPermission: (NSDictionary *) permission
forUserRoles: (NSArray *) userRoles
withSoClass: (SoClass *) soClass
matchSOGoPerms: (BOOL) matchSOGoPerms
{
NSString *sogoPermission;
NSDictionary *childPermission;
NSEnumerator *children;
BOOL appended, childrenAppended;
appended = YES;
if (matchSOGoPerms)
{
sogoPermission = [permission objectForKey: @"equivalent"];
if (sogoPermission
&& [soClass userRoles: userRoles havePermission: sogoPermission])
{
[davPermissions
addObject: [permission objectForKey: @"permission"]];
}
else
appended = NO;
}
else
[davPermissions
addObject: [permission objectForKey: @"permission"]];
children = [[permission objectForKey: @"children"] objectEnumerator];
if (children)
{
childrenAppended = YES;
while ((childPermission = [children nextObject]))
childrenAppended = (childrenAppended
&& [self _fillArray: davPermissions
withPermission: childPermission
forUserRoles: userRoles
withSoClass: soClass
matchSOGoPerms: (matchSOGoPerms && !appended)]);
if (childrenAppended && !appended)
{
[davPermissions
addObject: [permission objectForKey: @"permission"]];
appended = YES;
}
}
return appended;
}
- (NSArray *) davPermissionsForRoles: (NSArray *) roles
onObject: (SOGoObject *) object
{
NSMutableArray *davPermissions;
SoClass *soClass;
davPermissions = [NSMutableArray array];
soClass = [[object class] soClass];
[self _fillArray: davPermissions
withPermission: [aclTree objectForKey: @"{DAV:}all"]
forUserRoles: roles
withSoClass: soClass
matchSOGoPerms: YES];
return davPermissions;
}
- (SOGoWebDAVValue *)
_supportedPrivilegeSetFromPermission: (NSDictionary *) perm
{
NSMutableArray *privilege;
NSEnumerator *children;
NSDictionary *currentPerm;
privilege = [NSMutableArray array];
[privilege addObject:
davElementWithContent (@"privilege",
@"DAV:",
[perm objectForKey: @"permission"])];
if ([[perm objectForKey: @"abstract"] boolValue])
[privilege addObject: davElement (@"abstract", @"DAV:")];
children = [[perm objectForKey: @"children"] objectEnumerator];
while ((currentPerm = [children nextObject]))
[privilege addObject:
[self _supportedPrivilegeSetFromPermission: currentPerm]];
return davElementWithContent (@"supported-privilege",
@"DAV:", privilege);
}
- (SOGoWebDAVValue *) treeAsWebDAVValue
{
return [self _supportedPrivilegeSetFromPermission:
[aclTree objectForKey: @"{DAV:}all"]];
}
@end