1 /*
2 * Python object wrapper of libolecf_property_set_t
3 *
4 * Copyright (C) 2008-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <types.h>
24
25 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
26 #include <stdlib.h>
27 #endif
28
29 #include "pyolecf_error.h"
30 #include "pyolecf_guid.h"
31 #include "pyolecf_libcerror.h"
32 #include "pyolecf_libolecf.h"
33 #include "pyolecf_property_section.h"
34 #include "pyolecf_property_sections.h"
35 #include "pyolecf_property_set.h"
36 #include "pyolecf_python.h"
37 #include "pyolecf_unused.h"
38
39 PyMethodDef pyolecf_property_set_object_methods[] = {
40
41 { "get_class_identifier",
42 (PyCFunction) pyolecf_property_set_get_class_identifier,
43 METH_NOARGS,
44 "get_class_identifier() -> Unicode string or None\n"
45 "\n"
46 "Retrieves the class identifier." },
47
48 { "get_number_of_sections",
49 (PyCFunction) pyolecf_property_set_get_number_of_sections,
50 METH_NOARGS,
51 "get_number_of_sections() -> Integer or None\n"
52 "\n"
53 "Retrieves the number of sections." },
54
55 { "get_section",
56 (PyCFunction) pyolecf_property_set_get_section,
57 METH_VARARGS | METH_KEYWORDS,
58 "get_section(section_index) -> Object or None\n"
59 "\n"
60 "Retrieves the section specified by the index." },
61
62 /* Sentinel */
63 { NULL, NULL, 0, NULL }
64 };
65
66 PyGetSetDef pyolecf_property_set_object_get_set_definitions[] = {
67
68 { "class_identifier",
69 (getter) pyolecf_property_set_get_class_identifier,
70 (setter) 0,
71 "The class identifier.",
72 NULL },
73
74 { "number_of_sections",
75 (getter) pyolecf_property_set_get_number_of_sections,
76 (setter) 0,
77 "The number of sections.",
78 NULL },
79
80 { "sections",
81 (getter) pyolecf_property_set_get_sections,
82 (setter) 0,
83 "The sections.",
84 NULL },
85
86 /* Sentinel */
87 { NULL, NULL, NULL, NULL, NULL }
88 };
89
90 PyTypeObject pyolecf_property_set_type_object = {
91 PyVarObject_HEAD_INIT( NULL, 0 )
92
93 /* tp_name */
94 "pyolecf.property_set",
95 /* tp_basicsize */
96 sizeof( pyolecf_property_set_t ),
97 /* tp_itemsize */
98 0,
99 /* tp_dealloc */
100 (destructor) pyolecf_property_set_free,
101 /* tp_print */
102 0,
103 /* tp_getattr */
104 0,
105 /* tp_setattr */
106 0,
107 /* tp_compare */
108 0,
109 /* tp_repr */
110 0,
111 /* tp_as_number */
112 0,
113 /* tp_as_sequence */
114 0,
115 /* tp_as_mapping */
116 0,
117 /* tp_hash */
118 0,
119 /* tp_call */
120 0,
121 /* tp_str */
122 0,
123 /* tp_getattro */
124 0,
125 /* tp_setattro */
126 0,
127 /* tp_as_buffer */
128 0,
129 /* tp_flags */
130 Py_TPFLAGS_DEFAULT,
131 /* tp_doc */
132 "pyolecf property set object (wraps libolecf_property_set_t)",
133 /* tp_traverse */
134 0,
135 /* tp_clear */
136 0,
137 /* tp_richcompare */
138 0,
139 /* tp_weaklistoffset */
140 0,
141 /* tp_iter */
142 0,
143 /* tp_iternext */
144 0,
145 /* tp_methods */
146 pyolecf_property_set_object_methods,
147 /* tp_members */
148 0,
149 /* tp_getset */
150 pyolecf_property_set_object_get_set_definitions,
151 /* tp_base */
152 0,
153 /* tp_dict */
154 0,
155 /* tp_descr_get */
156 0,
157 /* tp_descr_set */
158 0,
159 /* tp_dictoffset */
160 0,
161 /* tp_init */
162 (initproc) pyolecf_property_set_init,
163 /* tp_alloc */
164 0,
165 /* tp_new */
166 0,
167 /* tp_free */
168 0,
169 /* tp_is_gc */
170 0,
171 /* tp_bases */
172 NULL,
173 /* tp_mro */
174 NULL,
175 /* tp_cache */
176 NULL,
177 /* tp_subclasses */
178 NULL,
179 /* tp_weaklist */
180 NULL,
181 /* tp_del */
182 0
183 };
184
185 /* Creates a new property set object
186 * Returns a Python object if successful or NULL on error
187 */
pyolecf_property_set_new(libolecf_property_set_t * property_set,PyObject * parent_object)188 PyObject *pyolecf_property_set_new(
189 libolecf_property_set_t *property_set,
190 PyObject *parent_object )
191 {
192 pyolecf_property_set_t *pyolecf_property_set = NULL;
193 static char *function = "pyolecf_property_set_new";
194
195 if( property_set == NULL )
196 {
197 PyErr_Format(
198 PyExc_ValueError,
199 "%s: invalid property set.",
200 function );
201
202 return( NULL );
203 }
204 /* PyObject_New does not invoke tp_init
205 */
206 pyolecf_property_set = PyObject_New(
207 struct pyolecf_property_set,
208 &pyolecf_property_set_type_object );
209
210 if( pyolecf_property_set == NULL )
211 {
212 PyErr_Format(
213 PyExc_MemoryError,
214 "%s: unable to initialize property set.",
215 function );
216
217 goto on_error;
218 }
219 pyolecf_property_set->property_set = property_set;
220 pyolecf_property_set->parent_object = parent_object;
221
222 if( pyolecf_property_set->parent_object != NULL )
223 {
224 Py_IncRef(
225 pyolecf_property_set->parent_object );
226 }
227 return( (PyObject *) pyolecf_property_set );
228
229 on_error:
230 if( pyolecf_property_set != NULL )
231 {
232 Py_DecRef(
233 (PyObject *) pyolecf_property_set );
234 }
235 return( NULL );
236 }
237
238 /* Initializes a property set object
239 * Returns 0 if successful or -1 on error
240 */
pyolecf_property_set_init(pyolecf_property_set_t * pyolecf_property_set)241 int pyolecf_property_set_init(
242 pyolecf_property_set_t *pyolecf_property_set )
243 {
244 static char *function = "pyolecf_property_set_init";
245
246 if( pyolecf_property_set == NULL )
247 {
248 PyErr_Format(
249 PyExc_ValueError,
250 "%s: invalid property set.",
251 function );
252
253 return( -1 );
254 }
255 /* Make sure libolecf property set is set to NULL
256 */
257 pyolecf_property_set->property_set = NULL;
258
259 PyErr_Format(
260 PyExc_NotImplementedError,
261 "%s: initialize of property set not supported.",
262 function );
263
264 return( -1 );
265 }
266
267 /* Frees a property set object
268 */
pyolecf_property_set_free(pyolecf_property_set_t * pyolecf_property_set)269 void pyolecf_property_set_free(
270 pyolecf_property_set_t *pyolecf_property_set )
271 {
272 struct _typeobject *ob_type = NULL;
273 libcerror_error_t *error = NULL;
274 static char *function = "pyolecf_property_set_free";
275 int result = 0;
276
277 if( pyolecf_property_set == NULL )
278 {
279 PyErr_Format(
280 PyExc_ValueError,
281 "%s: invalid property set.",
282 function );
283
284 return;
285 }
286 ob_type = Py_TYPE(
287 pyolecf_property_set );
288
289 if( ob_type == NULL )
290 {
291 PyErr_Format(
292 PyExc_ValueError,
293 "%s: missing ob_type.",
294 function );
295
296 return;
297 }
298 if( ob_type->tp_free == NULL )
299 {
300 PyErr_Format(
301 PyExc_ValueError,
302 "%s: invalid ob_type - missing tp_free.",
303 function );
304
305 return;
306 }
307 if( pyolecf_property_set->property_set != NULL )
308 {
309 Py_BEGIN_ALLOW_THREADS
310
311 result = libolecf_property_set_free(
312 &( pyolecf_property_set->property_set ),
313 &error );
314
315 Py_END_ALLOW_THREADS
316
317 if( result != 1 )
318 {
319 pyolecf_error_raise(
320 error,
321 PyExc_MemoryError,
322 "%s: unable to free libolecf property set.",
323 function );
324
325 libcerror_error_free(
326 &error );
327 }
328 }
329 if( pyolecf_property_set->parent_object != NULL )
330 {
331 Py_DecRef(
332 pyolecf_property_set->parent_object );
333 }
334 ob_type->tp_free(
335 (PyObject*) pyolecf_property_set );
336 }
337
338 /* Retrieves the class identifier
339 * Returns a Python object if successful or NULL on error
340 */
pyolecf_property_set_get_class_identifier(pyolecf_property_set_t * pyolecf_property_set,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)341 PyObject *pyolecf_property_set_get_class_identifier(
342 pyolecf_property_set_t *pyolecf_property_set,
343 PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
344 {
345 uint8_t guid_data[ 16 ];
346
347 PyObject *string_object = NULL;
348 libcerror_error_t *error = NULL;
349 static char *function = "pyolecf_property_set_get_class_identifier";
350 int result = 0;
351
352 PYOLECF_UNREFERENCED_PARAMETER( arguments )
353
354 if( pyolecf_property_set == NULL )
355 {
356 PyErr_Format(
357 PyExc_ValueError,
358 "%s: invalid property set.",
359 function );
360
361 return( NULL );
362 }
363 Py_BEGIN_ALLOW_THREADS
364
365 result = libolecf_property_set_get_class_identifier(
366 pyolecf_property_set->property_set,
367 guid_data,
368 16,
369 &error );
370
371 Py_END_ALLOW_THREADS
372
373 if( result == -1 )
374 {
375 pyolecf_error_raise(
376 error,
377 PyExc_IOError,
378 "%s: unable to retrieve class identifier.",
379 function );
380
381 libcerror_error_free(
382 &error );
383
384 return( NULL );
385 }
386 else if( result == 0 )
387 {
388 Py_IncRef(
389 Py_None );
390
391 return( Py_None );
392 }
393 string_object = pyolecf_string_new_from_guid(
394 guid_data,
395 16 );
396
397 return( string_object );
398 }
399
400 /* Retrieves the number of sections
401 * Returns a Python object if successful or NULL on error
402 */
pyolecf_property_set_get_number_of_sections(pyolecf_property_set_t * pyolecf_property_set,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)403 PyObject *pyolecf_property_set_get_number_of_sections(
404 pyolecf_property_set_t *pyolecf_property_set,
405 PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
406 {
407 PyObject *integer_object = NULL;
408 libcerror_error_t *error = NULL;
409 static char *function = "pyolecf_property_set_get_number_of_sections";
410 int number_of_sections = 0;
411 int result = 0;
412
413 PYOLECF_UNREFERENCED_PARAMETER( arguments )
414
415 if( pyolecf_property_set == NULL )
416 {
417 PyErr_Format(
418 PyExc_ValueError,
419 "%s: invalid property set.",
420 function );
421
422 return( NULL );
423 }
424 Py_BEGIN_ALLOW_THREADS
425
426 result = libolecf_property_set_get_number_of_sections(
427 pyolecf_property_set->property_set,
428 &number_of_sections,
429 &error );
430
431 Py_END_ALLOW_THREADS
432
433 if( result != 1 )
434 {
435 pyolecf_error_raise(
436 error,
437 PyExc_IOError,
438 "%s: unable to retrieve number of sections.",
439 function );
440
441 libcerror_error_free(
442 &error );
443
444 return( NULL );
445 }
446 #if PY_MAJOR_VERSION >= 3
447 integer_object = PyLong_FromLong(
448 (long) number_of_sections );
449 #else
450 integer_object = PyInt_FromLong(
451 (long) number_of_sections );
452 #endif
453 return( integer_object );
454 }
455
456 /* Retrieves a specific section by index
457 * Returns a Python object if successful or NULL on error
458 */
pyolecf_property_set_get_section_by_index(PyObject * pyolecf_property_set,int section_index)459 PyObject *pyolecf_property_set_get_section_by_index(
460 PyObject *pyolecf_property_set,
461 int section_index )
462 {
463 PyObject *section_object = NULL;
464 libcerror_error_t *error = NULL;
465 libolecf_property_section_t *section = NULL;
466 static char *function = "pyolecf_property_set_get_section_by_index";
467 int result = 0;
468
469 if( pyolecf_property_set == NULL )
470 {
471 PyErr_Format(
472 PyExc_ValueError,
473 "%s: invalid property set.",
474 function );
475
476 return( NULL );
477 }
478 Py_BEGIN_ALLOW_THREADS
479
480 result = libolecf_property_set_get_section_by_index(
481 ( (pyolecf_property_set_t *) pyolecf_property_set )->property_set,
482 section_index,
483 §ion,
484 &error );
485
486 Py_END_ALLOW_THREADS
487
488 if( result != 1 )
489 {
490 pyolecf_error_raise(
491 error,
492 PyExc_IOError,
493 "%s: unable to retrieve section: %d.",
494 function,
495 section_index );
496
497 libcerror_error_free(
498 &error );
499
500 goto on_error;
501 }
502 section_object = pyolecf_property_section_new(
503 section,
504 (PyObject *) pyolecf_property_set );
505
506 if( section_object == NULL )
507 {
508 PyErr_Format(
509 PyExc_MemoryError,
510 "%s: unable to create property section object.",
511 function );
512
513 goto on_error;
514 }
515 return( section_object );
516
517 on_error:
518 if( section != NULL )
519 {
520 libolecf_property_section_free(
521 §ion,
522 NULL );
523 }
524 return( NULL );
525 }
526
527 /* Retrieves a specific section
528 * Returns a Python object if successful or NULL on error
529 */
pyolecf_property_set_get_section(pyolecf_property_set_t * pyolecf_property_set,PyObject * arguments,PyObject * keywords)530 PyObject *pyolecf_property_set_get_section(
531 pyolecf_property_set_t *pyolecf_property_set,
532 PyObject *arguments,
533 PyObject *keywords )
534 {
535 PyObject *section_object = NULL;
536 static char *keyword_list[] = { "section_index", NULL };
537 int section_index = 0;
538
539 if( PyArg_ParseTupleAndKeywords(
540 arguments,
541 keywords,
542 "i",
543 keyword_list,
544 §ion_index ) == 0 )
545 {
546 return( NULL );
547 }
548 section_object = pyolecf_property_set_get_section_by_index(
549 (PyObject *) pyolecf_property_set,
550 section_index );
551
552 return( section_object );
553 }
554
555 /* Retrieves a sequence and iterator object for the sections
556 * Returns a Python object if successful or NULL on error
557 */
pyolecf_property_set_get_sections(pyolecf_property_set_t * pyolecf_property_set,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)558 PyObject *pyolecf_property_set_get_sections(
559 pyolecf_property_set_t *pyolecf_property_set,
560 PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
561 {
562 PyObject *sequence_object = NULL;
563 libcerror_error_t *error = NULL;
564 static char *function = "pyolecf_property_set_get_sections";
565 int number_of_sections = 0;
566 int result = 0;
567
568 PYOLECF_UNREFERENCED_PARAMETER( arguments )
569
570 if( pyolecf_property_set == NULL )
571 {
572 PyErr_Format(
573 PyExc_ValueError,
574 "%s: invalid property set.",
575 function );
576
577 return( NULL );
578 }
579 Py_BEGIN_ALLOW_THREADS
580
581 result = libolecf_property_set_get_number_of_sections(
582 pyolecf_property_set->property_set,
583 &number_of_sections,
584 &error );
585
586 Py_END_ALLOW_THREADS
587
588 if( result != 1 )
589 {
590 pyolecf_error_raise(
591 error,
592 PyExc_IOError,
593 "%s: unable to retrieve number of sections.",
594 function );
595
596 libcerror_error_free(
597 &error );
598
599 return( NULL );
600 }
601 sequence_object = pyolecf_property_sections_new(
602 (PyObject *) pyolecf_property_set,
603 &pyolecf_property_set_get_section_by_index,
604 number_of_sections );
605
606 if( sequence_object == NULL )
607 {
608 pyolecf_error_raise(
609 error,
610 PyExc_MemoryError,
611 "%s: unable to create sequence object.",
612 function );
613
614 return( NULL );
615 }
616 return( sequence_object );
617 }
618
619