1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
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
83
85 return len(self.value)
86
88 """
89 Returns the size of the string.
90 """
91 return len(self)
92
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
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
135 return ''.join([str(x) for x in self])
136
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
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):
207
209 return pack(self.endianness + ("b" if self.signed else "B"), self.value)
210
212 return len(str(self))
213
215 """
216 Returns L{TYPE_BYTE}.
217 """
218 return TYPE_BYTE
219
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):
243
245 return pack(self.endianness + ("h" if self.signed else "H"), self.value)
246
248 return len(str(self))
249
251 """
252 Returns L{TYPE_WORD}.
253 """
254 return TYPE_WORD
255
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):
277
279 return pack(self.endianness + ("l" if self.signed else "L"), self.value)
280
282 return len(str(self))
283
285 """Returns L{TYPE_DWORD}."""
286 return TYPE_DWORD
287
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):
309
311 return pack(self.endianness + ("q" if self.signed else "Q"), self.value)
312
314 return len(str(self))
315
317 """Returns L{TYPE_QWORD}."""
318 return TYPE_QWORD
319
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