Connects to an address on given port, send the packet, receive the response and return that. Closes the connection even if an exception is raised. :param addr: Address to connect to :param packet: packet to send, as returned from construct_packet :param port: Port to connect to, default protocol.PORT :raises: Protocol Error on and Construct Errors :return: Tuple of parsed response header and JSON loaded payload """ conn = socket.socket() conn.connect((addr, port)) try: conn.send(packet) res = conn.recv(HEADER.sizeof()) res = HEADER.parse(res) payload = conn.recv(res.payload_size) payload = json.loads(payload) return res, payload except (ConstructError, StreamError) as ex: raise ProtocolError from ex except: raise finally: conn.close() HEADER = Struct( "verb" / Enum(Int32ub, Verbs), "status" / Enum(Int32ub, Status), "payload_size" / Int32ub, )
class SetRtlsParamReq(NpiRequest, SyncReq, FromAp): command = Commands.RTLS_CMD_SET_RTLS_PARAM struct = Struct("rtlsParamType" / Enum(Int8ul, RtlsParamType), "len" / Int8ul, "data" / Byte[this.len])
def FatEntry(name): return Enum(ULInt16(name), free_cluster=0x0000, bad_cluster=0xfff7, last_cluster=0xffff, _default_=Pass)
CM = 1 AOA_TX = 2 AOA_RX = 4 TOF_SLAVE = 8 TOF_PASSIVE = 16 TOF_MASTER = 32 RTLS_SLAVE = 64 RTLS_MASTER = 128 RTLS_PASSIVE = 256 RtlsStatus = Enum( Int8ul, RTLS_SUCCESS=0, RTLS_FAIL=1, RTLS_LINK_ESTAB_FAIL=2, RTLS_LINK_TERMINATED=3, RTLS_OUT_OF_MEMORY=4, RTLS_CONFIG_NOT_SUPPORTED=5, RTLS_ILLEGAL_CMD=6, ) AssertCause = Enum( Int8ul, HAL_ASSERT_CAUSE_FALSE=0, HAL_ASSERT_CAUSE_TRUE=1, HAL_ASSERT_CAUSE_INTERNAL_ERROR=2, HAL_ASSERT_CAUSE_HW_ERROR=3, HAL_ASSERT_CAUSE_OUT_OF_MEMORY=4, HAL_ASSERT_CAUSE_ICALL_ABORT=5, HAL_ASSERT_CAUSE_ICALL_TIMEOUT=6, HAL_ASSERT_CAUSE_WRONG_API_CALL=7,
class TofRoleSwitchReq(NpiRequest, SyncReq, FromAp): command = Commands.RTLS_CMD_TOF_SWITCH_ROLE struct = Struct("tofRole" / Enum(Int8ul, TofRole))
coff_header = Struct( "signature" / Const(b"PE\x00\x00"), "machine" / Int16ul, "nsections" / Int16ul, "timestamp" / Int32ul, "symboltable_offset" / Int32ul, "nsymbols" / Int32ul, "optionalheader_size" / Int16ul, "characteristics" / Int16ul, ) pe_header = Struct( "offset" / Tell, "magic" / Enum(Int16ul, PE32=0x10B, PE32PLUS=0x20B), Seek(this.offset + 64), "checksum_offset" / Tell, "checksum" / Int32ul, Seek(lambda ctx: ctx.offset + (92 if ctx.magic == "PE32" else 108)), "nrvasizes" / Int32ul, Seek(lambda ctx: ctx.offset + (128 if ctx.magic == "PE32" else 144)), "certtable_info" / If(this.nrvasizes >= 5, Tell), "certtable_offset" / If(this.nrvasizes >= 5, Int32ul), "certtable_size" / If(this.nrvasizes >= 5, Int32ul), ) certificate = Struct( "size" / Int32ul, "revision" / Enum(Int16ul, REV1=0x0100, REV2=0x0200),
this.fields.data)) InitializeCommunication = Struct( "fields" / RawCopy( Struct( "po" / Struct("command" / Const(0x00, Int8ub)), "module_address" / Default(Int8ub, 0x00), "_not_used0" / Padding(2), "product_id" / ProductIdEnum, "firmware" / Struct("version" / Int8ub, "revision" / Int8ub, "build" / Int8ub), "panel_id" / Int16ub, "pc_password" / Default(Bytes(2), b'0000'), "modem_speed" / Bytes(1), "source_method" / Default( Enum(Int8ub, Winload_Connection=0x00, NEware_Connection=0x55), 0x00), "user_code" / Default(Int24ub, 0x000000), "serial_number" / Bytes(4), "evo_sections" / Bytes(9), # EVO section data 3030-3038 "_not_used1" / Padding(4), "source_id" / Default(CommunicationSourceIDEnum, 1), "carrier_length" / Bytes(1))), "checksum" / Checksum(Bytes(1), lambda data: calculate_checksum(data), this.fields.data)) RAMDataParserMap = { 1: Struct( "_weekday" / Int8ub, "pgm_flags" / PGMFlags(),
ABSOLUTE = 1 AUTO = 2 PASCAL_VAR = 3 REGISTER = 4 CONSTANT = 5 TYPEDEF = 6 STRUCT_UNION_OR_ENUM = 7 SYMBOL_RECORD_STRUCT = Struct( 'index' / Int16ul, # 1-based 'type' / Int16ul, 'offset' / Int16ul, 'segment' / Int16ul, 'bitfield' / BitStruct(Padding(5), 'symbol_class' / Enum(BitsInteger(3), SymbolClass))) TDINFO_HEADER_STRUCT = Struct( 'magic_number' / Const(TDINFO_MAGIC_LITTLE_ENDIAN, Int16ul), 'minor_version' / Byte, 'major_version' / Byte, 'names_pool_size_in_bytes' / Int32ul, 'names_count' / Int16ul, 'types_count' / Int16ul, 'members_count' / Int16ul, 'symbols_count' / Int16ul, 'globals_count' / Int16ul, Padding(28), 'extension_size' / Int16ul, Padding(this.extension_size)) DOS_MZ_EXE_STRUCT = Struct( 'signature' / Const(b'MZ'), 'used_bytes_in_last_page' / Int16ul, 'file_size_in_pages' / Int16ul, 'offset_of_unused_bytes' / Tell, Padding(lambda ctx: calculate_extra_information_offset(ctx) - ctx.
# ----------------------------------------------------------------------------- # DEFINE FILE FORMAT USING CONSTRUCT (V2.9) # https://github.com/construct/construct # ----------------------------------------------------------------------------- General = Struct( 'preset' / Byte, 'pchannel' / Byte, # Pads 'dchannel' / Byte, # Dials and Keys 'octave' / Enum( Byte, OCT_M4=0, OCT_M3=1, OCT_M2=2, OCT_M1=3, OCT_0=4, OCT_P1=5, OCT_P2=6, OCT_P3=7, OCT_P4=8, ), ) Arpeggio_enable = Struct( 'enable' / Default(Enum( Byte, OFF=0, ON=1, ), 0), ) Arpeggio_mode = Struct(
def __setup_constructors(self): '''Set endianness and create transport-specific constructors.''' # Set endianness of constructors before using them. self._set_endian('little') self.__Length = Int32ul self.__Type = Enum( Int16ul, default=Pass, Undefined=0x0000, Command=0x0001, Data=0x0002, Response=0x0003, Event=0x0004, ) # This is just a convenience constructor to get the size of a header. self.__Code = Int16ul self.__Header = Struct( 'Length' / self.__Length, 'Type' / self.__Type, 'Code' / self.__Code, 'TransactionID' / self._TransactionID, ) # These are the actual constructors for parsing and building. self.__CommandHeader = Struct( 'Length' / self.__Length, 'Type' / self.__Type, 'OperationCode' / self._OperationCode, 'TransactionID' / self._TransactionID, ) self.__ResponseHeader = Struct( 'Length' / self.__Length, 'Type' / self.__Type, 'ResponseCode' / self._ResponseCode, 'TransactionID' / self._TransactionID, ) self.__EventHeader = Struct( 'Length' / self.__Length, 'Type' / self.__Type, 'EventCode' / self._EventCode, 'TransactionID' / self._TransactionID, ) # Apparently nobody uses the SessionID field. Even though it is # specified in ISO15740:2013(E), no device respects it and the session # number is implicit over USB. self.__Param = Range(0, 5, self._Parameter) self.__CommandTransactionBase = Struct( Embedded(self.__CommandHeader), 'Payload' / Bytes(lambda ctx, h=self.__Header: ctx.Length - h.sizeof())) self.__CommandTransaction = ExprAdapter( self.__CommandTransactionBase, encoder=lambda obj, ctx, h=self.__Header: Container( Length=len(obj.Payload) + h.sizeof(), **obj), decoder=lambda obj, ctx: obj, ) self.__ResponseTransactionBase = Struct( Embedded(self.__ResponseHeader), 'Payload' / Bytes(lambda ctx, h=self.__Header: ctx.Length - h.sizeof())) self.__ResponseTransaction = ExprAdapter( self.__ResponseTransactionBase, encoder=lambda obj, ctx, h=self.__Header: Container( Length=len(obj.Payload) + h.sizeof(), **obj), decoder=lambda obj, ctx: obj, )
from construct import (Array, Const, Enum, GreedyRange, Int8ul, Int16ul, Int24ul, Int32ul, Padding, Rebuild, Struct) from database import enums ServerActionButtons = Struct( 'actions' / Array( 120, Struct( 'action' / Int24ul, 'type' / Enum(Int8ul, enums.ActionButtonType), )), )
from construct import (Bytes, GreedyBytes, Byte, Int16ub, Byte, BytesInteger, PascalString, Enum, FlagsEnum, Flag, Mapping, Int8ub, Struct, Embedded, EmbeddedSwitch, Const, Padded, If, Switch, Pass, Default, Seek, Adapter, ExprAdapter, this, Probe) _LOGGER = logging.getLogger(__name__) # Some help from https://github.com/Marcocanc/node-mi-lamp/blob/master/notes.md PairingStatus = Struct( "pairing_status" / Enum( Byte, PairRequest=0x01, PairSuccess=0x02, PairFailed=0x03, PairedDevice=0x04, UnknownState=0x06, Disconnected=0x07, # not documented? ), ) # Name doesn't fit to one element, so there's an index I assume.. # >>> x = bytes.fromhex("43 51 01 00 0d 5965656c696768742042656473") # >>> x # b'CQ\x01\x00\rYeelight Beds' # >>> x = bytes.fromhex("43 51 01 01 08 696465204c616d700000000000") # >>> x # b'CQ\x01\x01\x08ide Lamp\x00\x00\x00\x00\x00' Name = Struct( "id" / Byte,
class MacAddrAdapter(Adapter): def _encode(self, obj, context, path): return list(int(x, 16) for x in obj.split(":")) def _decode(self, obj, context, path): return ":".join("{:02x}".format(x) for x in obj) MacAddr = MacAddrAdapter(Byte[6]) KeepAlivePacketType = Enum(Int8ub, type_hello=0x0a, type_number=0x04, type_mac=0x00, type_ip=0x02, type_status=0x06, type_change=0x08) KeepAlivePacketSubtype = Enum( Int8ub, stype_hello=0x25, stype_number=0x26, stype_mac=0x2c, stype_ip=0x32, stype_status=0x36, stype_change=0x29, stype_status_mixer=0x00 # djm 900 nxs sends this stype on type_status )
from construct import Bytes, Const, Default, Enum, FocusedSeq, GreedyBytes, If, Int32ub, Pass, PascalString, Prefixed, Struct, Switch, this RpcMsgType = Enum(Int32ub, call=0, reply=1) RpcReplyStat = Enum(Int32ub, accepted=0, denied=1) RpcAcceptStat = Enum(Int32ub, success=0, prog_unavail=1, prog_mismatch=2, prog_unsupp=3, garbage_args=4) RpcRejectStat = Enum(Int32ub, rpc_mismatch=0, auth_error=1) RpcAuthStat = Enum(Int32ub, badcred=0, rejectedcred=1, badverf=2, rejectedverf=3, tooweak=4) RpcAuthFlavor = Enum(Int32ub, null=0, unix=1, short=2, des=3) RpcAuthUnix = Struct( "stamp" / Int32ub, "machine_name" / Default(PascalString(Int32ub, encoding="ascii"), ""), "uid" / Default(Int32ub, 0), "gid" / Default(Int32ub, 0), "gids" / Default(Int32ub, 0) # should be length-prefixed array? )
XcpError = Enum( Int8ul, ERR_CMD_SYNCH= 0x00, # Command processor synchronization. S0 ERR_CMD_BUSY= 0x10, # Command was not executed. S2 ERR_DAQ_ACTIVE= 0x11, # Command rejected because DAQ is running. S2 ERR_PGM_ACTIVE= 0x12, # Command rejected because PGM is running. S2 ERR_CMD_UNKNOWN= 0x20, # Unknown command or not implemented optional command. S2 ERR_CMD_SYNTAX= 0x21, # Command syntax invalid S2 ERR_OUT_OF_RANGE= 0x22, # Command syntax valid but command parameter(s) out of range. S2 ERR_WRITE_PROTECTED= 0x23, # The memory location is write protected. S2 ERR_ACCESS_DENIED= 0x24, # The memory location is not accessible. S2 ERR_ACCESS_LOCKED= 0x25, # Access denied, Seed & Key is required S2 ERR_PAGE_NOT_VALID= 0x26, # Selected page not available S2 ERR_MODE_NOT_VALID= 0x27, # Selected page mode not available S2 ERR_SEGMENT_NOT_VALID= 0x28, # Selected segment not valid S2 ERR_SEQUENCE= 0x29, # Sequence error S2 ERR_DAQ_CONFIG= 0x2A, # DAQ configuration not valid S2 ERR_MEMORY_OVERFLOW= 0x30, # Memory overflow error S2 ERR_GENERIC= 0x31, # Generic error. S2 ERR_VERIFY= 0x32, # The slave internal program verify routine detects an error. S3 )
from construct import Struct, Union, Enum, SLInt32 announcement_type = Enum( SLInt32("type"), LAUNCH=0, EXIT=1, ) announcement = Struct( "announcement", announcement_type, Union( "args", SLInt32("rank"), ), ) ANNOUNCEMENT_PACKET_LEN = announcement.sizeof()
# define PENALTY_HL_KID_REQUEST_FOR_SERVICE 6 # define PENALTY_HL_KID_REQUEST_FOR_PICKUP_2_SERVICE 7 # define MANUAL 15 "penalty" / Byte, "secs_till_unpenalized" / Byte, "number_of_yellow_cards" / Byte, "number_of_red_cards" / Byte) TeamInfo = "team" / Struct( "team_number" / Byte, "team_color" / Enum(Byte, BLUE=0, RED=1, YELLOW=2, BLACK=3, WHITE=4, GREEN=5, ORANGE=6, PURPLE=7, BROWN=8, GRAY=9), "score" / Byte, "penalty_shot" / Byte, # penalty shot counter "single_shots" / Short, # bits represent penalty shot success "coach_sequence" / Byte, "coach_message" / PaddedString(253, 'utf8'), "coach" / RobotInfo, "players" / Array(11, RobotInfo)) GameState = "gamedata" / Struct( "header" / Const(b'RGme'),
from ..adapters import LinearAdapter from construct import Adapter, BitsInteger, BitStruct, Container, Enum, Flag, \ Int8ub, Int16ub, Int32ub, Padding, Struct, Switch SOH_L0 = BitStruct( 'SOH_L0__WDT_2SEC_CNT' / BitsInteger(3), 'SOH_L0__RESET_ARMED' / Enum(Flag, ARMED=1, NOT_ARMED=0), 'SOH_L0__WDT_STAT' / Enum(Flag, NO_WDT=0, WDT=1), 'SOH_L0__WDT_EN' / Enum(Flag, DISABLED=0, ENABLED=1), 'SOH_L0__TABLE_SELECT' / Enum(Flag, FLASH=0, COMPILED=1), 'SOH_L0__BOOT_RELAY' / Enum(Flag, PRIMARY=1, REDUNDANT=0), 'SOH_L0__L0_ACPT_CNT' / BitsInteger(8), 'SOH_L0__L0_RJCT_CNT' / BitsInteger(8), 'SOH_L0__HW_SEC_CNT' / BitsInteger(8), Padding(64), 'SOH_L0__TIME_TAG' / BitsInteger(32), Padding(32), 'SOH_L0__PLD_TLM_ACK_CNT' / BitsInteger(8), 'SOH_L0__PLD_CMD_CNT' / BitsInteger(8), 'SOH_L0__PLD_TLM_TO_CNT' / BitsInteger(8), 'SOH_L0__PLD_TLM_NAK_CNT' / BitsInteger(8), 'SOH_L0__SPARE_END' / BitsInteger(64), ) SOH_COMMAND_TLM = BitStruct( 'SOH_COMMAND_TLM__CMD_STATUS' / Enum(BitsInteger(8), OK=0, BAD_APID=1, BAD_OPCODE=2, BAD_DATA=3, NOW_READING=4,
UBInt32("included_length"), UBInt32("record_length"), UBInt32("cumulative_drops"), EpochTimeStampAdapter(UBInt32("timestamp_seconds")), UBInt32("timestamp_microseconds"), HexDumpAdapter(Field("data", lambda ctx: ctx.included_length)), # 24 being the static length of the packet_record header Padding(lambda ctx: ctx.record_length - ctx.included_length - 24), ) datalink_type = Enum(UBInt32("datalink"), IEEE802dot3 = 0, IEEE802dot4 = 1, IEEE802dot5 = 2, IEEE802dot6 = 3, ETHERNET = 4, HDLC = 5, CHARSYNC = 6, IBMCHANNEL = 7, FDDI = 8, OTHER = 9, UNASSIGNED = 10, ) snoop_file = Struct("snoop", Magic("snoop\x00\x00\x00"), UBInt32("version"), # snoop v1 is deprecated datalink_type, OptionalGreedyRange(packet_record), )
QUEUE = Struct( 'header' / DelimitedField(bytes.fromhex(FILE_HEADER)), Const(bytes.fromhex(FILE_HEADER)), Const(bytes.fromhex(QUEUE_HEADER)), 'job_count' / Int32ul, 'jobs' / DelimitedField(bytes.fromhex(QUEUE_HEADER)), Const(bytes.fromhex(QUEUE_HEADER)), 'unknown' / DelimitedField(bytes.fromhex(FILE_HEADER)), Const(bytes.fromhex(FILE_HEADER)), 'remains' / GreedyBytes, ) # CONTROL : job control informations CONTROL_PART_0 = Struct( 'type' / Enum(Int32ul, default=Pass, download=0, upload=1, upload_reply=2), 'priority' / Enum(Int32ul, default=Pass, foreground=0, high=1, normal=2, low=3), 'state' / Enum(Int32ul, default=Pass, queued=0, connecting=1, transferring=2, suspended=3, error=4, transient_error=5, transferred=6, acknowleged=7, cancelled=8), Int32ul, 'job_id' / UUID(Bytes(16)),
"storageClass" / Enum( Byte, C_NULL=0, # No storage class C_USTATIC=14, # Undefined static C_AUTO=1, # Reserved C_ENTAG=15, # Reserved C_EXT=2, # External definition C_MOE=16, # Reserved C_STAT=3, # Static C_REGPARM=17, # Reserved C_REG=4, # Reserved C_FIELD=18, # Reserved C_EXTREF=5, # External reference C_UEXT=19, # Tentative external definition C_LABEL=6, # Label C_STATLAB=20, # Static load time label C_ULABEL=7, # Undefined label C_EXTLAB=21, # External load time label C_MOS=8, # Reserved C_VARARG= 27, # Last declared parameter of a function with a variable number of arguments C_ARG=9, # Reserved C_BLOCK=100, # Reserved C_STRTAG=10, # Reserved C_FCN=101, # Reserved C_MOU=11, # Reserved C_EOS=102, # Reserved C_UNTAG=12, # Reserved C_FILE=103, # Reserved C_TPDEF=13, # Reserved C_LINE=104, # Used only by utility programs ),
def prettyprint_blocktype(bt): res = [] for key in ('complex', 'type', 'deriv', 'extend', 'data', 'param'): name = BlockType_decoder[key][bt[key]] if name: res.append(name) if bt.param != 0: res.append('parameters') return ' '.join(res) Parameter = Struct( 'Name' / FixedSizeCString(4), # 4 bytes, 3 chars + null 'Type' / Enum(Int16ul, INT32=0, REAL64=1, STRING=2, ENUM=3, SENUM=4), 'ReservedSpace' / Int16ul, # Only look for a Value if this isn't the END pseudo-parameter. 'Value' / If( this.Name != b'END', Switch(this.Type, { 'INT32': Int32ul, 'REAL64': Float64l }, default=FixedSizeCString(this.ReservedSpace * 2)))) def is_ParameterList(block): return block.BlockType.param != 0
class DeviceInfoRsp(NpiRequest, AsyncReq, FromNwp): command = Commands.RTLS_CMD_SCAN struct = Struct("eventType" / Int8ul, "addrType" / Enum(Int8ul), "addr" / NiceBytes(ReverseBytes(Byte[6])), "rssi" / Int8sl, "dataLen" / Int8ul, "data" / NiceBytes(Byte[this.dataLen]))
from collections import OrderedDict from OpenSSL import crypto CTL_LISTS = 'https://www.gstatic.com/ct/log_list/log_list.json' CTL_INFO = "http://{}/ct/v1/get-sth" DOWNLOAD = "http://{}/ct/v1/get-entries?start={}&end={}" from construct import Struct, Byte, Int16ub, Int64ub, Enum, Bytes, Int24ub, this, GreedyBytes, GreedyRange, Terminated, \ Embedded MerkleTreeHeader = Struct( "Version" / Byte, "MerkleLeafType" / Byte, "Timestamp" / Int64ub, "LogEntryType" / Enum(Int16ub, X509LogEntryType=0, PrecertLogEntryType=1), "Entry" / GreedyBytes) Certificate = Struct("Length" / Int24ub, "CertData" / Bytes(this.Length)) CertificateChain = Struct( "ChainLength" / Int24ub, "Chain" / GreedyRange(Certificate), ) PreCertEntry = Struct("LeafCert" / Certificate, Embedded(CertificateChain), Terminated) async def retrieve_all_ctls(session=None): async with session.get(CTL_LISTS) as response:
class SetRtlsParamRsp(NpiRequest, SyncRsp, FromNwp): command = Commands.RTLS_CMD_SET_RTLS_PARAM struct = Struct( "rtlsParamType" / Enum(Int8ul, RtlsParamType), "status" / RtlsStatus, )
frontend_switch = Switch(this.type, { **FrontendMessage.name_to_struct(), **SharedMessage.name_to_struct() }, default=Bytes(this.length - 4)) backend_switch = Switch(this.type, { **BackendMessage.name_to_struct(), **SharedMessage.name_to_struct() }, default=Bytes(this.length - 4)) frontend_msgtypes = Enum( Byte, **{ **FrontendMessage.name_to_key(), **SharedMessage.name_to_key() }) backend_msgtypes = Enum( Byte, **{ **BackendMessage.name_to_key(), **SharedMessage.name_to_key() }) # It might seem a little circuitous to say a frontend message is a kind of frontend # message but this lets us easily customize how they're printed class Frontend(FrontendMessage): struct = Struct(
from __future__ import print_function import numpy as np from argparse import ArgumentParser from construct import (Struct, Const, Array, PascalString, Int32ul, Int64sl, Enum, Computed, OneOf, If, RepeatUntil, Bytes, Float64l, Float32l, Int32sl, Switch, LazyBound, Int8ul, Tell, Padding, this) from six.moves import xrange WIPTagType = Enum( Int32ul, WIP_TAG_LIST=0, # list of other tags WIP_TAG_EXTENDED=1, # x86 FPU native type, 10 bytes WIP_TAG_DOUBLE=2, WIP_TAG_FLOAT=3, WIP_TAG_INT64=4, WIP_TAG_INT32=5, WIP_TAG_UINT32=6, WIP_TAG_CHAR=7, WIP_TAG_BOOL=8, # 1 byte WIP_TAG_STRING=9 # int32 = nchars, n bytes = string ) WIPString = PascalString(lengthfield=Int32ul) WIPTag = Struct( 'WIPTag', 'name' / WIPString, 'type' / WIPTagType, 'data_start' / Int64sl, 'data_end' / Int64sl,
class ReadyForQuery(BackendMessage): key = 'Z' struct = Struct("state" / Enum(Byte, idle=ord('I'), in_transaction_block=ord('T'), in_failed_transaction_block=ord('E')))
# Metadata subconstruct. metadata = StringAdapter( RepeatUntil(lambda obj, ctx: obj == "\x7f", Field("metadata", 1))) # Build faces, used during dig and build. faces = { "noop": -1, "-y": 0, "+y": 1, "-z": 2, "+z": 3, "-x": 4, "+x": 5, } face = Enum(SBInt8("face"), **faces) packets = { 0: Struct("ping"), 1: Struct( "login", UBInt32("protocol"), AlphaString("username"), AlphaString("unused"), SBInt64("seed"), UBInt8("dimension"), ), 2: Struct(
import struct import zstandard from construct import Construct, Enum, Byte, this, Adapter, Struct, Seek, Int32ul, Array, CString, Tell, If, Bytes, \ Computed, Embedded, Switch, Error, Int24ul, Hex, String, Int16ul, GreedyBytes, StringsAsBytes from .common import zlib_stream NOT_PACKED_ADDED_OFFSET = 0x10 NOT_PACKED_FILE_DATA_TABLE_OFFSET = 0x20 NOT_PACKED_FILENAME_TABLE_OFFSET = 0x40 vromfs_type = Enum( Byte, unknown_type=0x40, maybe_packed=0x80, zstd_packed=0xc0 ) class ZstdContext(Construct): def __init__(self): super(ZstdContext, self).__init__() def _parse(self, stream, ctx, path): need_read_size = ctx._._.header.packed_size - (16 if ctx.first_part else 0) - (16 if ctx.second_part else 0) # ugly: align read size to 4 bytes need_read_size = need_read_size // 4 * 4 deobfs_compressed_data = (ctx.first_part if ctx.first_part else b'') + \ stream.getvalue()[ctx.middle_data_offset:ctx.middle_data_offset + need_read_size] + \ (ctx.second_part.data if ctx.second_part.data else b'') + \