Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKissaki <kissaki@gmx.de>2013-01-14 00:02:55 +0400
committerKissaki <kissaki@gmx.de>2013-06-04 23:59:54 +0400
commit2c490d71261ecd0dcfcb07735bc3289717628b93 (patch)
treea91468ffd842abf84f5822a20af7ad2ac849c220 /scripts/server
parent15370fb50475e60ad713b20bb90781b20539109e (diff)
categorize scripts (move example scripts for serverside into subfolders)
Diffstat (limited to 'scripts/server')
-rw-r--r--scripts/server/dbus/ListUsers.cs77
-rw-r--r--scripts/server/dbus/dbusauth.pl294
-rw-r--r--scripts/server/dbus/murmur.pl286
-rw-r--r--scripts/server/dbus/weblist.pl148
-rw-r--r--scripts/server/ice/addban.php50
-rw-r--r--scripts/server/ice/glacier/config3
-rw-r--r--scripts/server/ice/glacier/glacier.php45
-rw-r--r--scripts/server/ice/glacier/passwords3
-rw-r--r--scripts/server/ice/icedemo.php209
-rw-r--r--scripts/server/ice/idle.php81
-rw-r--r--scripts/server/ice/mumble-auth.py274
-rw-r--r--scripts/server/ice/rubytest.rb58
-rw-r--r--scripts/server/ice/simpleregister.php76
-rw-r--r--scripts/server/ice/testauth.py119
-rw-r--r--scripts/server/ice/testcallback.py117
-rw-r--r--scripts/server/ice/testdynamic.py29
-rw-r--r--scripts/server/ice/weblist.php60
17 files changed, 1929 insertions, 0 deletions
diff --git a/scripts/server/dbus/ListUsers.cs b/scripts/server/dbus/ListUsers.cs
new file mode 100644
index 000000000..cc6c8fa48
--- /dev/null
+++ b/scripts/server/dbus/ListUsers.cs
@@ -0,0 +1,77 @@
+/*
+This shows how to list connected users in C#. This depends on the NDesk-DBus
+package, which can be found at http://www.ndesk.org/DBusSharp
+
+Note that DBusSharp requires you to define the interface of the object you
+are connecting to at compile time. As such, you loose the advantages of DBus
+Introspection, but it's a bit faster (and type safe).
+This example only includes a very small subset of the interface definition.
+
+To compile this with Mono, type:
+gmcs -pkg:ndesk-dbus-1.0 ListUsers.cs
+
+To compile this with the Microsoft compiler, type:
+csc -r:NDesk.DBus.dll ListUsers.cs
+*/
+
+using System;
+using NDesk.DBus;
+using org.freedesktop.DBus;
+
+public class ListUsers
+{
+ public static void Main (string[] args)
+ {
+ Connection bus;
+ if (args.Length == 0) {
+ bus = Bus.Session;
+ } else {
+ if (args[0] == "--session")
+ bus = Bus.Session;
+ else if (args[0] == "--system")
+ bus = Bus.System;
+ else
+ bus = Connection.Open (args[0]);
+ }
+
+ Meta m = bus.GetObject<Meta>("net.sourceforge.mumble.murmur", new ObjectPath("/"));
+ int [] servers = m.getBootedServers();
+
+ foreach(int id in servers) {
+ string path="/"+id;
+ Console.WriteLine("Users on server #{0}, path {1}",id,path);
+ Server s = bus.GetObject<Server>("net.sourceforge.mumble.murmur", new ObjectPath(path));
+ PlayerInfoExtended [] players = s.getPlayers();
+ foreach(PlayerInfoExtended pi in players) {
+ Console.WriteLine(" {0} ({1})",pi.name,pi.session);
+ }
+ }
+ }
+}
+
+[Interface ("net.sourceforge.mumble.Meta")]
+public interface Meta : Introspectable
+{
+ int [] getBootedServers();
+}
+
+[Interface ("net.sourceforge.mumble.Murmur")]
+public interface Server : Introspectable
+{
+ PlayerInfoExtended [] getPlayers();
+}
+
+public struct PlayerInfoExtended
+{
+ public uint session;
+ public bool mute;
+ public bool deaf;
+ public bool suppressed;
+ public bool selfMute;
+ public bool selfDeaf;
+ public int channel;
+ public int id;
+ public string name;
+ public int onlinesecs;
+ public int bytespersec;
+}
diff --git a/scripts/server/dbus/dbusauth.pl b/scripts/server/dbus/dbusauth.pl
new file mode 100644
index 000000000..2a3ac7007
--- /dev/null
+++ b/scripts/server/dbus/dbusauth.pl
@@ -0,0 +1,294 @@
+#! /usr/bin/perl
+
+# This is a small example script of how to set up murmur to authenticate through
+# phpBB3. To use it, you'll have to have started murmur with DBus, and use the
+# same session for this script.
+#
+
+use warnings;
+use strict;
+
+# Replace these with whatever is correct for you
+our $dbname="phpbb3";
+our $dbuser="phpbb3";
+our $dbpass="uhduqw1237a";
+our $dbprefix="phpbb_";
+our $dbhost="localhost";
+
+# Assign user id as phpbb3 user_id plus this, to avoid clashing
+# with local murmur users. If you're going to use ONLY external
+# authentication, you can set this to 1, but there's no real point.
+# Note that Mumble ignores values above 1000000000 when allocating
+# player IDs on its own, so you probably want to leave this alone.
+our $id_offset = 1000000000;
+
+# Path to phpBB user avatars. If you want to disable avatar support, set
+# this blank. This can be either a directory path or a full URL.
+
+our $avatar_path = "http://xeno.stud.hive.no/phpBB3/download.php?avatar=";
+
+#
+# No user servicable parts below this point.
+#
+
+use DBI;
+use Net::DBus;
+use Data::Dumper;
+use Net::DBus::Reactor;
+use LWP::UserAgent;
+use Carp;
+
+our %texturecache;
+
+our @dbhparams=("dbi:mysql:dbname=${dbname};host=${dbhost}", $dbuser, $dbpass);
+our $agent=new LWP::UserAgent;
+$agent->timeout(5);
+
+our ($bus, $service);
+
+our $r = Net::DBus::Reactor->main;
+eval {
+ $bus = Net::DBus->system();
+ $service = $bus->get_service("net.sourceforge.mumble.murmur");
+};
+
+if (! $service) {
+ eval {
+ $bus = Net::DBus->session();
+ $service = $bus->get_service("net.sourceforge.mumble.murmur");
+ };
+}
+
+die "Murmur service not found" if (! $service);
+
+my $dbh=DBI->connect_cached(@dbhparams);
+if (! $dbh) {
+ die $DBI::errstr;
+}
+
+our $object = $service->get_object("/1");
+
+our $rservice = $bus->export_service("net.sourceforge.mumble.phpbb");
+our $robject = Mumble::Auth->new($rservice);
+
+
+package Mumble::Auth;
+
+use Data::Dumper;
+use Image::Magick;
+use Digest::MD5 qw(md5);
+use Net::DBus::Exporter qw(net.sourceforge.mumble.auther);
+use base qw(Net::DBus::Object);
+dbus_method("authenticate", ["string","string"], ["int32","string",["array","string"]]);
+dbus_method("getUserName", ["int32"], ["string"]);
+dbus_method("getUserId", ["string"], ["int32"]);
+dbus_method("getUserTexture", ["int32"], [["array", "byte"]]);
+
+sub new {
+ my $class = shift;
+ my $service = shift;
+ my $self = $class->SUPER::new($service, "/authority");
+ bless $self, $class;
+ return $self;
+}
+
+sub hash {
+ my $self = shift;
+ my $pw = shift;
+ my $hash = shift;
+ my $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+ my @itoa64 = split(//,$itoa64);
+ my $count_log2 = index($itoa64, substr($hash,3,1));
+ my $count = 1 << $count_log2;
+ my $salt = substr($hash, 4, 8);
+
+ my $nhash = $salt;
+
+ do {
+ $nhash = md5($nhash . $pw);
+ } while ($count--);
+
+ my $output = substr($hash, 0, 12);
+
+ my $i = 0;
+ my @input = split(//,$nhash);
+ while ($i < 16) {
+ my $value;
+ $value = ord($input[$i++]);
+ $output .= $itoa64[$value & 0x3f];
+ if ($i < 16) {
+ $value |= ord($input[$i]) << 8;
+ }
+ $output .= $itoa64[($value >> 6) & 0x3f];
+ last if ($i++ >= 16);
+
+ if ($i < 16) {
+ $value |= ord($input[$i]) << 16;
+ }
+ $output .= $itoa64[($value >> 12) & 0x3f];
+
+ last if ($i++ >= 16);
+ $output .= $itoa64[($value >> 18) & 0x3f];
+ };
+
+ return $output;
+}
+
+# Possible responses are:
+# >0 ID of user
+# 0 SuperUser
+# -1 Wrong password
+# -2 Unknown user -- fall back to builtin database
+
+sub authenticate {
+ my $self = shift;
+ my $uname = shift;
+ my $pw = shift;
+
+ my $dbh=DBI->connect_cached(@dbhparams);
+ if (! $dbh) {
+ carp $DBI::errstr;
+ return -2,'',undef;
+ }
+ $dbh->do("SET names utf8");
+ my $sth=$dbh->prepare("SELECT user_id, user_password, user_type, username FROM ${dbprefix}users WHERE LOWER(username) = LOWER(?)");
+ $sth->execute($uname);
+ if ((my $r=$sth->fetchrow_hashref())) {
+ if ($$r{'user_password'} ne $self->hash($pw,$$r{'user_password'})) {
+ print "Wrong password for $uname\n";
+ return -1,'',undef;
+ }
+ if (($$r{'user_type'} != 0) && ($$r{'user_type'} != 3)) {
+ return -1,'',undef;
+ }
+ my $id = $$r{'user_id'} + $id_offset;
+ my $name = $$r{'username'};
+ $sth->finish();
+
+ my @groups;
+ $sth=$dbh->prepare("SELECT group_name FROM ${dbprefix}user_group LEFT JOIN ${dbprefix}groups USING (group_id) WHERE user_id = ?");
+ $sth->execute($$r{'user_id'});
+ while ((my $g=$sth->fetchrow_hashref())) {
+ push @groups, lc $$g{'group_name'};
+ }
+ #my $response = $object->setTemporaryGroups(0, $id, \@groups);
+ #Dumper($response);
+ print "Authenticated $uname as ID $id with groups ".join(" ",@groups)."\n";
+ return $id,$name,\@groups;
+ } else {
+ print "Unknown user $uname\n";
+ return -2,'',undef;
+ }
+}
+
+# Possible responses are:
+# string Name of user
+# empty Unknown user
+# undef Fall back to builting database
+
+sub getUserName {
+ my $self = shift;
+ my $id = shift;
+
+ my $dbh=DBI->connect_cached(@dbhparams);
+ if (! $dbh) {
+ carp $DBI::errstr;
+ return undef;
+ }
+ $dbh->do("SET names utf8");
+ my $sth=$dbh->prepare("SELECT username FROM ${dbprefix}users WHERE user_id = ?");
+ $sth->execute($id - $id_offset);
+ if ((my $r=$sth->fetchrow_hashref())) {
+ print "UID $id :: " .$$r{'username'}."\n";
+ return $$r{'username'};
+ }
+ print "No match for id $id\n";
+ return undef;
+}
+
+# Same response as authenticate
+
+sub getUserId {
+ my $self = shift;
+ my $name = shift;
+
+ my $dbh=DBI->connect_cached(@dbhparams);
+ if (! $dbh) {
+ carp $DBI::errstr;
+ return -2;
+ }
+ $dbh->do("SET names utf8");
+ my $sth=$dbh->prepare("SELECT user_id FROM ${dbprefix}users WHERE username = ?");
+ $sth->execute($name);
+ if ((my $r=$sth->fetchrow_hashref())) {
+ return $$r{'user_id'} + $id_offset;
+ }
+ return -2;
+}
+
+# Grab a user texture.
+
+sub getUserTexture {
+ my $self = shift;
+ my $uid = shift;
+
+ my @a;
+
+ my $dbh=DBI->connect_cached(@dbhparams);
+ if (! $dbh) {
+ carp $DBI::errstr;
+ return undef;
+ }
+ $dbh->do("SET names utf8");
+ my $sth=$dbh->prepare("SELECT user_avatar, user_avatar_type FROM ${dbprefix}users WHERE user_id = ?");
+ $sth->execute($uid - $id_offset);
+ if ((my $r=$sth->fetchrow_hashref())) {
+ my $file = $$r{'user_avatar'};
+ my $type = $$r{'user_avatar_type'};
+ if (($type != 1) && ($type != 2)) {
+ print "Request for texture $uid :: not uploaded texture ($type)\n";
+ return \@a;
+ }
+ if (exists $texturecache{$file}) {
+ return $texturecache{$file};
+ }
+
+ my $url = (($type == 1) ? $avatar_path : '') . $file;
+ my $response = $agent->get($url);
+ if (! $response->is_success) {
+ print "Request for texture $uid :: Fetch $url failed: ". $response->status_line . "\n";
+ } else {
+ my $image = new Image::Magick();
+ my $r = $image->BlobToImage($response->content);
+ if ($r) {
+ print "Request for texture $uid :: Image $url load failed: $r\n";
+ } else {
+ $image->Extent(x => 0, y => 0, width => 600, height => 60);
+ my $out=$image->ImageToBlob(magick => 'rgba', depth => 8);
+ if (length($out) != (600*60*4)) {
+ print "Request for texture $uid :: Failed resize\n";
+ } else {
+ @a = unpack("C*", $out);
+ for(my $i=0;$i<600*60;$i++) {
+ my $red=$a[$i*4];
+ my $blue=$a[$i*4+2];
+ $a[$i*4]=$blue;
+ $a[$i*4+2]=$red;
+ }
+ print "Request for texture $uid :: $url :: Success\n";
+ }
+ }
+ }
+ $texturecache{$file} = \@a;
+ return $texturecache{$file};
+ }
+ return undef;
+}
+
+
+package main;
+
+my $response = $object->setAuthenticator("/authority", 0);
+
+print "Entering main DBus loop...\n";
+$r->run();
diff --git a/scripts/server/dbus/murmur.pl b/scripts/server/dbus/murmur.pl
new file mode 100644
index 000000000..ce439cd8a
--- /dev/null
+++ b/scripts/server/dbus/murmur.pl
@@ -0,0 +1,286 @@
+#! /usr/bin/perl
+#
+# For now, this is a CGI using Perl.
+#
+
+use warnings;
+use strict;
+
+## User configurable settings:
+
+# What's the name of this server?
+our $servername = "Mumble & Murmur Test Server";
+
+# Who should outgoing authentication emails be from?
+our $emailfrom = "";
+
+# And what server should be used?
+our $emailserver = "localhost";
+
+# Which server to add to? Unless you have multiple virtual servers,
+# this is always 1
+our $serverid = 1;
+
+## End of user configurable data
+##
+## Really. You shouldn't touch anything below this point.
+
+# If we're being run as a CGI in suexec, $HOME doesn't exist. Fake it.
+my $home = (getpwuid($<))[7];
+
+# This needs to be done before "use Net::DBus"
+if (open(F, "$home/murmur/.dbus.sh")) {
+ while(<F>) {
+ chomp();
+ if ($_ =~ /^(.+?)\='(.+)';$/) {
+ $ENV{$1}=$2;
+ }
+ }
+ close(F);
+}
+
+use CGI;
+use CGI::Carp 'fatalsToBrowser';
+use CGI::Session;
+use Net::SMTP;
+use Net::DNS;
+use Net::DBus;
+use Image::Magick;
+use Compress::Zlib;
+use Config::Simple;
+
+sub randomCode($) {
+ my ($length) = @_;
+ my $ret;
+ my $chars="0123456789abcdefghjiklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ for(my $i=0;$i<$length;$i++) {
+ $ret .= substr($chars, rand(int(length($chars))), 1);
+ }
+ return $ret;
+}
+
+my $showit = 1;
+
+CGI::Session->find( sub { } );
+
+my $q = new CGI();
+my $s = new CGI::Session();
+
+$s->expire('+1d');
+
+print $s->header();
+print $q->start_html(-title=>"Registration");
+
+my $bus;
+my $service;
+
+# First try the system bus
+eval {
+ $bus=Net::DBus->system();
+ $service = $bus->get_service("net.sourceforge.mumble.murmur");
+
+ my $cfg = new Config::Simple(filename => '/etc/mumble-server.ini', syntax => 'simple');
+ $servername = $cfg->param("registerName") || $servername;
+ $emailfrom = $cfg->param("emailfrom") || $emailfrom;
+};
+
+# If that failed, the session bus
+if (! $service) {
+ eval {
+ $bus = Net::DBus->session();
+ $service = $bus->get_service("net.sourceforge.mumble.murmur");
+ }
+}
+
+die "Murmur service not found" if (! $service);
+
+if (! defined($emailfrom) || ($emailfrom eq "")) {
+ croak(qq{Missing configuration.
+ Please edit either /etc/mumble-server.ini for systemwide installations,
+ or murmur.pl for a personal one.
+ });
+}
+
+
+# Fetch handle to remote object
+my $object = $service->get_object("/$serverid");
+my $res;
+
+my $auth = $q->param('auth');
+my $name = $q->param('name');
+my $pw = $q->param('pw');
+my $email = $q->param('email');
+my $image = $q->upload('image');
+
+if (defined($s->param('auth')) && ($auth eq $s->param('auth'))) {
+ $res = $object->getRegisteredPlayers($s->param('name'));
+ if ($#{$res} == 0) {
+ my $aref = $$res[0];
+ if ($email ne $$aref[2]) {
+ $$aref[3] = $s->param('pw');
+ $object->updateRegistration($aref);
+ print "<h1>Updated password</h1><p>Your password has been reset.</p>";
+ $showit = 0;
+ } else {
+ print "<h1>Apologies</h1><p>Someone has already registered that name in the meantime.</p>";
+ }
+ } else {
+ $res = $object->registerPlayer($s->param('name'));
+ if (($res != 0) && ($res != "0")) {
+ my @array = ($res, $s->param('name'), $s->param('email'), $s->param('pw'));
+ $object->updateRegistration(\@array);
+ print "<h1>Succeeded</h1><p>Thank you for registering.</p>";
+ $showit = 0;
+ } else {
+ print "<h1>Failed</h1><p>Username rejected by server.</p>";
+ }
+ }
+ $s->clear();
+} elsif (defined($name) && defined($pw) && defined($image)) {
+ my $id = $object->getPlayerIds( [ $name ] );
+ $res = $object->verifyPassword($$id[0], $pw);
+ if (! $res) {
+ print "<h1>Tsk tsk</h1><p>Now, that's not a valid user and password, is it?</p>";
+ } else {
+ my $blob;
+ sysread($image,$blob,1000000);
+ my $image=Image::Magick->new();
+ my $r=$image->BlobToImage($blob);
+ if (! $r) {
+ $image->Extent(x => 0, y => 0, width => 600, height => 60, background => "transparent");
+ my $out=$image->ImageToBlob(magick => 'rgba', depth => 8);
+ if (length($out) == (600*60*4)) {
+ # We need BGRA, AKA ARGB inverse
+ my @a=unpack("C*", $out);
+ for(my $i=0;$i<600*60;$i++) {
+ my $red=$a[$i*4];
+ my $blue=$a[$i*4+2];
+ $a[$i*4]=$blue;
+ $a[$i*4+2]=$red;
+ }
+ @a=unpack("C*", pack("N", $#a + 1) . compress(pack("C*",@a)));
+ $res = $object->setTexture($$id[0], \@a);
+ } else {
+ $r=1;
+ }
+ }
+ if ($r) {
+ print "<h1>Image failure</h1><p>Failed to convert that to a proper image.</p>";
+ } else {
+ print "<h1>Succeeded</h1><p>Reconnect to use the new image.</p>";
+ $showit = 0;
+ }
+ }
+} elsif (defined($name) && defined($pw) && defined($email)) {
+ my @errors;
+
+ if (length($name) < 4) {
+ push @errors, "Username is too short.";
+ }
+ if (length($pw) < 8) {
+ push @errors, "Password is too short.";
+ }
+ if ($name !~ /^[0-9a-zA-Z\(\)\[\]\-\_]+$/) {
+ push @errors, "Username contains illegal characters.";
+ }
+
+ if ($email !~ /^[0-9a-zA-Z\.\-\_]+\@(.+)$/) {
+ push @errors, "That doesn't even look like an email adddress.";
+ } else {
+ my @mx = mx($1);
+ if ($#mx == -1) {
+ push @errors, "And how am I supposed to send email there?";
+ }
+ }
+
+ $res=$object->getRegisteredPlayers($name);
+ if ( $#{$res} == 0 ) {
+ my $aref = $$res[0];
+ if ($email ne $$aref[2]) {
+ push @errors, "Name is already taken";
+ }
+ }
+
+ if ($#errors == -1) {
+ my $code = randomCode(10);
+
+ $s->param('name', $name);
+ $s->param('pw', $pw);
+ $s->param('email', $email);
+ $s->param('auth', $code);
+
+ my $smtp = new Net::SMTP($emailserver);
+ if (! $smtp) {
+ croak(qq{Failed to connect to SMTP server "$emailserver". This is most likely a configuration problem.\n});
+ }
+ $smtp->mail($emailfrom);
+ $smtp->to($email);
+ $smtp->data();
+ $smtp->datasend("From: $emailfrom\n");
+ $smtp->datasend("To: $email\n");
+ $smtp->datasend("Subject: Murmur registration\n");
+ $smtp->datasend("\n");
+ $smtp->datasend("A user from $ENV{'REMOTE_ADDR'} registered the username $name\n");
+ $smtp->datasend("on \"${servername}\".\n\n");
+ $smtp->datasend("If this was you, please visit the following url to activate your account:\n");
+ $q->delete_all();
+ $q->param('auth', $code);
+ $smtp->datasend($q->url(-query=>1));
+ $smtp->datasend("\n\n");
+ $smtp->datasend("If you have no idea what this is about, just disregard this message.");
+ $smtp->dataend();
+
+ print '<h1>Registration complete</h1><p>Thank you for registering. An email has been sent to you with ';
+ print 'an activation code.</p>';
+ $showit = 0;
+ } else {
+ print '<ul>';
+ foreach my $error (@errors) {
+ print "<li>$error</li>";
+ }
+ print '</ul>';
+ }
+}
+
+if ($showit) {
+ print '<h1>Registration form</h1>';
+ print '<p>Fill out your desired username, password and your current email address. A mail will be sent to you ';
+ print 'with an authentication code.</p>';
+ print '<p>If you\'ve forgotten your password, just reregister with the same name and email address. A new ';
+ print 'confirmation email will be sent.</p>';
+ print '<p>';
+ print $q->start_form(-method=>'POST');
+ print "Username ";
+ print $q->textfield(-name=>'name', -size=>'10');
+ print "<br />\n";
+ print "Email ";
+ print $q->textfield(-name=>'email', -size=>'30');
+ print "<br />\n";
+ print "Password ";
+ print $q->password_field(-name=>'pw', -size=>'10');
+ print "<br />\n";
+ print $q->submit(-value=>'Register');
+ print $q->end_form();
+ print '</p>';
+
+ print '<h1>Upload custom texture?</h1>';
+ print '<p>';
+ print 'Remember that the image must be 600 by 60 pixels, and must have an alpha channel.<br />';
+ print "\n";
+ print $q->start_form(-method=>'POST');
+ print "Username ";
+ print $q->textfield(-name=>'name', -size=>'10');
+ print "<br />\n";
+ print "Password ";
+ print $q->password_field(-name=>'pw', -size=>'10');
+ print "<br />\n";
+ print "Image ";
+ print $q->filefield(-name=>'image', -size=>'30');
+ print "<br />\n";
+ print $q->submit(-value=>'Upload Image');
+ print $q->end_form();
+ print '</p>';
+}
+
+print $q->end_html();
diff --git a/scripts/server/dbus/weblist.pl b/scripts/server/dbus/weblist.pl
new file mode 100644
index 000000000..5f78237e1
--- /dev/null
+++ b/scripts/server/dbus/weblist.pl
@@ -0,0 +1,148 @@
+#! /usr/bin/perl
+
+use warnings;
+use strict;
+
+# If we're being run as a CGI in suexec, $HOME doesn't exist. Fake it.
+my $home = (getpwuid($<))[7];
+
+# This needs to be done before "use Net::DBus"
+if (open(F, "$home/murmur/.dbus.sh")) {
+ while(<F>) {
+ chomp();
+ if ($_ =~ /^(.+?)\='(.+)';$/) {
+ $ENV{$1}=$2;
+ }
+ }
+ close(F);
+}
+
+use Net::DBus;
+use CGI::Carp qw(fatalsToBrowser);
+use HTML::Template;
+
+my $tmpl_fname = $1 if ($0 =~ /(.+)\.([a-z]+)$/);
+my $tmpl;
+if (-f "$tmpl_fname.tmpl") {
+ $tmpl = HTML::Template->new(filename => "$tmpl_fname.tmpl");
+} else {
+ $tmpl = HTML::Template->new(filehandle => *DATA);
+}
+my $bus;
+my $service;
+
+# First try the system bus
+eval {
+ $bus=Net::DBus->system();
+ $service = $bus->get_service("net.sourceforge.mumble.murmur");
+};
+
+# If that failed, the session bus
+if (! $service) {
+ eval {
+ $bus = Net::DBus->session();
+ $service = $bus->get_service("net.sourceforge.mumble.murmur");
+ }
+}
+
+die "Murmur service not found" if (! $service);
+
+# Fetch handle to remote object
+my $object = $service->get_object("/");
+# Call a function on the murmur object
+my $servers = $object->getBootedServers();
+
+my $params = [];
+foreach my $server (@{$servers}) {
+ my $name = $object->getConf($server, "registername");
+ my $servobj = $service->get_object("/$server");
+
+ my %users;
+ # First, get channel names
+ my $channels = $servobj->getChannels();
+ my %channels;
+ foreach my $c (@{$channels}) {
+ my @c = @{$c};
+ my $id = $c[0];
+ my $name = $c[1];
+ $channels{$id}=$name;
+ }
+ # Then, get and print the players
+ my $players = $servobj->getPlayers();
+ my $_total = 0;
+ foreach my $p (@{$players}) {
+ my @p = @{$p};
+ my $chanid = $p[6];
+ my $name = $p[8];
+ my $chan = $channels{$chanid};
+ $users{$chan} = [] unless $users{$chan};
+ push @{$users{$chan}}, $name;
+ $_total++;
+ }
+ my $_channels = [];
+ for my $c (sort keys %users) {
+ my $_users = [];
+ for my $u (sort @{$users{$c}}) {
+ push @{$_users}, {'user' => $u};
+ }
+ push @{$_channels}, {
+ 'channel' => $c,
+ 'users' => $_users
+ };
+ }
+ push @{$params}, {'server' => $server, 'name' => $name, 'total' => $_total, 'channels' => $_channels};
+}
+
+$tmpl->param("servers", $params);
+print "Content-type: text/html;charset=utf8\r\n\r\n",
+ $tmpl->output;
+
+__END__
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<HTML lang="ja">
+ <HEAD>
+ <Title>mumble server user list</title>
+ <STYLE TYPE="text/css">
+ <!--
+ body {
+ background-color: #ffffff;
+ color: #4b4b4b;
+ font-family: verdana, arial, sans-serif;
+ font-size: 13px;
+ margin: 10px 20px;
+ }
+ dl {
+ margin-left: 5px;
+ }
+ dt {
+ clear: both;
+ font-weight: bold;
+ padding-left: 5px;
+ border-left: #4b4b4b 5px solid
+ }
+ dd {
+ float: left;
+ margin-left: 5px;
+ margin-bottom: 5px;
+ margin-top: 2px;
+ }
+ -->
+ </STYLE>
+ </HEAD>
+ <BODY bgcolor="#ffffff" text="#4b4b4b" link="#3399ff" alink="#0099cc" vlink="#006666">
+ <TMPL_LOOP NAME="servers">
+ <H1>Server #<TMPL_VAR NAME="server"> <TMPL_VAR NAME="name"></H1>
+ total: <TMPL_VAR NAME="total">
+ <dl>
+ <TMPL_LOOP NAME="channels">
+ <dt><TMPL_VAR NAME="channel">
+ <dd>
+ <TMPL_LOOP NAME="users">
+ <TMPL_VAR NAME="user">,
+ </TMPL_LOOP>
+ </TMPL_LOOP>
+ </dl>
+ </TMPL_LOOP>
+ </BODY>
+</HTML>
+
diff --git a/scripts/server/ice/addban.php b/scripts/server/ice/addban.php
new file mode 100644
index 000000000..bc601bfa4
--- /dev/null
+++ b/scripts/server/ice/addban.php
@@ -0,0 +1,50 @@
+<?php
+
+# This shows how to use structs from PHP.
+
+if (Ice_intversion() >= 30400) {
+ require 'Ice.php';
+ require 'Murmur.php';
+} else {
+ Ice_loadProfile();
+}
+
+try {
+ if (Ice_intversion() >= 30400) {
+ $ICE = Ice_initialize();
+ }
+
+ $base = $ICE->stringToProxy("Meta:tcp -h 127.0.0.1 -p 6502");
+ $meta = $base->ice_checkedCast("::Murmur::Meta");
+
+ $default = $meta->getDefaultConf();
+
+ $server = $meta->getServer(1);
+
+
+ $bans = $server->getBans();
+
+ print_r($bans);
+ foreach($bans as $ban) {
+ for($i=0;$i<16;$i+=2) {
+ echo sprintf("%02x%02x", $ban->address[$i], $ban->address[$i+1]);
+ if ($i != 14) {
+ echo ":";
+ }
+ }
+ $mask = $ban->bits;
+ echo "/$mask\n";
+ }
+
+ $ban = new Murmur_Ban();
+ $ban->address = array(0,0,0,0,0,0,0,0,0,0,255,255,127,0,0,1);
+ $ban->bits = 128;
+
+ array_push($bans, $ban);
+
+ $server->setBans($bans);
+
+} catch (Ice_Exception $ex) {
+ print_r($ex);
+}
+?>
diff --git a/scripts/server/ice/glacier/config b/scripts/server/ice/glacier/config
new file mode 100644
index 000000000..399378e6a
--- /dev/null
+++ b/scripts/server/ice/glacier/config
@@ -0,0 +1,3 @@
+Glacier2.Client.Endpoints=tcp -h 0.0.0.0 -p 4063
+Glacier2.SessionTimeout=60
+Glacier2.CryptPasswords=passwords
diff --git a/scripts/server/ice/glacier/glacier.php b/scripts/server/ice/glacier/glacier.php
new file mode 100644
index 000000000..129fc47ab
--- /dev/null
+++ b/scripts/server/ice/glacier/glacier.php
@@ -0,0 +1,45 @@
+<html>
+<head>
+<title>Userlist</title>
+</head>
+<body>
+<?php
+
+Ice_loadProfile();
+
+try {
+ # Replace IP address with the one your glacier2 is running on
+ $router = $ICE->stringToProxy("Glacier2/router:tcp -p 4063 -h 128.39.114.1");
+ $router = $router->ice_uncheckedCast("::Glacier2::Router")->ice_router(null);
+ $session = $router->createSession("testuser", "testpass");
+
+ $base = $ICE->stringToProxy("Meta:tcp -h 127.0.0.1 -p 6502")->ice_router($router);
+ $meta = $base->ice_checkedCast("::Murmur::Meta");
+
+ $servers = $meta->getBootedServers();
+ $default = $meta->getDefaultConf();
+ foreach($servers as $s) {
+ $s = $s->ice_router($router);
+ $name = $s->getConf("registername");
+ if (! $name) {
+ $name = $default["registername"];
+ }
+ echo "<h1>SERVER #" . $s->id() . " " .$name ."</h1>\n";
+ echo "<table><tr><th>Name</th><th>Channel</th></tr>\n";
+
+ $channels = $s->getChannels();
+ $players = $s->getUsers();
+
+ foreach($players as $id => $state) {
+ $chan = $channels[$state->channel];
+ echo "<tr><td>".$state->name."</td><td>".$chan->name."</td></tr>\n";
+ }
+ echo "</table>\n";
+ }
+} catch (Ice_LocalException $ex) {
+ print_r($ex);
+}
+
+?>
+</body>
+</html>
diff --git a/scripts/server/ice/glacier/passwords b/scripts/server/ice/glacier/passwords
new file mode 100644
index 000000000..04d2dc5b4
--- /dev/null
+++ b/scripts/server/ice/glacier/passwords
@@ -0,0 +1,3 @@
+# Username/password pairs.
+# passwords are generated with 'openssl passwd'
+testuser Ok0Z9JAEBWiAY
diff --git a/scripts/server/ice/icedemo.php b/scripts/server/ice/icedemo.php
new file mode 100644
index 000000000..a19c3f3fc
--- /dev/null
+++ b/scripts/server/ice/icedemo.php
@@ -0,0 +1,209 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<title>Userlist</title>
+</head>
+<body>
+<?php
+
+if (!extension_loaded('ice')) {
+ exit('Error: This example script needs the PHP extension for Ice to be loaded.');
+}
+if ((!function_exists('Ice_intVersion') || Ice_intVersion() < 30400) || !function_exists('Ice_loadProfile')) {
+ exit('Error: This example script is compatible only for php-ice versions prior to 3.4.');
+}
+
+Ice_loadProfile();
+
+if ($argc > 0) {
+ for($i=1;$i<$argc;$i++) {
+ parse_str($argv[$i], $tmp);
+ $_REQUEST=array_merge($_REQUEST, $tmp);
+ }
+}
+
+function ucmp($a, $b) {
+ if (($a->playerid == 0) || ($b->playerid == 0)) {
+ return ($a->playerid - $b->playerid);
+ }
+ return strcasecmp($a->name, $b->name);
+}
+
+$confitems = array();
+$confbig = array();
+$confitems['host']="IP Address to bind to";
+$confitems['port']="Port to use";
+$confitems['password']="Password for unregistered users";
+$confitems['timeout']="Timeout before kicking dead connections";
+$confitems['bandwidth']="Maximum bandwidth in bytes/sec";
+$confitems['users']="Maximum number of users on server";
+$confitems['welcometext']="Welcome message";
+$confbig['welcometext']=1;
+$confitems['registername']="Server Name";
+$confitems['registerpassword']="Password for Global Server List";
+$confitems['registerhostname']="Hostname for Global Server List";
+$confitems['registerurl']="HTTP URL for Global Server List";
+$confitems['certificate']="PEM Encoded SSL Certificate";
+$confbig['certificate']=1;
+$confitems['key']="PEM Encoded SSL Key";
+$confbig['key']=1;
+
+try {
+ $base = $ICE->stringToProxy("Meta:tcp -h 127.0.0.1 -p 6502");
+ $meta = $base->ice_checkedCast("::Murmur::Meta");
+
+ $default = $meta->getDefaultConf();
+
+ if (! is_null($_REQUEST['newserver'])) {
+ $meta->newServer();
+ } else if (! is_null($_REQUEST['delserver'])) {
+ $meta->getServer((int)$_REQUEST['delserver'])->delete();
+ } else if (! is_null($_REQUEST['stop'])) {
+ $meta->getServer((int) $_REQUEST['stop'])->stop();
+ } else if (! is_null($_REQUEST['start'])) {
+ $meta->getServer((int) $_REQUEST['start'])->start();
+ } else if (! is_null($_REQUEST['action'])) {
+ $server = $meta->getServer((int) $_REQUEST['action']);
+ if (!is_null($_REQUEST['kick'])) {
+ $server->kickPlayer((int) $_REQUEST['kick'], "Mushroom");
+ }
+ } else if (! is_null($_REQUEST['uedit'])) {
+ $server = $meta->getServer((int) $_REQUEST['uedit']);
+ if (isset($_REQUEST['newplayer'])) {
+ $reg = array();
+ $reg[Murmur_UserInfo::UserName] = $_REQUEST['newplayer'];
+ if ($_REQUEST['password']) $reg[Murmur_UserInfo::UserPassword] = $_REQUEST['password']; // This line is added for password at user creation
+ $_REQUEST['uid'] = $server->registerUser($reg);
+ }
+ if (! is_null($_REQUEST['deleteplayer'])) {
+ $server->unregisterUser((int) $_REQUEST['deleteplayer']);
+ }
+ if (! is_null($_REQUEST['uid'])) {
+ $uid = (int) $_REQUEST['uid'];
+ $user = $server->getRegistration($uid);
+ if (! is_null($_REQUEST['set'])) {
+ $user[Murmur_UserInfo::UserEmail] = $_REQUEST['email'];
+ $user[Murmur_UserInfo::UserPassword] = $_REQUEST['pw'];
+ $server->updateRegistration($uid,$user);
+ } else {
+ echo "<form method=\"post\" action=\"".$_SERVER['PHP_SELF']."\">\n";
+ echo "<p>\n";
+ echo "<b>Name:</b> ".$user[Murmur_UserInfo::UserName]."<br />\n";
+ echo "<input type=\"hidden\" name=\"set\" value=\"1\" />\n";
+ echo "<input type=\"hidden\" name=\"uedit\" value=\"".$server->id()."\" />\n";
+ echo "<input type=\"hidden\" name=\"uid\" value=\"$uid\" />\n";
+ echo "<b>Email:</b> <input type=\"text\" name=\"email\" size=\"30\" maxlength=\"128\" value=\"".htmlspecialchars($user[Murmur_UserInfo::UserEmail])."\" /><br />\n";
+ echo "<b>New password:</b> <input type=\"password\" name=\"pw\" size=\"30\" maxlength=\"128\" /><br />\n";
+ echo "<input type=\"submit\" />\n";
+ echo "</p>\n";
+ echo "</form>\n";
+ }
+ }
+ echo "<h1>Registered User List</h1>\n";
+ echo "<form method=\"post\" action=\"".$_SERVER['PHP_SELF']."\">\n";
+ echo "<p>\n";
+ echo "<input type=\"hidden\" name=\"uedit\" value=\"".$server->id()."\" />\n";
+ echo "<b>New User:</b>";
+ echo "<input type=\"text\" name=\"newplayer\" size=\"30\" maxlength=\"60\" />";
+ echo "<b>User Password:</b>";
+ echo "<input type=\"text\" name=\"password\" size=\"30\" maxlength=\"60\" />";
+ echo "<input type=\"submit\" />\n";
+ echo "</p>\n";
+ echo "</form>\n";
+ echo "<table>\n";
+ echo "<tr><th>UserName</th><th>Email</th><th></th></tr>\n";
+ $users = $server->getRegisteredUsers("");
+ foreach($users as $id=>$name) {
+ $u = $server->getRegistration($id);
+ echo "<tr><td>$name $id</td><td>".$u[Murmur_UserInfo::UserEmail]."</td><td>";
+ echo "<a href=\"?uedit=".$server->id()."&amp;uid=".$id."\">[Edit]</a> ";
+ echo "<a href=\"?uedit=".$server->id()."&amp;deleteplayer=".$id."\">[Unregister]</a> ";
+ echo "</td></tr>\n";
+ }
+ echo "</table>\n";
+ } else if (! is_null($_REQUEST['server'])) {
+ $server = $meta->getServer($_REQUEST['server'] + 0);
+ if (! is_null($_REQUEST['set'])) {
+ foreach($confitems as $key=>$desc) {
+ $server->setConf($key, $_REQUEST[$key]);
+ }
+ } else {
+ $conf = $server->getAllConf();
+ $default['port'] += $server->id() - 1;
+ echo "<h1>Server Configuration</h1>\n";
+ echo "<form method=\"post\" action=\"".$_SERVER['PHP_SELF']."\">\n";
+ echo "<div>\n";
+ echo "<input type=\"hidden\" name=\"server\" value=\"".$server->id()."\" />\n";
+ echo "<input type=\"hidden\" name=\"set\" value=\"1\" />\n";
+ echo "</div>\n";
+ echo "<table><tr><th>Description</th><th>Default</th><th>Value</th></tr>\n";
+ foreach($confitems as $key=>$desc) {
+ if (! isset($confbig[$key])) {
+ echo "<tr><td>$desc</td><td>".htmlspecialchars($default[$key])."</td><td>";
+ echo "<input type=\"text\" name=\"$key\" size=\"30\" maxlength=\"64000\" value=\"".htmlspecialchars($conf[$key])."\" />";
+ echo "</td></tr>\n";
+ } else {
+ echo "<tr><td>$desc</td><td colspan=\"2\">".htmlspecialchars($default[$key])."</td></tr>";
+ echo "<tr><td>&nbsp;</td><td colspan=\"2\"><textarea rows=\"5\" cols=\"80\" name=\"$key\">".htmlspecialchars($conf[$key])."</textarea>";
+ echo "</td></tr>\n";
+ }
+ }
+ echo "</table>\n";
+ echo "<div><input type=\"submit\" /></div>\n";
+ echo "</form>\n";
+ }
+ }
+
+ $servers = $meta->getAllServers();
+ $booted = $meta->getBootedServers();
+
+ echo "<h1>Murmur ICE Interface demo</h1>\n";
+ echo "<p><b>Warning:</b> This is not intended as a full management suite. It's an example. It has bugs. It has security holes. ";
+ echo "It might make precious body parts fall off. <b>Do not run it on a production server</b>.\n";
+ echo "</p>\n";
+ echo "<p>\n";
+ echo "<a href=\"?newserver\">[New Server]</a>\n";
+ echo "</p>\n";
+ foreach($servers as $s) {
+ $name = $s->getConf("registername");
+ if (! $name) {
+ $name = $default["registername"];
+ }
+ $id = $s->id();
+ echo "<h1>SERVER #" . $id . " " .$name ."</h1>\n";
+ echo "<p>\n";
+ echo "<a href=\"?server=".$id."\">[Config]</a> ";
+ if (in_array($s, $booted)) {
+ echo "<a href=\"?uedit=".$id."\">[Manage Users]</a> ";
+ echo "<a href=\"?stop=".$id."\">[Stop]</a> ";
+ } else {
+ echo "<a href=\"?delserver=".$id."\">[Delete Server]</a> ";
+ echo "<a href=\"?start=".$id."\">[Start]</a> ";
+ }
+ echo "</p>\n";
+ if (in_array($s, $booted)) {
+ echo "<table><tr><th>Name</th><th>Channel</th><th>Actions</th></tr>\n";
+
+ $channels = $s->getChannels();
+ $players = $s->getUsers();
+
+ foreach($players as $pid => $state) {
+ $chan = $channels[$state->channel];
+ echo "<tr><td>".$state->name."</td><td>".$chan->name."</td><td>";
+ echo "<a href=\"?action=".$id."&amp;kick=$state->session\">[Kick]</a>";
+ echo "</td></tr>\n";
+ }
+ echo "</table>\n";
+ }
+ }
+} catch (Ice_Exception $ex) {
+ echo "<p>\n<pre>\n";
+ print_r($ex);
+ echo "</pre>\n</p>\n";
+}
+
+?>
+</body>
+</html>
diff --git a/scripts/server/ice/idle.php b/scripts/server/ice/idle.php
new file mode 100644
index 000000000..64ec27372
--- /dev/null
+++ b/scripts/server/ice/idle.php
@@ -0,0 +1,81 @@
+<?
+# idle.php - Sample "auto-idle mover" script. Run in a cron job.
+# Copyright (c) 2010, Jamie Fraser / MumbleDog/Sabrienix
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of MumbleDog/Sabrienix nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+######################################################################
+#
+# NOTE WELL: This is just an example. It has no error checking, left
+# out both because of my own laziness and to keep the example simple.
+# Steal the implementation and put it in your own script, or just use
+# as-is under the full understanding it might end the world as you
+# know it.
+
+# "AFK" channel ID
+$afk = 4;
+
+# Time in seconds user must be AFK to be moved
+$idle = 5000;
+
+# Ice Server
+$ice = 'Meta:tcp -h 127.0.0.1 -p 6502';
+
+# Murmur ID #
+$mid = 0;
+
+######################################################################
+
+if (!extension_loaded('ice')) {
+ exit('Error: This example script needs the PHP extension for Ice to be loaded.');
+}
+if ((!function_exists('Ice_intVersion') || Ice_intVersion() < 30400) || !function_exists('Ice_loadProfile')) {
+ exit('Error: This example script is compatible only for php-ice versions prior to 3.4.');
+}
+
+Ice_loadProfile();
+$base = $ICE->stringToProxy($ice);
+$murmur = $base->ice_checkedCast('::Murmur::Meta');
+
+$m = $murmur->getServer($mid);
+
+$users = $m->getUsers();
+
+foreach ($users as $u) {
+ printf("%s: %s\n", $u->name, $u->idlesecs);
+ if ($u->idlesecs > $idle && $u->channel != $afk) {
+ $state = $m->getState($u->session);
+ if ($state) {
+ $state->channel = $afk;
+ $m->setState($state);
+ }
+ }
+}
+?> \ No newline at end of file
diff --git a/scripts/server/ice/mumble-auth.py b/scripts/server/ice/mumble-auth.py
new file mode 100644
index 000000000..1a28328fa
--- /dev/null
+++ b/scripts/server/ice/mumble-auth.py
@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+#
+# mumble-auth.py - Sample script to show the basics of using server controlled
+# context menu entries for in-client registration tickets.
+#
+# Requirements:
+# * python 2.5 or higher
+# * cherrypy 3 or higher
+# * python ice bindings
+# * murmur + mumble rev 1530 or higher
+
+import cherrypy
+import Ice
+from threading import Semaphore
+import random, time
+
+#
+#--- Config stuff
+#
+baseurl = "http://localhost:8080/register?id=" # Baseurl for registrations
+storage_time = 10*24*60*60 # Time in seconds a reg entry is guaranteed to be valid
+proxy = "Meta:tcp -h 127.0.0.1 -p 6502"
+group = "admin" # ACL group which has the right to send regurls
+host = "0.0.0.0" # Interface to listen on
+port = 8080 # Cherrypy port
+slice = "Murmur.ice"
+production = False # Set this to true to surpress tracebacks
+
+# Runtime generate bindings
+Ice.loadSlice(slice)
+import Murmur
+
+# Global vars
+sema_ids = Semaphore()
+ids = {} #Contains list(sid, user, time)
+
+
+class MetaCallbackI(Murmur.MetaCallback):
+ def started(self, s, current=None):
+ serverR = Murmur.ServerCallbackPrx.uncheckedCast(adapter.addWithUUID(ServerCallbackI(server, current.adapter)))
+ s.addCallback(serverR)
+ def stopped(self, s, current=None): pass # Unused callback
+
+class ServerCallbackI(Murmur.ServerCallback):
+ def __init__(self, server, adapter):
+ self.server = server
+ self.contextR=Murmur.ServerContextCallbackPrx.uncheckedCast(adapter.addWithUUID(ServerContextCallbackI(server)))
+
+ def userConnected(self, p, current=None):
+ if p.userid != 0: # SuperUser is always allowed
+ # Check if the user is in the right acl class and add the context menu
+ allowed = False
+ for acl in self.server.getACL(0)[1]:
+ if acl.name == group and p.userid in acl.members:
+ allowed = True
+ break
+ if not allowed:
+ return
+
+ self.server.addContextCallback(p.session,
+ "sendregurl",
+ "Send registration URL",
+ self.contextR, Murmur.ContextUser)
+
+ def userDisconnected(self, p, current=None): pass # Unused callbacks
+ def userStateChanged(self, p, current=None): pass
+ def channelCreated(self, c, current=None): pass
+ def channelRemoved(self, c, current=None): pass
+ def channelStateChanged(self, c, current=None): pass
+
+class ServerContextCallbackI(Murmur.ServerContextCallback):
+ #--- Server message template strings
+ err_notallowed = "You are not allowed to send registration urls"
+ msg_regurl = "You've been allowed to register with this mumble server, " \
+ "please <a href='%(url)s'>click here to register</a>."
+
+
+ def __init__(self, server):
+ self.server = server
+
+ def contextAction(self, action, p, session, chanid, current=None):
+ if action == "sendregurl" and p:
+ if p.userid != 0:
+ # If it isn't SuperUser check if he is in the right acl group
+ allowed = False
+ for acl in self.server.getACL(0)[1]:
+ if acl.name == group and p.userid in acl.members:
+ allowed = True
+ break
+ if not allowed:
+ self.server.sendMessage(p, self.err_notallowed)
+ return
+
+ sema_ids.acquire()
+ try:
+ # Take the chance to cleanup old entries
+ todel = []
+ for key, reg in ids.iteritems():
+ if int(time.time()) - reg[2] > storage_time:
+ todel.append(key)
+ for key in todel:
+ del ids[key]
+
+ # Ok, now generate his registration id (64bit)
+ rid = None
+ while not rid or rid in ids:
+ rid = random.randrange(0, pow(2,64))
+ sid = self.server.id()
+
+ # Remember his username
+ try:
+ username = self.server.getState(session).name
+ except Murmur.InvalidSessionException:
+ username = ""
+
+ # Save everything
+ ids[str(rid)] = (sid, username, int(time.time()))
+ # Send reg url to the user
+ url = baseurl + str(rid)
+ self.server.sendMessage(session,
+ self.msg_regurl % {'url':url})
+ finally:
+ sema_ids.release()
+
+
+
+class mumble_auth(object):
+ #--- Web template strings
+ template = """<?xml version="1.0" encoding="utf-8" ?>
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>%(title)s</title>
+ <style type="text/css">
+ label { display:block; font-size:smaller; }
+ fieldset { border:1px solid; width:250px; }
+ h1 { border-bottom:2px solid; }
+ h2 { border-bottom:2px solid red; color:red; }
+ </style>
+ </head>
+ <body>
+ <h1>%(title)s</h1>
+ %(body)s
+ </body>
+ </html>"""
+
+ err_id = """<h2>Invalid ID</h2><p>
+ The ID for your registration has already been used or is invalid.<br />
+ Please request a new registration link from a Mumble administrator.<br /></p>"""
+
+ err_username = """<h2>Invalid username</h2><p>
+ The username you chose contains characters which are not allowed.<br/>
+ Please only use normal characters without whitespaces.<br /></p>"""
+
+ err_username_existing = """<h2>Username already registered</h2><p>
+ The username you chose is already registered on this server.<br />
+ Please choose another one.<br /></p>"""
+
+ err_password = """<h2>Invalid password</h2><p>
+ The password you chose didn't match the criteria enforced by this server.<br/>
+ Your password should be at least 6 characters long.<br /></p>"""
+
+ err_password_mismatch = """<h2>Passwords do not match</h2><p>
+ The password you entered did not match the one in the confirmation box.<br/>
+ Make sure both boxes contain the same password.<br /></p>"""
+
+ snippet_retry = '<br/><a href="%(url)s">Click here to try again</a>'
+
+ body_index = """<p>This is the mumble-auth script, to be able to register yourself
+ an account please ask a admin on the mumble server.</p>"""
+
+ body_complete = """<h2>Success</h2><p>
+ You have been registered with the server successfully,<br />
+ please try to login to the server with your new login credentials!</p>"""
+
+ body_regform = """
+ <form action="doregister" method="post">
+ <fieldset>
+ <legend>Enter user information</legend>
+ <label for="username">Username</label>
+ <input id="username" type="text" name="username" value="%(username)s"
+ size="20" maxlength="40" /><br />
+ <label for="password">Password</label>
+ <input id="password" type="password" name="password" value=""
+ size="20" maxlength="40" /><br />
+ <label for="cpassword">Confirm password</label>
+ <input id="cpassword" type="password" name="cpassword" value=""
+ size="20" maxlength="40" /><br />
+ <input type="hidden" name="id" value="%(id)s" />
+ <input id="register" type="submit" value="Register" />
+ </fieldset>
+ </form>"""
+
+ def __init__(self, murmur):
+ self.murmur = murmur
+
+ def index(self):
+ title = "Mumble Auth - Index"
+ return self.template % {'title':title,
+ 'body':self.body_index}
+ index.exposed = True
+
+ def register(self, id = None):
+ title = "Mumble Auth - Register";
+ if not id in ids:
+ body = self.err_id # Invalid ID
+ else:
+ # In case of a valid ID
+ body = self.body_regform % {'username':ids[id][1],
+ 'id':id}
+
+ return self.template % {'title':title,
+ 'body':body}
+ register.exposed = True
+
+ def doregister(self, id = None, username = None, password = None, cpassword = None):
+ title = "Mumble Auth - Register";
+ sema_ids.acquire()
+ try:
+ # Check if all parameters are ok
+ if not id in ids:
+ body = self.err_id # Invalid id
+ elif not username or " " in username: # Invalid username
+ body = self.err_username + \
+ self.snippet_retry % {'url':baseurl+id}
+ elif len(password) < 6: # Password criteria didn't match
+ body = self.err_password + \
+ self.snippet_retry % {'url':baseurl+id}
+ elif password != cpassword: # Password mismatch
+ body = self.err_password_mismatch + \
+ self.snippet_retry % {'url':baseurl+id}
+ else:
+ # Ok, try to register him
+ server = self.murmur.getServer(ids[id][0])
+ if (len(server.getRegisteredUsers(username))!=0):
+ body = self.err_username_existing + \
+ self.snippet_retry % {'url':baseurl+id}
+ else:
+ # Register user
+ info = {Murmur.UserInfo.UserName:username,
+ Murmur.UserInfo.UserPassword:password}
+ server.registerUser(info)
+ # Void registration id
+ del ids[id]
+ # Success
+ body = self.body_complete
+ finally:
+ sema_ids.release()
+ return self.template % {'title':title,
+ 'body':body}
+ doregister.exposed = True
+
+if __name__ == "__main__":
+ random.seed()
+ ice = Ice.initialize()
+ try:
+ meta = Murmur.MetaPrx.checkedCast(ice.stringToProxy(proxy))
+ adapter = ice.createObjectAdapterWithEndpoints("Callback.Client", "tcp -h 127.0.0.1")
+ metaR=Murmur.MetaCallbackPrx.uncheckedCast(adapter.addWithUUID(MetaCallbackI()))
+ adapter.activate()
+
+ meta.addCallback(metaR)
+ for server in meta.getBootedServers():
+ serverR=Murmur.ServerCallbackPrx.uncheckedCast(adapter.addWithUUID(ServerCallbackI(server, adapter)))
+ server.addCallback(serverR)
+
+ if production: cherrypy.config.update({'environment': 'production'})
+ cherrypy.server.socket_host = host
+ cherrypy.server.socket_port = port
+ cherrypy.quickstart(mumble_auth(meta))
+ finally:
+ ice.shutdown()
+ ice.waitForShutdown()
diff --git a/scripts/server/ice/rubytest.rb b/scripts/server/ice/rubytest.rb
new file mode 100644
index 000000000..82edb4d69
--- /dev/null
+++ b/scripts/server/ice/rubytest.rb
@@ -0,0 +1,58 @@
+#!/usr/bin/env ruby
+
+# Download Murmur.ice from
+# http://mumble.git.sourceforge.net/git/gitweb.cgi?p=mumble;a=blob_plain;f=src/murmur/Murmur.ice;hb=HEAD
+# and run 'slice2rb Murmur.ice'. slice2rb is part of ICE.
+# This will generate the necessary 'Murmur.rb' file which needs to be included:
+
+require 'Murmur.rb'
+
+status = 0
+ic = nil
+begin
+ ic = Ice::initialize(ARGV)
+ base = ic.stringToProxy("Meta:tcp -h 127.0.0.1 -p 6502")
+ meta = Murmur::MetaPrx::checkedCast(base)
+
+ unless meta
+ rais "invalid proxy"
+ end
+
+ # All commands are documented here:
+ # http://mumble.sourceforge.net/slice/?title=slice
+
+ servers = meta.getBootedServers
+ puts "Server version:", meta.getVersion[3]
+
+ servers.each do |server|
+ puts ""
+ puts "Server name:"+server.getConf('registername')
+
+ channels = server.getChannels
+ players = server.getPlayers
+
+ players.each do |id,player|
+ channel = channels[player.channel]
+ puts player.name+" in "+channel.name
+ end
+
+ end
+
+rescue
+ puts $!
+ puts $!.backtrace.join("\n")
+ status = 1
+end
+
+if ic
+ # Clean up
+ begin
+ ic.destroy()
+ rescue
+ puts $!
+ puts $!.backtrace.join("\n")
+ status = 1
+ end
+end
+
+exit(status)
diff --git a/scripts/server/ice/simpleregister.php b/scripts/server/ice/simpleregister.php
new file mode 100644
index 000000000..5712efc38
--- /dev/null
+++ b/scripts/server/ice/simpleregister.php
@@ -0,0 +1,76 @@
+<?php
+// Really simple script to add users to your mumble server.
+// Make sure to select the server this script should be used for first:
+$serverId = 1;
+
+// Requires a correctly set up PHP-ICE Module and mumble server running with ICE.
+// For instructions see http://mumble.sourceforge.net/ICE
+
+// Credits
+// This script was created by Kissaki
+
+// This is as simple as it can get. You really SHOULD NOT make the URL to this script all-public as it may be abused/spammed.
+
+
+if (!extension_loaded('ice')) {
+ exit('Error: This example script needs the PHP extension for Ice to be loaded.');
+}
+if ((!function_exists('Ice_intVersion') || Ice_intVersion() < 30400) || !function_exists('Ice_loadProfile')) {
+ exit('Error: This example script is compatible only for php-ice versions prior to 3.4.');
+}
+
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+</head>
+<body>
+<?php
+
+Ice_loadProfile();
+
+if( isset($_GET['uname']) && $_GET['password'] && $_GET['email'] && $_GET['uname']!='' && $_GET['password']!='' )
+{
+
+ try {
+ $base = $ICE->stringToProxy("Meta:tcp -h 127.0.0.1 -p 6502");
+ $meta = $base->ice_checkedCast("::Murmur::Meta");
+
+ $server = $meta->getServer($serverId);
+
+ if(empty($server)){
+ echo 'Server could not be found.';
+ }else{
+ $registrationId = $server->registerPlayer($_GET['uname']);
+
+ $registration = $server->getRegistration(intval($registrationId));
+ $registration->pw = $_GET['password'];
+ $registration->email = $_GET['email'];
+ $server->updateregistration($registration);
+ }
+
+ }catch(InvalidPlayerException $ex){
+ echo 'InvalidPlayerException';
+ }catch(ServerBootedException $ex){
+ echo 'Server is not running';
+ }catch(Ice_UnknownLocalException $exc){
+ echo 'Ice could probably not be found';
+ }catch (Ice_Exception $ex){
+ echo "<p>\n<pre>\n";
+ print_r($ex);
+ echo "</pre>\n</p>\n";
+ }
+}
+
+?>
+ <form action="" method="get">
+ <table>
+ <tr><td>Username</td><td><input name="uname" type="text" value=""/></td></tr>
+ <tr><td>Password</td><td><input name="password" type="password" value=""/></td>
+ <tr><td>eMail</td><td><input name="email" type="text" value=""/></td></tr>
+ </table>
+ <input type="submit"/>
+ </form>
+</body>
+</html>
diff --git a/scripts/server/ice/testauth.py b/scripts/server/ice/testauth.py
new file mode 100644
index 000000000..b165d6d2c
--- /dev/null
+++ b/scripts/server/ice/testauth.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+import Ice, sys, time
+from M2Crypto import X509;
+Ice.loadSlice('', ['-I' + Ice.getSliceDir(), 'Murmur.ice'])
+import Murmur
+
+class ServerAuthenticatorI(Murmur.ServerUpdatingAuthenticator):
+ def __init__(self, server, adapter):
+ self.server = server
+
+ def authenticate(self, name, pw, certlist, certhash, strong, current=None):
+ print certhash, strong
+ for cert in certlist:
+ cert = X509.load_cert_der_string(cert)
+ print cert.get_subject(), "issued by", cert.get_issuer()
+ groups = ("GroupA", "GroupB");
+ if (name == "One"):
+ if (pw == "Magic"):
+ return (1, "One", groups)
+ else:
+ return (-1, None, None)
+ elif (name == "Two"):
+ if (pw == "Mushroom"):
+ return (2, "twO", groups)
+ else:
+ return (-1, None, None)
+ elif (name == "White Space"):
+ if (pw == "Space White"):
+ return (3, "White Space", groups)
+ else:
+ return (-1, None, None)
+ elif (name == "Fail"):
+ time.sleep(6)
+ return (-2, None, None)
+
+ def getInfo(self, id, current=None):
+ print "getInfo ", id
+ name = self.idToName(id);
+ if (name == None):
+ return (False, {})
+ map = {}
+ map[Murmur.UserInfo.UserName]=name
+ return (True, map)
+
+ def nameToId(self, name, current=None):
+ if (name == "One"):
+ return 1
+ elif (name == "Twoer"):
+ return 2
+ else:
+ return -2;
+
+ def idToName(self, id, current=None):
+ if (id == 1):
+ return "One"
+ elif (id == 2):
+ return "Two"
+ else:
+ return None
+
+ def idToTexture(self, id, current=None):
+ print "idToTexture", id
+ return open("../icons/mumble.osx.png").read();
+
+ # The expanded methods from UpdatingAuthenticator. We only implement a subset for this example, but
+ # a valid implementation has to define all of them
+ def registerUser(self, name, current=None):
+ print "Someone tried to register " + name[Murmur.UserInfo.UserName]
+ return -2
+
+ def unregisterUser(self, id, current=None):
+ print "Unregister ", id
+ return -2
+
+ def getRegistration(self, id, current=None):
+ return (-2, None, None)
+
+ def setInfo(self, id, info, current=None):
+ print "Set", id, info
+ return -1
+
+if __name__ == "__main__":
+ global contextR
+
+ print "Creating callbacks...",
+ ice = Ice.initialize(sys.argv)
+
+ meta = Murmur.MetaPrx.checkedCast(ice.stringToProxy('Meta:tcp -h 127.0.0.1 -p 6502'))
+
+ adapter = ice.createObjectAdapterWithEndpoints("Callback.Client", "tcp -h 127.0.0.1")
+ adapter.activate()
+
+ for server in meta.getBootedServers():
+ serverR=Murmur.ServerUpdatingAuthenticatorPrx.uncheckedCast(adapter.addWithUUID(ServerAuthenticatorI(server, adapter)))
+ server.setAuthenticator(serverR)
+
+ print "Done"
+
+ map = {};
+ map[Murmur.UserInfo.UserName] = 'TestUser';
+
+ for server in meta.getBootedServers():
+ ids= server.getUserIds(["TestUser"])
+ for name,id in ids.iteritems():
+ if (id > 0):
+ print "Will unregister ", id
+ server.unregisterUser(id)
+ server.registerUser(map)
+
+ print 'Script running (press CTRL-C to abort)';
+ try:
+ ice.waitForShutdown()
+ except KeyboardInterrupt:
+ print 'CTRL-C caught, aborting'
+
+ meta.removeCallback(metaR)
+ ice.shutdown()
+ print "Goodbye"
diff --git a/scripts/server/ice/testcallback.py b/scripts/server/ice/testcallback.py
new file mode 100644
index 000000000..3e1566350
--- /dev/null
+++ b/scripts/server/ice/testcallback.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+import Ice, sys, sha
+from M2Crypto import X509;
+
+Ice.loadSlice('', ['-I' + Ice.getSliceDir(), 'Murmur.ice'])
+import Murmur
+
+class MetaCallbackI(Murmur.MetaCallback):
+ def started(self, s, current=None):
+ print "started"
+ serverR=Murmur.ServerCallbackPrx.uncheckedCast(adapter.addWithUUID(ServerCallbackI(server, current.adapter)))
+ s.addCallback(serverR)
+
+ def stopped(self, s, current=None):
+ print "stopped"
+
+class ServerCallbackI(Murmur.ServerCallback):
+ def __init__(self, server, adapter):
+ self.server = server
+ self.contextR=Murmur.ServerContextCallbackPrx.uncheckedCast(adapter.addWithUUID(ServerContextCallbackI(server)))
+
+ def userConnected(self, p, current=None):
+ print "connected"
+ print p
+ self.server.addContextCallback(p.session, "flubber", "Power up the T", self.contextR, Murmur.ContextChannel | Murmur.ContextUser)
+ if (self.server.hasPermission(p.session, 0, Murmur.PermissionWrite)):
+ print "Is a global admin"
+ certlist=self.server.getCertificateList(p.session)
+ for cert in certlist:
+ hash = sha.new()
+ hash.update(cert)
+ cert = X509.load_cert_der_string(cert)
+ print cert.get_subject(), "issued by", cert.get_issuer(), "hash", hash.hexdigest()
+ if current:
+ print current.ctx
+
+ def userDisconnected(self, p, current=None):
+ print "disconnected"
+ print p
+
+ def userStateChanged(self, p, current=None):
+ print "stateChanged"
+ print self.server
+ print p
+
+ def userTextMessage(self, p, msg, current=None):
+ print "userTextMessage"
+ print self.server
+ print p
+ print msg
+
+ def channelCreated(self, c, current=None):
+ print "created"
+ print c
+
+ def channelRemoved(self, c, current=None):
+ print "removed"
+ print c
+
+ def channelStateChanged(self, c, current=None):
+ print "stateChanged"
+ print c
+
+class ServerContextCallbackI(Murmur.ServerContextCallback):
+ def __init__(self, server):
+ self.server = server
+
+ def contextAction(self, action, p, session, chanid, current=None):
+ print "aaand ACTION"
+ print action
+ print p
+ print session
+ print chanid
+ if (session != 0):
+ server.sendMessage(session, "Bouncy")
+ elif (chanid >= 0):
+ server.sendMessageChannel(chanid, 0, "Channel Bouncy")
+
+if __name__ == "__main__":
+ global contextR
+
+ prop = Ice.createProperties(sys.argv)
+ prop.setProperty("Ice.ImplicitContext", "Shared")
+
+ idd = Ice.InitializationData()
+ idd.properties = prop
+
+ ice = Ice.initialize(idd)
+
+ print "Creating callbacks...",
+
+ # If icesecret is set, we need to set it here as well.
+ ice.getImplicitContext().put("secret", "fourtytwo")
+
+ meta = Murmur.MetaPrx.checkedCast(ice.stringToProxy('Meta:tcp -h 127.0.0.1 -p 6502'))
+ adapter = ice.createObjectAdapterWithEndpoints("Callback.Client", "tcp -h 127.0.0.1")
+
+ metaR=Murmur.MetaCallbackPrx.uncheckedCast(adapter.addWithUUID(MetaCallbackI()))
+ adapter.activate()
+
+ meta.addCallback(metaR)
+
+ for server in meta.getBootedServers():
+ serverR=Murmur.ServerCallbackPrx.uncheckedCast(adapter.addWithUUID(ServerCallbackI(server, adapter)))
+ server.addCallback(serverR)
+
+ print "Done"
+ print 'Script running (press CTRL-C to abort)';
+ try:
+ ice.waitForShutdown()
+ except KeyboardInterrupt:
+ print 'CTRL-C caught, aborting'
+
+ meta.removeCallback(metaR)
+ ice.shutdown()
+ print "Goodbye"
diff --git a/scripts/server/ice/testdynamic.py b/scripts/server/ice/testdynamic.py
new file mode 100644
index 000000000..639b81226
--- /dev/null
+++ b/scripts/server/ice/testdynamic.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+import Ice, IcePy, sys, tempfile, os
+
+ice = Ice.initialize(sys.argv)
+
+proxy = ice.stringToProxy('Meta:tcp -h 127.0.0.1 -p 6502')
+
+try:
+ slice = IcePy.Operation('getSlice', Ice.OperationMode.Idempotent, Ice.OperationMode.Idempotent, True, (), (), (), IcePy._t_string, ()).invoke(proxy, ((), None))
+
+ (slicefiledesc, slicefilepath) = tempfile.mkstemp(suffix = '.ice')
+ slicefile = os.fdopen(slicefiledesc, 'w')
+ slicefile.write(slice)
+ slicefile.flush()
+ Ice.loadSlice('', ['-I' + Ice.getSliceDir(), slicefilepath])
+ slicefile.close()
+ os.remove(slicefilepath)
+
+ print 'Using dynamic slice'
+except Exception:
+ Ice.loadSlice('', ['-I' + Ice.getSliceDir(), 'Murmur.ice'])
+ print 'Using bundled slice'
+
+import Murmur
+
+meta = Murmur.MetaPrx.checkedCast(proxy)
+
+print meta.getVersion()
diff --git a/scripts/server/ice/weblist.php b/scripts/server/ice/weblist.php
new file mode 100644
index 000000000..3f7f5cbdd
--- /dev/null
+++ b/scripts/server/ice/weblist.php
@@ -0,0 +1,60 @@
+<html>
+<head>
+<title>Userlist</title>
+</head>
+<body>
+<?php
+
+#
+# Murmur.php is generated by calling
+# slice2php /path/to/Murmur.ice
+# in this directory
+#
+
+if (Ice_intversion() >= 30400) {
+ if (!stream_resolve_include_path('Ice.php')) {
+ exit('The required file Ice.php could not be found in the PHP include path(s).');
+ }
+ if (!stream_resolve_include_path('Murmur.php')) {
+ exit('The required file Murmur.php could not be found in the PHP include path(s).');
+ }
+ require 'Ice.php';
+ require 'Murmur.php';
+} else {
+ Ice_loadProfile();
+}
+
+try {
+ if (Ice_intversion() >= 30400) {
+ $ICE = Ice_initialize();
+ }
+
+ $base = $ICE->stringToProxy("Meta:tcp -h 127.0.0.1 -p 6502");
+ $meta = $base->ice_checkedCast("::Murmur::Meta");
+
+ $servers = $meta->getBootedServers();
+ $default = $meta->getDefaultConf();
+ foreach($servers as $s) {
+ $name = $s->getConf("registername");
+ if (! $name) {
+ $name = $default["registername"];
+ }
+ echo "<h1>SERVER #" . $s->id() . " " .$name ."</h1>\n";
+ echo "<table><tr><th>Name</th><th>Channel</th></tr>\n";
+
+ $channels = $s->getChannels();
+ $players = $s->getUsers();
+
+ foreach($players as $id => $state) {
+ $chan = $channels[$state->channel];
+ echo "<tr><td>".$state->name."</td><td>".$chan->name."</td></tr>\n";
+ }
+ echo "</table>\n";
+ }
+} catch (Ice_LocalException $ex) {
+ print_r($ex);
+}
+
+?>
+</body>
+</html>