1 /*
2  * Python object wrapper of libfwsi_item_t
3  *
4  * Copyright (C) 2010-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 <narrow_string.h>
24 #include <types.h>
25 
26 #if defined( HAVE_STDLIB_H )
27 #include <stdlib.h>
28 #endif
29 
30 #include "pyfwsi_error.h"
31 #include "pyfwsi_extension_block.h"
32 #include "pyfwsi_extension_blocks.h"
33 #include "pyfwsi_file_entry_extension.h"
34 #include "pyfwsi_item.h"
35 #include "pyfwsi_item_list.h"
36 #include "pyfwsi_libcerror.h"
37 #include "pyfwsi_libclocale.h"
38 #include "pyfwsi_libfwsi.h"
39 #include "pyfwsi_python.h"
40 #include "pyfwsi_unused.h"
41 
42 PyMethodDef pyfwsi_item_object_methods[] = {
43 
44 	{ "copy_from_byte_stream",
45 	  (PyCFunction) pyfwsi_item_copy_from_byte_stream,
46 	  METH_VARARGS | METH_KEYWORDS,
47 	  "copy_from_byte_stream(byte_stream, ascii_codepage=cp1252)\n"
48 	  "\n"
49 	  "Copies the the item from the byte stream." },
50 
51 	/* Functions to access the item data */
52 
53 	{ "get_class_type",
54 	  (PyCFunction) pyfwsi_item_get_class_type,
55 	  METH_NOARGS,
56 	  "get_class_type() -> Integer\n"
57 	  "\n"
58 	  "Returns the class type." },
59 
60 	{ "get_data_size",
61 	  (PyCFunction) pyfwsi_item_get_data_size,
62 	  METH_NOARGS,
63 	  "get_data_size() -> Integer\n"
64 	  "\n"
65 	  "Returns the size of the item data." },
66 
67 #ifdef TODO
68 	{ "get_data",
69 	  (PyCFunction) pyfwsi_item_get_data,
70 	  METH_NOARGS,
71 	  "get_data() -> String or None\n"
72 	  "\n"
73 	  "Returns the item data." },
74 #endif
75 
76 	/* Functions to access the extension blocks */
77 
78 	{ "get_number_of_extension_blocks",
79 	  (PyCFunction) pyfwsi_item_get_number_of_extension_blocks,
80 	  METH_NOARGS,
81 	  "get_number_of_extension_blocks() -> Integer\n"
82 	  "\n"
83 	  "Retrieves the number of extension blocks." },
84 
85 	{ "get_extension_block",
86 	  (PyCFunction) pyfwsi_item_get_extension_block,
87 	  METH_VARARGS | METH_KEYWORDS,
88 	  "get_extension_block(extension_block_index) -> Object\n"
89 	  "\n"
90 	  "Retrieves a specific extension block." },
91 
92 	/* Sentinel */
93 	{ NULL, NULL, 0, NULL }
94 };
95 
96 PyGetSetDef pyfwsi_item_object_get_set_definitions[] = {
97 
98 	{ "class_type",
99 	  (getter) pyfwsi_item_get_class_type,
100 	  (setter) 0,
101 	  "The class type.",
102 	  NULL },
103 
104 	{ "data_size",
105 	  (getter) pyfwsi_item_get_data_size,
106 	  (setter) 0,
107 	  "The size of the item data.",
108 	  NULL },
109 
110 #ifdef TODO
111 	{ "data",
112 	  (getter) pyfwsi_item_get_data,
113 	  (setter) 0,
114 	  "The item data.",
115 	  NULL },
116 #endif
117 
118 	{ "number_of_extension_blocks",
119 	  (getter) pyfwsi_item_get_number_of_extension_blocks,
120 	  (setter) 0,
121 	  "The number of extension blocks.",
122 	  NULL },
123 
124 	{ "extension_blocks",
125 	  (getter) pyfwsi_item_get_extension_blocks,
126 	  (setter) 0,
127 	  "The extension blocks",
128 	  NULL },
129 
130 	/* Sentinel */
131 	{ NULL, NULL, NULL, NULL, NULL }
132 };
133 
134 PyTypeObject pyfwsi_item_type_object = {
135 	PyVarObject_HEAD_INIT( NULL, 0 )
136 
137 	/* tp_name */
138 	"pyfwsi.item",
139 	/* tp_basicsize */
140 	sizeof( pyfwsi_item_t ),
141 	/* tp_itemsize */
142 	0,
143 	/* tp_dealloc */
144 	(destructor) pyfwsi_item_free,
145 	/* tp_print */
146 	0,
147 	/* tp_getattr */
148 	0,
149 	/* tp_setattr */
150 	0,
151 	/* tp_compare */
152 	0,
153 	/* tp_repr */
154 	0,
155 	/* tp_as_number */
156 	0,
157 	/* tp_as_sequence */
158 	0,
159 	/* tp_as_mapping */
160 	0,
161 	/* tp_hash */
162 	0,
163 	/* tp_call */
164 	0,
165 	/* tp_str */
166 	0,
167 	/* tp_getattro */
168 	0,
169 	/* tp_setattro */
170 	0,
171 	/* tp_as_buffer */
172 	0,
173 	/* tp_flags */
174 	Py_TPFLAGS_DEFAULT,
175 	/* tp_doc */
176 	"pyfwsi item object (wraps libfwsi_item_t)",
177 	/* tp_traverse */
178 	0,
179 	/* tp_clear */
180 	0,
181 	/* tp_richcompare */
182 	0,
183 	/* tp_weaklistoffset */
184 	0,
185 	/* tp_iter */
186 	0,
187 	/* tp_iternext */
188 	0,
189 	/* tp_methods */
190 	pyfwsi_item_object_methods,
191 	/* tp_members */
192 	0,
193 	/* tp_getset */
194 	pyfwsi_item_object_get_set_definitions,
195 	/* tp_base */
196 	0,
197 	/* tp_dict */
198 	0,
199 	/* tp_descr_get */
200 	0,
201 	/* tp_descr_set */
202 	0,
203 	/* tp_dictoffset */
204 	0,
205 	/* tp_init */
206 	(initproc) pyfwsi_item_init,
207 	/* tp_alloc */
208 	0,
209 	/* tp_new */
210 	0,
211 	/* tp_free */
212 	0,
213 	/* tp_is_gc */
214 	0,
215 	/* tp_bases */
216 	NULL,
217 	/* tp_mro */
218 	NULL,
219 	/* tp_cache */
220 	NULL,
221 	/* tp_subclasses */
222 	NULL,
223 	/* tp_weaklist */
224 	NULL,
225 	/* tp_del */
226 	0
227 };
228 
229 /* Creates a new pyfwsi item object
230  * Returns a Python object if successful or NULL on error
231  */
pyfwsi_item_new(PyTypeObject * type_object,libfwsi_item_t * item,PyObject * parent_object)232 PyObject *pyfwsi_item_new(
233            PyTypeObject *type_object,
234            libfwsi_item_t *item,
235            PyObject *parent_object )
236 {
237 	pyfwsi_item_t *pyfwsi_item = NULL;
238 	static char *function      = "pyfwsi_item_new";
239 
240 	if( item == NULL )
241 	{
242 		PyErr_Format(
243 		 PyExc_TypeError,
244 		 "%s: invalid item.",
245 		 function );
246 
247 		return( NULL );
248 	}
249 	pyfwsi_item = PyObject_New(
250 	               struct pyfwsi_item,
251 	               type_object );
252 
253 	if( pyfwsi_item == NULL )
254 	{
255 		PyErr_Format(
256 		 PyExc_MemoryError,
257 		 "%s: unable to initialize item.",
258 		 function );
259 
260 		goto on_error;
261 	}
262 	pyfwsi_item->item          = item;
263 	pyfwsi_item->parent_object = parent_object;
264 
265 	Py_IncRef(
266 	 (PyObject *) pyfwsi_item->parent_object );
267 
268 	return( (PyObject *) pyfwsi_item );
269 
270 on_error:
271 	if( pyfwsi_item != NULL )
272 	{
273 		Py_DecRef(
274 		 (PyObject *) pyfwsi_item );
275 	}
276 	return( NULL );
277 }
278 
279 /* Initializes an item object
280  * Returns 0 if successful or -1 on error
281  */
pyfwsi_item_init(pyfwsi_item_t * pyfwsi_item)282 int pyfwsi_item_init(
283      pyfwsi_item_t *pyfwsi_item )
284 {
285 	libcerror_error_t *error = NULL;
286 	static char *function    = "pyfwsi_item_init";
287 
288 	if( pyfwsi_item == NULL )
289 	{
290 		PyErr_Format(
291 		 PyExc_TypeError,
292 		 "%s: invalid item.",
293 		 function );
294 
295 		return( -1 );
296 	}
297 	pyfwsi_item->item          = NULL;
298 	pyfwsi_item->parent_object = NULL;
299 
300 	if( libfwsi_item_initialize(
301 	     &( pyfwsi_item->item ),
302 	     &error ) != 1 )
303 	{
304 		pyfwsi_error_raise(
305 		 error,
306 		 PyExc_MemoryError,
307 		 "%s: unable to initialize item.",
308 		 function );
309 
310 		libcerror_error_free(
311 		 &error );
312 
313 		return( -1 );
314 	}
315 	return( 0 );
316 }
317 
318 /* Frees an item object
319  */
pyfwsi_item_free(pyfwsi_item_t * pyfwsi_item)320 void pyfwsi_item_free(
321       pyfwsi_item_t *pyfwsi_item )
322 {
323 	libcerror_error_t *error    = NULL;
324 	struct _typeobject *ob_type = NULL;
325 	static char *function       = "pyfwsi_item_free";
326 	int result                  = 0;
327 
328 	if( pyfwsi_item == NULL )
329 	{
330 		PyErr_Format(
331 		 PyExc_TypeError,
332 		 "%s: invalid item.",
333 		 function );
334 
335 		return;
336 	}
337 	if( pyfwsi_item->item == NULL )
338 	{
339 		PyErr_Format(
340 		 PyExc_TypeError,
341 		 "%s: invalid item - missing libfwsi item.",
342 		 function );
343 
344 		return;
345 	}
346 	ob_type = Py_TYPE(
347 	           pyfwsi_item );
348 
349 	if( ob_type == NULL )
350 	{
351 		PyErr_Format(
352 		 PyExc_ValueError,
353 		 "%s: missing ob_type.",
354 		 function );
355 
356 		return;
357 	}
358 	if( ob_type->tp_free == NULL )
359 	{
360 		PyErr_Format(
361 		 PyExc_ValueError,
362 		 "%s: invalid ob_type - missing tp_free.",
363 		 function );
364 
365 		return;
366 	}
367 	Py_BEGIN_ALLOW_THREADS
368 
369 	result = libfwsi_item_free(
370 	          &( pyfwsi_item->item ),
371 	          &error );
372 
373 	Py_END_ALLOW_THREADS
374 
375 	if( result != 1 )
376 	{
377 		pyfwsi_error_raise(
378 		 error,
379 		 PyExc_MemoryError,
380 		 "%s: unable to free item.",
381 		 function );
382 
383 		libcerror_error_free(
384 		 &error );
385 	}
386 	if( pyfwsi_item->parent_object != NULL )
387 	{
388 		Py_DecRef(
389 		 (PyObject *) pyfwsi_item->parent_object );
390 	}
391 	ob_type->tp_free(
392 	 (PyObject*) pyfwsi_item );
393 }
394 
395 /* Copies the item from a byte stream
396  * Returns a Python object if successful or NULL on error
397  */
pyfwsi_item_copy_from_byte_stream(pyfwsi_item_t * pyfwsi_item,PyObject * arguments,PyObject * keywords)398 PyObject *pyfwsi_item_copy_from_byte_stream(
399            pyfwsi_item_t *pyfwsi_item,
400            PyObject *arguments,
401            PyObject *keywords )
402 {
403 	PyObject *string_object       = NULL;
404 	libcerror_error_t *error      = NULL;
405 	static char *function         = "pyfwsi_item_copy_from_byte_stream";
406 	static char *keyword_list[]   = { "byte_stream", "ascii_codepage", NULL };
407 	const char *byte_stream       = NULL;
408 	char *codepage_string         = NULL;
409 	Py_ssize_t byte_stream_size   = 0;
410 	size_t codepage_string_length = 0;
411 	uint32_t feature_flags        = 0;
412 	int ascii_codepage            = LIBFWSI_CODEPAGE_WINDOWS_1252;
413 	int result                    = 0;
414 
415 	if( pyfwsi_item == NULL )
416 	{
417 		PyErr_Format(
418 		 PyExc_TypeError,
419 		 "%s: invalid item.",
420 		 function );
421 
422 		return( NULL );
423 	}
424 	if( PyArg_ParseTupleAndKeywords(
425 	     arguments,
426 	     keywords,
427 	     "O|s",
428 	     keyword_list,
429 	     &string_object,
430 	     &codepage_string ) == 0 )
431 	{
432 		return( NULL );
433 	}
434 	PyErr_Clear();
435 
436 #if PY_MAJOR_VERSION >= 3
437 	result = PyObject_IsInstance(
438 		  string_object,
439 		  (PyObject *) &PyBytes_Type );
440 #else
441 	result = PyObject_IsInstance(
442 		  string_object,
443 		  (PyObject *) &PyString_Type );
444 #endif
445 	if( result == -1 )
446 	{
447 		pyfwsi_error_fetch_and_raise(
448 	         PyExc_RuntimeError,
449 		 "%s: unable to determine if string object is of type string.",
450 		 function );
451 
452 		return( NULL );
453 	}
454 	else if( result == 0 )
455 	{
456 		PyErr_Format(
457 		 PyExc_TypeError,
458 		 "%s: unsupported string object type",
459 		 function );
460 
461 		return( NULL );
462 	}
463 	if( codepage_string != NULL )
464 	{
465 		codepage_string_length = narrow_string_length(
466 		                          codepage_string );
467 
468 		feature_flags = LIBCLOCALE_CODEPAGE_FEATURE_FLAG_HAVE_WINDOWS;
469 
470 		if( libclocale_codepage_copy_from_string(
471 		     &ascii_codepage,
472 		     codepage_string,
473 		     codepage_string_length,
474 		     feature_flags,
475 		     &error ) != 1 )
476 		{
477 			pyfwsi_error_raise(
478 			 error,
479 			 PyExc_RuntimeError,
480 			 "%s: unable to determine ASCII codepage.",
481 			 function );
482 
483 			libcerror_error_free(
484 			 &error );
485 
486 			return( NULL );
487 		}
488 	}
489 	PyErr_Clear();
490 
491 #if PY_MAJOR_VERSION >= 3
492 	byte_stream = PyBytes_AsString(
493 	               string_object );
494 
495 	byte_stream_size = PyBytes_Size(
496 	                    string_object );
497 #else
498 	byte_stream = PyString_AsString(
499 	               string_object );
500 
501 	byte_stream_size = PyString_Size(
502 	                    string_object );
503 #endif
504 /* TODO size bounds check */
505 
506 	Py_BEGIN_ALLOW_THREADS
507 
508 	result = libfwsi_item_copy_from_byte_stream(
509 	          pyfwsi_item->item,
510 	          (uint8_t *) byte_stream,
511 	          (size_t) byte_stream_size,
512 	          ascii_codepage,
513 	          &error );
514 
515 	Py_END_ALLOW_THREADS
516 
517 	if( result != 1 )
518 	{
519 		pyfwsi_error_raise(
520 		 error,
521 		 PyExc_IOError,
522 		 "%s: unable to copy item from byte stream.",
523 		 function );
524 
525 		libcerror_error_free(
526 		 &error );
527 
528 		return( NULL );
529 	}
530 	Py_IncRef(
531 	 Py_None );
532 
533 	return( Py_None );
534 }
535 
536 /* Retrieves the class type
537  * Returns a Python object if successful or NULL on error
538  */
pyfwsi_item_get_class_type(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)539 PyObject *pyfwsi_item_get_class_type(
540            pyfwsi_item_t *pyfwsi_item,
541            PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
542 {
543 	libcerror_error_t *error = NULL;
544 	static char *function    = "pyfwsi_item_get_class_type";
545 	uint8_t class_type       = 0;
546 	int result               = 0;
547 
548 	PYFWSI_UNREFERENCED_PARAMETER( arguments )
549 
550 	if( pyfwsi_item == NULL )
551 	{
552 		PyErr_Format(
553 		 PyExc_TypeError,
554 		 "%s: invalid item.",
555 		 function );
556 
557 		return( NULL );
558 	}
559 	Py_BEGIN_ALLOW_THREADS
560 
561 	result = libfwsi_item_get_class_type(
562 	          pyfwsi_item->item,
563 	          &class_type,
564 	          &error );
565 
566 	Py_END_ALLOW_THREADS
567 
568 	if( result != 1 )
569 	{
570 		pyfwsi_error_raise(
571 		 error,
572 		 PyExc_IOError,
573 		 "%s: unable to retrieve class type.",
574 		 function );
575 
576 		libcerror_error_free(
577 		 &error );
578 
579 		return( NULL );
580 	}
581 	return( PyLong_FromUnsignedLong(
582 	         (unsigned long) class_type ) );
583 }
584 
585 /* Retrieves the data size
586  * Returns a Python object if successful or NULL on error
587  */
pyfwsi_item_get_data_size(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)588 PyObject *pyfwsi_item_get_data_size(
589            pyfwsi_item_t *pyfwsi_item,
590            PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
591 {
592 	libcerror_error_t *error = NULL;
593 	static char *function    = "pyfwsi_item_get_data_size";
594 	size_t data_size         = 0;
595 	int result               = 0;
596 
597 	PYFWSI_UNREFERENCED_PARAMETER( arguments )
598 
599 	if( pyfwsi_item == NULL )
600 	{
601 		PyErr_Format(
602 		 PyExc_TypeError,
603 		 "%s: invalid item.",
604 		 function );
605 
606 		return( NULL );
607 	}
608 	Py_BEGIN_ALLOW_THREADS
609 
610 	result = libfwsi_item_get_data_size(
611 	          pyfwsi_item->item,
612 	          &data_size,
613 	          &error );
614 
615 	Py_END_ALLOW_THREADS
616 
617 	if( result != 1 )
618 	{
619 		pyfwsi_error_raise(
620 		 error,
621 		 PyExc_IOError,
622 		 "%s: unable to retrieve data size.",
623 		 function );
624 
625 		libcerror_error_free(
626 		 &error );
627 
628 		return( NULL );
629 	}
630 	return( PyLong_FromUnsignedLong(
631 	         (unsigned long) data_size ) );
632 }
633 
634 #ifdef TODO
635 /* Retrieves the data
636  * Returns a Python object if successful or NULL on error
637  */
pyfwsi_item_get_data(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)638 PyObject *pyfwsi_item_get_data(
639            pyfwsi_item_t *pyfwsi_item,
640            PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
641 {
642 	libcerror_error_t *error = NULL;
643 	PyObject *string_object  = NULL;
644 	uint8_t *data            = NULL;
645 	static char *function    = "pyfwsi_item_get_data";
646 	size_t data_size         = 0;
647 	int result               = 0;
648 
649 	PYFWSI_UNREFERENCED_PARAMETER( arguments )
650 
651 	if( pyfwsi_item == NULL )
652 	{
653 		PyErr_Format(
654 		 PyExc_TypeError,
655 		 "%s: invalid item.",
656 		 function );
657 
658 		return( NULL );
659 	}
660 	Py_BEGIN_ALLOW_THREADS
661 
662 	result = libfwsi_item_get_data_size(
663 	          pyfwsi_item->item,
664 	          &data_size,
665 	          &error );
666 
667 	Py_END_ALLOW_THREADS
668 
669 	if( result == -1 )
670 	{
671 		pyfwsi_error_raise(
672 		 error,
673 		 PyExc_IOError,
674 		 "%s: unable to retrieve data size.",
675 		 function );
676 
677 		libcerror_error_free(
678 		 &error );
679 
680 		goto on_error;
681 	}
682 	else if( ( result == 0 )
683 	      || ( data_size == 0 ) )
684 	{
685 		Py_IncRef(
686 		 Py_None );
687 
688 		return( Py_None );
689 	}
690 	data = (uint8_t *) PyMem_Malloc(
691 	                    sizeof( uint8_t ) * data_size );
692 
693 	if( data == NULL )
694 	{
695 		PyErr_Format(
696 		 PyExc_IOError,
697 		 "%s: unable to create data.",
698 		 function );
699 
700 		goto on_error;
701 	}
702 	Py_BEGIN_ALLOW_THREADS
703 
704 	result = libfwsi_item_get_data(
705 		  pyfwsi_item->item,
706 		  data,
707 		  data_size,
708 		  &error );
709 
710 	Py_END_ALLOW_THREADS
711 
712 	if( result != 1 )
713 	{
714 		pyfwsi_error_raise(
715 		 error,
716 		 PyExc_IOError,
717 		 "%s: unable to retrieve data.",
718 		 function );
719 
720 		libcerror_error_free(
721 		 &error );
722 
723 		goto on_error;
724 	}
725 #if PY_MAJOR_VERSION >= 3
726 	string_object = PyBytes_FromStringAndSize(
727 			 (char *) data,
728 			 (Py_ssize_t) data_size );
729 #else
730 	string_object = PyString_FromStringAndSize(
731 			 (char *) data,
732 			 (Py_ssize_t) data_size );
733 #endif
734 	PyMem_Free(
735 	 data );
736 
737 	return( string_object );
738 
739 on_error:
740 	if( data != NULL )
741 	{
742 		PyMem_Free(
743 		 data );
744 	}
745 	return( NULL );
746 }
747 #endif
748 
749 /* Retrieves the number of extension blocks
750  * Returns a Python object if successful or NULL on error
751  */
pyfwsi_item_get_number_of_extension_blocks(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)752 PyObject *pyfwsi_item_get_number_of_extension_blocks(
753            pyfwsi_item_t *pyfwsi_item,
754            PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
755 {
756 	libcerror_error_t *error       = NULL;
757 	PyObject *integer_object       = NULL;
758 	static char *function          = "pyfwsi_item_get_number_of_extension_blocks";
759 	int number_of_extension_blocks = 0;
760 	int result                     = 0;
761 
762 	PYFWSI_UNREFERENCED_PARAMETER( arguments )
763 
764 	if( pyfwsi_item == NULL )
765 	{
766 		PyErr_Format(
767 		 PyExc_TypeError,
768 		 "%s: invalid item.",
769 		 function );
770 
771 		return( NULL );
772 	}
773 	Py_BEGIN_ALLOW_THREADS
774 
775 	result = libfwsi_item_get_number_of_extension_blocks(
776 	          pyfwsi_item->item,
777 	          &number_of_extension_blocks,
778 	          &error );
779 
780 	Py_END_ALLOW_THREADS
781 
782 	if( result != 1 )
783 	{
784 		pyfwsi_error_raise(
785 		 error,
786 		 PyExc_IOError,
787 		 "%s: unable to retrieve number of extension blocks.",
788 		 function );
789 
790 		libcerror_error_free(
791 		 &error );
792 
793 		return( NULL );
794 	}
795 #if PY_MAJOR_VERSION >= 3
796 	integer_object = PyLong_FromLong(
797 	                  (long) number_of_extension_blocks );
798 #else
799 	integer_object = PyInt_FromLong(
800 	                  (long) number_of_extension_blocks );
801 #endif
802 	return( integer_object );
803 }
804 
805 /* Retrieves a specific extension block by index
806  * Returns a Python object if successful or NULL on error
807  */
pyfwsi_item_get_extension_block_by_index(PyObject * pyfwsi_item,int extension_block_index)808 PyObject *pyfwsi_item_get_extension_block_by_index(
809            PyObject *pyfwsi_item,
810            int extension_block_index )
811 {
812 	libcerror_error_t *error                   = NULL;
813 	libfwsi_extension_block_t *extension_block = NULL;
814 	PyObject *extension_block_object           = NULL;
815 	PyTypeObject *type_object                  = NULL;
816 	static char *function                      = "pyfwsi_item_get_extension_block_by_index";
817 	uint32_t signature                         = 0;
818 	int result                                 = 0;
819 
820 	if( pyfwsi_item == NULL )
821 	{
822 		PyErr_Format(
823 		 PyExc_TypeError,
824 		 "%s: invalid item.",
825 		 function );
826 
827 		return( NULL );
828 	}
829 	Py_BEGIN_ALLOW_THREADS
830 
831 	result = libfwsi_item_get_extension_block(
832 	          ( (pyfwsi_item_t *) pyfwsi_item )->item,
833 	          extension_block_index,
834 	          &extension_block,
835 	          &error );
836 
837 	Py_END_ALLOW_THREADS
838 
839 	if( result != 1 )
840 	{
841 		pyfwsi_error_raise(
842 		 error,
843 		 PyExc_IOError,
844 		 "%s: unable to retrieve extension block: %d.",
845 		 function,
846 		 extension_block_index );
847 
848 		libcerror_error_free(
849 		 &error );
850 
851 		goto on_error;
852 	}
853 	Py_BEGIN_ALLOW_THREADS
854 
855 	result = libfwsi_extension_block_get_signature(
856 	          extension_block,
857 	          &signature,
858 	          &error );
859 
860 	Py_END_ALLOW_THREADS
861 
862 	if( result != 1 )
863 	{
864 		pyfwsi_error_raise(
865 		 error,
866 		 PyExc_IOError,
867 		 "%s: unable to retrieve extension block: %d signature.",
868 		 function,
869 		 extension_block_index );
870 
871 		libcerror_error_free(
872 		 &error );
873 
874 		goto on_error;
875 	}
876 	switch( signature )
877 	{
878 		case 0xbeef0004UL:
879 			type_object = &pyfwsi_file_entry_extension_type_object;
880 			break;
881 
882 		default:
883 			type_object = &pyfwsi_extension_block_type_object;
884 			break;
885 	}
886 	extension_block_object = pyfwsi_extension_block_new(
887 	                          type_object,
888 	                          extension_block,
889 	                          pyfwsi_item );
890 
891 	if( extension_block_object == NULL )
892 	{
893 		PyErr_Format(
894 		 PyExc_MemoryError,
895 		 "%s: unable to create extension block object.",
896 		 function );
897 
898 		goto on_error;
899 	}
900 	return( extension_block_object );
901 
902 on_error:
903 	if( extension_block != NULL )
904 	{
905 		libfwsi_extension_block_free(
906 		 &extension_block,
907 		 NULL );
908 	}
909 	return( NULL );
910 }
911 
912 /* Retrieves a specific extension block
913  * Returns a Python object if successful or NULL on error
914  */
pyfwsi_item_get_extension_block(pyfwsi_item_t * pyfwsi_item,PyObject * arguments,PyObject * keywords)915 PyObject *pyfwsi_item_get_extension_block(
916            pyfwsi_item_t *pyfwsi_item,
917            PyObject *arguments,
918            PyObject *keywords )
919 {
920 	PyObject *extension_block_object = NULL;
921 	static char *keyword_list[]      = { "extension_block_index", NULL };
922 	int extension_block_index        = 0;
923 
924 	if( PyArg_ParseTupleAndKeywords(
925 	     arguments,
926 	     keywords,
927 	     "i",
928 	     keyword_list,
929 	     &extension_block_index ) == 0 )
930 	{
931 		return( NULL );
932 	}
933 	extension_block_object = pyfwsi_item_get_extension_block_by_index(
934 	                          (PyObject *) pyfwsi_item,
935 	                          extension_block_index );
936 
937 	return( extension_block_object );
938 }
939 
940 /* Retrieves an extension blocks sequence and iterator object for the extension blocks
941  * Returns a Python object if successful or NULL on error
942  */
pyfwsi_item_get_extension_blocks(pyfwsi_item_t * pyfwsi_item,PyObject * arguments PYFWSI_ATTRIBUTE_UNUSED)943 PyObject *pyfwsi_item_get_extension_blocks(
944            pyfwsi_item_t *pyfwsi_item,
945            PyObject *arguments PYFWSI_ATTRIBUTE_UNUSED )
946 {
947 	libcerror_error_t *error          = NULL;
948 	PyObject *extension_blocks_object = NULL;
949 	static char *function             = "pyfwsi_item_get_extension_blocks";
950 	int number_of_extension_blocks    = 0;
951 	int result                        = 0;
952 
953 	PYFWSI_UNREFERENCED_PARAMETER( arguments )
954 
955 	if( pyfwsi_item == NULL )
956 	{
957 		PyErr_Format(
958 		 PyExc_TypeError,
959 		 "%s: invalid item.",
960 		 function );
961 
962 		return( NULL );
963 	}
964 	Py_BEGIN_ALLOW_THREADS
965 
966 	result = libfwsi_item_get_number_of_extension_blocks(
967 	          pyfwsi_item->item,
968 	          &number_of_extension_blocks,
969 	          &error );
970 
971 	Py_END_ALLOW_THREADS
972 
973 	if( result != 1 )
974 	{
975 		pyfwsi_error_raise(
976 		 error,
977 		 PyExc_IOError,
978 		 "%s: unable to retrieve number of extension blocks.",
979 		 function );
980 
981 		libcerror_error_free(
982 		 &error );
983 
984 		return( NULL );
985 	}
986 	extension_blocks_object = pyfwsi_extension_blocks_new(
987 	                           (PyObject *) pyfwsi_item,
988 	                           &pyfwsi_item_get_extension_block_by_index,
989 	                           number_of_extension_blocks );
990 
991 	if( extension_blocks_object == NULL )
992 	{
993 		PyErr_Format(
994 		 PyExc_MemoryError,
995 		 "%s: unable to create extension blocks object.",
996 		 function );
997 
998 		return( NULL );
999 	}
1000 	return( extension_blocks_object );
1001 }
1002 
1003