1
0
mirror of https://github.com/dkmstr/openuds.git synced 2025-10-04 05:44:42 +03:00

Compare commits

..

2 Commits
v2.2 ... v2.0

Author SHA1 Message Date
Adolfo Gómez García
15a76f3b9b Small 2.0 fix 2017-04-07 10:47:57 +02:00
Adolfo Gómez García
a3110d4623 fixed tunneld cord access 2017-03-18 11:48:52 +01:00
399 changed files with 20525 additions and 62049 deletions

3
.gitignore vendored
View File

@@ -7,7 +7,6 @@
*_enterprise.*
.settings/
.ipynb_checkpoints
.mypy_cache
# Debian buildings
*.debhelper*
@@ -165,5 +164,3 @@
/udsService/udsgui/obj/Debug
/udsService/udsgui/obj/Release
/udsService/udsgui/obj/x86
.vscode

View File

@@ -1 +1 @@
2.2.1
2.0.0

6
actors/.gitignore vendored
View File

@@ -3,8 +3,6 @@ bin
udsactor*.deb
udsactor*.build
udsactor*.changes
/udsactor_*.dsc
/udsactor_*.tar.xz
/udsactor_*_amd64.buildinfo
/udsactor_1.7.0.dsc
/udsactor_1.7.0.tar.xz
/udsactor*.rpm
linux/debian/files

View File

@@ -69,14 +69,12 @@ install-udsactor:
cp scripts/udsactor $(BINDIR)
cp scripts/UDSActorConfig-pkexec $(SBINDIR)
cp scripts/UDSActorTool-startup $(BINDIR)
cp scripts/udsvapp ${BINDIR}
# Policy to run as administrator
cp policy/org.openuds.pkexec.UDSActorConfig.policy $(POLKITDIR)
# Fix permissions
chmod 755 $(BINDIR)/udsactor
chmod 755 $(BINDIR)/udsvapp
chmod 755 $(BINDIR)/UDSActorTool-startup
chmod 755 $(SBINDIR)/UDSActorConfig-pkexec
chmod 755 $(LIBDIR)/UDSActorConfig.py
@@ -95,4 +93,4 @@ endif
uninstall:
rm -rf $(LIBDIR)
# rm -f $(BINDIR)/udsactor
rm -rf $(CFGDIR)
rm -rf $(CFGDIR)

View File

@@ -1,21 +1,3 @@
udsactor (2.2.1) stable; urgency=medium
* Upgraded to 2.2.1 release
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 2 Oct 2018 12:44:12 +0200
udsactor (2.2.0) stable; urgency=medium
* Upgraded to 2.2.0 release
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 19 Oct 2017 16:44:12 +0200
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

View File

@@ -10,8 +10,22 @@ Package: udsactor
Section: admin
Priority: optional
Architecture: all
Depends: policykit-1(>=0.100), python3-requests (>=0.8.2), python3-pyqt4 (>=4.9), python3-six(>=1.1), python3 (>=3.4), libxss1, xscreensaver, ${misc:Depends}
Recommends: python3-prctl(>=1.1.1)
Depends: policykit-1(>=0.100), python-requests (>=0.8.2), python-qt4 (>=4.9), python-six(>=1.1), python-prctl(>=1.1.1), python (>=2.7), libxss1, ${misc:Depends}
Description: Actor for Universal Desktop Services (UDS) Broker
This package provides the required components to allow this machine to work on an environment managed by UDS Broker.
Package: udsactor-xrdp
Section: x11
Priority: optional
Architecture: all
Depends: xrdp (>= 0.5.0), udsactor (>= ${binary:Version}), libpam-modules-bin (>=1.0), ${misc:Depends}
Description: UDS Actor component for xrdp
This package provides connection between uds actor and xrdp
Package: udsactor-nx
Section: x11
Priority: optional
Architecture: all
Depends: nxnode (>= 3.5.0), udsactor (>= ${binary:Version}), ${misc:Depends}
Description: UDS Actor component for nx
This package provides connection between uds actor and nx

View File

@@ -0,0 +1,3 @@
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

View File

@@ -5,7 +5,6 @@
set -e
case "$1" in
configure)
/usr/bin/python3 -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

View File

@@ -8,5 +8,5 @@ Type=Application
NoDisplay=true
X-KDE-autostart-after=panel
X-KDE-StartupNotify=false
X-DBUS-StartupType=None
X-KDE-UniqueApplet=false
X-DBUS-StartupType=Unique
X-KDE-UniqueApplet=true

View File

@@ -3,4 +3,4 @@
FOLDER=/usr/share/UDSActor
cd $FOLDER
exec python3 -m udsactor.linux.UDSActorService $@
python -m udsactor.linux.UDSActorService $@

View File

@@ -1,5 +0,0 @@
#!/bin/sh
/usr/bin/udsactor login "$USER"
$@
/usr/bin/udsactor logout "$USER"

View File

@@ -60,7 +60,6 @@ This package provides the required components to allow this machine to work on a
/etc/init.d/udsactor
/usr/bin/UDSActorTool-startup
/usr/bin/udsactor
/usr/bin/udsvapp
/usr/bin/UDSActorTool
/usr/sbin/UDSActorConfig
/usr/sbin/UDSActorConfig-pkexec

View File

@@ -1,6 +1,4 @@
build
dist
*.spec
.idea
*_enterprise*
/samples/

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
@@ -33,7 +33,6 @@
from __future__ import unicode_literals
import sys
import os
from PyQt4 import QtCore, QtGui
import six
@@ -93,13 +92,7 @@ class UDSConfigDialog(QtGui.QDialog):
store.writeConfig(cfg)
self.close()
if __name__ == "__main__":
# If to be run as "sudo" on linux, we will need this to avoid problems
if 'linux' in sys.platform:
os.environ['QT_X11_NO_MITSHM'] = '1'
app = QtGui.QApplication(sys.argv)
if store.checkPermissions() is False:

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
@@ -39,7 +39,6 @@ import pickle
import time
import datetime
import signal
import six
from udsactor import ipc
from udsactor import utils
from udsactor.log import logger
@@ -52,19 +51,14 @@ from udsactor import VERSION
trayIcon = None
doLogoff = False
TIMER_TIMEOUT = 5 # In seconds
def sigTerm(sigNo, stackFrame):
if trayIcon:
trayIcon.quit(extra=" (by sigterm)")
trayIcon.quit()
# About dialog
class UDSAboutDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_UDSAboutDialog()
@@ -76,7 +70,6 @@ class UDSAboutDialog(QtGui.QDialog):
class UDSMessageDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_UDSMessageDialog()
@@ -93,13 +86,13 @@ class UDSMessageDialog(QtGui.QDialog):
class MessagesProcessor(QtCore.QThread):
logoff = QtCore.pyqtSignal(name='logoff')
displayMessage = QtCore.pyqtSignal(six.text_type, name='displayMessage')
script = QtCore.pyqtSignal(six.text_type, name='script')
displayMessage = QtCore.pyqtSignal(QtCore.QString, name='displayMessage')
script = QtCore.pyqtSignal(QtCore.QString, name='script')
exit = QtCore.pyqtSignal(name='exit')
information = QtCore.pyqtSignal(dict, name='information')
def __init__(self):
super(MessagesProcessor, self).__init__()
super(self.__class__, self).__init__()
# Retries connection for a while
for _ in range(10):
try:
@@ -150,11 +143,11 @@ class MessagesProcessor(QtCore.QThread):
msgId, data = msg
logger.debug('Got Message on User Space: {}:{}'.format(msgId, data))
if msgId == ipc.MSG_MESSAGE:
self.displayMessage.emit(data)
self.displayMessage.emit(QtCore.QString.fromUtf8(data))
elif msgId == ipc.MSG_LOGOFF:
self.logoff.emit()
elif msgId == ipc.MSG_SCRIPT:
self.script.emit(data)
self.script.emit(QtCore.QString.fromUtf8(data))
elif msgId == ipc.MSG_INFORMATION:
self.information.emit(pickle.loads(data))
except Exception as e:
@@ -170,7 +163,6 @@ class MessagesProcessor(QtCore.QThread):
class UDSSystemTray(QtGui.QSystemTrayIcon):
def __init__(self, app_, parent=None):
self.app = app_
@@ -211,34 +203,20 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
self.counter = 0
self.resetTimervars()
self.timer.start(TIMER_TIMEOUT * 1000) # Launch idle checking every 5 seconds
self.timer.start(5000) # Launch idle checking every 5 seconds
self.graceTimerShots = 6 # Start counting for idle after 30 seconds after login, got on windows some "instant" logout because of idle timer not being reset??
self.ipc.start()
# If this is running, it's because he have logged in
self.ipc.sendLogin(operations.getCurrentUser())
def resetTimervars(self):
self.lastTimerTime = datetime.datetime.now()
self.graceTimerShots = 6 # Start counting for idle after 30 seconds after login, got on windows some "instant" logout because of idle timer not being reset??
def checkTimers(self):
# Check clock readjustment
# This is executed
elapsed_seconds = (datetime.datetime.now() - self.lastTimerTime).total_seconds()
if elapsed_seconds > TIMER_TIMEOUT * 4 or elapsed_seconds < 0:
# Clock has changed a lot, reset session variables, idle timer, etc..
self.resetTimervars()
return
self.lastTimerTime = datetime.datetime.now()
self.checkIdle()
self.checkMaxSession()
def checkMaxSession(self):
if self.maxSessionTime is None or self.maxSessionTime == 0:
logger.debug('Returning because maxSessionTime is zero')
logger.debug('Returning because maxSessionTime is cero')
return
remainingTime = self.maxSessionTime - (datetime.datetime.now() - self.sessionStart).total_seconds()
@@ -251,7 +229,7 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
if remainingTime <= 0:
logger.debug('Remaining time is less than cero, exiting')
self.quit(extra=" (max session time {} {})".format(self.maxSessionTime, self.sessionStart))
self.quit()
def checkIdle(self):
if self.maxIdleTime is None: # No idle check
@@ -275,7 +253,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(logoff=True, extra=' (idle: {} vs {})'.format(idleTime, self.maxIdleTime))
self.quit()
def displayMessage(self, message):
logger.debug('Displaying message')
@@ -312,32 +290,32 @@ class UDSSystemTray(QtGui.QSystemTrayIcon):
def about(self):
self.aboutDlg.exec_()
def quit(self, logoff=False, extra=''):
global doLogoff # pylint: disable=global-statement
def quit(self):
logger.debug('Quit invoked')
if not self.stopped:
if self.stopped is False:
self.stopped = True
try:
# If we close Client, send Logoff to Broker
# if sys.platform != 'win32':
self.ipc.sendLogout(operations.getCurrentUser() + extra)
self.ipc.sendLogout(operations.getCurrentUser())
self.timer.stop()
self.ipc.stop()
except Exception:
# May we have lost connection with server, simply exit in that case
pass
doLogoff = logoff
try:
operations.loggoff() # Invoke log off
except Exception:
pass
self.app.quit()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
# if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
# # QtGui.QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.")
# sys.exit(1)
if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
# QtGui.QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system.")
sys.exit(1)
# This is important so our app won't close on message windows
QtGui.QApplication.setQuitOnLastWindowClosed(False)
@@ -349,24 +327,16 @@ if __name__ == '__main__':
sys.exit(1)
# Sets a default idle duration, but will not be used unless idle is notified from server
operations.initIdleDuration(3600 * 16)
operations.initIdleDuration(3600 * 10)
trayIcon.show()
# Catch kill and logout user :)
signal.signal(signal.SIGTERM, sigTerm)
# app.aboutToQuit.connect()
res = app.exec_()
logger.debug('Exiting')
trayIcon.quit(logoff=doLogoff) # Pass existing doLogoff
if doLogoff:
try:
time.sleep(1)
operations.loggoff() # Invoke log off
except Exception:
pass
trayIcon.quit()
sys.exit(res)

View File

@@ -2,7 +2,8 @@
# Resource object code
#
# Created by: The Resource Compiler for PyQt4 (Qt v4.8.7)
# Created: Mon Apr 27 22:05:02 2015
# by: The Resource Compiler for PyQt (Qt v4.8.6)
#
# WARNING! All changes made in this file will be lost!

View File

@@ -2,7 +2,8 @@
# Form implementation generated from reading ui file 'about-dialog.ui'
#
# Created by: PyQt4 UI code generator 4.12.1
# Created: Mon Apr 27 22:05:02 2015
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
@@ -33,8 +34,8 @@ class Ui_UDSAboutDialog(object):
UDSAboutDialog.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedStates))
UDSAboutDialog.setModal(True)
self.vboxlayout = QtGui.QVBoxLayout(UDSAboutDialog)
self.vboxlayout.setMargin(9)
self.vboxlayout.setSpacing(9)
self.vboxlayout.setMargin(9)
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
self.LogoLabel = QtGui.QLabel(UDSAboutDialog)
self.LogoLabel.setObjectName(_fromUtf8("LogoLabel"))
@@ -54,8 +55,8 @@ class Ui_UDSAboutDialog(object):
self.aboutTab = QtGui.QWidget()
self.aboutTab.setObjectName(_fromUtf8("aboutTab"))
self.vboxlayout1 = QtGui.QVBoxLayout(self.aboutTab)
self.vboxlayout1.setMargin(9)
self.vboxlayout1.setSpacing(6)
self.vboxlayout1.setMargin(9)
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
self.aboutBrowser = QtGui.QTextBrowser(self.aboutTab)
self.aboutBrowser.setOpenExternalLinks(True)
@@ -65,8 +66,8 @@ class Ui_UDSAboutDialog(object):
self.authorsTab = QtGui.QWidget()
self.authorsTab.setObjectName(_fromUtf8("authorsTab"))
self.vboxlayout2 = QtGui.QVBoxLayout(self.authorsTab)
self.vboxlayout2.setMargin(9)
self.vboxlayout2.setSpacing(6)
self.vboxlayout2.setMargin(9)
self.vboxlayout2.setObjectName(_fromUtf8("vboxlayout2"))
self.authorsBrowser = QtGui.QTextBrowser(self.authorsTab)
self.authorsBrowser.setOpenExternalLinks(True)
@@ -76,8 +77,8 @@ class Ui_UDSAboutDialog(object):
self.licenseTab = QtGui.QWidget()
self.licenseTab.setObjectName(_fromUtf8("licenseTab"))
self.vboxlayout3 = QtGui.QVBoxLayout(self.licenseTab)
self.vboxlayout3.setMargin(9)
self.vboxlayout3.setSpacing(6)
self.vboxlayout3.setMargin(9)
self.vboxlayout3.setObjectName(_fromUtf8("vboxlayout3"))
self.licenseBrowser = QtGui.QTextBrowser(self.licenseTab)
self.licenseBrowser.setObjectName(_fromUtf8("licenseBrowser"))
@@ -91,7 +92,7 @@ class Ui_UDSAboutDialog(object):
self.vboxlayout.addWidget(self.buttonBox)
self.retranslateUi(UDSAboutDialog)
self.tabWidget.setCurrentIndex(2)
self.tabWidget.setCurrentIndex(0)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("clicked(QAbstractButton*)")), UDSAboutDialog.closeDialog)
QtCore.QMetaObject.connectSlotsByName(UDSAboutDialog)
@@ -105,7 +106,7 @@ class Ui_UDSAboutDialog(object):
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\';\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\'; font-weight:600;\">(c) 2012-2016, Virtual Cable S.L.U.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'Sans Serif\'; font-weight:600;\">(c) 2014, Virtual Cable S.L.U.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'Sans Serif\'; font-style:italic;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.udsenterprise.com\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.udsenterprise.com</span></a></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.openuds.org\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt; text-decoration: underline; color:#0000ff;\">http://www.openuds.org</span></a></p>\n"
@@ -121,7 +122,7 @@ class Ui_UDSAboutDialog(object):
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Verdana\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Copyright (c) 2012-2016 Virtual Cable S.L.</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">Copyright (c) 2014 Virtual Cable S.L.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'MS Shell Dlg 2\'; font-size:8pt;\">All rights reserved.</span></p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'MS Shell Dlg 2\'; font-size:8pt;\"><br /></p>\n"

View File

@@ -2,7 +2,8 @@
# Form implementation generated from reading ui file 'message-dialog.ui'
#
# Created by: PyQt4 UI code generator 4.12.1
# Created: Mon Apr 27 22:05:02 2015
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!

View File

@@ -121,7 +121,7 @@
<x>20</x>
<y>20</y>
<width>361</width>
<height>166</height>
<height>131</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
@@ -205,7 +205,7 @@
<item row="3" column="1">
<widget class="QComboBox" name="logLevelComboBox">
<property name="currentIndex">
<number>3</number>
<number>1</number>
</property>
<property name="frame">
<bool>true</bool>
@@ -220,11 +220,6 @@
<string notr="true">INFO</string>
</property>
</item>
<item>
<property name="text">
<string>WARN</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">ERROR</string>

View File

@@ -2,7 +2,8 @@
# Form implementation generated from reading ui file 'setup-dialog.ui'
#
# Created by: PyQt4 UI code generator 4.12.1
# Created: Mon Apr 27 22:05:03 2015
# by: PyQt4 UI code generator 4.11.2
#
# WARNING! All changes made in this file will be lost!
@@ -62,7 +63,7 @@ class Ui_UdsActorSetupDialog(object):
self.cancelButton.setSizePolicy(sizePolicy)
self.cancelButton.setObjectName(_fromUtf8("cancelButton"))
self.layoutWidget = QtGui.QWidget(UdsActorSetupDialog)
self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 361, 166))
self.layoutWidget.setGeometry(QtCore.QRect(20, 20, 361, 131))
self.layoutWidget.setObjectName(_fromUtf8("layoutWidget"))
self.formLayout = QtGui.QFormLayout(self.layoutWidget)
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
@@ -101,14 +102,13 @@ class Ui_UdsActorSetupDialog(object):
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(1, _fromUtf8("INFO"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(2, _fromUtf8("ERROR"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(3, _fromUtf8("ERROR"))
self.logLevelComboBox.addItem(_fromUtf8(""))
self.logLevelComboBox.setItemText(4, _fromUtf8("FATAL"))
self.logLevelComboBox.setItemText(3, _fromUtf8("FATAL"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.logLevelComboBox)
self.retranslateUi(UdsActorSetupDialog)
self.logLevelComboBox.setCurrentIndex(3)
self.logLevelComboBox.setCurrentIndex(1)
QtCore.QObject.connect(self.host, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.masterKey, QtCore.SIGNAL(_fromUtf8("textChanged(QString)")), UdsActorSetupDialog.textChanged)
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL(_fromUtf8("pressed()")), UdsActorSetupDialog.cancelAndDiscard)
@@ -139,7 +139,6 @@ class Ui_UdsActorSetupDialog(object):
self.useSSl.setItemText(0, _translate("UdsActorSetupDialog", "Do not use SSL", None))
self.useSSl.setItemText(1, _translate("UdsActorSetupDialog", "Use SSL", None))
self.logLevelLabel.setText(_translate("UdsActorSetupDialog", "Log Level", None))
self.logLevelComboBox.setItemText(2, _translate("UdsActorSetupDialog", "WARN", None))
if __name__ == "__main__":

View File

@@ -78,7 +78,7 @@ class OsManagerError(RESTError):
try:
import urllib3 # @UnusedImport
except Exception:
from requests.packages import urllib3 # @Reimport @UnresolvedImport
from requests.packages import urllib3 # @Reimport
try:
urllib3.disable_warnings() # @UndefinedVariable
@@ -101,7 +101,6 @@ def ensureResultIsOk(result):
class Api(object):
def __init__(self, host, masterKey, ssl):
self.host = host
self.masterKey = masterKey
@@ -113,7 +112,7 @@ class Api(object):
self.maxSession = None
self.secretKey = six.text_type(uuid.uuid4())
try:
self.newerRequestLib = requests.__version__.split('.')[0] >= '1' # @UndefinedVariable
self.newerRequestLib = requests.__version__.split('.')[0] >= '1'
except Exception:
self.newerRequestLib = False # I no version, guess this must be an old requests
@@ -155,11 +154,7 @@ class Api(object):
logger.debug('Requesting with old')
r = requests.post(url, data=data, headers={'content-type': 'application/json'})
# From versions of requests, content maybe bytes or str. We need str for json.loads
content = r.content
if not isinstance(content, six.text_type):
content = content.decode('utf8')
r = json.loads(content) # Using instead of r.json() to make compatible with oooold rquests lib versions
r = json.loads(r.content) # Using instead of r.json() to make compatible with oooold rquests lib versions
except requests.exceptions.RequestException as e:
raise ConnectionError(e)
except Exception as e:
@@ -206,8 +201,6 @@ class Api(object):
raise ConnectionError('REST api has not been initialized')
if processData:
if data and not isinstance(data, six.text_type):
data = data.decode('utf8')
data = json.dumps({'data': data})
url = self._getUrl('/'.join([self.uuid, msg]))
return self._request(url, data)['result']

View File

@@ -34,22 +34,21 @@ from __future__ import unicode_literals
# On centos, old six release does not includes byte2int, nor six.PY2
import six
VERSION = '2.2.1'
VERSION = '2.0.0'
__title__ = 'udsactor'
__version__ = VERSION
__build__ = 0x010756
__build__ = 0x010750
__author__ = 'Adolfo Gómez <dkmaster@dkmon.com>'
__license__ = "BSD 3-clause"
__copyright__ = "Copyright 2014-2018 VirtualCable S.L.U."
__copyright__ = "Copyright 2014-2016 VirtualCable S.L.U."
if not hasattr(six, 'byte2int'):
if six.PY3:
import operator
six.byte2int = operator.itemgetter(0)
else:
def _byte2int(bs):
return ord(bs[0])
six.byte2int = _byte2int

View File

@@ -116,8 +116,8 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
try:
HTTPServerHandler.lock.acquire()
length = int(self.headers.get('content-length'))
content = self.rfile.read(length).decode('utf8')
length = int(self.headers.getheader('content-length'))
content = self.rfile.read(length)
logger.debug('length: {}, content >>{}<<'.format(length, content))
params = json.loads(content)
@@ -181,7 +181,7 @@ class HTTPServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
logger.error('HTTP ' + fmt % args)
def log_message(self, fmt, *args):
logger.debug('HTTP ' + fmt % args)
logger.info('HTTP ' + fmt % args)
class HTTPServerThread(threading.Thread):
@@ -196,22 +196,13 @@ 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.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 = socketserver.TCPServer(address, HTTPServerHandler)
self.server.socket = ssl.wrap_socket(self.server.socket, certfile=self.certFile, server_side=True)
def getServerUrl(self):
return 'https://{}:{}/{}'.format(self.getIp(), self.getPort(), HTTPServerHandler.uuid)
return 'https://{}:{}/{}'.format(self.server.server_address[0], self.server.server_address[1], HTTPServerHandler.uuid)
def stop(self):
logger.debug('Stopping REST Service')
@@ -220,14 +211,11 @@ class HTTPServerThread(threading.Thread):
def restart(self, address=None):
if address is None:
# address = self.server.server_address
address = self.address
address = self.server.server_address
self.address = (address[0], self.address[1]) # Copy address & keep it for future reference, port is never changed once assigned on init
self.stop()
# Listening on 0.0.0.0, does not need to restart listener..
# self.stop()
# self.initiateServer(address)
self.initiateServer(address)
def run(self):
self.server.serve_forever()

View File

@@ -33,11 +33,9 @@ from __future__ import unicode_literals
import socket
import threading
import sys
import six
import traceback
import pickle
import errno
import time
import six
from udsactor.utils import toUnicode
from udsactor.log import logger
@@ -89,9 +87,11 @@ REV_DICT = {
MAGIC = b'\x55\x44\x53\x00' # UDS in hexa with a padded 0 to the right
# Allows notifying login/logout from client for linux platform
ALLOW_LOG_METHODS = sys.platform != 'win32'
# States for client processor
ST_SECOND_BYTE = 0x01
ST_RECEIVING = 0x02
@@ -99,9 +99,8 @@ ST_PROCESS_MESSAGE = 0x02
class ClientProcessor(threading.Thread):
def __init__(self, parent, clientSocket):
super(ClientProcessor, self).__init__()
super(self.__class__, self).__init__()
self.parent = parent
self.clientSocket = clientSocket
self.running = False
@@ -132,7 +131,6 @@ class ClientProcessor(threading.Thread):
if b == b'':
# Client disconnected
self.running = False
# self.processRequest(REQ_LOGOUT, 'CLIENT_CONNECTION_LOST')
break
buf = six.byte2int(b) # Empty buffer, this is set as non-blocking
if state is None:
@@ -187,8 +185,8 @@ class ClientProcessor(threading.Thread):
try:
m = msg[1] if msg[1] is not None else b''
ln = len(m)
data = MAGIC + six.int2byte(msg[0]) + six.int2byte(ln & 0xFF) + six.int2byte(ln >> 8) + m
l = len(m)
data = MAGIC + six.int2byte(msg[0]) + six.int2byte(l & 0xFF) + six.int2byte(l >> 8) + m
try:
self.clientSocket.sendall(data)
except socket.error as e:
@@ -208,7 +206,7 @@ class ClientProcessor(threading.Thread):
class ServerIPC(threading.Thread):
def __init__(self, listenPort, clientMessageProcessor=None):
super(ServerIPC, self).__init__()
super(self.__class__, self).__init__()
self.port = listenPort
self.running = False
self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -291,7 +289,6 @@ class ServerIPC(threading.Thread):
class ClientIPC(threading.Thread):
def __init__(self, listenPort):
super(ClientIPC, self).__init__()
self.port = listenPort
@@ -321,8 +318,8 @@ class ClientIPC(threading.Thread):
if isinstance(data, six.text_type): # Convert to bytes if necessary
data = data.encode('utf-8')
ln = len(data)
msg = six.int2byte(msg) + six.int2byte(ln & 0xFF) + six.int2byte(ln >> 8) + data
l = len(data)
msg = six.int2byte(msg) + six.int2byte(l & 0xFF) + six.int2byte(l >> 8) + data
self.clientSocket.sendall(msg)
def requestInformation(self):
@@ -410,11 +407,8 @@ 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()

View File

@@ -31,37 +31,28 @@
'''
from __future__ import unicode_literals
import sys
import os
import stat
import subprocess
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 import store
from udsactor.log import logger
from udsactor.linux.daemon import Daemon
from udsactor.linux import renamer
POST_CMD = '/etc/udsactor/post'
import sys
import time
try:
from prctl import set_proctitle # @UnresolvedImport
from prctl import set_proctitle
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)
@@ -71,12 +62,6 @@ 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:
@@ -90,48 +75,13 @@ 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)
if self.rebootMachineAfterOp is False:
self.setReady()
else:
logger.info('Rebooting computer to activate new name {}'.format(name))
self.reboot()
self.setReady()
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:
pre_cmd = store.preApplication()
if os.path.isfile(pre_cmd):
if (os.stat(pre_cmd).st_mode & stat.S_IXUSR) != 0:
subprocess.call([pre_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:
# Ignore output of execution command
logger.error('Executing preconnect command give')
return 'ok'
def run(self):
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))
initCfg()
logger.debug('Running Daemon')
set_proctitle('UDSActorDaemon')
@@ -156,21 +106,6 @@ 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()
# *********************
@@ -196,7 +131,6 @@ def usage():
sys.stderr.write("usage: {} start|stop|restart|login 'username'|logout 'username'\n".format(sys.argv[0]))
sys.exit(2)
if __name__ == '__main__':
logger.setLevel(20000)

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014-2018 Virtual Cable S.L.
# Copyright (c) 2014 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@@ -46,7 +46,6 @@ class Daemon:
Usage: subclass the Daemon class and override the run() method
"""
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
@@ -89,8 +88,8 @@ class Daemon:
sys.stdout.flush()
sys.stderr.flush()
si = open(self.stdin, 'r')
so = open(self.stdout, 'ab+')
se = open(self.stderr, 'ab+', 0)
so = open(self.stdout, 'a+')
se = open(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

View File

@@ -122,7 +122,7 @@ def getComputerName():
def getNetworkInfo():
for ifname in _getInterfaces():
ip, mac = _getIpAndMac(ifname)
if mac != '00:00:00:00:00:00' and ip.startswith('169.254') is False: # Skips local interfaces & interfaces with no dhcp IPs
if mac != '00:00:00:00:00:00': # Skips local interfaces
yield utils.Bunch(name=ifname, mac=mac, ip=ip)
@@ -232,7 +232,7 @@ def getIdleDuration():
xss.XScreenSaverQueryInfo(display, xlib.XDefaultRootWindow(display), info)
# Centos seems to set state to 1?? (weird, but it's happening don't know why... will try this way)
if info.contents.state == 1:
if info.contents.state != 0 and 'centos' not in platform.linux_distribution()[0].lower().strip():
return 3600 * 100 * 1000 # If screen saver is active, return a high enough value
return info.contents.idle / 1000.0

View File

@@ -30,13 +30,13 @@
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''
import six
import os
DEBUG = False
CONFIGFILE = '/etc/udsactor/udsactor.cfg' if DEBUG is False else '/tmp/udsactor.cfg'
PRECONNECT_CMD = '/etc/udsactor/pre'
def checkPermissions():
@@ -78,16 +78,3 @@ 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
def preApplication():
return PRECONNECT_CMD

View File

@@ -45,7 +45,6 @@ OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in six.moves.xra
class Logger(object):
def __init__(self):
self.logLevel = INFO
self.logger = LocalLogger()

View File

@@ -44,10 +44,6 @@ from .utils import exceptionToMessage
import socket
import time
import random
import os
import subprocess
import shlex
import stat
IPC_PORT = 39188
@@ -74,11 +70,8 @@ def initCfg():
cfg = None
break
return cfg
class CommonService(object):
def __init__(self):
self.isAlive = True
self.api = None
@@ -86,31 +79,11 @@ class CommonService(object):
self.httpServer = None
self.rebootRequested = False
self.knownIps = []
self.loggedIn = False
socket.setdefaulttimeout(20)
def reboot(self):
self.rebootRequested = True
def execute(self, cmdLine, section): # pylint: disable=no-self-use
cmd = shlex.split(cmdLine, posix=False)
if os.path.isfile(cmd[0]):
if (os.stat(cmd[0]).st_mode & stat.S_IXUSR) != 0:
try:
res = subprocess.check_call(cmd)
except Exception as e:
logger.error('Got exception executing: {} - {}'.format(cmdLine, e))
return False
logger.info('Result of executing cmd was {}'.format(res))
return True
else:
logger.error('{} file exists but it it is not executable (needs execution permission by admin/root)'.format(section))
else:
logger.error('{} file not found & not executed'.format(section))
return False
def setReady(self):
self.api.setReady([(v.mac, v.ip) for v in operations.getNetworkInfo()])
@@ -163,14 +136,6 @@ 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:
logger.info('Executing runOnce app: {}'.format(runOnce))
if self.execute(runOnce, 'RunOnce') is True:
# operations.reboot()
return False
# Broker connection is initialized, now get information about what to
# do
counter = 0
@@ -245,7 +210,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], self.httpServer.getPort())
address = (self.knownIps[self.api.mac], random.randrange(43900, 44000))
# And new listening address
self.httpServer.restart(address)
# sends notification
@@ -261,15 +226,13 @@ class CommonService(object):
return
if msg == ipc.REQ_LOGIN:
self.loggedIn = True
res = self.api.login(data).split('\t')
# third parameter, if exists, sets maxSession duration to this.
# First & second parameters are ip & hostname of connection source
if len(res) >= 3:
self.api.maxSession = int(res[2]) # Third parameter is max session duration
msg = ipc.REQ_INFORMATION # Senf information, requested or not, to client on login notification
if msg == ipc.REQ_LOGOUT and self.loggedIn is True:
self.loggedIn = False
if msg == ipc.REQ_LOGOUT:
self.api.logout(data)
self.onLogout(data)
if msg == ipc.REQ_INFORMATION:
@@ -312,14 +275,11 @@ class CommonService(object):
def endAPI(self):
if self.api is not None:
try:
if self.loggedIn:
self.loggedIn = False
self.api.logout('service_stopped')
self.api.notifyComm(None)
except Exception as e:
logger.error('Couln\'t remove comms url from broker: {}'.format(e))
except Exception:
logger.error('Couln\'t remove comms url from broker')
# self.notifyStop()
self.notifyStop()
# ***************************************************
# Methods that ARE overriden by linux & windows Actor

View File

@@ -32,10 +32,6 @@
from __future__ import unicode_literals
# pylint: disable=unused-wildcard-import, wildcard-import
import subprocess
import os
import stat
import win32serviceutil # @UnresolvedImport, pylint: disable=import-error
import win32service # @UnresolvedImport, pylint: disable=import-error
import win32security # @UnresolvedImport, pylint: disable=import-error
@@ -44,9 +40,9 @@ 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 os
from udsactor import operations
from udsactor import store
from udsactor.service import CommonService
from udsactor.service import initCfg
@@ -59,8 +55,6 @@ 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):
'''
@@ -119,7 +113,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
operations.renameComputer(name)
# Reboot just after renaming
logger.info('Rebooting computer to activate new name {}'.format(name))
logger.info('Rebooting computer got activate new name {}'.format(name))
self.reboot()
def oneStepJoin(self, name, domain, ou, account, password):
@@ -164,15 +158,12 @@ 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 and store.useOldJoinSystem() is False:
if ver >= 60:
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):
@@ -189,7 +180,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
resumeHandle = 0
while True:
users, _, resumeHandle = win32net.NetLocalGroupGetMembers(None, groupName, 1, resumeHandle, 32768)
if user.lower() in [u['name'].lower() for u in users]:
if user in [u['name'] for u in users]:
useraAlreadyInGroup = True
break
if resumeHandle == 0:
@@ -207,20 +198,6 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
self._user = None
logger.debug('User {} already in group'.format(user))
# Now try to run pre connect command
try:
pre_cmd = store.preApplication()
if os.path.isfile(pre_cmd):
if (os.stat(pre_cmd).st_mode & stat.S_IXUSR) != 0:
subprocess.call([pre_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 {}'.format(e))
return 'ok'
def onLogout(self, user):
@@ -239,7 +216,7 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
except Exception as e:
logger.error('Exception removing user from Remote Desktop Users: {}'.format(e))
def SvcDoRun(self): # pylint: disable=too-many-statements, too-many-branches
def SvcDoRun(self):
'''
Main service loop
'''
@@ -315,17 +292,6 @@ 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 *
# *********************

View File

@@ -37,7 +37,7 @@ import os
import tempfile
# Valid logging levels, from UDS Broker (uds.core.utils.log)
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in range(6))
OTHER, DEBUG, INFO, WARN, ERROR, FATAL = (10000 * (x + 1) for x in xrange(6))
class LocalLogger(object):
@@ -58,7 +58,7 @@ class LocalLogger(object):
# our loglevels are 10000 (other), 20000 (debug), ....
# logging levels are 10 (debug), 20 (info)
# OTHER = logging.NOTSET
self.logger.log(level // 1000 - 10, message)
self.logger.log(level / 1000 - 10, message)
if level < INFO or self.serviceLogger is False: # Only information and above will be on event log
return

View File

@@ -91,7 +91,6 @@ def getDomainName():
def getWindowsVersion():
return win32api.GetVersionEx()
EWX_LOGOFF = 0x00000000
EWX_SHUTDOWN = 0x00000001
EWX_REBOOT = 0x00000002
@@ -122,7 +121,6 @@ def renameComputer(newName):
computerName = win32api.GetComputerNameEx(win32con.ComputerNamePhysicalDnsHostname)
raise Exception('Error renaming computer from {} to {}: {}'.format(computerName, newName, error))
NETSETUP_JOIN_DOMAIN = 0x00000001
NETSETUP_ACCT_CREATE = 0x00000002
NETSETUP_ACCT_DELETE = 0x00000004
@@ -189,8 +187,8 @@ def changeUserPassword(user, oldPassword, newPassword):
if res != 0:
# Log the error, and raise exception to parent
error = getErrorMessage(res)
raise Exception('Error changing password for user {}: {} {}'.format(user.value, res, error))
error = getErrorMessage()
raise Exception('Error changing password for user {}: {}'.format(user.value, error))
class LASTINPUTINFO(ctypes.Structure):
@@ -208,21 +206,11 @@ def initIdleDuration(atLeastSeconds):
def getIdleDuration():
try:
lastInputInfo = LASTINPUTINFO()
lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo)
if ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo)) == 0:
return 0
# if lastInputInfo.dwTime > 1000000000: # Value toooo high, nonsense...
# return 0
current = ctypes.c_uint(ctypes.windll.kernel32.GetTickCount())
millis = current.value - lastInputInfo.dwTime # @UndefinedVariable
if millis < 0:
return 0
return millis / 1000.0
except Exception as e:
logger.error('Getting idle duration: {}'.format(e))
return 0
lastInputInfo = LASTINPUTINFO()
lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo)
ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo))
millis = ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime # @UndefinedVariable
return millis / 1000.0
def getCurrentUser():

View File

@@ -31,13 +31,10 @@
'''
from __future__ import unicode_literals
import pickle
from win32com.shell import shell # @UnresolvedImport, pylint: disable=import-error
try:
import winreg as wreg
except ImportError: # Python 2.7 fallback
import _winreg as wreg # @UnresolvedImport, pylint: disable=import-error
import _winreg as wreg # @UnresolvedImport, pylint: disable=import-error
import win32security # @UnresolvedImport, pylint: disable=import-error
import cPickle
DEBUG = False
@@ -50,7 +47,6 @@ def encoder(data):
def decoder(data):
return data.decode('bz2')
path = 'Software\\UDSActor'
baseKey = wreg.HKEY_CURRENT_USER if DEBUG is True else wreg.HKEY_LOCAL_MACHINE # @UndefinedVariable
@@ -82,7 +78,7 @@ def readConfig():
key = wreg.OpenKey(baseKey, path, 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
data, _ = wreg.QueryValueEx(key, '') # @UndefinedVariable
wreg.CloseKey(key) # @UndefinedVariable
return pickle.loads(decoder(data))
return cPickle.loads(decoder(data))
except Exception:
return None
@@ -95,49 +91,5 @@ def writeConfig(data, fixPermissions=True):
if fixPermissions is True:
fixRegistryPermissions(key.handle)
wreg.SetValueEx(key, "", 0, wreg.REG_BINARY, encoder(pickle.dumps(data))) # @UndefinedVariable
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 Exception:
data = None
return data
def preApplication():
try:
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
try:
data, _ = wreg.QueryValueEx(key, 'pre') # @UndefinedVariable
except Exception:
data = None
wreg.CloseKey(key) # @UndefinedVariable
except Exception:
data = None
return data

View File

@@ -1,2 +0,0 @@
udsclient_2.2.1_all.deb admin optional
udsclient_2.2.1_amd64.buildinfo admin optional

View File

@@ -1,6 +1,6 @@
#!/bin/bash
VERSION=`cat ../../../VERSION`
VERSION=`cat ../../VERSION`
RELEASE=1
# Debian based
dpkg-buildpackage -b

View File

@@ -1,21 +1,3 @@
udsclient (2.2.1) stable; urgency=medium
* Upgraded to 2.2.1 release
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 2 Oct 2018 12:44:12 +0200
udsclient (2.2.0) stable; urgency=medium
* Updated release
-- Adolfo Gómez García <agomez@virtualcable.es> Thu, 27 Aug 2017 14:18:18 +0200
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

View File

@@ -10,6 +10,6 @@ Package: udsclient
Section: admin
Priority: optional
Architecture: all
Depends: python-paramiko (>=0.8.2), python-qt4 (>=4.9), python-six(>=1.1), python (>=2.7), freerdp2-x11 | freerdp-x11, desktop-file-utils, ${misc:Depends}
Depends: python-paramiko (>=0.8.2), python-qt4 (>=4.9), python-six(>=1.1), python (>=2.7), rdesktop | freerdp-x11, desktop-file-utils, ${misc:Depends}
Description: Client connector for Universal Desktop Services (UDS) Broker
This package provides the required components to allow this machine to connect to services provided by UDS Broker.

View File

@@ -0,0 +1 @@
udsclient_2.0.0_all.deb admin optional

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014-2017 Virtual Cable S.L.
# Copyright (c) 2014 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@@ -43,15 +43,9 @@ from uds import tools
from uds import VERSION
import webbrowser
import json
import sys
import six
from UDSWindow import Ui_MainWindow
# Server before this version uses "unsigned" scripts
OLD_METHOD_VERSION = '2.4.0'
class RetryException(Exception):
pass
@@ -63,7 +57,6 @@ class UDSClient(QtGui.QMainWindow):
animTimer = None
anim = 0
animInverted = False
serverVersion = 'X.Y.Z' # Will be overwriten on getVersion
def __init__(self):
QtGui.QMainWindow.__init__(self)
@@ -153,8 +146,6 @@ class UDSClient(QtGui.QMainWindow):
webbrowser.open(data['result']['downloadUrl'])
self.closeWindow()
return
self.serverVersion = data['result']['requiredVersion']
self.getTransportData()
except RetryException as e:
@@ -162,7 +153,6 @@ class UDSClient(QtGui.QMainWindow):
QtCore.QTimer.singleShot(1000, self.getVersion)
except Exception as e:
logger.exception('Version')
self.showError(e)
@@ -182,20 +172,7 @@ class UDSClient(QtGui.QMainWindow):
try:
self.processError(data)
params = None
if self.serverVersion <= OLD_METHOD_VERSION:
script = data['result'].decode('base64').decode('bz2')
else:
res = data['result']
# We have three elements on result:
# * Script
# * Signature
# * Script data
# We test that the Script has correct signature, and them execute it with the parameters
script, signature, params = res['script'].decode('base64').decode('bz2'), res['signature'], json.loads(res['params'].decode('base64').decode('bz2'))
if tools.verifySignature(script, signature) is False:
raise Exception('Invalid UDS code signature. Please, report to administrator')
script = data['result'].decode('base64').decode('bz2')
self.stopAnim()
@@ -205,14 +182,7 @@ class UDSClient(QtGui.QMainWindow):
QtCore.QTimer.singleShot(3000, self.endScript)
self.hide()
# if self.serverVersion <= OLD_METHOD_VERSION:
# errorString = '<p>The server <b>{}</b> runs an old version of UDS:</p>'.format(host)
# errorString += '<p>To avoid security issues, you must approve old UDS Version access.</p>'
# if QtGui.QMessageBox.warning(None, 'ACCESS Warning', errorString, QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) == QtGui.QMessageBox.No:
# raise Exception('Server not approved. Access denied.')
logger.debug('Script: {}'.format(script))
six.exec_(script, globals(), {'parent': self, 'sp': params})
six.exec_(script, globals(), {'parent': self})
except RetryException as e:
self.ui.info.setText(six.text_type(e) + ', retrying access...')
@@ -254,7 +224,7 @@ def done(data):
QtGui.QMessageBox.critical(None, 'Notice', six.text_type(data.data), QtGui.QMessageBox.Ok)
sys.exit(0)
# Ask user to approve endpoint
# Ask user to aprobe endpoint
def approveHost(host, parentWindow=None):
settings = QtCore.QSettings()
settings.beginGroup('endpoints')
@@ -271,7 +241,6 @@ def approveHost(host, parentWindow=None):
settings.endGroup()
return approved
if __name__ == "__main__":
logger.debug('Initializing connector')
# Initialize app
@@ -312,7 +281,7 @@ if __name__ == "__main__":
# Setup REST api endpoint
RestRequest.restApiUrl = '{}://{}/rest/client'.format(['http', 'https'][ssl], host)
logger.debug('Setting request URL to {}'.format(RestRequest.restApiUrl))
logger.debug('Setting requert URL to {}'.format(RestRequest.restApiUrl))
# RestRequest.restApiUrl = 'https://172.27.0.1/rest/client'
try:

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 137 KiB

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014-2017 Virtual Cable S.L.
# Copyright (c) 2014 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@@ -34,11 +34,11 @@ from __future__ import unicode_literals
# On centos, old six release does not includes byte2int, nor six.PY2
import six
VERSION = '2.2.0'
VERSION = '2.0.0'
__title__ = 'udclient'
__version__ = VERSION
__build__ = 0x010760
__build__ = 0x010750
__author__ = 'Adolfo Gómez'
__license__ = "BSD 3-clause"
__copyright__ = "Copyright 2014-2017 VirtualCable S.L.U."
__copyright__ = "Copyright 2014-2015 VirtualCable S.L.U."

View File

@@ -33,17 +33,10 @@ 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=logFile,
filename=os.path.join(tempfile.gettempdir(), b'udsclient.log'),
filemode='a',
format='%(levelname)s %(asctime)s %(message)s',
level=logging.DEBUG

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Virtual Cable S.L.
# Copyright (c) 2015 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Virtual Cable S.L.
# Copyright (c) 2015 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,

View File

@@ -32,8 +32,6 @@
'''
from __future__ import unicode_literals
from base64 import b64decode
import tempfile
import string
import random
@@ -50,25 +48,9 @@ _unlinkFiles = []
_tasksToWait = []
_execBeforeExit = []
sys_fs_enc = sys.getfilesystemencoding() or 'mbcs'
# Public key for scripts
PUBLIC_KEY = '''-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNURlGjBpqbglkTTg2lh
dU5qPbg9Q+RofoDDucGfrbY0pjB9ULgWXUetUWDZhFG241tNeKw+aYFTEorK5P+g
ud7h9KfyJ6huhzln9eyDu3k+kjKUIB1PLtA3lZLZnBx7nmrHRody1u5lRaLVplsb
FmcnptwYD+3jtJ2eK9ih935DYAkYS4vJFi2FO+npUQdYBZHPG/KwXLjP4oGOuZp0
pCTLiCXWGjqh2GWsTECby2upGS/ZNZ1r4Ymp4V2A6DZnN0C0xenHIY34FWYahbXF
ZGdr4DFBPdYde5Rb5aVKJQc/pWK0CV7LK6Krx0/PFc7OGg7ItdEuC7GSfPNV/ANt
5BEQNF5w2nUUsyN8ziOrNih+z6fWQujAAUZfpCCeV9ekbwXGhbRtdNkbAryE5vH6
eCE0iZ+cFsk72VScwLRiOhGNelMQ7mIMotNck3a0P15eaGJVE2JV0M/ag/Cnk0Lp
wI1uJQRAVqz9ZAwvF2SxM45vnrBn6TqqxbKnHCeiwstLDYG4fIhBwFxP3iMH9EqV
2+QXqdJW/wLenFjmXfxrjTRr+z9aYMIdtIkSpADIlbaJyTtuQpEdWnrlDS2b1IGd
Okbm65EebVzOxfje+8dRq9Uqwip8f/qmzFsIIsx3wPSvkKawFwb0G5h2HX5oJrk0
nVgtClKcDDlSaBsO875WDR0CAwEAAQ==
-----END PUBLIC KEY-----'''
def saveTempFile(content, filename=None):
if filename is None:
filename = b''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(16))
@@ -86,7 +68,6 @@ def saveTempFile(content, filename=None):
logger.info('Returning filename')
return filename
def readTempFile(filename):
if 'win32' in sys.platform:
filename = filename.encode('utf-8')
@@ -98,7 +79,6 @@ def readTempFile(filename):
except Exception:
return None
def testServer(host, port, timeOut=4):
try:
sock = socket.create_connection((host, int(port)), timeOut)
@@ -180,24 +160,3 @@ def addExecBeforeExit(fnc):
def execBeforeExit():
for fnc in _execBeforeExit:
fnc.__call__()
def verifySignature(script, signature):
'''
Verifies with a public key from whom the data came that it was indeed
signed by their private key
param: public_key_loc Path to public key
param: signature String signature to be verified
return: Boolean. True if the signature is valid; False otherwise.
'''
# For signature checking
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
rsakey = RSA.importKey(PUBLIC_KEY)
signer = PKCS1_v1_5.new(rsakey)
digest = SHA256.new(script) # Script is "binary string" here
if signer.verify(digest, b64decode(signature)):
return True
return False

View File

@@ -1,17 +0,0 @@
<?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>

View File

@@ -1,8 +0,0 @@
<?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>

View File

@@ -1,158 +0,0 @@
# -*- 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

View File

@@ -1 +0,0 @@
../../../full/src/uds/__init__.py

View File

@@ -1 +0,0 @@
../../../full/src/uds/forward.py

View File

@@ -1 +0,0 @@
../../../full/src/uds/log.py

View File

@@ -1 +0,0 @@
../../../full/src/uds/osDetector.py

View File

@@ -1,86 +0,0 @@
# -*- 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 }, verify=False)
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

View File

@@ -1 +0,0 @@
../../../full/src/uds/tools.py

View File

@@ -1,44 +0,0 @@
# -*- 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)

View File

@@ -1,58 +0,0 @@
# -*- 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)

View File

@@ -1,49 +0,0 @@
# -*- 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

View File

@@ -1,143 +0,0 @@
# -*- 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

View File

@@ -1,4 +0,0 @@
#!/bin/sh
cd /lib/UDSClient
exec python UDSClient.pyc $@

Some files were not shown because too many files have changed in this diff Show More