diff --git a/bin/rdpy-rdpproxy b/bin/rdpy-rdpproxy index d0b9395..03d4e62 100755 --- a/bin/rdpy-rdpproxy +++ b/bin/rdpy-rdpproxy @@ -29,10 +29,20 @@ sys.path.insert(1, os.path.join(sys.path[0], '..')) from rdpy.base import log, error from rdpy.protocol.rdp import rdp -from rdpy.network.proxy import IProxyClient +from rdpy.ui import widget from twisted.internet import reactor from PyQt4 import QtCore, QtGui +class IProxyClient(object): + def getColorDepth(self): + pass + def sendKeyEventScancode(self, code, isPressed): + pass + def sendKeyEventUnicode(self, code, isPressed): + pass + def sendPointerEvent(self, x, y, button, isPressed): + pass + class ProxyServer(rdp.RDPServerObserver): """ Server side of proxy @@ -62,7 +72,7 @@ class ProxyServer(rdp.RDPServerObserver): domain, username, password = self._controller.getCredentials() if self._credentialProvider.isAdmin(domain, username, password): - self.clientConnected(AdminGUI(self)) + self.clientConnected(ProxyAdmin(self)) return try: @@ -126,29 +136,6 @@ class ProxyClient(rdp.RDPClientObserver, IProxyClient): rdp.RDPClientObserver.__init__(self, controller) self._server = server - def getColorDepth(self): - """ - @return: color depth of session (15,16,24,32) - """ - return self._controller.getColorDepth() - - def sendKeyEventScancode(self, code, isPressed): - """ - Send key event with scan code - @param code: scan code - @param isPressed: True if keyboard key is pressed - """ - self._controller.sendKeyEventScancode(code, isPressed) - - def sendPointerEvent(self, x, y, button, isPressed): - """ - Send Pointer event - @param x: x position - @param y: y position - @param button: mouse button 1|2|3 - """ - self._controller.sendPointerEvent(x, y, button, isPressed) - def onReady(self): """ Event use to signal that RDP stack is ready @@ -172,6 +159,14 @@ class ProxyClient(rdp.RDPClientObserver, IProxyClient): @param data: bitmap data """ self._server._controller.sendUpdate(destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data) + def getColorDepth(self): + return self._controller.getColorDepth() + def sendKeyEventScancode(self, code, isPressed): + self._controller.sendKeyEventScancode(code, isPressed) + def sendKeyEventUnicode(self, code, isPressed): + self._controller.sendKeyEventUnicode(code, isPressed) + def sendPointerEvent(self, x, y, button, isPressed): + self._controller.sendPointerEvent(x, y, button, isPressed) class ProxyServerFactory(rdp.ServerFactory): """ @@ -182,7 +177,7 @@ class ProxyServerFactory(rdp.ServerFactory): @param config: rdp-proxy configuration @param credentialProvider: CredentialProvider """ - rdp.ServerFactory.__init__(self, "/home/speyrefitte/dev/certificate/rdpy.key", "/home/speyrefitte/dev/certificate/rdpy.crt", 16) + rdp.ServerFactory.__init__(self, "/home/sylvain/dev/certificate/rdpy.key", "/home/sylvain/dev/certificate/rdpy.crt", 16) self._credentialProvider = credentialProvider def buildObserver(self, controller): @@ -281,62 +276,24 @@ class CredentialProvider(object): """ return self._config['admin']['domain'] == domain and self._config['admin']['username'] == username and self._config['admin']['password'] == password -class AdminGUI(IProxyClient): - """ - Simple Administration GUI - """ +class ProxyAdmin(IProxyClient): def __init__(self, server): - """ - @param server: ProxyServer - @param colorDepth: color depth use to generate screen - """ self._server = server - self._colorDepth = self._server._controller.getColorDepth() - self._activeSessions = [ (x, y) for x, y in ProxyClientFactory._CLIENT_PROXY_.iteritems() ] - self._current = 0 - self.display() - + #self._list = widget.List(ProxyClientFactory._CLIENT_PROXY_.keys(), 100, 100, self.onSelect, widget.Anchor(0, 0, widget.RDPWidgetListener(self._server._controller))) + self._list = widget.List(["salut les copains"], 300, 300, self.onSelect, widget.Anchor(0, 0, widget.RDPWidgetListener(self._server._controller))) def getColorDepth(self): - return self._colorDepth - + return 16 def sendKeyEventScancode(self, code, isPressed): - #enter key - if code == 28: - clientController = self._activeSessions[self._current][1]._controller - self._server.clientConnected(ProxyClient(clientController, self._server)) - #force refresh for new admin screen - width, height = self._server._controller.getScreen() - clientController.sendRefreshOrder(0, 0, width, height) - + if isPressed: + self._list.keyEvent(code) + def sendKeyEventUnicode(self, code, isPressed): + pass def sendPointerEvent(self, x, y, button, isPressed): pass - - def display(self): - """ - Draw GUI that list active session - """ - i = 0 - for name, session in self._activeSessions: - screen = QtGui.QImage(200, 20, QtGui.QImage.Format_RGB16) - if i == self._current: - screen.fill(QtCore.Qt.darkGray) - else: - screen.fill(QtCore.Qt.black) - - with QtGui.QPainter(screen) as qp: - if i == self._current: - qp.setPen(QtCore.Qt.black) - else: - qp.setPen(QtCore.Qt.gray) - qp.setFont(QtGui.QFont('arial', 12)) - qp.drawText(screen.rect(), QtCore.Qt.AlignCenter, name) - - ptr = screen.bits() - ptr.setsize(screen.byteCount()) - self._server._controller.sendUpdate(0, i*25, 199, 19, 200, 20, self._colorDepth, False, ptr.asstring()) + def onSelect(self, name): + if ProxyClientFactory._CLIENT_PROXY_.has_key(name): + self._server.clientConnected(ProxyClient(ProxyClientFactory._CLIENT_PROXY_[name]._controller, self._server)) - i+= 1 - def help(): """ Print help in console diff --git a/rdpy/network/proxy.py b/rdpy/network/proxy.py deleted file mode 100644 index 0a25c63..0000000 --- a/rdpy/network/proxy.py +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (c) 2014 Sylvain Peyrefitte -# -# This file is part of rdpy. -# -# rdpy 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 3 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, see . -# - -""" -Proxy Interface -client -> ProxyServer | ProxyClient -> server -""" - -from rdpy.base.error import CallPureVirtualFuntion - -class IProxyClient(object): - """ - Proxy interface for client side - """ - def getColorDepth(self): - """ - @return: color depth of session (15,16,24,32) - """ - raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "IProxyClient")) - - def sendKeyEventScancode(self, code, isPressed): - """ - Send key event with scan code - @param code: scan code - @param isPressed: True if keyboard key is pressed - """ - raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "IProxyClient")) - - def sendPointerEvent(self, x, y, button, isPressed): - """ - Send Pointer event - @param x: x position - @param y: y position - @param button: mouse button 1|2|3 - """ - raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "IProxyClient")) - diff --git a/rdpy/ui/widget.py b/rdpy/ui/widget.py new file mode 100644 index 0000000..148a653 --- /dev/null +++ b/rdpy/ui/widget.py @@ -0,0 +1,118 @@ +# +# Copyright (c) 2014 Sylvain Peyrefitte +# +# This file is part of rdpy. +# +# rdpy 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 3 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, see . +# + +""" +Fake widget +""" +from rdpy.base.error import CallPureVirtualFuntion +from PyQt4 import QtGui, QtCore + +class IWidgetLister(object): + """ + Listener for object + """ + def onUpdate(self, x, y, image): + """ + Event call by widget when it need to be updated + @param x: x position + @param y: y position + @param image: QImage + """ + raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "onUpdate", "IWidgetLister")) + +class IWidget(object): + def keyEvent(self, code): + pass + def pointerEvent(self, x, y, button): + pass + +class Anchor(IWidgetLister): + def __init__(self, x, y, listener): + self._x = x + self._y = y + self._listener = listener + def onUpdate(self, x, y, image): + self._listener.onUpdate(x + self._x, y + self._y, image) + + +class List(IWidget): + """ + List widget simulate by QT painter + """ + def __init__(self, labels, width, height, callback, listener): + self._labels = labels + self._width = width + self._height = height + self._current = 0 + self._listener = listener + self.update() + self._callback = callback + + def keyEvent(self, code): + #enter key + if code == 28 and len(self._labels) > 0: + self._callback(self._labels[self._current]) + + def pointerEvent(self, x, y, button): + pass + + def update(self): + """ + Draw GUI that list active session + """ + i = 0 + drawArea = QtGui.QImage(self._width, self._height, QtGui.QImage.Format_RGB16) + drawArea.fill(QtCore.Qt.blue) + with QtGui.QPainter(drawArea) as qp: + for label in self._labels: + if i == self._current: + qp.setPen(QtCore.Qt.darkGreen) + qp.drawRoundedRect(0, i * 25, self._width, 25, 0.2, 0.2) + qp.setPen(QtCore.Qt.black) + else: + qp.setPen(QtCore.Qt.gray) + + qp.setFont(QtGui.QFont('courier', 12)) + qp.drawText(0, 0, label) + + self._listener.onUpdate(0, 25 * i, drawArea) + +class RDPWidgetListener(IWidgetLister): + def __init__(self, server): + """ + @param server: RDPServerController + """ + self._server = server + + def onUpdate(self, x, y, image): + """ + Event call by widget when it need to be updated + @param x: x position + @param y: y position + @param image: QImage + """ + nbWidth = image.width() / 64 + 1 + nbHeight = image.height() / 64 + 1 + for i in range(0, nbWidth): + for j in range(0, nbHeight): + tmp = image.copy(i * 64, j * 64, 64, 64) + ptr = tmp.bits() + ptr.setsize(tmp.byteCount()) + self._server.sendUpdate(i*64 + x, j*64 + y, i*64 + x + tmp.width() - 1, j*64 + y + tmp.height() - 1, tmp.width(), tmp.height(), 16, False, ptr.asstring()) + \ No newline at end of file