def test_parse(self): s = GreedyString("s", encoding="utf8") self.assertEqual(s.parse(b"hello\x00"), u"hello\x00") self.assertEqual(s.parse(b""), u"") s = GreedyString("s") self.assertEqual(s.parse(b"hello\x00"), b"hello\x00") self.assertEqual(s.parse(b""), b"")
RadioTest = Struct( "packet_counter" / Int8ul ) TxPower = Struct( "tx_power" / Int8ul ) UptimeStatus = Struct( "uptime" / Int32ul ) LastFault = Struct( "time" / Int32ul, "fault" / GreedyString("utf8") ) SystemStats = Struct( "stats" / DictAdapter( GreedyRange( Struct( "name" / PaddedString(8, "utf8"), "high_water_mark" / Int16ul, "rfu" / Padding(4), ) ), key=this.name, value=this.high_water_mark ) )
def compute_header_hmac_hash(context): """Compute HMAC-SHA256 hash of header. Used to prevent header tampering.""" return hmac.new( hashlib.sha512(b'\xff' * 8 + hashlib.sha512( context._.header.value.dynamic_header.master_seed.data + context.transformed_key + b'\x01').digest()).digest(), context._.header.data, hashlib.sha256).digest() # --------------- KDF Params / Plugin Data ---------------- VariantDictionaryItem = Struct( "type" / Byte, "key" / Prefixed(Int32ul, GreedyString('utf-8')), "value" / Prefixed( Int32ul, Switch( this.type, { 0x04: Int32ul, 0x05: Int64ul, 0x08: Flag, 0x0C: Int32sl, 0x0D: Int64sl, 0x42: GreedyBytes, 0x18: GreedyString('utf-8') })), "next_byte" / Peek(Byte)) # new dynamic dictionary structure added in KDBX4 VariantDictionary = Struct(
def FixedUTF16String(size_func): """At parse time parses a UTF16 string with a known size, and at build time builds the string with its given size. """ return IfThenElse(lambda ctx: ctx._parsing, PaddedString(size_func, "UTF_16_le"), GreedyString("UTF_16_le"))
EDDYSTONE_TLM_ENCRYPTED, EDDYSTONE_UID_FRAME, EDDYSTONE_URL_FRAME, \ EDDYSTONE_TLM_FRAME, EDDYSTONE_EID_FRAME, FLAGS_DATA_TYPE, \ SERVICE_DATA_TYPE, SERVICE_UUIDS_DATA_TYPE, ESTIMOTE_UUID, \ ESTIMOTE_TELEMETRY_FRAME from .estimote import EstimoteTelemetryFrame # pylint: disable=invalid-name EddystoneUIDFrame = Struct("tx_power" / Int8sl, "namespace" / Array(10, Byte), "instance" / Array(6, Byte), "rfu" / Array(2, Byte)) EddystoneURLFrame = Struct( "tx_power" / Int8sl, "url_scheme" / OneOf(Byte, list(EDDYSTONE_URL_SCHEMES)), "url" / GreedyString(encoding="ascii")) UnencryptedTLMFrame = Struct( "voltage" / Int16ub, "temperature" / Int16ul, "advertising_count" / Int32ub, "seconds_since_boot" / Int32ub, ) EncryptedTLMFrame = Struct("encrypted_data" / Array(12, Byte), "salt" / Int16ul, "mic" / Int16ul) EddystoneTLMFrame = Struct( "tlm_version" / Byte, "data" / Switch( lambda ctx: ctx.tlm_version, { EDDYSTONE_TLM_UNENCRYPTED: UnencryptedTLMFrame,
def test_build(self): s = GreedyString("foo", encoding="utf8") self.assertEqual(s.build(six.u("hello")), six.b("hello"))
def test_parse(self): s = GreedyString("foo", encoding="utf8") self.assertEqual(s.parse(six.b("hello\x00")), six.u("hello\x00"))
[ Subrecord( "SCHR", Struct( "_unknown_0" / Bytes(4), "ref_count" / Int32ul, "compiled_size" / Int32ul, "variable_count" / Int32ul, "type" / FlagsEnum(Int16ul, object=0x000, quest=0x001, effect=0x100), "flags" / FlagsEnum(Int16ul, enabled=0x0001), ) * "Basic Script Data", ), Subrecord("SCDA", GreedyBytes * "Commpiled Script Source"), Subrecord("SCTX", GreedyString("utf8") * "Script Source"), SubrecordCollection( "ScriptVariables", [ Subrecord( "SLSD", Struct( "index" / Int32ul, "_unknown_0" / Bytes(12), "flags" / FlagsEnum(Int8ul, is_long_or_short=0x01), "_unknown_1" / Bytes(7), ) * "Local Variable Data", ), Subrecord("SCVR", CString("utf8") * "Local Variable Name"), ],
if obj == u"": return b"" return obj.encode("UTF-16le", "replace") def PaddedUTF16StringBestEffort(length): return UTF16EncodedBestEffort( FixedSized(length, NullStripped(GreedyBytes, pad="\x00\x00"))) FixedNullTerminatedUTF16String = Struct( # I don't use PascalString because it's a null terminated string. "string_size" / Int32ul, "string" / IfThenElse( lambda this: this.string_size, FixedSized( lambda this: this.string_size, NullTerminated(GreedyString("UTF_16_le"), term="\x00".encode("utf-16le"))), Computed(''))) class FiletimeAdapter(Adapter): def _decode(self, obj, context, path): if 0 == obj: return None # 0 is not really a date secs = int(obj // int(1e7)) nanosecs = int(obj - int(secs * int(1e7))) * 100 # I use numpy's datetime64 instead of datetime.datetime because filetime have 100 nanoseconds precision. return datetime64('1601-01-01') + timedelta64(secs, 's') + timedelta64( nanosecs, 'ns') def _encode(self, obj, context, path):
def test_build(self): s = GreedyString("s", encoding="utf8") self.assertEqual(s.build(u"hello"), b"hello") s = GreedyString("s") self.assertEqual(s.build(b"hello"), b"hello")
def test_build(self): s = GreedyString("foo", encoding="utf8") self.assertEqual(s.build(u("hello")), b"hello")
def test_parse(self): s = GreedyString("foo", encoding="utf8") self.assertEqual(s.parse(b"hello\x00"), u("hello\x00"))
"le_br_edr_support_host" / Flag, "le_br_edr_support_controller" / Flag, "br_edr_not_supported" / Flag, "le_general_discoverable_mode" / Flag, "le_limited_discoverable_mode" / Flag, ), MFG_DEFINED_TYPE: Switch(lambda ctx: ctx.length, { 27: BT510, LEN_BT510_EXT_FW_1_2: BT510_EXT_FW_1_2, LEN_BT510_EXT_FW_1_4: BT510_EXT_FW_1_4, LEN_EXT_SCAN_RESP_E4: EXT_SCAN_RESP_E4, 3: unknown }, default=Array(lambda ctx: ctx.length - 1, Byte)), SHORT_LOCAL_NAME_TYPE: GreedyString("utf8"), NAME_TYPE: GreedyString("utf8") }, default=Array(lambda ctx: ctx.length - 1, Byte)), ) advert_frame = GreedyRange(ADVERT) def parse(hex_string): barr = bytes(bytearray.fromhex(hex_string)) frame = advert_frame.parse(barr) return frame
TimeslotTxPowerStatus = Struct("tx_power" / Int8ul) SoftdeviceTxPowerGet = Struct() SoftdeviceTxPowerStatus = Struct("tx_power" / Int8ul) UptimeGet = Struct() UptimeStatus = Struct("uptime" / Int32ul) LastSwFaultGet = Struct() LastSwFaultClear = Struct() LastSwFaultStatus = Struct("time" / Int32ul, "fault" / GreedyString("utf8")) SystemStatsGet = Struct() SystemStat = Struct("name" / PaddedString(8, "utf8"), "high_water_mark" / Int32ul, "_rfu" / Padding(2)) SystemStatsStatus = Struct("stats" / GreedyRange(SystemStat)) LastMallocFaultGet = Struct() LastMallocFaultClear = Struct() LastMallocFaultStatus = LastSwFaultStatus LastFdsFaultGet = Struct()
Paired=0x02, PairedUDID=0x04, Disconnected=0x07) ) # 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 = "name" / Struct( "part" / Byte, "text_part" / GreedyString(), ) class LampMode(enum.Enum): Color = 0x01 White = 0x02 Flow = 0x03 class ModeAdapter(Adapter): def _encode(self, obj, context): return obj.value() def _decode(self, obj, context): return LampMode(obj)