def update(self, s: BytesIO): if self.ctx.field(1): self.x = read_coord(s, self.ctx.deltaCoords, self.x) if self.ctx.field(2): self.y = read_coord(s, self.ctx.deltaCoords, self.y) if self.ctx.field(3): self.w = read_coord(s, self.ctx.deltaCoords, self.w) if self.ctx.field(4): self.h = read_coord(s, self.ctx.deltaCoords, self.h) if self.ctx.field(5): self.rop = Uint8.unpack(s) if self.ctx.field(6): self.bg = read_rgb(s) if self.ctx.field(7): self.fg = read_rgb(s) self.brush.update(s, self.ctx.fieldFlags >> 7) if self.ctx.field(13): self.numRectangles = Uint8.unpack(s) if self.ctx.field(14): self.cbData = Uint16LE.unpack(s) self.rectangles = read_delta_rectangles(s, self.numRectangles) return self
def parse(s: BytesIO, flags: int) -> CacheBitmap: self = CacheBitmapV3(3) self.cacheId = flags & 0x00000003 self.flags = (flags & 0x0000FF80) >> 7 bitsPerPixelId = (flags & 0x00000078) >> 3 # The spec says this should never be 0, but it is... self.bpp = CBR23_BPP[bitsPerPixelId] self.cacheIndex = Uint16LE.unpack(s) self.key1 = Uint32LE.unpack(s) self.key2 = Uint32LE.unpack(s) self.bpp = Uint8.unpack(s) compressed = Uint8.unpack(s) s.read(1) # Reserved (1 bytes) self.codecId = Uint8.unpack(s) self.width = Uint16LE.unpack(s) self.height = Uint16LE.unpack(s) dataLen = Uint32LE.unpack(s) if compressed: # TS_COMPRESSED_BITMAP_HEADER_EX present. s.read(24) # Non-essential. self.data = s.read(dataLen) return self
def update(self, s: BytesIO): num = self.numPoints if self.ctx.field(1): self.x0 = read_coord(s, self.ctx.deltaCoords, self.x0) if self.ctx.field(2): self.y0 = read_coord(s, self.ctx.deltaCoords, self.y0) if self.ctx.field(3): self.rop2 = Uint8.unpack(s) if self.ctx.field(4): self.fillMode = Uint8.unpack(s) if self.ctx.field(5): self.bg = read_rgb(s) if self.ctx.field(6): self.fg = read_rgb(s) self.brush.update(s, self.ctx.fieldFlags >> 6) if self.ctx.field(12): num = Uint8.unpack(s) if self.ctx.field(13): self.cbData = Uint8.unpack(s) self.numPoints = num self.points = read_delta_points(s, self.numPoints, self.x0, self.y0) self.bgMode = BACKMODE_TRANSPARENT if self.rop2 & 0x80 else BACKMODE_OPAQUE self.rop2 = self.rop2 & 0x1F return self
def parse(s: BytesIO, flags: int, glyph: GlyphSupport) -> 'CacheGlyph': """ Parse a CACHE_GLYPH order. :param s: The byte stream to parse :param flags: The UPDATE PDU controlFlags :param glyph: One of Glyph or GlyphV2 classes to select the parsing strategy """ self = CacheGlyph() if GlyphSupport.GLYPH_SUPPORT_ENCODE: self.cacheId = flags & 0x0F cGlyphs = flags >> 8 unicodePresent = (flags >> 4 & 0x0F) & 0x01 self.glyphs = [GlyphV2.parse(s) for _ in range(cGlyphs)] else: self.cacheId = Uint8.unpack(s) cGlyphs = Uint8.unpack(s) unicodePresent = flags & CG_GLYPH_UNICODE_PRESENT self.glyphs = [Glyph.parse(s) for _ in range(cGlyphs)] if unicodePresent and cGlyphs > 0: self.unicode = read_utf16_str(s, cGlyphs) return self
def update(self, s: BytesIO): if self.ctx.field(1): self.nLeftRect = read_coord(s, self.ctx.deltaCoords, self.nLeftRect) if self.ctx.field(2): self.nTopRect = read_coord(s, self.ctx.deltaCoords, self.nTopRect) if self.ctx.field(3): self.nWidth = read_coord(s, self.ctx.deltaCoords, self.nWidth) if self.ctx.field(4): self.nHeight = read_coord(s, self.ctx.deltaCoords, self.nHeight) if self.ctx.field(5): r = Uint8.unpack(s) self.color = (self.color & 0x00FFFF00) | r if self.ctx.field(6): g = Uint8.unpack(s) self.color = (self.color & 0x00FF00FF) | (g << 8) if self.ctx.field(7): b = Uint8.unpack(s) self.color = (self.color & 0x0000FFFF) | (b << 16) if self.ctx.field(8): self.numRectangles = Uint8.unpack(s) if self.ctx.field(9): self.cbData = Uint16LE.unpack(s) self.rectangles = read_delta_rectangles(s, self.numRectangles) return self
def update(self, s: BytesIO): if self.ctx.field(1): self.nLeftRect = read_coord(s, self.ctx.deltaCoords, self.nLeftRect) if self.ctx.field(2): self.nTopRect = read_coord(s, self.ctx.deltaCoords, self.nTopRect) if self.ctx.field(3): self.nWidth = read_coord(s, self.ctx.deltaCoords, self.nWidth) if self.ctx.field(4): self.nHeight = read_coord(s, self.ctx.deltaCoords, self.nHeight) if self.ctx.field(5): self.bRop = Uint8.unpack(s) if self.ctx.field(6): self.nXSrc = read_coord(s, self.ctx.deltaCoords, self.nXSrc) if self.ctx.field(7): self.nYSrc = read_coord(s, self.ctx.deltaCoords, self.nYSrc) if self.ctx.field(8): self.numRectangles = Uint8.unpack(s) if self.ctx.field(9): self.cbData = Uint16LE.unpack(s) self.rectangles = read_delta_rectangles(s, self.numRectangles) return self
def writeObjectIdentifier(oid): """ Pack a PER object identifier :param oid: object identifier (tuple of 6 integers) :type oid: (int, int, int, int, int, int) :return: str """ return writeLength(5) + Uint8.pack((oid[0] << 4) & (oid[1] & 0x0f)) + b"".join(Uint8.pack(b) for b in oid[2 :])
def read_encoded_uint16(s: BytesIO) -> int: """Read an encoded UINT16.""" # 2.2.2.2.1.2.1.2 b = Uint8.unpack(s) if b & 0x80: return (b & 0x7F) << 8 | Uint8.unpack(s) else: return b & 0x7F
def writeLength(length: int) -> bytes: """ Pack structure length as expected in BER specification :param length: structure length. """ if length > 0x7f: return Uint8.pack(0x82) + Uint16BE.pack(length) else: return Uint8.pack(length)
def read_encoded_int16(s: BytesIO) -> int: # 2.2.2.2.1.2.1.3 msb = Uint8.unpack(s) val = msb & 0x3F if msb & 0x80: lsb = Uint8.unpack(s) val = (val << 8) | lsb return -val if msb & 0x40 else val
def readLength(s: BinaryIO) -> int: """ Unpack a PER length indicator :param s: stream """ byte = Uint8.unpack(s.read(1)) if byte & 0x80: byte &= ~0x80 return (byte << 8) + Uint8.unpack(s.read(1)) else: return byte
def writeApplicationTag(tag, size): """ Pack an application tag. :param tag: application tag. :type tag: Tag :param size: the size of the application packet. :type size: int """ if tag > 30: return Uint8.pack((Class.BER_CLASS_APPL | PC.BER_CONSTRUCT) | Tag.BER_TAG_MASK) + Uint8.pack(tag) + writeLength(size) else: return Uint8.pack((Class.BER_CLASS_APPL | PC.BER_CONSTRUCT) | (Tag.BER_TAG_MASK & tag)) + writeLength(size)
def readLength(s): """ Unpack a PER length indicator :param s: stream :type s: file :return: int """ byte = Uint8.unpack(s.read(1)) size = 0 if byte & 0x80: byte &= ~0x80 return (byte << 8) + Uint8.unpack(s.read(1)) else: return byte
def update(self, s: BytesIO, flags: int): """ Update the context when parsing a new primary order. This method should be called at the beginning of every new primary order to process contextual changes. :param s BytesIO: The raw byte stream :param flags int: The controlFlags received in the UPDATE PDU. :return: The orderType to act upon. """ if flags & ControlFlags.TS_TYPE_CHANGE: self.orderType = Uint8.unpack(s) assert self.orderType is not None self.fieldFlags = read_field_flags(s, flags, self.orderType) # Process bounding rectangle updates if flags & ControlFlags.TS_BOUNDS: self.bounded = True if not flags & ControlFlags.TS_ZERO_BOUNDS_DELTAS: self.bounds.update(s) else: self.bounded = False self.deltaCoords = flags & ControlFlags.TS_DELTA_COORDS != 0 return self.orderType
def update(self, s: BytesIO) -> 'MemBlt': ctx = self.ctx if ctx.field(1): self.cacheId = Uint16LE.unpack(s) if ctx.field(2): self.left = read_coord(s, ctx.deltaCoords, self.left) if ctx.field(3): self.top = read_coord(s, ctx.deltaCoords, self.top) if ctx.field(4): self.width = read_coord(s, ctx.deltaCoords, self.width) if ctx.field(5): self.height = read_coord(s, ctx.deltaCoords, self.height) if ctx.field(6): self.rop = Uint8.unpack(s) if ctx.field(7): self.xSrc = read_coord(s, ctx.deltaCoords, self.xSrc) if ctx.field(8): self.ySrc = read_coord(s, ctx.deltaCoords, self.ySrc) if ctx.field(9): self.cacheIndex = Uint16LE.unpack(s) self.colorIndex = self.cacheId >> 8 self.cacheId = self.cacheId & 0xFF return self
def writeEnumeration(value): """ Pack a BER enumeration value :type value: int :return: str """ return writeUniversalTag(Tag.BER_TAG_ENUMERATED, False) + writeLength(1) + Uint8.pack(value)
def update(self, s: BytesIO): if self.ctx.field(1): self.cacheId = Uint16LE.unpack(s) if self.ctx.field(2): self.left = read_coord(s, self.ctx.deltaCoords, self.left) if self.ctx.field(3): self.top = read_coord(s, self.ctx.deltaCoords, self.top) if self.ctx.field(4): self.width = read_coord(s, self.ctx.deltaCoords, self.width) if self.ctx.field(5): self.height = read_coord(s, self.ctx.deltaCoords, self.height) if self.ctx.field(6): self.rop = Uint8.unpack(s) if self.ctx.field(7): self.nXSrc = read_coord(s, self.ctx.deltaCoords, self.nXSrc) if self.ctx.field(8): self.nYSrc = read_coord(s, self.ctx.deltaCoords, self.nYSrc) if self.ctx.field(9): self.bg = read_rgb(s) if self.ctx.field(10): self.fg = read_rgb(s) self.brush.update(s, self.ctx.fieldFlags >> 10) if self.ctx.field(16): self.cacheIndex = Uint16LE.unpack(s) self.colorIndex = self.cacheId >> 8 self.cacheId = self.cacheId & 0xFF return self
def _parse_secondary(self, s: BytesIO, flags: int): Uint16LE.unpack(s) # orderLength (unused) extraFlags = Uint16LE.unpack(s) orderType = Uint8.unpack(s) assert orderType >= 0 and orderType < len(_sec) _sec[orderType](self, s, orderType, extraFlags)
def writeBoolean(value: bool) -> bytes: """ Pack a BER boolean """ boolean = Uint8.pack(0xff if value else 0) return writeUniversalTag(Tag.BER_TAG_BOOLEAN, False) + writeLength(1) + boolean
def writeNumericString(string: str, minValue: int) -> bytes: """ Pack a PER numeric string :param string: numeric string :param minValue: minimum string length """ length = len(string) mlength = minValue if length >= minValue: mlength = length - minValue result = b"" for i in range(0, length, 2): c1 = ord(string[i : i + 1]) if i + 1 < length: c2 = ord(string[i + 1 : i + 2]) else: c2 = 0x30 c1 = (c1 - 0x30) % 10 c2 = (c2 - 0x30) % 10 result += Uint8.pack((c1 << 4) | c2) return writeLength(mlength) + result
def writeLength(value: int) -> bytes: """ Pack a PER length indicator """ if value > 0x7f: return Uint16BE.pack(value | 0x8000) else: return Uint8.pack(value)
def writeBoolean(value): """ Pack a BER boolean :type value: bool :return: str """ boolean = Uint8.pack(0xff if value else 0) return writeUniversalTag(Tag.BER_TAG_BOOLEAN, False) + writeLength(1) + boolean
def writeNumberOfSet(numberOfSet): """ Pack a PER NumberOfSet :param numberOfSet: NumberOfSet value :type numberOfSet: int :return: str """ return Uint8.pack(numberOfSet)
def writeSelection(selection): """ Pack a PER selection :param selection: selection value :type selection: int :return: str """ return Uint8.pack(selection)
def readNumberOfSet(s): """ Unpack a PER NumberOfSet :param s: stream :type s: file :return: int """ return Uint8.unpack(s.read(1))
def readSelection(s): """ Unpack a PER selection :param s: stream :type s: file :return: int """ return Uint8.unpack(s.read(1))
def writeChoice(choice): """ Pack a PER choice :param choice: choice value :type choice: int :return: str """ return Uint8.pack(choice)
def readChoice(s): """ Unpack a PER choice :param s: stream :type s: file :return: int """ return Uint8.unpack(s.read(1))
def readEnumeration(s): """ Unpack a PER enumeration format :param s: stream :type s: file :return: int """ return Uint8.unpack(s.read(1))
def writeEnumeration(enum): """ Pack a PER enumeration :param enum: enumeration value :type enum: int :return: str """ return Uint8.pack(enum)