forked from shaba/openuds
Fixing up mac os RDP transport support
This commit is contained in:
parent
da23222f0f
commit
cab09aea9c
@ -87,6 +87,7 @@ class RDPTransport(BaseRDPTransport):
|
|||||||
printerString = BaseRDPTransport.printerString
|
printerString = BaseRDPTransport.printerString
|
||||||
smartcardString = BaseRDPTransport.smartcardString
|
smartcardString = BaseRDPTransport.smartcardString
|
||||||
customParameters = BaseRDPTransport.customParameters
|
customParameters = BaseRDPTransport.customParameters
|
||||||
|
allowMacMSRDC = BaseRDPTransport.allowMacMSRDC
|
||||||
|
|
||||||
def getUDSTransportScript( # pylint: disable=too-many-locals
|
def getUDSTransportScript( # pylint: disable=too-many-locals
|
||||||
self,
|
self,
|
||||||
@ -164,13 +165,14 @@ class RDPTransport(BaseRDPTransport):
|
|||||||
elif osName == 'linux':
|
elif osName == 'linux':
|
||||||
sp.update({
|
sp.update({
|
||||||
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
||||||
'as_rdesktop_params': r.as_rdesktop_params,
|
|
||||||
'address': r.address,
|
'address': r.address,
|
||||||
})
|
})
|
||||||
else: # Mac
|
else: # Mac
|
||||||
sp.update({
|
sp.update({
|
||||||
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
||||||
'as_rdp_url': r.as_rdp_url,
|
'as_rdp_url': r.as_rdp_url if self.allowMacMSRDC.isTrue() else '',
|
||||||
|
'as_file': r.as_file if self.allowMacMSRDC.isTrue() else '',
|
||||||
|
'address': r.address,
|
||||||
})
|
})
|
||||||
|
|
||||||
return self.getScript('scripts/{}/direct.py', osName, sp)
|
return self.getScript('scripts/{}/direct.py', osName, sp)
|
||||||
|
@ -139,6 +139,8 @@ class BaseRDPTransport(transports.Transport):
|
|||||||
smartcardString = gui.TextField(label=_('Smartcard string'), order=44, tooltip=_('If smartcard is checked, the smartcard string used with xfreerdp client'), tab='Linux Client', length=256)
|
smartcardString = gui.TextField(label=_('Smartcard string'), order=44, tooltip=_('If smartcard is checked, the smartcard string used with xfreerdp client'), tab='Linux Client', length=256)
|
||||||
customParameters = gui.TextField(label=_('Custom parameters'), order=45, tooltip=_('If not empty, extra parameter to include for Linux Client (for example /usb:id,dev:054c:0268, or aything compatible with your xfreerdp client)'), tab='Linux Client', length=256)
|
customParameters = gui.TextField(label=_('Custom parameters'), order=45, tooltip=_('If not empty, extra parameter to include for Linux Client (for example /usb:id,dev:054c:0268, or aything compatible with your xfreerdp client)'), tab='Linux Client', length=256)
|
||||||
|
|
||||||
|
allowMacMSRDC = gui.CheckBoxField(label=_('Allow Microsoft Rdp Client'), order=40, tooltip=_('If checked, allows use of Microsoft Remote Desktop Clien. PASSWORD WILL BE PRONPTED!'), tab='Mac OS X', defvalue=gui.FALSE)
|
||||||
|
|
||||||
def isAvailableFor(self, userService: 'models.UserService', ip: str) -> bool:
|
def isAvailableFor(self, userService: 'models.UserService', ip: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if the transport is available for the requested destination ip
|
Checks if the transport is available for the requested destination ip
|
||||||
|
@ -85,10 +85,8 @@ class RDPFile:
|
|||||||
self.target = target
|
self.target = target
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
if self.target in (OsDetector.Windows, OsDetector.Linux):
|
if self.target in (OsDetector.Windows, OsDetector.Linux, OsDetector.Macintosh):
|
||||||
return self.getGeneric()
|
return self.getGeneric()
|
||||||
if self.target == OsDetector.Macintosh:
|
|
||||||
return self.getMacOsX()
|
|
||||||
# Unknown target
|
# Unknown target
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@ -114,7 +112,7 @@ class RDPFile:
|
|||||||
params.append('/smartcard')
|
params.append('/smartcard')
|
||||||
|
|
||||||
if self.redirectAudio:
|
if self.redirectAudio:
|
||||||
if self.alsa:
|
if self.alsa and self.target != OsDetector.Macintosh:
|
||||||
params.append('/sound:sys:alsa,format:1,quality:high')
|
params.append('/sound:sys:alsa,format:1,quality:high')
|
||||||
params.append('/microphone:sys:alsa')
|
params.append('/microphone:sys:alsa')
|
||||||
else:
|
else:
|
||||||
@ -125,7 +123,10 @@ class RDPFile:
|
|||||||
params.append('/video')
|
params.append('/video')
|
||||||
|
|
||||||
if self.redirectDrives != 'false':
|
if self.redirectDrives != 'false':
|
||||||
params.append('/drive:media,/media')
|
if self.target == OsDetector.Linux:
|
||||||
|
params.append('/drive:media,/media')
|
||||||
|
else:
|
||||||
|
params.append('/drive:Users,/Users')
|
||||||
# params.append('/home-drive')
|
# params.append('/home-drive')
|
||||||
|
|
||||||
if self.redirectHome is True:
|
if self.redirectHome is True:
|
||||||
@ -151,7 +152,11 @@ class RDPFile:
|
|||||||
params.append('/multimon')
|
params.append('/multimon')
|
||||||
|
|
||||||
if self.fullScreen:
|
if self.fullScreen:
|
||||||
params.append('/f')
|
if self.target != OsDetector.Macintosh:
|
||||||
|
params.append('/f')
|
||||||
|
else: # On mac, will fix this later...
|
||||||
|
params.append('/w:#WIDTH#')
|
||||||
|
params.append('/h:#HEIGHT#')
|
||||||
else:
|
else:
|
||||||
params.append('/w:{}'.format(self.width))
|
params.append('/w:{}'.format(self.width))
|
||||||
params.append('/h:{}'.format(self.height))
|
params.append('/h:{}'.format(self.height))
|
||||||
@ -183,61 +188,6 @@ class RDPFile:
|
|||||||
|
|
||||||
return params
|
return params
|
||||||
|
|
||||||
@property
|
|
||||||
def as_rdesktop_params(self): # pylint: disable=too-many-branches
|
|
||||||
"""
|
|
||||||
Parameters for rdestop with self rdp description
|
|
||||||
Note that server is not added
|
|
||||||
"""
|
|
||||||
|
|
||||||
params = ['-TUDS Connection', '-P']
|
|
||||||
|
|
||||||
if self.enableClipboard:
|
|
||||||
params.append('-rclipboard:PRIMARYCLIPBOARD')
|
|
||||||
|
|
||||||
if self.redirectSmartcards:
|
|
||||||
params.append('-rsdcard')
|
|
||||||
|
|
||||||
if self.redirectAudio:
|
|
||||||
params.append('-rsound:local')
|
|
||||||
else:
|
|
||||||
params.append('-rsound:off')
|
|
||||||
|
|
||||||
if self.redirectDrives != 'false':
|
|
||||||
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
|
|
||||||
|
|
||||||
def getGeneric(self): # pylint: disable=too-many-statements
|
def getGeneric(self): # pylint: disable=too-many-statements
|
||||||
password = '{password}'
|
password = '{password}'
|
||||||
screenMode = '2' if self.fullScreen else '1'
|
screenMode = '2' if self.fullScreen else '1'
|
||||||
@ -253,8 +203,9 @@ class RDPFile:
|
|||||||
|
|
||||||
res = ''
|
res = ''
|
||||||
res += 'screen mode id:i:' + screenMode + '\n'
|
res += 'screen mode id:i:' + screenMode + '\n'
|
||||||
res += 'desktopwidth:i:' + self.width + '\n'
|
if self.width[0] != '-' and self.height[0] != '-':
|
||||||
res += 'desktopheight:i:' + self.height + '\n'
|
res += 'desktopwidth:i:' + self.width + '\n'
|
||||||
|
res += 'desktopheight:i:' + self.height + '\n'
|
||||||
res += 'session bpp:i:' + self.bpp + '\n'
|
res += 'session bpp:i:' + self.bpp + '\n'
|
||||||
res += 'use multimon:i:' + useMultimon + '\n'
|
res += 'use multimon:i:' + useMultimon + '\n'
|
||||||
res += 'auto connect:i:1' + '\n'
|
res += 'auto connect:i:1' + '\n'
|
||||||
|
@ -101,6 +101,7 @@ class TRDPTransport(BaseRDPTransport):
|
|||||||
printerString = BaseRDPTransport.printerString
|
printerString = BaseRDPTransport.printerString
|
||||||
smartcardString = BaseRDPTransport.smartcardString
|
smartcardString = BaseRDPTransport.smartcardString
|
||||||
customParameters = BaseRDPTransport.customParameters
|
customParameters = BaseRDPTransport.customParameters
|
||||||
|
allowMacMSRDC = BaseRDPTransport.allowMacMSRDC
|
||||||
|
|
||||||
def initialize(self, values: 'Module.ValuesType'):
|
def initialize(self, values: 'Module.ValuesType'):
|
||||||
if values:
|
if values:
|
||||||
@ -190,12 +191,12 @@ class TRDPTransport(BaseRDPTransport):
|
|||||||
elif osName == 'linux':
|
elif osName == 'linux':
|
||||||
sp.update({
|
sp.update({
|
||||||
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
||||||
'as_rdesktop_params': r.as_rdesktop_params,
|
|
||||||
})
|
})
|
||||||
else: # Mac
|
else: # Mac
|
||||||
sp.update({
|
sp.update({
|
||||||
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
'as_new_xfreerdp_params': r.as_new_xfreerdp_params,
|
||||||
'as_rdp_url': r.as_rdp_url,
|
'as_file': r.as_file if self.allowMacMSRDC.isTrue() else '',
|
||||||
|
'as_rdp_url': r.as_rdp_url if self.allowMacMSRDC.isTrue() else '',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
|
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import shutil
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from uds import tools # @UnresolvedImport
|
from uds import tools # @UnresolvedImport
|
||||||
@ -12,17 +13,25 @@ from uds import tools # @UnresolvedImport
|
|||||||
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
|
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
|
||||||
|
|
||||||
msrdc = '/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
|
msrdc = '/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
|
||||||
xfreerdp = 'xfreerdp' # TODO
|
xfreerdp = '/usr/local/bin/xfreerdp'
|
||||||
executable = None
|
executable = None
|
||||||
|
|
||||||
|
def fixResolution():
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0])
|
||||||
|
res = re.search(': \d* x \d*', results).group(0).split(' ')
|
||||||
|
width, height = str(int(res[1])-4), str(int(int(res[3])-128)) # Width and Height
|
||||||
|
return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params']))
|
||||||
|
|
||||||
# Check first xfreerdp, allow password redir
|
# Check first xfreerdp, allow password redir
|
||||||
if os.path.isfile(xfreerdp):
|
if os.path.isfile(xfreerdp):
|
||||||
executable = xfreerdp
|
executable = xfreerdp
|
||||||
elif os.path.isfile(msrdc) and sp['as_rdp_url']:
|
elif os.path.isfile(msrdc) and sp['as_file']:
|
||||||
executable = msrdc
|
executable = msrdc
|
||||||
|
|
||||||
if executable is None:
|
if executable is None:
|
||||||
if sp['as_rdp_url']:
|
if sp['as_file']:
|
||||||
raise Exception('''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
|
raise Exception('''<p><b>Microsoft Remote Desktop or xfreerdp not found</b></p>
|
||||||
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
|
<p>In order to connect to UDS RDP Sessions, you need to have a<p>
|
||||||
<ul>
|
<ul>
|
||||||
@ -44,6 +53,20 @@ if executable is None:
|
|||||||
</ul>
|
</ul>
|
||||||
''')
|
''')
|
||||||
elif executable == msrdc:
|
elif executable == msrdc:
|
||||||
url = sp['as_rdp_url'] # @UndefinedVariable
|
theFile = sp['as_file']
|
||||||
|
filename = tools.saveTempFile(theFile)
|
||||||
|
# Rename as .rdp, so open recognizes it
|
||||||
|
shutil.move(filename, filename + '.rdp')
|
||||||
|
|
||||||
|
tools.addTaskToWait(subprocess.Popen(['open', filename + '.rdp']))
|
||||||
|
tools.addFileToUnlink(filename + '.rdp')
|
||||||
|
elif executable == xfreerdp:
|
||||||
|
# Fix resolution...
|
||||||
|
try:
|
||||||
|
xfparms = fixResolution()
|
||||||
|
except Exception as e:
|
||||||
|
xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params']))
|
||||||
|
|
||||||
|
params = [executable] + xfparms + ['/v:{}'.format(sp['address'])] # @UndefinedVariable
|
||||||
|
subprocess.Popen(params)
|
||||||
|
|
||||||
tools.addTaskToWait(subprocess.Popen(['open', url]))
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Nyiuosn1S6FeFLxz7BT7vOOt0WCnObOYM+vi6PkKbGj+hkwuFIPV/OFml7SxneujX3/197wVZxnhu0JTNb32sa8VB0FWz2OJoinH+l5cjcugA9Hsde9tjtMkhPc84tv0pQf+vPL3kHmfq7Qw1cQ/UuYfnp02HGmHDzIlnLmxoOy1CqxomTd8W4Ko0qVgLGUrvACinl8Z/Ya/LViECenIvC/ske8ZAlyIF/ICMp3VxB5QedNezwxm6KthL/BtgttX6IYNcr+caxnYfVO+VAzpfe4P9hg+91OE71zG0DpY1/CQIOEBd3ejxhRjfGnNGGisimxrQ1sutzsNBMjUJYxJNFGVdRlRNp4phM1pIrb9LWRoKaqXlRbSNyXn041oL10EP9wf3GzG0KnQVLhZ/bYl88tTIBJC7res9Q90fffw1EzbPFkcG6QyCaabv6mQ+9GsIH/zOPQsihqREtCL2HCDc+wlY9DBiU5q4KJp3hRzHFjwzzqqXpejV/cJfOENhlJA5AGRmlu3hLREsfyC9QR3G26dgSXF/FR6VeZZzB44KEY3DI7hq6CplyTwoOgGzUJW7wxkqRhdzV3tpZereBYJW3ntkeNsBOzzzEJax+robmzHPiYPQM7WCWsGWdP3jux+yDPAtFnAC5YKGyhXhOgjeLiByI/nmw3k+/g5M8XOASQ=
|
Hfx61+xy7yzVCe4mq8/9rekZvTpbW64z3rPRV7ythmT+zLjOdd07nCresS/mA5FwfK1B2dGqkUw2Sj7XYfPVHp+pfxa1MSVDeAeyh12mhLNi9AcEvrkRw7kfQ59ZHgm4fZvAtOpkWqN/pU+V73T5eTdhIBATRS9PCwJwbYOTiEw7ndF+nZpvW/n6E0grpSoqr2QuEqj8tK+4Sb7OTtwHeYku3KDM/CZ8RYP5+OLW1OcyjpqkbbL9xgN+8zPu0wNpBMHSzwRNkQ8I0WVvWhtyhbx2RpwaFBd2ETOAUzaczJoZ/R8dNOBqBbqUk3YkuJdGhUQ+bo8ZL9Ga14Ew/wKyht+G9IkiyLzVgOxKCPT05g0ept2DU2PqJw3isK3vzkhHV7JQC7T75Aqouc/N37YNcv/OWsTD+HcLHpZoo8kMaG6PQxyfg9smrcuJPoeOHVbklRLR7cptuZ8HPEyTCKjvCx5rpi2uvXw/LsHsEWesqYt69o8BOOMhm23Hz0LK/ZAhQ7Ll/9p17+g/JeUIFeBxuXNg5A28fvTdbK6GwzbSf54Y7/woyFFcw+ii/FRUpjehN0R9M6JVqLa0XTYgQuIwrPApL5uepdZZcNFXn/ax9lK7HPkJy55iun4buQFODxMi4slgJaPrjkiY8/LwQzh0cohwWBOy05U2nOEahxUQXrA=
|
@ -4,7 +4,9 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
|
# pylint: disable=import-error, no-name-in-module, too-many-format-args, undefined-variable, invalid-sequence-index
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import shutil
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from uds.forward import forward # @UnresolvedImport
|
from uds.forward import forward # @UnresolvedImport
|
||||||
|
|
||||||
from uds import tools # @UnresolvedImport
|
from uds import tools # @UnresolvedImport
|
||||||
@ -12,8 +14,14 @@ from uds import tools # @UnresolvedImport
|
|||||||
# Inject local passed sp into globals for functions
|
# Inject local passed sp into globals for functions
|
||||||
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
|
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
|
||||||
|
|
||||||
# Inject local passed sp into globals for functions
|
def fixResolution():
|
||||||
globals()['sp'] = sp # type: ignore # pylint: disable=undefined-variable
|
import re
|
||||||
|
import subprocess
|
||||||
|
results = str(subprocess.Popen(['system_profiler SPDisplaysDataType'],stdout=subprocess.PIPE, shell=True).communicate()[0])
|
||||||
|
res = re.search(': \d* x \d*', results).group(0).split(' ')
|
||||||
|
width, height = str(int(res[1])-4), str(int(int(res[3])-128)) # Width and Height
|
||||||
|
return list(map(lambda x: x.replace('#WIDTH#', width).replace('#HEIGHT#', height), sp['as_new_xfreerdp_params']))
|
||||||
|
|
||||||
|
|
||||||
msrdc = '/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
|
msrdc = '/Applications/Microsoft Remote Desktop.app/Contents/MacOS/Microsoft Remote Desktop'
|
||||||
xfreerdp = 'xfreerdp' # TODO
|
xfreerdp = 'xfreerdp' # TODO
|
||||||
@ -22,7 +30,7 @@ executable = None
|
|||||||
# Check first xfreerdp, allow password redir
|
# Check first xfreerdp, allow password redir
|
||||||
if os.path.isfile(xfreerdp):
|
if os.path.isfile(xfreerdp):
|
||||||
executable = xfreerdp
|
executable = xfreerdp
|
||||||
elif os.path.isfile(msrdc) and sp['as_rdp_url']:
|
elif os.path.isfile(msrdc) and sp['as_file']:
|
||||||
executable = msrdc
|
executable = msrdc
|
||||||
|
|
||||||
if executable is None:
|
if executable is None:
|
||||||
@ -47,7 +55,6 @@ if executable is None:
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
''')
|
''')
|
||||||
elif executable == msrdc:
|
|
||||||
|
|
||||||
forwardThread, port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], 3389, waitTime=sp['tunWait']) # @UndefinedVariable
|
forwardThread, port = forward(sp['tunHost'], sp['tunPort'], sp['tunUser'], sp['tunPass'], sp['ip'], 3389, waitTime=sp['tunWait']) # @UndefinedVariable
|
||||||
address = '127.0.0.1:{}'.format(port)
|
address = '127.0.0.1:{}'.format(port)
|
||||||
@ -57,6 +64,23 @@ if forwardThread.status == 2:
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
if executable == msrdc:
|
if executable == msrdc:
|
||||||
url = sp['as_rdp_url'] # @UndefinedVariable
|
theFile = theFile = sp['as_file'].format(
|
||||||
|
address='127.0.0.1:{}'.format(port)
|
||||||
|
)
|
||||||
|
|
||||||
|
filename = tools.saveTempFile(theFile)
|
||||||
|
# Rename as .rdp, so open recognizes it
|
||||||
|
shutil.move(filename, filename + '.rdp')
|
||||||
|
|
||||||
|
tools.addTaskToWait(subprocess.Popen(['open', filename + '.rdp']))
|
||||||
|
tools.addFileToUnlink(filename + '.rdp')
|
||||||
|
elif executable == xfreerdp:
|
||||||
|
# Fix resolution...
|
||||||
|
try:
|
||||||
|
xfparms = fixResolution()
|
||||||
|
except Exception as e:
|
||||||
|
xfparms = list(map(lambda x: x.replace('#WIDTH#', '1400').replace('#HEIGHT#', '800'), sp['as_new_xfreerdp_params']))
|
||||||
|
|
||||||
|
params = [executable] + xfparms + ['/v:{}'.format(address)]
|
||||||
|
subprocess.Popen(params)
|
||||||
|
|
||||||
tools.addTaskToWait(subprocess.Popen(['open', url]))
|
|
||||||
|
@ -1 +1 @@
|
|||||||
DBEvNnwbYQG8ycmmkatf1kBDFYbyZvOLG34Xb4WDu+JVvZarWJVwcgqJL6N7dHY3oTl0X8wqnMQJ4zXB5ee3UoXISoHiglCprov/DvvgF5O0ZY+Gw4qeW+J+BZ9HgUUeIBI1aKTt0EcfsqMwy/QubsdZqMVkBhorU+0il5WxSU5tbMsE6Z0t3p65diT2YgIE85LHtcaSVYGYXD93d+UcnQIxFm5WJWXQrXad9mcfZNhME98ITvtnYOlUQJPN2JbTqwEPCKOzptiY2mPOuObZiXZ4ziWRdTZr/ANP+dpX63/L0yWdKIlb4kpBJHYTpYxHd8ncVPT+qFhGV3mJ5wi3uHB1bkO8dJ7vsMk+3oYabXjPDPyXixaGTLqtF9NnYOsLJHO6238dtprAd+FvOw2oqR5Mm4oXvV661nyc27y7HqjhoMN3fqO0UDR94xUxJWucD8AwypRADYhrQifvJZMVRZ/UWjdGlp/VBTKW7UhJNGu4fg1SSgCCMSCbLCCylaqRg0bSwvrR3NR7Mv+OsKxqNBh7D83c7LkL551ccL/+LVTatKbuZd9Ely1x9ngjxplkvOWYS90i3rfDN2oLnkGKWz/xuDvkZUtXZbJD95GL51vm8BUxYlB6SebwVGd829BL5eV/tpq4xdL7uin6cFc6lvOexHM1eIbaayOsn1o75so=
|
rFojgaIeYnTAmzNEhZU1N1Tf8I4p4zm4MrJAQM3evy9B6VDKEFSsF1iHh93AP8HVsYzwgHhvLil19f7PfGvdTi8lS3fBNuz7MB9lEV3EP6uXOkVXIvTzGIRJgQGybT0ibJMqLHAfYZISMLIZkU/yE5thlydWCQjUjUsaDoGqCYSQ7u2kz6ggNcxOUYN1KuDuRKGO01k3wRFC5wymvoId4iRPbS17F2WZxB0PbofYkJyn3ZI3eTvQENjWkL6hIA7MdRsYMzBzx/xyIjmZPeOn5pIIn7fqtGZkUTW9nw25egf8VtIUsHaY/SaP04plDDaTt2vRpeHSBpLvW9uhzektFEMZ2clzblYv2xqd5HUrTp9MUWDauyCJ8r3H/MAC01akqSaOiTbmfJ8pT8gLu+Tlo7FOJN37YhDYUs22z61A4Po0DaiCGj9nP1S9hOplbBTWgfkZQQxJlsdZX6iw0co3c59TTtgNKn1QB9wMlbb6ukdH7xqE3d10cGXzBQC0cz9thnaWdCh+wqVyZI8YeEdS8aqF0C2AogfXjrxbU6obVnU0h2r+epOhvPzKpLO5y9RKnWFFSNqrvMluQlGmEt25AQSpS/KRuGwpsVjSOt55OpXA9BMf6qTU/QE+UDO3DRpBAljzJJOPGhmKNRr59wT0g+SaRg4YkQg2NT5ZN6vTntw=
|
Loading…
Reference in New Issue
Block a user