Beispiel #1
0
 def writeOffsetTable(self, output):
     """Writes all of the object reference offsets."""
     all_positions = []
     writtenReferences = list(self.writtenReferences.items())
     writtenReferences.sort(key=lambda x: x[1])
     for obj,order in writtenReferences:
         # Porting note: Elsewhere we deliberately replace empty unicdoe strings
         # with empty binary strings, but the empty unicode string
         # goes into writtenReferences.  This isn't an issue in Py2
         # because u'' and b'' have the same hash; but it is in
         # Py3, where they don't.
         if six.PY3 and obj == six.u(''):
             obj = six.b('')
         position = self.referencePositions.get(obj)
         if position is None:
             raise InvalidPlistException("Error while writing offsets table. Object not found. %s" % obj)
         output += self.binaryInt(position, self.trailer.offsetSize)
         all_positions.append(position)
     return output
Beispiel #2
0
 def writeObject(self, obj, output, setReferencePosition=False):
     """Serializes the given object to the output. Returns output.
        If setReferencePosition is True, will set the position the
        object was written.
     """
     def proc_variable_length(format, length):
         result = six.b('')
         if length > 0b1110:
             result += pack('!B', (format << 4) | 0b1111)
             result = self.writeObject(length, result)
         else:
             result += pack('!B', (format << 4) | length)
         return result
     
     if isinstance(obj, six.text_type) and obj == six.u(''):
         # The Apple Plist decoder can't decode a zero length Unicode string.
         obj = six.b('')
    
     if setReferencePosition:
         self.referencePositions[obj] = len(output)
     
     if obj is None:
         output += pack('!B', 0b00000000)
     elif isinstance(obj, BoolWrapper):
         if obj.value is False:
             output += pack('!B', 0b00001000)
         else:
             output += pack('!B', 0b00001001)
     elif isinstance(obj, Uid):
         size = self.intSize(obj)
         output += pack('!B', (0b1000 << 4) | size - 1)
         output += self.binaryInt(obj)
     elif isinstance(obj, six.integer_types):
         bytes = self.intSize(obj)
         root = math.log(bytes, 2)
         output += pack('!B', (0b0001 << 4) | int(root))
         output += self.binaryInt(obj)
     elif isinstance(obj, float):
         # just use doubles
         output += pack('!B', (0b0010 << 4) | 3)
         output += self.binaryReal(obj)
     elif isinstance(obj, datetime.datetime):
         timestamp = calendar.timegm(obj.utctimetuple())
         timestamp -= apple_reference_date_offset
         output += pack('!B', 0b00110011)
         output += pack('!d', float(timestamp))
     elif isinstance(obj, Data):
         output += proc_variable_length(0b0100, len(obj))
         output += obj
     elif isinstance(obj, six.text_type):
         bytes = obj.encode('utf_16_be')
         output += proc_variable_length(0b0110, len(bytes)//2)
         output += bytes
     elif isinstance(obj, six.binary_type):
         bytes = obj
         output += proc_variable_length(0b0101, len(bytes))
         output += bytes
     elif isinstance(obj, HashableWrapper):
         obj = obj.value
         if isinstance(obj, (set, list, tuple)):
             if isinstance(obj, set):
                 output += proc_variable_length(0b1100, len(obj))
             else:
                 output += proc_variable_length(0b1010, len(obj))
         
             objectsToWrite = []
             for objRef in obj:
                 (isNew, output) = self.writeObjectReference(objRef, output)
                 if isNew:
                     objectsToWrite.append(objRef)
             for objRef in objectsToWrite:
                 output = self.writeObject(objRef, output, setReferencePosition=True)
         elif isinstance(obj, dict):
             output += proc_variable_length(0b1101, len(obj))
             keys = []
             values = []
             objectsToWrite = []
             for key, value in six.iteritems(obj):
                 keys.append(key)
                 values.append(value)
             for key in keys:
                 (isNew, output) = self.writeObjectReference(key, output)
                 if isNew:
                     objectsToWrite.append(key)
             for value in values:
                 (isNew, output) = self.writeObjectReference(value, output)
                 if isNew:
                     objectsToWrite.append(value)
             for objRef in objectsToWrite:
                 output = self.writeObject(objRef, output, setReferencePosition=True)
     return output