[X2Go-Commits] x2gobroker.git - build-main (branch) updated: 0.0.1.0-51-gf4fc469

X2Go dev team git-admin at x2go.org
Sun May 19 13:03:34 CEST 2013


The branch, build-main has been updated
  discards  e4f4a3be711ee2246032b555da42151dfb232af8 (commit)
  discards  0318f27362e56d6587c82d63926cfe677eaccffd (commit)
  discards  bf9ca01cd94266ee47c6ce056a702a942803124c (commit)
  discards  d6e31e806eeb92472e1eaa2c87c3bae3f5d94dc4 (commit)
  discards  ad12802c5aa0c60a2586d5874f638ef1dd7dc8e3 (commit)
  discards  11cc12dd2fe8c0d0e171bb79e8272c7ee60528c9 (commit)
  discards  26dd0105562fbdebc0662b8f86d78a3a8d71c2fa (commit)
  discards  ca33ea93056615c370586d9f1054b29695b56393 (commit)
  discards  6089879c268eaafb9cd3bdc76dc9f06346ef592f (commit)
  discards  bff088d523cccbcbe5c6836eaf61e05bc2145df7 (commit)
  discards  1298863cc62b9167f4a270cf5262d8d234fe56b0 (commit)
       via  f4fc469442dcdb43047f2165ccda4f6c0e25df4e (commit)
       via  e115d0666c21ebecd8c7c8549192ffe4bbf02071 (commit)
       via  75f4cb8a59b9e8591aaed2f92dce4a6781ff8299 (commit)
       via  688b8ea22350b99660413a3333926bfa81d19609 (commit)
       via  dc9eb932798d2679780d1343e1ab3ea4fa7386cc (commit)
       via  b487008f79052cc4da52e7e6093ff99a3d1a80af (commit)
       via  8c27295aedf58ab801edad949dde0ca121eb5f18 (commit)
       via  e1c90224f4e364345e9e76aa3db086988e03a056 (commit)
       via  e6bbdb5bb97de5ee01cd9e659ba43f1dde5c7376 (commit)
       via  6ab6f454d8976ab5c42937e44e81ab2bf570f9e6 (commit)
       via  e19494d1cf6fa3f04f946d50196c3a5123835ba2 (commit)
       via  c09f1966fdde02156a5371b2a909b13b3620dc4f (commit)
       via  5b884430d73643ab81fc0aac11f22e52be8706ee (commit)
       via  3fd14f204a2f570d88c95b455fdcffd57b99ed4e (commit)
       via  870b98422e7e2ceff6e2f2c5f90172e63109b75a (commit)
       via  8546ee4fcd4c094b1a1a7a04ba81ed549055920e (commit)
       via  b57e5c7d732c94056ded5046bd2f475074a3d933 (commit)
       via  ac6024e007f2a0f5a63d82513a7370c72378925a (commit)
       via  bf62865e24d79f1c697c2ff2d353c52001e41041 (commit)
       via  3366ab187d971a0de2bf2f13d33c02e24ce77ed5 (commit)
       via  87e0d33ee82cbbc48ff738d5fa33a49a7b9f904f (commit)
       via  f5c77c7654c180c9f55f175b9dc2a611a4a26a1c (commit)
       via  12ace4ff77e043274948ada6f13ffedc5e561d26 (commit)
       via  d3a17b136b23755840e13547152011193c2febe9 (commit)
       via  cbe481e17814bf14404b4adc95fc6ae53efa52a1 (commit)
       via  5f08ed5c43d6c8c96515f5628d3a60cb0c386ab7 (commit)
       via  a505addd53fee98a0445278c838447b4b20e3d1b (commit)
       via  9ec668c96ad7a70e1024194c3f7eae7ea3e9e6ba (commit)
       via  b075080bcd2a1510f4ac820f752580000712e509 (commit)
       via  d76dcd7f32e82452e74e167ff9de4020403ecb84 (commit)
       via  b24fe4ed32dc3f3066f20b4f93f1df5bbbdaa778 (commit)
       via  b440438bdbdcdd248957f6e2e0cfe4deaab895b5 (commit)
       via  830502fcaa69733d4c5f6561d335a5f7032c4baa (commit)
       via  317325dd112ba89775ff81984ef985f061a81b21 (commit)
       via  2cee942cb70599dd79ef3cf7f93fc2aeaa950472 (commit)
       via  0beb6626be0dd1c9d0363435268def8df85f1380 (commit)
       via  d14d83a114d66019fe9fa031f3a367c65224cf6a (commit)
       via  8130c9d12e3447fda3064b4b3f1ba0aef1015341 (commit)
       via  00fb61c3429809f7511f7bda5667a77facd96918 (commit)
       via  e341bd86111730b2919697a74ac18d759d2a9e74 (commit)
       via  c9c92dbff6b4e9ee872eb738121dbd51da94d329 (commit)
       via  1734e9987eebeaf7574c42c28b92f010fb827008 (commit)
       via  cd9500b7a1d12cd973af7726dbead83b79bc8581 (commit)
       via  890debb62b31a29ed482d392e7d276c5d9936d90 (commit)
       via  aea8e30472982caf3be18c73e3175becfc6d6b4a (commit)
       via  19582aa37e0e3cab202c43cd7497d791cbeee1b3 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (e4f4a3be711ee2246032b555da42151dfb232af8)
            \
             N -- N -- N (f4fc469442dcdb43047f2165ccda4f6c0e25df4e)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
-----------------------------------------------------------------------

Summary of changes:
 debian/changelog                                   |    4 +
 debian/control                                     |    4 +-
 debian/python-x2gobroker.install                   |    1 -
 debian/python-x2gobroker.postinst                  |   29 +++
 debian/python-x2gobroker.postrm                    |   27 +++
 debian/python-x2gobroker.preinst                   |   31 +++
 debian/x2gobroker-agent.postinst                   |    3 +
 debian/x2gobroker-authservice.install              |    3 +-
 debian/x2gobroker-daemon.install                   |    1 +
 debian/x2gobroker-daemon.postinst                  |    3 +
 debian/x2gobroker-wsgi.install                     |    3 +-
 debian/x2gobroker-wsgi.postinst                    |    3 +
 etc/broker/x2gobroker-loggers.conf                 |   21 +-
 etc/broker/x2gobroker-sessionprofiles.conf         |    4 +-
 etc/x2gobroker-wsgi.apache.conf                    |    1 +
 etc/x2gobroker.conf                                |    5 +
 logrotate/x2gobroker-authservice                   |   13 ++
 logrotate/x2gobroker-daemon                        |   13 ++
 logrotate/{x2gobroker => x2gobroker-wsgi}          |    4 +-
 sbin/x2gobroker                                    |    2 +
 sbin/x2gobroker-authservice                        |   21 +-
 x2gobroker/__init__.py                             |    9 -
 x2gobroker/agent.py                                |    5 +-
 x2gobroker/authservice.py                          |   50 +++-
 x2gobroker/brokers/base_broker.py                  |    3 +
 x2gobroker/brokers/zeroconf_broker.py              |    7 +-
 x2gobroker/defaults.py                             |    6 +-
 x2gobroker/loggers.py                              |    5 -
 x2gobroker/tests/test_broker_base.py               |    4 +-
 x2gobroker/tests/test_broker_inifile.py            |  142 +++++++++---
 x2gobroker/tests/test_broker_zeroconf.py           |    2 +
 x2gobroker/tests/test_web_plain_zeroconf.py        |    9 +-
 x2gobroker/tests/test_web_uccs_zeroconf.py         |   80 +++++++
 x2gobroker/uccsjson.py                             |  241 ++++++++++++++++++++
 x2gobroker/web/uccs.py                             |  165 ++++++++++++++
 .../{__init__.py => x2gobroker_exceptions.py}      |    0
 36 files changed, 829 insertions(+), 95 deletions(-)
 create mode 100755 debian/python-x2gobroker.postinst
 create mode 100755 debian/python-x2gobroker.postrm
 create mode 100755 debian/python-x2gobroker.preinst
 create mode 100644 debian/x2gobroker-daemon.install
 create mode 100644 logrotate/x2gobroker-authservice
 create mode 100644 logrotate/x2gobroker-daemon
 rename logrotate/{x2gobroker => x2gobroker-wsgi} (57%)
 create mode 100644 x2gobroker/tests/test_web_uccs_zeroconf.py
 create mode 100644 x2gobroker/uccsjson.py
 create mode 100644 x2gobroker/web/uccs.py
 copy x2gobroker/{__init__.py => x2gobroker_exceptions.py} (100%)

The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index 4bf0feb..594ca76 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,10 +5,14 @@ x2gobroker (0.0.1.1-0~x2go1) UNRELEASED; urgency=low
       Apache2 by using the mod_wsgi module.
     - Add Apache2 configuration for WSGI support that shows how to
       setup a VirtualHost for X2Go Session Broker.
+    - Add cmd and directrdp session profile parameters to defaults.
+    - Fix wrong usage of session option »cmd«, has to be »command«.
     - For sessions profiles with autologin enable, add a dummy key
       session profile parameter that triggers key based auth in X2Go Client.
       (Fixes: #154).
     - Fix hard-coded path to x2gobroker's authservice socket.
+    - Separate logging logic of x2gobroker-authservice from the rest of
+      the logging in x2gobroker. (Fixes: #172).
   * /debian/control:
     + Fix --root parameter in DEB_PYTHON_INSTALL_ARGS.
     + Let bin:package x2gobroker-authservice depend on python-x2gobroker (of the
diff --git a/debian/control b/debian/control
index a493d8a..21554ca 100644
--- a/debian/control
+++ b/debian/control
@@ -58,6 +58,7 @@ Depends:
  python-argparse,
  python-setproctitle,
  python-tornado,
+ python-wsgilog,
  python-x2gobroker (>= ${source:Version}), python-x2gobroker (<< ${source:Version}.1~),
 Suggests:
  apache2 | httpd,
@@ -87,6 +88,7 @@ Architecture: all
 Depends:
  ${python:Depends},
  ${misc:Depends},
+ adduser,
  python,
  python-argparse,
  python-setproctitle,
@@ -153,7 +155,7 @@ Depends:
  ${python:Depends},
  python,
  adduser,
- python-wsgilog,
+ x2gobroker (>= ${source:Version}), x2gobroker (<< ${source:Version}.1~),
 Suggests:
  apache2,
 Description: X2Go http(s) based session broker (CGI)
diff --git a/debian/python-x2gobroker.install b/debian/python-x2gobroker.install
index 91aabf6..c8bd09a 100644
--- a/debian/python-x2gobroker.install
+++ b/debian/python-x2gobroker.install
@@ -1,5 +1,4 @@
 etc/x2gobroker.conf etc/x2go/
 etc/broker etc/x2go/
-logrotate/x2gobroker etc/logrotate.d/
 pam/x2gobroker etc/pam.d/
 usr/
diff --git a/debian/python-x2gobroker.postinst b/debian/python-x2gobroker.postinst
new file mode 100755
index 0000000..5829481
--- /dev/null
+++ b/debian/python-x2gobroker.postinst
@@ -0,0 +1,29 @@
+#!/bin/sh
+# postinst script for python-x2gobroker
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <postinst> `abort-remove'
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+if dpkg-maintscript-helper supports rm_conffile 2>/dev/null; then
+	dpkg-maintscript-helper rm_conffile /etc/logrotate.d/x2gobroker 0.0.1.1-0 -- "$@"
+fi
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/debian/python-x2gobroker.postrm b/debian/python-x2gobroker.postrm
new file mode 100755
index 0000000..d8e6815
--- /dev/null
+++ b/debian/python-x2gobroker.postrm
@@ -0,0 +1,27 @@
+#! /bin/sh
+# postrm script for python-x2gobroker
+#
+# see: dh_installdeb(1)
+# summary of how this script can be called:
+#        * <postrm> `remove'
+#        * <postrm> `purge'
+#        * <old-postrm> `upgrade' <new-version>
+#        * <new-postrm> `failed-upgrade' <old-version>
+#        * <new-postrm> `abort-install'
+#        * <new-postrm> `abort-install' <old-version>
+#        * <new-postrm> `abort-upgrade' <old-version>
+#        * <disappearer's-postrm> `disappear' <r>overwrit>r> <new-version>
+# for details, see /usr/share/doc/packaging-manual/
+
+set -e
+
+if dpkg-maintscript-helper supports rm_conffile 2>/dev/null; then
+	dpkg-maintscript-helper rm_conffile /etc/logrotate.d/x2gobroker 0.0.1.1-0 -- "$@"
+fi
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
\ No newline at end of file
diff --git a/debian/python-x2gobroker.preinst b/debian/python-x2gobroker.preinst
new file mode 100755
index 0000000..1f28dd6
--- /dev/null
+++ b/debian/python-x2gobroker.preinst
@@ -0,0 +1,31 @@
+#!/bin/sh
+# preinst script for python-x2gobroker
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <postinst> `abort-remove'
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+if dpkg-maintscript-helper supports rm_conffile 2>/dev/null; then
+	dpkg-maintscript-helper rm_conffile /etc/logrotate.d/x2gobroker 0.0.1.1-0 -- "$@"
+fi
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
diff --git a/debian/x2gobroker-agent.postinst b/debian/x2gobroker-agent.postinst
index 8f48ccd..a6fd79d 100755
--- a/debian/x2gobroker-agent.postinst
+++ b/debian/x2gobroker-agent.postinst
@@ -56,6 +56,9 @@ case "$1" in
 		if ! dpkg-statoverride --list /usr/lib/x2go/x2gobroker-agent 1>/dev/null; then
 		    dpkg-statoverride --add --update root x2gobroker 4750 /usr/lib/x2go/x2gobroker-agent
 		fi
+		touch /var/log/x2gobroker/broker.log && chown x2gobroker:adm /var/log/x2gobroker/broker.log
+		touch /var/log/x2gobroker/error.log && chown x2gobroker:adm /var/log/x2gobroker/error.log
+
 
 		;;
 
diff --git a/debian/x2gobroker-authservice.install b/debian/x2gobroker-authservice.install
index 03fb37c..8d466ac 100644
--- a/debian/x2gobroker-authservice.install
+++ b/debian/x2gobroker-authservice.install
@@ -1 +1,2 @@
-sbin/x2gobroker-authservice usr/sbin/
\ No newline at end of file
+sbin/x2gobroker-authservice usr/sbin/
+logrotate/x2gobroker-authservice etc/logrotate.d/
\ No newline at end of file
diff --git a/debian/x2gobroker-daemon.install b/debian/x2gobroker-daemon.install
new file mode 100644
index 0000000..7f70476
--- /dev/null
+++ b/debian/x2gobroker-daemon.install
@@ -0,0 +1 @@
+logrotate/x2gobroker-daemon etc/logrotate.d/
\ No newline at end of file
diff --git a/debian/x2gobroker-daemon.postinst b/debian/x2gobroker-daemon.postinst
index 9bc1d52..95c4475 100755
--- a/debian/x2gobroker-daemon.postinst
+++ b/debian/x2gobroker-daemon.postinst
@@ -53,6 +53,9 @@ case "$1" in
 		if ! dpkg-statoverride --list /var/log/x2gobroker 1>/dev/null; then
 			dpkg-statoverride --add --update x2gobroker adm 2750 /var/log/x2gobroker
 		fi
+		touch /var/log/x2gobroker/access.log && chown x2gobroker:adm /var/log/x2gobroker/access.log
+		touch /var/log/x2gobroker/broker.log && chown x2gobroker:adm /var/log/x2gobroker/broker.log
+		touch /var/log/x2gobroker/error.log && chown x2gobroker:adm /var/log/x2gobroker/error.log
 
 		;;
 
diff --git a/debian/x2gobroker-wsgi.install b/debian/x2gobroker-wsgi.install
index 26c32b7..f7f6452 100644
--- a/debian/x2gobroker-wsgi.install
+++ b/debian/x2gobroker-wsgi.install
@@ -1,2 +1,3 @@
 etc/x2gobroker-wsgi.apache.conf /etc/x2go/
-etc/x2gobroker-wsgi.apache.vhost /etc/x2go/
\ No newline at end of file
+etc/x2gobroker-wsgi.apache.vhost /etc/x2go/
+logrotate/x2gobroker-wsgi etc/logrotate.d/
\ No newline at end of file
diff --git a/debian/x2gobroker-wsgi.postinst b/debian/x2gobroker-wsgi.postinst
index 873b123..0372383 100755
--- a/debian/x2gobroker-wsgi.postinst
+++ b/debian/x2gobroker-wsgi.postinst
@@ -56,6 +56,9 @@ case "$1" in
 		if ! dpkg-statoverride --list /var/log/x2gobroker 1>/dev/null; then
 			dpkg-statoverride --add --update x2gobroker adm 2750 /var/log/x2gobroker
 		fi
+		touch /var/log/x2gobroker/broker.log && chown x2gobroker:adm /var/log/x2gobroker/broker.log
+		touch /var/log/x2gobroker/error.log && chown x2gobroker:adm /var/log/x2gobroker/error.log
+		touch /var/log/x2gobroker/wsgi.log && chown x2gobroker:adm /var/log/x2gobroker/wsgi.log
 
 		;;
 
diff --git a/etc/broker/x2gobroker-loggers.conf b/etc/broker/x2gobroker-loggers.conf
index 87d7dca..e2edd23 100644
--- a/etc/broker/x2gobroker-loggers.conf
+++ b/etc/broker/x2gobroker-loggers.conf
@@ -21,17 +21,17 @@
 # WARNING: only modify this file if you _exactly_ know what you are doing!!!
 
 [loggers]
-keys=root,broker,authservice,access,error
+keys=root,broker,access,error
 
 [logger_root]
 level=NOTSET
 handlers=stderrHandler
 
 [handlers]
-keys=stderrHandler,brokerFileHandler,authserviceFileHandler,accessFileHandler,errorFileHandler
+keys=stderrHandler,brokerFileHandler,accessFileHandler,errorFileHandler
 
 [formatters]
-keys=brokerFormatter,authserviceFormatter,accessFormatter,errorFormatter
+keys=brokerFormatter,accessFormatter,errorFormatter
 
 [handler_stderrHandler]
 class=StreamHandler
@@ -52,21 +52,6 @@ args=('/var/log/x2gobroker/broker.log',)
 format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
 datefmt=
 
-[logger_authservice]
-level=DEBUG
-handlers=authserviceFileHandler
-qualname=authservice
-propagate=0
-
-[handler_authserviceFileHandler]
-class=FileHandler
-formatter=authserviceFormatter
-args=('/var/log/x2gobroker/authservice.log',)
-
-[formatter_authserviceFormatter]
-format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
-datefmt=
-
 [logger_access]
 level=DEBUG
 handlers=accessFileHandler
diff --git a/etc/broker/x2gobroker-sessionprofiles.conf b/etc/broker/x2gobroker-sessionprofiles.conf
index dc79a6b..8d060ec 100644
--- a/etc/broker/x2gobroker-sessionprofiles.conf
+++ b/etc/broker/x2gobroker-sessionprofiles.conf
@@ -29,6 +29,7 @@
 
 
 [DEFAULT]
+command=TERMINAL
 defsndport=true
 useiconv=false
 iconvfrom=UTF-8
@@ -52,13 +53,14 @@ applications=TERMINAL,WWWBROWSER,MAILCLIENT,OFFICE
 multidisp=false
 sshproxyport=22
 sound=true
-rootless=false
+rootless=true
 iconvto=UTF-8
 soundtunnel=true
 dpi=96
 sshport=22
 setdpi=0
 pack=16m-jpeg
+directrdp=false
 
 ### EXAMPLES: Below you find some config examples. Adapt them to your needs or
 ### simply write your own session profiles and remove the examples below.
diff --git a/etc/x2gobroker-wsgi.apache.conf b/etc/x2gobroker-wsgi.apache.conf
index 92c432f..63ba34a 100644
--- a/etc/x2gobroker-wsgi.apache.conf
+++ b/etc/x2gobroker-wsgi.apache.conf
@@ -5,6 +5,7 @@
 #X2GOBROKER_DAEMON_USER=x2gobroker
 #X2GOBROKER_DAEMON_GROUP=x2gobroker
 WSGIDaemonProcess x2gobroker user=x2gobroker group=x2gobroker processes=5 threads=15
+WSGIPassAuthorization On
 
 # default broker backend (default: zeroconf)
 SetEnv X2GOBROKER_DEFAULT_BACKEND zeroconf
diff --git a/etc/x2gobroker.conf b/etc/x2gobroker.conf
index 24a530f..cf544bb 100644
--- a/etc/x2gobroker.conf
+++ b/etc/x2gobroker.conf
@@ -71,6 +71,11 @@
 # enable {base_url}/plain/
 #enable-plain-output = true
 
+# enable {base_url}/uccs/
+#enable-uccs-output = false
+# use this URL base to create URL field in UCCS-style JSON output
+#my-uccs-url-base = http://localhost:8080/
+
 # enable {base_url}/json/ (THIS IS FUTURE, mg-20121129)
 #enable-json-output = false
 
diff --git a/logrotate/x2gobroker-authservice b/logrotate/x2gobroker-authservice
new file mode 100644
index 0000000..d19cc13
--- /dev/null
+++ b/logrotate/x2gobroker-authservice
@@ -0,0 +1,13 @@
+/var/log/x2gobroker/authservice.log {
+	weekly
+	missingok
+	rotate 52
+	compress
+	delaycompress
+	notifempty
+	create 640 root adm
+	sharedscripts
+	postrotate
+		invoke-rc.d x2gobroker-authservice restart > /dev/null
+	endscript
+}
diff --git a/logrotate/x2gobroker-daemon b/logrotate/x2gobroker-daemon
new file mode 100644
index 0000000..31da1bd
--- /dev/null
+++ b/logrotate/x2gobroker-daemon
@@ -0,0 +1,13 @@
+/var/log/x2gobroker/access.log /var/log/x2gobroker/broker.log /var/log/x2gobroker/error.log {
+	weekly
+	missingok
+	rotate 52
+	compress
+	delaycompress
+	notifempty
+	create 640 x2gobroker adm
+	sharedscripts
+	postrotate
+		invoke-rc.d x2gobroker-daemon restart > /dev/null
+	endscript
+}
diff --git a/logrotate/x2gobroker b/logrotate/x2gobroker-wsgi
similarity index 57%
rename from logrotate/x2gobroker
rename to logrotate/x2gobroker-wsgi
index 4e8c689..bb040b7 100644
--- a/logrotate/x2gobroker
+++ b/logrotate/x2gobroker-wsgi
@@ -1,4 +1,4 @@
-/var/log/x2gobroker/*.log {
+/var/log/x2gobroker/broker.log /var/log/x2gobroker/error.log /var/log/x2gobroker/wsgi.log {
 	weekly
 	missingok
 	rotate 52
@@ -7,7 +7,5 @@
 	notifempty
 	create 640 x2gobroker adm
 	sharedscripts
-	postrotate
-		/etc/init.d/x2gobroker restart > /dev/null
 	endscript
 }
diff --git a/sbin/x2gobroker b/sbin/x2gobroker
index a092172..5abd86d 100755
--- a/sbin/x2gobroker
+++ b/sbin/x2gobroker
@@ -107,12 +107,14 @@ if __name__ == "__main__":
 
 # import classes serving the different web.py URLs
 import x2gobroker.web.plain
+import x2gobroker.web.uccs
 #import x2gobroker.web.json
 #import x2gobroker.web.html
 import x2gobroker.web.extras
 
 # define the web.py URLs
 urls = ( ('/plain/(.*)', x2gobroker.web.plain.X2GoBrokerWeb,),
+         ('/uccs/(.*)', x2gobroker.web.uccs.X2GoBrokerWeb,),
 #        ('/json/(.*)', x2gobroker.web.json.X2GoBrokerWeb,),
 #        ('/html/(.*)', x2gobroker.web.html.X2GoBrokerWeb,),
          ('/pubkeys/', x2gobroker.web.extras.X2GoBrokerPubKeyService,),
diff --git a/sbin/x2gobroker-authservice b/sbin/x2gobroker-authservice
index e17271e..5f0bd13 100755
--- a/sbin/x2gobroker-authservice
+++ b/sbin/x2gobroker-authservice
@@ -28,12 +28,10 @@ import argparse
 import logging
 
 try:
-    import x2gobroker.defaults
+    import x2gobroker.authservice
 except ImportError:
     sys.path.insert(0, os.path.join(os.getcwd(), '..'))
-    import x2gobroker.defaults
-
-import x2gobroker.authservice
+    import x2gobroker.authservice
 
 PROG_NAME = os.path.basename(sys.argv[0])
 PROG_OPTIONS = sys.argv[1:]
@@ -41,20 +39,19 @@ setproctitle.setproctitle("%s %s" % (PROG_NAME, " ".join(PROG_OPTIONS)))
 
 from x2gobroker import __VERSION__
 from x2gobroker import __AUTHOR__
-from x2gobroker.loggers import logger_authservice
 
 # raise log level to DEBUG if requested...
-if x2gobroker.defaults.X2GOBROKER_DEBUG and not x2gobroker.defaults.X2GOBROKER_TESTSUITE:
-    logger_authservice.setLevel(logging.DEBUG)
+if x2gobroker.authservice.X2GOBROKER_DEBUG and not x2gobroker.authservice.X2GOBROKER_TESTSUITE:
+    x2gobroker.authservice.logger_authservice.setLevel(logging.DEBUG)
 
-logger_authservice.info('X2Go Session Broker ({version}), written by {author}'.format(version=__VERSION__, author=__AUTHOR__))
-logger_authservice.info('Setting up the PAM authentication service\'s environment...')
-logger_authservice.info('  X2GOBROKER_DEBUG: {value}'.format(value=x2gobroker.defaults.X2GOBROKER_DEBUG))
-logger_authservice.info('  X2GOBROKER_AUTHSERVICE_SOCKET: {value}'.format(value=x2gobroker.defaults.X2GOBROKER_AUTHSERVICE_SOCKET))
+x2gobroker.authservice.logger_authservice.info('X2Go Session Broker ({version}), written by {author}'.format(version=__VERSION__, author=__AUTHOR__))
+x2gobroker.authservice.logger_authservice.info('Setting up the PAM authentication service\'s environment...')
+x2gobroker.authservice.logger_authservice.info('  X2GOBROKER_DEBUG: {value}'.format(value=x2gobroker.authservice.X2GOBROKER_DEBUG))
+x2gobroker.authservice.logger_authservice.info('  X2GOBROKER_AUTHSERVICE_SOCKET: {value}'.format(value=x2gobroker.authservice.X2GOBROKER_AUTHSERVICE_SOCKET))
 
 # check effective UID the broker runs as and complain appropriately...
 if os.geteuid() != 0:
-    logger_authservice.warn('X2Go Session Broker\'s PAM authentication service should run with root privileges to guarantee proper access to all PAM modules.')
+    x2gobroker.authservice.logger_authservice.warn('X2Go Session Broker\'s PAM authentication service should run with root privileges to guarantee proper access to all PAM modules.')
 
 if __name__ == '__main__':
 
diff --git a/x2gobroker/__init__.py b/x2gobroker/__init__.py
index 5ebaa35..f912e33 100644
--- a/x2gobroker/__init__.py
+++ b/x2gobroker/__init__.py
@@ -20,12 +20,3 @@
 
 __VERSION__ = '0.0.1.1'
 __AUTHOR__ = 'Mike Gabriel (X2Go Project) <mike.gabriel at das-netzwerkteam.de>'
-
-from loggers import logger_error
-
-class X2GoBrokerBaseException(BaseException):
-    def __init__(self, *args, **kwargs):
-        BaseException.__init__(self, *args, **kwargs)
-        logger_error.error('An exceptional problem occurred: {exception}("{msg}")'.format(exception=type(self).__name__, msg=str(self)))
-
-class X2GoBrokerAgentException(X2GoBrokerBaseException): pass
diff --git a/x2gobroker/agent.py b/x2gobroker/agent.py
index 001a800..35bb6a6 100644
--- a/x2gobroker/agent.py
+++ b/x2gobroker/agent.py
@@ -31,6 +31,7 @@ x2gobroker._paramiko.monkey_patch_paramiko()
 
 # X2Go Broker modules
 import x2gobroker.defaults
+import x2gobroker.x2gobroker_exceptions
 from x2gobroker.loggers import logger_broker, logger_error
 
 
@@ -83,7 +84,7 @@ def call_local_broker_agent(username, mode, cmdline_args=[]):
     if result[0].startswith('OK'):
         return [ r for r in result[1:] if r ]
 
-    raise x2gobroker.X2GoBrokerAgentException('Query to local X2Go Broker Agent failed with no response')
+    raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Query to local X2Go Broker Agent failed with no response')
 
 def call_remote_broker_agent(username, mode, cmdline_args=[], remote_agent=None):
     """\
@@ -135,7 +136,7 @@ def call_remote_broker_agent(username, mode, cmdline_args=[], remote_agent=None)
         if result and result[0].startswith('OK'):
             return [ r for r in result[1:] if r ]
     except (paramiko.SSHException, paramiko.AuthenticationException, paramiko.BadHostKeyException, socket.error):
-        raise x2gobroker.X2GoBrokerAgentException('Query to remote X2Go Broker Agent (user: {user}, hostname: {hostname}, port: {port}) failed'.format(user=remote_username, hostname=remote_hostname, port=remote_port))
+        raise x2gobroker.x2gobroker_exceptions.X2GoBrokerAgentException('Query to remote X2Go Broker Agent (user: {user}, hostname: {hostname}, port: {port}) failed'.format(user=remote_username, hostname=remote_hostname, port=remote_port))
 
 
 def list_sessions(username, query_mode='LOCAL', remote_agent=None):
diff --git a/x2gobroker/authservice.py b/x2gobroker/authservice.py
index df97435..0f97a29 100644
--- a/x2gobroker/authservice.py
+++ b/x2gobroker/authservice.py
@@ -24,22 +24,56 @@ import os
 import asyncore
 import pam
 import socket
+import getpass
+import logging
+import logging.config
 
 from pwd import getpwnam
 from grp import getgrnam
 
-# set up the broker's environment
-import x2gobroker.defaults
-
-from loggers import logger_authservice
-
-logger_authservice.info('X2Go Session Broker PAM Authentication Service: Setting up the broker\'s environment...')
+# normally this would go into defaults.py, however, we do not want to pull in defaults.py here as that will create
+# unwanted logfiles (access.log, broker.log, error.log) when x2gobroker-authservice is installed as standalone service
+if os.environ.has_key('X2GOBROKER_DEBUG'):
+    X2GOBROKER_DEBUG = ( os.environ['X2GOBROKER_DEBUG'].lower() in ('1', 'on', 'true', 'yes', ) )
+else:
+    X2GOBROKER_DEBUG = False
+if os.environ.has_key('X2GOBROKER_TESTSUITE'):
+    X2GOBROKER_TESTSUITE = ( os.environ['X2GOBROKER_TESTSUITE'].lower() in ('1', 'on', 'true', 'yes', ) )
+else:
+    X2GOBROKER_TESTSUITE = False
+if os.environ.has_key('X2GOBROKER_DAEMON_USER'):
+    X2GOBROKER_DAEMON_USER=os.environ['X2GOBROKER_DAEMON_USER']
+else:
+    X2GOBROKER_DAEMON_USER="x2gobroker"
+if os.environ.has_key('X2GOBROKER_AUTHSERVICE_LOGCONFIG'):
+    X2GOBROKER_AUTHSERVICE_LOGCONFIG=os.environ['X2GOBROKER_AUTHSERVICE_LOGCONFIG']
+else:
+    X2GOBROKER_AUTHSERVICE_LOGCONFIG="/etc/x2go/broker/x2gobroker-authservice-logger.conf"
 if os.environ.has_key('X2GOBROKER_AUTHSERVICE_SOCKET'):
     X2GOBROKER_AUTHSERVICE_SOCKET=os.environ['X2GOBROKER_AUTHSERVICE_SOCKET']
 else:
     X2GOBROKER_AUTHSERVICE_SOCKET="/run/x2gobroker/x2gobroker-authservice.socket"
-logger_authservice.info('  X2GOBROKER_AUTHSERVICE_SOCKET: {value}'.format(value=X2GOBROKER_AUTHSERVICE_SOCKET))
 
+# standalone daemon mode (x2gobroker-authservice as daemon) or interactive mode (called from the cmdline)?
+if getpass.getuser() in (X2GOBROKER_DAEMON_USER, 'root'):
+
+    # we run in standalone daemon mode, so let's use the system configuration for logging
+    logging.config.fileConfig(X2GOBROKER_AUTHSERVICE_LOGCONFIG)
+
+    # create authservice logger
+    logger_authservice = logging.getLogger('authservice')
+
+else:
+    logger_root = logging.getLogger()
+    stderr_handler = logging.StreamHandler(sys.stderr)
+    stderr_handler.setFormatter(logging.Formatter(fmt='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt=''))
+
+    # all loggers stream to stderr...
+    logger_root.addHandler(stderr_handler)
+
+    logger_authservice = logging.getLogger('authservice')
+    logger_authservice.addHandler(stderr_handler)
+    logger_authservice.propagate = 0
 
 class AuthClient(asyncore.dispatcher_with_send):
 
@@ -91,7 +125,9 @@ def loop():
 
 def authenticate(username, password, service="x2gobroker"):
     s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    logger_authservice.debug('connecting to authentication service socket {socket}'.format(socket=X2GOBROKER_AUTHSERVICE_SOCKET))
     s.connect(X2GOBROKER_AUTHSERVICE_SOCKET)
+    logger_authservice.debug('sending username={username}, password=<hidden>, service={service} to authentication service'.format(username=username, service=service))
     s.send('{username} {password} {service}\n'.format(username=username, password=password, service=service))
     result = s.recv(1024)
     s.close()
diff --git a/x2gobroker/brokers/base_broker.py b/x2gobroker/brokers/base_broker.py
index 76ed8ef..365ce0b 100644
--- a/x2gobroker/brokers/base_broker.py
+++ b/x2gobroker/brokers/base_broker.py
@@ -715,6 +715,9 @@ class X2GoBroker(object):
 
         access = False
         access = self._do_authenticate(username=username, password=password)
+        if not access and "@" in username:
+            _username = username.split('@')[0]
+            access = self._do_authenticate(username=_username, password=password)
         logger_broker.debug('base_broker.X2GoBroker.check_access(): result of authentication check is: {access}'.format(access=access))
 
         ### HANDLING OF DYNAMIC AUTHENTICATION ID HASHES
diff --git a/x2gobroker/brokers/zeroconf_broker.py b/x2gobroker/brokers/zeroconf_broker.py
index 5970659..6cb83ad 100644
--- a/x2gobroker/brokers/zeroconf_broker.py
+++ b/x2gobroker/brokers/zeroconf_broker.py
@@ -36,7 +36,7 @@ class X2GoBroker(base.X2GoBroker):
 
     def list_profiles(self, username):
 
-        list_of_profiles = {
+        _list_of_profiles = {
             uuid.uuid4(): {
                 'user': u'',
                 'defsndport': True,
@@ -74,6 +74,11 @@ class X2GoBroker(base.X2GoBroker):
                 'pack': u'16m-jpeg',
             },
         }
+        list_of_profiles = {}
+        for profile_id in _list_of_profiles.keys():
+            profile = self.get_profile_defaults()
+            profile.update(_list_of_profiles[profile_id])
+            list_of_profiles[profile_id] = profile
         return list_of_profiles
 
     def select_session(self, profile_id, username=None):
diff --git a/x2gobroker/defaults.py b/x2gobroker/defaults.py
index ee5d7f8..d734cc6 100644
--- a/x2gobroker/defaults.py
+++ b/x2gobroker/defaults.py
@@ -118,6 +118,8 @@ X2GOBROKER_CONFIG_DEFAULTS = {
         u'use-static-cookie': False,
         u'my-cookie': uuid.uuid4(),
         u'enable-plain-output': True,
+        u'enable-uccs-output': False,
+        u'my-uccs-url-base': 'http://localhost:8080/',
         u'enable-json-output': False,
         u'enable-html-output':  False,
         u'default-auth-mech': u'pam',
@@ -160,6 +162,7 @@ X2GOBROKER_CONFIG_DEFAULTS = {
 # defaults for X2Go Sessino Broker session profiles file
 X2GOBROKER_SESSIONPROFILE_DEFAULTS = {
     u'DEFAULT': {
+        u'command': u'TERMINAL',
         u'defsndport': True,
         u'useiconv': False,
         u'iconvfrom': u'UTF-8',
@@ -183,7 +186,7 @@ X2GOBROKER_SESSIONPROFILE_DEFAULTS = {
         u'multidisp': False,
         u'sshproxyport': 22,
         u'sound': True,
-        u'rootless': False,
+        u'rootless': True,
         u'iconvto': u'UTF-8',
         u'soundtunnel': True,
         u'dpi': 96,
@@ -192,6 +195,7 @@ X2GOBROKER_SESSIONPROFILE_DEFAULTS = {
         u'pack': u'16m-jpeg',
         u'user': '',
         u'host': [ u'localhost', ],
+        u'directrdp': False,
         u'acl-users-allow': [],
         u'acl-users-deny': [],
         u'acl-users-order': '',
diff --git a/x2gobroker/loggers.py b/x2gobroker/loggers.py
index e7eabe0..2d0963c 100644
--- a/x2gobroker/loggers.py
+++ b/x2gobroker/loggers.py
@@ -43,7 +43,6 @@ if getpass.getuser() in (X2GOBROKER_DAEMON_USER, 'root'):
 
     # create loggers
     logger_broker = logging.getLogger('broker')
-    logger_authservice = logging.getLogger('authservice')
     logger_access = logging.getLogger('access')
     logger_error = logging.getLogger('error')
 
@@ -59,10 +58,6 @@ else:
     logger_broker.addHandler(stderr_handler)
     logger_broker.propagate = 0
 
-    logger_authservice = logging.getLogger('authservice')
-    logger_authservice.addHandler(stderr_handler)
-    logger_authservice.propagate = 0
-
     logger_access = logging.getLogger('access')
     logger_access.addHandler(stderr_handler)
     logger_access.propagate = 0
diff --git a/x2gobroker/tests/test_broker_base.py b/x2gobroker/tests/test_broker_base.py
index 0bda18e..1371724 100644
--- a/x2gobroker/tests/test_broker_base.py
+++ b/x2gobroker/tests/test_broker_base.py
@@ -274,6 +274,7 @@ check-credentials = false
     def test_getdefaultprofile(self):
         base_backend = self._init_base_backend()
         _expected_profile = {
+            'command': 'TERMINAL',
             'defsndport': True,
             'useiconv': False,
             'iconvfrom': 'UTF-8',
@@ -297,7 +298,7 @@ check-credentials = false
             'multidisp': False,
             'sshproxyport': 22,
             'sound': True,
-            'rootless': False,
+            'rootless': True,
             'iconvto': 'UTF-8',
             'soundtunnel': True,
             'dpi': 96,
@@ -306,6 +307,7 @@ check-credentials = false
             'pack': '16m-jpeg',
             'user': '',
             'host': [u'localhost'],
+            'directrdp': False,
         }
         _profile = base_backend.get_profile_defaults()
         self.assertEqual(len(_expected_profile.keys()), len(_profile.keys()))
diff --git a/x2gobroker/tests/test_broker_inifile.py b/x2gobroker/tests/test_broker_inifile.py
index 35b4289..6bc62f8 100644
--- a/x2gobroker/tests/test_broker_inifile.py
+++ b/x2gobroker/tests/test_broker_inifile.py
@@ -47,6 +47,96 @@ class TestX2GoBrokerBackendInifile(unittest.TestCase):
         for _profile_id in _profile_ids:
             self.assertTrue( ( 'default' not in inifile_backend.get_profile(_profile_id).keys() ) )
 
+    # TEST COMPLETION OF DEFAULTS FROM CODE IN defaults.py
+
+    def test_getprofilecompletion(self):
+        _session_profiles = """
+[DEFAULT]
+exports =
+fullscreen = false
+width = 800
+height = 600
+applications = TERMINAL, WWWBROWSER
+
+[testprofile]
+user = foo
+command = GNOME
+
+"""
+        tf = tempfile.NamedTemporaryFile()
+        print >> tf, _session_profiles
+        tf.seek(0)
+        inifile_backend = inifile.X2GoBroker(profile_config_file=tf.name)
+        _expected_defaults = copy.deepcopy(x2gobroker.defaults.X2GOBROKER_SESSIONPROFILE_DEFAULTS['DEFAULT'])
+        for key in copy.deepcopy(_expected_defaults).keys():
+            if key.startswith('acl-'):
+                del _expected_defaults[key]
+        _expected_defaults.update( {
+            u'exports': '',
+            u'fullscreen': False,
+            u'width': 800,
+            u'height': 600,
+            u'applications': ['TERMINAL','WWWBROWSER',],
+            u'user': 'foo',
+            u'command': 'GNOME',
+        } )
+        # just testing the directrdp hard-coded defaults
+        _expected_defaults.update( {
+            u'directrdp': False,
+        } )
+        _expected_profile = copy.deepcopy(_expected_defaults)
+        _profile = inifile_backend.get_profile('testprofile')
+        print _expected_defaults
+        for key in _expected_profile.keys():
+            self.assertTrue( ( key in _profile.keys() ) )
+        for key in _profile.keys():
+            self.assertTrue( ( key in _expected_profile.keys()  and _profile[key] == _expected_profile[key] ) )
+
+    # TEST COMPLETION OF DEFAULTS FROM CODE IN defaults.py
+
+    def test_getprofilecompletion(self):
+        _session_profiles = """
+[DEFAULT]
+exports =
+fullscreen = false
+width = 800
+height = 600
+applications = TERMINAL, WWWBROWSER
+
+[testprofile]
+user = foo
+command = GNOME
+
+"""
+        tf = tempfile.NamedTemporaryFile()
+        print >> tf, _session_profiles
+        tf.seek(0)
+        inifile_backend = inifile.X2GoBroker(profile_config_file=tf.name)
+        _expected_defaults = copy.deepcopy(x2gobroker.defaults.X2GOBROKER_SESSIONPROFILE_DEFAULTS['DEFAULT'])
+        for key in copy.deepcopy(_expected_defaults).keys():
+            if key.startswith('acl-'):
+                del _expected_defaults[key]
+        _expected_defaults.update( {
+            u'exports': '',
+            u'fullscreen': False,
+            u'width': 800,
+            u'height': 600,
+            u'applications': ['TERMINAL','WWWBROWSER',],
+            u'user': 'foo',
+            u'command': 'GNOME',
+        } )
+        # just testing the directrdp hard-coded defaults
+        _expected_defaults.update( {
+            u'directrdp': False,
+        } )
+        _expected_profile = copy.deepcopy(_expected_defaults)
+        _profile = inifile_backend.get_profile('testprofile')
+        for key in _expected_profile.keys():
+            self.assertTrue( ( key in _profile.keys() ) )
+        for key in _profile.keys():
+            self.assertTrue( ( key in _expected_profile.keys()  and _profile[key] == _expected_profile[key] ) )
+
+
     ### TEST SESSION PROFILES: get_profile_defaults()
 
     def test_getprofiledefaults(self):
@@ -74,16 +164,16 @@ applications = TERMINAL, WWWBROWSER
 
 [testprofile1]
 user = foo
-cmd = GNOME
+command = GNOME
 
 [testprofile2]
 user = bar
-cmd = KDE
+command = KDE
 fullscreen = true
 
 [testprofile3]
 user = bar
-cmd = KDE
+command = KDE
 fullscreen = true
 acl-users-deny = ALL
 acl-users-allow = foo,bar
@@ -102,23 +192,23 @@ acl-users-order = deny-allow
             u'fullscreen': False,
             u'width': 800,
             u'height': 600,
-            u'applications': ['TERMINAL','WWWBROWSER',]
+            u'applications': ['TERMINAL','WWWBROWSER',],
         } )
         _expected_profile1 = copy.deepcopy(_expected_defaults)
         _expected_profile1.update({
             u'user': 'foo',
-            u'cmd': 'GNOME',
+            u'command': 'GNOME',
         })
         _expected_profile2 = copy.deepcopy(_expected_defaults)
         _expected_profile2.update({
             u'user': 'bar',
-            u'cmd': 'KDE',
+            u'command': 'KDE',
             u'fullscreen': True,
         })
         _expected_profile3 = copy.deepcopy(_expected_defaults)
         _expected_profile3.update({
             u'user': 'bar',
-            u'cmd': 'KDE',
+            u'command': 'KDE',
             u'fullscreen': True,
         })
         _profile1 = inifile_backend.get_profile('testprofile1')
@@ -154,16 +244,16 @@ acl-clients-allow = 10.0.0.0/16,10.1.0.0/16,admin-1.intern,admin-2.intern
 
 [testprofile1]
 user = foo
-cmd = GNOME
+command = GNOME
 
 [testprofile2]
 user = foo
-cmd = GNOME
+command = GNOME
 acl-clients-deny = 10.0.2.0/24,ALL
 
 [testprofile3]
 user = bar
-cmd = KDE
+command = KDE
 fullscreen = true
 acl-users-deny = ALL
 acl-users-allow = foo,bar
@@ -223,15 +313,15 @@ applications = TERMINAL, WWWBROWSER
 
 [testprofile1]
 user =
-cmd = GNOME
+command = GNOME
 
 [testprofile2]
 user =
-cmd = XFCE
+command = XFCE
 
 [testprofile3]
 user =
-cmd = KDE
+command = KDE
 fullscreen = true
 """
         tf = tempfile.NamedTemporaryFile()
@@ -273,21 +363,21 @@ acl-groups-order = deny-allow
 
 [testprofile1]
 user =
-cmd = GNOME
+command = GNOME
 acl-users-allow = flip
 acl-users-deny = ALL
 acl-users-order = deny-allow
 
 [testprofile2]
 user =
-cmd = XFCE
+command = XFCE
 acl-users-allow = thekla
 acl-users-deny = ALL
 acl-users-order = deny-allow
 
 [testprofile3]
 user =
-cmd = KDE
+command = KDE
 fullscreen = true
 acl-users-deny = willi
 acl-users-order = deny-allow
@@ -302,40 +392,40 @@ acl-users-order = deny-allow
         list_of_profile_ids = list_of_profiles.keys()
         list_of_profile_ids.sort()
         self.assertEqual(list_of_profile_ids, ['testprofile1'])
-        self.assertEqual(list_of_profiles['testprofile1']['cmd'], 'GNOME')
+        self.assertEqual(list_of_profiles['testprofile1']['command'], 'GNOME')
 
         username_m = 'maja'
         list_of_profiles = inifile_backend.list_profiles(username_m)
         list_of_profile_ids = list_of_profiles.keys()
         list_of_profile_ids.sort()
         self.assertEqual(list_of_profile_ids, ['testprofile1', 'testprofile2', 'testprofile3'])
-        self.assertEqual(list_of_profiles['testprofile1']['cmd'], 'GNOME')
-        self.assertEqual(list_of_profiles['testprofile2']['cmd'], 'XFCE')
-        self.assertEqual(list_of_profiles['testprofile3']['cmd'], 'KDE')
+        self.assertEqual(list_of_profiles['testprofile1']['command'], 'GNOME')
+        self.assertEqual(list_of_profiles['testprofile2']['command'], 'XFCE')
+        self.assertEqual(list_of_profiles['testprofile3']['command'], 'KDE')
 
         username_k = 'kassandra'
         list_of_profiles = inifile_backend.list_profiles(username_k)
         list_of_profile_ids = list_of_profiles.keys()
         list_of_profile_ids.sort()
         self.assertEqual(list_of_profile_ids, ['testprofile1', 'testprofile2', 'testprofile3'])
-        self.assertEqual(list_of_profiles['testprofile1']['cmd'], 'GNOME')
-        self.assertEqual(list_of_profiles['testprofile2']['cmd'], 'XFCE')
-        self.assertEqual(list_of_profiles['testprofile3']['cmd'], 'KDE')
+        self.assertEqual(list_of_profiles['testprofile1']['command'], 'GNOME')
+        self.assertEqual(list_of_profiles['testprofile2']['command'], 'XFCE')
+        self.assertEqual(list_of_profiles['testprofile3']['command'], 'KDE')
 
         username_t = 'thekla'
         list_of_profiles = inifile_backend.list_profiles(username_t)
         list_of_profile_ids = list_of_profiles.keys()
         list_of_profile_ids.sort()
         self.assertEqual(list_of_profile_ids, ['testprofile2'])
-        self.assertEqual(list_of_profiles['testprofile2']['cmd'], 'XFCE')
+        self.assertEqual(list_of_profiles['testprofile2']['command'], 'XFCE')
 
         username_w = 'willi'
         list_of_profiles = inifile_backend.list_profiles(username_w)
         list_of_profile_ids = list_of_profiles.keys()
         list_of_profile_ids.sort()
         self.assertEqual(list_of_profile_ids, ['testprofile1', 'testprofile2'])
-        self.assertEqual(list_of_profiles['testprofile1']['cmd'], 'GNOME')
-        self.assertEqual(list_of_profiles['testprofile2']['cmd'], 'XFCE')
+        self.assertEqual(list_of_profiles['testprofile1']['command'], 'GNOME')
+        self.assertEqual(list_of_profiles['testprofile2']['command'], 'XFCE')
 
     ### TEST: select_session() method
 
diff --git a/x2gobroker/tests/test_broker_zeroconf.py b/x2gobroker/tests/test_broker_zeroconf.py
index 0e97b66..485e8bd 100644
--- a/x2gobroker/tests/test_broker_zeroconf.py
+++ b/x2gobroker/tests/test_broker_zeroconf.py
@@ -63,6 +63,8 @@ class TestX2GoBrokerBackendZeroconf(unittest.TestCase):
                 'sshport': 22,
                 'setdpi': 0,
                 'pack': u'16m-jpeg',
+                # make sure, hard-coded defaults end up in the list_profiles() output of the zeroconf backend, as well
+                'directrdp': False,
             },
         }
         zeroconf_backend = x2gobroker.brokers.zeroconf_broker.X2GoBroker()
diff --git a/x2gobroker/tests/test_web_plain_zeroconf.py b/x2gobroker/tests/test_web_plain_zeroconf.py
index dad829b..8b98daf 100644
--- a/x2gobroker/tests/test_web_plain_zeroconf.py
+++ b/x2gobroker/tests/test_web_plain_zeroconf.py
@@ -52,11 +52,10 @@ desktop-shell = KDE
         r.mustcontain('START_USER_SESSIONS')
         r.mustcontain('command=KDE')
         r.mustcontain('END_USER_SESSIONS')
-        # FIXME: get html tags out of the text/plain web renderer, needs patching of X2Go Client
-        #r.mustcontain(no='<BR>',)
-        #r.mustcontain(no='<br>',)
-        #r.mustcontain(no='<BR />', )
-        #r.mustcontain(no='<br />', )
+        r.mustcontain(no='<BR>',)
+        r.mustcontain(no='<br>',)
+        r.mustcontain(no='<BR />', )
+        r.mustcontain(no='<br />', )
         tf.close()
         _config = """
 [zeroconf]
diff --git a/x2gobroker/tests/test_web_uccs_zeroconf.py b/x2gobroker/tests/test_web_uccs_zeroconf.py
new file mode 100644
index 0000000..6c5d2b5
--- /dev/null
+++ b/x2gobroker/tests/test_web_uccs_zeroconf.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2012 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
+#
+# X2Go Session Broker is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# X2Go Session Broker 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+import unittest
+import tempfile
+from paste.fixture import TestApp
+from nose.tools import *
+import tornado.wsgi
+import json
+
+# Python X2GoBroker modules
+import x2gobroker.defaults
+import x2gobroker.web.uccs
+
+urls = ( ('/uccs/(.*)', x2gobroker.web.uccs.X2GoBrokerWeb,) ,)
+application = tornado.wsgi.WSGIApplication(urls)
+
+class TestX2GoBrokerWebUccsZeroConf(unittest.TestCase):
+
+    ### TEST TASK: listsessions (you can influence the session command via the X2Go Broker's configurationfile)
+
+    def test_listsessions(self):
+        _expected_result = {
+            u'URL': u'http://localhost:8080/uccs/zeroconf',
+            u'AdditionalManagementServers': [],
+            u'Name': u'X2Go Session Broker',
+            u'RemoteDesktopServers': [
+                {
+                    u'Username': u'',
+                    u'Protocol': u'x2go',
+                    u'Name': u'LOCALHOST',
+                    u'URL': u'localhost:22',
+                    u'SessionTypeRequired': True,
+                    u'Password': None
+                },
+            ],
+        }
+        _config = """
+[global]
+enable-uccs-output=true
+
+[zeroconf]
+enable = true
+auth-mech = testsuite
+desktop-shell = KDE
+"""
+        tf = tempfile.NamedTemporaryFile()
+        print >> tf, _config
+        tf.seek(0)
+        x2gobroker.defaults.X2GOBROKER_CONFIG = tf.name
+        testApp = TestApp(application)
+        r = testApp.get('/uccs/zeroconf/', params={'user': 'test', 'password': 'sweet',  'task': 'listsessions', }, expect_errors=True)
+        assert_equal(r.status, 200)
+        body = r.normal_body
+        result = json.loads(body)
+        self.assertEqual(_expected_result, result)
+        tf.close()
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestX2GoBrokerWebUccsZeroConf))
+    return suite
diff --git a/x2gobroker/uccsjson.py b/x2gobroker/uccsjson.py
new file mode 100644
index 0000000..efbbc32
--- /dev/null
+++ b/x2gobroker/uccsjson.py
@@ -0,0 +1,241 @@
+# Copyright (C) 2012 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
+# Copyright (C) 2012 by Oleksandr Shneyder <oleksandr.shneyder at obviously-nice.de>
+# Copyright (C) 2012 by Heinz-Markus Graesing <heinz-m.graesing at obviously-nice.de>
+#
+# X2Go Session Broker is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# X2Go Session Broker 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+import json
+
+def convert_to_builtin_type(obj):
+    """\
+    Helper function for converting Python objects to dictionaries.
+    Used for doing JSON dumps.
+
+    """
+    d = { }
+    d.update(obj.__dict__)
+    return d
+
+class ManagementServer():
+    """\
+    Base class for generating UCCS compatible JSON object.
+
+    """
+    def __init__(self, url, name):
+        """\
+        Initializ instance.
+
+        @param url: URL of the UCCS broker server
+        @type url: C{unicode}
+        @param name: human-readable, descriptive server name
+        @type name: C{unicode}
+
+        """
+        self.RemoteDesktopServers = []
+        self.AdditionalManagementServers = []
+        self.URL = url
+        self.Name = name
+
+    def set_default(self, ts_name):
+        """\
+        Define the default (terminal) server instance.
+
+        @param ts_name: name of the terminal server that is to be set as default
+        @type ts_name: C{unicode}
+
+        """
+        if isinstance(tsName, str):
+            self.DefaultServer = tsName
+        else:
+            raise TypeError("set_default expects a string argument")
+
+    def add_terminalserver(self, server):
+        """\
+        Add a terminal server to this management server object.
+
+        @param server: instance of class L{RDPServer} or L{X2GoServer}.
+        @type server: C{obj}
+
+        """
+        self.RemoteDesktopServers.append(server)
+
+    # NOT USED!!!
+    #def add_additional_management_server(self, amserver):
+    #    if isinstance(amserver, AdditionalManagementServer):
+    #        self.AdditionalManagementServers.append(amserver)
+    #    else:
+    #        raise TypeError("add_additional_management_server expects a "\
+    #            "AdditionalManagementServer argument")
+
+    def toJson(self):
+        """\
+        Dump this instance as JSON object.
+
+        """
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
+
+
+# NOT USED!!!
+#class AdditionalManagementServer():
+#    def __init__(self, url, name):
+#        self.URL = url
+#        self.Name = name
+
+
+class RDPServer():
+    """\
+    Instantiate a UCCS compatible RDP server session profile object.
+
+    """
+    def __init__(self, host, name, username=None, password=None):
+        """\
+        @param host: hostname of RDP server host
+        @type host: C{unicode}
+        @param name: session profile name
+        @type name: C{unicode}
+        @param username: username to be used for login
+        @type username: C{unicode}
+        @param password: password to be used for login
+        @type password: C{unicode}
+
+        """
+        self.URL = unicode(host)
+        self.Name = unicode(name)
+        self.Protocol = u'freerdp'
+        self.DomainRequired = unicode(True)
+        self.Username = unicode(username)
+        self.Password = unicode(password)
+
+    def set_domain(self, domain):
+        """\
+        Set the domain for this RDP server.
+
+        @param domain: the domain name to be set
+        @type domain: C{unicode}
+
+        @raise TypeError: domain has to be C{str} or C{unicode}
+
+        """
+        if isinstance(domain, str):
+            self.WindowsDomain = unicode(domain)
+        elif isinstance(domain, unicode):
+            self.WindowsDomain = domain
+        else:
+            raise TypeError("set_domain() expects a string or unicode argument")
+
+    def toJson(self):
+        """\
+        Dump this instance as JSON object.
+
+        """
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
+
+
+class ICAServer():
+    """\
+    Instantiate a UCCS compatible ICA server session profile object.
+
+    """
+    def __init__(self, host, name, username=None, password=None):
+        """\
+        @param host: hostname of ICA server host
+        @type host: C{unicode}
+        @param name: session profile name
+        @type name: C{unicode}
+        @param username: username to be used for login
+        @type username: C{unicode}
+        @param password: password to be used for login
+        @type password: C{unicode}
+
+        """
+        self.URL = unicode(host)
+        self.Name = unicode(name)
+        self.Protocol = u'ica'
+        self.DomainRequired = unicode(True)
+        self.Username = unicode(username)
+        self.Password = unicode(password)
+
+    def set_domain(self, domain):
+        """\
+        Set the domain for this ICA server.
+
+        @param domain: the domain name to be set
+        @type domain: C{unicode}
+
+        @raise TypeError: domain has to be C{str} or C{unicode}
+
+        """
+        if isinstance(domain, str):
+            self.WindowsDomain = unicode(domain)
+        elif isinstance(domain, unicode):
+            self.WindowsDomain = domain
+        else:
+            raise TypeError("set_domain() expects a string or unicode argument")
+
+    def toJson(self):
+        """\
+        Dump this instance as JSON object.
+
+        """
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
+
+
+class X2GoServer():
+    """\
+    Instantiate a UCCS compatible X2Go Server session profile object.
+
+    """
+    def __init__(self, host, name, username=None, password=None):
+        """\
+        @param host: hostname of X2Go Server host
+        @type host: C{unicode}
+        @param name: session profile name
+        @type name: C{unicode}
+        @param username: username to be used for login
+        @type username: C{unicode}
+        @param password: password to be used for login
+        @type password: C{unicode}
+
+        """
+        self.URL = unicode(host)
+        self.Name = unicode(name)
+        self.Protocol = u'x2go'
+        self.SessionTypeRequired = True
+        self.Username = unicode(username)
+        self.Password = unicode(password)
+
+    def set_session_type(self, session_type):
+        """\
+        Set the session type to be used with this X2Go Server.
+
+        @param session_type: the session type to be set
+        @type session_type: C{unicode}
+
+        @raise TypeError: session_type has to be C{str} or C{unicode}
+
+        """
+        if isinstance(session_type, str):
+            self.SessionType = session_type
+        else:
+            raise TypeError("set_session_type() expects a string or unicode argument")
+
+    def toJson(self):
+        """\
+        Dump this instance as JSON object.
+
+        """
+        return json.dumps(self, default=convert_to_builtin_type, sort_keys=True, indent=4)
+
diff --git a/x2gobroker/web/uccs.py b/x2gobroker/web/uccs.py
new file mode 100644
index 0000000..db59f24
--- /dev/null
+++ b/x2gobroker/web/uccs.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+
+# This file is part of the  X2Go Project - http://www.x2go.org
+# Copyright (C) 2011-2012 by Oleksandr Shneyder <oleksandr.shneyder at obviously-nice.de>
+# Copyright (C) 2011-2012 by Heinz-Markus Graesing <heinz-m.graesing at obviously-nice.de>
+# Copyright (C) 2012 by Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
+#
+# X2Go Session Broker is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# X2Go Session Broker 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# modules
+import types
+import re
+import base64
+import tornado.web
+from tornado.escape import native_str, parse_qs_bytes
+
+# Python X2Go Broker modules
+import x2gobroker.defaults
+
+from x2gobroker.loggers import logger_broker, logger_error
+import x2gobroker.uccsjson
+
+def require_basic_auth(realm, validate_callback):
+    def require_basic_auth_decorator(handler_class):
+        def wrap_execute(handler_execute):
+            def require_basic_auth(handler, kwargs):
+                def create_auth_header():
+                    handler.set_status(401)
+                    handler.set_header('WWW-Authenticate', 'Basic realm="{realm}"'.format(realm=realm))
+                    handler._transforms = []
+                    handler.finish()
+
+                auth_header = handler.request.headers.get('Authorization')
+                if auth_header is None or not auth_header.startswith('Basic '):
+                    create_auth_header()
+                else:
+                    auth_decoded = base64.decodestring(auth_header[6:])
+                    kwargs['basicauth_user'], kwargs['basicauth_pass'] = [ unicode(s) for s in auth_decoded.split(':', 2) ]
+                    if validate_callback(handler_class, kwargs['basicauth_user'], kwargs['basicauth_pass']):
+                        return True
+                    else:
+                        create_auth_header()
+            def _execute(self, transforms, *args, **kwargs):
+                if not require_basic_auth(self, kwargs):
+                    return False
+                return handler_execute(self, transforms, *args, **kwargs)
+            return _execute
+
+        handler_class._execute = wrap_execute(handler_class._execute)
+        return handler_class
+    return require_basic_auth_decorator
+
+
+def credentials_validate(handler_class, username, password):
+    import x2gobroker.brokers.base_broker
+    # FIXME: with the below hack, the backend broker detection in X2GoBrokerWeb is disabled, only global options
+    #        from x2gobroker.conf are available here...
+    return x2gobroker.brokers.base_broker.X2GoBroker().check_access(username=username, password=password)
+
+
+ at require_basic_auth('Authentication required', credentials_validate)
+class X2GoBrokerWeb(tornado.web.RequestHandler):
+
+    http_header_items = {
+        'Content-Type': 'text/plain; charset=utf-8',
+        'Expires': '+1h',
+    }
+
+    def _gen_http_header(self):
+
+        for http_header_item in self.http_header_items.keys():
+            self.set_header(http_header_item, self.http_header_items[http_header_item])
+
+    def get(self, backend, basicauth_user, basicauth_pass):
+        if x2gobroker.defaults.X2GOBROKER_DEBUG:
+            self._gen_http_header()
+            logger_broker.warn('GET http request detected, if unwanted: disable X2GOBROKER_DEBUG')
+            return self.head(backend, basicauth_user, basicauth_pass)
+        raise tornado.web.HTTPError(404)
+
+    def head(self, backend, basicauth_user, basicauth_pass):
+
+        if not backend:
+            backend = x2gobroker.defaults.X2GOBROKER_DEFAULT_BACKEND
+        else:
+            backend = backend.rstrip('/')
+
+        api_version = 4
+        if re.match('.*/api/[0-9].*', backend):
+            # get the first and the third item as backend, api_version
+            backend, api_version = backend.split('/')[:3:2]
+            api_version = int(api_version)
+
+        try:
+            # dynamically detect broker backend from given URL
+            exec("import x2gobroker.brokers.{backend}_broker".format(backend=backend))
+            exec("self.broker_backend = x2gobroker.brokers.{backend}_broker.X2GoBroker()".format(backend=backend))
+        except ImportError:
+            # throw a 404 if the backend does not exist
+            raise tornado.web.HTTPError(404)
+
+        global_config = self.broker_backend.get_global_config()
+
+        # if the broker backend is disabled in the configuration, pretend to have nothing on offer
+        if not self.broker_backend.is_enabled():
+            raise tornado.web.HTTPError(404)
+
+        # set the client address for the broker backend
+        ip = self.request.remote_ip
+        if ip:
+            logger_broker.info('client address is {address}'.format(address=ip))
+            self.broker_backend.set_client_address(ip)
+        elif not x2gobroker.defaults.X2GOBROKER_DEBUG:
+            # if the client IP is not set, we pretend to have nothing on offer
+            logger_error.error('client could not provide an IP address, pretending: 404 Not Found')
+            raise tornado.web.HTTPError(404)
+
+        username, password = basicauth_user, basicauth_pass
+        cookie = ''
+
+        output = ''
+
+        logger_broker.debug ('Authenticated as username: {username}, with password: <hidden>'.format(username=username))
+
+        ###
+        ### CONFIRM SUCCESSFUL AUTHENTICATION FIRST
+        ###
+
+        profiles = self.broker_backend.list_profiles(username)
+        urlbase = self.broker_backend.get_global_value('my-uccs-url-base').rstrip('/')
+        ms = x2gobroker.uccsjson.ManagementServer('{urlbase}/uccs/{backend}'.format(urlbase=urlbase, backend=backend), 'X2Go Session Broker')
+
+        profile_ids = profiles.keys()
+        profile_ids.sort()
+
+        for profile_id in profile_ids:
+
+            if profiles[profile_id][u'directrdp']:
+                pass
+            else:
+                ts = x2gobroker.uccsjson.X2GoServer(
+                        host='{hostname}:{port}'.format(hostname=profiles[profile_id][u'host'], port=profiles[profile_id][u'sshport']),
+                        name=profiles[profile_id][u'name'],
+                        username=profiles[profile_id][u'user'],
+                )
+            ms.add_terminalserver(ts)
+
+        output += ms.toJson()
+
+        self.write(output)
+        return
+
diff --git a/x2gobroker/__init__.py b/x2gobroker/x2gobroker_exceptions.py
similarity index 100%
copy from x2gobroker/__init__.py
copy to x2gobroker/x2gobroker_exceptions.py


hooks/post-receive
-- 
x2gobroker.git (HTTP(S) Session broker for X2Go)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "x2gobroker.git" (HTTP(S) Session broker for X2Go).




More information about the x2go-commits mailing list