Initial version for linux packagers

This commit is contained in:
Adolfo Gómez García 2015-04-10 15:46:15 +02:00
parent bdef8b2e8c
commit 250441056b
30 changed files with 502 additions and 37 deletions

2
client/.gitignore vendored
View File

@ -1 +1,3 @@
/bin
/udsclient_*
/*.rpm

4
client/linux/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/udsclient-opensuse-1.*.spec
/udsclient-1.*.spec
/debian/udsclient

42
client/linux/Makefile Normal file
View File

@ -0,0 +1,42 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Directories
SOURCEDIR := ../src
LIBDIR := $(DESTDIR)/usr/lib/UDSClient
BINDIR := $(DESTDIR)/usr/bin
SBINDIR = $(DESTDIR)/usr/sbin
APPSDIR := $(DESTDIR)/usr/share/applications
PYC := $(shell find $(SOURCEDIR) -name '*.py[co]')
CACHES := $(shell find $(SOURCEDIR) -name '__pycache__')
clean:
rm -rf $(PYC) $(CACHES) $(DESTDIR)
install:
rm -rf $(DESTDIR)
mkdir -p $(LIBDIR)
mkdir -p $(BINDIR)
mkdir -p $(SBINDIR)
mkdir -p $(APPSDIR)
mkdir $(LIBDIR)/uds
# Cleans up .pyc and cache folders
rm -f $(PYC) $(CACHES)
cp $(SOURCEDIR)/uds/*.py $(LIBDIR)/uds
cp $(SOURCEDIR)/UDS*.py $(LIBDIR)
# URL Catchers elements for gnome/kde
cp desktop/UDSClient.desktop $(APPSDIR)
chmod 755 $(LIBDIR)/UDSClient.py
# chmod 0755 $(BINDIR)/udsclient
uninstall:
rm -rf $(LIBDIR)
# rm -f $(BINDIR)/udsclient
rm -rf $(CFGDIR)

30
client/linux/buildrpm.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash
VERSION=1.7.5
RELEASE=1
top=`pwd`
cat udsclient-template.spec |
sed -e s/"version 1.7.0"/"version ${VERSION}"/g |
sed -e s/"release 1"/"release ${RELEASE}"/g > udsclient-$VERSION.spec
# Now fix dependencies for opensuse
cat udsclient-template.spec |
sed -e s/"name udsclient"/"name udsclient-opensuse"/g |
sed -e s/"PyQt4"/"python-qt4"/g |
sed -e s/"libXScrnSaver"/"libXss1"/g > udsclient-opensuse-$VERSION.spec
# Right now, udsactor-xrdp-1.7.0.spec is not needed
for pkg in udsclient-$VERSION.spec udsclient-opensuse-$VERSION.spec; do
rm -rf rpm
for folder in SOURCES BUILD RPMS SPECS SRPMS; do
mkdir -p rpm/$folder
done
rpmbuild -v -bb --clean --buildroot=$top/rpm/BUILD/$pkg-root --target noarch $pkg 2>&1
done
#rm udsclient-$VERSION

3
client/linux/debian/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/udsactor/
/udsactor-xrdp/
/udsactor-nx/

View File

@ -0,0 +1,5 @@
udsclient (1.7.5) stable; urgency=medium
* Initial release.
-- Adolfo Gómez García <agomez@virtualcable.es> Fri, 10 Apr 2015 05:32:41 +0100

View File

@ -0,0 +1 @@
9

View File

@ -0,0 +1,15 @@
Source: udsclient
Section: admin
Priority: optional
Maintainer: Adolfo Gómez García <agomez@virtualcable.es>
Build-Depends: debhelper (>= 7), po-debconf
Standards-Version: 3.9.2
Homepage: http://www.virtualcable.es
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), rdesktop | freerdp-x11, ${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,26 @@
Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135
Name: udsclient
Maintainer: Adolfo Gómez García
Source: http://www.udsenterprise.com/
Copyright: 2014 Virtual Cable S.L.U.
License: BSD-3-clause
License: GPL-2+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
.
On Debian systems, the full text of the GNU General Public
License version 2 can be found in the file
`/usr/share/common-licenses/GPL-2'.

1
client/linux/debian/docs Normal file
View File

@ -0,0 +1 @@
readme.txt

View File

@ -0,0 +1 @@
udsclient_1.7.5_all.deb admin optional

44
client/linux/debian/rules Executable file
View File

@ -0,0 +1,44 @@
#!/usr/bin/make -f
# -*- makefile -*-
configure: configure-stamp
configure-stamp:
dh_testdir
touch configure-stamp
build: build-arch build-indep
build-arch: build-stamp
build-indep: build-stamp
build-stamp: configure-stamp
dh_testdir
$(MAKE)
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
dh_clean
install: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
$(MAKE) DESTDIR=$(CURDIR)/debian/udsclient install
binary-arch: build install
# emptyness
binary-indep: build install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installdebconf
dh_installinit --no-start
dh_python2=python
dh_compress
dh_link
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep
.PHONY: build clean binary-indep binary install configure

View File

@ -0,0 +1,17 @@
dh_prep
dh_installdirs
dh_installchangelogs
dh_installdocs
dh_installdebconf
dh_installinit
dh_compress
dh_link
dh_fixperms
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
dh_builddeb
dh_builddeb
dh_builddeb

View File

@ -0,0 +1,21 @@
#!/bin/sh
. /usr/share/debconf/confmodule
set -e
case "$1" in
configure)
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
#DEBHELPER#
exit 0

View File

@ -0,0 +1,6 @@
#!/bin/sh -e
. /usr/share/debconf/confmodule
set -e

View File

@ -0,0 +1 @@
#! /bin/bash -e

View File

@ -0,0 +1,20 @@
Template: udsactor/host
Type: string
Default:
Description: UDS Server address:
The actor needs the address of the server in order to communicate with it.
Provide here full address (or i) of the UDS server
Template: udsactor/secure
Type: boolean
Default: true
Description: Use secure (https) connection to communicate with UDS server?
If selected, the communication will be done using https.
If not selected, the communication will be done using http
Template: udsactor/masterKey
Type: string
Default:
Description: Master Key:
This key is available on UDS Administration interface.
Look for it under configuration, on Security tab.

View File

@ -0,0 +1,12 @@
[Desktop Entry]
Name=UDSClient
Comment=UDS Helper
Keywords=uds;client;vdi;
OnlyShowIn=GNOME;Unity;
Exec=/usr/lib/UDSClient/UDSClient.py %u
Icon=help-browser
StartupNotify=true
Terminal=false
Type=Application
Categories=Utility;
MimeType=x-scheme-handler/uds;x-scheme-handler/udss;

3
client/linux/readme.txt Normal file
View File

@ -0,0 +1,3 @@
UDSClient is the client connector needed to get acccess to services managed by UDS Broker.
Please, visit http://www.udsenterprise.com for more information

View File

@ -0,0 +1,47 @@
%define _topdir %(echo $PWD)/rpm
%define name udsclient
%define version 1.7.0
%define release 1
%define buildroot %{_topdir}/%{name}-%{version}-%{release}-root
BuildRoot: %{buildroot}
Name: %{name}
Version: %{version}
Release: %{release}
Summary: Client for Universal Desktop Services (UDS) Broker
License: BSD3
Group: Applications/Productivity
Requires: python-six python-paramiko PyQt4
Vendor: Virtual Cable S.L.U.
URL: http://www.udsenterprise.com
Provides: udsclient
%define _rpmdir ../
%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
%install
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh install
cd $curdir
%clean
rm -rf $RPM_BUILD_ROOT
curdir=`pwd`
cd ../..
make DESTDIR=$RPM_BUILD_ROOT DISTRO=rh clean
cd $curdir
%postun
# And, posibly, the .pyc leaved behind on /usr/share/UDSActor
rm -rf /usr/share/UDClient > /dev/null 2>&1
%description
This package provides the required components to allow connection to services offered by UDS Broker.
%files
%defattr(-,root,root)
/usr/lib/UDSClient/*
/usr/share/applications/UDSClient.desktop

View File

@ -67,6 +67,12 @@ class UDSClient(QtGui.QMainWindow):
self.ui.info.setText('Initializing...')
screen = QtGui.QDesktopWidget().screenGeometry()
mysize = self.geometry()
hpos = (screen.width() - mysize.width()) / 2
vpos = (screen.height() - mysize.height() - mysize.height()) / 2
self.move(hpos, vpos)
self.activateWindow()
def closeWindow(self):
@ -204,6 +210,7 @@ if __name__ == "__main__":
exitVal = app.exec_()
except Exception as e:
exitVal = 128
QtGui.QMessageBox.critical(None, 'Error', six.text_type(e), QtGui.QMessageBox.Ok)
sys.exit(exitVal)

View File

@ -113,8 +113,7 @@ class ForwardThread(threading.Thread):
try:
self.client.connect(self.server, self.port, username=self.username, password=self.password)
except Exception as e:
verbose('Exception: {}'.format(e))
except Exception:
self.status = 2 # Error
return

View File

@ -38,6 +38,7 @@ from __future__ import unicode_literals
from uds.core.util import OsDetector
import six
import os
class RDPFile(object):
@ -80,6 +81,10 @@ class RDPFile(object):
@property
def as_new_xfreerdp_params(self):
'''
Parameters for xfreerdp >= 1.1.0 with self rdp description
Note that server is not added
'''
params = ['/clipboard', '/t:UDS Connection', '/cert-ignore']
if self.redirectSmartcards:
@ -94,6 +99,9 @@ class RDPFile(object):
params.append('/drive:media,/media')
params.append('/home-drive')
if self.redirectSerials is True:
params.append('/serial:/dev/ttyS0')
if self.redirectPrinters:
params.append('/printer')
@ -114,10 +122,65 @@ class RDPFile(object):
params.append('/h:{}'.format(self.height))
params.append('/bpp:{}'.format(self.bpp))
params.append('/u:{}'.format(self.username))
params.append('/p:{}'.format(self.password))
params.append('/d:{}'.format(self.domain))
params.append('/v:{}'.format(self.address))
if self.username != '':
params.append('/u:{}'.format(self.username))
if self.password != '':
params.append('/p:{}'.format(self.password))
if self.domain != '':
params.append('/d:{}'.format(self.domain))
return params
@property
def as_rdesktop_params(self):
'''
Parameters for rdestop with self rdp description
Note that server is not added
'''
params = ['-TUDS Connection', '-P', '-rclipboard:PRIMARYCLIPBOARD]']
if self.redirectSmartcards:
params.append('-rsdcard')
if self.redirectAudio:
params.append('-rsound:local')
else:
params.append('-rsound:off')
if self.redirectDrives is True:
params.append('-rdisk:home=' + os.environ['HOME'])
params.append('-rdisk:media=/media')
if self.redirectSerials is True:
params.append('-rcomport:COM1=/dev/ttyS0')
if self.redirectPrinters:
pass
if self.compression:
params.append('-z')
if self.showWallpaper:
params.append('-xl')
else:
params.append('-xb')
if self.multimon:
pass
if self.fullScreen:
params.append('-f')
else:
params.append('-g{}x{}'.format(self.width, self.height))
params.append('-a{}'.format(self.bpp))
if self.username != '':
params.append('-u{}'.format(self.username))
if self.password != '':
params.append('-p-')
if self.domain != '':
params.append('-d{}'.format(self.domain))
return params

View File

@ -132,10 +132,15 @@ class RDPTransport(BaseRDPTransport):
if m.os == OsDetector.Windows:
m.r.password = '{password}'
return self.windowsScript(m)
if m.os == OsDetector.Macintosh:
return self.macOsXScript(m)
if m.os == OsDetector.Linux:
return self.getLinuxScript(m)
return ''
os = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
OsDetector.Macintosh: 'macosx'
}.get(m.os)
if os == '':
return '' # In fact, should return an error, but this will be fine right now
return self.getScript('scripts/{}/direct.py'.format(os)).format(m=m)

View File

@ -86,8 +86,6 @@ class TSRDPTransport(BaseRDPTransport):
raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
def windowsScript(self, m):
# The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc
return self.getScript('scripts/windows/tunnel.py').format(m=m)
def macOsXScript(self, m):
@ -113,6 +111,7 @@ class TSRDPTransport(BaseRDPTransport):
r = RDPFile(width == -1 or height == -1, width, height, depth, target=os['OS'])
r.address = '{address}'
r.username = username
r.password = password
r.domain = domain
r.redirectPrinters = self.allowPrinters.isTrue()
r.redirectSmartcards = self.allowSmartcards.isTrue()
@ -158,8 +157,15 @@ class TSRDPTransport(BaseRDPTransport):
if m.os == OsDetector.Windows:
r.password = '{password}'
return self.windowsScript(m)
if m.os == OsDetector.Macintosh:
return self.macOsXScript(m)
return ''
os = {
OsDetector.Windows: 'windows',
OsDetector.Linux: 'linux',
OsDetector.Macintosh: 'macosx'
}.get(m.os)
if os == '':
return '' # In fact, should return an error, but this will be fine right now
return self.getScript('scripts/{}/tunnel.py'.format(os)).format(m=m)

View File

@ -5,7 +5,6 @@ from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
from PyQt4 import QtCore, QtGui
import subprocess
import os
import re
from uds import tools # @UnresolvedImport
@ -13,37 +12,51 @@ from uds import tools # @UnresolvedImport
import six
def execOldXFreeRdp(parent, xfreerdp):
QtGui.QMessageBox.critical(parent, 'Notice', 'Old xfreerdp', QtGui.QMessageBox.Ok) # @UndefinedVariable
def execNewXFreeRdp(parent, xfreerdp):
import subprocess
params = [xfreerdp] + {m.r.as_new_xfreerdp_params} # @UndefinedVariable
import subprocess # @Reimport
params = [xfreerdp] + {m.r.as_new_xfreerdp_params} + ['/v:{m.r.address}'] # @UndefinedVariable
tools.addTaskToWait(subprocess.Popen(params))
def execRdesktop(parent, rdesktop):
return
import subprocess # @Reimport
params = [rdesktop] + {m.r.as_rdesktop_params} + ['{m.r.address}'] # @UndefinedVariable
p = subprocess.Popen(params, stdin=subprocess.PIPE)
if '{m.password}' != '':
p.stdin.write('{m.password}')
p.stdin.close()
tools.addTaskToWait(p)
# Try to locate a "valid" version of xfreerdp as first option
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)
xfreerdp = tools.findApp('xfreerdp')
rdesktop = tools.findApp('rdesktop')
fnc, app = None, None
if rdesktop is not None:
fnc, app = execRdesktop, rdesktop
if xfreerdp is not None:
# Check for nice version
try:
version = subprocess.check_output([xfreerdp, '--version'])
try:
version = subprocess.check_output([xfreerdp, '--version'])
except subprocess.CalledProcessError as e:
version = e.output
version = float(re.search(r'version ([0-9]*\.[0-9]*)', version).groups()[0])
if version < 1.0:
raise Exception()
if version < 1.1:
execOldXFreeRdp(parent, xfreerdp) # @UndefinedVariable
raise Exception()
else:
execNewXFreeRdp(parent, xfreerdp) # @UndefinedVariable
fnc, app = execNewXFreeRdp, xfreerdp
except Exception as e: # Valid version not found, pass to check rdesktop
QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
# QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
pass
if app is None or fnc is None:
raise Exception('''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
<p>Please, install apropiate package for your system.</p>
<p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
''')
else:
rdesktop = tools.findApp('rdesktop')
if rdesktop is None:
raise Exception('You need to have installed xfreerdp or rdesktop to connect to theese UDS services.\nPlease, install apropiate package for your system.')
fnc(parent, app) # @UndefinedVariable

View File

@ -0,0 +1,69 @@
# This is a template
# Saved as .py for easier editing
from __future__ import unicode_literals
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
from PyQt4 import QtCore, QtGui
import subprocess
import re
from uds.forward import forward # @UnresolvedImport
from uds import tools # @UnresolvedImport
import six
def execNewXFreeRdp(parent, xfreerdp, port):
import subprocess # @Reimport
params = [xfreerdp] + {m.r.as_new_xfreerdp_params} + ['/v:127.0.0.1:{{}}'.format(port)] # @UndefinedVariable
tools.addTaskToWait(subprocess.Popen(params))
def execRdesktop(parent, rdesktop, port):
import subprocess # @Reimport
params = [rdesktop] + {m.r.as_rdesktop_params} + ['127.0.0.1:{{}}'.format(port)] # @UndefinedVariable
p = subprocess.Popen(params, stdin=subprocess.PIPE)
if {m.hasCredentials}: # @UndefinedVariable
p.stdin.write('{m.password}')
p.stdin.close()
tools.addTaskToWait(p)
# Try to locate a "valid" version of xfreerdp as first option (<1.1 does not allows drive redirections, so it will not be used if found)
xfreerdp = tools.findApp('xfreerdp')
rdesktop = tools.findApp('rdesktop')
fnc, app = None, None
if rdesktop is not None:
fnc, app = execRdesktop, rdesktop
if xfreerdp is not None:
# Check for nice version
try:
try:
version = subprocess.check_output([xfreerdp, '--version'])
except subprocess.CalledProcessError as e:
version = e.output
version = float(re.search(r'version ([0-9]*\.[0-9]*)', version).groups()[0])
if version < 1.1:
raise Exception()
else:
fnc, app = execNewXFreeRdp, xfreerdp
except Exception as e: # Valid version not found, pass to check rdesktop
# QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
pass
if app is None or fnc is None:
raise Exception('''<p>You need to have installed xfreerdp (>= 1.1) or rdesktop, and have them in your PATH in order to connect to this UDS service.</p>
<p>Please, install apropiate package for your system.</p>
<p>Also note that xfreerdp prior to version 1.1 will not be taken into consideration.</p>
''')
else:
# Open tunnel
forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389)
if forwardThread.status == 2:
raise Exception('Unable to open tunnel')
fnc(parent, app, port) # @UndefinedVariable

View File

@ -59,7 +59,7 @@ if executable is None:
forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.tunPass}', '{m.ip}', 3389)
if forwardThread.status == 2:
QtGui.QMessageBox.critical(parent, 'Error', 'Unable to open tunnel', QtGui.QMessageBox.Ok) # @UndefinedVariable
raise Exception('Unable to open tunnel')
else:
theFile = '''{m.r.as_file}'''.format(

View File

@ -12,6 +12,7 @@ from uds import tools # @UnresolvedImport
import six
# The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc
theFile = '''{m.r.as_file}'''.format(password=win32crypt.CryptProtectData(six.binary_type('{m.password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex'))
filename = tools.saveTempFile(theFile)

View File

@ -19,6 +19,7 @@ forwardThread, port = forward('{m.tunHost}', '{m.tunPort}', '{m.tunUser}', '{m.t
if forwardThread.status == 2:
raise Exception('Unable to open file')
# The password must be encoded, to be included in a .rdp file, as 'UTF-16LE' before protecting (CtrpyProtectData) it in order to work with mstsc
theFile = '''{m.r.as_file}'''.format(
password=win32crypt.CryptProtectData(six.binary_type('{m.password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex'),
address='127.0.0.1:{{}}'.format(port)