Package pype32 :: Module datatypes |
[hide private]
[frames] | no frames]

# Source Code for Module pype32.datatypes

      1  #!/usr/bin/python
      2  # -*- coding: utf-8 -*-
      3
      4  # Copyright (c) 2013, Nahuel Riva
      5  # All rights reserved.
      6  #
      7  # Redistribution and use in source and binary forms, with or without
      8  # modification, are permitted provided that the following conditions are met:
      9  #
     10  #     * Redistributions of source code must retain the above copyright notice,
     11  #       this list of conditions and the following disclaimer.
     12  #     * Redistributions in binary form must reproduce the above copyright
     13  #       notice,this list of conditions and the following disclaimer in the
     14  #       documentation and/or other materials provided with the distribution.
     15  #     * Neither the name of the copyright holder nor the names of its
     16  #       contributors may be used to endorse or promote products derived from
     17  #       this software without specific prior written permission.
     18  #
     19  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     20  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     23  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  # POSSIBILITY OF SUCH DAMAGE.
     30
     31  """
     32  Data types objects.
     33
     34  @group Strings:
     35      String, AlignedString
     36
     37  @group Native:
     38      BYTE, WORD, DWORD, QWORD, Array
     39  """
     40
     41  __revision__ = "$Id$"
     42
     43  __all__ = [
     44             "String",
     45             "AlignedString",
     46             "BYTE",
     47             "WORD",
     48             "DWORD",
     49             "QWORD",
     50             "Array",
     51             ]
     52
     53  import utils
     54  import excep
     55
     56  from baseclasses import DataTypeBaseClass
     57  from struct import pack,  unpack
     58
     59  TYPE_QWORD = 0xFECAFECA
     60  TYPE_DWORD = 0xDEADBEEF
     61  TYPE_WORD = 0xCAFECAFE
     62  TYPE_BYTE = 0xC00FEE
     63  TYPE_ARRAY = 0xFECA
     64  UNKNOWN_ARRAY_TYPE = 0xFFFF
     65
     66 -class String(object):
     67      """String object."""
     68 -    def __init__(self, value = "", shouldPack = True):
     69          """
     70          @type value: str
     71          @param value: the string to be built.
     72
     73          @type shouldPack: bool
     74          @param shouldPack: (Optional) If set to c{True}, the object will be packed. If set to C{False}, the object won't be packed.
     75
     76          @todo: Add a UnicodeString class.
     77          """
     78          self.value = value
     79          self.shouldPack = shouldPack
     80
     81 -    def __str__(self):
     82          return self.value
     83
     84 -    def __len__(self):
     85          return len(self.value)
     86
     87 -    def sizeof(self):
     88          """
     89          Returns the size of the string.
     90          """
     91          return len(self)
     92
     93 -class AlignedString(String):
     94      """Aligned string object."""
     95 -    def __init__(self, value, shouldPack = True, align = 4):
     96          """
     97          This object represent an aligned ASCII string.
     98
     99          @type value: str
    100          @param value: The string to be built.
    101
    102          @type shouldPack: bool
    103          @param shouldPack: (Optional) If set to c{True}, the object will be packed. If set to C{False}, the object won't be packed.
    104
    105          @type align: int
    106          @param align: (Optional) The alignment to be used. The default alignment is 4.
    107          """
    108          String.__init__(self,  value)
    109
    110          self.align = align
    111          self.value = value + "\x00" * (self.align - len(value) % self.align)
    112          self.shouldPack = shouldPack
    113
    114 -class Array(list):
    115      """Array object."""
    116 -    def __init__(self, arrayType,  shouldPack = True):
    117          """
    118          @type arrayType: int
    119          @param arrayType: The type of array to be built. This value can be C{TYPE_BYTE}, C{TYPE_WORD}, C{TYPE_DWORD} or C{TYPE_QWORD}.
    120
    121          @type shouldPack: bool
    122          @param shouldPack: (Optional) If set to c{True}, the object will be packed. If set to C{False}, the object won't be packed.
    123
    124          @todo: Before to add an element to the array we must check if the type of that element is one we are expecting.
    125          """
    126          list.__init__(self)
    127
    128          self.arrayType = arrayType
    129          self.shouldPack = shouldPack
    130
    131          if not self.arrayType in [TYPE_BYTE,  TYPE_WORD,  TYPE_DWORD,  TYPE_QWORD]:
    132              raise TypeError("Couldn\'t create an Array of type %r" % self.arrayType)
    133
    134 -    def __str__(self):
    135          return ''.join([str(x) for x in self])
    136
    137 -    def sizeof(self):
    138          """
    139          Returns the size of the array.
    140          """
    141          return len(self)
    142
    143      @staticmethod
    144 -    def parse(readDataInstance,  arrayType,  arrayLength):
    145          """
    146          Returns a new L{Array} object.
    147
    148          @type readDataInstance: L{ReadData}
    149          @param readDataInstance: The L{ReadData} object containing the array data.
    150
    151          @type arrayType: int
    152          @param arrayType: The type of L{Array} to be built.
    153
    154          @type arrayLength: int
    155          @param arrayLength: The length of the array passed as an argument.
    156
    157          @rtype: L{Array}
    158          @return: New L{Array} object.
    159          """
    160          newArray = Array(arrayType)
    161
    162          dataLength = len(readDataInstance)
    163
    164          if arrayType is TYPE_DWORD:
    165              toRead = arrayLength * 4
    166              if dataLength >= toRead:
    167                  for i in range(arrayLength):
    168                      newArray.append(DWORD(readDataInstance.readDword()))
    169              else:
    170                  raise excep.DataLengthException("Not enough bytes to read.")
    171
    172          elif arrayType is TYPE_WORD:
    173              toRead = arrayLength * 2
    174              if dataLength >= toRead:
    175                  for i in range(arrayLength):
    176                      newArray.append(DWORD(readDataInstance.readWord()))
    177              else:
    178                  raise excep.DataLengthException("Not enough bytes to read.")
    179
    180          elif arrayType is TYPE_QWORD:
    181              toRead = arrayLength * 8
    182              if dataLength >= toRead:
    183                  for i in range(arrayLength):
    184                      newArray.append(QWORD(readDataInstance.readQword()))
    185              else:
    186                  raise excep.DataLengthException("Not enough bytes to read.")
    187
    188          elif arrayType is TYPE_BYTE:
    189              for i in range(arrayLength):
    190                  newArray.append(BYTE(readDataInstance.readByte()))
    191
    192          else:
    193              raise ArrayTypeException("Could\'t create an array of type %d" % arrayType)
    194
    195          return newArray
    196
    197 -    def getType(self):
    198          """
    199          Returns an integer value identifying the type of object.
    200          """
    201          return TYPE_ARRAY
    202
    203 -class BYTE(DataTypeBaseClass):
    204      """Byte object."""
    205 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    206          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    207
    208 -    def __str__(self):
    209          return pack(self.endianness  + ("b" if self.signed else "B"),  self.value)
    210
    211 -    def __len__(self):
    212          return len(str(self))
    213
    214 -    def getType(self):
    215          """
    216          Returns L{TYPE_BYTE}.
    217          """
    218          return TYPE_BYTE
    219
    220 -    def sizeof(self):
    221          """
    222          Returns the size of L{BYTE}.
    223          """
    224          return len(self)
    225
    226      @staticmethod
    227 -    def parse(readDataInstance):
    228          """
    229          Returns a new L{BYTE} object.
    230
    231          @type readDataInstance: L{ReadData}
    232          @param readDataInstance: A L{ReadData} object with the corresponding data to generate a new L{BYTE} object.
    233
    234          @rtype: L{BYTE}
    235          @return: A new L{BYTE} object.
    236          """
    237          return BYTE(readDataInstance.readByte())
    238
    239 -class WORD(DataTypeBaseClass):
    240      """Word object."""
    241 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    242          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    243
    244 -    def __str__(self):
    245          return pack(self.endianness + ("h" if self.signed else "H"),  self.value)
    246
    247 -    def __len__(self):
    248          return len(str(self))
    249
    250 -    def getType(self):
    251          """
    252          Returns L{TYPE_WORD}.
    253          """
    254          return TYPE_WORD
    255
    256 -    def sizeof(self):
    257          """Returns the size of L{WORD}."""
    258          return len(self)
    259
    260      @staticmethod
    261 -    def parse(readDataInstance):
    262          """
    263          Returns a new L{WORD} object.
    264
    265          @type readDataInstance: L{ReadData}
    266          @param readDataInstance: A L{ReadData} object containing the necessary data to build a new L{WORD} object.
    267
    268          @rtype: L{WORD}
    269          @return: A new L{WORD} object.
    270          """
    271          return WORD(readDataInstance.readWord())
    272
    273 -class DWORD(DataTypeBaseClass):
    274      """Dword object."""
    275 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    276          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    277
    278 -    def __str__(self):
    279          return pack(self.endianness  + ("l" if self.signed else "L"),  self.value)
    280
    281 -    def __len__(self):
    282          return len(str(self))
    283
    284 -    def getType(self):
    285          """Returns L{TYPE_DWORD}."""
    286          return TYPE_DWORD
    287
    288 -    def sizeof(self):
    289          """Returns the size of L{DWORD}."""
    290          return len(self)
    291
    292      @staticmethod
    293 -    def parse(readDataInstance):
    294          """
    295          Returns a new L{DWORD} object.
    296
    297          @type readDataInstance: L{ReadData}
    298          @param readDataInstance: A L{ReadData} object with the necessary data to build a new L{DWORD} object.
    299
    300          @rtype: L{DWORD}
    301          @return: A new L{DWORD} object.
    302          """
    303          return DWORD(readDataInstance.readDword())
    304
    305 -class QWORD(DataTypeBaseClass):
    306      """Qword object."""
    307 -    def __init__(self,  value = 0,  endianness = "<",  signed = False,  shouldPack = True):
    308          DataTypeBaseClass.__init__(self, value, endianness, signed, shouldPack)
    309
    310 -    def __str__(self):
    311          return pack(self.endianness + ("q" if self.signed else "Q"),  self.value)
    312
    313 -    def __len__(self):
    314          return len(str(self))
    315
    316 -    def getType(self):
    317          """Returns L{TYPE_QWORD}."""
    318          return TYPE_QWORD
    319
    320 -    def sizeof(self):
    321          """Returns the size of L{QWORD}."""
    322          return len(self)
    323
    324      @staticmethod
    325 -    def parse(readDataInstance):
    326          """
    327          Returns a new L{QWORD} object.
    328
    329          @type readDataInstance: L{ReadData}
    330          @param readDataInstance: A L{ReadData} object with the necessary data to build a new L{QWORD} object.
    331
    332          @rtype: L{QWORD}
    333          @return: A new L{QWORD} object.
    334          """
    335          return QWORD(readDataInstance.readQword())
    336