Locked History Actions

Custom

Custom

The Custom element is used to add custom data-types to Peach data models. Custom types require the writing of a python class that defines how the custom type is parsed, cracked, and generated.

<Custom name="mib" class="MyCustomType"/>

Attributes:

  • name -- Name of the data model [required]

  • ref -- Reference to a data model to use as a template [optional]

  • minOccurs -- The minimum number of times this block must occur

  • maxOccurs -- The maximum number of times this block can occur

  • value -- The default value contained within the Blob

  • valueType -- The format in which the default value is expressed. (i.e hex, string, or literal)

  • isStatic -- This element should be treated as a token when parsing, defaults to False [DEPRECATED] [optional]

  • token -- (Peach 2.3)This element should be treated as a token when parsing, defaults to False [optional]

  • mutable -- (Peach 2.3) Is data element changeable (should it be mutated), defaults to true [optional]

Valid Child-Elements:

  • ??? - All children are handled by the custom type

Python Code

'''
Custom type example
'''

from Peach.Engine.dom import *

class MultiByteInteger(Custom):
        '''
        A custom type
        '''
        
        def handleParsing(self, node):
                '''
                Handle any custom parsing of the XML such as
                attributes.
                '''
                pass
        
        def handleIncomingSize(self, node, data, pos, parent):
                '''
                Return initial read size for this type.
                '''
                
                # Always at least a single byte
                return (2,1)
        
        def handleIncoming(self, cntx, data, pos, parent, doingMinMax = False):
                '''
                Handle data cracking.
                '''
                
                try:
                        while(True):
                                i = struct.unpack("B", data[pos])[0]
                                pos += 1
                                if i & 0x80 == 0:
                                        break
                                
                                i &= 0x7F
                                
                                j = struct.unpack("B", data[pos])[0]
                                pos += 1
                                i |= (j & 0x7f) << 7
                                if j & 0x80 == 0:
                                        break
                                
                                k = struct.unpack("B", data[pos])[0]
                                pos += 1
                                i |= (k & 0x7f) << 14
                                if k & 0x80 == 0:
                                        break
                                
                                l = struct.unpack("B", data[pos])[0]
                                pos += 1
                                i |= (l & 0x7f) << 0x15
                                if l & 0x80 == 0:
                                        break
                                
                                m = struct.unpack("B", data[pos])[0]
                                pos += 1
                                i |= m << 0x1c
                                if m & 0xf8 != 0:
                                        # failed to parse...
                                        return (4, pos)
                                
                                break
                except:
                        raise
                        # out of data
                        if not cntx.haveAllData:
                                raise NeedMoreData(1, "")
                        else:
                                return (4, pos)
                
                value = str(i)
                eval("self.%s(value)" % cntx.method)
                
                return (2, pos)
        
        def getInternalValue(self, sout = None):
                '''
                Return the internal value of this date element.  This
                value comes before any modifications such as packing,
                padding, truncating, etc.
                
                For Numbers this is the python int value.
                '''
                
                value = None
                
                # Override value?
                if self.currentValue != None:
                        value = self.currentValue
                
                else:
                        # Default value
                        value = self.defaultValue
                        
                        # Relation
                        value = str(self.getRelationValue(value))
                        
                        # Fixup
                        if self.fixup != None:
                                self.fixup.fixup.context = self
                                ret = self.fixup.fixup.dofixup()
                                if ret != None:
                                        value = ret
                
                # Write to buffer
                if sout != None:
                        sout.write(value, self.getFullDataName())
                
                # Return value
                return value
        
        def getLength(self):
                '''
                Get the length of this element.
                '''
                
                return len(self.getValue())
        
        def getRawValue(self, sout = None):
                value = self.getInternalValue()
        
                # Apply mbint pack
                ret = ""
                i = long(value)
                while ((i & 0xffffff80L) != 0L):
                        ret += struct.pack("B", ((i & 0x7f) | 0x80))
                        i = i >> 7
                
                ret += struct.pack("B", i)
                
                # Write to buffer
                if sout != None:
                        sout.write(ret, self.getFullDataName())
                
                return ret

# end