def read_properties(entry): stream = entry.get('properties') if stream is None: raise Exception("can not find properties") s = stream.open() # read the whole stream f = BytesIO(s.read()) byte_order = read_u8(f) if byte_order != 0x4c: raise NotImplementedError("be byteorder") version = read_u8(f) entry_count = read_u16le(f) props = [] for i in range(entry_count): pid = read_u16le(f) format = read_u16le(f) byte_size = read_u16le(f) props.append([pid, format, byte_size]) property_entries = {} for pid, format, byte_size in props: data = f.read(byte_size) property_entries[pid] = data return property_entries
def read_set_index(entry): s = entry.open('r') # read the whole of the index f = BytesIO(s.read()) count = read_u32le(f) next_free_key = read_u32le(f) last_free_key = read_u32le(f) key_pid = read_u16le(f) key_size = read_u8(f) assert key_size in (16, 32) references = [] for i in range(count): local_key = read_u32le(f) ref_count = read_u32le(f) # not sure if ref count is actually used # doesn't apear to be assert ref_count == 1 if key_size == 16: key = UUID(bytes_le=f.read(key_size)) else: key = mobid.MobID(bytes_le=f.read(key_size)) references.append((key, local_key)) # references[key] = local_key return references
def decode_weakref(data): f = BytesIO(data) weakref_index = read_u16le(f) key_pid = read_u16le(f) key_size = read_u8(f) assert key_size in (16, 32) if key_size == 16: ref = UUID(bytes_le=f.read(key_size)) else: ref = key = MobID(bytes_le=f.read(key_size)) return ref
def read_weakref_array_index(entry): s = entry.open('r') # read the whole index f = BytesIO(s.read()) count = read_u32le(f) weakref_index = read_u16le(f) key_pid = read_u16le(f) key_size = read_u8(f) assert key_size in (16, 32) references = [] for i in range(count): if key_size == 16: key = UUID(bytes_le=f.read(key_size)) else: key = key = MobID(bytes_le=f.read(key_size)) references.append(key) return references
def read_reference_properties(cfb): f = cfb.open("/referenced properties") byte_order = read_u8(f) if byte_order != 0x4c: raise NotImplementedError("be byteorder") path_count = read_u16le(f) pid_count = read_u32le(f) weakref_table = [] path = [] for i in range(pid_count): pid = read_u16le(f) if pid != 0: path.append(pid) else: weakref_table.append(path) path = [] assert len(weakref_table) == path_count return weakref_table
def read_typedef(entry, types): p = read_properties(entry) name = decode_utf16le(p[NAME_PID]) identification = UUID(bytes_le=p[IDENTIFICATION_PID]) types['all'][identification] = name # description = decode_utf16le(p[DESCRIPTION_PID]) # print(name, description) data = [identification] if entry.class_id == TypeDefInt: size = read_u8(BytesIO(p[TypeDefInt_Size])) signed = p[TypeDefInt_IsSigned] == b"\x01" data.extend([size, signed]) types['ints'][name] = data elif entry.class_id == TypeDefStrongRef: ref_type = decode_weakref(p[TypeDefStrongRef_ReferencedType]) data.extend([ref_type]) types['strongrefs'][name] = data elif entry.class_id == TypeDefWeakRef: ref_type = decode_weakref(p[TypeDefWeakRef_ReferencedType]) target_set = decode_auid_array(p[TypeDefWeakRef_TargetSet]) data.extend([ref_type, target_set]) types['weakrefs'][name] = data elif entry.class_id == TypeDefEnum: type = decode_weakref(p[TypeDefEnum_ElementType]) names = decode_utf16_array(p[TypeDefEnum_ElementNames]) # aafInt64Array values = p[TypeDefEnum_ElementValues] size = 8 elements = len(values) // size values = unpack('<%dq' % elements, values) data.extend([type, dict(zip(values, names))]) types['enums'][name] = data elif entry.class_id == TypeDefFixedArray: # aafUInt32 elements = read_u32le(BytesIO(p[TypeDefFixedArray_ElementCount])) type = decode_weakref(p[TypeDefFixedArray_ElementType]) data.extend([type, elements]) types['fixed_arrays'][name] = data elif entry.class_id == TypeDefVariableArray: type = decode_weakref(p[TypeDefVariableArray_ElementType]) data.extend([type]) types['var_arrays'][name] = data elif entry.class_id == TypeDefSet: type = decode_weakref(p[TypeDefSet_ElementType]) data.extend([type]) types['sets'][name] = data elif entry.class_id == TypeDefString: type = decode_weakref(p[TypeDefString_ElementType]) data.extend([type]) types['strings'][name] = data elif entry.class_id == TypeDefStream: types['streams'][name] = data elif entry.class_id == TypeDefRecord: member_names = decode_utf16_array(p[TypeDefRecord_MemberNames]) member_index_name = decode_utf16le(p[TypeDefRecord_MemberTypes]) member_types = read_weakref_array_index( entry.get(member_index_name + " index")) data.append(list(zip(member_names, member_types))) types['records'][name] = data elif entry.class_id == TypeDefRename: type = decode_weakref(p[TypeDefRename_RenamedType]) data.extend([type]) types['renames'][name] = data elif entry.class_id == TypeDefExtendibleEnum: element_values = decode_auid_array( p[TypeDefExtendibleEnum_ElementValues]) element_names = decode_utf16_array( p[TypeDefExtendibleEnum_ElementNames]) data.extend([dict(zip(element_values, element_names))]) types['extenums'][name] = data elif entry.class_id == TypeDefIndirect: types['indirects'][name] = data elif entry.class_id == TypeDefOpaque: types['opaques'][name] = data elif entry.class_id == TypeDefCharacter: types['chars'][name] = data else: raise ValueError("Unknown TypeDef: " + str(entry.class_id))