* Simplified Transports after tests

* Added direct linux support for xfreerdp right now
This commit is contained in:
Adolfo Gómez García 2015-04-08 15:21:09 +02:00
parent aef71ba48c
commit bdef8b2e8c
17 changed files with 298 additions and 173 deletions

3
client/src/UDSClient.py Normal file → Executable file
View File

@ -172,7 +172,8 @@ if __name__ == "__main__":
QtCore.QCoreApplication.setOrganizationName('Virtual Cable S.L.U.')
QtCore.QCoreApplication.setApplicationName('UDS Connector')
app.setStyle(QtGui.QStyleFactory.create('plastique'))
if 'darwin' not in sys.platform:
app.setStyle('plastique')
if six.PY3 is False:
import threading

View File

@ -36,6 +36,7 @@ import tempfile
import string
import random
import os
import stat
_unlinkFiles = []
_tasksToWait = []
@ -53,6 +54,16 @@ def saveTempFile(content, filename=None):
return filename
def findApp(appName):
for path in os.environ['PATH'].split(os.pathsep):
fileName = os.path.join(path, appName)
if os.path.isfile(fileName) and (os.stat(fileName).st_mode & stat.S_IXUSR) != 0:
return fileName
return None
# Queing operations (to be executed before exit)
def addFileToUnlink(filename):
'''
Adds a file to the wait-and-unlink list

View File

@ -97,6 +97,9 @@ class Client(Handler):
'downloadUrl': url
})
if len(self._args) == 1:
return Client.result(_('Correct'))
try:
ticket, scrambler = self._args
except Exception:
@ -121,7 +124,7 @@ class Client(Handler):
logger.debug('Script:\n{}'.format(transportScript))
return Client.result(transportScript.encode('bz2').encode('base64'))
return Client.result(result=transportScript.encode('bz2').encode('base64'))
except Exception as e:
logger.exception("Exception")
return Client.result(error=six.text_type(e))

View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2012 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
class DictAsObj(object):
def __init__(self, dct=None, **kwargs):
if dct is not None:
self.__dict__.update(dct)
self.__dict__.update(kwargs)

View File

@ -69,5 +69,5 @@ class AssignedAndUnused(Job):
osm.processUnused(us)
else: # No os manager, simply remove unused services in specified time
for us in ds.assignedUserServices().filter(in_use=False, state_date__lt=since_state, state=State.USABLE, os_state=State.USABLE):
logger.debug('Found unused assigned service {0}'.format(us))
logger.debug('Found unused assigned service with no OS Manager {0}'.format(us))
us.remove()

View File

@ -0,0 +1,2 @@
UDSClient.dmg
UDSClientSetup.exe

View File

@ -8,10 +8,11 @@
{% block body %}
<div class="row">
<div class="col-md-8 col-md-offset-2 bg-primary img-rounded">
<h3 class="text-center">{% trans 'Download UDS Plugin for' %} {{ os|osName }}</h3>
<p>{% trans 'In order to be able to execute UDS services, you need to have uds plugin installed.' %}</p>
<p class="text-center"><a href="{{ os|pluginDownloadUrl }}" class="btn btn-success">{% trans 'Download UDS Plugin for' %} {{ os|osName }}</a></p>
<h3>{% trans 'Or select another version' %}</h3>
<h3>{% trans 'Download UDS Plugin for' %} {{ os|osName }}</h3>
<p>{% trans 'In order to be able to execute UDS services, you need to have UDS plugin installed.' %}</p>
<p class="text-center">{{ os|pluginDownloadUrl|safe }}</a></p>
<h3>{% trans 'Or download another version' %}</h3>
<p>{% trans 'In case that your platform has been incorrectly detected, you can download manually the version required for your Operating System' %}</p>
<p>
{% if os != 'linux' %}
<p class="text-center">
@ -31,15 +32,17 @@
</p>
{% if request.user %}
<p>{% trans 'If you already have UDS Plugin installed but this message persists to appear, you can disable it here' %}</p>
<p>{% trans 'If you already have UDS Plugin installed but this message persists to appear, you can disable automatic detection here' %}</p>
<p>
<form>
<select id="plugin" class="selectpicker show-menu-arrow" data-width="100%" data-size="2" style="display: none;">
<option value="0">{% trans 'Automatic plugin detection is enabled' %}</option>
<option value="1">{% trans 'Automatic plugin detection is disabled' %}</option>
<option value="1">{% trans 'WARNING: Automatic plugin detection is disabled' %}</option>
</select>
</form>
</p>
<p>{% trans "Please, note that disabling automatic detection will not trigger this page again in case you don't have the plugin installed." %}<br/>
{% trans "In this case, you will have to manually download the plugin by using the menu on upper right corner." %}</p>
<p class="text-center">
<a href="{% url 'uds.web.views.index' %}" class="btn btn-info"><i class="fa fa-home"></i> {% trans "Return" %}</a>
</div>

View File

@ -33,6 +33,9 @@
from __future__ import unicode_literals
from django import template
from django.utils.translation import ugettext as _
from django.templatetags.static import static
from uds.core.util import html
from uds.core.util.request import getRequest
from uds.core.auths.auth import ROOT_ID
@ -213,9 +216,10 @@ def osName(os):
@register.filter(name='pluginDownloadUrl')
def pluginDownloadUrl(os):
tmpl = '<a href="{url}" class="btn btn-success">' + _('Download UDS Plugin for') + ' {os}</a>'
if os == 'windows':
return '1'
return tmpl.format(url=static('client/UDSClientSetup.exe'), os='Windows')
elif os == 'linux':
return '2'
else:
return '3'
return tmpl.format(url=static('client/UDSClient.dmg'), os='Mac OSX')

View File

@ -67,12 +67,61 @@ class RDPFile(object):
self.target = target
def get(self):
if self.target == OsDetector.Windows:
return self.getWindows()
if self.target in (OsDetector.Windows, OsDetector.Linux):
return self.getGeneric()
elif self.target == OsDetector.Macintosh:
return self.getMacOsX()
# Unknown target
return ''
def getWindows(self):
@property
def as_file(self):
return self.get()
@property
def as_new_xfreerdp_params(self):
params = ['/clipboard', '/t:UDS Connection', '/cert-ignore']
if self.redirectSmartcards:
params.append('/smartcard')
if self.redirectAudio:
params.append('/sound:sys:alsa')
params.append('/microphone:sys:alsa')
params.append('/multimedia:sys:alsa')
if self.redirectDrives is True:
params.append('/drive:media,/media')
params.append('/home-drive')
if self.redirectPrinters:
params.append('/printer')
if self.compression:
params.append('/compression:on')
if self.showWallpaper:
params.append('+themes')
params.append('+wallpaper')
if self.multimon:
params.append('/multimon')
if self.fullScreen:
params.append('/f')
else:
params.append('/w:{}'.format(self.width))
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))
return params
def getGeneric(self):
password = "{password}"
screenMode = self.fullScreen and "2" or "1"
audioMode = self.redirectAudio and "0" or "2"
@ -105,7 +154,8 @@ class RDPFile(object):
if len(self.username) != 0:
res += 'username:s:' + self.username + '\n'
res += 'domain:s:' + self.domain + '\n'
res += 'password 51:b:' + password + '\n'
if self.target == OsDetector.Windows:
res += 'password 51:b:' + password + '\n'
res += 'alternate shell:s:' + '\n'
res += 'shell working directory:s:' + '\n'

View File

@ -2,7 +2,7 @@
#
# Copyright (c) 2012 Virtual Cable S.L.
# All rights reserved.
# All rights reservem.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
@ -34,6 +34,7 @@
from django.utils.translation import ugettext_noop as _
from uds.core.managers.UserPrefsManager import CommonPrefs
from uds.core.util import OsDetector
from uds.core.util import tools
from .BaseRDPTransport import BaseRDPTransport
from .RDPFile import RDPFile
@ -66,47 +67,15 @@ class RDPTransport(BaseRDPTransport):
wallpaper = BaseRDPTransport.wallpaper
multimon = BaseRDPTransport.multimon
def windowsScript(self, data):
r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Windows)
r.address = '{}:{}'.format(data['ip'], 3389)
r.username = data['username']
r.password = '{password}'
r.domain = data['domain']
r.redirectPrinters = self.allowPrinters.isTrue()
r.redirectSmartcards = self.allowSmartcards.isTrue()
r.redirectDrives = self.allowDrives.isTrue()
r.redirectSerials = self.allowSerials.isTrue()
r.showWallpaper = self.wallpaper.isTrue()
r.multimon = self.multimon.isTrue()
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/direct.py').format(os=data['os'], file=r.get(), password=data['password'])
return self.getScript('scripts/windows/direct.py').format(m=m)
def macOsXScript(self, data):
r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Macintosh)
r.address = '{}:{}'.format(data['ip'], 3389)
r.username = data['username']
r.domain = data['domain']
r.redirectPrinters = self.allowPrinters.isTrue()
r.redirectSmartcards = self.allowSmartcards.isTrue()
r.redirectDrives = self.allowDrives.isTrue()
r.redirectSerials = self.allowSerials.isTrue()
r.showWallpaper = self.wallpaper.isTrue()
r.multimon = self.multimon.isTrue()
def macOsXScript(self, m):
return self.getScript('scripts/macosx/direct.py').format(m=m)
if data['domain'] != '':
username = '{}\\\\{}'.format(data['domain'], data['username'])
else:
username = data['username']
return self.getScript('scripts/macosx/direct.py').format(os=data['os'],
file=r.get(),
password=data['password'],
username=username,
ip=data['ip'],
this_server=data['this_server'],
r=r
)
def getLinuxScript(self, m):
return self.getScript('scripts/linux/direct.py').format(m=m)
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
# We use helper to keep this clean
@ -118,6 +87,18 @@ class RDPTransport(BaseRDPTransport):
width, height = CommonPrefs.getWidthHeight(prefs)
depth = CommonPrefs.getDepth(prefs)
r = RDPFile(width == -1 or height == -1, width, height, depth, target=os['OS'])
r.address = '{}:{}'.format(ip, 3389)
r.username = username
r.password = password
r.domain = domain
r.redirectPrinters = self.allowPrinters.isTrue()
r.redirectSmartcards = self.allowSmartcards.isTrue()
r.redirectDrives = self.allowDrives.isTrue()
r.redirectSerials = self.allowSerials.isTrue()
r.showWallpaper = self.wallpaper.isTrue()
r.multimon = self.multimon.isTrue()
# data
data = {
'os': os['OS'],
@ -125,6 +106,7 @@ class RDPTransport(BaseRDPTransport):
'port': 3389,
'username': username,
'password': password,
'hasCredentials': username != '' and password != '',
'domain': domain,
'width': width,
'height': height,
@ -137,14 +119,23 @@ class RDPTransport(BaseRDPTransport):
'wallpaper': self.wallpaper.isTrue(),
'multimon': self.multimon.isTrue(),
'fullScreen': width == -1 or height == -1,
'this_server': request.build_absolute_uri('/')
'this_server': request.build_absolute_uri('/'),
'r': r,
}
logger.debug('Detected os: {}'.format(data['os']))
m = tools.DictAsObj(data)
if data['os'] == OsDetector.Windows:
return self.windowsScript(data)
elif data['os'] == OsDetector.Macintosh:
return self.macOsXScript(data)
if m.domain != '':
m.usernameWithDomain = '{}\\\\{}'.format(m.domain, m.username)
else:
m.usernameWithDomain = m.username
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 ''

View File

@ -38,6 +38,7 @@ from uds.core.transports.BaseTransport import Transport
from uds.core.transports import protocols
from uds.models import TicketStore
from uds.core.util import OsDetector
from uds.core.util import tools
from .BaseRDPTransport import BaseRDPTransport
from .RDPFile import RDPFile
@ -84,61 +85,13 @@ class TSRDPTransport(BaseRDPTransport):
if values['tunnelServer'].count(':') != 1:
raise Transport.ValidationException(_('Must use HOST:PORT in Tunnel Server Field'))
def windowsScript(self, data):
r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Windows)
r.address = '{address}'
r.username = data['username']
r.password = '{password}'
r.domain = data['domain']
r.redirectPrinters = self.allowPrinters.isTrue()
r.redirectSmartcards = self.allowSmartcards.isTrue()
r.redirectDrives = self.allowDrives.isTrue()
r.redirectSerials = self.allowSerials.isTrue()
r.showWallpaper = self.wallpaper.isTrue()
r.multimon = self.multimon.isTrue()
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(
file=r.get(), password=data['password'],
server=data['ip'],
port=3389,
tunUser=data['tunUser'],
tunPass=data['tunPass'],
tunHost=data['tunHost'],
tunPort=data['tunPort']
)
return self.getScript('scripts/windows/tunnel.py').format(m=m)
def macOsXScript(self, data):
r = RDPFile(data['fullScreen'], data['width'], data['height'], data['depth'], target=OsDetector.Macintosh)
r.address = '{address}'
r.username = data['username']
r.domain = data['domain']
r.redirectPrinters = self.allowPrinters.isTrue()
r.redirectSmartcards = self.allowSmartcards.isTrue()
r.redirectDrives = self.allowDrives.isTrue()
r.redirectSerials = self.allowSerials.isTrue()
r.showWallpaper = self.wallpaper.isTrue()
r.multimon = self.multimon.isTrue()
if data['domain'] != '':
username = '{}\\\\{}'.format(data['domain'], data['username'])
else:
username = data['username']
return self.getScript('scripts/macosx/tunnel.py').format(
os=data['os'],
file=r.get(),
password=data['password'],
username=username,
server=data['ip'],
this_server=data['this_server'],
r=r,
port=3389,
tunUser=data['tunUser'],
tunPass=data['tunPass'],
tunHost=data['tunHost'],
tunPort=data['tunPort']
)
def macOsXScript(self, m):
return self.getScript('scripts/macosx/tunnel.py').format(m=m)
def getUDSTransportScript(self, userService, transport, ip, os, user, password, request):
# We use helper to keep this clean
@ -157,6 +110,18 @@ class TSRDPTransport(BaseRDPTransport):
logger.debug('Username generated: {0}, password: {1}'.format(tunuser, tunpass))
r = RDPFile(width == -1 or height == -1, width, height, depth, target=os['OS'])
r.address = '{address}'
r.username = username
r.domain = domain
r.redirectPrinters = self.allowPrinters.isTrue()
r.redirectSmartcards = self.allowSmartcards.isTrue()
r.redirectDrives = self.allowDrives.isTrue()
r.redirectSerials = self.allowSerials.isTrue()
r.showWallpaper = self.wallpaper.isTrue()
r.multimon = self.multimon.isTrue()
# data
data = {
'os': os['OS'],
@ -167,6 +132,7 @@ class TSRDPTransport(BaseRDPTransport):
'tunPort': sshPort,
'username': username,
'password': password,
'hasCredentials': username != '' and password != '',
'domain': domain,
'width': width,
'height': height,
@ -179,12 +145,21 @@ class TSRDPTransport(BaseRDPTransport):
'wallpaper': self.wallpaper.isTrue(),
'multimon': self.multimon.isTrue(),
'fullScreen': width == -1 or height == -1,
'this_server': request.build_absolute_uri('/')
'this_server': request.build_absolute_uri('/'),
'r': r,
}
if data['os'] == OsDetector.Windows:
return self.windowsScript(data)
elif data['os'] == OsDetector.Macintosh:
return self.macOsXScript(data)
m = tools.DictAsObj(data)
if m.domain != '':
m.usernameWithDomain = '{}\\\\{}'.format(m.domain, m.username)
else:
m.usernameWithDomain = m.username
if m.os == OsDetector.Windows:
r.password = '{password}'
return self.windowsScript(m)
if m.os == OsDetector.Macintosh:
return self.macOsXScript(m)
return ''

View File

@ -0,0 +1,49 @@
# 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 os
import re
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
tools.addTaskToWait(subprocess.Popen(params))
def execRdesktop(parent, rdesktop):
return
# Try to locate a "valid" version of xfreerdp as first option
xfreerdp = tools.findApp('xfreerdp')
if xfreerdp is not None:
# Check for nice version
try:
version = subprocess.check_output([xfreerdp, '--version'])
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
else:
execNewXFreeRdp(parent, xfreerdp) # @UndefinedVariable
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
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.')

View File

@ -12,7 +12,7 @@ from uds import tools # @UnresolvedImport
import six
theFile = '''{file}'''
theFile = '''{m.r.as_file}'''
# First, try to locate Remote Desktop Connection (version 2, from Microsoft website, not the app store one)
@ -35,8 +35,8 @@ def onExit():
[
'security',
'delete-generic-password',
'-a', '{username}',
'-s', 'Remote Desktop Connection 2 Password for {ip}',
'-a', '{m.usernameWithDomain}',
'-s', 'Remote Desktop Connection 2 Password for {m.ip}',
]
)
@ -52,7 +52,7 @@ if executable is None:
</li>
<li>
<p><b>CoRD</b> (A bit unstable from 10.7 onwards)</p>
<p>You can get it from <a href="{this_server}static/other/CoRD.pkg">this link</a></p>
<p>You can get it from <a href="{m.this_server}static/other/CoRD.pkg">this link</a></p>
</li>
</ul>
<p>If both apps are installed, Remote Desktop Connection will be used as first option</p>
@ -60,54 +60,52 @@ if executable is None:
''', QtGui.QMessageBox.Ok)
elif executable == msrdc:
try:
if '{username}' != '' and '{password}' != '':
if {m.hasCredentials}: # @UndefinedVariable
subprocess.call(
[
'security',
'add-generic-password',
'-w', '{password}',
'-w', '{m.password}',
'-U',
'-a', '{username}',
'-s', 'Remote Desktop Connection 2 Password for {ip}',
'-a', '{m.usernameWithDomain}',
'-s', 'Remote Desktop Connection 2 Password for {m.ip}',
'-T', '/Applications/Remote Desktop Connection.app',
]
)
tools.addExecBeforeExit(onExit)
# Call but do not wait for exit
tools.addTaskToWait(subprocess.Popen([executable, filename]))
tools.addExecBeforeExit(onExit)
tools.addFileToUnlink(filename)
except Exception as e:
QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
else: # CoRD
url = 'rdp://'
if '\\' in '{username}':
username, domain = '{username}'.split('\\')
else:
username, domain = '{username}', ''
username, domain = '{m.username}', '{m.domain}'
if username != '':
url += username
if '{password}' != '':
url += ':' + urllib.quote('{password}')
if '{m.password}' != '':
url += ':' + urllib.quote('{m.password}')
url += '@'
url += '{ip}/'
url += '{m.ip}/'
if domain != '':
url += domain
url += '?screenDepth={r.bpp}'
url += '?screenDepth={m.r.bpp}'
if {r.fullScreen}: # @UndefinedVariable
if {m.r.fullScreen}: # @UndefinedVariable
url += '&fullscreen=true'
else:
url += 'screenWidth={r.width}&screenHeight={r.height}'
url += 'screenWidth={m.r.width}&screenHeight={m.r.height}'
url += '&forwardAudio=' + '01'[{r.redirectAudio}] # @UndefinedVariable
url += '&forwardAudio=' + '01'[{m.r.redirectAudio}] # @UndefinedVariable
if {r.redirectDrives}: # @UndefinedVariable
if {m.r.redirectDrives}: # @UndefinedVariable
url += '&forwardDisks=true'
if {r.redirectPrinters}: # @UndefinedVariable
if {m.r.redirectPrinters}: # @UndefinedVariable
url += '&forwardPrinters=true'
tools.addTaskToWait(subprocess.Popen(['open', url]))

View File

@ -31,7 +31,7 @@ def onExit():
[
'security',
'delete-generic-password',
'-a', '{username}',
'-a', '{m.username}',
'-s', 'Remote Desktop Connection 2 Password for 127.0.0.1',
]
)
@ -48,7 +48,7 @@ if executable is None:
</li>
<li>
<p><b>CoRD</b> (A bit unstable from 10.7 onwards)</p>
<p>You can get it from <a href="{this_server}static/other/CoRD.pkg">this link</a></p>
<p>You can get it from <a href="{m.this_server}static/other/CoRD.pkg">this link</a></p>
</li>
</ul>
<p>If both apps are installed, Remote Desktop Connection will be used as first option</p>
@ -56,13 +56,13 @@ if executable is None:
''', QtGui.QMessageBox.Ok)
forwardThread, port = forward('{tunHost}', '{tunPort}', '{tunUser}', '{tunPass}', '{server}', '{port}')
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
else:
theFile = '''{file}'''.format(
theFile = '''{m.r.as_file}'''.format(
address='127.0.0.1:{{}}'.format(port)
)
filename = tools.saveTempFile(theFile)
@ -70,54 +70,51 @@ else:
if executable == msrdc:
try:
if '{username}' != '' and '{password}' != '':
if {m.hasCredentials}: # @UndefinedVariable
subprocess.call(
[
'security',
'add-generic-password',
'-w', '{password}',
'-w', '{m.password}',
'-U',
'-a', '{username}',
'-a', '{m.username}',
'-s', 'Remote Desktop Connection 2 Password for 127.0.0.1'.format(port),
'-T', '/Applications/Remote Desktop Connection.app',
]
)
tools.addExecBeforeExit(onExit)
# Call but do not wait for exit
tools.addTaskToWait(subprocess.Popen([executable, filename]))
tools.addExecBeforeExit(onExit)
tools.addFileToUnlink(filename)
except Exception as e:
QtGui.QMessageBox.critical(parent, 'Notice', six.text_type(e), QtGui.QMessageBox.Ok) # @UndefinedVariable
else: # CoRD
url = 'rdp://'
if '\\' in '{username}':
username, domain = '{username}'.split('\\')
else:
username, domain = '{username}', ''
username, domain = '{m.username}', '{m.domain}'
if username != '':
url += username
if '{password}' != '':
url += ':' + urllib.quote('{password}')
if '{m.password}' != '':
url += ':' + urllib.quote('{m.password}')
url += '@'
url += '127.0.0.1:3389/'
if domain != '':
url += domain
url += '?screenDepth={r.bpp}'
url += '?screenDepth={m.r.bpp}'
if {r.fullScreen}: # @UndefinedVariable
if {m.r.fullScreen}: # @UndefinedVariable
url += '&fullscreen=true'
else:
url += 'screenWidth={r.width}&screenHeight={r.height}'
url += 'screenWidth={m.r.width}&screenHeight={m.r.height}'
url += '&forwardAudio=' + '01'[{r.redirectAudio}] # @UndefinedVariable
url += '&forwardAudio=' + '01'[{m.r.redirectAudio}] # @UndefinedVariable
if {r.redirectDrives}: # @UndefinedVariable
if {m.r.redirectDrives}: # @UndefinedVariable
url += '&forwardDisks=true'
if {r.redirectPrinters}: # @UndefinedVariable
if {m.r.redirectPrinters}: # @UndefinedVariable
url += '&forwardPrinters=true'
tools.addTaskToWait(subprocess.Popen(['open', url]))

View File

@ -12,10 +12,10 @@ from uds import tools # @UnresolvedImport
import six
theFile = '''{file}'''.format(password=win32crypt.CryptProtectData(six.binary_type('{password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex'))
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)
executable = os.path.join(os.path.join(os.environ['WINDIR'], 'system32'), 'mstsc.exe')
executable = tools.findApp('mstsc.exe')
subprocess.call([executable, filename])
# tools.addFileToUnlink(filename)

View File

@ -14,22 +14,22 @@ from uds import tools # @UnresolvedImport
import six
forwardThread, port = forward('{tunHost}', '{tunPort}', '{tunUser}', '{tunPass}', '{server}', '{port}')
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 file')
else:
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)
)
theFile = '''{file}'''.format(
password=win32crypt.CryptProtectData(six.binary_type('{password}'.encode('UTF-16LE')), None, None, None, None, 0x01).encode('hex'),
address='127.0.0.1:{{}}'.format(port)
)
filename = tools.saveTempFile(theFile)
executable = tools.findApp('mstsc.exe')
if executable is None:
raise Exception('Unable to find mstsc.exe')
filename = tools.saveTempFile(theFile)
executable = os.path.join(os.path.join(os.environ['WINDIR'], 'system32'), 'mstsc.exe')
subprocess.call([executable, filename])
tools.addFileToUnlink(filename)
subprocess.call([executable, filename])
tools.addFileToUnlink(filename)
# QtGui.QMessageBox.critical(parent, 'Notice', filename + ", " + executable, QtGui.QMessageBox.Ok)