code refactoring + integrate rdesktop code for bitmap decompression
This commit is contained in:
@@ -53,7 +53,7 @@ class RDPClientQtFactory(rdp.ClientFactory):
|
||||
#create qt widget
|
||||
self._w = client.getWidget()
|
||||
self._w.resize(self._width, self._height)
|
||||
self._w.setWindowTitle('rdpyclient-rdp')
|
||||
self._w.setWindowTitle('rdpy-rdpclient')
|
||||
self._w.show()
|
||||
return client
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class RFBClientQtFactory(rfb.ClientFactory):
|
||||
#create qt widget
|
||||
self._w = client.getWidget()
|
||||
self._w.resize(1024, 800)
|
||||
self._w.setWindowTitle('rdpyclient-vnc')
|
||||
self._w.setWindowTitle('rdpy-vncclient')
|
||||
self._w.show()
|
||||
return client
|
||||
|
||||
|
||||
@@ -4,6 +4,5 @@
|
||||
#include "../../src/rle/rle.h"
|
||||
%End
|
||||
|
||||
int rle_decode_uint8(void* output, int width, int height, char* input, int size);
|
||||
int rle_decode_uint16(void* output, int width, int height, char* input, int size);
|
||||
int rle_decode_uint24(void* output, int width, int height, char* input, int size);
|
||||
int bitmap_decompress(void * output, int width, int height, char * input, int size, int Bpp);
|
||||
|
||||
|
||||
1372
lib/src/rle/rle.c
1372
lib/src/rle/rle.c
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,6 @@
|
||||
#ifndef _RLE_H_
|
||||
#define _RLE_H_
|
||||
|
||||
|
||||
int rle_decode_uint8(char* output, int width, int height, char* input, int size);
|
||||
int rle_decode_uint16(char* output, int width, int height, char* input, int size);
|
||||
int rle_decode_uint24(char* output, int width, int height, char* input, int size);
|
||||
int bitmap_decompress(char * output, int width, int height, char * input, int size, int Bpp);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef _RLE_M_H_
|
||||
#define _RLE_M_H_
|
||||
|
||||
#include "rle.h"
|
||||
|
||||
#define CVAL(p) ((unsigned char)(*(p++)))
|
||||
|
||||
#if defined(B_ENDIAN)
|
||||
#define EIK0 1
|
||||
#define EIK1 0
|
||||
#else
|
||||
#define EIK0 0
|
||||
#define EIK1 1
|
||||
#endif
|
||||
|
||||
#define REPEAT(statement) \
|
||||
{ \
|
||||
while ((count > 0) && (x < width)) \
|
||||
{ \
|
||||
statement; \
|
||||
count--; \
|
||||
x++; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MASK_UPDATE \
|
||||
{ \
|
||||
mixmask <<= 1; \
|
||||
if ((mixmask & 0xff) == 0) \
|
||||
{ \
|
||||
mask = fom_mask ? fom_mask : CVAL(input); \
|
||||
mixmask = 1; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
@@ -28,17 +28,15 @@ import struct
|
||||
from copy import deepcopy
|
||||
from StringIO import StringIO
|
||||
from error import InvalidValue
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidSize
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidSize, CallPureVirtualFuntion
|
||||
|
||||
def sizeof(element):
|
||||
'''
|
||||
byte size of type
|
||||
sum sizeof of tuple element
|
||||
and count only element that condition
|
||||
is true at sizeof call
|
||||
"""
|
||||
Byte size of type sum sizeof of tuple element
|
||||
And count only element that condition is true at sizeof call
|
||||
@param element: Type or Tuple(Type | Tuple,)
|
||||
@return: size of element in byte
|
||||
'''
|
||||
"""
|
||||
if isinstance(element, tuple) or isinstance(element, list):
|
||||
size = 0
|
||||
for i in element:
|
||||
@@ -50,18 +48,16 @@ def sizeof(element):
|
||||
|
||||
|
||||
class Type(object):
|
||||
'''
|
||||
root type object inheritance
|
||||
record conditional optional of constant
|
||||
mechanism
|
||||
'''
|
||||
"""
|
||||
Root type object inheritance
|
||||
Record conditional optional of constant mechanism
|
||||
"""
|
||||
def __init__(self, conditional = lambda:True, optional = False, constant = False):
|
||||
'''
|
||||
constructor of any type object
|
||||
"""
|
||||
@param conditional : function call before read or write type
|
||||
@param optional: boolean check before read if there is still data in stream
|
||||
@param constant: if true check any changement of object during reading
|
||||
'''
|
||||
@param constant: if true check any modification of object during reading
|
||||
"""
|
||||
self._conditional = conditional
|
||||
self._optional = optional
|
||||
self._constant = constant
|
||||
@@ -73,22 +69,22 @@ class Type(object):
|
||||
self._is_writed = False
|
||||
|
||||
def write(self, s):
|
||||
'''
|
||||
write type into stream if conditional is true
|
||||
and call private
|
||||
"""
|
||||
Write type into stream if conditional is true
|
||||
Call virtual __write__ method
|
||||
@param s: Stream which will be written
|
||||
'''
|
||||
"""
|
||||
self._is_writed = self._conditional()
|
||||
if not self._is_writed:
|
||||
return
|
||||
self.__write__(s)
|
||||
|
||||
def read(self, s):
|
||||
'''
|
||||
read type from stream s if conditional
|
||||
is true and check constantness
|
||||
"""
|
||||
Read type from stream s if conditional is true
|
||||
Check constantness
|
||||
@param s: Stream
|
||||
'''
|
||||
"""
|
||||
self._is_readed = self._conditional()
|
||||
if not self._is_readed:
|
||||
return
|
||||
@@ -108,56 +104,54 @@ class Type(object):
|
||||
raise InvalidExpectedDataException("%s const value expected %s != %s"%(self.__class__, old.value, self.value))
|
||||
|
||||
def __read__(self, s):
|
||||
'''
|
||||
interface definition of private read funtion
|
||||
"""
|
||||
Interface definition of private read function
|
||||
@param s: Stream
|
||||
'''
|
||||
pass
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__read__", "Type"))
|
||||
|
||||
def __write__(self, s):
|
||||
'''
|
||||
interface definition of private write funtion
|
||||
"""
|
||||
Interface definition of private write function
|
||||
@param s: Stream
|
||||
'''
|
||||
pass
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__write__", "Type"))
|
||||
|
||||
def __sizeof__(self):
|
||||
'''
|
||||
return size of type use for sizeof function
|
||||
"""
|
||||
Return size of type use for sizeof function
|
||||
@return: size in byte of type
|
||||
'''
|
||||
pass
|
||||
"""
|
||||
raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "__sizeof__", "Type"))
|
||||
|
||||
class CallableValue(object):
|
||||
'''
|
||||
wrap access of callable value.
|
||||
"""
|
||||
Wrap access of callable value.
|
||||
When use getter value is call.
|
||||
Constant value can also be wrap
|
||||
and will be transformed into callable value(lambda function)
|
||||
'''
|
||||
Constant value can also be wrap and will be transformed into callable value(lambda function)
|
||||
"""
|
||||
def __init__(self, value):
|
||||
'''
|
||||
construtor
|
||||
"""
|
||||
@param value: value will be wrapped (constant | lambda | function)
|
||||
'''
|
||||
"""
|
||||
self._value = None
|
||||
self.value = value
|
||||
|
||||
def __getValue__(self):
|
||||
'''
|
||||
can be overwritten to add specific check before
|
||||
"""
|
||||
Can be overwritten to add specific check before
|
||||
self.value is call
|
||||
@return: result of callbale value
|
||||
'''
|
||||
@return: result of callable value
|
||||
"""
|
||||
return self._value()
|
||||
|
||||
def __setValue__(self, value):
|
||||
'''
|
||||
can be overwritten to add specific check before
|
||||
"""
|
||||
Can be overwritten to add specific check before
|
||||
self.value = value is call
|
||||
check if value is callable and if not transform it
|
||||
Check if value is callable and if not transform it
|
||||
@param value: new value wrapped if constant -> lambda function
|
||||
'''
|
||||
"""
|
||||
value_callable = lambda:value
|
||||
if callable(value):
|
||||
value_callable = value
|
||||
@@ -166,37 +160,34 @@ class CallableValue(object):
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
'''
|
||||
shortcut to access inner value
|
||||
main getter of value
|
||||
"""
|
||||
Shortcut to access inner value main getter of value
|
||||
@return: result of callable value
|
||||
'''
|
||||
"""
|
||||
return self.__getValue__()
|
||||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
'''
|
||||
setter of value after check it
|
||||
main setter of value
|
||||
@param value: new value encompass in valuetype object
|
||||
'''
|
||||
"""
|
||||
Setter of value after check it main setter of value
|
||||
@param value: new value encompass in value type object
|
||||
"""
|
||||
self.__setValue__(value)
|
||||
|
||||
class SimpleType(Type, CallableValue):
|
||||
'''
|
||||
simple type
|
||||
'''
|
||||
"""
|
||||
Simple type
|
||||
"""
|
||||
def __init__(self, structFormat, typeSize, signed, value, conditional = lambda:True, optional = False, constant = False):
|
||||
'''
|
||||
constructor of simple type
|
||||
"""
|
||||
@param structFormat: letter that represent type in struct package
|
||||
@param typeSize: size in byte of type
|
||||
@param signed: true if type represent a signed type
|
||||
@param value: value recorded in this object (can be callable value which be call when is acces usefull with closure)
|
||||
@param value: value recorded in this object (can be callable value which be call when is access useful with closure)
|
||||
@param conditional : function call before read or write type
|
||||
@param optional: boolean check before read if there is still data in stream
|
||||
@param constant: if true check any changement of object during reading
|
||||
'''
|
||||
@param constant: if true check any modification of object during reading
|
||||
"""
|
||||
self._signed = signed
|
||||
self._typeSize = typeSize
|
||||
self._structFormat = structFormat
|
||||
@@ -204,13 +195,12 @@ class SimpleType(Type, CallableValue):
|
||||
CallableValue.__init__(self, value)
|
||||
|
||||
def __getValue__(self):
|
||||
'''
|
||||
CallableValue overwrite
|
||||
check mask type of value
|
||||
"""
|
||||
CallableValue overwrite check mask type of value
|
||||
use CallableValue access
|
||||
@return: python value wrap into type
|
||||
@return: Python value wrap into type
|
||||
@raise InvalidValue: if value doesn't respect type range
|
||||
'''
|
||||
"""
|
||||
value = CallableValue.__getValue__(self)
|
||||
if not self.isInRange(value):
|
||||
raise InvalidValue("value is out of range for %s"%self.__class__)
|
||||
@@ -221,12 +211,12 @@ class SimpleType(Type, CallableValue):
|
||||
return value & self.mask()
|
||||
|
||||
def __setValue__(self, value):
|
||||
'''
|
||||
"""
|
||||
CallableValue overwrite
|
||||
check mask type of value
|
||||
@param value: new value encompass in object (respect python type | lambda | function)
|
||||
Check mask type of value
|
||||
@param value: new value encompass in object (respect Python type | lambda | function)
|
||||
@raise InvalidValue: if value doesn't respect type range
|
||||
'''
|
||||
"""
|
||||
#check static value range
|
||||
if not callable(value) and not self.isInRange(value):
|
||||
raise InvalidValue("value is out of range for %s"%self.__class__)
|
||||
@@ -235,40 +225,40 @@ class SimpleType(Type, CallableValue):
|
||||
|
||||
|
||||
def __cmp__(self, other):
|
||||
'''
|
||||
compare inner value
|
||||
magic function of python use for any compare operators
|
||||
"""
|
||||
Compare inner value
|
||||
Magic function of Python use for any compare operators
|
||||
@param other: SimpleType value which will be compared with self value
|
||||
or try to construct same type as self around other value
|
||||
@return: python value compare
|
||||
'''
|
||||
@return: Python value compare
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.value.__cmp__(other.value)
|
||||
|
||||
def __write__(self, s):
|
||||
'''
|
||||
write value in stream s
|
||||
use struct package to pack value
|
||||
"""
|
||||
Write value in stream s
|
||||
Use Struct package to pack value
|
||||
@param s: Stream which will be written
|
||||
'''
|
||||
"""
|
||||
s.write(struct.pack(self._structFormat, self.value))
|
||||
|
||||
def __read__(self, s):
|
||||
'''
|
||||
read inner value from stream
|
||||
use struct package
|
||||
"""
|
||||
Read inner value from stream
|
||||
Use struct package
|
||||
@param s: Stream
|
||||
'''
|
||||
"""
|
||||
if s.dataLen() < self._typeSize:
|
||||
raise InvalidSize("Stream is too small to read expected data")
|
||||
self.value = struct.unpack(self._structFormat, s.read(self._typeSize))[0]
|
||||
|
||||
def mask(self):
|
||||
'''
|
||||
compute bit mask for type
|
||||
because in python all numbers are int long or float
|
||||
'''
|
||||
"""
|
||||
Compute bit mask for type
|
||||
Because in Python all numbers are Int long or float
|
||||
"""
|
||||
if not self.__dict__.has_key("_mask"):
|
||||
mask = 0xff
|
||||
for i in range(1, self._typeSize):
|
||||
@@ -277,106 +267,106 @@ class SimpleType(Type, CallableValue):
|
||||
return self._mask
|
||||
|
||||
def isInRange(self, value):
|
||||
'''
|
||||
check if value is in mask range
|
||||
@param value: python value
|
||||
"""
|
||||
Check if value is in mask range
|
||||
@param value: Python value
|
||||
@return: true if value is in type range
|
||||
'''
|
||||
"""
|
||||
if self._signed:
|
||||
return not (value < -(self.mask() >> 1) or value > (self.mask() >> 1))
|
||||
else:
|
||||
return not (value < 0 or value > self.mask())
|
||||
|
||||
def __sizeof__(self):
|
||||
'''
|
||||
return size of type
|
||||
"""
|
||||
Return size of type
|
||||
@return: typeSize pass in constructor
|
||||
'''
|
||||
"""
|
||||
return self._typeSize
|
||||
|
||||
def __invert__(self):
|
||||
'''
|
||||
implement not operator
|
||||
"""
|
||||
Implement not operator
|
||||
@return: __class__ value
|
||||
'''
|
||||
"""
|
||||
invert = ~self.value
|
||||
if not self._signed:
|
||||
invert &= self.mask()
|
||||
return self.__class__(invert)
|
||||
|
||||
def __add__(self, other):
|
||||
'''
|
||||
implement addition operator
|
||||
"""
|
||||
Implement addition operator
|
||||
@param other: SimpleType value or try to construct same type as self
|
||||
around other value
|
||||
@return: self.__class__ object with add result
|
||||
@raise InvalidValue: if new value is out of bound
|
||||
'''
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.__class__(self.value.__add__(other.value))
|
||||
|
||||
def __sub__(self, other):
|
||||
'''
|
||||
implement sub operator
|
||||
"""
|
||||
Implement sub operator
|
||||
@param other: SimpleType value or try to construct same type as self
|
||||
around other value
|
||||
@return: self.__class__ object with sub result
|
||||
@raise InvalidValue: if new value is out of bound
|
||||
'''
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.__class__(self.value.__sub__(other.value))
|
||||
|
||||
def __and__(self, other):
|
||||
'''
|
||||
implement bitwise and operator
|
||||
"""
|
||||
Implement bitwise and operator
|
||||
@param other: SimpleType value or try to construct same type as self
|
||||
around other value
|
||||
@return: self.__class__ object with and result
|
||||
'''
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.__class__(self.value.__and__(other.value))
|
||||
|
||||
def __or__(self, other):
|
||||
'''
|
||||
"""
|
||||
implement bitwise or operator
|
||||
@param other: SimpleType value or try to construct same type as self
|
||||
around other value
|
||||
@return: self.__class__ object with or result
|
||||
'''
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.__class__(self.value.__or__(other.value))
|
||||
|
||||
def __xor__(self, other):
|
||||
'''
|
||||
implement bitwise xor operator
|
||||
"""
|
||||
Implement bitwise xor operator
|
||||
@param other: SimpleType value or try to construct same type as self
|
||||
around other value
|
||||
@return: self.__class__ object with or result
|
||||
'''
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.__class__(self.value.__xor__(other.value))
|
||||
|
||||
def __lshift__(self, other):
|
||||
'''
|
||||
left shift operator
|
||||
@param other: python int
|
||||
"""
|
||||
Left shift operator
|
||||
@param other: Python Int
|
||||
@return: self.__class__ object with or result
|
||||
'''
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.__class__(self.value.__lshift__(other.value))
|
||||
|
||||
def __rshift__(self, other):
|
||||
'''
|
||||
left shift operator
|
||||
"""
|
||||
Left shift operator
|
||||
@param other: python int
|
||||
@return: self.__class__ object with or result
|
||||
'''
|
||||
"""
|
||||
if not isinstance(other, SimpleType):
|
||||
other = self.__class__(other)
|
||||
return self.__class__(self.value.__rshift__(other.value))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'''
|
||||
@author sylvain
|
||||
@summary gcc language
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240510.aspx
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240508.aspx
|
||||
'''
|
||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.network.type import UInt8, UInt16Le, UInt32Le, CompositeType, String, UniString, Stream, sizeof
|
||||
|
||||
@@ -18,14 +18,12 @@
|
||||
#
|
||||
|
||||
"""
|
||||
Implement Multi Channel Service
|
||||
Implement Multi-Channel Service
|
||||
|
||||
Each channel have a particular role.
|
||||
The main channel is the graphical channel.
|
||||
It exist channel for file system order, audio channel, clipboard etc...
|
||||
"""
|
||||
|
||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender
|
||||
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
@@ -33,8 +31,6 @@ from rdpy.protocol.rdp.ber import writeLength
|
||||
|
||||
import ber, gcc, per
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class Message(object):
|
||||
"""
|
||||
Message type
|
||||
@@ -42,8 +38,6 @@ class Message(object):
|
||||
MCS_TYPE_CONNECT_INITIAL = 0x65
|
||||
MCS_TYPE_CONNECT_RESPONSE = 0x66
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class DomainMCSPDU:
|
||||
"""
|
||||
Domain MCS PDU header
|
||||
@@ -57,8 +51,6 @@ class DomainMCSPDU:
|
||||
SEND_DATA_REQUEST = 25
|
||||
SEND_DATA_INDICATION = 26
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Be)
|
||||
class Channel:
|
||||
"""
|
||||
Channel id of main channels use in RDP
|
||||
@@ -126,7 +118,7 @@ class MCS(LayerAutomata):
|
||||
self._clientSettings = gcc.ClientSettings()
|
||||
self._serverSettings = gcc.ServerSettings()
|
||||
#default user Id
|
||||
self._userId = UInt16Be(1)
|
||||
self._userId = 1
|
||||
#list of channel use in this layer and connection state
|
||||
self._channelIds = {Channel.MCS_GLOBAL_CHANNEL: presentation}
|
||||
#use to record already requested channel
|
||||
@@ -137,7 +129,7 @@ class MCS(LayerAutomata):
|
||||
Connection send for client mode
|
||||
a write connect initial packet
|
||||
"""
|
||||
self._clientSettings.core.serverSelectedProtocol = self._transport._selectedProtocol
|
||||
self._clientSettings.core.serverSelectedProtocol.value = self._transport._selectedProtocol
|
||||
self.sendConnectInitial()
|
||||
|
||||
def connectNextChannel(self):
|
||||
@@ -173,7 +165,7 @@ class MCS(LayerAutomata):
|
||||
self.writeDomainParams(1, 1, 1, 0x420),
|
||||
self.writeDomainParams(0xffff, 0xfc17, 0xffff, 0xffff),
|
||||
ber.writeOctetstring(ccReqStream.getvalue()))
|
||||
self._transport.send((ber.writeApplicationTag(Message.MCS_TYPE_CONNECT_INITIAL, sizeof(tmp)), tmp))
|
||||
self._transport.send((ber.writeApplicationTag(UInt8(Message.MCS_TYPE_CONNECT_INITIAL), sizeof(tmp)), tmp))
|
||||
#we must receive a connect response
|
||||
self.setNextState(self.recvConnectResponse)
|
||||
|
||||
@@ -181,26 +173,26 @@ class MCS(LayerAutomata):
|
||||
"""
|
||||
Send a formated erect domain request for RDP connection
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.ERECT_DOMAIN_REQUEST), per.writeInteger(0), per.writeInteger(0)))
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ERECT_DOMAIN_REQUEST)), per.writeInteger(0), per.writeInteger(0)))
|
||||
|
||||
def sendAttachUserRequest(self):
|
||||
"""
|
||||
Send a formated attach user request for RDP connection
|
||||
"""
|
||||
self._transport.send(self.writeMCSPDUHeader(DomainMCSPDU.ATTACH_USER_REQUEST))
|
||||
self._transport.send(self.writeMCSPDUHeader(UInt8(DomainMCSPDU.ATTACH_USER_REQUEST)))
|
||||
|
||||
def sendChannelJoinRequest(self, channelId):
|
||||
"""
|
||||
Send a formated Channel join request from client to server
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.CHANNEL_JOIN_REQUEST), self._userId, channelId))
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.CHANNEL_JOIN_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId)))
|
||||
|
||||
def recvConnectResponse(self, data):
|
||||
"""
|
||||
receive MCS connect response from server
|
||||
@param data: Stream
|
||||
"""
|
||||
ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE)
|
||||
ber.readApplicationTag(data, UInt8(Message.MCS_TYPE_CONNECT_RESPONSE))
|
||||
ber.readEnumerated(data)
|
||||
ber.readInteger(data)
|
||||
self.readDomainParams(data)
|
||||
@@ -225,13 +217,15 @@ class MCS(LayerAutomata):
|
||||
"""
|
||||
opcode = UInt8()
|
||||
confirm = UInt8()
|
||||
userId = UInt16Be()
|
||||
data.readType((opcode, confirm))
|
||||
if not self.readMCSPDUHeader(opcode, DomainMCSPDU.ATTACH_USER_CONFIRM):
|
||||
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.ATTACH_USER_CONFIRM):
|
||||
raise InvalidExpectedDataException("invalid MCS PDU")
|
||||
if confirm != 0:
|
||||
raise Exception("server reject user")
|
||||
if opcode & UInt8(2) == UInt8(2):
|
||||
data.readType(self._userId)
|
||||
data.readType(userId)
|
||||
self._userId = userId.value
|
||||
|
||||
#build channel list because we have user id
|
||||
#add default channel + channels accepted by gcc connection sequence
|
||||
@@ -247,7 +241,7 @@ class MCS(LayerAutomata):
|
||||
opcode = UInt8()
|
||||
confirm = UInt8()
|
||||
data.readType((opcode, confirm))
|
||||
if not self.readMCSPDUHeader(opcode, DomainMCSPDU.CHANNEL_JOIN_CONFIRM):
|
||||
if not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.CHANNEL_JOIN_CONFIRM):
|
||||
raise InvalidExpectedDataException("invalid MCS PDU")
|
||||
userId = UInt16Be()
|
||||
channelId = UInt16Be()
|
||||
@@ -269,11 +263,11 @@ class MCS(LayerAutomata):
|
||||
opcode = UInt8()
|
||||
data.readType(opcode)
|
||||
|
||||
if self.readMCSPDUHeader(opcode, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM):
|
||||
if self.readMCSPDUHeader(opcode.value, DomainMCSPDU.DISCONNECT_PROVIDER_ULTIMATUM):
|
||||
print "receive DISCONNECT_PROVIDER_ULTIMATUM"
|
||||
self.close()
|
||||
|
||||
elif not self.readMCSPDUHeader(opcode, DomainMCSPDU.SEND_DATA_INDICATION):
|
||||
elif not self.readMCSPDUHeader(opcode.value, DomainMCSPDU.SEND_DATA_INDICATION):
|
||||
raise InvalidExpectedDataException("invalid expected mcs opcode")
|
||||
|
||||
userId = UInt16Be()
|
||||
@@ -306,7 +300,7 @@ class MCS(LayerAutomata):
|
||||
@param channelId: Channel use to send
|
||||
@param data: message to send
|
||||
"""
|
||||
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.SEND_DATA_REQUEST), self._userId, channelId, UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data))
|
||||
self._transport.send((self.writeMCSPDUHeader(UInt8(DomainMCSPDU.SEND_DATA_REQUEST)), UInt16Be(self._userId), UInt16Be(channelId), UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data))
|
||||
|
||||
|
||||
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
|
||||
@@ -336,7 +330,7 @@ class MCS(LayerAutomata):
|
||||
def readMCSPDUHeader(self, opcode, mcsPdu):
|
||||
"""
|
||||
Read mcsPdu header and return options parameter
|
||||
@param opcode: UInt8 opcode
|
||||
@param opcode: opcode
|
||||
@param mcsPdu: mcsPdu will be checked
|
||||
@return: true if opcode is correct
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
'''
|
||||
@author: citronneur
|
||||
'''
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Implement the main graphic layer
|
||||
|
||||
In this layer are managed all mains bitmap update orders end user inputs
|
||||
"""
|
||||
|
||||
from rdpy.network.layer import LayerAutomata
|
||||
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
|
||||
@@ -12,18 +33,18 @@ import gcc, lic, caps
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class SecurityFlag(object):
|
||||
'''
|
||||
microsoft security flags
|
||||
'''
|
||||
"""
|
||||
Microsoft security flags
|
||||
"""
|
||||
SEC_INFO_PKT = 0x0040
|
||||
SEC_LICENSE_PKT = 0x0080
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
class InfoFlag(object):
|
||||
'''
|
||||
client capabilities informations
|
||||
'''
|
||||
"""
|
||||
Client capabilities informations
|
||||
"""
|
||||
INFO_MOUSE = 0x00000001
|
||||
INFO_DISABLECTRLALTDEL = 0x00000002
|
||||
INFO_AUTOLOGON = 0x00000008
|
||||
@@ -47,9 +68,9 @@ class InfoFlag(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
class PerfFlag(object):
|
||||
'''
|
||||
network performances flag
|
||||
'''
|
||||
"""
|
||||
Network performances flag
|
||||
"""
|
||||
PERF_DISABLE_WALLPAPER = 0x00000001
|
||||
PERF_DISABLE_FULLWINDOWDRAG = 0x00000002
|
||||
PERF_DISABLE_MENUANIMATIONS = 0x00000004
|
||||
@@ -62,16 +83,19 @@ class PerfFlag(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class AfInet(object):
|
||||
"""
|
||||
IPv4 or IPv6 adress style
|
||||
"""
|
||||
AF_INET = 0x00002
|
||||
AF_INET6 = 0x0017
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class PDUType(object):
|
||||
'''
|
||||
data pdu type primary index
|
||||
"""
|
||||
Data PDU type primary index
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240576.aspx
|
||||
'''
|
||||
"""
|
||||
PDUTYPE_DEMANDACTIVEPDU = 0x11
|
||||
PDUTYPE_CONFIRMACTIVEPDU = 0x13
|
||||
PDUTYPE_DEACTIVATEALLPDU = 0x16
|
||||
@@ -81,10 +105,10 @@ class PDUType(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class PDUType2(object):
|
||||
'''
|
||||
data pdu type secondary index
|
||||
"""
|
||||
Data PDU type secondary index
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
||||
'''
|
||||
"""
|
||||
PDUTYPE2_UPDATE = 0x02
|
||||
PDUTYPE2_CONTROL = 0x14
|
||||
PDUTYPE2_POINTER = 0x1B
|
||||
@@ -113,10 +137,10 @@ class PDUType2(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class StreamId(object):
|
||||
'''
|
||||
stream priority
|
||||
"""
|
||||
Stream priority
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
||||
'''
|
||||
"""
|
||||
STREAM_UNDEFINED = 0x00
|
||||
STREAM_LOW = 0x01
|
||||
STREAM_MED = 0x02
|
||||
@@ -125,10 +149,10 @@ class StreamId(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class CompressionOrder(object):
|
||||
'''
|
||||
pdu compression order
|
||||
"""
|
||||
PDU compression order
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
||||
'''
|
||||
"""
|
||||
CompressionTypeMask = 0x0F
|
||||
PACKET_COMPRESSED = 0x20
|
||||
PACKET_AT_FRONT = 0x40
|
||||
@@ -137,10 +161,10 @@ class CompressionOrder(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class CompressionType(object):
|
||||
'''
|
||||
pdu compression type
|
||||
"""
|
||||
PDU compression type
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
||||
'''
|
||||
"""
|
||||
PACKET_COMPR_TYPE_8K = 0x0
|
||||
PACKET_COMPR_TYPE_64K = 0x1
|
||||
PACKET_COMPR_TYPE_RDP6 = 0x2
|
||||
@@ -149,10 +173,10 @@ class CompressionType(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class Action(object):
|
||||
'''
|
||||
"""
|
||||
Action flag use in Control PDU packet
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240492.aspx
|
||||
'''
|
||||
"""
|
||||
CTRLACTION_REQUEST_CONTROL = 0x0001
|
||||
CTRLACTION_GRANTED_CONTROL = 0x0002
|
||||
CTRLACTION_DETACH = 0x0003
|
||||
@@ -161,30 +185,30 @@ class Action(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class PersistentKeyListFlag(object):
|
||||
'''
|
||||
use to determine the number of persistent key packet
|
||||
"""
|
||||
Use to determine the number of persistent key packet
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240495.aspx
|
||||
'''
|
||||
"""
|
||||
PERSIST_FIRST_PDU = 0x01
|
||||
PERSIST_LAST_PDU = 0x02
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class BitmapFlag(object):
|
||||
'''
|
||||
use in bitmap update PDU
|
||||
"""
|
||||
Use in bitmap update PDU
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240612.aspx
|
||||
'''
|
||||
"""
|
||||
BITMAP_COMPRESSION = 0x0001
|
||||
NO_BITMAP_COMPRESSION_HDR = 0x0400
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
class UpdateType(object):
|
||||
'''
|
||||
use in update pdu to determine which type of update
|
||||
"""
|
||||
Use in update PDU to determine which type of update
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240608.aspx
|
||||
'''
|
||||
"""
|
||||
UPDATETYPE_ORDERS = 0x0000
|
||||
UPDATETYPE_BITMAP = 0x0001
|
||||
UPDATETYPE_PALETTE = 0x0002
|
||||
@@ -193,10 +217,10 @@ class UpdateType(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
class ErrorInfo(object):
|
||||
'''
|
||||
Error code use in Error info pdu
|
||||
"""
|
||||
Error code use in Error info PDU
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240544.aspx
|
||||
'''
|
||||
"""
|
||||
ERRINFO_RPC_INITIATED_DISCONNECT = 0x00000001
|
||||
ERRINFO_RPC_INITIATED_LOGOFF = 0x00000002
|
||||
ERRINFO_IDLE_TIMEOUT = 0x00000003
|
||||
@@ -404,11 +428,11 @@ class ErrorInfo(object):
|
||||
}
|
||||
|
||||
class RDPInfo(CompositeType):
|
||||
'''
|
||||
client informations
|
||||
contains credentials (very important packet)
|
||||
"""
|
||||
Client informations
|
||||
Contains credentials (very important packet)
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240475.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, extendedInfoConditional):
|
||||
CompositeType.__init__(self)
|
||||
#code page
|
||||
@@ -431,10 +455,10 @@ class RDPInfo(CompositeType):
|
||||
self.extendedInfo = RDPExtendedInfo(conditional = extendedInfoConditional)
|
||||
|
||||
class RDPExtendedInfo(CompositeType):
|
||||
'''
|
||||
add more client informations
|
||||
use for performance flag!!!
|
||||
'''
|
||||
"""
|
||||
Add more client informations
|
||||
Use for performance flag!!!
|
||||
"""
|
||||
def __init__(self, conditional):
|
||||
CompositeType.__init__(self, conditional = conditional)
|
||||
self.clientAddressFamily = AfInet.AF_INET
|
||||
@@ -446,10 +470,10 @@ class RDPExtendedInfo(CompositeType):
|
||||
#self.performanceFlags = PerfFlag.PERF_DISABLE_WALLPAPER | PerfFlag.PERF_DISABLE_MENUANIMATIONS | PerfFlag.PERF_DISABLE_CURSOR_SHADOW
|
||||
|
||||
class ShareControlHeader(CompositeType):
|
||||
'''
|
||||
"""
|
||||
PDU share control header
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240576.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, totalLength, pduType, userId):
|
||||
'''
|
||||
constructor
|
||||
@@ -462,10 +486,10 @@ class ShareControlHeader(CompositeType):
|
||||
self.PDUSource = UInt16Le(userId.value + 1001)
|
||||
|
||||
class ShareDataHeader(CompositeType):
|
||||
'''
|
||||
"""
|
||||
PDU share data header
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, size, pduType2 = None, userId = UInt16Le(), shareId = UInt32Le()):
|
||||
CompositeType.__init__(self)
|
||||
self.shareControlHeader = ShareControlHeader(size, PDUType.PDUTYPE_DATAPDU, userId)
|
||||
@@ -478,10 +502,10 @@ class ShareDataHeader(CompositeType):
|
||||
self.compressedLength = UInt16Le()
|
||||
|
||||
class DemandActivePDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240485.aspx
|
||||
main use for capabilities exchange server -> client
|
||||
'''
|
||||
Main use for capabilities exchange server -> client
|
||||
"""
|
||||
def __init__(self, userId = UInt16Le()):
|
||||
CompositeType.__init__(self)
|
||||
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_DEMANDACTIVEPDU, userId)
|
||||
@@ -495,10 +519,10 @@ class DemandActivePDU(CompositeType):
|
||||
self.sessionId = UInt32Le()
|
||||
|
||||
class ConfirmActivePDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240488.aspx
|
||||
main use for capabilities confirm client -> sever
|
||||
'''
|
||||
Main use for capabilities confirm client -> sever
|
||||
"""
|
||||
def __init__(self, userId = UInt16Le()):
|
||||
CompositeType.__init__(self)
|
||||
self.shareControlHeader = ShareControlHeader(lambda:sizeof(self), PDUType.PDUTYPE_CONFIRMACTIVEPDU, userId)
|
||||
@@ -512,21 +536,21 @@ class ConfirmActivePDU(CompositeType):
|
||||
self.capabilitySets = ArrayType(caps.Capability, readLen = self.numberCapabilities)
|
||||
|
||||
class PersistentListEntry(CompositeType):
|
||||
'''
|
||||
use to record persistent key in PersistentListPDU
|
||||
"""
|
||||
Use to record persistent key in PersistentListPDU
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240496.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.key1 = UInt32Le()
|
||||
self.key2 = UInt32Le()
|
||||
|
||||
class PersistentListPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
Use to indicate that bitmap cache was already
|
||||
fill with some keys from previous session
|
||||
Fill with some keys from previous session
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240495.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, userId = UInt16Le(), shareId = UInt32Le()):
|
||||
CompositeType.__init__(self)
|
||||
self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST, userId, shareId)
|
||||
@@ -546,9 +570,9 @@ class PersistentListPDU(CompositeType):
|
||||
self.entries = ArrayType(PersistentListEntry, readLen = UInt16Le(lambda:(self.numEntriesCache0 + self.numEntriesCache1 + self.numEntriesCache2 + self.numEntriesCache3 + self.numEntriesCache4)))
|
||||
|
||||
class DataPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
Generic pdu packet use after connection sequence
|
||||
'''
|
||||
"""
|
||||
def __init__(self, pduType = None, pduData = None, userId = UInt16Le(), shareId = UInt32Le()):
|
||||
CompositeType.__init__(self)
|
||||
self.shareDataHeader = ShareDataHeader(lambda:sizeof(self), pduType, userId, shareId)
|
||||
@@ -576,18 +600,18 @@ class DataPDU(CompositeType):
|
||||
self.pduData = FactoryType(pduData)
|
||||
|
||||
class SynchronizeDataPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
@see http://msdn.microsoft.com/en-us/library/cc240490.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, targetUser = UInt16Le()):
|
||||
CompositeType.__init__(self)
|
||||
self.messageType = UInt16Le(1, constant = True)
|
||||
self.targetUser = targetUser
|
||||
|
||||
class ControlDataPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
@see http://msdn.microsoft.com/en-us/library/cc240492.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, action = None):
|
||||
CompositeType.__init__(self)
|
||||
self.action = UInt16Le(action.value, constant = True) if not action is None else UInt16Le()
|
||||
@@ -595,21 +619,21 @@ class ControlDataPDU(CompositeType):
|
||||
self.controlId = UInt32Le()
|
||||
|
||||
class ErrorInfoDataPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
Use to inform error in PDU layer
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240544.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, errorInfo = UInt32Le()):
|
||||
CompositeType.__init__(self)
|
||||
#use to collect error info pdu
|
||||
self.errorInfo = errorInfo
|
||||
|
||||
class FontListDataPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
Use to indicate list of font. Deprecated packet
|
||||
client -> server
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240498.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.numberFonts = UInt16Le()
|
||||
@@ -618,11 +642,11 @@ class FontListDataPDU(CompositeType):
|
||||
self.entrySize = UInt16Le(0x0032)
|
||||
|
||||
class FontMapDataPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
Use to indicate map of font. Deprecated packet (maybe the same as FontListDataPDU)
|
||||
server -> client
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240498.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.numberEntries = UInt16Le()
|
||||
@@ -631,11 +655,11 @@ class FontMapDataPDU(CompositeType):
|
||||
self.entrySize = UInt16Le(0x0004)
|
||||
|
||||
class UpdateDataPDU(CompositeType):
|
||||
'''
|
||||
Update data pdu use by server to inform update img or palette
|
||||
"""
|
||||
Update data PDU use by server to inform update img or palette
|
||||
for example
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240608.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, updateType = UInt16Le(), updateData = None):
|
||||
CompositeType.__init__(self)
|
||||
self.updateType = updateType
|
||||
@@ -652,20 +676,20 @@ class UpdateDataPDU(CompositeType):
|
||||
self.updateData = FactoryType(updateData, conditional = lambda:(self.updateType != UpdateType.UPDATETYPE_SYNCHRONIZE))
|
||||
|
||||
class BitmapUpdateDataPDU(CompositeType):
|
||||
'''
|
||||
"""
|
||||
PDU use to send raw bitmap compressed or not
|
||||
@see: http://msdn.microsoft.com/en-us/library/dd306368.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.numberRectangles = UInt16Le()
|
||||
self.rectangles = ArrayType(BitmapData, readLen = self.numberRectangles)
|
||||
|
||||
class BitmapCompressedDataHeader(CompositeType):
|
||||
'''
|
||||
"""
|
||||
Compressed header of bitmap
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240644.aspx
|
||||
'''
|
||||
"""
|
||||
def __init__(self, conditional = lambda:True):
|
||||
CompositeType.__init__(self, conditional = conditional)
|
||||
self.cbCompFirstRowSize = UInt16Le(0x0000, constant = True)
|
||||
@@ -676,9 +700,9 @@ class BitmapCompressedDataHeader(CompositeType):
|
||||
self.cbUncompressedSize = UInt16Le()
|
||||
|
||||
class BitmapData(CompositeType):
|
||||
'''
|
||||
"""
|
||||
Bitmap data here the screen capture
|
||||
'''
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.destLeft = UInt16Le()
|
||||
@@ -694,16 +718,15 @@ class BitmapData(CompositeType):
|
||||
self.bitmapDataStream = String(readLen = UInt16Le(lambda:(self.bitmapLength.value if (self.flags | BitmapFlag.NO_BITMAP_COMPRESSION_HDR) else self.bitmapComprHdr.cbCompMainBodySize.value)))
|
||||
|
||||
class PDU(LayerAutomata):
|
||||
'''
|
||||
"""
|
||||
Global channel for mcs that handle session
|
||||
identification user, licensing management, and capabilities exchange
|
||||
'''
|
||||
"""
|
||||
def __init__(self, mode, controller):
|
||||
'''
|
||||
Constructor
|
||||
"""
|
||||
@param mode: LayerMode
|
||||
@param controller: controller use to inform orders
|
||||
'''
|
||||
"""
|
||||
LayerAutomata.__init__(self, mode, None)
|
||||
#logon info send from client to server
|
||||
self._info = RDPInfo(extendedInfoConditional = lambda:self._transport.getGCCServerSettings().core.rdpVersion == gcc.Version.RDP_VERSION_5_PLUS)
|
||||
@@ -745,26 +768,32 @@ class PDU(LayerAutomata):
|
||||
self._controller = controller
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
connect event in client mode send logon info
|
||||
next state recv licence pdu
|
||||
'''
|
||||
"""
|
||||
Connect event in client mode send logon info
|
||||
Next state recv licence pdu
|
||||
"""
|
||||
self.sendInfoPkt()
|
||||
#next state is licence info PDU
|
||||
self.setNextState(self.recvLicenceInfo)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Send PDU close packet and call close method on transport method
|
||||
"""
|
||||
self._transport.send(ShareDataHeader(PDUType2.PDUTYPE2_SHUTDOWN_REQUEST, UInt16Le(self._transport.getUserId()), self._shareId))
|
||||
|
||||
def sendInfoPkt(self):
|
||||
'''
|
||||
send a logon info packet
|
||||
'''
|
||||
"""
|
||||
Send a logon info packet
|
||||
"""
|
||||
#always send extended info because rdpy only accept rdp version 5 and more
|
||||
self._transport.send((SecurityFlag.SEC_INFO_PKT, UInt16Le(), self._info))
|
||||
|
||||
def recvLicenceInfo(self, data):
|
||||
'''
|
||||
read license info packet and check if is a valid client info
|
||||
"""
|
||||
Read license info packet and check if is a valid client info
|
||||
@param data: Stream
|
||||
'''
|
||||
"""
|
||||
securityFlag = UInt16Le()
|
||||
securityFlagHi = UInt16Le()
|
||||
data.readType((securityFlag, securityFlagHi))
|
||||
@@ -784,11 +813,11 @@ class PDU(LayerAutomata):
|
||||
self.setNextState(self.recvDemandActivePDU)
|
||||
|
||||
def readDataPDU(self, data):
|
||||
'''
|
||||
"""
|
||||
Read a DataPdu struct. If is an error pdu log and close layer
|
||||
@param data: Stream from transport layer
|
||||
@return:
|
||||
'''
|
||||
"""
|
||||
#maybe an error message
|
||||
dataPDU = DataPDU()
|
||||
data.readType(dataPDU)
|
||||
@@ -803,13 +832,13 @@ class PDU(LayerAutomata):
|
||||
|
||||
|
||||
def recvDemandActivePDU(self, data):
|
||||
'''
|
||||
receive demand active PDU which contains
|
||||
server capabilities. In this version of RDPY only
|
||||
restricted group of capabilities are used.
|
||||
send confirm active PDU
|
||||
"""
|
||||
Receive demand active PDU which contains
|
||||
Server capabilities. In this version of RDPY only
|
||||
Restricted group of capabilities are used.
|
||||
Send confirm active PDU
|
||||
@param data: Stream
|
||||
'''
|
||||
"""
|
||||
demandActivePDU = DemandActivePDU()
|
||||
data.readType(demandActivePDU)
|
||||
|
||||
@@ -821,40 +850,40 @@ class PDU(LayerAutomata):
|
||||
self.sendConfirmActivePDU()
|
||||
|
||||
def recvServerSynchronizePDU(self, data):
|
||||
'''
|
||||
receive from server
|
||||
"""
|
||||
Receive from server
|
||||
@param data: Stream from transport layer
|
||||
'''
|
||||
"""
|
||||
dataPDU = self.readDataPDU(data)
|
||||
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_SYNCHRONIZE:
|
||||
raise InvalidExpectedDataException("Error in PDU layer automata : expected synchronizePDU")
|
||||
self.setNextState(self.recvServerControlCooperatePDU)
|
||||
|
||||
def recvServerControlCooperatePDU(self, data):
|
||||
'''
|
||||
receive control cooperate pdu from server
|
||||
"""
|
||||
Receive control cooperate pdu from server
|
||||
@param data: Stream from transport layer
|
||||
'''
|
||||
"""
|
||||
dataPDU = self.readDataPDU(data)
|
||||
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_CONTROL or dataPDU.pduData._value.action != Action.CTRLACTION_COOPERATE:
|
||||
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlCooperatePDU")
|
||||
self.setNextState(self.recvServerControlGrantedPDU)
|
||||
|
||||
def recvServerControlGrantedPDU(self, data):
|
||||
'''
|
||||
receive last control pdu the granted control pdu
|
||||
"""
|
||||
Receive last control pdu the granted control pdu
|
||||
@param data: Stream from transport layer
|
||||
'''
|
||||
"""
|
||||
dataPDU = self.readDataPDU(data)
|
||||
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_CONTROL or dataPDU.pduData._value.action != Action.CTRLACTION_GRANTED_CONTROL:
|
||||
raise InvalidExpectedDataException("Error in PDU layer automata : expected controlGrantedPDU")
|
||||
self.setNextState(self.recvServerFontMapPDU)
|
||||
|
||||
def recvServerFontMapPDU(self, data):
|
||||
'''
|
||||
last useless connection packet from server to client
|
||||
"""
|
||||
Last useless connection packet from server to client
|
||||
@param data: Stream from transport layer
|
||||
'''
|
||||
"""
|
||||
dataPDU = self.readDataPDU(data)
|
||||
if dataPDU.shareDataHeader.pduType2 != PDUType2.PDUTYPE2_FONTMAP:
|
||||
raise InvalidExpectedDataException("Error in PDU layer automata : expected fontMapPDU")
|
||||
@@ -864,19 +893,19 @@ class PDU(LayerAutomata):
|
||||
self.setNextState(self.recvDataPDU)
|
||||
|
||||
def recvDataPDU(self, data):
|
||||
'''
|
||||
main receive function after connection sequence
|
||||
"""
|
||||
Main receive function after connection sequence
|
||||
@param data: Stream from transport layer
|
||||
'''
|
||||
"""
|
||||
dataPDU = self.readDataPDU(data)
|
||||
if dataPDU.shareDataHeader.pduType2 == PDUType2.PDUTYPE2_UPDATE and dataPDU.pduData._value.updateType == UpdateType.UPDATETYPE_BITMAP:
|
||||
self._controller.recvBitmapUpdateDataPDU(dataPDU.pduData._value.updateData._value)
|
||||
|
||||
|
||||
def sendConfirmActivePDU(self):
|
||||
'''
|
||||
send all client capabilities
|
||||
'''
|
||||
"""
|
||||
Send all client capabilities
|
||||
"""
|
||||
#init general capability
|
||||
generalCapability = self._clientCapabilities[caps.CapsType.CAPSTYPE_GENERAL].capability._value
|
||||
generalCapability.osMajorType = caps.MajorType.OSMAJORTYPE_WINDOWS
|
||||
@@ -903,7 +932,7 @@ class PDU(LayerAutomata):
|
||||
inputCapability.imeFileName = self._transport.getGCCClientSettings().core.imeFileName
|
||||
|
||||
#make active PDU packet
|
||||
confirmActivePDU = ConfirmActivePDU(self._transport.getUserId())
|
||||
confirmActivePDU = ConfirmActivePDU(UInt16Le(self._transport.getUserId()))
|
||||
confirmActivePDU.shareId = self._shareId
|
||||
confirmActivePDU.capabilitySets._array = self._clientCapabilities.values()
|
||||
self._transport.send(confirmActivePDU)
|
||||
@@ -911,18 +940,18 @@ class PDU(LayerAutomata):
|
||||
self.sendClientFinalizeSynchronizePDU()
|
||||
|
||||
def sendClientFinalizeSynchronizePDU(self):
|
||||
'''
|
||||
"""
|
||||
send a synchronize PDU from client to server
|
||||
'''
|
||||
synchronizePDU = DataPDU(PDUType2.PDUTYPE2_SYNCHRONIZE, SynchronizeDataPDU(UInt16Le(self._transport.getChannelId().value)), self._transport.getUserId(), self._shareId)
|
||||
"""
|
||||
synchronizePDU = DataPDU(PDUType2.PDUTYPE2_SYNCHRONIZE, SynchronizeDataPDU(UInt16Le(self._transport.getChannelId())), UInt16Le(self._transport.getUserId()), self._shareId)
|
||||
self._transport.send(synchronizePDU)
|
||||
|
||||
#ask for cooperation
|
||||
controlCooperatePDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_COOPERATE), self._transport.getUserId(), self._shareId)
|
||||
controlCooperatePDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_COOPERATE), UInt16Le(self._transport.getUserId()), self._shareId)
|
||||
self._transport.send(controlCooperatePDU)
|
||||
|
||||
#request control
|
||||
controlRequestPDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_REQUEST_CONTROL), self._transport.getUserId(), self._shareId)
|
||||
controlRequestPDU = DataPDU(PDUType2.PDUTYPE2_CONTROL, ControlDataPDU(Action.CTRLACTION_REQUEST_CONTROL), UInt16Le(self._transport.getUserId()), self._shareId)
|
||||
self._transport.send(controlRequestPDU)
|
||||
|
||||
#send persistent list pdu I don't know why this packet is rejected maybe beacause we made a 0 size bitmapcache capability
|
||||
@@ -931,7 +960,7 @@ class PDU(LayerAutomata):
|
||||
#self._transport.send(persistentListPDU)
|
||||
|
||||
#deprecated font list pdu
|
||||
fontListPDU = DataPDU(PDUType2.PDUTYPE2_FONTLIST, FontListDataPDU(), self._transport.getUserId(), self._shareId)
|
||||
fontListPDU = DataPDU(PDUType2.PDUTYPE2_FONTLIST, FontListDataPDU(), UInt16Le(self._transport.getUserId()), self._shareId)
|
||||
self._transport.send(fontListPDU)
|
||||
|
||||
self.setNextState(self.recvServerSynchronizePDU)
|
||||
|
||||
@@ -18,22 +18,19 @@
|
||||
#
|
||||
|
||||
"""
|
||||
Implement transport pdu layer
|
||||
Implement transport PDU layer
|
||||
|
||||
This layer have main goal to negociate ssl transport
|
||||
This layer have main goal to negociate SSL transport
|
||||
RDP basic security is not supported by RDPY (because is not a true security layer...)
|
||||
"""
|
||||
|
||||
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.network.const import ConstAttributes, TypeAttributes
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class MessageType(object):
|
||||
"""
|
||||
message type
|
||||
Message type
|
||||
"""
|
||||
X224_TPDU_CONNECTION_REQUEST = 0xE0
|
||||
X224_TPDU_CONNECTION_CONFIRM = 0xD0
|
||||
@@ -41,32 +38,26 @@ class MessageType(object):
|
||||
X224_TPDU_DATA = 0xF0
|
||||
X224_TPDU_ERROR = 0x70
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class NegociationType(object):
|
||||
"""
|
||||
negotiation header
|
||||
Negotiation header
|
||||
"""
|
||||
TYPE_RDP_NEG_REQ = 0x01
|
||||
TYPE_RDP_NEG_RSP = 0x02
|
||||
TYPE_RDP_NEG_FAILURE = 0x03
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
class Protocols(object):
|
||||
"""
|
||||
protocols available for TPDU layer
|
||||
Protocols available for TPDU layer
|
||||
"""
|
||||
PROTOCOL_RDP = 0x00000000
|
||||
PROTOCOL_SSL = 0x00000001
|
||||
PROTOCOL_HYBRID = 0x00000002
|
||||
PROTOCOL_HYBRID_EX = 0x00000008
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Le)
|
||||
|
||||
class NegotiationFailureCode(object):
|
||||
"""
|
||||
protocol negotiation failure code
|
||||
Protocol negotiation failure code
|
||||
"""
|
||||
SSL_REQUIRED_BY_SERVER = 0x00000001
|
||||
SSL_NOT_ALLOWED_BY_SERVER = 0x00000002
|
||||
@@ -77,7 +68,7 @@ class NegotiationFailureCode(object):
|
||||
|
||||
class TPDUConnectMessage(CompositeType):
|
||||
"""
|
||||
header of TPDU connection messages
|
||||
Header of TPDU connection messages
|
||||
"""
|
||||
def __init__(self, code):
|
||||
"""
|
||||
@@ -85,24 +76,24 @@ class TPDUConnectMessage(CompositeType):
|
||||
"""
|
||||
CompositeType.__init__(self)
|
||||
self.len = UInt8(lambda:sizeof(self) - 1)
|
||||
self.code = UInt8(code.value, constant = True)
|
||||
self.code = UInt8(code, constant = True)
|
||||
self.padding = (UInt16Be(), UInt16Be(), UInt8())
|
||||
#read if there is enough data
|
||||
self.protocolNeg = Negotiation(optional = True)
|
||||
|
||||
class TPDUDataHeader(CompositeType):
|
||||
"""
|
||||
header send when tpdu exchange application data
|
||||
Header send when TPDU exchange application data
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.header = UInt8(2, constant = True)
|
||||
self.messageType = UInt8(MessageType.X224_TPDU_DATA.value, constant = True)
|
||||
self.messageType = UInt8(MessageType.X224_TPDU_DATA, constant = True)
|
||||
self.separator = UInt8(0x80, constant = True)
|
||||
|
||||
class Negotiation(CompositeType):
|
||||
"""
|
||||
negociate request message
|
||||
Negociate request message
|
||||
@see: request -> http://msdn.microsoft.com/en-us/library/cc240500.aspx
|
||||
@see: response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx
|
||||
@see: failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx
|
||||
@@ -113,8 +104,8 @@ class Negotiation(CompositeType):
|
||||
self.flag = UInt8(0)
|
||||
#always 8
|
||||
self.len = UInt16Le(0x0008, constant = True)
|
||||
self.selectedProtocol = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_RSP)
|
||||
self.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE)
|
||||
self.selectedProtocol = UInt32Le(conditional = lambda: (self.code.value != NegociationType.TYPE_RDP_NEG_FAILURE))
|
||||
self.failureCode = UInt32Le(conditional = lambda: (self.code.value == NegociationType.TYPE_RDP_NEG_FAILURE))
|
||||
|
||||
class TPDU(LayerAutomata, StreamSender):
|
||||
"""
|
||||
@@ -134,15 +125,15 @@ class TPDU(LayerAutomata, StreamSender):
|
||||
#server selected selectedProtocol
|
||||
self._selectedProtocol = Protocols.PROTOCOL_SSL
|
||||
|
||||
#Server mode informations for tls connexion
|
||||
#Server mode informations for TLS connection
|
||||
self._serverPrivateKeyFileName = None
|
||||
self._serverCertificateFileName = None
|
||||
|
||||
def initTLSServerInfos(self, privateKeyFileName, certificateFileName):
|
||||
"""
|
||||
Init informations for ssl server connexion
|
||||
Initialize informations for SSL server connection
|
||||
@param privateKeyFileName: file contain server private key
|
||||
@param certficiateFileName: file that contain publi key
|
||||
@param certficiateFileName: file that contain public key
|
||||
"""
|
||||
self._serverPrivateKeyFileName = privateKeyFileName
|
||||
self._serverCertificateFileName = certificateFileName
|
||||
@@ -176,7 +167,7 @@ class TPDU(LayerAutomata, StreamSender):
|
||||
if message.protocolNeg.failureCode._is_readed:
|
||||
raise InvalidExpectedDataException("negotiation failure code %x"%message.protocolNeg.failureCode.value)
|
||||
|
||||
self._selectedProtocol = message.protocolNeg.selectedProtocol
|
||||
self._selectedProtocol = message.protocolNeg.selectedProtocol.value
|
||||
|
||||
if self._selectedProtocol != Protocols.PROTOCOL_SSL:
|
||||
raise InvalidExpectedDataException("only ssl protocol is supported in RDPY version")
|
||||
@@ -190,8 +181,8 @@ class TPDU(LayerAutomata, StreamSender):
|
||||
|
||||
def recvConnectionRequest(self, data):
|
||||
"""
|
||||
read connection confirm packet
|
||||
next state is send connection confirm
|
||||
Read connection confirm packet
|
||||
Next state is send connection confirm
|
||||
@param data: Stream
|
||||
@see : http://msdn.microsoft.com/en-us/library/cc240470.aspx
|
||||
"""
|
||||
@@ -199,16 +190,16 @@ class TPDU(LayerAutomata, StreamSender):
|
||||
data.readType(message)
|
||||
|
||||
if not message.protocolNeg._is_readed or message.protocolNeg.failureCode._is_readed:
|
||||
raise InvalidExpectedDataException("Too older rdp client")
|
||||
raise InvalidExpectedDataException("Too older RDP client")
|
||||
|
||||
self._requestedProtocol = message.protocolNeg.selectedProtocol
|
||||
self._requestedProtocol = message.protocolNeg.selectedProtocol.value
|
||||
|
||||
if not self._requestedProtocol & Protocols.PROTOCOL_SSL:
|
||||
#send error message and quit
|
||||
message = TPDUConnectMessage()
|
||||
message.code = MessageType.X224_TPDU_CONNECTION_CONFIRM
|
||||
message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_FAILURE
|
||||
message.protocolNeg.failureCode = NegotiationFailureCode.SSL_REQUIRED_BY_SERVER
|
||||
message.code.value = MessageType.X224_TPDU_CONNECTION_CONFIRM
|
||||
message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_FAILURE
|
||||
message.protocolNeg.failureCode.value = NegotiationFailureCode.SSL_REQUIRED_BY_SERVER
|
||||
self._transport.send(message)
|
||||
raise InvalidExpectedDataException("rdpy needs ssl client compliant")
|
||||
|
||||
@@ -217,8 +208,8 @@ class TPDU(LayerAutomata, StreamSender):
|
||||
|
||||
def recvData(self, data):
|
||||
"""
|
||||
read data header from packet
|
||||
and pass to presentation layer
|
||||
Read data header from packet
|
||||
And pass to presentation layer
|
||||
@param data: Stream
|
||||
"""
|
||||
header = TPDUDataHeader()
|
||||
@@ -227,25 +218,25 @@ class TPDU(LayerAutomata, StreamSender):
|
||||
|
||||
def sendConnectionRequest(self):
|
||||
"""
|
||||
write connection request message
|
||||
next state is recvConnectionConfirm
|
||||
Write connection request message
|
||||
Next state is recvConnectionConfirm
|
||||
@see: http://msdn.microsoft.com/en-us/library/cc240500.aspx
|
||||
"""
|
||||
message = TPDUConnectMessage(MessageType.X224_TPDU_CONNECTION_REQUEST)
|
||||
message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_REQ
|
||||
message.protocolNeg.selectedProtocol = self._requestedProtocol
|
||||
message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ
|
||||
message.protocolNeg.selectedProtocol.value = self._requestedProtocol
|
||||
self._transport.send(message)
|
||||
self.setNextState(self.recvConnectionConfirm)
|
||||
|
||||
def sendConnectionConfirm(self):
|
||||
"""
|
||||
write connection confirm message
|
||||
next state is recvData
|
||||
Write connection confirm message
|
||||
Next state is recvData
|
||||
@see : http://msdn.microsoft.com/en-us/library/cc240501.aspx
|
||||
"""
|
||||
message = TPDUConnectMessage(MessageType.X224_TPDU_CONNECTION_CONFIRM)
|
||||
message.protocolNeg.code = NegociationType.TYPE_RDP_NEG_REQ
|
||||
message.protocolNeg.selectedProtocol = self._selectedProtocol
|
||||
message.protocolNeg.code.value = NegociationType.TYPE_RDP_NEG_REQ
|
||||
message.protocolNeg.selectedProtocol.value = self._selectedProtocol
|
||||
self._transport.send(message)
|
||||
#_transport is TPKT and transport is TCP layer of twisted
|
||||
self._transport.transport.startTLS(ServerTLSContext(self._serverPrivateKeyFileName, self._serverCertificateFileName))
|
||||
@@ -254,8 +245,8 @@ class TPDU(LayerAutomata, StreamSender):
|
||||
|
||||
def send(self, message):
|
||||
"""
|
||||
write message packet for TPDU layer
|
||||
add TPDU header
|
||||
Write message packet for TPDU layer
|
||||
Add TPDU header
|
||||
@param message: network.Type message
|
||||
"""
|
||||
self._transport.send((TPDUDataHeader(), message))
|
||||
@@ -294,7 +285,7 @@ class ClientTLSContext(ssl.ClientContextFactory):
|
||||
|
||||
class ServerTLSContext(ssl.DefaultOpenSSLContextFactory):
|
||||
"""
|
||||
server context factory for open ssl
|
||||
Server context factory for open ssl
|
||||
@param privateKeyFileName: Name of a file containing a private key
|
||||
@param certificateFileName: Name of a file containing a certificate
|
||||
"""
|
||||
|
||||
@@ -32,7 +32,7 @@ class TPKT(RawLayer):
|
||||
and determine if is a fast path packet
|
||||
"""
|
||||
#first byte of classic tpkt header
|
||||
TPKT_PACKET = UInt8(3)
|
||||
TPKT_PACKET = 3
|
||||
|
||||
def __init__(self, presentation):
|
||||
"""
|
||||
@@ -64,7 +64,7 @@ class TPKT(RawLayer):
|
||||
#first read packet version
|
||||
data.readType(self._lastPacketVersion)
|
||||
#classic packet
|
||||
if self._lastPacketVersion == TPKT.TPKT_PACKET:
|
||||
if self._lastPacketVersion.value == TPKT.TPKT_PACKET:
|
||||
#padding
|
||||
data.readType(UInt8())
|
||||
#read end header
|
||||
@@ -122,4 +122,4 @@ class TPKT(RawLayer):
|
||||
send encompassed data
|
||||
@param message: network.Type message to send
|
||||
"""
|
||||
RawLayer.send(self, (TPKT.TPKT_PACKET, UInt8(0), UInt16Be(sizeof(message) + 4), message))
|
||||
RawLayer.send(self, (UInt8(TPKT.TPKT_PACKET), UInt8(0), UInt16Be(sizeof(message) + 4), message))
|
||||
@@ -153,16 +153,23 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
if bitsPerPixel == 16:
|
||||
if isCompress:
|
||||
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB16)
|
||||
data = rle.rle_decode_uint16(image.bits(), width, height, data, len(data))
|
||||
data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 2)
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB16)
|
||||
|
||||
elif bitsPerPixel == 24:
|
||||
if isCompress:
|
||||
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB888)
|
||||
data = rle.rle_decode_uint24(image.bits(), width, height, data, len(data))
|
||||
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB24)
|
||||
data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 3)
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB24)
|
||||
|
||||
elif bitsPerPixel == 32:
|
||||
if isCompress:
|
||||
image = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
|
||||
data = rle.bitmap_decompress(image.bits(), width, height, data, len(data), 4)
|
||||
else:
|
||||
image = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB32)
|
||||
else:
|
||||
print "Receive image in bad format"
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user