1 /*
2  * Python object wrapper of libolecf_item_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 <memory.h>
24 #include <narrow_string.h>
25 #include <types.h>
26 
27 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
28 #include <stdlib.h>
29 #endif
30 
31 #include "pyolecf_datetime.h"
32 #include "pyolecf_error.h"
33 #include "pyolecf_integer.h"
34 #include "pyolecf_item.h"
35 #include "pyolecf_items.h"
36 #include "pyolecf_libcerror.h"
37 #include "pyolecf_libolecf.h"
38 #include "pyolecf_property_set_stream.h"
39 #include "pyolecf_python.h"
40 #include "pyolecf_stream.h"
41 #include "pyolecf_unused.h"
42 
43 PyMethodDef pyolecf_item_object_methods[] = {
44 
45 	{ "get_name",
46 	  (PyCFunction) pyolecf_item_get_name,
47 	  METH_NOARGS,
48 	  "get_name() -> Unicode string or None\n"
49 	  "\n"
50 	  "Retrieves the name." },
51 
52 	{ "get_size",
53 	  (PyCFunction) pyolecf_item_get_size,
54 	  METH_NOARGS,
55 	  "get_size() -> Integer or None\n"
56 	  "\n"
57 	  "Retrieves the size." },
58 
59 	{ "get_creation_time",
60 	  (PyCFunction) pyolecf_item_get_creation_time,
61 	  METH_NOARGS,
62 	  "get_creation_time() -> Datetime or None\n"
63 	  "\n"
64 	  "Retrieves the creation time." },
65 
66 	{ "get_creation_time_as_integer",
67 	  (PyCFunction) pyolecf_item_get_creation_time_as_integer,
68 	  METH_NOARGS,
69 	  "get_creation_time_as_integer() -> Integer or None\n"
70 	  "\n"
71 	  "Retrieves the creation time as a 64-bit integer containing a FILETIME value." },
72 
73 	{ "get_modification_time",
74 	  (PyCFunction) pyolecf_item_get_modification_time,
75 	  METH_NOARGS,
76 	  "get_modification_time() -> Datetime or None\n"
77 	  "\n"
78 	  "Retrieves the modification time." },
79 
80 	{ "get_modification_time_as_integer",
81 	  (PyCFunction) pyolecf_item_get_modification_time_as_integer,
82 	  METH_NOARGS,
83 	  "get_modification_time_as_integer() -> Integer or None\n"
84 	  "\n"
85 	  "Retrieves the modification time as a 64-bit integer containing a FILETIME value." },
86 
87 	{ "get_number_of_sub_items",
88 	  (PyCFunction) pyolecf_item_get_number_of_sub_items,
89 	  METH_NOARGS,
90 	  "get_number_of_sub_items() -> Integer or None\n"
91 	  "\n"
92 	  "Retrieves the number of sub items." },
93 
94 	{ "get_sub_item",
95 	  (PyCFunction) pyolecf_item_get_sub_item,
96 	  METH_VARARGS | METH_KEYWORDS,
97 	  "get_sub_item(sub_item_index) -> Object or None\n"
98 	  "\n"
99 	  "Retrieves the sub item specified by the index." },
100 
101 	{ "get_sub_item_by_name",
102 	  (PyCFunction) pyolecf_item_get_sub_item_by_name,
103 	  METH_VARARGS | METH_KEYWORDS,
104 	  "get_sub_item_by_name(name) -> Object or None\n"
105 	  "\n"
106 	  "Retrieves the sub item specified by the name." },
107 
108 	{ "get_sub_item_by_path",
109 	  (PyCFunction) pyolecf_item_get_sub_item_by_path,
110 	  METH_VARARGS | METH_KEYWORDS,
111 	  "get_sub_item_by_path(path) -> Object or None\n"
112 	  "\n"
113 	  "Retrieves the sub item specified by the path." },
114 
115 	/* Sentinel */
116 	{ NULL, NULL, 0, NULL }
117 };
118 
119 PyGetSetDef pyolecf_item_object_get_set_definitions[] = {
120 
121 	{ "name",
122 	  (getter) pyolecf_item_get_name,
123 	  (setter) 0,
124 	  "The name.",
125 	  NULL },
126 
127 	{ "size",
128 	  (getter) pyolecf_item_get_size,
129 	  (setter) 0,
130 	  "The size.",
131 	  NULL },
132 
133 	{ "creation_time",
134 	  (getter) pyolecf_item_get_creation_time,
135 	  (setter) 0,
136 	  "The creation time.",
137 	  NULL },
138 
139 	{ "modification_time",
140 	  (getter) pyolecf_item_get_modification_time,
141 	  (setter) 0,
142 	  "The modification time.",
143 	  NULL },
144 
145 	{ "number_of_sub_items",
146 	  (getter) pyolecf_item_get_number_of_sub_items,
147 	  (setter) 0,
148 	  "The number of sub items.",
149 	  NULL },
150 
151 	{ "sub_items",
152 	  (getter) pyolecf_item_get_sub_items,
153 	  (setter) 0,
154 	  "The sub items.",
155 	  NULL },
156 
157 	/* Sentinel */
158 	{ NULL, NULL, NULL, NULL, NULL }
159 };
160 
161 PyTypeObject pyolecf_item_type_object = {
162 	PyVarObject_HEAD_INIT( NULL, 0 )
163 
164 	/* tp_name */
165 	"pyolecf.item",
166 	/* tp_basicsize */
167 	sizeof( pyolecf_item_t ),
168 	/* tp_itemsize */
169 	0,
170 	/* tp_dealloc */
171 	(destructor) pyolecf_item_free,
172 	/* tp_print */
173 	0,
174 	/* tp_getattr */
175 	0,
176 	/* tp_setattr */
177 	0,
178 	/* tp_compare */
179 	0,
180 	/* tp_repr */
181 	0,
182 	/* tp_as_number */
183 	0,
184 	/* tp_as_sequence */
185 	0,
186 	/* tp_as_mapping */
187 	0,
188 	/* tp_hash */
189 	0,
190 	/* tp_call */
191 	0,
192 	/* tp_str */
193 	0,
194 	/* tp_getattro */
195 	0,
196 	/* tp_setattro */
197 	0,
198 	/* tp_as_buffer */
199 	0,
200 	/* tp_flags */
201 	Py_TPFLAGS_DEFAULT,
202 	/* tp_doc */
203 	"pyolecf item object (wraps libolecf_item_t)",
204 	/* tp_traverse */
205 	0,
206 	/* tp_clear */
207 	0,
208 	/* tp_richcompare */
209 	0,
210 	/* tp_weaklistoffset */
211 	0,
212 	/* tp_iter */
213 	0,
214 	/* tp_iternext */
215 	0,
216 	/* tp_methods */
217 	pyolecf_item_object_methods,
218 	/* tp_members */
219 	0,
220 	/* tp_getset */
221 	pyolecf_item_object_get_set_definitions,
222 	/* tp_base */
223 	0,
224 	/* tp_dict */
225 	0,
226 	/* tp_descr_get */
227 	0,
228 	/* tp_descr_set */
229 	0,
230 	/* tp_dictoffset */
231 	0,
232 	/* tp_init */
233 	(initproc) pyolecf_item_init,
234 	/* tp_alloc */
235 	0,
236 	/* tp_new */
237 	0,
238 	/* tp_free */
239 	0,
240 	/* tp_is_gc */
241 	0,
242 	/* tp_bases */
243 	NULL,
244 	/* tp_mro */
245 	NULL,
246 	/* tp_cache */
247 	NULL,
248 	/* tp_subclasses */
249 	NULL,
250 	/* tp_weaklist */
251 	NULL,
252 	/* tp_del */
253 	0
254 };
255 
256 /* Creates a new item object
257  * Returns a Python object if successful or NULL on error
258  */
pyolecf_item_new(PyTypeObject * type_object,libolecf_item_t * item,PyObject * parent_object)259 PyObject *pyolecf_item_new(
260            PyTypeObject *type_object,
261            libolecf_item_t *item,
262            PyObject *parent_object )
263 {
264 	pyolecf_item_t *pyolecf_item = NULL;
265 	static char *function        = "pyolecf_item_new";
266 
267 	if( item == NULL )
268 	{
269 		PyErr_Format(
270 		 PyExc_ValueError,
271 		 "%s: invalid item.",
272 		 function );
273 
274 		return( NULL );
275 	}
276 	/* PyObject_New does not invoke tp_init
277 	 */
278 	pyolecf_item = PyObject_New(
279 	                struct pyolecf_item,
280 	                type_object );
281 
282 	if( pyolecf_item == NULL )
283 	{
284 		PyErr_Format(
285 		 PyExc_MemoryError,
286 		 "%s: unable to initialize item.",
287 		 function );
288 
289 		goto on_error;
290 	}
291 	pyolecf_item->item          = item;
292 	pyolecf_item->parent_object = parent_object;
293 
294 	if( pyolecf_item->parent_object != NULL )
295 	{
296 		Py_IncRef(
297 		 pyolecf_item->parent_object );
298 	}
299 	return( (PyObject *) pyolecf_item );
300 
301 on_error:
302 	if( pyolecf_item != NULL )
303 	{
304 		Py_DecRef(
305 		 (PyObject *) pyolecf_item );
306 	}
307 	return( NULL );
308 }
309 
310 /* Initializes an item object
311  * Returns 0 if successful or -1 on error
312  */
pyolecf_item_init(pyolecf_item_t * pyolecf_item)313 int pyolecf_item_init(
314      pyolecf_item_t *pyolecf_item )
315 {
316 	static char *function = "pyolecf_item_init";
317 
318 	if( pyolecf_item == NULL )
319 	{
320 		PyErr_Format(
321 		 PyExc_ValueError,
322 		 "%s: invalid item.",
323 		 function );
324 
325 		return( -1 );
326 	}
327 	/* Make sure libolecf item is set to NULL
328 	 */
329 	pyolecf_item->item = NULL;
330 
331 	PyErr_Format(
332 	 PyExc_NotImplementedError,
333 	 "%s: initialize of item not supported.",
334 	 function );
335 
336 	return( -1 );
337 }
338 
339 /* Frees an item object
340  */
pyolecf_item_free(pyolecf_item_t * pyolecf_item)341 void pyolecf_item_free(
342       pyolecf_item_t *pyolecf_item )
343 {
344 	struct _typeobject *ob_type = NULL;
345 	libcerror_error_t *error    = NULL;
346 	static char *function       = "pyolecf_item_free";
347 	int result                  = 0;
348 
349 	if( pyolecf_item == NULL )
350 	{
351 		PyErr_Format(
352 		 PyExc_ValueError,
353 		 "%s: invalid item.",
354 		 function );
355 
356 		return;
357 	}
358 	ob_type = Py_TYPE(
359 	           pyolecf_item );
360 
361 	if( ob_type == NULL )
362 	{
363 		PyErr_Format(
364 		 PyExc_ValueError,
365 		 "%s: missing ob_type.",
366 		 function );
367 
368 		return;
369 	}
370 	if( ob_type->tp_free == NULL )
371 	{
372 		PyErr_Format(
373 		 PyExc_ValueError,
374 		 "%s: invalid ob_type - missing tp_free.",
375 		 function );
376 
377 		return;
378 	}
379 	if( pyolecf_item->item != NULL )
380 	{
381 		Py_BEGIN_ALLOW_THREADS
382 
383 		result = libolecf_item_free(
384 		          &( pyolecf_item->item ),
385 		          &error );
386 
387 		Py_END_ALLOW_THREADS
388 
389 		if( result != 1 )
390 		{
391 			pyolecf_error_raise(
392 			 error,
393 			 PyExc_MemoryError,
394 			 "%s: unable to free libolecf item.",
395 			 function );
396 
397 			libcerror_error_free(
398 			 &error );
399 		}
400 	}
401 	if( pyolecf_item->parent_object != NULL )
402 	{
403 		Py_DecRef(
404 		 pyolecf_item->parent_object );
405 	}
406 	ob_type->tp_free(
407 	 (PyObject*) pyolecf_item );
408 }
409 
410 /* Retrieves the name
411  * Returns a Python object if successful or NULL on error
412  */
pyolecf_item_get_name(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)413 PyObject *pyolecf_item_get_name(
414            pyolecf_item_t *pyolecf_item,
415            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
416 {
417 	PyObject *string_object  = NULL;
418 	libcerror_error_t *error = NULL;
419 	const char *errors       = NULL;
420 	static char *function    = "pyolecf_item_get_name";
421 	char *utf8_string        = NULL;
422 	size_t utf8_string_size  = 0;
423 	int result               = 0;
424 
425 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
426 
427 	if( pyolecf_item == NULL )
428 	{
429 		PyErr_Format(
430 		 PyExc_ValueError,
431 		 "%s: invalid item.",
432 		 function );
433 
434 		return( NULL );
435 	}
436 	Py_BEGIN_ALLOW_THREADS
437 
438 	result = libolecf_item_get_utf8_name_size(
439 	          pyolecf_item->item,
440 	          &utf8_string_size,
441 	          &error );
442 
443 	Py_END_ALLOW_THREADS
444 
445 	if( result == -1 )
446 	{
447 		pyolecf_error_raise(
448 		 error,
449 		 PyExc_IOError,
450 		 "%s: unable to determine size of name as UTF-8 string.",
451 		 function );
452 
453 		libcerror_error_free(
454 		 &error );
455 
456 		goto on_error;
457 	}
458 	else if( ( result == 0 )
459 	      || ( utf8_string_size == 0 ) )
460 	{
461 		Py_IncRef(
462 		 Py_None );
463 
464 		return( Py_None );
465 	}
466 	utf8_string = (char *) PyMem_Malloc(
467 	                        sizeof( char ) * utf8_string_size );
468 
469 	if( utf8_string == NULL )
470 	{
471 		PyErr_Format(
472 		 PyExc_MemoryError,
473 		 "%s: unable to create UTF-8 string.",
474 		 function );
475 
476 		goto on_error;
477 	}
478 	Py_BEGIN_ALLOW_THREADS
479 
480 	result = libolecf_item_get_utf8_name(
481 	          pyolecf_item->item,
482 	          (uint8_t *) utf8_string,
483 	          utf8_string_size,
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 name as UTF-8 string.",
494 		 function );
495 
496 		libcerror_error_free(
497 		 &error );
498 
499 		goto on_error;
500 	}
501 	/* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
502 	 * the end of string character is part of the string
503 	 */
504 	string_object = PyUnicode_DecodeUTF8(
505 	                 utf8_string,
506 	                 (Py_ssize_t) utf8_string_size - 1,
507 	                 errors );
508 
509 	if( string_object == NULL )
510 	{
511 		PyErr_Format(
512 		 PyExc_IOError,
513 		 "%s: unable to convert UTF-8 string into Unicode object.",
514 		 function );
515 
516 		goto on_error;
517 	}
518 	PyMem_Free(
519 	 utf8_string );
520 
521 	return( string_object );
522 
523 on_error:
524 	if( utf8_string != NULL )
525 	{
526 		PyMem_Free(
527 		 utf8_string );
528 	}
529 	return( NULL );
530 }
531 
532 /* Retrieves the size
533  * Returns a Python object if successful or NULL on error
534  */
pyolecf_item_get_size(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)535 PyObject *pyolecf_item_get_size(
536            pyolecf_item_t *pyolecf_item,
537            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
538 {
539 	PyObject *integer_object = NULL;
540 	libcerror_error_t *error = NULL;
541 	static char *function    = "pyolecf_item_get_size";
542 	uint32_t value_32bit     = 0;
543 	int result               = 0;
544 
545 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
546 
547 	if( pyolecf_item == NULL )
548 	{
549 		PyErr_Format(
550 		 PyExc_ValueError,
551 		 "%s: invalid item.",
552 		 function );
553 
554 		return( NULL );
555 	}
556 	Py_BEGIN_ALLOW_THREADS
557 
558 	result = libolecf_item_get_size(
559 	          pyolecf_item->item,
560 	          &value_32bit,
561 	          &error );
562 
563 	Py_END_ALLOW_THREADS
564 
565 	if( result == -1 )
566 	{
567 		pyolecf_error_raise(
568 		 error,
569 		 PyExc_IOError,
570 		 "%s: unable to retrieve size.",
571 		 function );
572 
573 		libcerror_error_free(
574 		 &error );
575 
576 		return( NULL );
577 	}
578 	else if( result == 0 )
579 	{
580 		Py_IncRef(
581 		 Py_None );
582 
583 		return( Py_None );
584 	}
585 	integer_object = PyLong_FromUnsignedLong(
586 	                  (unsigned long) value_32bit );
587 
588 	return( integer_object );
589 }
590 
591 /* Retrieves the creation time
592  * Returns a Python object if successful or NULL on error
593  */
pyolecf_item_get_creation_time(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)594 PyObject *pyolecf_item_get_creation_time(
595            pyolecf_item_t *pyolecf_item,
596            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
597 {
598 	PyObject *datetime_object = NULL;
599 	libcerror_error_t *error  = NULL;
600 	static char *function     = "pyolecf_item_get_creation_time";
601 	uint64_t filetime         = 0;
602 	int result                = 0;
603 
604 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
605 
606 	if( pyolecf_item == NULL )
607 	{
608 		PyErr_Format(
609 		 PyExc_ValueError,
610 		 "%s: invalid item.",
611 		 function );
612 
613 		return( NULL );
614 	}
615 	Py_BEGIN_ALLOW_THREADS
616 
617 	result = libolecf_item_get_creation_time(
618 	          pyolecf_item->item,
619 	          &filetime,
620 	          &error );
621 
622 	Py_END_ALLOW_THREADS
623 
624 	if( result == -1 )
625 	{
626 		pyolecf_error_raise(
627 		 error,
628 		 PyExc_IOError,
629 		 "%s: unable to retrieve creation time.",
630 		 function );
631 
632 		libcerror_error_free(
633 		 &error );
634 
635 		return( NULL );
636 	}
637 	else if( result == 0 )
638 	{
639 		Py_IncRef(
640 		 Py_None );
641 
642 		return( Py_None );
643 	}
644 	datetime_object = pyolecf_datetime_new_from_filetime(
645 	                   filetime );
646 
647 	return( datetime_object );
648 }
649 
650 /* Retrieves the creation time as an integer
651  * Returns a Python object if successful or NULL on error
652  */
pyolecf_item_get_creation_time_as_integer(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)653 PyObject *pyolecf_item_get_creation_time_as_integer(
654            pyolecf_item_t *pyolecf_item,
655            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
656 {
657 	PyObject *integer_object = NULL;
658 	libcerror_error_t *error = NULL;
659 	static char *function    = "pyolecf_item_get_creation_time_as_integer";
660 	uint64_t filetime        = 0;
661 	int result               = 0;
662 
663 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
664 
665 	if( pyolecf_item == NULL )
666 	{
667 		PyErr_Format(
668 		 PyExc_ValueError,
669 		 "%s: invalid item.",
670 		 function );
671 
672 		return( NULL );
673 	}
674 	Py_BEGIN_ALLOW_THREADS
675 
676 	result = libolecf_item_get_creation_time(
677 	          pyolecf_item->item,
678 	          &filetime,
679 	          &error );
680 
681 	Py_END_ALLOW_THREADS
682 
683 	if( result == -1 )
684 	{
685 		pyolecf_error_raise(
686 		 error,
687 		 PyExc_IOError,
688 		 "%s: unable to retrieve creation time.",
689 		 function );
690 
691 		libcerror_error_free(
692 		 &error );
693 
694 		return( NULL );
695 	}
696 	else if( result == 0 )
697 	{
698 		Py_IncRef(
699 		 Py_None );
700 
701 		return( Py_None );
702 	}
703 	integer_object = pyolecf_integer_unsigned_new_from_64bit(
704 	                  (uint64_t) filetime );
705 
706 	return( integer_object );
707 }
708 
709 /* Retrieves the modification time
710  * Returns a Python object if successful or NULL on error
711  */
pyolecf_item_get_modification_time(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)712 PyObject *pyolecf_item_get_modification_time(
713            pyolecf_item_t *pyolecf_item,
714            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
715 {
716 	PyObject *datetime_object = NULL;
717 	libcerror_error_t *error  = NULL;
718 	static char *function     = "pyolecf_item_get_modification_time";
719 	uint64_t filetime         = 0;
720 	int result                = 0;
721 
722 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
723 
724 	if( pyolecf_item == NULL )
725 	{
726 		PyErr_Format(
727 		 PyExc_ValueError,
728 		 "%s: invalid item.",
729 		 function );
730 
731 		return( NULL );
732 	}
733 	Py_BEGIN_ALLOW_THREADS
734 
735 	result = libolecf_item_get_modification_time(
736 	          pyolecf_item->item,
737 	          &filetime,
738 	          &error );
739 
740 	Py_END_ALLOW_THREADS
741 
742 	if( result == -1 )
743 	{
744 		pyolecf_error_raise(
745 		 error,
746 		 PyExc_IOError,
747 		 "%s: unable to retrieve modification time.",
748 		 function );
749 
750 		libcerror_error_free(
751 		 &error );
752 
753 		return( NULL );
754 	}
755 	else if( result == 0 )
756 	{
757 		Py_IncRef(
758 		 Py_None );
759 
760 		return( Py_None );
761 	}
762 	datetime_object = pyolecf_datetime_new_from_filetime(
763 	                   filetime );
764 
765 	return( datetime_object );
766 }
767 
768 /* Retrieves the modification time as an integer
769  * Returns a Python object if successful or NULL on error
770  */
pyolecf_item_get_modification_time_as_integer(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)771 PyObject *pyolecf_item_get_modification_time_as_integer(
772            pyolecf_item_t *pyolecf_item,
773            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
774 {
775 	PyObject *integer_object = NULL;
776 	libcerror_error_t *error = NULL;
777 	static char *function    = "pyolecf_item_get_modification_time_as_integer";
778 	uint64_t filetime        = 0;
779 	int result               = 0;
780 
781 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
782 
783 	if( pyolecf_item == NULL )
784 	{
785 		PyErr_Format(
786 		 PyExc_ValueError,
787 		 "%s: invalid item.",
788 		 function );
789 
790 		return( NULL );
791 	}
792 	Py_BEGIN_ALLOW_THREADS
793 
794 	result = libolecf_item_get_modification_time(
795 	          pyolecf_item->item,
796 	          &filetime,
797 	          &error );
798 
799 	Py_END_ALLOW_THREADS
800 
801 	if( result == -1 )
802 	{
803 		pyolecf_error_raise(
804 		 error,
805 		 PyExc_IOError,
806 		 "%s: unable to retrieve modification time.",
807 		 function );
808 
809 		libcerror_error_free(
810 		 &error );
811 
812 		return( NULL );
813 	}
814 	else if( result == 0 )
815 	{
816 		Py_IncRef(
817 		 Py_None );
818 
819 		return( Py_None );
820 	}
821 	integer_object = pyolecf_integer_unsigned_new_from_64bit(
822 	                  (uint64_t) filetime );
823 
824 	return( integer_object );
825 }
826 
827 /* Retrieves the number of sub items
828  * Returns a Python object if successful or NULL on error
829  */
pyolecf_item_get_number_of_sub_items(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)830 PyObject *pyolecf_item_get_number_of_sub_items(
831            pyolecf_item_t *pyolecf_item,
832            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
833 {
834 	PyObject *integer_object = NULL;
835 	libcerror_error_t *error = NULL;
836 	static char *function    = "pyolecf_item_get_number_of_sub_items";
837 	int number_of_sub_items  = 0;
838 	int result               = 0;
839 
840 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
841 
842 	if( pyolecf_item == NULL )
843 	{
844 		PyErr_Format(
845 		 PyExc_ValueError,
846 		 "%s: invalid item.",
847 		 function );
848 
849 		return( NULL );
850 	}
851 	Py_BEGIN_ALLOW_THREADS
852 
853 	result = libolecf_item_get_number_of_sub_items(
854 	          pyolecf_item->item,
855 	          &number_of_sub_items,
856 	          &error );
857 
858 	Py_END_ALLOW_THREADS
859 
860 	if( result != 1 )
861 	{
862 		pyolecf_error_raise(
863 		 error,
864 		 PyExc_IOError,
865 		 "%s: unable to retrieve number of sub items.",
866 		 function );
867 
868 		libcerror_error_free(
869 		 &error );
870 
871 		return( NULL );
872 	}
873 #if PY_MAJOR_VERSION >= 3
874 	integer_object = PyLong_FromLong(
875 	                  (long) number_of_sub_items );
876 #else
877 	integer_object = PyInt_FromLong(
878 	                  (long) number_of_sub_items );
879 #endif
880 	return( integer_object );
881 }
882 
883 /* Retrieves the item type object
884  * Returns a Python type object if successful or NULL on error
885  */
pyolecf_item_get_item_type_object(libolecf_item_t * item)886 PyTypeObject *pyolecf_item_get_item_type_object(
887                libolecf_item_t *item )
888 {
889 	uint8_t utf8_string[ 32 ];
890 
891 	libcerror_error_t *error = NULL;
892 	static char *function    = "pyolecf_item_get_item_type_object";
893 	size_t utf8_string_size  = 0;
894 	uint8_t item_type        = 0;
895 	int result               = 0;
896 
897 	if( item == NULL )
898 	{
899 		PyErr_Format(
900 		 PyExc_TypeError,
901 		 "%s: invalid item.",
902 		 function );
903 
904 		return( NULL );
905 	}
906 	Py_BEGIN_ALLOW_THREADS
907 
908 	result = libolecf_item_get_type(
909 	          item,
910 	          &item_type,
911 	          &error );
912 
913 	Py_END_ALLOW_THREADS
914 
915 	if( result == -1 )
916 	{
917 		pyolecf_error_raise(
918 		 error,
919 		 PyExc_IOError,
920 		 "%s: unable to retrieve item type.",
921 		 function );
922 
923 		libcerror_error_free(
924 		 &error );
925 
926 		return( NULL );
927 	}
928 	if( item_type == LIBOLECF_ITEM_TYPE_STREAM )
929 	{
930 		Py_BEGIN_ALLOW_THREADS
931 
932 		result = libolecf_item_get_utf8_name_size(
933 		          item,
934 		          &utf8_string_size,
935 		          &error );
936 
937 		Py_END_ALLOW_THREADS
938 
939 		if( result == -1 )
940 		{
941 			pyolecf_error_raise(
942 			 error,
943 			 PyExc_IOError,
944 			 "%s: unable to retrieve name size.",
945 			 function );
946 
947 			libcerror_error_free(
948 			 &error );
949 
950 			return( NULL );
951 		}
952 		if( ( utf8_string_size == 20 )
953 		 || ( utf8_string_size == 28 ) )
954 		{
955 			Py_BEGIN_ALLOW_THREADS
956 
957 			result = libolecf_item_get_utf8_name(
958 			          item,
959 			          utf8_string,
960 			          utf8_string_size,
961 			          &error );
962 
963 			Py_END_ALLOW_THREADS
964 
965 			if( result != 1 )
966 			{
967 				pyolecf_error_raise(
968 				 error,
969 				 PyExc_IOError,
970 				 "%s: unable to retrieve name.",
971 				 function );
972 
973 				libcerror_error_free(
974 				 &error );
975 
976 				return( NULL );
977 			}
978 			if( utf8_string_size == 20 )
979 			{
980 				if( narrow_string_compare(
981 				     "\005SummaryInformation",
982 				     utf8_string,
983 				     19 ) == 0 )
984 				{
985 					return( &pyolecf_property_set_stream_type_object );
986 				}
987 			}
988 			else if( utf8_string_size == 28 )
989 			{
990 				if( narrow_string_compare(
991 				     "\005DocumentSummaryInformation",
992 				     utf8_string,
993 				     27 ) == 0 )
994 				{
995 					return( &pyolecf_property_set_stream_type_object );
996 				}
997 			}
998 		}
999 		return( &pyolecf_stream_type_object );
1000 	}
1001 	return( &pyolecf_item_type_object );
1002 }
1003 
1004 /* Retrieves a specific sub item by index
1005  * Returns a Python object if successful or NULL on error
1006  */
pyolecf_item_get_sub_item_by_index(PyObject * pyolecf_item,int sub_item_index)1007 PyObject *pyolecf_item_get_sub_item_by_index(
1008            PyObject *pyolecf_item,
1009            int sub_item_index )
1010 {
1011 	PyObject *item_object     = NULL;
1012 	PyTypeObject *type_object = NULL;
1013 	libcerror_error_t *error  = NULL;
1014 	libolecf_item_t *sub_item = NULL;
1015 	static char *function     = "pyolecf_item_get_sub_item_by_index";
1016 	int result                = 0;
1017 
1018 	if( pyolecf_item == NULL )
1019 	{
1020 		PyErr_Format(
1021 		 PyExc_ValueError,
1022 		 "%s: invalid item.",
1023 		 function );
1024 
1025 		return( NULL );
1026 	}
1027 	Py_BEGIN_ALLOW_THREADS
1028 
1029 	result = libolecf_item_get_sub_item(
1030 	          ( (pyolecf_item_t *) pyolecf_item )->item,
1031 	          sub_item_index,
1032 	          &sub_item,
1033 	          &error );
1034 
1035 	Py_END_ALLOW_THREADS
1036 
1037 	if( result != 1 )
1038 	{
1039 		pyolecf_error_raise(
1040 		 error,
1041 		 PyExc_IOError,
1042 		 "%s: unable to retrieve sub item: %d.",
1043 		 function,
1044 		 sub_item_index );
1045 
1046 		libcerror_error_free(
1047 		 &error );
1048 
1049 		goto on_error;
1050 	}
1051 	type_object = pyolecf_item_get_item_type_object(
1052 	               sub_item );
1053 
1054 	if( type_object == NULL )
1055 	{
1056 		PyErr_Format(
1057 		 PyExc_IOError,
1058 		 "%s: unable to retrieve item type object.",
1059 		 function );
1060 
1061 		goto on_error;
1062 	}
1063 	item_object = pyolecf_item_new(
1064 	               type_object,
1065 	               sub_item,
1066 	               ( (pyolecf_item_t *) pyolecf_item )->parent_object );
1067 
1068 	if( item_object == NULL )
1069 	{
1070 		PyErr_Format(
1071 		 PyExc_MemoryError,
1072 		 "%s: unable to create sub item object.",
1073 		 function );
1074 
1075 		goto on_error;
1076 	}
1077 	return( item_object );
1078 
1079 on_error:
1080 	if( sub_item != NULL )
1081 	{
1082 		libolecf_item_free(
1083 		 &sub_item,
1084 		 NULL );
1085 	}
1086 	return( NULL );
1087 }
1088 
1089 /* Retrieves a specific sub item
1090  * Returns a Python object if successful or NULL on error
1091  */
pyolecf_item_get_sub_item(pyolecf_item_t * pyolecf_item,PyObject * arguments,PyObject * keywords)1092 PyObject *pyolecf_item_get_sub_item(
1093            pyolecf_item_t *pyolecf_item,
1094            PyObject *arguments,
1095            PyObject *keywords )
1096 {
1097 	PyObject *item_object       = NULL;
1098 	static char *keyword_list[] = { "sub_item_index", NULL };
1099 	int sub_item_index          = 0;
1100 
1101 	if( PyArg_ParseTupleAndKeywords(
1102 	     arguments,
1103 	     keywords,
1104 	     "i",
1105 	     keyword_list,
1106 	     &sub_item_index ) == 0 )
1107 	{
1108 		return( NULL );
1109 	}
1110 	item_object = pyolecf_item_get_sub_item_by_index(
1111 	               (PyObject *) pyolecf_item,
1112 	               sub_item_index );
1113 
1114 	return( item_object );
1115 }
1116 
1117 /* Retrieves a sequence and iterator object for the sub items
1118  * Returns a Python object if successful or NULL on error
1119  */
pyolecf_item_get_sub_items(pyolecf_item_t * pyolecf_item,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)1120 PyObject *pyolecf_item_get_sub_items(
1121            pyolecf_item_t *pyolecf_item,
1122            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
1123 {
1124 	PyObject *sequence_object = NULL;
1125 	libcerror_error_t *error  = NULL;
1126 	static char *function     = "pyolecf_item_get_sub_items";
1127 	int number_of_sub_items   = 0;
1128 	int result                = 0;
1129 
1130 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
1131 
1132 	if( pyolecf_item == NULL )
1133 	{
1134 		PyErr_Format(
1135 		 PyExc_ValueError,
1136 		 "%s: invalid item.",
1137 		 function );
1138 
1139 		return( NULL );
1140 	}
1141 	Py_BEGIN_ALLOW_THREADS
1142 
1143 	result = libolecf_item_get_number_of_sub_items(
1144 	          pyolecf_item->item,
1145 	          &number_of_sub_items,
1146 	          &error );
1147 
1148 	Py_END_ALLOW_THREADS
1149 
1150 	if( result != 1 )
1151 	{
1152 		pyolecf_error_raise(
1153 		 error,
1154 		 PyExc_IOError,
1155 		 "%s: unable to retrieve number of sub items.",
1156 		 function );
1157 
1158 		libcerror_error_free(
1159 		 &error );
1160 
1161 		return( NULL );
1162 	}
1163 	sequence_object = pyolecf_items_new(
1164 	                   (PyObject *) pyolecf_item,
1165 	                   &pyolecf_item_get_sub_item_by_index,
1166 	                   number_of_sub_items );
1167 
1168 	if( sequence_object == NULL )
1169 	{
1170 		pyolecf_error_raise(
1171 		 error,
1172 		 PyExc_MemoryError,
1173 		 "%s: unable to create sequence object.",
1174 		 function );
1175 
1176 		return( NULL );
1177 	}
1178 	return( sequence_object );
1179 }
1180 
1181 /* Retrieves the sub item specified by the name
1182  * Returns a Python object if successful or NULL on error
1183  */
pyolecf_item_get_sub_item_by_name(pyolecf_item_t * pyolecf_item,PyObject * arguments,PyObject * keywords)1184 PyObject *pyolecf_item_get_sub_item_by_name(
1185            pyolecf_item_t *pyolecf_item,
1186            PyObject *arguments,
1187            PyObject *keywords )
1188 {
1189 	PyObject *item_object       = NULL;
1190 	PyTypeObject *type_object   = NULL;
1191 	libcerror_error_t *error    = NULL;
1192 	libolecf_item_t *sub_item   = NULL;
1193 	static char *function       = "pyolecf_item_get_sub_item_by_name";
1194 	static char *keyword_list[] = { "name", NULL };
1195 	char *utf8_name             = NULL;
1196 	size_t utf8_name_length     = 0;
1197 	int result                  = 0;
1198 
1199 	if( pyolecf_item == NULL )
1200 	{
1201 		PyErr_Format(
1202 		 PyExc_ValueError,
1203 		 "%s: invalid item.",
1204 		 function );
1205 
1206 		return( NULL );
1207 	}
1208 	if( PyArg_ParseTupleAndKeywords(
1209 	     arguments,
1210 	     keywords,
1211 	     "s",
1212 	     keyword_list,
1213 	     &utf8_name ) == 0 )
1214 	{
1215 		goto on_error;
1216 	}
1217 	utf8_name_length = narrow_string_length(
1218 	                    utf8_name );
1219 
1220 	Py_BEGIN_ALLOW_THREADS
1221 
1222 	result = libolecf_item_get_sub_item_by_utf8_name(
1223 	          pyolecf_item->item,
1224 	          (uint8_t *) utf8_name,
1225 	          utf8_name_length,
1226 	          &sub_item,
1227 	          &error );
1228 
1229 	Py_END_ALLOW_THREADS
1230 
1231 	if( result == -1 )
1232 	{
1233 		pyolecf_error_raise(
1234 		 error,
1235 		 PyExc_IOError,
1236 		 "%s: unable to retrieve sub item.",
1237 		 function );
1238 
1239 		libcerror_error_free(
1240 		 &error );
1241 
1242 		goto on_error;
1243 	}
1244 	else if( result == 0 )
1245 	{
1246 		Py_IncRef(
1247 		 Py_None );
1248 
1249 		return( Py_None );
1250 	}
1251 	type_object = pyolecf_item_get_item_type_object(
1252 	               sub_item );
1253 
1254 	if( type_object == NULL )
1255 	{
1256 		PyErr_Format(
1257 		 PyExc_IOError,
1258 		 "%s: unable to retrieve item type object.",
1259 		 function );
1260 
1261 		goto on_error;
1262 	}
1263 	item_object = pyolecf_item_new(
1264 	               type_object,
1265 	               sub_item,
1266 	               pyolecf_item->parent_object );
1267 
1268 	if( item_object == NULL )
1269 	{
1270 		PyErr_Format(
1271 		 PyExc_MemoryError,
1272 		 "%s: unable to create sub item object.",
1273 		 function );
1274 
1275 		goto on_error;
1276 	}
1277 	return( item_object );
1278 
1279 on_error:
1280 	if( sub_item != NULL )
1281 	{
1282 		libolecf_item_free(
1283 		 &sub_item,
1284 		 NULL );
1285 	}
1286 	return( NULL );
1287 }
1288 
1289 /* Retrieves the sub item specified by the path
1290  * Returns a Python object if successful or NULL on error
1291  */
pyolecf_item_get_sub_item_by_path(pyolecf_item_t * pyolecf_item,PyObject * arguments,PyObject * keywords)1292 PyObject *pyolecf_item_get_sub_item_by_path(
1293            pyolecf_item_t *pyolecf_item,
1294            PyObject *arguments,
1295            PyObject *keywords )
1296 {
1297 	PyObject *item_object       = NULL;
1298 	PyTypeObject *type_object   = NULL;
1299 	libcerror_error_t *error    = NULL;
1300 	libolecf_item_t *sub_item   = NULL;
1301 	static char *function       = "pyolecf_item_get_sub_item_by_path";
1302 	static char *keyword_list[] = { "path", NULL };
1303 	char *utf8_path             = NULL;
1304 	size_t utf8_path_length     = 0;
1305 	int result                  = 0;
1306 
1307 	if( pyolecf_item == NULL )
1308 	{
1309 		PyErr_Format(
1310 		 PyExc_ValueError,
1311 		 "%s: invalid item.",
1312 		 function );
1313 
1314 		return( NULL );
1315 	}
1316 	if( PyArg_ParseTupleAndKeywords(
1317 	     arguments,
1318 	     keywords,
1319 	     "s",
1320 	     keyword_list,
1321 	     &utf8_path ) == 0 )
1322 	{
1323 		goto on_error;
1324 	}
1325 	utf8_path_length = narrow_string_length(
1326 	                    utf8_path );
1327 
1328 	Py_BEGIN_ALLOW_THREADS
1329 
1330 	result = libolecf_item_get_sub_item_by_utf8_path(
1331 	          pyolecf_item->item,
1332 	          (uint8_t *) utf8_path,
1333 	          utf8_path_length,
1334 	          &sub_item,
1335 	          &error );
1336 
1337 	Py_END_ALLOW_THREADS
1338 
1339 	if( result == -1 )
1340 	{
1341 		pyolecf_error_raise(
1342 		 error,
1343 		 PyExc_IOError,
1344 		 "%s: unable to retrieve sub item.",
1345 		 function );
1346 
1347 		libcerror_error_free(
1348 		 &error );
1349 
1350 		goto on_error;
1351 	}
1352 	else if( result == 0 )
1353 	{
1354 		Py_IncRef(
1355 		 Py_None );
1356 
1357 		return( Py_None );
1358 	}
1359 	type_object = pyolecf_item_get_item_type_object(
1360 	               sub_item );
1361 
1362 	if( type_object == NULL )
1363 	{
1364 		PyErr_Format(
1365 		 PyExc_IOError,
1366 		 "%s: unable to retrieve item type object.",
1367 		 function );
1368 
1369 		goto on_error;
1370 	}
1371 	item_object = pyolecf_item_new(
1372 	               type_object,
1373 	               sub_item,
1374 	               pyolecf_item->parent_object );
1375 
1376 	if( item_object == NULL )
1377 	{
1378 		PyErr_Format(
1379 		 PyExc_MemoryError,
1380 		 "%s: unable to create sub item object.",
1381 		 function );
1382 
1383 		goto on_error;
1384 	}
1385 	return( item_object );
1386 
1387 on_error:
1388 	if( sub_item != NULL )
1389 	{
1390 		libolecf_item_free(
1391 		 &sub_item,
1392 		 NULL );
1393 	}
1394 	return( NULL );
1395 }
1396 
1397