From bf23e9d250d476f53ce91bf7523000c6fd8daa35 Mon Sep 17 00:00:00 2001 From: Emilio Pavia Date: Tue, 19 Jun 2012 20:19:23 +0200 Subject: [PATCH] Add administrative features (set/retrieve groups and ACLs, channel creation). --- AUTHORS | 1 + CONTRIBUTORS | 8 ++ MumbleKit.xcodeproj/project.pbxproj | 42 ++++++++ src/MKAccessControl.m | 17 ++++ src/MKChannelACL.m | 146 ++++++++++++++++++++++++++++ src/MKChannelGroup.m | 27 +++++ src/MKServerModel.m | 136 +++++++++++++++++++++++++- src/MumbleKit/MKAccessControl.h | 11 +++ src/MumbleKit/MKChannelACL.h | 18 ++++ src/MumbleKit/MKChannelGroup.h | 15 +++ src/MumbleKit/MKPermission.h | 24 +++++ src/MumbleKit/MKServerModel.h | 64 ++++++++---- 12 files changed, 488 insertions(+), 21 deletions(-) create mode 100644 CONTRIBUTORS create mode 100644 src/MKAccessControl.m create mode 100644 src/MKChannelACL.m create mode 100644 src/MKChannelGroup.m create mode 100644 src/MumbleKit/MKAccessControl.h create mode 100644 src/MumbleKit/MKChannelACL.h create mode 100644 src/MumbleKit/MKChannelGroup.h create mode 100644 src/MumbleKit/MKPermission.h diff --git a/AUTHORS b/AUTHORS index fceebdf..11b4574 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,3 +5,4 @@ Thorvald Natvig Mikkel Krautz Stefan Hacker Benjamin Jemlich +TOK.TV Inc. \ No newline at end of file diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..432c95e --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,8 @@ +// This is the official list of people who can contribute +// (and typically have contributed) code to MumbleKit. + +Benjamin Jemlich +Emilio Pavia +Mikkel Krautz +Stefan Hacker +Thorvald Natvig \ No newline at end of file diff --git a/MumbleKit.xcodeproj/project.pbxproj b/MumbleKit.xcodeproj/project.pbxproj index 0a51948..4ef4a3a 100644 --- a/MumbleKit.xcodeproj/project.pbxproj +++ b/MumbleKit.xcodeproj/project.pbxproj @@ -126,6 +126,20 @@ 28CC3717132EDC7300241269 /* libSpeexDSP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 28CC3712132EDC7300241269 /* libSpeexDSP.a */; }; 28F2FAD513E37BA000034BF2 /* MKAudioOutputUserPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 28F2FAD413E37BA000034BF2 /* MKAudioOutputUserPrivate.h */; }; 28F2FAD613E37BA000034BF2 /* MKAudioOutputUserPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 28F2FAD413E37BA000034BF2 /* MKAudioOutputUserPrivate.h */; }; + BCD11DF2158F3FD600321E06 /* MKPermission.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF1158F3FD600321E06 /* MKPermission.h */; }; + BCD11DF3158F3FD600321E06 /* MKPermission.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF1158F3FD600321E06 /* MKPermission.h */; }; + BCD11DF7158F40A900321E06 /* MKAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF4158F40A900321E06 /* MKAccessControl.h */; }; + BCD11DF8158F40A900321E06 /* MKAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF4158F40A900321E06 /* MKAccessControl.h */; }; + BCD11DF9158F40A900321E06 /* MKChannelACL.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF5158F40A900321E06 /* MKChannelACL.h */; }; + BCD11DFA158F40A900321E06 /* MKChannelACL.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF5158F40A900321E06 /* MKChannelACL.h */; }; + BCD11DFB158F40A900321E06 /* MKChannelGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF6158F40A900321E06 /* MKChannelGroup.h */; }; + BCD11DFC158F40A900321E06 /* MKChannelGroup.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD11DF6158F40A900321E06 /* MKChannelGroup.h */; }; + BCD11E09158F40FA00321E06 /* MKAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD11E06158F40FA00321E06 /* MKAccessControl.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + BCD11E0A158F40FA00321E06 /* MKAccessControl.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD11E06158F40FA00321E06 /* MKAccessControl.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + BCD11E0B158F40FA00321E06 /* MKChannelACL.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD11E07158F40FA00321E06 /* MKChannelACL.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + BCD11E0C158F40FA00321E06 /* MKChannelACL.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD11E07158F40FA00321E06 /* MKChannelACL.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + BCD11E0D158F40FA00321E06 /* MKChannelGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD11E08158F40FA00321E06 /* MKChannelGroup.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + BCD11E0E158F40FA00321E06 /* MKChannelGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = BCD11E08158F40FA00321E06 /* MKChannelGroup.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -396,6 +410,13 @@ 28CC3711132EDC7300241269 /* libSpeex.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libSpeex.a; sourceTree = BUILT_PRODUCTS_DIR; }; 28CC3712132EDC7300241269 /* libSpeexDSP.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libSpeexDSP.a; sourceTree = BUILT_PRODUCTS_DIR; }; 28F2FAD413E37BA000034BF2 /* MKAudioOutputUserPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKAudioOutputUserPrivate.h; path = src/MKAudioOutputUserPrivate.h; sourceTree = SOURCE_ROOT; }; + BCD11DF1158F3FD600321E06 /* MKPermission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKPermission.h; path = src/MumbleKit/MKPermission.h; sourceTree = SOURCE_ROOT; }; + BCD11DF4158F40A900321E06 /* MKAccessControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKAccessControl.h; path = src/MumbleKit/MKAccessControl.h; sourceTree = SOURCE_ROOT; }; + BCD11DF5158F40A900321E06 /* MKChannelACL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKChannelACL.h; path = src/MumbleKit/MKChannelACL.h; sourceTree = SOURCE_ROOT; }; + BCD11DF6158F40A900321E06 /* MKChannelGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKChannelGroup.h; path = src/MumbleKit/MKChannelGroup.h; sourceTree = SOURCE_ROOT; }; + BCD11E06158F40FA00321E06 /* MKAccessControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MKAccessControl.m; path = src/MKAccessControl.m; sourceTree = SOURCE_ROOT; }; + BCD11E07158F40FA00321E06 /* MKChannelACL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MKChannelACL.m; path = src/MKChannelACL.m; sourceTree = SOURCE_ROOT; }; + BCD11E08158F40FA00321E06 /* MKChannelGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MKChannelGroup.m; path = src/MKChannelGroup.m; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -485,6 +506,7 @@ 28CC36F8132ED92500241269 /* Mumble.pb.m */, 28CC36F9132ED92500241269 /* ObjectivecDescriptor.pb.m */, 2845A781132D9C220034D631 /* CryptState.cpp */, + BCD11E06158F40FA00321E06 /* MKAccessControl.m */, 2845A782132D9C220034D631 /* MKAudio.m */, 2845A783132D9C220034D631 /* MKAudioInput.m */, 2845A784132D9C220034D631 /* MKAudioOutput.m */, @@ -493,6 +515,8 @@ 2845A786132D9C220034D631 /* MKAudioOutputUser.m */, 2845A787132D9C220034D631 /* MKCertificate.m */, 2845A788132D9C220034D631 /* MKChannel.m */, + BCD11E07158F40FA00321E06 /* MKChannelACL.m */, + BCD11E08158F40FA00321E06 /* MKChannelGroup.m */, 2845A789132D9C220034D631 /* MKConnection.m */, 2845A78A132D9C220034D631 /* MKConnectionController.m */, 2845A78B132D9C220034D631 /* MKCryptState_openssl.mm */, @@ -512,11 +536,15 @@ 2845A780132D9BF50034D631 /* Public Headers */ = { isa = PBXGroup; children = ( + BCD11DF4158F40A900321E06 /* MKAccessControl.h */, 2845A7C7132D9C520034D631 /* MKAudio.h */, 2845A7CC132D9C520034D631 /* MKCertificate.h */, 2845A7CD132D9C520034D631 /* MKChannel.h */, + BCD11DF5158F40A900321E06 /* MKChannelACL.h */, + BCD11DF6158F40A900321E06 /* MKChannelGroup.h */, 2845A7CE132D9C520034D631 /* MKConnection.h */, 2845A7CF132D9C520034D631 /* MKConnectionController.h */, + BCD11DF1158F3FD600321E06 /* MKPermission.h */, 2845A7D3132D9C520034D631 /* MKServerModel.h */, 282F6B0613624187008F555B /* MKServerPinger.h */, 2845A7D5132D9C520034D631 /* MKServices.h */, @@ -685,6 +713,10 @@ 2879526914C1BDD800567430 /* MKTextMessage.h in Headers */, 281EADA61530EA30000793AB /* MKDistinguishedNameParser.h in Headers */, 28074E91158A6E5100E0A4D0 /* MKAudioOutputSidetone.h in Headers */, + BCD11DF3158F3FD600321E06 /* MKPermission.h in Headers */, + BCD11DF8158F40A900321E06 /* MKAccessControl.h in Headers */, + BCD11DFA158F40A900321E06 /* MKChannelACL.h in Headers */, + BCD11DFC158F40A900321E06 /* MKChannelGroup.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -717,6 +749,10 @@ 2879526814C1BDD800567430 /* MKTextMessage.h in Headers */, 281EADA51530EA30000793AB /* MKDistinguishedNameParser.h in Headers */, 28074E90158A6E5100E0A4D0 /* MKAudioOutputSidetone.h in Headers */, + BCD11DF2158F3FD600321E06 /* MKPermission.h in Headers */, + BCD11DF7158F40A900321E06 /* MKAccessControl.h in Headers */, + BCD11DF9158F40A900321E06 /* MKChannelACL.h in Headers */, + BCD11DFB158F40A900321E06 /* MKChannelGroup.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -948,6 +984,9 @@ 2879526514C1BAB900567430 /* MKTextMessage.m in Sources */, 281EADA81530EA30000793AB /* MKDistinguishedNameParser.m in Sources */, 28074E93158A6E5100E0A4D0 /* MKAudioOutputSidetone.m in Sources */, + BCD11E0A158F40FA00321E06 /* MKAccessControl.m in Sources */, + BCD11E0C158F40FA00321E06 /* MKChannelACL.m in Sources */, + BCD11E0E158F40FA00321E06 /* MKChannelGroup.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -978,6 +1017,9 @@ 2879526414C1BAB900567430 /* MKTextMessage.m in Sources */, 281EADA71530EA30000793AB /* MKDistinguishedNameParser.m in Sources */, 28074E92158A6E5100E0A4D0 /* MKAudioOutputSidetone.m in Sources */, + BCD11E09158F40FA00321E06 /* MKAccessControl.m in Sources */, + BCD11E0B158F40FA00321E06 /* MKChannelACL.m in Sources */, + BCD11E0D158F40FA00321E06 /* MKChannelGroup.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/MKAccessControl.m b/src/MKAccessControl.m new file mode 100644 index 0000000..b13aaaa --- /dev/null +++ b/src/MKAccessControl.m @@ -0,0 +1,17 @@ +// Copyright 2012 The MumbleKit Developers. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#import "MKAccessControl.h" + +@implementation MKAccessControl + +@synthesize inheritACLs; +@synthesize groups; +@synthesize acls; + +- (NSString *) description { + return [NSString stringWithFormat:@"{\n\tinheritACLs: %@\n\tgroups: %@\n\tacls: %@\n}", self.inheritACLs ? @"YES" : @"NO", self.groups, self.acls]; +} + +@end diff --git a/src/MKChannelACL.m b/src/MKChannelACL.m new file mode 100644 index 0000000..4a5b1ce --- /dev/null +++ b/src/MKChannelACL.m @@ -0,0 +1,146 @@ +// Copyright 2012 The MumbleKit Developers. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#import "MKChannelACL.h" + +@implementation MKChannelACL + +@synthesize applyHere; +@synthesize applySubs; +@synthesize inherited; +@synthesize userID; +@synthesize group; +@synthesize grant; +@synthesize deny; + +- (BOOL) hasUserID { + return (self.userID > -1); +} + +- (NSString *) description { + NSMutableString *grantDescription = [[NSMutableString alloc] init]; + if (self.grant == MKPermissionAll) { + [grantDescription appendString:@"All"]; + } else if (self.grant == MKPermissionNone) { + [grantDescription appendString:@"None"]; + } else { + if ((self.grant & MKPermissionWrite) == MKPermissionWrite) { + [grantDescription appendString:@"Write | "]; + } + if ((self.grant & MKPermissionTraverse) == MKPermissionTraverse) { + [grantDescription appendString:@"Traverse | "]; + } + if ((self.grant & MKPermissionEnter) == MKPermissionEnter) { + [grantDescription appendString:@"Enter | "]; + } + if ((self.grant & MKPermissionSpeak) == MKPermissionSpeak) { + [grantDescription appendString:@"Speak | "]; + } + if ((self.grant & MKPermissionMuteDeafen) == MKPermissionMuteDeafen) { + [grantDescription appendString:@"MuteDeafen | "]; + } + if ((self.grant & MKPermissionMove) == MKPermissionMove) { + [grantDescription appendString:@"Move | "]; + } + if ((self.grant & MKPermissionMakeChannel) == MKPermissionMakeChannel) { + [grantDescription appendString:@"MakeChannel | "]; + } + if ((self.grant & MKPermissionLinkChannel) == MKPermissionLinkChannel) { + [grantDescription appendString:@"LinkChannel | "]; + } + if ((self.grant & MKPermissionWhisper) == MKPermissionWhisper) { + [grantDescription appendString:@"Whisper | "]; + } + if ((self.grant & MKPermissionTextMessage) == MKPermissionTextMessage) { + [grantDescription appendString:@"TextMessage | "]; + } + if ((self.grant & MKPermissionMakeTempChannel) == MKPermissionMakeTempChannel) { + [grantDescription appendString:@"MakeTempChannel | "]; + } + if ((self.grant & MKPermissionKick) == MKPermissionKick) { + [grantDescription appendString:@"Kick | "]; + } + if ((self.grant & MKPermissionBan) == MKPermissionBan) { + [grantDescription appendString:@"Ban | "]; + } + if ((self.grant & MKPermissionRegister) == MKPermissionRegister) { + [grantDescription appendString:@"Register | "]; + } + if ((self.grant & MKPermissionSelfRegister) == MKPermissionSelfRegister) { + [grantDescription appendString:@"SelfRegister | "]; + } + + if (grantDescription.length > 0) { + grantDescription = [NSMutableString stringWithString:[grantDescription substringToIndex:grantDescription.length-3]]; + } + } + + NSMutableString *denyDescription = [[NSMutableString alloc] init]; + if (self.deny == MKPermissionAll) { + [denyDescription appendString:@"All"]; + } else if (self.deny == MKPermissionNone) { + [denyDescription appendString:@"None"]; + } else { + if ((self.deny & MKPermissionWrite) == MKPermissionWrite) { + [denyDescription appendString:@"Write | "]; + } + if ((self.deny & MKPermissionTraverse) == MKPermissionTraverse) { + [denyDescription appendString:@"Traverse | "]; + } + if ((self.deny & MKPermissionEnter) == MKPermissionEnter) { + [denyDescription appendString:@"Enter | "]; + } + if ((self.deny & MKPermissionSpeak) == MKPermissionSpeak) { + [denyDescription appendString:@"Speak | "]; + } + if ((self.deny & MKPermissionMuteDeafen) == MKPermissionMuteDeafen) { + [denyDescription appendString:@"MuteDeafen | "]; + } + if ((self.deny & MKPermissionMove) == MKPermissionMove) { + [denyDescription appendString:@"Move | "]; + } + if ((self.deny & MKPermissionMakeChannel) == MKPermissionMakeChannel) { + [denyDescription appendString:@"MakeChannel | "]; + } + if ((self.deny & MKPermissionLinkChannel) == MKPermissionLinkChannel) { + [denyDescription appendString:@"LinkChannel | "]; + } + if ((self.deny & MKPermissionWhisper) == MKPermissionWhisper) { + [denyDescription appendString:@"Whisper | "]; + } + if ((self.deny & MKPermissionTextMessage) == MKPermissionTextMessage) { + [denyDescription appendString:@"TextMessage | "]; + } + if ((self.deny & MKPermissionMakeTempChannel) == MKPermissionMakeTempChannel) { + [denyDescription appendString:@"MakeTempChannel | "]; + } + if ((self.deny & MKPermissionKick) == MKPermissionKick) { + [denyDescription appendString:@"Kick | "]; + } + if ((self.deny & MKPermissionBan) == MKPermissionBan) { + [denyDescription appendString:@"Ban | "]; + } + if ((self.deny & MKPermissionRegister) == MKPermissionRegister) { + [denyDescription appendString:@"Register | "]; + } + if ((self.deny & MKPermissionSelfRegister) == MKPermissionSelfRegister) { + [denyDescription appendString:@"SelfRegister | "]; + } + + if (denyDescription.length > 0) { + denyDescription = [NSMutableString stringWithString:[denyDescription substringToIndex:denyDescription.length-3]]; + } + } + + return [NSString stringWithFormat:@"{applyHere: %@; applySubs: %@; inherited: %@; %@: %@; grant: %@; deny: %@}", + self.applyHere ? @"YES" : @"NO", + self.applySubs ? @"YES" : @"NO", + self.inherited ? @"YES" : @"NO", + self.hasUserID ? @"userID" : @"group", + self.hasUserID ? [NSNumber numberWithInt:self.userID] : self.group, + grantDescription, + denyDescription]; +} + +@end diff --git a/src/MKChannelGroup.m b/src/MKChannelGroup.m new file mode 100644 index 0000000..fb710c1 --- /dev/null +++ b/src/MKChannelGroup.m @@ -0,0 +1,27 @@ +// Copyright 2012 The MumbleKit Developers. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#import "MKChannelGroup.h" + +@implementation MKChannelGroup + +@synthesize name; +@synthesize inherited; +@synthesize inherit; +@synthesize inheritable; +@synthesize members; +@synthesize excludedMembers; +@synthesize inheritedMembers; + +- (NSString *) description { + return [NSString stringWithFormat:@"{name: %@; inherited: %@; inherit: %@; inheritable: %@; members: %@; excludedMembers: %@; inheritedMembers: %@}", + self.name, + self.inherited ? @"YES" : @"NO", + self.inherit ? @"YES" : @"NO", + self.inheritable ? @"YES" : @"NO", + self.members, + self.excludedMembers, + self.inheritedMembers]; +} +@end diff --git a/src/MKServerModel.m b/src/MKServerModel.m index 9ce0cb4..f113ebc 100644 --- a/src/MKServerModel.m +++ b/src/MKServerModel.m @@ -20,6 +20,9 @@ #import "MulticastDelegate.h" +#import +#import + // fixme(mkrautz): Refactor once 1.0's out the door. @interface MKAudio () - (void) setSelfMuted:(BOOL)selfMuted; @@ -399,7 +402,7 @@ - (void) connection:(MKConnection *)conn handlePermissionDeniedMessage: (MPPermi break; } case MPPermissionDenied_DenyTypeChannelName: { - [_delegate serverModelChannelFullError:self]; + [_delegate serverModelChannelNameError:self]; break; } case MPPermissionDenied_DenyTypeTextTooLong: { @@ -449,7 +452,65 @@ - (void) connection:(MKConnection *)conn handleTextMessageMessage: (MPTextMessag [_delegate serverModel:self textMessageReceived:txtMsg fromUser:sender]; } -- (void) connection:(MKConnection *)conn handleACLMessage: (MPACL *)msg { +- (void) connection:(MKConnection *)conn handleACLMessage: (MPACL *)msg { + if (! [msg hasChannelId]) { + return; + } + + MKChannel *chan = [self channelWithId:[msg channelId]]; + + MKAccessControl *acl = [[MKAccessControl alloc] init]; + acl.inheritACLs = msg.inheritAcls; + acl.acls = [NSMutableArray array]; + acl.groups = [NSMutableArray array]; + + for (MPACL_ChanACL *chanACL in msg.acls) { + MKChannelACL *channelACL = [[MKChannelACL alloc] init]; + if (chanACL.hasUserId) { + channelACL.userID = chanACL.userId; + channelACL.group = nil; + } else { + channelACL.userID = -1; + channelACL.group = chanACL.group; + } + + channelACL.applyHere = chanACL.applyHere; + channelACL.applySubs = chanACL.applySubs; + channelACL.deny = chanACL.deny; + channelACL.grant = chanACL.grant; + channelACL.inherited = chanACL.inherited; + + [acl.acls addObject:channelACL]; + [channelACL release]; + } + + + for (MPACL_ChanGroup *chanGroup in msg.groups) { + MKChannelGroup *channelGroup = [[MKChannelGroup alloc] init]; + channelGroup.name = chanGroup.name; + channelGroup.inheritable = chanGroup.inheritable; + channelGroup.inherit = chanGroup.inherit; + channelGroup.inherited = chanGroup.inherited; + + channelGroup.members = [NSMutableArray array]; + channelGroup.excludedMembers = [NSMutableArray array]; + channelGroup.inheritedMembers = [NSMutableArray array]; + + for (NSNumber *value in chanGroup.add) { + [channelGroup.members addObject:value]; + } + for (NSNumber *value in chanGroup.remove) { + [channelGroup.excludedMembers addObject:value]; + } + for (NSNumber *value in chanGroup.inheritedMembers) { + [channelGroup.inheritedMembers addObject:value]; + } + + [acl.groups addObject:channelGroup]; + [channelGroup release]; + } + + [_delegate serverModel:self didReceiveAccessControl:[acl autorelease] forChannel:chan]; } - (void) connection:(MKConnection *)conn handleQueryUsersMessage: (MPQueryUsers *)msg { @@ -860,6 +921,77 @@ - (void) joinChannel:(MKChannel *)chan { [_connection sendMessageWithType:UserStateMessage data:data]; } +// Create a channel +- (void) createChannelWithName:(NSString *)channelName parent:(MKChannel *)parent temporary:(BOOL)temp { + MPChannelState_Builder *channelState = [MPChannelState builder]; + channelState.name = channelName; + channelState.parent = parent.channelId; + channelState.temporary = temp; + + NSData *data = [[channelState build] data]; + [_connection sendMessageWithType:ChannelStateMessage data:data]; +} + +// Request the access control for a channel +- (void) requestAccessControlForChannel:(MKChannel *)channel { + MPACL_Builder *mpacl = [MPACL builder]; + mpacl.channelId = channel.channelId; + mpacl.query = YES; + + NSData *data = [[mpacl build] data]; + [_connection sendMessageWithType:ACLMessage data:data]; +} + +// Set the access control for a channel +- (void) setAccessControl:(MKAccessControl *)accessControl forChannel:(MKChannel *)channel { + MPACL_Builder *mpacl = [MPACL builder]; + mpacl.channelId = channel.channelId; + mpacl.query = YES; + mpacl.inheritAcls = accessControl.inheritACLs; + + NSMutableArray *aclsArray = [NSMutableArray array]; + for (MKChannelACL *channelACL in accessControl.acls) { + if (channelACL.inherited) { + continue; + } + + MPACL_ChanACL_Builder *chanACL = [MPACL_ChanACL builder]; + chanACL.applyHere = channelACL.applyHere; + chanACL.applySubs = channelACL.applySubs; + chanACL.deny = channelACL.deny; + chanACL.grant = channelACL.grant; + + if (channelACL.hasUserID) { + chanACL.userId = channelACL.userID; + } else { + chanACL.group = channelACL.group; + } + + [aclsArray addObject:[chanACL build]]; + } + [mpacl setAclsArray:aclsArray]; + + NSMutableArray *groupsArray = [NSMutableArray array]; + for (MKChannelGroup *channelGroup in accessControl.groups) { + if (channelGroup.inherited) { + continue; + } + + MPACL_ChanGroup_Builder *chanGroup = [MPACL_ChanGroup builder]; + chanGroup.name = channelGroup.name; + chanGroup.inherit = channelGroup.inherit; + chanGroup.inheritable = channelGroup.inheritable; + chanGroup.addArray = channelGroup.members; + chanGroup.removeArray = channelGroup.excludedMembers; + [groupsArray addObject:[chanGroup build]]; + } + [mpacl setGroupsArray:groupsArray]; + + NSData *data = [[mpacl build] data]; + + [_connection sendMessageWithType:ACLMessage data:data]; +} + #pragma mark - #pragma mark Text message operations diff --git a/src/MumbleKit/MKAccessControl.h b/src/MumbleKit/MKAccessControl.h new file mode 100644 index 0000000..3a37858 --- /dev/null +++ b/src/MumbleKit/MKAccessControl.h @@ -0,0 +1,11 @@ +// Copyright 2012 The MumbleKit Developers. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +@interface MKAccessControl : NSObject + +@property (nonatomic) BOOL inheritACLs; +@property (nonatomic, strong) NSMutableArray * groups; +@property (nonatomic, strong) NSMutableArray * acls; + +@end diff --git a/src/MumbleKit/MKChannelACL.h b/src/MumbleKit/MKChannelACL.h new file mode 100644 index 0000000..38ddca3 --- /dev/null +++ b/src/MumbleKit/MKChannelACL.h @@ -0,0 +1,18 @@ +// Copyright 2012 The MumbleKit Developers. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#import + +@interface MKChannelACL : NSObject + +@property (nonatomic) BOOL applyHere; +@property (nonatomic) BOOL applySubs; +@property (nonatomic) BOOL inherited; +@property (nonatomic) NSInteger userID; +@property (nonatomic, strong) NSString * group; +@property (nonatomic) MKPermission grant; +@property (nonatomic) MKPermission deny; +@property (nonatomic, readonly) BOOL hasUserID; + +@end diff --git a/src/MumbleKit/MKChannelGroup.h b/src/MumbleKit/MKChannelGroup.h new file mode 100644 index 0000000..d4dd008 --- /dev/null +++ b/src/MumbleKit/MKChannelGroup.h @@ -0,0 +1,15 @@ +// Copyright 2012 The MumbleKit Developers. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +@interface MKChannelGroup : NSObject + +@property (nonatomic, strong) NSString * name; +@property (nonatomic) BOOL inherited; +@property (nonatomic) BOOL inherit; +@property (nonatomic) BOOL inheritable; +@property (nonatomic, strong) NSMutableArray * members; +@property (nonatomic, strong) NSMutableArray * excludedMembers; +@property (nonatomic, strong) NSMutableArray * inheritedMembers; + +@end diff --git a/src/MumbleKit/MKPermission.h b/src/MumbleKit/MKPermission.h new file mode 100644 index 0000000..41fd39d --- /dev/null +++ b/src/MumbleKit/MKPermission.h @@ -0,0 +1,24 @@ +// Copyright 2010-2012 The MumbleKit Developers. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +typedef enum { + MKPermissionNone = 0x00000, + MKPermissionWrite = 0x00001, + MKPermissionTraverse = 0x00002, + MKPermissionEnter = 0x00004, + MKPermissionSpeak = 0x00008, + MKPermissionMuteDeafen = 0x00010, + MKPermissionMove = 0x00020, + MKPermissionMakeChannel = 0x00040, + MKPermissionLinkChannel = 0x00080, + MKPermissionWhisper = 0x00100, + MKPermissionTextMessage = 0x00200, + MKPermissionMakeTempChannel = 0x00400, + MKPermissionKick = 0x10000, + MKPermissionBan = 0x20000, + MKPermissionRegister = 0x40000, + MKPermissionSelfRegister = 0x80000, + MKPermissionAll = 0xf07ff, +} MKPermission; + diff --git a/src/MumbleKit/MKServerModel.h b/src/MumbleKit/MKServerModel.h index d06c366..edc1261 100644 --- a/src/MumbleKit/MKServerModel.h +++ b/src/MumbleKit/MKServerModel.h @@ -6,29 +6,12 @@ #import #import #import +#import +#import @class MulticastDelegate; @class MKServerModel; -typedef enum { - MKPermissionNone = 0x00000, - MKPermissionWrite = 0x00001, - MKPermissionTraverse = 0x00002, - MKPermissionEnter = 0x00004, - MKPermissionSpeak = 0x00008, - MKPermissionMuteDeafen = 0x00010, - MKPermissionMove = 0x00020, - MKPermissionMakeChannel = 0x00040, - MKPermissionLinkChannel = 0x00080, - MKPermissionWhisper = 0x00100, - MKPermissionTextMessage = 0x00200, - MKPermissionMakeTempChannel = 0x00400, - MKPermissionKick = 0x10000, - MKPermissionBan = 0x20000, - MKPermissionRegister = 0x40000, - MKPermissionSelfRegister = 0x80000, -} MKPermission; - /** * MKServerModelDelegate is the delegate of MKServerModel. * It is called to notify any registered delegates of events happening on the server, or @@ -524,6 +507,14 @@ typedef enum { */ - (void) serverModelChannelFullError:(MKServerModel *)model; +/** + * Called when a channel create operation failed because the channel + * name was invalid. + * + * @param model The MKServerModel in which this error occurred. + */ +- (void) serverModelChannelNameError:(MKServerModel *)model; + /** * Called when a simple 'Permission denied.' message is sufficient to show to the user. * Can include a reason. This kind of permission error is also used as a fallback, if @@ -534,6 +525,16 @@ typedef enum { * @param reason The reason for the error. May be nil if no reason was given. */ - (void) serverModel:(MKServerModel *)model permissionDeniedForReason:(NSString *)reason; + +/** + * Called after an access control request + * + * @param model The MKServerModel in which this event originated. + * @param accessControl The requested access control. + * @param channel The channel to which access control refers. + */ +- (void) serverModel:(MKServerModel *)model didReceiveAccessControl:(MKAccessControl *)accessControl forChannel:(MKChannel *)channel; + @end /** @@ -642,6 +643,31 @@ typedef enum { */ - (void) joinChannel:(MKChannel *)channel; +/** + * Create a new channel in the server the underlying MKConnection is currently + * connected to. + * + * @param channelName The name of the channel to create. + * @param parent The MKChannel that must contain the newly created one. + * @param temp Specify if the channel is temporary or not. + */ +- (void) createChannelWithName:(NSString *)channelName parent:(MKChannel *)parent temporary:(BOOL)temp; + +/** + * Ask the underlying connection to receive the access control for the given channel. + * + * @param channel The channel for which you are requesting the access control. + */ +- (void) requestAccessControlForChannel:(MKChannel *)channel; + +/** + * Set access control for a channel. + * + * @param acl The access control you want to set. + * @param channel The channel for which you are setting the access control. + */ +- (void) setAccessControl:(MKAccessControl *)accessControl forChannel:(MKChannel *)channel; + ///------------------------------ /// @name Text message operations ///------------------------------