diff --git a/.gitignore b/.gitignore index 0964ec0..b8f27d5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ .project .pydevproject README.md~ -lib/build/* +rdpy/core/tmp/* *.so *.os .sconsign.dblite diff --git a/bin/rdpy-test b/bin/rdpy-test deleted file mode 100755 index bd3e233..0000000 --- a/bin/rdpy-test +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python -# -# 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 . -# - -import sys, os -# Change path so we find rdpy -sys.path.insert(1, os.path.join(sys.path[0], '..')) -import unittest, rdpy.tests.network.type, rdpy.tests.network.const, rdpy.tests.network.layer - -def headerTest(name): - print "*"*70 - print name - print "*"*70 - -if __name__ == '__main__': - headerTest("Test case rdpy.test.network.type.TypeCase") - suite = unittest.TestLoader().loadTestsFromTestCase(rdpy.tests.network.type.TypeCase) - unittest.TextTestRunner(verbosity=2).run(suite) - - headerTest("Test case rdpy.test.network.const.ConstCase") - suite = unittest.TestLoader().loadTestsFromTestCase(rdpy.tests.network.const.ConstCase) - unittest.TextTestRunner(verbosity=2).run(suite) - - headerTest("Test case rdpy.test.network.type.layer.LayerCase") - suite = unittest.TestLoader().loadTestsFromTestCase(rdpy.tests.network.layer.LayerCase) - unittest.TextTestRunner(verbosity=2).run(suite) - diff --git a/rdpy/tests/__init__.py b/rdpy/base/__init__.py similarity index 100% rename from rdpy/tests/__init__.py rename to rdpy/base/__init__.py diff --git a/rdpy/network/const.py b/rdpy/base/const.py similarity index 100% rename from rdpy/network/const.py rename to rdpy/base/const.py diff --git a/rdpy/network/error.py b/rdpy/base/error.py similarity index 100% rename from rdpy/network/error.py rename to rdpy/base/error.py diff --git a/rdpy/base/log.py b/rdpy/base/log.py new file mode 100644 index 0000000..a6433e3 --- /dev/null +++ b/rdpy/base/log.py @@ -0,0 +1,57 @@ +# +# 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 . +# + +""" +Log engine in RDPY +Actually very basic log engine +""" + +class Level(object): + """ + Level log + """ + DEBUG = 0 + INFO = 1 + WARNING = 2 + ERROR = 3 + +_LOG_LEVEL = Level.DEBUG + +def log(message): + print message + +def error(message): + if _LOG_LEVEL > Level.ERROR: + return + log("ERROR : %s"%message) + +def warning(message): + if _LOG_LEVEL > Level.WARNING: + return + log("WARNING : %s"%message) + +def info(message): + if _LOG_LEVEL > Level.INFO: + return + log("INFO : %s"%message) + +def debug(message): + if _LOG_LEVEL > Level.DEBUG: + return + log("DEBUG : %s"%message) \ No newline at end of file diff --git a/rdpy/tests/network/__init__.py b/rdpy/core/__init__.py similarity index 100% rename from rdpy/tests/network/__init__.py rename to rdpy/core/__init__.py diff --git a/lib/sconstruct b/rdpy/core/sconstruct similarity index 70% rename from lib/sconstruct rename to rdpy/core/sconstruct index c76e8de..f541ac5 100644 --- a/lib/sconstruct +++ b/rdpy/core/sconstruct @@ -2,7 +2,7 @@ import os import sipconfig script_dir = os.path.dirname(os.path.realpath(Dir("#/Sconstruct").abspath)) -build_dir = os.path.join(script_dir, "build") +tmp_dir = os.path.join(script_dir, "tmp") src_dir = os.path.join(script_dir, "src") sip_dir = os.path.join(script_dir, "sip") @@ -14,11 +14,11 @@ def build_sip(target, source, env): os.system(" ".join([config.sip_bin, "-c", os.path.dirname(str(target[0])), str(source[0])])) def build_module(name, install_dir, env): - targetName = os.path.join(build_dir, name, "%s.so"%name) + targetName = os.path.join(tmp_dir, name, "%s.so"%name) - sources = [Glob(os.path.join(src_dir, name,'*.c')), os.path.join(build_dir, name, "sip%scmodule.c"%name)] + sources = [Glob(os.path.join(src_dir, name,'*.c')), os.path.join(tmp_dir, name, "sip%scmodule.c"%name)] - env.Sip(os.path.join(build_dir, name, "sip%scmodule.c"%name), os.path.join(sip_dir, "%s.sip"%name)) + env.Sip(os.path.join(tmp_dir, name, "sip%scmodule.c"%name), os.path.join(sip_dir, "%s.sip"%name)) #sources.append(sip) lib = env.SharedLibrary(target = targetName, source = sources, SHLIBPREFIX='') @@ -31,6 +31,6 @@ def build_module(name, install_dir, env): env = Environment() env.Append(BUILDERS = {'Sip' : Builder(action = build_sip)}) env.Append(CPPPATH = ["/usr/include/python2.7"]); -env.VariantDir('build', 'src', duplicate=0) -build_module("rle", os.path.join(script_dir, "..", "rdpy", "ui"), env) +env.VariantDir('tmp', 'src', duplicate=0) +build_module("rle", script_dir, env) diff --git a/lib/sip/rle.sip b/rdpy/core/sip/rle.sip similarity index 100% rename from lib/sip/rle.sip rename to rdpy/core/sip/rle.sip diff --git a/lib/src/rle/rle.c b/rdpy/core/src/rle/rle.c similarity index 100% rename from lib/src/rle/rle.c rename to rdpy/core/src/rle/rle.c diff --git a/lib/src/rle/rle.h b/rdpy/core/src/rle/rle.h similarity index 100% rename from lib/src/rle/rle.h rename to rdpy/core/src/rle/rle.h diff --git a/rdpy/network/layer.py b/rdpy/network/layer.py index bd9f5a7..396743c 100644 --- a/rdpy/network/layer.py +++ b/rdpy/network/layer.py @@ -23,7 +23,7 @@ Join RDPY design with twisted design RDPY use Layer Protocol design (like twisted) """ -from rdpy.network.error import CallPureVirtualFuntion +from rdpy.base.error import CallPureVirtualFuntion class LayerMode(object): NONE = 0 diff --git a/rdpy/network/type.py b/rdpy/network/type.py index fd76c7b..40d91cd 100644 --- a/rdpy/network/type.py +++ b/rdpy/network/type.py @@ -27,8 +27,8 @@ We are in python we can use that! import struct from copy import deepcopy from StringIO import StringIO -from error import InvalidValue -from rdpy.network.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion +from rdpy.base.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion, InvalidValue +import rdpy.base.log as log def sizeof(element): """ @@ -432,7 +432,7 @@ class CompositeType(Type): raise InvalidSize("Impossible to read type %s : read length is too small"%(self.__class__)) except Exception as e: - print "Error during read %s::%s"%(self.__class__, name) + log.error("Error during read %s::%s"%(self.__class__, name)) #roll back already read for tmpName in self._typeName: if tmpName == name: @@ -440,7 +440,7 @@ class CompositeType(Type): s.pos -= sizeof(self.__dict__[tmpName]) raise e if not self._readLen is None and readLen < self._readLen.value: - print "WARNING : still have correct data in packet %s, read it as padding"%self.__class__ + log.warning("still have correct data in packet %s, read it as padding"%self.__class__) s.read(self._readLen.value - readLen) def __write__(self, s): @@ -452,7 +452,7 @@ class CompositeType(Type): try: s.writeType(self.__dict__[name]) except Exception as e: - print "Error during write %s::%s"%(self.__class__, name) + log.error("Error during write %s::%s"%(self.__class__, name)) raise e def __sizeof__(self): @@ -949,16 +949,4 @@ def CheckValueOnRead(cls): if self != old: raise InvalidValue("CheckValueOnRead %s != %s"%(self, old)) cls.read = read - return cls - -def hexDump(src, length=16): - ''' - print hex representation of str - @param src: string - ''' - FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or '.' for x in range(256)]) - for c in xrange(0, len(src), length): - chars = src[c:c+length] - hexa = ' '.join(["%02x" % ord(x) for x in chars]) - printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or '.') for x in chars]) - print "%04x %-*s %s" % (c, length*3, hexa, printable) \ No newline at end of file + return cls \ No newline at end of file diff --git a/rdpy/protocol/rdp/ber.py b/rdpy/protocol/rdp/ber.py index 32af834..7c9eea5 100644 --- a/rdpy/protocol/rdp/ber.py +++ b/rdpy/protocol/rdp/ber.py @@ -23,7 +23,7 @@ ASN.1 standard """ from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String -from rdpy.network.error import InvalidExpectedDataException, InvalidSize +from rdpy.base.error import InvalidExpectedDataException, InvalidSize class BerPc(object): BER_PC_MASK = 0x20 diff --git a/rdpy/protocol/rdp/caps.py b/rdpy/protocol/rdp/caps.py index c51f8a9..6189082 100644 --- a/rdpy/protocol/rdp/caps.py +++ b/rdpy/protocol/rdp/caps.py @@ -16,7 +16,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -from rdpy.network.error import InvalidExpectedDataException +from rdpy.base.error import InvalidExpectedDataException +import rdpy.base.log as log """ Definition of structure use for capabilities nego @@ -237,7 +238,7 @@ class Capability(CompositeType): for c in [GeneralCapability, BitmapCapability, OrderCapability, BitmapCacheCapability, PointerCapability, InputCapability, BrushCapability, GlyphCapability, OffscreenBitmapCacheCapability, VirtualChannelCapability, SoundCapability, ControlCapability, WindowActivationCapability, FontCapability, ColorCacheCapability, ShareCapability]: if self.capabilitySetType.value == c._TYPE_: return c(readLen = self.lengthCapability - 4) - print "WARNING : unknown Capability type : %s"%hex(self.capabilitySetType.value) + log.debug("unknown Capability type : %s"%hex(self.capabilitySetType.value)) #read entire packet return String(readLen = self.lengthCapability - 4) diff --git a/rdpy/protocol/rdp/gcc.py b/rdpy/protocol/rdp/gcc.py index 735da1f..c782959 100644 --- a/rdpy/protocol/rdp/gcc.py +++ b/rdpy/protocol/rdp/gcc.py @@ -23,8 +23,9 @@ http://msdn.microsoft.com/en-us/library/cc240508.aspx """ from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, Stream, sizeof, FactoryType, ArrayType -import per -from rdpy.network.error import InvalidExpectedDataException +import per, mcs +from rdpy.base.error import InvalidExpectedDataException +import rdpy.base.log as log t124_02_98_oid = ( 0, 0, 20, 124, 0, 1 ) @@ -204,7 +205,7 @@ class DataBlock(CompositeType): for c in [ClientCoreData, ClientSecurityData, ClientNetworkData, ServerCoreData, ServerNetworkData, ServerSecurityData]: if self.type.value == c._TYPE_: return c(readLen = self.length - 4) - print "WARNING : unknown GCC block type : %s"%hex(self.type.value) + log.debug("unknown GCC block type : %s"%hex(self.type.value)) #read entire packet return String(readLen = self.length - 4) @@ -285,8 +286,7 @@ class ServerSecurityData(CompositeType): def __init__(self, readLen = None): CompositeType.__init__(self, readLen = readLen) self.encryptionMethod = UInt32Le() - self.encryptionLevel = UInt32Le() - + self.encryptionLevel = UInt32Le() class ChannelDef(CompositeType): """ @@ -310,7 +310,7 @@ class ClientNetworkData(CompositeType): def __init__(self, readLen = None): CompositeType.__init__(self, readLen = readLen) - self.channelCount = UInt32Le() + self.channelCount = UInt32Le(lambda:len(self.channelDefArray._array)) self.channelDefArray = ArrayType(ChannelDef, readLen = self.channelCount) class ServerNetworkData(CompositeType): @@ -323,7 +323,7 @@ class ServerNetworkData(CompositeType): def __init__(self, readLen = None): CompositeType.__init__(self, readLen = readLen) - self.MCSChannelId = UInt16Le() + self.MCSChannelId = UInt16Le(mcs.Channel.MCS_GLOBAL_CHANNEL) self.channelCount = UInt16Le(lambda:len(self.channelIdArray._array)) self.channelIdArray = ArrayType(UInt16Le, readLen = self.channelCount) self.pad = UInt16Le(conditional = lambda:((self.channelCount.value % 2) == 1)) diff --git a/rdpy/protocol/rdp/lic.py b/rdpy/protocol/rdp/lic.py index ae91144..c882437 100644 --- a/rdpy/protocol/rdp/lic.py +++ b/rdpy/protocol/rdp/lic.py @@ -23,7 +23,8 @@ RDP extended license """ from rdpy.network.type import CompositeType, UInt8, UInt16Le, UInt32Le, String, sizeof, FactoryType, ArrayType -from rdpy.network.error import InvalidExpectedDataException +from rdpy.base.error import InvalidExpectedDataException +import rdpy.base.log as log class MessageType(object): """ @@ -193,7 +194,7 @@ class LicPacket(CompositeType): for c in [LicensingErrorMessage, ServerLicenseRequest, ClientNewLicenseRequest]: if self.bMsgtype.value == c._MESSAGE_TYPE_: return c() - print "WARNING : unknown license message : %s"%self.bMsgtype.value + log.debug("unknown license message : %s"%self.bMsgtype.value) return String() if message is None: diff --git a/rdpy/protocol/rdp/mcs.py b/rdpy/protocol/rdp/mcs.py index fa103ac..b84f9ee 100644 --- a/rdpy/protocol/rdp/mcs.py +++ b/rdpy/protocol/rdp/mcs.py @@ -26,8 +26,9 @@ It exist channel for file system order, audio channel, clipboard etc... """ from rdpy.network.layer import LayerAutomata, StreamSender, Layer, LayerMode from rdpy.network.type import sizeof, Stream, UInt8, UInt16Le -from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize +from rdpy.base.error import InvalidExpectedDataException, InvalidValue, InvalidSize from rdpy.protocol.rdp.ber import writeLength +import rdpy.base.log as log import ber, gcc, per @@ -115,10 +116,11 @@ class MCS(LayerAutomata): return self._mcs._serverSettings - def __init__(self, mode, presentation): + def __init__(self, mode, presentation, virtualChannels = []): """ @param mode: mode of MCS layer @param presentation: presentation layer + @param virtualChannels: list additional channels like rdpsnd... [tuple(mcs.ChannelDef, layer)] """ LayerAutomata.__init__(self, mode, presentation) self._clientSettings = gcc.clientSettings() @@ -126,7 +128,13 @@ class MCS(LayerAutomata): #default user Id self._userId = 1 + Channel.MCS_USERCHANNEL_BASE #list of channel use in this layer and connection state - self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: presentation} + self._channels = {Channel.MCS_GLOBAL_CHANNEL: presentation} + #virtual channels + self._virtualChannels = virtualChannels + #nb join and confirm channel + self._nbJoinAndConfirmChannel = 0 + self._isGlobalChannelRequested = False + self._isUserChannelRequested = False #use to record already requested channel self._channelIdsRequested = {} @@ -137,7 +145,12 @@ class MCS(LayerAutomata): """ if self._mode == LayerMode.CLIENT: self._clientSettings.getBlock(gcc.MessageType.CS_CORE).serverSelectedProtocol.value = self._transport._selectedProtocol + #ask for virtual channel + self._clientSettings.getBlock(gcc.MessageType.CS_NET).channelDefArray._array = [x for (x, _) in self._virtualChannels] + #send connect initial self.sendConnectInitial() + #next wait response + self.setNextState(self.recvConnectResponse) else: self._serverSettings.getBlock(gcc.MessageType.SC_CORE).clientRequestedProtocol.value = self._transport._requestedProtocol self.setNextState(self.recvConnectInitial) @@ -147,21 +160,41 @@ class MCS(LayerAutomata): Send sendChannelJoinRequest message on next disconnect channel client automata function """ - for (channelId, layer) in self._channelIds.iteritems(): - #for each disconnect channel send a request - if not self._channelIdsRequested.has_key(channelId): - self.sendChannelJoinRequest(channelId) - self.setNextState(self.recvChannelJoinConfirm) - return - + self.setNextState(self.recvChannelJoinConfirm) + #global channel + if not self._isGlobalChannelRequested: + self.sendChannelJoinRequest(Channel.MCS_GLOBAL_CHANNEL) + self._isGlobalChannelRequested = True + return + + #user channel + if not self._isUserChannelRequested: + self.sendChannelJoinRequest(self._userId) + self._isUserChannelRequested = True + return + + #static virtual channel + if self._nbJoinAndConfirmChannel < self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelCount.value: + channelId = self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelIdArray._array[self._nbJoinAndConfirmChannel] + self._nbJoinAndConfirmChannel += 1 + self.sendChannelJoinRequest(channelId) + return + + self.allChannelConnected() + + def allChannelConnected(self): + """ + All channels are connected to MCS layer + Send connect to upper channel + And prepare MCS layer to receive data + """ #connection is done self.setNextState(self.recvData) #try connection on all requested channel - for (channelId, layer) in self._channelIds.iteritems(): - if self._channelIdsRequested[channelId] and not layer is None: - #use proxy for each channel - layer._transport = MCS.MCSProxySender(self, channelId) - layer.connect() + for (channelId, layer) in self._channels.iteritems(): + #use proxy for each channel + layer._transport = MCS.MCSProxySender(self, channelId) + layer.connect() def sendConnectInitial(self): """ @@ -178,8 +211,6 @@ class MCS(LayerAutomata): self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff), ber.writeOctetstring(ccReqStream.getvalue())) self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp)) - #we must receive a connect response - self.setNextState(self.recvConnectResponse) def sendConnectResponse(self): """ @@ -194,8 +225,6 @@ class MCS(LayerAutomata): ber.writeOctetstring(ccReqStream.getvalue())) self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_RESPONSE, sizeof(tmp)), tmp)) - self.setNextState(self.recvErectDomainRequest) - def sendErectDomainRequest(self): """ Send a formated erect domain request for RDP connection @@ -217,7 +246,7 @@ class MCS(LayerAutomata): Send attach user confirm server automata function """ - self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_CONFIRM)), + self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_CONFIRM), 2), per.writeEnumerates(0), per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE))) @@ -237,7 +266,7 @@ class MCS(LayerAutomata): @param channelId: id of channel @param confirm: connection state """ - self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_CONFIRM)), + self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_CONFIRM), 2), per.writeEnumerates(int(confirm)), per.writeInteger16(self._userId, Channel.MCS_USERCHANNEL_BASE), per.writeInteger16(channelId), @@ -276,6 +305,7 @@ class MCS(LayerAutomata): self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelIdArray._array = [UInt16Le(x + Channel.MCS_GLOBAL_CHANNEL) for x in range(1, len(self._clientSettings.getBlock(gcc.MessageType.CS_NET).channelDefArray._array) + 1)] self.sendConnectResponse() + self.setNextState(self.recvErectDomainRequest) def recvConnectResponse(self, data): """ @@ -350,10 +380,6 @@ class MCS(LayerAutomata): self._userId = per.readInteger16(data, Channel.MCS_USERCHANNEL_BASE) - #build channel list because we have user id - #add default channel + channels accepted by GCC connection sequence - self._channelIds[self._userId] = None - self.connectNextChannel() def recvChannelJoinRequest(self, data): @@ -374,7 +400,12 @@ class MCS(LayerAutomata): raise InvalidExpectedDataException("Invalid MCS User Id") channelId = per.readInteger16(data) - self.sendChannelJoinConfirm(channelId, channelId in self._channelIds.keys() or channelId == self._userId) + #TODO check if it's a virtual channel too + #actually algo support virtual channel but not RDPY + self.sendChannelJoinConfirm(channelId, channelId in self._channels.keys() or channelId == self._userId) + self._nbJoinAndConfirmChannel += 1 + if self._nbJoinAndConfirmChannel == self._serverSettings.getBlock(gcc.MessageType.SC_NET).channelCount.value + 2: + self.allChannelConnected() def recvChannelJoinConfirm(self, data): """ @@ -395,8 +426,16 @@ class MCS(LayerAutomata): raise InvalidExpectedDataException("Invalid MCS User Id") channelId = per.readInteger16(data) - #save state of channel - self._channelIdsRequested[channelId] = (confirm == 0) + #must confirm global channel and user channel + if (confirm != 0) and (channelId == Channel.MCS_GLOBAL_CHANNEL or channelId == self._userId): + raise InvalidExpectedDataException("Server must confirm static channel") + + if confirm ==0: + serverNet = self._serverSettings.getBlock(gcc.MessageType.SC_NET) + for i in range(0, serverNet.channelCount.value): + if channelId == serverNet.channelIdArray._array[i].value: + self._channels[channelId] = self._virtualChannels[i][1] + self.connectNextChannel() def recvData(self, data): @@ -408,7 +447,7 @@ class MCS(LayerAutomata): data.readType(opcode) if self.readMCSPDUHeader(opcode.value, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM): - print "INFO : MCS DISCONNECT_PROVIDER_ULTIMATUM" + log.info("MCS DISCONNECT_PROVIDER_ULTIMATUM") self._transport.close() return @@ -424,16 +463,11 @@ class MCS(LayerAutomata): per.readLength(data) #channel id doesn't match a requested layer - if not self._channelIdsRequested.has_key(channelId): - print "ERROR : receive data for an unrequested layer" + if not self._channels.has_key(channelId): + log.error("receive data for an unconnected layer") return - - #channel id math an unconnected layer - if not self._channelIdsRequested[channelId]: - print "ERROR : receive data for an unconnected layer" - return - - self._channelIds[channelId].recv(data) + + self._channels[channelId].recv(data) def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize): """ diff --git a/rdpy/protocol/rdp/pdu.py b/rdpy/protocol/rdp/pdu.py index 141d937..b2257a6 100644 --- a/rdpy/protocol/rdp/pdu.py +++ b/rdpy/protocol/rdp/pdu.py @@ -25,8 +25,8 @@ In this layer are managed all mains bitmap update orders end user inputs from rdpy.network.layer import LayerAutomata, LayerMode from rdpy.network.type import CompositeType, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType -from rdpy.network.error import InvalidExpectedDataException, CallPureVirtualFuntion, InvalidType - +from rdpy.base.error import InvalidExpectedDataException, CallPureVirtualFuntion, InvalidType +import rdpy.base.log as log import gcc, lic, caps, tpkt class SecurityFlag(object): @@ -562,7 +562,7 @@ class PDU(CompositeType): for c in [DemandActivePDU, ConfirmActivePDU, DataPDU, DeactiveAllPDU]: if self.shareControlHeader.pduType.value == c._PDUTYPE_: return c() - print "WARNING : unknown PDU type : %s"%hex(self.shareControlHeader.pduType.value) + log.debug("unknown PDU type : %s"%hex(self.shareControlHeader.pduType.value)) #read entire packet return String() @@ -643,7 +643,7 @@ class DataPDU(CompositeType): for c in [UpdateDataPDU, SynchronizeDataPDU, ControlDataPDU, ErrorInfoDataPDU, FontListDataPDU, FontMapDataPDU, PersistentListPDU, ClientInputEventPDU, ShutdownDeniedPDU, ShutdownRequestPDU]: if self.shareDataHeader.pduType2.value == c._PDUTYPE2_: return c() - print "WARNING : unknown PDU data type : %s"%hex(self.shareDataHeader.pduType2.value) + log.debug("unknown PDU data type : %s"%hex(self.shareDataHeader.pduType2.value)) return String() if pduData is None: @@ -936,7 +936,7 @@ class SlowPathInputEvent(CompositeType): for c in [PointerEvent, ScancodeKeyEvent, UnicodeKeyEvent]: if self.messageType.value == c._INPUT_MESSAGE_TYPE_: return c() - print "WARNING : unknown slow path input : %s"%hex(self.messageType.value) + log.debug("unknown slow path input : %s"%hex(self.messageType.value)) return String() if messageData is None: @@ -1219,7 +1219,7 @@ class PDULayer(LayerAutomata, tpkt.FastPathListener): if ErrorInfo._MESSAGES_.has_key(dataPDU.pduData.errorInfo): message = ErrorInfo._MESSAGES_[dataPDU.pduData.errorInfo] - print "Error INFO PDU : %s"%message + log.error("INFO PDU : %s"%message) elif dataPDU.shareDataHeader.pduType2.value == PDUType2.PDUTYPE2_SHUTDOWN_DENIED: #may be an event to ask to user self._transport.close() diff --git a/rdpy/protocol/rdp/per.py b/rdpy/protocol/rdp/per.py index f74a5dd..e9f843d 100644 --- a/rdpy/protocol/rdp/per.py +++ b/rdpy/protocol/rdp/per.py @@ -3,7 +3,7 @@ ''' from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String -from rdpy.network.error import InvalidValue, InvalidExpectedDataException +from rdpy.base.error import InvalidValue, InvalidExpectedDataException def readLength(s): ''' diff --git a/rdpy/protocol/rdp/rdp.py b/rdpy/protocol/rdp/rdp.py index 3f7b390..7f3057b 100644 --- a/rdpy/protocol/rdp/rdp.py +++ b/rdpy/protocol/rdp/rdp.py @@ -22,8 +22,9 @@ Use to manage RDP stack in twisted """ from twisted.internet import protocol -from rdpy.network.error import CallPureVirtualFuntion, InvalidValue +from rdpy.base.error import CallPureVirtualFuntion, InvalidValue from rdpy.network.layer import LayerMode +import rdpy.base.log as log import tpkt, tpdu, mcs, pdu, gcc class RDPClientController(pdu.PDUClientListener): @@ -153,7 +154,7 @@ class RDPClientController(pdu.PDUClientListener): self._pduLayer.sendInputEvents([event]) except InvalidValue: - print "try send pointer event with incorrect position" + log.info("try send pointer event with incorrect position") def sendKeyEventScancode(self, code, isPressed): """ @@ -176,7 +177,7 @@ class RDPClientController(pdu.PDUClientListener): self._pduLayer.sendInputEvents([event]) except InvalidValue: - print "try send bad key event" + log.info("try send bad key event") def sendKeyEventUnicode(self, code, isPressed): """ @@ -197,7 +198,7 @@ class RDPClientController(pdu.PDUClientListener): self._pduLayer.sendInputEvents([event]) except InvalidValue: - print "try send bad key event" + log.info("try send bad key event") def close(self): """ diff --git a/rdpy/protocol/rdp/tpdu.py b/rdpy/protocol/rdp/tpdu.py index 1673e80..7ffd9eb 100644 --- a/rdpy/protocol/rdp/tpdu.py +++ b/rdpy/protocol/rdp/tpdu.py @@ -26,7 +26,7 @@ RDP basic security is not supported by RDPY (because is not a true security laye from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender from rdpy.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof -from rdpy.network.error import InvalidExpectedDataException +from rdpy.base.error import InvalidExpectedDataException class MessageType(object): """ diff --git a/rdpy/protocol/rdp/tpkt.py b/rdpy/protocol/rdp/tpkt.py index 0cb0648..12ca336 100644 --- a/rdpy/protocol/rdp/tpkt.py +++ b/rdpy/protocol/rdp/tpkt.py @@ -24,7 +24,7 @@ Use to build correct size packet and handle slow path and fast path mode """ from rdpy.network.layer import RawLayer, LayerMode from rdpy.network.type import UInt8, UInt16Be, sizeof -from rdpy.network.error import CallPureVirtualFuntion +from rdpy.base.error import CallPureVirtualFuntion class FastPathListener(object): """ diff --git a/rdpy/protocol/rfb/rfb.py b/rdpy/protocol/rfb/rfb.py index 14097c1..faddffc 100644 --- a/rdpy/protocol/rfb/rfb.py +++ b/rdpy/protocol/rfb/rfb.py @@ -29,7 +29,7 @@ Implement Remote FrameBuffer protocol use in VNC client and server from twisted.internet import protocol from rdpy.network.layer import RawLayer, LayerMode from rdpy.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType -from rdpy.network.error import InvalidValue, CallPureVirtualFuntion, InvalidType +from rdpy.base.error import InvalidValue, CallPureVirtualFuntion, InvalidType class ProtocolVersion(object): """ diff --git a/rdpy/tests/protocol/__init__.py b/rdpy/tests/protocol/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/rdpy/tests/protocol/rfb/__init__.py b/rdpy/tests/protocol/rfb/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/rdpy/ui/qt4.py b/rdpy/ui/qt4.py index 5207eb6..908e518 100644 --- a/rdpy/ui/qt4.py +++ b/rdpy/ui/qt4.py @@ -26,8 +26,14 @@ QRemoteDesktop is a widget use for render in rdpy from PyQt4 import QtGui, QtCore from rdpy.protocol.rfb.rfb import RFBClientObserver from rdpy.protocol.rdp.rdp import RDPClientObserver -from rdpy.network.error import CallPureVirtualFuntion -import rle +from rdpy.base.error import CallPureVirtualFuntion + +import rdpy.base.log as log + +try: + import rdpy.core.rle as rle +except: + log.error("Please build core package before using RLE algorithm : scons -C rdpy/core install") class QAdaptor(object): @@ -97,7 +103,7 @@ class RFBClientQt(RFBClientObserver, QAdaptor): if pixelFormat.BitsPerPixel.value == 32 and pixelFormat.RedShift.value == 16: imageFormat = QtGui.QImage.Format_RGB32 else: - print "Receive image in bad format" + log.error("Receive image in bad format") return image = QtGui.QImage(data, width, height, imageFormat) @@ -218,7 +224,7 @@ class RDPClientQt(RDPClientObserver, QAdaptor): else: image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB32) else: - print "Receive image in bad format" + log.error("Receive image in bad format") return #if image need to be cut @@ -290,8 +296,6 @@ class QRemoteDesktop(QtGui.QWidget): Call when mouse move @param event: QMouseEvent """ - if self._adaptor is None: - print "No adaptor to send mouse move event" self._adaptor.sendMouseEvent(event, False) def mousePressEvent(self, event): diff --git a/rdpy/tests/network/const.py b/tests/const.py similarity index 83% rename from rdpy/tests/network/const.py rename to tests/const.py index e5d99ae..46c2339 100644 --- a/rdpy/tests/network/const.py +++ b/tests/const.py @@ -2,19 +2,19 @@ @author: sylvain ''' import unittest -import rdpy.network.const +import rdpy.base.const import rdpy.network.type class ConstCase(unittest.TestCase): ''' represent test case for all classes and function - present in rdpy.network.const + present in rdpy.base.const ''' def test_type_attributes(self): ''' test if type attributes decorator works ''' - @rdpy.network.const.TypeAttributes(rdpy.network.type.UInt16Le) + @rdpy.base.const.TypeAttributes(rdpy.network.type.UInt16Le) class Test: MEMBER_1 = 1 MEMBER_2 = 2 @@ -26,7 +26,7 @@ class ConstCase(unittest.TestCase): ''' test if get on const class member generate new object each ''' - @rdpy.network.const.ConstAttributes + @rdpy.base.const.ConstAttributes class Test: MEMBER_1 = 1 MEMBER_2 = 2 diff --git a/rdpy/tests/network/layer.py b/tests/layer.py similarity index 80% rename from rdpy/tests/network/layer.py rename to tests/layer.py index bfa35da..0f67cf2 100644 --- a/rdpy/tests/network/layer.py +++ b/tests/layer.py @@ -26,17 +26,6 @@ class LayerCase(unittest.TestCase): self.assertRaises(LayerCase.LayerCaseException, rdpy.network.layer.Layer(presentation = TestConnect()).connect) - def test_layer_receive_event(self): - ''' - test if recv event is send from transport to presentation - ''' - class TestConnect(rdpy.network.layer.Layer): - def recv(self, s): - if s == "message": - raise LayerCase.LayerCaseException() - - self.assertRaises(LayerCase.LayerCaseException, rdpy.network.layer.Layer(presentation = TestConnect()).recv, "message") - def test_layer_automata_more_than_expected(self): ''' test layer automata mechanism if data received is more than expected diff --git a/rdpy/tests/protocol/rfb/rfb.py b/tests/rfb.py similarity index 100% rename from rdpy/tests/protocol/rfb/rfb.py rename to tests/rfb.py diff --git a/rdpy/tests/network/type.py b/tests/type.py similarity index 93% rename from rdpy/tests/network/type.py rename to tests/type.py index 6fecfcb..083eab5 100644 --- a/rdpy/tests/network/type.py +++ b/tests/type.py @@ -331,20 +331,4 @@ class TypeCase(unittest.TestCase): except Exception: self.assertEqual(s.readLen(), 0, "invalid stream roll back operation") return - self.assertTrue(False, "Constant constraint fail") - - def test_stream_composite_type_force_read_length_optional(self): - ''' - test where type have readLen forced and have optional subtype which have - length greater than last subtype of composite type - ''' - class TestType(rdpy.network.type.CompositeType): - def __init__(self, readLen = None): - rdpy.network.type.CompositeType.__init__(self, readLen = readLen) - self.t1 = rdpy.network.type.UInt32Le(0, optional = True) - self.t2 = rdpy.network.type.UInt16Le(0, optional = True) - - s = rdpy.network.type.Stream("\x00\x00\x00\x00\x00\x00\x00") - t = TestType(readLen = rdpy.network.type.UInt8(2)) - s.readType(t) - self.assertTrue(not t.t1._is_readed and t.t2._is_readed, "Invalid optional reading when length is forced") \ No newline at end of file + self.assertTrue(False, "Constant constraint fail") \ No newline at end of file