[X2Go-Commits] pyhoca-gui.git - build-59a18b6e3b5d3f1dd8f07f26433d37fe5984a57d (branch) updated: 66a75dce88b6ea0d3a5e38d2beab3dcb3eddb46e
X2Go dev team
git-admin at x2go.org
Tue Aug 27 13:20:32 CEST 2013
The branch, build-59a18b6e3b5d3f1dd8f07f26433d37fe5984a57d has been updated
via 66a75dce88b6ea0d3a5e38d2beab3dcb3eddb46e (commit)
from 04ed83455e600017764b185eeb5eda65220b9432 (commit)
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:
SessionProfile.py | 251 ++++++++++++++++++++++++++++
pyhoca-gui.py | 145 +++++++++++++++++
pyx2go_client.py | 313 +++++++++++++++++++++++++++++++++++
x2go | 1 +
x2goLogon.py | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1181 insertions(+)
create mode 100644 SessionProfile.py
create mode 100644 pyhoca-gui.py
create mode 100644 pyx2go_client.py
create mode 120000 x2go
create mode 100644 x2goLogon.py
The diff of changes is:
diff --git a/SessionProfile.py b/SessionProfile.py
new file mode 100644
index 0000000..48e2844
--- /dev/null
+++ b/SessionProfile.py
@@ -0,0 +1,251 @@
+# -*- coding: utf-8 -*-
+#-----------------------------------------------------------------------------
+# Name: SessionProfile.py
+# Purpose: Define the session info coming from an ini file
+#
+# Author: Dick Kniep
+#
+# Created: 2010/10/21
+# RCS-ID: $Id: SessionProfile.py,v 1.2 2010/10/21 20:07:56 dick Exp $
+# Copyright: (c) 2010 Lindix
+#-----------------------------------------------------------------------------
+
+import os
+import ConfigParser
+from types import *
+
+class processINI:
+ """
+ Base class to process the different ini files used in x2go.
+ Primarily used to standardize the content of the
+ ini file.
+ If entries are omitted in the file, they are filled with
+ default values, so the resulting objects always contain
+ the same fields
+ """
+ def __init__(self, fileName):
+ self.writeconfig = False
+ self.iniConfig = ConfigParser.SafeConfigParser()
+ if fileName and os.path.exists(fileName):
+ self.iniConfig.read(fileName)
+
+
+ def fillDefaultsSection(self):
+ for section, sectionvalue in self.defaultValues.items():
+ for key, value in sectionvalue.items():
+ if self.iniConfig.has_option(section,key): continue
+ if not self.iniConfig.has_section(section):
+ self.iniConfig.add_section(section)
+ self.storeValueTypes(section, key, value)
+
+ def updValue(self, section, key, value):
+ if not self.iniConfig.has_section(section):
+ self.iniConfig.add_section(section)
+ self.storeValueTypes(section, key, value)
+ self.writeconfig = True
+
+ def storeValueTypes(self, section, key, value):
+ if type(value) is StringType:
+ self.iniConfig.set(section,key,value)
+ elif type(value) is BooleanType:
+ if value:
+ self.iniConfig.set(section,key,'1')
+ else:
+ self.iniConfig.set(section,key,'0')
+ else:
+ self.iniConfig.set(section,key,str(value))
+
+ def writeIni(self):
+ if self.writeconfig:
+ fd = open(self.fileName, 'wb')
+ self.iniConfig.write(fd)
+ fd.close()
+ self.writeconfig = False
+
+ def getValue(self, section, key, getType=None):
+ if self.iniConfig.has_option(section, key):
+ if getType is None:
+ return self.iniConfig.get(section, key)
+ elif getType is BooleanType:
+ return self.iniConfig.getboolean(section, key)
+ elif getType is IntType:
+ return self.iniConfig.getint(section, key)
+
+ def bldSessionObj(self):
+ """
+ This routine flattens the items making them simple
+ object members
+
+ Note, it assumes the option is unique within the config!
+ """
+ for section in self.iniConfig.sections():
+ for option in self.iniConfig.options(section):
+ if section in self.defaultValues and option in self.defaultValues[section]:
+ setattr(self, option, self.getValue(section, option, type(self.defaultValues[section][option])))
+ else:
+ setattr(self, option, self.getValue(section, option))
+
+class Settings(processINI):
+ """
+ Settings object that contains all data that is generally necessary
+ """
+ defaultValues = { 'LDAP':{'useldap':False,'port':389,'server':'localhost','port1':0,'port2':0}, \
+ 'General':{'clientport':22,'autoresume':True}, \
+ 'Authorization': {'newprofile':True,'suspend':True,'editprofile':True,'resume':True}
+ }
+ def __init__(self, fileName=None):
+ if fileName is None:
+ fileName = os.path.normpath(os.path.expanduser('~/.x2goclient/settings'))
+ processINI.__init__(self, fileName)
+ self.fillDefaultsSection()
+ self.bldSessionObj()
+
+class Printing(processINI):
+ """
+ Printing object that contains all data that is necessary for printing
+ """
+ defaultValues = { 'General': {'showdialog':False,'pdfview':False}, \
+ 'print': {'startcmd':False,'command':'lpr','stdin':False,'ps':False}, \
+ 'view': {'open':True,'command':'xpdf'}, \
+ 'CUPS': {'defaultprinter':None, 'options':'@Invalid()'}
+ }
+ def __init__(self, fileName=None):
+
+ if fileName is None:
+ fileName = os.path.normpath(os.path.expanduser('~/.x2goclient/printing'))
+ processINI.__init__(self, fileName)
+ self.fillDefaultsSection()
+ self.bldSessionObj()
+
+
+class SessionProfiles(processINI):
+ """
+ Session object that contains several sessionProfiles that contain all data necessary to open the connection with
+ an x2go server
+ """
+ defaultValues = \
+ {'speed':2,'pack':'16m-jpeg','quality':9,'fstunnel':True,'export':'"/home/dick/Documenten:1;"','fullscreen':False,'width':800,'height':600,'dpi':96,
+ 'setdpi':False,'usekbd':True,'layout':'us','type':'pc105/us','sound':False,'soundsystem':'pulse','startsoundsystem':True,'soundtunnel':True,
+ 'defsndport':True,'sndport':4713, 'printing':True,'name':None,'icon':':icons/128x128/x2gosession.png','host':None,'user':None, 'key':None,
+ 'sshport':22,'rootless':True,'applications':'dummy, WWWBROWSER, MAILCLIENT, OFFICE, TERMINAL','command':'dummy','rdpoptions':None,
+ 'rdpserver':None,'default':False,'connected':False}
+ def __init__(self, fileName=None):
+ if fileName is None:
+ fileName = os.path.normpath(os.path.expanduser('~/.x2goclient/sessions'))
+ processINI.__init__(self, fileName)
+ self.SessionProfiles = self.iniConfig.sections()
+ for section in self.SessionProfiles:
+ for key, sectionvalue in self.defaultValues.items():
+ if not self.iniConfig.has_option(section,key):
+ self.storeValueTypes(section, key, sectionvalue)
+
+ def getSection(self, section):
+ return self.iniConfig.items(section)
+
+
+class SingleProfile:
+ def __init__(self, prof, profiles):
+ self.prof = prof
+ self.profiles = profiles
+ self.session_uuid = None
+ self.showConfigScreen = False
+ self.bldSessionObj()
+ if self.host is None:
+ self.showConfigScreen = True
+
+ def bldSessionObj(self):
+ for option in self.profiles.iniConfig.options(self.prof):
+ if self.prof in self.profiles.defaultValues and option in self.profiles.defaultValues[self.prof]:
+ setattr(self, option, self.profiles.getValue(self.prof, option, type(self.profiles.defaultValues[self.prof][option])))
+ else:
+ setattr(self, option, self.profiles.getValue(self.prof, option))
+
+ def updConfig(self):
+ for key, retType in self.fieldList:
+ self.updValue(self.prof, key, self.__dict__[key])
+
+ def Connect(self, parent, printing):
+ geometry = str(self.width) + 'x' + str(self.height)
+ self.c = x2go.X2goClient(logger=parent.liblogger)
+ self.session_uuid = c.register_session(self.host, port=self.sshport,
+ username=self.user,
+ password=self.password,
+ key_filename=self.key,
+ add_to_known_hosts=self.add_to_known_hosts,
+ profile_name = self.name,
+ session_type=self.session_type,
+ link=self.link,
+ geometry=geometry,
+ pack=self.pack,
+ cache_type=self.cache_type,
+ kblayout=self.layout,
+ kbtype=self.type,
+ snd_system=self.sound,
+ printing=self.printing,
+ print_action=printing.print_action,
+ print_action_args=printing.print_action_args,
+ cmd=printing.command)
+ self.c.session_start(session_uid)
+ self.profiles.updValue(self.prof, 'connected', True)
+ self.connected = True
+ self.profiles.writeIni()
+
+ def Resume(self, parent, printing):
+ pass
+
+ def DisConnect(self):
+ self.profiles.updValue(self.prof, 'connected', True)
+ self.connected = False
+ self.profiles.writeIni()
+
+ def isAlive(self):
+ return True
+
+class x2goProfiles:
+ def __init__(self):
+ self.x2goprofs = []
+ self.there_is_a_default = 0
+ self.profiles = SessionProfiles()
+ for prof in self.profiles.SessionProfiles:
+ newSession = SingleProfile(prof, self.profiles)
+ if newSession.default:
+ self.x2goprofs.insert(0,newSession)
+ self.there_is_a_default += 1
+ else:
+ self.x2goprofs.append(newSession)
+ if len(self.profiles.SessionProfiles):
+ self.current_profile = self.x2goprofs[0]
+
+ def append(self, name):
+ self.x2goprofs.append(SingleProfile(name))
+
+ def writeIni(self):
+ for s in self.x2goprofs:
+ s.updConfig()
+ self.profiles.writeIni()
+
+ def defaultAvailable(self):
+ return self.there_is_a_default == 1
+
+ def profileExists(self, name):
+ for profile in self.x2goprofs:
+ if profile.prof == name or profile.name == name:
+ self.current_profile = profile
+ return True
+ return False
+
+ def runningSessions(self):
+ running = []
+ for idx, profs in enumerate(self.profiles.iniConfig.sections()):
+ connected = self.profiles.getValue(profs, 'connected', getType='bool')
+ if running:
+ running.append(x2goprofs[idx])
+ return running
+
+ def suspendedSessions(self):
+ running = self.runningSessions()
+ suspended = []
+ for idx, run in enumerate(running):
+ if running.isAlive(): continue
+ suspended.appended(run)
+ return suspended
\ No newline at end of file
diff --git a/pyhoca-gui.py b/pyhoca-gui.py
new file mode 100644
index 0000000..67c1e70
--- /dev/null
+++ b/pyhoca-gui.py
@@ -0,0 +1,145 @@
+#-----------------------------------------------------------------------------
+# Name: pyhoca-gui.py
+# Purpose: Main program to start the python x2go gui
+#
+# Author: Dick Kniep
+#
+# Created: 2010/10/25
+# RCS-ID: $Id: PyApp1.py $
+# Copyright: (c) 2010 Lindix
+#-----------------------------------------------------------------------------
+#!/usr/bin/env python
+#Boa:PyApp:main
+
+modules ={}
+
+try:
+ import wxversion
+ wxversion.select('2.8')
+except: pass
+import wx
+import x2go
+import x2goLogon
+import argparse
+import os.path
+import os
+import sys
+import platform
+import exceptions
+
+class notsupportedError(exceptions.StandardError): pass
+
+# version information
+PROG_NAME = os.path.basename(sys.argv[0])
+PROG_PID = os.getpid()
+VERSION="0.0.1"
+VERSION_TEXT="""
+%s[%s] - an X2go GUI client written in Python
+----------------------------------------------------------------------
+developed by Dick Kniep <dick.kniep at lindix.nl>
+
+VERSION: %s
+
+""" % (PROG_NAME, PROG_PID, VERSION)
+
+__author__ = "Dick J. Kniep"
+__version__ = "$Id$"
+
+class pyhocagui(wx.App):
+ def __init__(self, args, logger, liblogger):
+ self.args = args
+ self.logger = logger
+ self.liblogger = liblogger
+ wx.App.__init__(self)
+
+ def OnInit(self):
+ wx.BeginBusyCursor()
+ self.SetAppName('pyhoca, GUI Client of X2Go')
+ self.SetVendorName('Lindix BV. Almere (c) 2010')
+ x2goLogon.startX2Go(self)
+ wx.EndBusyCursor()
+ return True
+
+ def OnExit(self):
+ pass
+
+# debug options...
+debug_options = [
+ {'args':['-d','--debug'], 'default': False, 'action': 'store_true', 'help': 'enable application debugging code', },
+ {'args':['--libdebug'], 'default': False, 'action': 'store_true', 'help': 'enable debugging code of the underlying Python X2go module', },
+ {'args':['--libdebug-sftpxfer'], 'default': False, 'action': 'store_true', 'help': 'enable debugging code of Python X2go\'s sFTP server code (very verbose, and even promiscuous)', },
+ {'args':['-V', '--version'], 'default': False, 'action': 'store_true', 'help': 'print version number and exit', },
+ ]
+x2go_gui_options = [
+ {'args':['-m','--minimized'], 'default':False, 'action': 'store_true', 'help': 'start x2go gui minimized on the taskbar',} ,
+ {'args':['-u','--username'], 'default': None, 'help': 'username for the session (default: current user)', },
+ {'args':['-p','--password'], 'default': None, 'help': 'user password (not recommended from the command line, default: not set)', },
+ {'args':['-s','--profile'], 'default': None, 'help': 'The name of the sessionprofile to be used to make the connection', }
+ ]
+
+def parseargs():
+
+ global DEBUG
+ global print_action_args
+
+ p = argparse.ArgumentParser(description='X2go Gui client implemented in (wx)Python.',\
+ epilog="""Possible values for the --pack NX option are:""", \
+ formatter_class=argparse.RawDescriptionHelpFormatter, \
+ add_help=True, argument_default=None)
+ p_debugopts = p.add_argument_group('debug options')
+ p_guiopts = p.add_argument_group('PyHoca Gui options')
+
+ for (p_group, opts) in ((p_guiopts, x2go_gui_options), (p_debugopts, debug_options)):
+ required = False
+ for opt in opts:
+
+ args = opt['args']
+ del opt['args']
+ p_group.add_argument(*args, **opt)
+
+ a = p.parse_args()
+
+ logger = x2go.X2goLogger(tag='MAIN')
+ liblogger = x2go.X2goLogger()
+
+ if a.debug:
+ logger.set_loglevel_debug()
+
+ if a.libdebug:
+ liblogger.set_loglevel_debug()
+
+ if a.libdebug_sftpxfer:
+ liblogger.enable_debug_sftpxfer()
+
+ if a.version:
+ version()
+
+ if a.username is None:
+ if platform.system() == 'Windows':
+ import win32api
+ a.username = win32api.GetUserName()
+ elif platform.system() == 'Linux':
+ import getpass
+ a.username = getpass.getuser()
+ elif platform.system() == 'Mac':
+ import getpass
+ a.username = getpass.getuser()
+ else:
+ raise notsupportedError('Platform %s is not supported' % platform.system())
+
+ return a, logger, liblogger
+
+# print version text and exit
+def version():
+
+ sys.stderr.write ("%s\n" % VERSION_TEXT)
+ sys.exit(0)
+
+
+def main():
+ args, logger, liblogger = parseargs()
+ pgui = pyhocagui(args, logger, liblogger)
+ pgui.MainLoop()
+
+if __name__ == '__main__':
+ main()
diff --git a/pyx2go_client.py b/pyx2go_client.py
new file mode 100644
index 0000000..e4028d1
--- /dev/null
+++ b/pyx2go_client.py
@@ -0,0 +1,313 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+ Copyright (C) 2010 by Mike Gabriel <m.gabriel at das-netzwerkteam.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contributors to the code of this programme:
+ Jörg Sawatzki <joerg.sawatzki at web.de>
+ Dick Kniep <dick.kniep at lindix.nl>
+
+
+
+"""
+
+
+###
+### module section
+###
+
+import sys, os
+import time
+import argparse
+import getpass
+import x2go
+import paramiko
+from types import *
+import SessionProfile
+
+# for debugging
+import pprint
+
+# Python X2go provides the current local username (OS independent)
+from x2go.utils import CURRENT_LOCAL_USER as current_user
+
+# version information
+PROG_NAME = os.path.basename(sys.argv[0])
+PROG_PID = os.getpid()
+VERSION="0.0.14"
+VERSION_TEXT="""
+%s[%s] - an X2go client written in Python
+----------------------------------------------------------------------
+developed by Mike Gabriel <m.gabriel at das-netzwerkteam.de>
+and Dick Kniep <dick.kniep at lindix.nl>
+
+VERSION: %s
+
+""" % (PROG_NAME, PROG_PID, VERSION)
+
+class X2GoConnection:
+ def __init__(self):
+
+ self.x2goSession = SessionProfile.x2goSession()
+
+ # ,,constants'' needed for debugging
+ self.logger = x2go.X2goLogger(tag='MAIN')
+ self.liblogger = x2go.X2goLogger()
+ x2go_session_hash = ''
+
+ # use current_home as user home dir
+ current_home = os.path.expanduser("~")
+
+ # define and create known_hosts file (if not there)
+ ssh_known_hosts_filename = os.path.join(current_home, '.ssh', 'known_hosts')
+ if not os.path.isfile(ssh_known_hosts_filename):
+ self._touch_file(ssh_known_hosts_filename)
+ # define and create ssh_config file (if not there)
+ ssh_config_filename = os.path.join(current_home, '.ssh', 'config')
+ if not os.path.isfile(ssh_config_filename):
+ self._touch_file(ssh_config_filename)
+
+
+ ###
+ ### beginning of code
+ ###
+
+ def _touch_file(self, filename):
+
+ if not os.path.isfile(filename):
+ f = open(filename, 'w')
+ f.close()
+
+
+ # print version text and exit
+ def version(self):
+
+ sys.stderr.write ("%s\n" % VERSION_TEXT)
+ sys.exit(0)
+
+
+ # sometimes we have to fail...
+ def runtime_error(self, m, parser=None, exitcode=-1):
+ if parser is not None:
+ parser.print_usage()
+ sys.stderr.write ("%s: error: %s\n" % (PROG_NAME, m))
+ sys.exit(exitcode)
+
+
+ def makeConnection(self):
+
+ self.logger('preparing requested X2go session', x2go.loglevel_NOTICE, )
+
+ x2goclient = x2go.X2goClient(logger=self.liblogger)
+ x2go_session_hash = x2goclient.register_session(self.x2goSession.server, port=int(self.x2goSession.remote_ssh_port),
+ username=self.x2goSession.username,
+ password=self.x2goSession.password,
+ key_filename=self.x2goSession.ssh_privkey,
+ add_to_known_hosts=self.x2goSession.add_to_known_hosts,
+ profile_name = 'Pyhoca-Client_Session',
+ session_type=self.x2goSession.session_type,
+ link=self.x2goSession.link,
+ geometry=self.x2goSession.geometry,
+ pack=self.x2goSession.pack,
+ cache_type='unix-kde',
+ kblayout=self.x2goSession.kbd_layout,
+ kbtype=self.x2goSession.kbd_type,
+ snd_system=self.x2goSession.sound,
+ printing=self.x2goSession.printing,
+ cmd=self.x2goSession.command)
+
+ x2goclient.with_session(x2go_session_hash).load_host_keys(ssh_known_hosts_filename)
+ self.connected = False
+ force_password_auth = False
+ x2goclient.connect_session(x2go_session_hash, password=self.x2goSession.password, force_password_auth=force_password_auth)
+ self.connected = True
+
+ def checkSSHConfig(self)
+ ###
+ ### initialize SSH context
+ ###
+ # check if SERVER is in .ssh/config file, extract information from there...
+ ssh_config = paramiko.SSHConfig()
+ ssh_config_fileobj = open(ssh_config_filename)
+ ssh_config.parse(ssh_config_fileobj)
+ ssh_host = ssh_config.lookup(a.server)
+ if ssh_host:
+ if 'hostname' in ssh_host.keys():
+ a.server = ssh_host['hostname']
+ if 'port' in ssh_host.keys():
+ a.remote_ssh_port = ssh_host['port']
+ ssh_config_fileobj.close()
+ # check if ssh priv key exists
+ if a.ssh_privkey and not os.path.isfile(a.ssh_privkey):
+ runtime_error("SSH private key %s file does not exist." % a.ssh_privkey, parser=p, exitcode=30)
+ if not a.ssh_privkey and os.path.isfile('%s/.ssh/id_rsa' % current_home):
+ a.ssh_privkey = '%s/.ssh/id_rsa' % current_home
+ if not a.ssh_privkey and os.path.isfile('%s/.ssh/id_dsa' % current_home):
+ a.ssh_privkey = '%s/.ssh/id_dsa' % current_home
+
+ return p, a
+
+
+ def list_sessions(self, cli, s_hash):
+ # retrieve a session list
+ print
+ print "Available runing/suspended X2go sessions"
+ print "========================================"
+ print "Hostname: [%s]:%s" % cli.get_server(s_hash)
+ print "Username: %s" % cli.get_username(s_hash)
+ print
+ session_infos = cli.list_sessions(s_hash)
+ for session_info in session_infos.values():
+ print "Session Name: %s" % session_info
+ print "-------------"
+ print "cookie: %s" % session_info.cookie
+ print "agent PID: %s" % session_info.agent_pid
+ print "display: %s" % session_info.display
+ print "status: %s" % session_info.status
+ print "graphic port: %s" % session_info.graphics_port
+ print "snd port: %s" % session_info.snd_port
+ print "sshfs port: %s" % session_info.sshfs_port
+ print "username: %s" % session_info.username
+ print "hostname: %s" % session_info.hostname
+ # TODO: turn into datetime object
+ print "create date: %s" % session_info.date_created
+ # TODO: turn into datetime object
+ print "suspended since: %s" % session_info.date_suspended
+ print
+
+
+ def clean_sessions(self, cli, s_hash):
+ # clean all sessions from X2go server
+ logger('cleaning up all running sessions from X2go server: %s' % self.x2goSession.server, x2go.loglevel_NOTICE, )
+ cli.clean_sessions(s_hash)
+
+
+ def new_session(self, cli, s_hash):
+ # start a new session and run a command
+ logger('starting a new X2go session', x2go.loglevel_INFO, )
+ logger('Command for new session is: %s' % self.x2goSession.command, x2go.loglevel_DEBUG, )
+ cli.start_session(s_hash)
+
+
+ def resume_session(self, cli, s_hash):
+ # resume a running session
+ logger('resuming X2go session: %s' % self.x2goSession.resume, x2go.loglevel_INFO, )
+ available_sessions = cli.list_sessions(s_hash)
+ if self.x2goSession.resume in available_sessions.keys():
+ cli.resume_session(s_hash, self.x2goSession.resume)
+ else:
+ runtime_error('requested session not available on X2go server [%s]:%s.' % (self.x2goSession.server, self.x2goSession.remote_ssh_port), exitcode=20)
+
+
+ def suspend_session(self, cli, s_hash):
+ # send a suspend request to a session
+ logger('requesting X2go session suspend of session: %s' % self.x2goSession.suspend, x2go.loglevel_INFO, )
+ available_sessions = cli.list_sessions(s_hash)
+ if self.x2goSession.suspend in available_sessions.keys():
+ cli.suspend_session(s_hash, self.x2goSession.suspend)
+ else:
+ runtime_error('requested session not available on X2go server [%s]:%s.' % (self.x2goSession.server, self.x2goSession.remote_ssh_port), exitcode=21)
+
+ def terminate_session(self, cli, s_hash):
+ # send a terminate request to a session
+ logger('requesting X2go session terminate of session: %s' % self.x2goSession.terminate, x2go.loglevel_INFO, )
+ available_sessions = cli.list_sessions(s_hash)
+ if self.x2goSession.terminate in available_sessions.keys():
+ cli.terminate_session(s_hash, self.x2goSession.terminate)
+ else:
+ runtime_error('requested session not available on X2go server [%s]:%s.' % (self.x2goSession.server, self.x2goSession.remote_ssh_port), exitcode=22)
+
+
+if __name__ == '__main__':
+
+
+ if self.x2goSession.clean_sessions:
+ clean_sessions(x2goclient, x2go_session_hash)
+
+ # go through the possible X2go client modes
+ if self.x2goSession.list_sessions:
+ # print a beautified session list for the user
+ list_sessions(x2goclient, x2go_session_hash)
+ sys.exit(0)
+
+ if args.resume:
+ resume_session(x2goclient, x2go_session_hash)
+
+ elif args.suspend:
+ suspend_session(x2goclient, x2go_session_hash)
+
+ elif args.terminate:
+ terminate_session(x2goclient, x2go_session_hash)
+
+ elif args.new:
+ new_session(x2goclient, x2go_session_hash)
+
+
+ if args.new or args.resume:
+ # give the session some time to come up...
+ # no CTRL-C is allowed during this phase...
+ i=0
+ logger("give the X2go session some time to come up...", x2go.loglevel_NOTICE, )
+ while i < args.time_to_wait:
+ time.sleep(1)
+ i+=1
+
+ if x2goclient.session_ok(x2go_session_hash):
+
+ profile_name = x2goclient.get_profile_name(x2go_session_hash)
+ session_name = x2goclient.get_session_name(x2go_session_hash)
+ logger("X2go session is now running, the X2go client's profile name is: %s." % profile_name, x2go.loglevel_INFO, )
+ logger("X2go session name is: %s." % session_name, x2go.loglevel_INFO, )
+ logger("Press CTRL+C to suspend the running session.", x2go.loglevel_NOTICE, )
+ try:
+
+ session_duration = 0
+ mounted = False
+ while x2goclient.session_ok(x2go_session_hash):
+ time.sleep(2)
+ session_duration +=2
+
+ if session_duration > 2 and not mounted and args.share_local_folders is not None:
+ if x2goclient.with_session(x2go_session_hash).get_transport().reverse_tunnels['sshfs'][1] is not None:
+ for _folder in args.share_local_folders:
+ x2goclient.share_local_folder(x2go_session_hash, _folder)
+ mounted = True
+
+ # wait a little longer before telling the user what had happened
+ time.sleep(2)
+
+ if x2goclient.has_terminated(x2go_session_hash):
+ logger("X2go session %s has terminated." % session_name, x2go.loglevel_NOTICE, )
+ elif x2goclient.is_suspended(x2go_session_hash):
+ logger("X2go session %s has been suspended." % session_name, x2go.loglevel_NOTICE, )
+ elif x2goclient.is_running(x2go_session_hash):
+ logger("X2go session %s has been moved to a different screen." % session_name, x2go.loglevel_NOTICE, )
+
+ except KeyboardInterrupt:
+ logger("Suspending X2go session %s." % session_name, x2go.loglevel_INFO, )
+ x2goclient.suspend_session(x2go_session_hash)
+ # giving nxproxy's SSH tunnel some time to settle
+ time.sleep(2)
+ logger("X2go session %s has been suspended." % session_name, x2go.loglevel_NOTICE, )
+
+ sys.exit(0)
+
+ except (KeyboardInterrupt, SystemExit), e:
+ x2go.x2go_cleanup(e)
+
diff --git a/x2go b/x2go
new file mode 120000
index 0000000..3e76290
--- /dev/null
+++ b/x2go
@@ -0,0 +1 @@
+../../python/python-x2go/trunk/x2go
\ No newline at end of file
diff --git a/x2goLogon.py b/x2goLogon.py
new file mode 100644
index 0000000..b5f28a6
--- /dev/null
+++ b/x2goLogon.py
@@ -0,0 +1,471 @@
+# -*- coding: utf-8 -*-
+#-----------------------------------------------------------------------------
+# Name: x2goLogon.py
+# Purpose: display the Logon screen for x2go
+#
+# Author: Dick Kniep
+#
+# Created: 2010/10/21
+# Copyright: (c) Lindix BV 2010
+#-----------------------------------------------------------------------------
+
+
+import wx
+import time
+import sys
+import wx.lib.scrolledpanel as scrolled
+import SessionProfile
+import x2go
+try:
+ from agw import knobctrl as KC
+ knobctrlavailable = True
+except ImportError: # if it's not there locally, try the wxPython lib.
+ try:
+ import wx.lib.agw.knobctrl as KC
+ knobctrlavailable = True
+ except ImportError:
+ knobctrlavailable = False
+
+import wx.lib.sized_controls as sc
+
+class menuActions(wx.Menu):
+ def __init__(self, parent, settingsProfile, SessionProfiles):
+ OPENNEWMENUTXT = "Open new Session"
+ RUNNINGMENUTXT = "Running sessions"
+ SUSPENDMENUTXT = "Suspend session"
+ RESUMEMENUTXT = "Resume suspended session"
+ UPDATEPROFMNUTEXT = "Update Profile"
+ EXITMENUTXT = "E&xit sessions"
+ MENU_NEWSESSION = wx.NewId()
+ MENU_LISTSESSIONS = wx.NewId()
+ MENU_SUSPEND = wx.NewId()
+ MENU_RESUME = wx.NewId()
+ MENU_EDITSESSION = wx.NewId()
+ MENU_EXIT = wx.NewId()
+ wx.Menu.__init__(self)
+ parent.logger('settingsProfile.newProfile %s' % dir(settingsProfile), x2go.loglevel_INFO, )
+ if settingsProfile.newprofile:
+ self.Append(MENU_NEWSESSION, OPENNEWMENUTXT)
+ self.Bind(wx.EVT_MENU, self.OnNewSession, id=MENU_NEWSESSION)
+ if SessionProfiles.runningSessions():
+ self.Append(MENU_LISTSESSIONS, RUNNINGMENUTXT)
+ self.Bind(wx.EVT_MENU, self.OnListSessions, id=MENU_LISTSESSIONS)
+ self.Append(MENU_SUSPEND, SUSPENDMENUTXT)
+ self.Bind(wx.EVT_MENU, self.OnSuspend, id=MENU_SUSPEND)
+ if SessionProfiles.suspendedSessions() and settingsProfile.resume:
+ self.Append(MENU_RESUME, RESUMEMENUTXT)
+ self.Bind(wx.EVT_MENU, self.OnResume, id=MENU_RESUME)
+ if settingsProfile.editprofile:
+ self.AppendSeparator()
+ self.Append(MENU_EDITSESSION, UPDATEPROFMNUTEXT)
+ self.Bind(wx.EVT_MENU, self.OnUpdateProfile, id=MENU_EDITSESSION)
+ self.AppendSeparator()
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+ self.Bind(wx.EVT_MENU, self.OnExit, id=MENU_EXIT)
+
+ def OnNewSession(self, evt):
+ pass
+
+ def OnListSessions(self, evt):
+ pass
+
+ def OnSuspend(self, evt):
+ pass
+
+ def OnResume(self, evt):
+ pass
+
+ def OnUpdateProfile(self, evt):
+ pass
+
+ def OnExit(self, evt):
+ self.Close(True)
+
+ def OnClose(self, evt):
+ self.parent.env.exitAllChildren()
+ self.Destroy()
+
+class LogonStatusBar(wx.StatusBar):
+ def __init__(self, parent):
+ wx.StatusBar.__init__(self, parent, -1)
+ font = self.GetFont()
+ font.SetPointSize(7)
+ self.SetFont(font)
+ self.SetFieldsCount(2)
+ self.SetStatusWidths([-1,200])
+ self.parent = parent
+
+ self.timer = wx.PyTimer(self.Notify)
+ self.timer.Start(1000)
+ self.Notify()
+
+ def Notify(self):
+ self.SetStatusText(self.parent.Environment, 0)
+ self.SetStatusText(self.parent.StatusText, 1)
+ t = time.localtime(time.time())
+
+class X2GoResumeSessions(sc.SizedFrame):
+ def __init__(self, parent, SessionProfiles, settingsProfile, printProfile, Iconize):
+ sc.SizedFrame.__init__(self, None, -1, "X2go Password entry",
+ style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+
+class X2GoPasswordScrn(sc.SizedFrame):
+ def __init__(self, parent, SessionProfiles, settingsProfile, printProfile, Iconize):
+ """
+ Screen to enter the userid and password for the session
+
+ if the screen is iconized, but an error occurs, the screen is displayed
+ and the user can enter another userid/password
+ """
+ sc.SizedFrame.__init__(self, None, -1, "X2go Password entry",
+ style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+ self.CentreOnScreen()
+
+ self.SetSize((350,250))
+
+ self.settingsProfile = settingsProfile
+ self.SessionProfiles = SessionProfiles
+ self.current_profile = SessionProfiles.current_profile
+ self.parent = parent
+ parent.logger('Password entry screen started', x2go.loglevel_INFO, )
+ pane = self.GetContentsPane()
+ pane.SetSizerType("form")
+ pwScrn = self.passwordScrn(pane)
+ self.Main_MenuBar = wx.MenuBar()
+ self.SetMenuBar(self.Main_MenuBar)
+ self.Main_MenuBar.Append(menuActions(parent, settingsProfile, SessionProfiles), '&Connection')
+ self.tb = X2GoLogonTaskBarIcon(self)
+ if Iconize:
+ if self.IsIconized():
+ self.Iconize(True)
+ if parent.args.password and parent.args.username and parent.args.profile and SessionProfiles.profileExists(parent.args.profile):
+ self.onConnect()
+ else:
+ Message(self, 'Not all credentials are available')
+ self.Iconize(False)
+ else:
+ self.Show(True)
+
+ def passwordScrn(self, pnl):
+ wx.StaticText(pnl, -1, 'User'),
+ self.username_ctl = wx.TextCtrl(pnl, -1)
+ self.username_ctl.SetSizerProps(expand=True)
+ if hasattr(self.current_profile,'username'):
+ self.username_ctl.SetValue(self.SessionProfile.username)
+ else:
+ self.username_ctl.SetValue(self.parent.args.username)
+
+ wx.StaticText(pnl, -1, 'Password'),
+ self.passwd_ctl = wx.TextCtrl(pnl, -1, style=wx.TE_PASSWORD)
+
+ self.ConnectButton = wx.Button(pnl, -1, "Connect")
+ self.ConnectButton.Bind(wx.EVT_BUTTON, self.OnOK)
+
+ self.CancelButton = wx.Button(pnl, -1, "Cancel")
+ self.CancelButton.Bind(wx.EVT_BUTTON, self.OnCancel)
+ #self.SetButtonSizer(self.CreateStdDialogButtonSizer(self.ConnectButton | self.CancelButton))
+ #self.SetButtonSizer(self.CreateStdDialogButtonSizer(wx.OK| wx.CANCEL))
+
+ def OnOK(self, evt):
+ username = self.username_ctl.GetValue()
+ password = self.passwd_ctl.GetValue()
+ if len(username) == 0:
+ self.Message(self,'Userid is invalid')
+ return
+ if len(password) == 0:
+ self.Message(self,'Password is required')
+ return
+ self.current_profile.updValue('server','username',username)
+ self.current_profile.password = password
+ self.onConnect()
+
+ def onConnect(self):
+ set_iconize = False
+ try:
+ connection = x2goConnect.X2GoConnection(self.current_profile)
+ connection.makeConnection(self.session, self.StatusText)
+ set_iconize = True
+ except x2go.AuthenticationException:
+ self.Message(self,'Userid/Password verification failed')
+ except x2go.BadHostKeyException:
+ self.Message(self,'SSH host key verification for remote host [%s]:%s failed' % (self.current_profile.host, self.current_profile.ssh_port ))
+ except x2go.SSHException, e:
+ self.Message(self,'Problem with ssh tunnel for host [%s]:%s failed' % (self.current_profile.host, self.current_profile.ssh_port ))
+ if (set_iconize and not self.IsIconized()) or (self.IsIconized() and not set_iconize):
+ self.Iconize(set_iconize)
+ return
+
+ def OnCancel(self, evt):
+ self.Close
+
+
+class Message:
+ def __init__(self, parent, message, extraCaption='', msgtype='error'):
+ if msgtype == 'warning':
+ msgstyle = wx.ICON_QUESTION|wx.STAY_ON_TOP
+ caption = 'Warning '
+ elif msgtype == 'error':
+ msgstyle = wx.ICON_QUESTION|wx.STAY_ON_TOP
+ caption = 'Error '
+ else:
+ msgstyle = wx.ICON_INFORMATION|wx.STAY_ON_TOP
+ caption = 'Information '
+ caption += extraCaption
+ md = wx.MessageDialog(parent, message, caption=caption, style=msgstyle)
+ result = md.ShowModal()
+ self.retValue = False
+ if result == wx.OK:
+ self.retValue = True
+ md.Destroy()
+
+class X2GoChooseSessionScrn(sc.SizedDialog):
+ def __init__(self, parent, settingsProfile, printProfile):
+ parent.logger('Choose Session screen started', x2go.loglevel_INFO, )
+ pass
+
+class X2GoSessionDefScrn(sc.SizedDialog):
+ SESSIONNOTEBOOK = wx.NewId()
+ TypeList = ['GNOME','LXDE','Connect to Windows terminal server','Custom desktop','Server security','Single application']
+ CommandList = ['Internet Browser','Email client','OpenOffice','Terminal']
+ ConnectList = ['Modem','ISDN','ADSL','WAN','LAN']
+ CommpressionList = ['nopack','64k','256k','2m','256-rdp','32k-rdp','64k-rdp','16m-rdp','16m-rdp-compressed','64k-tight','2m-tight','4k-jpeg','16m-jpeg','64k-png-jpeg','16m-png-jpeg','64k-png','16m-png','16m-rgb','16m-rle']
+ def __init__(self, parent, SessionProfiles, settingsProfile, printProfile):
+
+ parent.logger('Session definition screen started', x2go.loglevel_INFO, )
+ self.pnl = wx.Panel(self, -1)
+ if self.current_profile and self.current_profile.connected:
+ self.StatusText = self.current_profile.StatusText
+ self.Environment = self.current_profile.Environment
+ else:
+ self.StatusText = 'Not Connected'
+ self.Environment = ''
+ self.sb = LogonStatusBar(self)
+ self.SetStatusBar(self.sb)
+
+ self.Main_MenuBar = wx.MenuBar()
+ self.SetMenuBar(self.Main_MenuBar)
+
+ if self.current_profile and self.current_profile.showConfigScreen is False:
+ self.passwordScrn(self.pnl)
+ else:
+ self.defineSessionScrn(self.pnl)
+
+ def defineSessionScrn(self, pnl, session):
+ self.SessionDefinition = wx.Notebook(id = SESSIONNOTEBOOK, name = 'SessionNoteBook', parent = pnl, pos = wx.Point(0, 0), style = 0)
+ self.SessionDefinition.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=SESSIONNOTEBOOK)
+ self.HostPanel = wx.Panel(self.SessionDefinition, -1)
+ self.SessionDefinition.AddPage(self.HostPanel, 'Host')
+ self.ConnectionPanel = wx.Panel(self.SessionDefinition, -1)
+ self.SessionDefinition.AddPage(self.ConnectionPanel, 'Connection')
+ self.SessionPanel = wx.Panel(self.SessionDefinition, -1)
+ self.SessionDefinition.AddPage(self.SessionPanel, 'Session')
+ self.SharedFilesPanel = wx.Panel(self.SessionDefinition, -1)
+ self.SessionDefinition.AddPage(self.SharedFilesPanel, 'Shared Files')
+
+ self.bldHostPanel(self.HostPanel)
+ self.bldConnPanel(self.ConnectionPanel)
+ self.bldSessionPanel(self.SessionPanel)
+ self.bldSharedFilesPanel(self.SharedFilesPanel)
+
+ def bldHostPanel(self, pnl):
+ self.hostgbs = wx.GridBagSizer(6, 4)
+ self.hostgbs.Add((0,0), (1,1))
+ self.hostgbs.Add( wx.StaticText(pnl, -1, 'Session Name'),
+ (1,0), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.ctl_sessionName = wx.TextCtrl(pnl, -1)
+ self.ctl_sessionName.SetValue(self.current_profile.username)
+ self.hostgbs.Add(self.ctl_sessionName, (3,0))
+
+ self.hostgbs.Add( wx.StaticText(pnl, -1, 'Server address'),
+ (1,1), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.ctl_serverName = wx.TextCtrl(pnl, -1)
+ self.ctl_serverName.SetValue(self.current_profile.servername)
+ self.hostgbs.Add(self.ctl_serverName, (3,1))
+
+ self.hostgbs.Add( wx.StaticText(pnl, -1, 'Server port'),
+ (1,2), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.ctl_remote_ssh_port = wx.TextCtrl(pnl, -1)
+ self.ctl_remote_ssh_port.SetValue(self.current_profile.remote_ssh_port)
+ self.hostgbs.Add(self.ctl_remote_ssh_port, (3,2))
+
+ self.hostgbs.Add( wx.StaticText(pnl, -1, 'Login'),
+ (1,3), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.ctl_username = wx.TextCtrl(pnl, -1)
+ self.ctl_username.SetValue(self.current_profile.username)
+ self.hostgbs.Add(self.ctl_username, (3,3))
+
+ self.hostgbs.Add( wx.StaticText(pnl, -1, 'Use RSA/DSA key for connection'),
+ (1,4), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.ctl_username = wx.TextCtrl(pnl, -1)
+ self.ctl_username.SetValue(self.current_profile.username)
+ self.hostgbs.Add(self.ctl_username, (3,4))
+
+ self.hostgbs.Add( wx.StaticText(pnl, -1, 'Session type'),
+ (1,5), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.cb = wx.ComboBox(self, 500, "KDE", (90, 50), (160, -1), self.TypeList, wx.CB_DROPDOWN|wx.CB_READONLY)
+ self.hostgbs.Add(self.cb, (3,5))
+
+ self.hostgbs.Add( wx.StaticText(pnl, -1, 'Command'),
+ (1,6), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.cmdcb = wx.ComboBox(self, 500, "Path to executable", (90, 50), (160, -1), self.CommandList, wx.CB_DROPDOWN)
+ self.Bind(wx.EVT_TEXT_ENTER, self.onCommandEntered, self.cmdcb)
+ self.hostgbs.Add(self.cmdcb, (3,6))
+
+
+ def bldConnectionPanel(self, pnl):
+ lefttopsizer_staticbox = wx.StaticBox(self.panel, -1, "Connection Speed")
+ mainsizer = wx.BoxSizer(wx.VERTICAL)
+ panelsizer = wx.BoxSizer(wx.HORIZONTAL)
+ rightsizer = wx.FlexGridSizer(6, 2, 10, 10)
+ leftsizer = wx.BoxSizer(wx.VERTICAL)
+ lefttopsizer = wx.StaticBoxSizer(lefttopsizer_staticbox, wx.VERTICAL)
+
+ self.knob1 = KC.KnobCtrl(pnl, -1, size=(100, 100))
+ self.knob1.SetTags(range(0, 4, 1))
+ self.knob1.SetAngularRange(-45, 225)
+ knobValue = self.__findConnection(self.current_profile.link)
+ self.knob1.SetValue(knobValue)
+ self.knobtracker1 = wx.StaticText(self.panel, -1, self.ConnectList[knobValue])
+ lefttopsizer.Add(self.knob1, 1, wx.ALL|wx.EXPAND, 5)
+ lefttopsizer.Add(self.knobtracker1, 0, wx.ALL)
+ leftbottomsizer_staticbox = wx.StaticBox(self.panel, -1, "Compression")
+
+ self.conngbs = wx.GridBagSizer(6, 4)
+ self.conngbs.Add((0,0), (1,1))
+ self.conngbs.Add( wx.StaticText(pnl, -1, 'Method'),
+ (1,0), flag=wx.ALIGN_LEFT | wx.ALL)
+ self.cbComp = wx.ComboBox(self, 500, "16m-jpeg-9", (90, 50), (160, -1), self.CommpressionList, wx.CB_DROPDOWN|wx.CB_READONLY)
+ self.conngbs.Add(self.cbComp, (3,4))
+
+ def bldSessionPanel(self, pnl):
+ self.sessgbs = wx.GridBagSizer(6, 4)
+ lefttopsizer_staticbox = wx.StaticBox(self.panel, -1, "Display")
+
+ def bldSharedFilesPanel(self, pnl):
+ pass
+
+
+ def __findConnection(self, value):
+ for idx, c in enumerate(self.ConnectList):
+ if c.lower() == value.lower(): break
+ return idx
+
+ def onCommandEntered(self, evt):
+ pass
+
+ def getSession(self):
+ pass
+
+ def OnUpdateProfile(self, evt):
+ pass
+
+class X2GoLogonTaskBarIcon(wx.TaskBarIcon):
+
+ def __init__(self, frame=None):
+ wx.TaskBarIcon.__init__(self)
+ self.frame = frame
+ self.frame.parent.logger('Start TaskBarIcon', x2go.loglevel_INFO, )
+ img = wx.Image('/usr/share/icons/hicolor/32x32/apps/x2goclient.png')
+ icon = self.MakeIcon(img)
+ self.SetIcon(icon, "x2go connect")
+ self.imgidx = 1
+
+ def CreatePopupMenu(self):
+ """
+ This method is called by the base class when it needs to popup
+ the menu for the default EVT_RIGHT_DOWN event. Just create
+ the menu how you want it and return it from this function,
+ the base class takes care of the rest.
+ """
+ menu = menuActions(self.frame.parent, self.frame.settingsProfile, self.frame.SessionProfiles)
+ return menu
+
+ def MakeIcon(self, img):
+ """
+ The various platforms have different requirements for the
+ icon size...
+ """
+ if "wxMSW" in wx.PlatformInfo:
+ img = img.Scale(16, 16)
+ elif "wxGTK" in wx.PlatformInfo:
+ img = img.Scale(22, 22)
+ # wxMac can be any size upto 128x128, so leave the source img alone....
+ icon = wx.IconFromBitmap(img.ConvertToBitmap() )
+ return icon
+
+ def OnTaskBarEditSession(self, evt):
+ if self.frame:
+ if self.frame.IsIconized():
+ self.frame.Iconize(False)
+ if not self.frame.IsShown():
+ self.frame.Show(True)
+ self.frame.Raise()
+
+
+ def OnTaskBarExitSessions(self, evt):
+ if self.frame:
+ wx.CallAfter(self.frame.Close)
+
+
+ def OnTaskBarResumeSession(self, evt):
+ names = [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
+ name = names[self.imgidx]
+
+ eImg = getattr(images, name)
+ self.imgidx += 1
+ if self.imgidx >= len(names):
+ self.imgidx = 0
+
+ icon = self.MakeIcon(eImg.Image)
+ self.SetIcon(icon, "This is a new icon: " + name)
+
+
+ def OnTaskBarNewSession(self, evt):
+ self.RemoveIcon()
+
+
+def checkArgs(parent, args, SessionProfiles):
+ if args.profile and not SessionProfiles.profileExists(args.profile):
+ Message(parent, 'Profile is entered, but is not known')
+ exit(0)
+
+
+def startX2Go(parent):
+ """
+ This routine starts processing
+
+ If there is only one profile available, or if there is one (1) single
+ profile that has the default switch, the logon screen
+ can be shown immediately
+ """
+ parent.logger('starting a new X2go GUI session', x2go.loglevel_INFO, )
+
+ printProfile = SessionProfile.Printing()
+ settingsProfile = SessionProfile.Settings()
+ SessionProfiles = SessionProfile.x2goProfiles()
+ noSessionsDefined = len(SessionProfiles.x2goprofs) == 0
+ moreSessionsDefined = len(SessionProfiles.x2goprofs) > 1
+
+ checkArgs(parent, parent.args, SessionProfiles)
+ sessionsSuspended = SessionProfiles.suspendedSessions()
+ if len(sessionsSuspended) and settingsProfile.autoresume:
+ parent.logger('autoresume sessionsSuspended %s' % sessionsSuspended, x2go.loglevel_INFO, )
+ for suspended in sessionsSuspended:
+ suspended.Resume()
+ elif len(sessionsSuspended):
+ parent.logger('Choose SuspendedSessions %s' % sessionsSuspended, x2go.loglevel_INFO, )
+ X2GoResumeSessions(parent, sessionsSuspended, settingsProfile, printProfile)
+ else:
+ if parent.args.minimized:
+ parent.logger('Start minimized', x2go.loglevel_INFO, )
+ pwScrn = X2GoPasswordScrn(parent, SessionProfiles, settingsProfile, printProfile, Iconize=True)
+ else:
+ if not noSessionsDefined and (not moreSessionsDefined or SessionProfiles.defaultAvailable()):
+ parent.logger('Start password entry normally', x2go.loglevel_INFO, )
+ pwScrn = X2GoPasswordScrn(parent, SessionProfiles, settingsProfile, printProfile)
+ elif noSessionsDefined:
+ parent.logger('Start Profile Definition', x2go.loglevel_INFO, )
+ defScrn = X2GoSessionDefScrn(parent, SessionProfiles, settingsProfile, printProfile)
+ else:
+ parent.logger('Start Profile choice', x2go.loglevel_INFO, )
+ choiceScrn = X2GoChooseSessionScrn(parent, settingsProfile, printProfile)
hooks/post-receive
--
pyhoca-gui.git (Python X2Go Client (wxPython GUI))
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 "pyhoca-gui.git" (Python X2Go Client (wxPython GUI)).
More information about the x2go-commits
mailing list