Compare commits
195 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
16f05920b5 | ||
|
98befc7cee | ||
|
1e6f806563 | ||
|
08ed93121b | ||
|
840cc57fdc | ||
|
e46b0d22e7 | ||
|
085b0c1393 | ||
|
e257ca0571 | ||
|
29e062ba5d | ||
|
2b9cd5508d | ||
|
79a591180d | ||
|
1e711eecbb | ||
|
7da01597e6 | ||
|
2e4bd4b1db | ||
|
f3f936e401 | ||
|
90ed08c779 | ||
|
c2874e74c8 | ||
|
3a11c9832f | ||
|
0f6ffb559b | ||
|
4769d7dc51 | ||
|
4fc2e98313 | ||
|
09a48c9c5a | ||
|
ac245e71e9 | ||
|
e5d2c711ce | ||
|
de5e7380c4 | ||
|
3e87c90c67 | ||
|
4a97872cdd | ||
|
19e67f5a18 | ||
|
3e7c01f7f9 | ||
|
0bda00e43d | ||
|
fe18faa863 | ||
|
808c715710 | ||
|
16d458bb69 | ||
|
22a7e2336e | ||
|
f773cb5ecc | ||
|
d1b6891ca7 | ||
|
a9e65975c5 | ||
|
c1377255b5 | ||
|
cce8fa4869 | ||
|
dda1018901 | ||
|
b44d02dbd9 | ||
|
cfded58563 | ||
|
8642f4291b | ||
|
e83ff8d69d | ||
|
16edf04f1d | ||
|
cbaa5cef46 | ||
|
da75dc79a7 | ||
|
9965be5a76 | ||
|
9d6f3111da | ||
|
9265ab3ac3 | ||
|
34e70394e9 | ||
|
3a750018e2 | ||
|
390eea5c3d | ||
|
dbf94b4c17 | ||
|
bc8b2de151 | ||
|
b73408043e | ||
|
2ba6e4fa7c | ||
|
9bbd7fd57d | ||
|
0ec3cb104a | ||
|
b1f1d6701e | ||
|
d54b447bf7 | ||
|
6ca7c5fb34 | ||
|
ca9ad5efbd | ||
|
b5154cbbe9 | ||
|
a3ad88b9e6 | ||
|
a4b9bf1fb9 | ||
|
a95684d864 | ||
|
6057e8a3f8 | ||
|
4fbbfb8d10 | ||
|
2daafa2c4a | ||
|
846489244e | ||
|
ec33b46848 | ||
|
e067f09958 | ||
|
8cbfcbb104 | ||
|
2b5cf494db | ||
|
39158bd7ae | ||
|
95a695ee88 | ||
|
a860732ed2 | ||
|
5d391a9fc4 | ||
|
148cd249cd | ||
|
57e643333e | ||
|
5794fab7da | ||
|
9955e7bcff | ||
|
86b252916c | ||
|
e81a8fdc5f | ||
|
92cf8c36bd | ||
|
de07a4f3cd | ||
|
320a530bbc | ||
|
e945ad9fe8 | ||
|
be3c242a7d | ||
|
f86712a05a | ||
|
777ca4c016 | ||
|
f715f48a7b | ||
|
315dd77a5a | ||
|
82f7f56590 | ||
|
8e594c7c7f | ||
|
e99c77a97f | ||
|
a80fc629a2 | ||
|
8b644d4fec | ||
|
17196ac31d | ||
|
632bb3e6d4 | ||
|
def1c59e4c | ||
|
e90e56c426 | ||
|
5f1676e56b | ||
|
72230c5a60 | ||
|
fad5eca5b9 | ||
|
8054f088b9 | ||
|
544b8b7b25 | ||
|
4d6f54f54c | ||
|
2004f4f882 | ||
|
08e33ee20e | ||
|
330973ac30 | ||
|
f78c755f12 | ||
|
bbc2cdfa30 | ||
|
d566285098 | ||
|
4c7b48588f | ||
|
22313a517f | ||
|
0c7a4911d2 | ||
|
f11bccc868 | ||
|
c62e90f0a1 | ||
|
170319f871 | ||
|
c6dd782150 | ||
|
cc7740bafb | ||
|
1626fe96b1 | ||
|
efbca46af9 | ||
|
548f44b1a7 | ||
|
2664be7ec4 | ||
|
bd3d0dd006 | ||
|
a83e218679 | ||
|
8ee34cd42b | ||
|
1ad57ee70c | ||
|
c9ab76c19c | ||
|
217655c276 | ||
|
57d1041f87 | ||
|
b56bf7b13f | ||
|
3a137213a7 | ||
|
90cb224c9a | ||
|
69ad1baa7d | ||
|
6d2dee2664 | ||
|
ace11fd77a | ||
|
afa6f62daa | ||
|
6c8f9affc2 | ||
|
fa0acb6a1a | ||
|
4fa7d26191 | ||
|
e22f489038 | ||
|
11100e3fda | ||
|
047eac18a7 | ||
|
32b5354a15 | ||
|
0d085ba708 | ||
|
d184f0eec3 | ||
|
675d502f73 | ||
|
4268004fcf | ||
|
aabc5540d0 | ||
|
68806c6366 | ||
|
343fed3245 | ||
|
c740457860 | ||
|
1d417c6075 | ||
|
ec7d3d39bd | ||
|
2e98197376 | ||
|
df17a86820 | ||
|
54c751e4c5 | ||
|
151d35459e | ||
|
1ae22ff249 | ||
|
983114af88 | ||
|
8a828bd087 | ||
|
76fc938604 | ||
|
c08cb38dbc | ||
|
f5dcb73e33 | ||
|
4108cf4df7 | ||
|
f33c536adf | ||
|
a66b36e142 | ||
|
c9bff899ba | ||
|
82097b67f4 | ||
|
3a58e0e446 | ||
|
5ce61e1f98 | ||
|
5af198db75 | ||
|
1f6279cd46 | ||
|
a07f1d5b24 | ||
|
26c0532fd5 | ||
|
9901bc2c8f | ||
|
715957feb2 | ||
|
c7dc1e8b81 | ||
|
00798e5927 | ||
|
a68837bf4b | ||
|
387b7f51d4 | ||
|
649a3515fc | ||
|
fe8f8be1d8 | ||
|
cd9f9ad523 | ||
|
bba494cdc0 | ||
|
49e3f72d89 | ||
|
a266cdaeff | ||
|
43bf2de385 | ||
|
447dc23914 | ||
|
49aaaedbe9 | ||
|
7892a196ac |
2
actors/.gitignore
vendored
@@ -6,3 +6,5 @@ udsactor*.changes
|
||||
/udsactor_1.7.0.dsc
|
||||
/udsactor_1.7.0.tar.xz
|
||||
/udsactor*.rpm
|
||||
/udsactor_2.1.0_amd64.buildinfo
|
||||
linux/debian/files
|
||||
|
@@ -1,3 +1,9 @@
|
||||
udsactor (2.1.0) stable; urgency=medium
|
||||
|
||||
* Fixes for 2.1.0 release
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Tue, 19 Jan 2017 08:00:22 +0200
|
||||
|
||||
udsactor (2.0.0) stable; urgency=medium
|
||||
|
||||
* Upgrade for 2.0.0
|
||||
|
@@ -1,3 +0,0 @@
|
||||
udsactor-nx_2.0.0_all.deb x11 optional
|
||||
udsactor-xrdp_2.0.0_all.deb x11 optional
|
||||
udsactor_2.0.0_all.deb admin optional
|
@@ -5,6 +5,7 @@
|
||||
set -e
|
||||
case "$1" in
|
||||
configure)
|
||||
/usr/bin/python2.7 -m compileall /usr/share/UDSActor > /dev/nul 2>&1
|
||||
# If new "fresh" install or if configuration file has disappeared...
|
||||
if [ "$2" = "" ] || [ ! -f /etc/udsactor/udsactor.cfg ]; then
|
||||
db_get udsactor/host
|
||||
|
@@ -8,5 +8,5 @@ Type=Application
|
||||
NoDisplay=true
|
||||
X-KDE-autostart-after=panel
|
||||
X-KDE-StartupNotify=false
|
||||
X-DBUS-StartupType=Unique
|
||||
X-KDE-UniqueApplet=true
|
||||
X-DBUS-StartupType=None
|
||||
X-KDE-UniqueApplet=false
|
||||
|
@@ -51,6 +51,8 @@ from udsactor import VERSION
|
||||
|
||||
trayIcon = None
|
||||
|
||||
doLogoff = False
|
||||
|
||||
|
||||
def sigTerm(sigNo, stackFrame):
|
||||
if trayIcon:
|
||||
@@ -253,7 +255,7 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
|
||||
|
||||
if remainingTime <= 0:
|
||||
logger.info('User has been idle for too long, notifying Broker that service can be reclaimed')
|
||||
self.quit()
|
||||
self.quit(logoff=True)
|
||||
|
||||
def displayMessage(self, message):
|
||||
logger.debug('Displaying message')
|
||||
@@ -290,7 +292,8 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
|
||||
def about(self):
|
||||
self.aboutDlg.exec_()
|
||||
|
||||
def quit(self):
|
||||
def quit(self, logoff=False):
|
||||
global doLogoff
|
||||
logger.debug('Quit invoked')
|
||||
if self.stopped is False:
|
||||
self.stopped = True
|
||||
@@ -303,10 +306,7 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
|
||||
# May we have lost connection with server, simply exit in that case
|
||||
pass
|
||||
|
||||
try:
|
||||
operations.loggoff() # Invoke log off
|
||||
except Exception:
|
||||
pass
|
||||
doLogoff = logoff
|
||||
|
||||
self.app.quit()
|
||||
|
||||
@@ -339,4 +339,12 @@ if __name__ == '__main__':
|
||||
logger.debug('Exiting')
|
||||
trayIcon.quit()
|
||||
|
||||
if doLogoff:
|
||||
try:
|
||||
time.sleep(1)
|
||||
operations.loggoff() # Invoke log off
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
sys.exit(res)
|
||||
|
@@ -34,7 +34,7 @@ from __future__ import unicode_literals
|
||||
# On centos, old six release does not includes byte2int, nor six.PY2
|
||||
import six
|
||||
|
||||
VERSION = '2.0.0'
|
||||
VERSION = '2.1.0'
|
||||
|
||||
__title__ = 'udsactor'
|
||||
__version__ = VERSION
|
||||
|
@@ -196,13 +196,22 @@ class HTTPServerThread(threading.Thread):
|
||||
|
||||
self.initiateServer(address)
|
||||
|
||||
def getPort(self):
|
||||
return self.address[1]
|
||||
|
||||
def getIp(self):
|
||||
return self.address[0]
|
||||
|
||||
def initiateServer(self, address):
|
||||
self.server = socketserver.TCPServer(address, HTTPServerHandler)
|
||||
self.address = (address[0], address[1]) # Copy address & keep it for future reference...
|
||||
|
||||
addr = ('0.0.0.0', address[1]) # Adapt to listen on 0.0.0.0
|
||||
|
||||
self.server = socketserver.TCPServer(addr, HTTPServerHandler)
|
||||
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
|
||||
|
||||
def getServerUrl(self):
|
||||
return 'https://{}:{}/{}'.format(self.server.server_address[0], self.server.server_address[1], HTTPServerHandler.uuid)
|
||||
return 'https://{}:{}/{}'.format(self.getIp(), self.getPort(), HTTPServerHandler.uuid)
|
||||
|
||||
def stop(self):
|
||||
logger.debug('Stopping REST Service')
|
||||
@@ -211,11 +220,14 @@ class HTTPServerThread(threading.Thread):
|
||||
def restart(self, address=None):
|
||||
|
||||
if address is None:
|
||||
address = self.server.server_address
|
||||
# address = self.server.server_address
|
||||
address = self.address
|
||||
|
||||
self.stop()
|
||||
self.address = (address[0], self.address[1]) # Copy address & keep it for future reference, port is never changed once assigned on init
|
||||
|
||||
self.initiateServer(address)
|
||||
# Listening on 0.0.0.0, does not need to restart listener..
|
||||
# self.stop()
|
||||
# self.initiateServer(address)
|
||||
|
||||
def run(self):
|
||||
self.server.serve_forever()
|
||||
|
@@ -36,6 +36,8 @@ import sys
|
||||
import six
|
||||
import traceback
|
||||
import pickle
|
||||
import errno
|
||||
import time
|
||||
|
||||
from udsactor.utils import toUnicode
|
||||
from udsactor.log import logger
|
||||
@@ -407,8 +409,11 @@ class ClientIPC(threading.Thread):
|
||||
self.messageReceived()
|
||||
|
||||
except socket.error as e:
|
||||
if e.errno == errno.EINTR:
|
||||
time.sleep(1) #
|
||||
continue # Ignore interrupted system call
|
||||
logger.error('Communication with server got an error: {}'.format(toUnicode(e.strerror)))
|
||||
self.running = False
|
||||
# self.running = False
|
||||
return
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
|
@@ -36,6 +36,7 @@ from udsactor import operations
|
||||
from udsactor.service import CommonService
|
||||
from udsactor.service import initCfg
|
||||
from udsactor.service import IPC_PORT
|
||||
|
||||
from udsactor import ipc
|
||||
|
||||
from udsactor.log import logger
|
||||
@@ -44,15 +45,23 @@ from udsactor.linux.daemon import Daemon
|
||||
from udsactor.linux import renamer
|
||||
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
import stat
|
||||
import subprocess
|
||||
|
||||
POST_CMD = '/etc/udsactor/post'
|
||||
PRECONNECT_CMD = '/etc/udsactor/pre'
|
||||
|
||||
try:
|
||||
from prctl import set_proctitle
|
||||
from prctl import set_proctitle # @UnresolvedImport
|
||||
except Exception: # Platform may not include prctl, so in case it's not available, we let the "name" as is
|
||||
def set_proctitle(_):
|
||||
pass
|
||||
|
||||
|
||||
class UDSActorSvc(Daemon, CommonService):
|
||||
rebootMachineAfterOp = False
|
||||
|
||||
def __init__(self, args=None):
|
||||
Daemon.__init__(self, '/var/run/udsa.pid')
|
||||
CommonService.__init__(self)
|
||||
@@ -62,6 +71,12 @@ class UDSActorSvc(Daemon, CommonService):
|
||||
Renames the computer, and optionally sets a password for an user
|
||||
before this
|
||||
'''
|
||||
hostName = operations.getComputerName()
|
||||
|
||||
if hostName.lower() == name.lower():
|
||||
logger.info('Computer name is already {}'.format(hostName))
|
||||
self.setReady()
|
||||
return
|
||||
|
||||
# Check for password change request for an user
|
||||
if user is not None:
|
||||
@@ -75,13 +90,48 @@ class UDSActorSvc(Daemon, CommonService):
|
||||
'Could not change password for user {} (maybe invalid current password is configured at broker): {} '.format(user, unicode(e)))
|
||||
|
||||
renamer.rename(name)
|
||||
self.setReady()
|
||||
|
||||
if self.rebootMachineAfterOp is False:
|
||||
self.setReady()
|
||||
else:
|
||||
logger.info('Rebooting computer to activate new name {}'.format(name))
|
||||
self.reboot()
|
||||
|
||||
|
||||
def joinDomain(self, name, domain, ou, account, password):
|
||||
logger.fatal('Join domain is not supported on linux platforms right now')
|
||||
|
||||
def preConnect(self, user, protocol):
|
||||
'''
|
||||
Invoked when received a PRE Connection request via REST
|
||||
'''
|
||||
# Execute script in /etc/udsactor/post after interacting with broker, if no reboot is requested ofc
|
||||
# This will be executed only when machine gets "ready"
|
||||
try:
|
||||
|
||||
if os.path.isfile(PRECONNECT_CMD):
|
||||
if (os.stat(PRECONNECT_CMD).st_mode & stat.S_IXUSR) != 0:
|
||||
subprocess.call([PRECONNECT_CMD, user, protocol])
|
||||
else:
|
||||
logger.info('PRECONNECT file exists but it it is not executable (needs execution permission by root)')
|
||||
else:
|
||||
logger.info('PRECONNECT file not found & not executed')
|
||||
except Exception as e:
|
||||
# Ignore output of execution command
|
||||
logger.error('Executing preconnect command give')
|
||||
|
||||
|
||||
def run(self):
|
||||
initCfg()
|
||||
cfg = initCfg() # Gets a local copy of config to get "reboot"
|
||||
|
||||
logger.debug('CFG: {}'.format(cfg))
|
||||
|
||||
if cfg is not None:
|
||||
self.rebootMachineAfterOp = cfg.get('reboot', True)
|
||||
else:
|
||||
self.rebootMachineAfterOp = False
|
||||
|
||||
logger.info('Reboot after is {}'.format(self.rebootMachineAfterOp))
|
||||
|
||||
logger.debug('Running Daemon')
|
||||
set_proctitle('UDSActorDaemon')
|
||||
@@ -106,6 +156,21 @@ class UDSActorSvc(Daemon, CommonService):
|
||||
logger.debug('Reboot has been requested, stopping service')
|
||||
return
|
||||
|
||||
# Execute script in /etc/udsactor/post after interacting with broker, if no reboot is requested ofc
|
||||
# This will be executed only when machine gets "ready"
|
||||
try:
|
||||
|
||||
if os.path.isfile(POST_CMD):
|
||||
if (os.stat(POST_CMD).st_mode & stat.S_IXUSR) != 0:
|
||||
subprocess.call([POST_CMD, ])
|
||||
else:
|
||||
logger.info('POST file exists but it it is not executable (needs execution permission by root)')
|
||||
else:
|
||||
logger.info('POST file not found & not executed')
|
||||
except Exception as e:
|
||||
# Ignore output of execution command
|
||||
logger.error('Executing post command give')
|
||||
|
||||
self.initIPC()
|
||||
|
||||
# *********************
|
||||
|
@@ -122,7 +122,7 @@ def getComputerName():
|
||||
def getNetworkInfo():
|
||||
for ifname in _getInterfaces():
|
||||
ip, mac = _getIpAndMac(ifname)
|
||||
if mac != '00:00:00:00:00:00': # Skips local interfaces
|
||||
if mac != '00:00:00:00:00:00' and ip.startswith('169.254') is False: # Skips local interfaces & interfaces with no dhcp IPs
|
||||
yield utils.Bunch(name=ifname, mac=mac, ip=ip)
|
||||
|
||||
|
||||
|
@@ -78,3 +78,11 @@ def writeConfig(data):
|
||||
cfg.write(f)
|
||||
|
||||
os.chmod(CONFIGFILE, 0o0600)
|
||||
|
||||
def useOldJoinSystem():
|
||||
return False
|
||||
|
||||
# Right now, we do not really need an application to be run on "startup" as could ocur with windows
|
||||
def runApplication():
|
||||
return None
|
||||
|
||||
|
@@ -70,6 +70,8 @@ def initCfg():
|
||||
cfg = None
|
||||
break
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
class CommonService(object):
|
||||
def __init__(self):
|
||||
@@ -84,6 +86,23 @@ class CommonService(object):
|
||||
def reboot(self):
|
||||
self.rebootRequested = True
|
||||
|
||||
def execute(self, cmd, section):
|
||||
import os
|
||||
import subprocess
|
||||
import stat
|
||||
|
||||
if os.path.isfile(cmd):
|
||||
if (os.stat(cmd).st_mode & stat.S_IXUSR) != 0:
|
||||
subprocess.call([cmd, ])
|
||||
return True
|
||||
else:
|
||||
logger.info('{} file exists but it it is not executable (needs execution permission by admin/root)'.format(section))
|
||||
else:
|
||||
logger.info('{} file not found & not executed'.format(section))
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def setReady(self):
|
||||
self.api.setReady([(v.mac, v.ip) for v in operations.getNetworkInfo()])
|
||||
|
||||
@@ -136,6 +155,13 @@ class CommonService(object):
|
||||
# Wait a bit before next check
|
||||
self.doWait(5000)
|
||||
|
||||
# Now try to run the "runonce" element
|
||||
runOnce = store.runApplication()
|
||||
if runOnce is not None:
|
||||
if self.execute(runOnce, 'RunOnce') is True:
|
||||
# operations.reboot()
|
||||
return False
|
||||
|
||||
# Broker connection is initialized, now get information about what to
|
||||
# do
|
||||
counter = 0
|
||||
@@ -210,7 +236,7 @@ class CommonService(object):
|
||||
self.knownIps = dict(((v.mac, v.ip) for v in netInfo))
|
||||
|
||||
# And notify new listening address to broker
|
||||
address = (self.knownIps[self.api.mac], random.randrange(43900, 44000))
|
||||
address = (self.knownIps[self.api.mac], self.httpServer.getPort())
|
||||
# And new listening address
|
||||
self.httpServer.restart(address)
|
||||
# sends notification
|
||||
|
@@ -40,9 +40,11 @@ import win32event # @UnresolvedImport, pylint: disable=import-error
|
||||
import win32com.client # @UnresolvedImport, @UnusedImport, pylint: disable=import-error
|
||||
import pythoncom # @UnresolvedImport, pylint: disable=import-error
|
||||
import servicemanager # @UnresolvedImport, pylint: disable=import-error
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
from udsactor import operations
|
||||
from udsactor import store
|
||||
from udsactor.service import CommonService
|
||||
from udsactor.service import initCfg
|
||||
|
||||
@@ -55,6 +57,8 @@ from .SENS import SENSGUID_PUBLISHER
|
||||
from .SENS import PROGID_EventSubscription
|
||||
from .SENS import PROGID_EventSystem
|
||||
|
||||
POST_CMD = 'c:\\windows\\post-uds.bat'
|
||||
|
||||
|
||||
class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
'''
|
||||
@@ -113,7 +117,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
|
||||
operations.renameComputer(name)
|
||||
# Reboot just after renaming
|
||||
logger.info('Rebooting computer got activate new name {}'.format(name))
|
||||
logger.info('Rebooting computer to activate new name {}'.format(name))
|
||||
self.reboot()
|
||||
|
||||
def oneStepJoin(self, name, domain, ou, account, password):
|
||||
@@ -158,12 +162,15 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
ver = ver[0] * 10 + ver[1]
|
||||
logger.debug('Starting joining domain {} with name {} (detected operating version: {})'.format(
|
||||
domain, name, ver))
|
||||
# If file c:\compat.bin exists, joind domain in two steps instead one
|
||||
|
||||
# Accepts one step joinDomain, also remember XP is no more supported by
|
||||
# microsoft, but this also must works with it because will do a "multi
|
||||
# step" join
|
||||
if ver >= 60:
|
||||
if ver >= 60 and store.useOldJoinSystem() is False:
|
||||
self.oneStepJoin(name, domain, ou, account, password)
|
||||
else:
|
||||
logger.info('Using multiple step join because configuration requests to do so')
|
||||
self.multiStepJoin(name, domain, ou, account, password)
|
||||
|
||||
def preConnect(self, user, protocol):
|
||||
@@ -292,6 +299,17 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
|
||||
logger.debug('Registered SENS, running main loop')
|
||||
|
||||
# Execute script in c:\\windows\\post-uds.bat after interacting with broker, if no reboot is requested ofc
|
||||
# This will be executed only when machine gets "ready"
|
||||
try:
|
||||
if os.path.isfile(POST_CMD):
|
||||
subprocess.call([POST_CMD, ])
|
||||
else:
|
||||
logger.info('POST file not found & not executed')
|
||||
except Exception as e:
|
||||
# Ignore output of execution command
|
||||
logger.error('Executing post command give')
|
||||
|
||||
# *********************
|
||||
# * Main Service loop *
|
||||
# *********************
|
||||
|
@@ -82,7 +82,6 @@ def readConfig():
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def writeConfig(data, fixPermissions=True):
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, path, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
|
||||
@@ -93,3 +92,32 @@ def writeConfig(data, fixPermissions=True):
|
||||
|
||||
wreg.SetValueEx(key, "", 0, wreg.REG_BINARY, encoder(cPickle.dumps(data))) # @UndefinedVariable
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
|
||||
def useOldJoinSystem():
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
|
||||
try:
|
||||
data, _ = wreg.QueryValueEx(key, 'join') # @UndefinedVariable
|
||||
except Exception:
|
||||
data = ''
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
except:
|
||||
data = ''
|
||||
|
||||
return data == 'old'
|
||||
|
||||
# Gives the oportunity to run an application ONE TIME (because, the registry key "run" will be deleted after read)
|
||||
def runApplication():
|
||||
try:
|
||||
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
|
||||
try:
|
||||
data, _ = wreg.QueryValueEx(key, 'run') # @UndefinedVariable
|
||||
wreg.DeleteValue(key, 'run') # @UndefinedVariable
|
||||
except Exception:
|
||||
data = None
|
||||
wreg.CloseKey(key) # @UndefinedVariable
|
||||
except:
|
||||
data = None
|
||||
|
||||
return data
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION=`cat ../../VERSION`
|
||||
VERSION=`cat ../../../VERSION`
|
||||
RELEASE=1
|
||||
# Debian based
|
||||
dpkg-buildpackage -b
|
@@ -1,3 +1,9 @@
|
||||
udsclient (2.1.0) stable; urgency=medium
|
||||
|
||||
* Updated release
|
||||
|
||||
-- Adolfo Gómez García <agomez@virtualcable.es> Sun, 23 Oct 2016 21:12:23 +0200
|
||||
|
||||
udsclient (2.0.0) stable; urgency=medium
|
||||
|
||||
* Release upgrade
|
2
client/full/linux/debian/files
Normal file
@@ -0,0 +1,2 @@
|
||||
udsclient_2.1.0_all.deb admin optional
|
||||
udsclient_2.1.0_amd64.buildinfo admin optional
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2014 Virtual Cable S.L.
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -281,7 +281,7 @@ if __name__ == "__main__":
|
||||
|
||||
# Setup REST api endpoint
|
||||
RestRequest.restApiUrl = '{}://{}/rest/client'.format(['http', 'https'][ssl], host)
|
||||
logger.debug('Setting requert URL to {}'.format(RestRequest.restApiUrl))
|
||||
logger.debug('Setting request URL to {}'.format(RestRequest.restApiUrl))
|
||||
# RestRequest.restApiUrl = 'https://172.27.0.1/rest/client'
|
||||
|
||||
try:
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 137 KiB |
@@ -34,7 +34,7 @@ from __future__ import unicode_literals
|
||||
# On centos, old six release does not includes byte2int, nor six.PY2
|
||||
import six
|
||||
|
||||
VERSION = '2.0.0'
|
||||
VERSION = '2.1.0'
|
||||
|
||||
__title__ = 'udclient'
|
||||
__version__ = VERSION
|
@@ -33,10 +33,17 @@ from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
if sys.platform.startswith('linux'):
|
||||
from os.path import expanduser
|
||||
logFile = expanduser('~/udsclient.log')
|
||||
else:
|
||||
logFile = os.path.join(tempfile.gettempdir(), b'udsclient.log')
|
||||
|
||||
logging.basicConfig(
|
||||
filename=os.path.join(tempfile.gettempdir(), b'udsclient.log'),
|
||||
filename=logFile,
|
||||
filemode='a',
|
||||
format='%(levelname)s %(asctime)s %(message)s',
|
||||
level=logging.DEBUG
|
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1 +0,0 @@
|
||||
udsclient_2.0.0_all.deb admin optional
|
17
client/thin/.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>UDSClient-Thin</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.python.pydev.PyDevBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.python.pydev.pythonNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
8
client/thin/.pydevproject
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/${PROJECT_DIR_NAME}/src</path>
|
||||
</pydev_pathproperty>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
</pydev_project>
|
158
client/thin/src/UDSClient.py
Normal file
@@ -0,0 +1,158 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from uds import ui
|
||||
from uds.rest import RestRequest, RetryException
|
||||
from uds.forward import forward
|
||||
from uds import VERSION
|
||||
from uds.log import logger # @UnresolvedImport
|
||||
from uds import tools
|
||||
|
||||
import six
|
||||
import sys
|
||||
import pickle
|
||||
|
||||
|
||||
def approveHost(host):
|
||||
from os.path import expanduser
|
||||
hostsFile = expanduser('~/.udsclient.hosts')
|
||||
|
||||
try:
|
||||
with open(hostsFile, 'r') as f:
|
||||
approvedHosts = f.read().splitlines()
|
||||
except Exception:
|
||||
approvedHosts = []
|
||||
|
||||
host = host.lower()
|
||||
|
||||
if host in approvedHosts:
|
||||
return True
|
||||
|
||||
errorString = 'The server {} must be approved:\n'.format(host)
|
||||
errorString += 'Only approve UDS servers that you trust to avoid security issues.'
|
||||
|
||||
approved = ui.question("ACCESS Warning", errorString)
|
||||
|
||||
if approved:
|
||||
approvedHosts.append(host)
|
||||
logger.debug('Host was approved, saving to approvedHosts file')
|
||||
try:
|
||||
with open(hostsFile, 'w') as f:
|
||||
f.write('\n'.join(approvedHosts))
|
||||
except Exception:
|
||||
logger.warn('Got exception writing to {}'.format(hostsFile))
|
||||
|
||||
return approved
|
||||
|
||||
|
||||
def getWithRetry(rest, url, params=None):
|
||||
while True:
|
||||
try:
|
||||
res = rest.get(url, params)
|
||||
return res
|
||||
except RetryException as e:
|
||||
if ui.question('Service not available', 'Error {}.\nPlease, wait a minute and press "OK" to retry, or "CANCEL" to abort'.format(e)) is True:
|
||||
continue
|
||||
raise Exception('Cancelled by user')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.debug('Initializing connector')
|
||||
|
||||
if six.PY3 is False:
|
||||
logger.debug('Fixing threaded execution of commands')
|
||||
import threading
|
||||
threading._DummyThread._Thread__stop = lambda x: 42
|
||||
|
||||
# First parameter must be url
|
||||
try:
|
||||
uri = sys.argv[1]
|
||||
|
||||
if uri == '--test':
|
||||
sys.exit(0)
|
||||
|
||||
logger.debug('URI: {}'.format(uri))
|
||||
if uri[:6] != 'uds://' and uri[:7] != 'udss://':
|
||||
raise Exception()
|
||||
|
||||
ssl = uri[3] == 's'
|
||||
host, ticket, scrambler = uri.split('//')[1].split('/')
|
||||
logger.debug('ssl: {}, host:{}, ticket:{}, scrambler:{}'.format(ssl, host, ticket, scrambler))
|
||||
|
||||
except Exception:
|
||||
logger.debug('Detected execution without valid URI, exiting')
|
||||
ui.message('UDS Client', 'UDS Client Version {}'.format(VERSION))
|
||||
sys.exit(1)
|
||||
|
||||
rest = RestRequest(host, ssl)
|
||||
logger.debug('Setting request URL to {}'.format(rest.restApiUrl))
|
||||
|
||||
# Main requests part
|
||||
# First, get version
|
||||
try:
|
||||
res = getWithRetry(rest, '')
|
||||
|
||||
logger.debug('Got information {}'.format(res))
|
||||
|
||||
if res['requiredVersion'] > VERSION:
|
||||
ui.message("New UDS Client available", "A new uds version is needed in order to access this version of UDS.\nPlease, download and install it")
|
||||
sys.exit(1)
|
||||
|
||||
res = getWithRetry(rest, '/{}/{}'.format(ticket, scrambler), params={'hostname': tools.getHostName(), 'version': VERSION})
|
||||
|
||||
script = res.decode('base64').decode('bz2')
|
||||
|
||||
logger.debug('Script: {}'.format(script))
|
||||
|
||||
six.exec_(script, globals(), {'parent': None})
|
||||
except Exception as e:
|
||||
error = 'ERROR: {}'.format(e)
|
||||
logger.error(error)
|
||||
ui.message('Error', error)
|
||||
sys.exit(2)
|
||||
|
||||
# Finalize
|
||||
try:
|
||||
tools.waitForTasks()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
tools.unlinkFiles()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
tools.execBeforeExit()
|
||||
except Exception:
|
||||
pass
|
1
client/thin/src/uds/__init__.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../full/src/uds/__init__.py
|
1
client/thin/src/uds/forward.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../full/src/uds/forward.py
|
1
client/thin/src/uds/log.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../full/src/uds/log.py
|
1
client/thin/src/uds/osDetector.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../full/src/uds/osDetector.py
|
86
client/thin/src/uds/rest.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import requests
|
||||
from . import VERSION
|
||||
|
||||
import json
|
||||
import six
|
||||
import osDetector
|
||||
|
||||
|
||||
from .log import logger
|
||||
|
||||
class RetryException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class RestRequest(object):
|
||||
|
||||
restApiUrl = ''
|
||||
|
||||
def __init__(self, host, ssl=True): # parent not used
|
||||
super(RestRequest, self).__init__()
|
||||
|
||||
self.host = host
|
||||
self.ssl = ssl
|
||||
self.restApiUrl = '{}://{}/rest/client'.format(['http', 'https'][ssl], host)
|
||||
|
||||
def get(self, url, params=None):
|
||||
url = self.restApiUrl + url
|
||||
if params is not None:
|
||||
url += '?' + '&'.join('{}={}'.format(k, six.moves.urllib.parse.quote(six.text_type(v).encode('utf8'))) for k, v in params.iteritems()) # @UndefinedVariable
|
||||
|
||||
logger.debug('Requesting {}'.format(url))
|
||||
|
||||
try:
|
||||
r = requests.get(url, headers={'Content-type': 'application/json', 'User-Agent': osDetector.getOs() + " - UDS Connector " + VERSION })
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
raise Exception('Error connecting to UDS Server at {}'.format(self.restApiUrl[0:-11]))
|
||||
|
||||
if r.ok:
|
||||
logger.debug('Request was OK. {}'.format(r.text))
|
||||
data = json.loads(r.text)
|
||||
if not 'error' in data:
|
||||
return data['result']
|
||||
# Has error
|
||||
if data.get('retryable', '0') == '1':
|
||||
raise RetryException(data['error'])
|
||||
|
||||
raise Exception(data['error'])
|
||||
else:
|
||||
logger.error('Error requesting {}: {}, {}'.format(url, r.code. r.text))
|
||||
raise Exception('Error {}: {}'.format(r.code, r.text))
|
||||
|
||||
return data
|
1
client/thin/src/uds/tools.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../full/src/uds/tools.py
|
44
client/thin/src/uds/ui/__init__.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
try:
|
||||
import gtkui as theUI
|
||||
except Exception:
|
||||
import consoleui as theUI # @Reimport
|
||||
|
||||
def message(title, message):
|
||||
theUI.message(title, message)
|
||||
|
||||
def question(title, message):
|
||||
return theUI.question(title, message)
|
||||
|
58
client/thin/src/uds/ui/browser.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
import random
|
||||
import os
|
||||
import tempfile
|
||||
import string
|
||||
import webbrowser
|
||||
|
||||
TEMPLATE = '''<html>
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{title}</h1>
|
||||
<p>{message}<P>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
def _htmlFilename():
|
||||
return os.path.join(tempfile.gettempdir(), ''.join([random.choice(string.ascii_lowercase) for i in range(22)]) + '.html')
|
||||
|
||||
def message(title, message):
|
||||
filename = _htmlFilename()
|
||||
with open(filename, 'w') as f:
|
||||
f.write(TEMPLATE.format(title=title, message=message))
|
||||
|
||||
webbrowser.open('file://' + filename, new=0, autoraise=False)
|
49
client/thin/src/uds/ui/consoleui.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
import sys
|
||||
import time
|
||||
from uds.log import logger
|
||||
|
||||
counter = 0
|
||||
|
||||
def message(title, message):
|
||||
sys.stderr.write("** {} **\n {}\n".format(title, message))
|
||||
|
||||
def question(title, message):
|
||||
global counter
|
||||
if counter > 100: # 5 minutes
|
||||
return False
|
||||
counter += 1
|
||||
sys.stderr.write("** {} **\n{}\nReturning YES in 3 seconds. (counter is {})\n".format(title, message, counter))
|
||||
time.sleep(3) # Wait 3 seconds before returning
|
||||
return True
|
143
client/thin/src/uds/ui/gtkui.py
Normal file
@@ -0,0 +1,143 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
'''
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import re
|
||||
|
||||
import pygtk
|
||||
pygtk.require('2.0')
|
||||
import gtk
|
||||
import gobject
|
||||
|
||||
LINE_LEN = 65
|
||||
|
||||
class Dialog():
|
||||
def __init__(self, title, message, timeout=-1, withCancel=True):
|
||||
self.title = title
|
||||
self.message = message
|
||||
self.timeout = timeout
|
||||
self.withCancel = withCancel
|
||||
|
||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
self.window.set_position(gtk.WIN_POS_CENTER)
|
||||
# self.window.set_size_request(320, 200)
|
||||
self.window.set_title(self.title)
|
||||
self.create_widgets()
|
||||
self.connect_signals()
|
||||
self.window.show_all()
|
||||
|
||||
self.window.connect("destroy", self.destroy)
|
||||
|
||||
# Setup "auto OK" timer
|
||||
if timeout != -1:
|
||||
self.timerId = gobject.timeout_add(self.timeout * 1000, self.callback_timer)
|
||||
else:
|
||||
self.timerId = -1
|
||||
|
||||
self.result = False
|
||||
|
||||
gtk.main()
|
||||
|
||||
@property
|
||||
def adapted_message(self):
|
||||
msg = ''
|
||||
for l in re.sub(r'<p[^>]*>', '', self.message).replace('</p>', '\n').split('\n'):
|
||||
words = []
|
||||
length = 0
|
||||
for word in l.split(' '):
|
||||
if length + len(word) >= LINE_LEN:
|
||||
msg += ' '.join(words) + '\n'
|
||||
words = []
|
||||
length = 0
|
||||
length += len(word) + 1
|
||||
words.append(word)
|
||||
msg += ' '.join(words) + '\n'
|
||||
return msg
|
||||
|
||||
def create_widgets(self):
|
||||
self.vbox = gtk.VBox(spacing=10)
|
||||
self.vbox.set_size_request(490, -1)
|
||||
|
||||
self.messageLabel = gtk.Label()
|
||||
# Fix message markup
|
||||
# self.message = re.sub(r'<p[^>]*>', '<span font_weight="bold">', self.message).replace('</p>', '</span>\n' )
|
||||
|
||||
# Set as simple markup
|
||||
self.messageLabel.set_markup('\n' + self.adapted_message + '\n')
|
||||
self.messageLabel.set_alignment(xalign=0.5, yalign=1)
|
||||
|
||||
self.hbox = gtk.HBox(spacing=10)
|
||||
self.button_ok = gtk.Button("OK")
|
||||
self.hbox.pack_start(self.button_ok)
|
||||
|
||||
if self.withCancel:
|
||||
self.button_cancel = gtk.Button("Cancel")
|
||||
self.hbox.pack_start(self.button_cancel)
|
||||
|
||||
self.vbox.pack_start(self.messageLabel)
|
||||
self.vbox.pack_start(self.hbox)
|
||||
|
||||
self.window.add(self.vbox)
|
||||
|
||||
def connect_signals(self):
|
||||
self.button_ok.connect("clicked", self.callback_ok)
|
||||
if self.withCancel:
|
||||
self.button_cancel.connect("clicked", self.callback_cancel)
|
||||
|
||||
def destroy(self, widget, data=None):
|
||||
self.setResult(False)
|
||||
|
||||
def setResult(self, val):
|
||||
if self.timerId != -1:
|
||||
gobject.source_remove(self.timerId)
|
||||
self.timerId = -1
|
||||
|
||||
self.result = val
|
||||
self.window.hide()
|
||||
gtk.main_quit()
|
||||
|
||||
|
||||
def callback_ok(self, widget, callback_data=None):
|
||||
self.setResult(True)
|
||||
|
||||
def callback_cancel(self, widget, callback_data=None):
|
||||
self.setResult(False)
|
||||
|
||||
def callback_timer(self):
|
||||
self.setResult(True)
|
||||
|
||||
def message(title, message):
|
||||
Dialog(title, message, withCancel=False)
|
||||
|
||||
def question(title, message):
|
||||
dlg = Dialog(title, message, timeout=30, withCancel=True)
|
||||
return dlg.result
|
4
client/thin/src/udsclient
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd /lib/UDSClient
|
||||
exec python UDSClient.pyc $@
|
11
client/thin/thinstation/README.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Steps:
|
||||
1.- If building from repository, full copy (recursive) the "src" folder of "udsclient/thin" inside the "udsclient" folder. If building from the .tar.gz, simply ignor4e this step
|
||||
2.- Copy the folder "udsclient" to /build/packages inside the thinstation build environment
|
||||
3.- enter the chroot of thinstation
|
||||
4.- go to the udsclient folder (/build/packages/udsclient)
|
||||
5.- Execute "build.sh"
|
||||
6.- Edit the file /build/build.conf, and add this line:
|
||||
package udsclient
|
||||
7.- Execute the build process
|
||||
|
||||
Ready!!!
|
0
client/thin/thinstation/udsclient/.dna
Normal file
2
client/thin/thinstation/udsclient/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
lib
|
||||
src
|
11
client/thin/thinstation/udsclient/UDSClient.desktop
Normal file
@@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Name=UDSClient
|
||||
Comment=UDS Helper
|
||||
Keywords=uds;client;vdi;
|
||||
Exec=/bin/udsclient %u
|
||||
Icon=help-browser
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Utility;
|
||||
MimeType=x-scheme-handler/uds;x-scheme-handler/udss;
|
4
client/thin/thinstation/udsclient/bin/udsclient
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd /lib/UDSClient
|
||||
exec python UDSClient.pyc $@
|
13
client/thin/thinstation/udsclient/build.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
pip install paramiko requests six
|
||||
rm -rf lib
|
||||
mkdir -p lib/python2.7/site-packages
|
||||
for a in requests paramiko pyasn1 cryptography packaging idna asn1crypto six enum ipaddress cffi ; do cp -r /usr/lib/python2.7/site-packages/$a* lib/python2.7/site-packages/; done
|
||||
cp src/udsclient bin
|
||||
chmod 755 bin/udsclient
|
||||
mkdir lib/UDSClient
|
||||
cp src/UDSClient.py lib/UDSClient
|
||||
chmod 755 lib/UDSClient/UDSClient.py
|
||||
cp -r src/uds lib/UDSClient
|
||||
mkdir lib/applications
|
||||
cp UDSClient.desktop lib/applications
|
5
client/thin/thinstation/udsclient/dependencies
Normal file
@@ -0,0 +1,5 @@
|
||||
base
|
||||
#add your own dependancies to this file, base should always be included.
|
||||
python
|
||||
pygtk
|
||||
freerdp
|
15
client/thin/thinstation/udsclient/etc/cmd/README
Normal file
@@ -0,0 +1,15 @@
|
||||
In here you place the commands to start your application if using the scripts
|
||||
|
||||
/etc/thinstation.packages
|
||||
or /etc/thinstation.console
|
||||
|
||||
see examples for for information
|
||||
|
||||
|
||||
possible types are
|
||||
|
||||
example.global (this is always needed)
|
||||
example.menu
|
||||
example.console
|
||||
example.window
|
||||
example.fullscreen
|
1
client/thin/thinstation/udsclient/etc/cmd/example.fullscreen
Executable file
@@ -0,0 +1 @@
|
||||
CMD_FULLSCREEN="example -FULLSCREEN"
|
1
client/thin/thinstation/udsclient/etc/cmd/example.global
Executable file
@@ -0,0 +1 @@
|
||||
CMD_GLOBAL="example -startapp"
|
1
client/thin/thinstation/udsclient/etc/console/README
Normal file
@@ -0,0 +1 @@
|
||||
Place a 0 length file in here as the same name as the package if your application is a Console App
|
34
client/thin/thinstation/udsclient/etc/init.d/your_start_up_script
Executable file
@@ -0,0 +1,34 @@
|
||||
#! /bin/sh
|
||||
|
||||
. /etc/thinstation.global
|
||||
|
||||
# note you can replace this package with a symlink to /etc/thinstation.packages
|
||||
# for GUI apps, or /etc/thinstation.console for console apps
|
||||
# if you do then you will need to create a seperate initilization script for
|
||||
# any other parameters which need to be started at bootup
|
||||
|
||||
|
||||
case "$1" in
|
||||
init)
|
||||
if ! pkg_initialized $PACKAGE; then
|
||||
|
||||
# Your startup instructions go here
|
||||
|
||||
pkg_set_init_flag $PACKAGE
|
||||
fi
|
||||
;;
|
||||
console)
|
||||
;;
|
||||
window)
|
||||
;;
|
||||
fullscreen)
|
||||
;;
|
||||
help)
|
||||
echo "Usage: $0 init"
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
@@ -0,0 +1 @@
|
||||
/etc/init.d/your_start_up_script
|
13
guacamole-tunnel/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Backup files
|
||||
*~
|
||||
|
||||
# Generated files
|
||||
src/main/webapp/META-INF/
|
||||
src/main/webapp/generated/
|
||||
target/
|
||||
|
||||
# IDE-specific configuration
|
||||
nb-configuration.xml
|
||||
.classpath
|
||||
.project
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<groupId>org.openuds.server</groupId>
|
||||
<artifactId>transport</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.0.0</version>
|
||||
<version>2.5.0</version>
|
||||
<name>Guacamole Transport</name>
|
||||
<url>https://github.com/dkmstr/openuds</url>
|
||||
|
||||
@@ -81,14 +81,14 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.guacamole</groupId>
|
||||
<artifactId>guacamole-common</artifactId>
|
||||
<version>0.9.9-incubating</version>
|
||||
<version>0.9.10-incubating</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Guacamole JavaScript library -->
|
||||
<dependency>
|
||||
<groupId>org.apache.guacamole</groupId>
|
||||
<artifactId>guacamole-common-js</artifactId>
|
||||
<version>0.9.9-incubating</version>
|
||||
<version>0.9.12-incubating</version>
|
||||
<type>zip</type>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2013 Glyptodon LLC
|
||||
Copyright (C) 2017 Glyptodon, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -147,30 +147,12 @@
|
||||
|
||||
<!-- guacamole-default-webapp scripts -->
|
||||
<script type="text/javascript" src="scripts/session.js"></script>
|
||||
<script type="text/javascript" src="scripts/history.js"></script>
|
||||
<script type="text/javascript" src="scripts/service.js"></script>
|
||||
<script type="text/javascript" src="scripts/guac-ui.js"></script>
|
||||
<script type="text/javascript" src="scripts/client-ui.js"></script>
|
||||
|
||||
<!-- Init -->
|
||||
<script type="text/javascript"> /* <![CDATA[ */
|
||||
|
||||
/*function getQueryParams(qs) {
|
||||
qs = qs.split("+").join(" ");
|
||||
|
||||
var params = {}, tokens,
|
||||
re = /[?&]?([^=]+)=([^&]*)/g;
|
||||
|
||||
while (tokens = re.exec(qs)) {
|
||||
params[decodeURIComponent(tokens[1])]
|
||||
= decodeURIComponent(tokens[2]);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
window.query = getQueryParams(document.location.search);*/
|
||||
|
||||
// Adapted to 1.5
|
||||
function getQueryParams(qs) {
|
||||
qs = qs.split("+").join(" ");
|
||||
@@ -187,16 +169,11 @@
|
||||
|
||||
window.query = getQueryParams(document.location.href);
|
||||
|
||||
// Sanity check Guacamole JavaScript API version
|
||||
// if (Guacamole.API_VERSION !== "0.9.1")
|
||||
// GuacUI.Client.showStatus("Clear Your Cache", "An older version of Guacamole has been cached by your browser. Please clear your browser's cache and try again.");
|
||||
|
||||
// Start connect after control returns from onload (allow browser
|
||||
// to consider the page loaded).
|
||||
//else
|
||||
window.onload = function() {
|
||||
window.setTimeout(GuacUI.Client.connect, 10);
|
||||
};
|
||||
window.onload = function() {
|
||||
window.setTimeout(GuacUI.Client.connect, 10);
|
||||
};
|
||||
|
||||
/* ]]> */ </script>
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* Copyright (C) 2017 Glyptodon, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -746,48 +746,6 @@ GuacUI.Client.Pinch = function(element) {
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Flattens the attached Guacamole.Client, storing the result within the
|
||||
* connection history.
|
||||
*/
|
||||
GuacUI.Client.updateThumbnail = function() {
|
||||
|
||||
var guac = GuacUI.Client.attachedClient;
|
||||
if (!guac)
|
||||
return;
|
||||
|
||||
// Do not create empty thumbnails
|
||||
if (guac.getDisplay().getWidth() <= 0 || guac.getDisplay().getHeight() <= 0)
|
||||
return;
|
||||
|
||||
// Get screenshot
|
||||
var canvas = guac.getDisplay().flatten();
|
||||
|
||||
// Calculate scale of thumbnail (max 320x240, max zoom 100%)
|
||||
var scale = Math.min(
|
||||
320 / canvas.width,
|
||||
240 / canvas.height,
|
||||
1
|
||||
);
|
||||
|
||||
// Create thumbnail canvas
|
||||
var thumbnail = document.createElement("canvas");
|
||||
thumbnail.width = canvas.width*scale;
|
||||
thumbnail.height = canvas.height*scale;
|
||||
|
||||
// Scale screenshot to thumbnail
|
||||
var context = thumbnail.getContext("2d");
|
||||
context.drawImage(canvas,
|
||||
0, 0, canvas.width, canvas.height,
|
||||
0, 0, thumbnail.width, thumbnail.height
|
||||
);
|
||||
|
||||
// Save thumbnail to history
|
||||
var id = decodeURIComponent(window.location.search.substring(4));
|
||||
GuacamoleHistory.update(id, thumbnail.toDataURL());
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current display scale to the given value, where 1 is 100% (1:1
|
||||
* pixel ratio). Out-of-range values will be clamped in-range.
|
||||
@@ -1588,15 +1546,11 @@ GuacUI.Client.attach = function(guac) {
|
||||
}, false);
|
||||
|
||||
/*
|
||||
* Disconnect and update thumbnail on close
|
||||
* Disconnect on close
|
||||
*/
|
||||
window.onunload = function() {
|
||||
|
||||
GuacUI.Client.updateThumbnail();
|
||||
|
||||
if (GuacUI.Client.attachedClient)
|
||||
GuacUI.Client.attachedClient.disconnect();
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|