From 0caba5a1ae52df804776fb2406004968000bd33c Mon Sep 17 00:00:00 2001 From: Michael Ziegler Date: Fri, 18 Dec 2009 13:44:39 +0100 Subject: [PATCH] create ChannelInfo objects like ice does for dbus as well, prevent Ice errors from being hidden by an IndexError --- pyweb/mumble/MumbleCtlDbus.py | 15 +++++++- pyweb/mumble/MumbleCtlIce.py | 65 ++++++++++++++++++++++++----------- pyweb/mumble/mmobjects.py | 25 ++++++++++---- pyweb/mumble/models.py | 24 ++++++------- pyweb/mumble/utils.py | 30 ++++++++++++++++ 5 files changed, 120 insertions(+), 39 deletions(-) create mode 100644 pyweb/mumble/utils.py diff --git a/pyweb/mumble/MumbleCtlDbus.py b/pyweb/mumble/MumbleCtlDbus.py index d0accf0..cb442ea 100644 --- a/pyweb/mumble/MumbleCtlDbus.py +++ b/pyweb/mumble/MumbleCtlDbus.py @@ -20,6 +20,7 @@ from struct import pack, unpack from zlib import compress, decompress from mctl import MumbleCtlBase +from utils import ObjectInfo import dbus from dbus.exceptions import DBusException @@ -92,7 +93,19 @@ class MumbleCtlDbus_118(MumbleCtlBase): self._getDbusServerObject(srvid).unregisterPlayer(dbus.Int32( mumbleid )) def getChannels(self, srvid): - return MumbleCtlDbus_118.convertDbusTypeToNative(self._getDbusServerObject(srvid).getChannels()) + chans = MumbleCtlDbus_118.convertDbusTypeToNative(self._getDbusServerObject(srvid).getChannels()) + + ret = {}; + + for channel in chans: + ret[ channel[0] ] = ObjectInfo( + id = channel[0], + name = channel[1], + parent = channel[2], + links = channel[3], + ); + + return ret; def getPlayers(self, srvid): return MumbleCtlDbus_118.convertDbusTypeToNative(self._getDbusServerObject(srvid).getPlayers()) diff --git a/pyweb/mumble/MumbleCtlIce.py b/pyweb/mumble/MumbleCtlIce.py index 6f97bce..c467c95 100644 --- a/pyweb/mumble/MumbleCtlIce.py +++ b/pyweb/mumble/MumbleCtlIce.py @@ -27,6 +27,17 @@ from mctl import MumbleCtlBase import Ice + +def protectDjangoErrPage( func ): + def protection_wrapper( *args, **kwargs ): + try: + return func( *args, **kwargs ); + except Ice.Exception, e: + raise e; + + return protection_wrapper; + +@protectDjangoErrPage def MumbleCtlIce( connstring ): version = settings.SLICE_VERSION; @@ -54,8 +65,6 @@ def MumbleCtlIce( connstring ): return MumbleCtlIce_118( connstring, meta ); elif murmurversion[0] == 1 and murmurversion[1] == 2 and murmurversion[2] == 0: return MumbleCtlIce_120( connstring, meta ); - - @@ -66,24 +75,29 @@ class MumbleCtlIce_118(MumbleCtlBase): self.proxy = connstring; self.meta = meta; + @protectDjangoErrPage def _getIceServerObject(self, srvid): return self.meta.getServer(srvid); + @protectDjangoErrPage def getBootedServers(self): ret = [] for x in self.meta.getBootedServers(): ret.append(x.id()) return ret + @protectDjangoErrPage def getVersion( self ): return self.meta.getVersion(); + @protectDjangoErrPage def getAllServers(self): ret = [] for x in self.meta.getAllServers(): ret.append(x.id()) return ret + @protectDjangoErrPage def getRegisteredPlayers(self, srvid, filter = ''): users = self._getIceServerObject(srvid).getRegisteredPlayers( filter.encode( "UTF-8" ) ) ret = [] @@ -93,16 +107,11 @@ class MumbleCtlIce_118(MumbleCtlBase): return ret + @protectDjangoErrPage def getChannels(self, srvid): - chans = self._getIceServerObject(srvid).getChannels() - ret = [] - - for x in chans: - chan = chans[x] - ret.append([chan.id, self.setUnicodeFlag(chan.name), chan.parent, chan.links]) - - return ret + return self._getIceServerObject(srvid).getChannels(); + @protectDjangoErrPage def getPlayers(self, srvid): users = self._getIceServerObject(srvid).getPlayers() ret = [] @@ -113,43 +122,55 @@ class MumbleCtlIce_118(MumbleCtlBase): return ret + @protectDjangoErrPage def getDefaultConf(self): return self.setUnicodeFlag(self.meta.getDefaultConf()) + @protectDjangoErrPage def getAllConf(self, srvid): return self.setUnicodeFlag(self._getIceServerObject(srvid).getAllConf()) + @protectDjangoErrPage def newServer(self): return self.meta.newServer().id() + @protectDjangoErrPage def isBooted( self, srvid ): return bool( self._getIceServerObject(srvid).isRunning() ); + @protectDjangoErrPage def start( self, srvid ): self._getIceServerObject(srvid).start(); + @protectDjangoErrPage def stop( self, srvid ): self._getIceServerObject(srvid).stop(); + @protectDjangoErrPage def deleteServer( self, srvid ): if self._getIceServerObject(srvid).isRunning(): self._getIceServerObject(srvid).stop() self._getIceServerObject(srvid).delete() + @protectDjangoErrPage def setSuperUserPassword(self, srvid, value): self._getIceServerObject(srvid).setSuperuserPassword( value.encode( "UTF-8" ) ) + @protectDjangoErrPage def setConf(self, srvid, key, value): self._getIceServerObject(srvid).setConf( key, value.encode( "UTF-8" ) ) + @protectDjangoErrPage def registerPlayer(self, srvid, name, email, password): mumbleid = self._getIceServerObject(srvid).registerPlayer( name.encode( "UTF-8" ) ) self.setRegistration( srvid, mumbleid, name, email, password ); return mumbleid; + @protectDjangoErrPage def unregisterPlayer(self, srvid, mumbleid): self._getIceServerObject(srvid).unregisterPlayer(mumbleid) + @protectDjangoErrPage def getRegistration(self, srvid, mumbleid): user = self._getIceServerObject(srvid).getRegistration(mumbleid) return { @@ -157,6 +178,7 @@ class MumbleCtlIce_118(MumbleCtlBase): 'email': user.email, }; + @protectDjangoErrPage def setRegistration(self, srvid, mumbleid, name, email, password): user = self._getIceServerObject(srvid).getRegistration(mumbleid) user.name = name.encode( "UTF-8" ) @@ -165,6 +187,7 @@ class MumbleCtlIce_118(MumbleCtlBase): # update*r*egistration r is lowercase... return self._getIceServerObject(srvid).updateregistration(user) + @protectDjangoErrPage def getACL(self, srvid, channelid): import Murmur acls = self._getIceServerObject(srvid).getACL(channelid) @@ -184,6 +207,7 @@ class MumbleCtlIce_118(MumbleCtlBase): return ret + @protectDjangoErrPage def setACL(self, srvid, acl): import Murmur @@ -214,6 +238,7 @@ class MumbleCtlIce_118(MumbleCtlBase): self._getIceServerObject(srvid).setACL( acl.channelId, newacls, newgroups, acl.inherit ); + @protectDjangoErrPage def getTexture(self, srvid, mumbleid): texture = self._getIceServerObject(srvid).getTexture(mumbleid) if len(texture) == 0: @@ -233,6 +258,7 @@ class MumbleCtlIce_118(MumbleCtlBase): # return an 600x60 RGBA image object created from the data return Image.fromstring( "RGBA", ( 600, 60 ), imgdata ); + @protectDjangoErrPage def setTexture(self, srvid, mumbleid, infile): # open image, convert to RGBA, and resize to 600x60 img = Image.open( infile ).convert( "RGBA" ).transform( ( 600, 60 ), Image.EXTENT, ( 0, 0, 600, 60 ) ); @@ -250,6 +276,7 @@ class MumbleCtlIce_118(MumbleCtlBase): # finally call murmur and set the texture self._getIceServerObject(srvid).setTexture(mumbleid, texture) + @protectDjangoErrPage def verifyPassword(self, srvid, username, password): return self._getIceServerObject(srvid).verifyPassword(username, password); @@ -269,6 +296,7 @@ class MumbleCtlIce_118(MumbleCtlBase): class MumbleCtlIce_120(MumbleCtlIce_118): + @protectDjangoErrPage def getRegisteredPlayers(self, srvid, filter = ''): users = self._getIceServerObject( srvid ).getRegisteredUsers( filter.encode( "UTF-8" ) ) ret = [] @@ -278,16 +306,7 @@ class MumbleCtlIce_120(MumbleCtlIce_118): return ret - def getChannels(self, srvid): - chans = self._getIceServerObject(srvid).getChannels() - ret = [] - - for x in chans: - chan = chans[x] - ret.append([chan.id, self.setUnicodeFlag(chan.name), chan.parent, chan.links, chan.description]) - - return ret - + @protectDjangoErrPage def getPlayers(self, srvid): serv = self._getIceServerObject(srvid); users = serv.getUsers() @@ -299,6 +318,7 @@ class MumbleCtlIce_120(MumbleCtlIce_118): return ret + @protectDjangoErrPage def registerPlayer(self, srvid, name, email, password): # To get the real values of these ENUM entries, try # Murmur.UserInfo.UserX.value @@ -310,9 +330,11 @@ class MumbleCtlIce_120(MumbleCtlIce_118): }; return self._getIceServerObject(srvid).registerUser( user ); + @protectDjangoErrPage def unregisterPlayer(self, srvid, mumbleid): self._getIceServerObject(srvid).unregisterUser(mumbleid) + @protectDjangoErrPage def getRegistration(self, srvid, mumbleid): from Murmur import UserInfo reg = self._getIceServerObject( srvid ).getRegistration( mumbleid ) @@ -327,6 +349,7 @@ class MumbleCtlIce_120(MumbleCtlIce_118): user['hash'] = reg[UserInfo.UserHash]; return user; + @protectDjangoErrPage def setRegistration(self, srvid, mumbleid, name, email, password): from Murmur import UserInfo user = { @@ -336,6 +359,7 @@ class MumbleCtlIce_120(MumbleCtlIce_118): }; return self._getIceServerObject( srvid ).updateRegistration( mumbleid, user ) + @protectDjangoErrPage def getACL(self, srvid, channelid): import Murmur acls = self._getIceServerObject(srvid).getACL(channelid) @@ -355,6 +379,7 @@ class MumbleCtlIce_120(MumbleCtlIce_118): return ret + @protectDjangoErrPage def setACL(self, srvid, acl): import Murmur diff --git a/pyweb/mumble/mmobjects.py b/pyweb/mumble/mmobjects.py index db58028..eb90826 100644 --- a/pyweb/mumble/mmobjects.py +++ b/pyweb/mumble/mmobjects.py @@ -44,16 +44,27 @@ class mmChannel( object ): self.subchans = list(); self.linked = list(); - self.chanid = channelObj[0]; - self.name = channelObj[1]; - parent = channelObj[2]; - self.linkedIDs = channelObj[3]; + self.chanid = channelObj.id; + self.name = channelObj.name; + parent = channelObj.parent; + self.linkedIDs = channelObj.links; - if len( channelObj ) == 5: - self.description = channelObj[4]; + if hasattr( channelObj, "description" ): + self.description = channelObj.description; else: self.description = ""; + if hasattr( channelObj, "temporary" ): + self.temporary = channelObj.temporary; + else: + self.temporary = False; + + if hasattr( channelObj, "position" ): + self.position = channelObj.position; + else: + # None would be better imho, but Murmur reports 0 for unknown too. + self.position = 0; + self.parent = parentChan; if self.parent is not None: self.parent.subchans.append( self ); @@ -151,6 +162,8 @@ class mmChannel( object ): return { 'chanid': self.chanid, 'description': self.description, + 'temporary': self.temporary, + 'position': self.position, 'linked': [], 'linkedIDs': [], 'name': self.name, diff --git a/pyweb/mumble/models.py b/pyweb/mumble/models.py index 610c1d7..691235c 100644 --- a/pyweb/mumble/models.py +++ b/pyweb/mumble/models.py @@ -297,7 +297,7 @@ class Mumble( models.Model ): """ if self._channels is None: self._channels = {}; - chanlist = self.ctl.getChannels(self.srvid); + chanlist = self.ctl.getChannels(self.srvid).values(); links = {}; # sometimes, ICE seems to return the Channel list in a weird order. @@ -308,32 +308,32 @@ class Mumble( models.Model ): itercount += 1; for theChan in chanlist: # Channels - Fields: 0 = ID, 1 = Name, 2 = Parent-ID, 3 = Links - if( theChan[2] == -1 ): + if( theChan.parent == -1 ): # No parent - self._channels[theChan[0]] = mmChannel( self, theChan ); - elif theChan[2] in self.channels: + self._channels[theChan.id] = mmChannel( self, theChan ); + elif theChan.parent in self.channels: # parent already known - self._channels[theChan[0]] = mmChannel( self, theChan, self.channels[theChan[2]] ); + self._channels[theChan.id] = mmChannel( self, theChan, self.channels[theChan.parent] ); else: continue; chanlist.remove( theChan ); - self._channels[theChan[0]].serverId = self.id; + self._channels[theChan.id].serverId = self.id; # process links - if the linked channels are known, link; else save their ids to link later - for linked in theChan[3]: + for linked in theChan.links: if linked in self._channels: - self._channels[theChan[0]].linked.append( self._channels[linked] ); + self._channels[theChan.id].linked.append( self._channels[linked] ); else: if linked not in links: links[linked] = list(); - links[linked].append( self._channels[theChan[0]] ); + links[linked].append( self._channels[theChan.id] ); # check if earlier round trips saved channel ids to be linked to the current channel - if theChan[0] in links: - for targetChan in links[theChan[0]]: - targetChan.linked.append( self._channels[theChan[0]] ); + if theChan.id in links: + for targetChan in links[theChan.id]: + targetChan.linked.append( self._channels[theChan.id] ); self._channels[0].name = self.name; diff --git a/pyweb/mumble/utils.py b/pyweb/mumble/utils.py new file mode 100644 index 0000000..19a0b8f --- /dev/null +++ b/pyweb/mumble/utils.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +""" + * Copyright (C) 2009, Michael "Svedrin" Ziegler + * + * Mumble-Django 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 of the License, or + * (at your option) any later version. + * + * This package 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. +""" + +class ObjectInfo( object ): + """ Wraps arbitrary information to be easily accessed. """ + + def __init__( self, **kwargs ): + self.__dict__ = kwargs; + + def __str__( self ): + return unicode( self ); + + def __repr__( self ): + return unicode( self ); + + def __unicode__( self ): + return unicode( self.__dict__ );