Skip to content

Commit

Permalink
Fixes farcaller#10 - Make sure object header is an int
Browse files Browse the repository at this point in the history
Also removes trailing whitespace

farcaller#10
  • Loading branch information
unformatt committed Nov 18, 2020
1 parent 0cd8c10 commit 64eeadd
Showing 1 changed file with 37 additions and 29 deletions.
66 changes: 37 additions & 29 deletions bplist/bplist.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,27 @@ class BPListWriter(object):
def __init__(self, objects):
self.bplist = ""
self.objects = objects

def binary(self):
'''binary -> string
Generates bplist
'''
self.data = 'bplist00'

# TODO: flatten objects and count max length size

# TODO: write objects and save offsets

# TODO: write offsets

# TODO: write metadata

return self.data

def write(self, filename):
'''
Writes bplist to file
'''
if self.bplist != "":
Expand All @@ -62,10 +62,18 @@ def __init__(self, s):
self.data = s
self.objects = []
self.resolved = {}


def __getObjHeader(self, offset):
obj_header = self.data[offset]

if type(obj_header) == str:
obj_header = ord(obj_header)

return obj_header

def __unpackIntStruct(self, sz, s):
'''__unpackIntStruct(size, string) -> int
Unpacks the integer of given size (1, 2 or 4 bytes) from string
'''
if sz == 1:
Expand All @@ -79,27 +87,27 @@ def __unpackIntStruct(self, sz, s):
else:
raise Exception('int unpack size '+str(sz)+' unsupported')
return struct.unpack(ot, s)[0]

def __unpackInt(self, offset):
'''__unpackInt(offset) -> int
Unpacks int field from plist at given offset
'''
return self.__unpackIntMeta(offset)[1]

def __unpackIntMeta(self, offset):
'''__unpackIntMeta(offset) -> (size, int)
Unpacks int field from plist at given offset and returns its size and value
'''
obj_header = self.data[offset]
obj_header = self.__getObjHeader(offset)
obj_type, obj_info = (obj_header & 0xF0), (obj_header & 0x0F)
int_sz = 2**obj_info
return int_sz, self.__unpackIntStruct(int_sz, self.data[offset+1:offset+1+int_sz])

def __resolveIntSize(self, obj_info, offset):
'''__resolveIntSize(obj_info, offset) -> (count, offset)
Calculates count of objref* array entries and returns count and offset to first element
'''
if obj_info == 0x0F:
Expand All @@ -112,7 +120,7 @@ def __resolveIntSize(self, obj_info, offset):

def __unpackFloatStruct(self, sz, s):
'''__unpackFloatStruct(size, string) -> float
Unpacks the float of given size (4 or 8 bytes) from string
'''
if sz == 4:
Expand All @@ -125,10 +133,10 @@ def __unpackFloatStruct(self, sz, s):

def __unpackFloat(self, offset):
'''__unpackFloat(offset) -> float
Unpacks float field from plist at given offset
'''
obj_header = self.data[offset]
obj_header = self.__getObjHeader(offset)
obj_type, obj_info = (obj_header & 0xF0), (obj_header & 0x0F)
int_sz = 2**obj_info
return int_sz, self.__unpackFloatStruct(int_sz, self.data[offset+1:offset+1+int_sz])
Expand All @@ -139,10 +147,10 @@ def __unpackDate(self, offset):

def __unpackItem(self, offset):
'''__unpackItem(offset)
Unpacks and returns an item from plist
'''
obj_header = self.data[offset]
obj_header = self.__getObjHeader(offset)
obj_type, obj_info = (obj_header & 0xF0), (obj_header & 0x0F)
if obj_type == 0x00:
if obj_info == 0x00: # null 0000 0000
Expand Down Expand Up @@ -198,7 +206,7 @@ def __unpackItem(self, offset):
return dic
else:
raise Exception('don\'t know how to unpack obj type '+hex(obj_type)+' at '+str(offset))

def __resolveObject(self, idx):
try:
return self.resolved[idx]
Expand All @@ -225,16 +233,16 @@ def __resolveObject(self, idx):
else:
self.resolved[idx] = obj
return obj

def parse(self):
# read header
if self.data[:8] != b'bplist00':
raise Exception('Bad magic')

# read trailer
self.offset_size, self.object_ref_size, self.number_of_objects, self.top_object, self.table_offset = struct.unpack('!6xBB4xI4xI4xI', self.data[-32:])
#print "** plist offset_size:",self.offset_size,"objref_size:",self.object_ref_size,"num_objs:",self.number_of_objects,"top:",self.top_object,"table_ofs:",self.table_offset

# read offset table
self.offset_table = self.data[self.table_offset:-32]
self.offsets = []
Expand All @@ -244,7 +252,7 @@ def parse(self):
ot = ot[self.offset_size:]
self.offsets.append(self.__unpackIntStruct(self.offset_size, offset_entry))
#print "** plist offsets:",self.offsets

# read object table
self.objects = []
k = 0
Expand All @@ -253,14 +261,14 @@ def parse(self):
#print "** plist unpacked",k,type(obj),obj,"at",i
k += 1
self.objects.append(obj)

# rebuild object tree
#for i in range(len(self.objects)):
# self.__resolveObject(i)

# return root object
return self.__resolveObject(self.top_object)

@classmethod
def plistWithString(cls, s):
parser = cls(s)
Expand Down

0 comments on commit 64eeadd

Please sign in to comment.