1 /*
2  * Python object wrapper of libolecf_file_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 <narrow_string.h>
24 #include <types.h>
25 
26 #if defined( HAVE_STDLIB_H ) || defined( HAVE_WINAPI )
27 #include <stdlib.h>
28 #endif
29 
30 #include "pyolecf_codepage.h"
31 #include "pyolecf_error.h"
32 #include "pyolecf_file.h"
33 #include "pyolecf_file_object_io_handle.h"
34 #include "pyolecf_item.h"
35 #include "pyolecf_libbfio.h"
36 #include "pyolecf_libcerror.h"
37 #include "pyolecf_libclocale.h"
38 #include "pyolecf_libolecf.h"
39 #include "pyolecf_python.h"
40 #include "pyolecf_stream.h"
41 #include "pyolecf_unused.h"
42 
43 #if !defined( LIBOLECF_HAVE_BFIO )
44 
45 LIBOLECF_EXTERN \
46 int libolecf_file_open_file_io_handle(
47      libolecf_file_t *file,
48      libbfio_handle_t *file_io_handle,
49      int access_flags,
50      libolecf_error_t **error );
51 
52 #endif /* !defined( LIBOLECF_HAVE_BFIO ) */
53 
54 PyMethodDef pyolecf_file_object_methods[] = {
55 
56 	{ "signal_abort",
57 	  (PyCFunction) pyolecf_file_signal_abort,
58 	  METH_NOARGS,
59 	  "signal_abort() -> None\n"
60 	  "\n"
61 	  "Signals the file to abort the current activity." },
62 
63 	{ "open",
64 	  (PyCFunction) pyolecf_file_open,
65 	  METH_VARARGS | METH_KEYWORDS,
66 	  "open(filename, mode='r') -> None\n"
67 	  "\n"
68 	  "Opens a file." },
69 
70 	{ "open_file_object",
71 	  (PyCFunction) pyolecf_file_open_file_object,
72 	  METH_VARARGS | METH_KEYWORDS,
73 	  "open_file_object(file_object, mode='r') -> None\n"
74 	  "\n"
75 	  "Opens a file using a file-like object." },
76 
77 	{ "close",
78 	  (PyCFunction) pyolecf_file_close,
79 	  METH_NOARGS,
80 	  "close() -> None\n"
81 	  "\n"
82 	  "Closes a file." },
83 
84 	{ "get_sector_size",
85 	  (PyCFunction) pyolecf_file_get_sector_size,
86 	  METH_NOARGS,
87 	  "get_sector_size() -> Integer or None\n"
88 	  "\n"
89 	  "Retrieves the sector size." },
90 
91 	{ "get_short_sector_size",
92 	  (PyCFunction) pyolecf_file_get_short_sector_size,
93 	  METH_NOARGS,
94 	  "get_short_sector_size() -> Integer or None\n"
95 	  "\n"
96 	  "Retrieves the short sector size." },
97 
98 	{ "get_ascii_codepage",
99 	  (PyCFunction) pyolecf_file_get_ascii_codepage,
100 	  METH_NOARGS,
101 	  "get_ascii_codepage() -> String\n"
102 	  "\n"
103 	  "Retrieves the codepage for ASCII strings used in the file." },
104 
105 	{ "set_ascii_codepage",
106 	  (PyCFunction) pyolecf_file_set_ascii_codepage,
107 	  METH_VARARGS | METH_KEYWORDS,
108 	  "set_ascii_codepage(codepage) -> None\n"
109 	  "\n"
110 	  "Sets the codepage for ASCII strings used in the file.\n"
111 	  "Expects the codepage to be a string containing a Python codec definition." },
112 
113 	{ "get_format_version",
114 	  (PyCFunction) pyolecf_file_get_format_version,
115 	  METH_NOARGS,
116 	  "get_format_version() -> Unicode string or None\n"
117 	  "\n"
118 	  "Retrieves the format version." },
119 
120 	{ "get_root_item",
121 	  (PyCFunction) pyolecf_file_get_root_item,
122 	  METH_NOARGS,
123 	  "get_root_item() -> Object or None\n"
124 	  "\n"
125 	  "Retrieves the root item." },
126 
127 	{ "get_item_by_path",
128 	  (PyCFunction) pyolecf_file_get_item_by_path,
129 	  METH_VARARGS | METH_KEYWORDS,
130 	  "get_item_by_path(path) -> Object or None\n"
131 	  "\n"
132 	  "Retrieves the item specified by the path." },
133 
134 	/* Sentinel */
135 	{ NULL, NULL, 0, NULL }
136 };
137 
138 PyGetSetDef pyolecf_file_object_get_set_definitions[] = {
139 
140 	{ "sector_size",
141 	  (getter) pyolecf_file_get_sector_size,
142 	  (setter) 0,
143 	  "The sector size.",
144 	  NULL },
145 
146 	{ "short_sector_size",
147 	  (getter) pyolecf_file_get_short_sector_size,
148 	  (setter) 0,
149 	  "The short sector size.",
150 	  NULL },
151 
152 	{ "ascii_codepage",
153 	  (getter) pyolecf_file_get_ascii_codepage,
154 	  (setter) pyolecf_file_set_ascii_codepage_setter,
155 	  "The codepage used for ASCII strings in the file.",
156 	  NULL },
157 
158 	{ "format_version",
159 	  (getter) pyolecf_file_get_format_version,
160 	  (setter) 0,
161 	  "The format version.",
162 	  NULL },
163 
164 	{ "root_item",
165 	  (getter) pyolecf_file_get_root_item,
166 	  (setter) 0,
167 	  "The root item.",
168 	  NULL },
169 
170 	/* Sentinel */
171 	{ NULL, NULL, NULL, NULL, NULL }
172 };
173 
174 PyTypeObject pyolecf_file_type_object = {
175 	PyVarObject_HEAD_INIT( NULL, 0 )
176 
177 	/* tp_name */
178 	"pyolecf.file",
179 	/* tp_basicsize */
180 	sizeof( pyolecf_file_t ),
181 	/* tp_itemsize */
182 	0,
183 	/* tp_dealloc */
184 	(destructor) pyolecf_file_free,
185 	/* tp_print */
186 	0,
187 	/* tp_getattr */
188 	0,
189 	/* tp_setattr */
190 	0,
191 	/* tp_compare */
192 	0,
193 	/* tp_repr */
194 	0,
195 	/* tp_as_number */
196 	0,
197 	/* tp_as_sequence */
198 	0,
199 	/* tp_as_mapping */
200 	0,
201 	/* tp_hash */
202 	0,
203 	/* tp_call */
204 	0,
205 	/* tp_str */
206 	0,
207 	/* tp_getattro */
208 	0,
209 	/* tp_setattro */
210 	0,
211 	/* tp_as_buffer */
212 	0,
213 	/* tp_flags */
214 	Py_TPFLAGS_DEFAULT,
215 	/* tp_doc */
216 	"pyolecf file object (wraps libolecf_file_t)",
217 	/* tp_traverse */
218 	0,
219 	/* tp_clear */
220 	0,
221 	/* tp_richcompare */
222 	0,
223 	/* tp_weaklistoffset */
224 	0,
225 	/* tp_iter */
226 	0,
227 	/* tp_iternext */
228 	0,
229 	/* tp_methods */
230 	pyolecf_file_object_methods,
231 	/* tp_members */
232 	0,
233 	/* tp_getset */
234 	pyolecf_file_object_get_set_definitions,
235 	/* tp_base */
236 	0,
237 	/* tp_dict */
238 	0,
239 	/* tp_descr_get */
240 	0,
241 	/* tp_descr_set */
242 	0,
243 	/* tp_dictoffset */
244 	0,
245 	/* tp_init */
246 	(initproc) pyolecf_file_init,
247 	/* tp_alloc */
248 	0,
249 	/* tp_new */
250 	0,
251 	/* tp_free */
252 	0,
253 	/* tp_is_gc */
254 	0,
255 	/* tp_bases */
256 	NULL,
257 	/* tp_mro */
258 	NULL,
259 	/* tp_cache */
260 	NULL,
261 	/* tp_subclasses */
262 	NULL,
263 	/* tp_weaklist */
264 	NULL,
265 	/* tp_del */
266 	0
267 };
268 
269 /* Initializes a file object
270  * Returns 0 if successful or -1 on error
271  */
pyolecf_file_init(pyolecf_file_t * pyolecf_file)272 int pyolecf_file_init(
273      pyolecf_file_t *pyolecf_file )
274 {
275 	libcerror_error_t *error = NULL;
276 	static char *function    = "pyolecf_file_init";
277 
278 	if( pyolecf_file == NULL )
279 	{
280 		PyErr_Format(
281 		 PyExc_ValueError,
282 		 "%s: invalid file.",
283 		 function );
284 
285 		return( -1 );
286 	}
287 	/* Make sure libolecf file is set to NULL
288 	 */
289 	pyolecf_file->file           = NULL;
290 	pyolecf_file->file_io_handle = NULL;
291 
292 	if( libolecf_file_initialize(
293 	     &( pyolecf_file->file ),
294 	     &error ) != 1 )
295 	{
296 		pyolecf_error_raise(
297 		 error,
298 		 PyExc_MemoryError,
299 		 "%s: unable to initialize file.",
300 		 function );
301 
302 		libcerror_error_free(
303 		 &error );
304 
305 		return( -1 );
306 	}
307 	return( 0 );
308 }
309 
310 /* Frees a file object
311  */
pyolecf_file_free(pyolecf_file_t * pyolecf_file)312 void pyolecf_file_free(
313       pyolecf_file_t *pyolecf_file )
314 {
315 	struct _typeobject *ob_type = NULL;
316 	libcerror_error_t *error    = NULL;
317 	static char *function       = "pyolecf_file_free";
318 	int result                  = 0;
319 
320 	if( pyolecf_file == NULL )
321 	{
322 		PyErr_Format(
323 		 PyExc_ValueError,
324 		 "%s: invalid file.",
325 		 function );
326 
327 		return;
328 	}
329 	ob_type = Py_TYPE(
330 	           pyolecf_file );
331 
332 	if( ob_type == NULL )
333 	{
334 		PyErr_Format(
335 		 PyExc_ValueError,
336 		 "%s: missing ob_type.",
337 		 function );
338 
339 		return;
340 	}
341 	if( ob_type->tp_free == NULL )
342 	{
343 		PyErr_Format(
344 		 PyExc_ValueError,
345 		 "%s: invalid ob_type - missing tp_free.",
346 		 function );
347 
348 		return;
349 	}
350 	if( pyolecf_file->file != NULL )
351 	{
352 		Py_BEGIN_ALLOW_THREADS
353 
354 		result = libolecf_file_free(
355 		          &( pyolecf_file->file ),
356 		          &error );
357 
358 		Py_END_ALLOW_THREADS
359 
360 		if( result != 1 )
361 		{
362 			pyolecf_error_raise(
363 			 error,
364 			 PyExc_MemoryError,
365 			 "%s: unable to free libolecf file.",
366 			 function );
367 
368 			libcerror_error_free(
369 			 &error );
370 		}
371 	}
372 	ob_type->tp_free(
373 	 (PyObject*) pyolecf_file );
374 }
375 
376 /* Signals the file to abort the current activity
377  * Returns a Python object if successful or NULL on error
378  */
pyolecf_file_signal_abort(pyolecf_file_t * pyolecf_file,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)379 PyObject *pyolecf_file_signal_abort(
380            pyolecf_file_t *pyolecf_file,
381            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
382 {
383 	libcerror_error_t *error = NULL;
384 	static char *function    = "pyolecf_file_signal_abort";
385 	int result               = 0;
386 
387 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
388 
389 	if( pyolecf_file == NULL )
390 	{
391 		PyErr_Format(
392 		 PyExc_ValueError,
393 		 "%s: invalid file.",
394 		 function );
395 
396 		return( NULL );
397 	}
398 	Py_BEGIN_ALLOW_THREADS
399 
400 	result = libolecf_file_signal_abort(
401 	          pyolecf_file->file,
402 	          &error );
403 
404 	Py_END_ALLOW_THREADS
405 
406 	if( result != 1 )
407 	{
408 		pyolecf_error_raise(
409 		 error,
410 		 PyExc_IOError,
411 		 "%s: unable to signal abort.",
412 		 function );
413 
414 		libcerror_error_free(
415 		 &error );
416 
417 		return( NULL );
418 	}
419 	Py_IncRef(
420 	 Py_None );
421 
422 	return( Py_None );
423 }
424 
425 /* Opens a file
426  * Returns a Python object if successful or NULL on error
427  */
pyolecf_file_open(pyolecf_file_t * pyolecf_file,PyObject * arguments,PyObject * keywords)428 PyObject *pyolecf_file_open(
429            pyolecf_file_t *pyolecf_file,
430            PyObject *arguments,
431            PyObject *keywords )
432 {
433 	PyObject *string_object      = NULL;
434 	libcerror_error_t *error     = NULL;
435 	const char *filename_narrow  = NULL;
436 	static char *function        = "pyolecf_file_open";
437 	static char *keyword_list[]  = { "filename", "mode", NULL };
438 	char *mode                   = NULL;
439 	int result                   = 0;
440 
441 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
442 	const wchar_t *filename_wide = NULL;
443 #else
444 	PyObject *utf8_string_object = NULL;
445 #endif
446 
447 	if( pyolecf_file == NULL )
448 	{
449 		PyErr_Format(
450 		 PyExc_ValueError,
451 		 "%s: invalid file.",
452 		 function );
453 
454 		return( NULL );
455 	}
456 	/* Note that PyArg_ParseTupleAndKeywords with "s" will force Unicode strings to be converted to narrow character string.
457 	 * On Windows the narrow character strings contains an extended ASCII string with a codepage. Hence we get a conversion
458 	 * exception. This will also fail if the default encoding is not set correctly. We cannot use "u" here either since that
459 	 * does not allow us to pass non Unicode string objects and Python (at least 2.7) does not seems to automatically upcast them.
460 	 */
461 	if( PyArg_ParseTupleAndKeywords(
462 	     arguments,
463 	     keywords,
464 	     "O|s",
465 	     keyword_list,
466 	     &string_object,
467 	     &mode ) == 0 )
468 	{
469 		return( NULL );
470 	}
471 	if( ( mode != NULL )
472 	 && ( mode[ 0 ] != 'r' ) )
473 	{
474 		PyErr_Format(
475 		 PyExc_ValueError,
476 		 "%s: unsupported mode: %s.",
477 		 function,
478 		 mode );
479 
480 		return( NULL );
481 	}
482 	PyErr_Clear();
483 
484 	result = PyObject_IsInstance(
485 	          string_object,
486 	          (PyObject *) &PyUnicode_Type );
487 
488 	if( result == -1 )
489 	{
490 		pyolecf_error_fetch_and_raise(
491 		 PyExc_RuntimeError,
492 		 "%s: unable to determine if string object is of type unicode.",
493 		 function );
494 
495 		return( NULL );
496 	}
497 	else if( result != 0 )
498 	{
499 		PyErr_Clear();
500 
501 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
502 		filename_wide = (wchar_t *) PyUnicode_AsUnicode(
503 		                             string_object );
504 		Py_BEGIN_ALLOW_THREADS
505 
506 		result = libolecf_file_open_wide(
507 		          pyolecf_file->file,
508 		          filename_wide,
509 		          LIBOLECF_OPEN_READ,
510 		          &error );
511 
512 		Py_END_ALLOW_THREADS
513 #else
514 		utf8_string_object = PyUnicode_AsUTF8String(
515 		                      string_object );
516 
517 		if( utf8_string_object == NULL )
518 		{
519 			pyolecf_error_fetch_and_raise(
520 			 PyExc_RuntimeError,
521 			 "%s: unable to convert unicode string to UTF-8.",
522 			 function );
523 
524 			return( NULL );
525 		}
526 #if PY_MAJOR_VERSION >= 3
527 		filename_narrow = PyBytes_AsString(
528 		                   utf8_string_object );
529 #else
530 		filename_narrow = PyString_AsString(
531 		                   utf8_string_object );
532 #endif
533 		Py_BEGIN_ALLOW_THREADS
534 
535 		result = libolecf_file_open(
536 		          pyolecf_file->file,
537 		          filename_narrow,
538 		          LIBOLECF_OPEN_READ,
539 		          &error );
540 
541 		Py_END_ALLOW_THREADS
542 
543 		Py_DecRef(
544 		 utf8_string_object );
545 #endif
546 		if( result != 1 )
547 		{
548 			pyolecf_error_raise(
549 			 error,
550 			 PyExc_IOError,
551 			 "%s: unable to open file.",
552 			 function );
553 
554 			libcerror_error_free(
555 			 &error );
556 
557 			return( NULL );
558 		}
559 		Py_IncRef(
560 		 Py_None );
561 
562 		return( Py_None );
563 	}
564 	PyErr_Clear();
565 
566 #if PY_MAJOR_VERSION >= 3
567 	result = PyObject_IsInstance(
568 	          string_object,
569 	          (PyObject *) &PyBytes_Type );
570 #else
571 	result = PyObject_IsInstance(
572 	          string_object,
573 	          (PyObject *) &PyString_Type );
574 #endif
575 	if( result == -1 )
576 	{
577 		pyolecf_error_fetch_and_raise(
578 		 PyExc_RuntimeError,
579 		 "%s: unable to determine if string object is of type string.",
580 		 function );
581 
582 		return( NULL );
583 	}
584 	else if( result != 0 )
585 	{
586 		PyErr_Clear();
587 
588 #if PY_MAJOR_VERSION >= 3
589 		filename_narrow = PyBytes_AsString(
590 		                   string_object );
591 #else
592 		filename_narrow = PyString_AsString(
593 		                   string_object );
594 #endif
595 		Py_BEGIN_ALLOW_THREADS
596 
597 		result = libolecf_file_open(
598 		          pyolecf_file->file,
599 		          filename_narrow,
600 		          LIBOLECF_OPEN_READ,
601 		          &error );
602 
603 		Py_END_ALLOW_THREADS
604 
605 		if( result != 1 )
606 		{
607 			pyolecf_error_raise(
608 			 error,
609 			 PyExc_IOError,
610 			 "%s: unable to open file.",
611 			 function );
612 
613 			libcerror_error_free(
614 			 &error );
615 
616 			return( NULL );
617 		}
618 		Py_IncRef(
619 		 Py_None );
620 
621 		return( Py_None );
622 	}
623 	PyErr_Format(
624 	 PyExc_TypeError,
625 	 "%s: unsupported string object type.",
626 	 function );
627 
628 	return( NULL );
629 }
630 
631 /* Opens a file using a file-like object
632  * Returns a Python object if successful or NULL on error
633  */
pyolecf_file_open_file_object(pyolecf_file_t * pyolecf_file,PyObject * arguments,PyObject * keywords)634 PyObject *pyolecf_file_open_file_object(
635            pyolecf_file_t *pyolecf_file,
636            PyObject *arguments,
637            PyObject *keywords )
638 {
639 	PyObject *file_object       = NULL;
640 	libcerror_error_t *error    = NULL;
641 	static char *function       = "pyolecf_file_open_file_object";
642 	static char *keyword_list[] = { "file_object", "mode", NULL };
643 	char *mode                  = NULL;
644 	int result                  = 0;
645 
646 	if( pyolecf_file == NULL )
647 	{
648 		PyErr_Format(
649 		 PyExc_ValueError,
650 		 "%s: invalid file.",
651 		 function );
652 
653 		return( NULL );
654 	}
655 	if( PyArg_ParseTupleAndKeywords(
656 	     arguments,
657 	     keywords,
658 	     "O|s",
659 	     keyword_list,
660 	     &file_object,
661 	     &mode ) == 0 )
662 	{
663 		return( NULL );
664 	}
665 	if( ( mode != NULL )
666 	 && ( mode[ 0 ] != 'r' ) )
667 	{
668 		PyErr_Format(
669 		 PyExc_ValueError,
670 		 "%s: unsupported mode: %s.",
671 		 function,
672 		 mode );
673 
674 		return( NULL );
675 	}
676 	PyErr_Clear();
677 
678 	result = PyObject_HasAttrString(
679 	          file_object,
680 	          "read" );
681 
682 	if( result != 1 )
683 	{
684 		PyErr_Format(
685 		 PyExc_TypeError,
686 		 "%s: unsupported file object - missing read attribute.",
687 		 function );
688 
689 		return( NULL );
690 	}
691 	PyErr_Clear();
692 
693 	result = PyObject_HasAttrString(
694 	          file_object,
695 	          "seek" );
696 
697 	if( result != 1 )
698 	{
699 		PyErr_Format(
700 		 PyExc_TypeError,
701 		 "%s: unsupported file object - missing seek attribute.",
702 		 function );
703 
704 		return( NULL );
705 	}
706 	if( pyolecf_file->file_io_handle != NULL )
707 	{
708 		pyolecf_error_raise(
709 		 error,
710 		 PyExc_IOError,
711 		 "%s: invalid file - file IO handle already set.",
712 		 function );
713 
714 		return( NULL );
715 	}
716 	if( pyolecf_file_object_initialize(
717 	     &( pyolecf_file->file_io_handle ),
718 	     file_object,
719 	     &error ) != 1 )
720 	{
721 		pyolecf_error_raise(
722 		 error,
723 		 PyExc_MemoryError,
724 		 "%s: unable to initialize file IO handle.",
725 		 function );
726 
727 		libcerror_error_free(
728 		 &error );
729 
730 		goto on_error;
731 	}
732 	Py_BEGIN_ALLOW_THREADS
733 
734 	result = libolecf_file_open_file_io_handle(
735 	          pyolecf_file->file,
736 	          pyolecf_file->file_io_handle,
737 	          LIBOLECF_OPEN_READ,
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 open file.",
748 		 function );
749 
750 		libcerror_error_free(
751 		 &error );
752 
753 		goto on_error;
754 	}
755 	Py_IncRef(
756 	 Py_None );
757 
758 	return( Py_None );
759 
760 on_error:
761 	if( pyolecf_file->file_io_handle != NULL )
762 	{
763 		libbfio_handle_free(
764 		 &( pyolecf_file->file_io_handle ),
765 		 NULL );
766 	}
767 	return( NULL );
768 }
769 
770 /* Closes a file
771  * Returns a Python object if successful or NULL on error
772  */
pyolecf_file_close(pyolecf_file_t * pyolecf_file,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)773 PyObject *pyolecf_file_close(
774            pyolecf_file_t *pyolecf_file,
775            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
776 {
777 	libcerror_error_t *error = NULL;
778 	static char *function    = "pyolecf_file_close";
779 	int result               = 0;
780 
781 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
782 
783 	if( pyolecf_file == NULL )
784 	{
785 		PyErr_Format(
786 		 PyExc_ValueError,
787 		 "%s: invalid file.",
788 		 function );
789 
790 		return( NULL );
791 	}
792 	Py_BEGIN_ALLOW_THREADS
793 
794 	result = libolecf_file_close(
795 	          pyolecf_file->file,
796 	          &error );
797 
798 	Py_END_ALLOW_THREADS
799 
800 	if( result != 0 )
801 	{
802 		pyolecf_error_raise(
803 		 error,
804 		 PyExc_IOError,
805 		 "%s: unable to close file.",
806 		 function );
807 
808 		libcerror_error_free(
809 		 &error );
810 
811 		return( NULL );
812 	}
813 	if( pyolecf_file->file_io_handle != NULL )
814 	{
815 		Py_BEGIN_ALLOW_THREADS
816 
817 		result = libbfio_handle_free(
818 		          &( pyolecf_file->file_io_handle ),
819 		          &error );
820 
821 		Py_END_ALLOW_THREADS
822 
823 		if( result != 1 )
824 		{
825 			pyolecf_error_raise(
826 			 error,
827 			 PyExc_IOError,
828 			 "%s: unable to free libbfio file IO handle.",
829 			 function );
830 
831 			libcerror_error_free(
832 			 &error );
833 
834 			return( NULL );
835 		}
836 	}
837 	Py_IncRef(
838 	 Py_None );
839 
840 	return( Py_None );
841 }
842 
843 /* Retrieves the sector size
844  * Returns a Python object if successful or NULL on error
845  */
pyolecf_file_get_sector_size(pyolecf_file_t * pyolecf_file,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)846 PyObject *pyolecf_file_get_sector_size(
847            pyolecf_file_t *pyolecf_file,
848            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
849 {
850 	PyObject *integer_object = NULL;
851 	libcerror_error_t *error = NULL;
852 	static char *function    = "pyolecf_file_get_sector_size";
853 	size32_t sector_size     = 0;
854 	int result               = 0;
855 
856 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
857 
858 	if( pyolecf_file == NULL )
859 	{
860 		PyErr_Format(
861 		 PyExc_ValueError,
862 		 "%s: invalid file.",
863 		 function );
864 
865 		return( NULL );
866 	}
867 	Py_BEGIN_ALLOW_THREADS
868 
869 	result = libolecf_file_get_sector_size(
870 	          pyolecf_file->file,
871 	          &sector_size,
872 	          &error );
873 
874 	Py_END_ALLOW_THREADS
875 
876 	if( result != 1 )
877 	{
878 		pyolecf_error_raise(
879 		 error,
880 		 PyExc_IOError,
881 		 "%s: failed to retrieve sector size.",
882 		 function );
883 
884 		libcerror_error_free(
885 		 &error );
886 
887 		return( NULL );
888 	}
889 	integer_object = PyLong_FromUnsignedLong(
890 	                  (unsigned long) sector_size );
891 
892 	return( integer_object );
893 }
894 
895 /* Retrieves the short sector size
896  * Returns a Python object if successful or NULL on error
897  */
pyolecf_file_get_short_sector_size(pyolecf_file_t * pyolecf_file,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)898 PyObject *pyolecf_file_get_short_sector_size(
899            pyolecf_file_t *pyolecf_file,
900            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
901 {
902 	PyObject *integer_object   = NULL;
903 	libcerror_error_t *error   = NULL;
904 	static char *function      = "pyolecf_file_get_short_sector_size";
905 	size32_t short_sector_size = 0;
906 	int result                 = 0;
907 
908 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
909 
910 	if( pyolecf_file == NULL )
911 	{
912 		PyErr_Format(
913 		 PyExc_ValueError,
914 		 "%s: invalid file.",
915 		 function );
916 
917 		return( NULL );
918 	}
919 	Py_BEGIN_ALLOW_THREADS
920 
921 	result = libolecf_file_get_short_sector_size(
922 	          pyolecf_file->file,
923 	          &short_sector_size,
924 	          &error );
925 
926 	Py_END_ALLOW_THREADS
927 
928 	if( result != 1 )
929 	{
930 		pyolecf_error_raise(
931 		 error,
932 		 PyExc_IOError,
933 		 "%s: failed to retrieve short sector size.",
934 		 function );
935 
936 		libcerror_error_free(
937 		 &error );
938 
939 		return( NULL );
940 	}
941 	integer_object = PyLong_FromUnsignedLong(
942 	                  (unsigned long) short_sector_size );
943 
944 	return( integer_object );
945 }
946 
947 /* Retrieves the codepage used for ASCII strings in the file
948  * Returns a Python object if successful or NULL on error
949  */
pyolecf_file_get_ascii_codepage(pyolecf_file_t * pyolecf_file,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)950 PyObject *pyolecf_file_get_ascii_codepage(
951            pyolecf_file_t *pyolecf_file,
952            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
953 {
954 	PyObject *string_object     = NULL;
955 	libcerror_error_t *error    = NULL;
956 	const char *codepage_string = NULL;
957 	static char *function       = "pyolecf_file_get_ascii_codepage";
958 	int ascii_codepage          = 0;
959 	int result                  = 0;
960 
961 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
962 
963 	if( pyolecf_file == NULL )
964 	{
965 		PyErr_Format(
966 		 PyExc_ValueError,
967 		 "%s: invalid file.",
968 		 function );
969 
970 		return( NULL );
971 	}
972 	Py_BEGIN_ALLOW_THREADS
973 
974 	result = libolecf_file_get_ascii_codepage(
975 	          pyolecf_file->file,
976 	          &ascii_codepage,
977 	          &error );
978 
979 	Py_END_ALLOW_THREADS
980 
981 	if( result != 1 )
982 	{
983 		pyolecf_error_raise(
984 		 error,
985 		 PyExc_IOError,
986 		 "%s: unable to retrieve ASCII codepage.",
987 		 function );
988 
989 		libcerror_error_free(
990 		 &error );
991 
992 		return( NULL );
993 	}
994 	codepage_string = pyolecf_codepage_to_string(
995 	                   ascii_codepage );
996 
997 	if( codepage_string == NULL )
998 	{
999 		PyErr_Format(
1000 		 PyExc_ValueError,
1001 		 "%s: unsupported ASCII codepage: %d.",
1002 		 function,
1003 		 ascii_codepage );
1004 
1005 		return( NULL );
1006 	}
1007 #if PY_MAJOR_VERSION >= 3
1008 	string_object = PyBytes_FromString(
1009 	                 codepage_string );
1010 #else
1011 	string_object = PyString_FromString(
1012 	                 codepage_string );
1013 #endif
1014 	if( string_object == NULL )
1015 	{
1016 		PyErr_Format(
1017 		 PyExc_IOError,
1018 		 "%s: unable to convert codepage string into string object.",
1019 		 function );
1020 
1021 		return( NULL );
1022 	}
1023 	return( string_object );
1024 }
1025 
1026 /* Sets the codepage used for ASCII strings in the file
1027  * Returns 1 if successful or -1 on error
1028  */
pyolecf_file_set_ascii_codepage_from_string(pyolecf_file_t * pyolecf_file,const char * codepage_string)1029 int pyolecf_file_set_ascii_codepage_from_string(
1030      pyolecf_file_t *pyolecf_file,
1031      const char *codepage_string )
1032 {
1033 	libcerror_error_t *error      = NULL;
1034 	static char *function         = "pyolecf_file_set_ascii_codepage_from_string";
1035 	size_t codepage_string_length = 0;
1036 	uint32_t feature_flags        = 0;
1037 	int ascii_codepage            = 0;
1038 	int result                    = 0;
1039 
1040 	if( pyolecf_file == NULL )
1041 	{
1042 		PyErr_Format(
1043 		 PyExc_ValueError,
1044 		 "%s: invalid file.",
1045 		 function );
1046 
1047 		return( -1 );
1048 	}
1049 	if( codepage_string == NULL )
1050 	{
1051 		PyErr_Format(
1052 		 PyExc_ValueError,
1053 		 "%s: invalid codepage string.",
1054 		 function );
1055 
1056 		return( -1 );
1057 	}
1058 	codepage_string_length = narrow_string_length(
1059 	                          codepage_string );
1060 
1061 	feature_flags = LIBCLOCALE_CODEPAGE_FEATURE_FLAG_HAVE_WINDOWS;
1062 
1063 	if( libclocale_codepage_copy_from_string(
1064 	     &ascii_codepage,
1065 	     codepage_string,
1066 	     codepage_string_length,
1067 	     feature_flags,
1068 	     &error ) != 1 )
1069 	{
1070 		pyolecf_error_raise(
1071 		 error,
1072 		 PyExc_RuntimeError,
1073 		 "%s: unable to determine ASCII codepage.",
1074 		 function );
1075 
1076 		libcerror_error_free(
1077 		 &error );
1078 
1079 		return( -1 );
1080 	}
1081 	Py_BEGIN_ALLOW_THREADS
1082 
1083 	result = libolecf_file_set_ascii_codepage(
1084 	          pyolecf_file->file,
1085 	          ascii_codepage,
1086 	          &error );
1087 
1088 	Py_END_ALLOW_THREADS
1089 
1090 	if( result != 1 )
1091 	{
1092 		pyolecf_error_raise(
1093 		 error,
1094 		 PyExc_IOError,
1095 		 "%s: unable to set ASCII codepage.",
1096 		 function );
1097 
1098 		libcerror_error_free(
1099 		 &error );
1100 
1101 		return( -1 );
1102 	}
1103 	return( 1 );
1104 }
1105 
1106 /* Sets the codepage used for ASCII strings in the file
1107  * Returns a Python object if successful or NULL on error
1108  */
pyolecf_file_set_ascii_codepage(pyolecf_file_t * pyolecf_file,PyObject * arguments,PyObject * keywords)1109 PyObject *pyolecf_file_set_ascii_codepage(
1110            pyolecf_file_t *pyolecf_file,
1111            PyObject *arguments,
1112            PyObject *keywords )
1113 {
1114 	char *codepage_string       = NULL;
1115 	static char *keyword_list[] = { "codepage", NULL };
1116 	int result                  = 0;
1117 
1118 	if( PyArg_ParseTupleAndKeywords(
1119 	     arguments,
1120 	     keywords,
1121 	     "s",
1122 	     keyword_list,
1123 	     &codepage_string ) == 0 )
1124 	{
1125 		return( NULL );
1126 	}
1127 	result = pyolecf_file_set_ascii_codepage_from_string(
1128 	          pyolecf_file,
1129 	          codepage_string );
1130 
1131 	if( result != 1 )
1132 	{
1133 		return( NULL );
1134 	}
1135 	Py_IncRef(
1136 	 Py_None );
1137 
1138 	return( Py_None );
1139 }
1140 
1141 /* Sets the codepage used for ASCII strings in the file
1142  * Returns a Python object if successful or NULL on error
1143  */
pyolecf_file_set_ascii_codepage_setter(pyolecf_file_t * pyolecf_file,PyObject * string_object,void * closure PYOLECF_ATTRIBUTE_UNUSED)1144 int pyolecf_file_set_ascii_codepage_setter(
1145      pyolecf_file_t *pyolecf_file,
1146      PyObject *string_object,
1147      void *closure PYOLECF_ATTRIBUTE_UNUSED )
1148 {
1149 	PyObject *utf8_string_object = NULL;
1150 	char *codepage_string        = NULL;
1151 	static char *function        = "pyolecf_file_set_ascii_codepage_setter";
1152 	int result                   = 0;
1153 
1154 	PYOLECF_UNREFERENCED_PARAMETER( closure )
1155 
1156 	PyErr_Clear();
1157 
1158 	result = PyObject_IsInstance(
1159 	          string_object,
1160 	          (PyObject *) &PyUnicode_Type );
1161 
1162 	if( result == -1 )
1163 	{
1164 		pyolecf_error_fetch_and_raise(
1165 		 PyExc_RuntimeError,
1166 		 "%s: unable to determine if string object is of type unicode.",
1167 		 function );
1168 
1169 		return( -1 );
1170 	}
1171 	else if( result != 0 )
1172 	{
1173 		/* The codepage string should only contain ASCII characters.
1174 		 */
1175 		utf8_string_object = PyUnicode_AsUTF8String(
1176 		                      string_object );
1177 
1178 		if( utf8_string_object == NULL )
1179 		{
1180 			pyolecf_error_fetch_and_raise(
1181 			 PyExc_RuntimeError,
1182 			 "%s: unable to convert unicode string to UTF-8.",
1183 			 function );
1184 
1185 			return( -1 );
1186 		}
1187 #if PY_MAJOR_VERSION >= 3
1188 		codepage_string = PyBytes_AsString(
1189 		                   utf8_string_object );
1190 #else
1191 		codepage_string = PyString_AsString(
1192 		                   utf8_string_object );
1193 #endif
1194 		if( codepage_string == NULL )
1195 		{
1196 			return( -1 );
1197 		}
1198 		result = pyolecf_file_set_ascii_codepage_from_string(
1199 		          pyolecf_file,
1200 		          codepage_string );
1201 
1202 		if( result != 1 )
1203 		{
1204 			return( -1 );
1205 		}
1206 		return( 0 );
1207 	}
1208 	PyErr_Clear();
1209 
1210 #if PY_MAJOR_VERSION >= 3
1211 	result = PyObject_IsInstance(
1212 	          string_object,
1213 	          (PyObject *) &PyBytes_Type );
1214 #else
1215 	result = PyObject_IsInstance(
1216 	          string_object,
1217 	          (PyObject *) &PyString_Type );
1218 #endif
1219 	if( result == -1 )
1220 	{
1221 		pyolecf_error_fetch_and_raise(
1222 		 PyExc_RuntimeError,
1223 		 "%s: unable to determine if string object is of type string.",
1224 		 function );
1225 
1226 		return( -1 );
1227 	}
1228 	else if( result != 0 )
1229 	{
1230 #if PY_MAJOR_VERSION >= 3
1231 		codepage_string = PyBytes_AsString(
1232 		                   string_object );
1233 #else
1234 		codepage_string = PyString_AsString(
1235 		                   string_object );
1236 #endif
1237 		if( codepage_string == NULL )
1238 		{
1239 			return( -1 );
1240 		}
1241 		result = pyolecf_file_set_ascii_codepage_from_string(
1242 		          pyolecf_file,
1243 		          codepage_string );
1244 
1245 		if( result != 1 )
1246 		{
1247 			return( -1 );
1248 		}
1249 		return( 0 );
1250 	}
1251 	PyErr_Format(
1252 	 PyExc_TypeError,
1253 	 "%s: unsupported string object type.",
1254 	 function );
1255 
1256 	return( -1 );
1257 }
1258 
1259 /* Retrieves the format version
1260  * Returns a Python object if successful or NULL on error
1261  */
pyolecf_file_get_format_version(pyolecf_file_t * pyolecf_file,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)1262 PyObject *pyolecf_file_get_format_version(
1263            pyolecf_file_t *pyolecf_file,
1264            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
1265 {
1266 	char utf8_string[ 4 ];
1267 
1268 	PyObject *string_object  = NULL;
1269 	libcerror_error_t *error = NULL;
1270 	const char *errors       = NULL;
1271 	static char *function    = "pyolecf_file_get_format_version";
1272 	uint16_t major_version   = 0;
1273 	uint16_t minor_version   = 0;
1274 	int result               = 0;
1275 
1276 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
1277 
1278 	if( pyolecf_file == NULL )
1279 	{
1280 		PyErr_Format(
1281 		 PyExc_ValueError,
1282 		 "%s: invalid file.",
1283 		 function );
1284 
1285 		return( NULL );
1286 	}
1287 	Py_BEGIN_ALLOW_THREADS
1288 
1289 	result = libolecf_file_get_format_version(
1290 	          pyolecf_file->file,
1291 	          &major_version,
1292 	          &minor_version,
1293 	          &error );
1294 
1295 	Py_END_ALLOW_THREADS
1296 
1297 	if( result != 1 )
1298 	{
1299 		pyolecf_error_raise(
1300 		 error,
1301 		 PyExc_IOError,
1302 		 "%s: unable to retrieve format version.",
1303 		 function );
1304 
1305 		libcerror_error_free(
1306 		 &error );
1307 
1308 		return( NULL );
1309 	}
1310 	if( major_version > 9 )
1311 	{
1312 		PyErr_Format(
1313 		 PyExc_ValueError,
1314 		 "%s: major version out of bounds.",
1315 		 function );
1316 
1317 		return( NULL );
1318 	}
1319 	if( minor_version > 9 )
1320 	{
1321 		PyErr_Format(
1322 		 PyExc_ValueError,
1323 		 "%s: minor version out of bounds.",
1324 		 function );
1325 
1326 		return( NULL );
1327 	}
1328 	utf8_string[ 0 ] = '0' + (char) major_version;
1329 	utf8_string[ 1 ] = '.';
1330 	utf8_string[ 2 ] = '0' + (char) minor_version;
1331 	utf8_string[ 3 ] = 0;
1332 
1333 	/* Pass the string length to PyUnicode_DecodeUTF8 otherwise it makes
1334 	 * the end of string character is part of the string
1335 	 */
1336 	string_object = PyUnicode_DecodeUTF8(
1337 	                 utf8_string,
1338 	                 (Py_ssize_t) 3,
1339 	                 errors );
1340 
1341 	if( string_object == NULL )
1342 	{
1343 		PyErr_Format(
1344 		 PyExc_IOError,
1345 		 "%s: unable to convert UTF-8 string into Unicode object.",
1346 		 function );
1347 
1348 		return( NULL );
1349 	}
1350 	return( string_object );
1351 }
1352 
1353 /* Retrieves the item type object
1354  * Returns a Python type object if successful or NULL on error
1355  */
pyolecf_file_get_item_type_object(libolecf_item_t * item)1356 PyTypeObject *pyolecf_file_get_item_type_object(
1357                libolecf_item_t *item )
1358 {
1359 	libcerror_error_t *error = NULL;
1360 	static char *function    = "pyolecf_file_get_item_type_object";
1361 	uint8_t item_type        = 0;
1362 	int result               = 0;
1363 
1364 	if( item == NULL )
1365 	{
1366 		PyErr_Format(
1367 		 PyExc_TypeError,
1368 		 "%s: invalid item.",
1369 		 function );
1370 
1371 		return( NULL );
1372 	}
1373 	Py_BEGIN_ALLOW_THREADS
1374 
1375 	result = libolecf_item_get_type(
1376 	          item,
1377 	          &item_type,
1378 	          &error );
1379 
1380 	Py_END_ALLOW_THREADS
1381 
1382 	if( result == -1 )
1383 	{
1384 		pyolecf_error_raise(
1385 		 error,
1386 		 PyExc_IOError,
1387 		 "%s: unable to retrieve item type.",
1388 		 function );
1389 
1390 		libcerror_error_free(
1391 		 &error );
1392 
1393 		return( NULL );
1394 	}
1395 	if( item_type == LIBOLECF_ITEM_TYPE_STREAM )
1396 	{
1397 		return( &pyolecf_stream_type_object );
1398 	}
1399 	return( &pyolecf_item_type_object );
1400 }
1401 
1402 /* Retrieves the root item
1403  * Returns a Python object if successful or NULL on error
1404  */
pyolecf_file_get_root_item(pyolecf_file_t * pyolecf_file,PyObject * arguments PYOLECF_ATTRIBUTE_UNUSED)1405 PyObject *pyolecf_file_get_root_item(
1406            pyolecf_file_t *pyolecf_file,
1407            PyObject *arguments PYOLECF_ATTRIBUTE_UNUSED )
1408 {
1409 	PyObject *item_object      = NULL;
1410 	PyTypeObject *type_object  = NULL;
1411 	libcerror_error_t *error   = NULL;
1412 	libolecf_item_t *root_item = NULL;
1413 	static char *function      = "pyolecf_file_get_root_item";
1414 	int result                 = 0;
1415 
1416 	PYOLECF_UNREFERENCED_PARAMETER( arguments )
1417 
1418 	if( pyolecf_file == NULL )
1419 	{
1420 		PyErr_Format(
1421 		 PyExc_ValueError,
1422 		 "%s: invalid file.",
1423 		 function );
1424 
1425 		return( NULL );
1426 	}
1427 	Py_BEGIN_ALLOW_THREADS
1428 
1429 	result = libolecf_file_get_root_item(
1430 	          pyolecf_file->file,
1431 	          &root_item,
1432 	          &error );
1433 
1434 	Py_END_ALLOW_THREADS
1435 
1436 	if( result == -1 )
1437 	{
1438 		pyolecf_error_raise(
1439 		 error,
1440 		 PyExc_IOError,
1441 		 "%s: unable to retrieve root item.",
1442 		 function );
1443 
1444 		libcerror_error_free(
1445 		 &error );
1446 
1447 		goto on_error;
1448 	}
1449 	else if( result == 0 )
1450 	{
1451 		Py_IncRef(
1452 		 Py_None );
1453 
1454 		return( Py_None );
1455 	}
1456 	type_object = pyolecf_file_get_item_type_object(
1457 	               root_item );
1458 
1459 	if( type_object == NULL )
1460 	{
1461 		PyErr_Format(
1462 		 PyExc_IOError,
1463 		 "%s: unable to retrieve root item type object.",
1464 		 function );
1465 
1466 		goto on_error;
1467 	}
1468 	item_object = pyolecf_item_new(
1469 	               type_object,
1470 	               root_item,
1471 	               (PyObject *) pyolecf_file );
1472 
1473 	if( item_object == NULL )
1474 	{
1475 		PyErr_Format(
1476 		 PyExc_MemoryError,
1477 		 "%s: unable to create item object.",
1478 		 function );
1479 
1480 		goto on_error;
1481 	}
1482 	return( item_object );
1483 
1484 on_error:
1485 	if( root_item != NULL )
1486 	{
1487 		libolecf_item_free(
1488 		 &root_item,
1489 		 NULL );
1490 	}
1491 	return( NULL );
1492 }
1493 
1494 /* Retrieves the item specified by the path
1495  * Returns a Python object if successful or NULL on error
1496  */
pyolecf_file_get_item_by_path(pyolecf_file_t * pyolecf_file,PyObject * arguments,PyObject * keywords)1497 PyObject *pyolecf_file_get_item_by_path(
1498            pyolecf_file_t *pyolecf_file,
1499            PyObject *arguments,
1500            PyObject *keywords )
1501 {
1502 	PyObject *item_object       = NULL;
1503 	PyTypeObject *type_object   = NULL;
1504 	libcerror_error_t *error    = NULL;
1505 	libolecf_item_t *item       = NULL;
1506 	static char *function       = "pyolecf_file_get_item_by_path";
1507 	static char *keyword_list[] = { "path", NULL };
1508 	char *utf8_path             = NULL;
1509 	size_t utf8_path_length     = 0;
1510 	int result                  = 0;
1511 
1512 	if( pyolecf_file == NULL )
1513 	{
1514 		PyErr_Format(
1515 		 PyExc_ValueError,
1516 		 "%s: invalid file.",
1517 		 function );
1518 
1519 		return( NULL );
1520 	}
1521 	if( PyArg_ParseTupleAndKeywords(
1522 	     arguments,
1523 	     keywords,
1524 	     "s",
1525 	     keyword_list,
1526 	     &utf8_path ) == 0 )
1527 	{
1528 		goto on_error;
1529 	}
1530 	utf8_path_length = narrow_string_length(
1531 	                    utf8_path );
1532 
1533 	Py_BEGIN_ALLOW_THREADS
1534 
1535 	result = libolecf_file_get_item_by_utf8_path(
1536 	          pyolecf_file->file,
1537 	          (uint8_t *) utf8_path,
1538 	          utf8_path_length,
1539 	          &item,
1540 	          &error );
1541 
1542 	Py_END_ALLOW_THREADS
1543 
1544 	if( result == -1 )
1545 	{
1546 		pyolecf_error_raise(
1547 		 error,
1548 		 PyExc_IOError,
1549 		 "%s: unable to retrieve item.",
1550 		 function );
1551 
1552 		libcerror_error_free(
1553 		 &error );
1554 
1555 		goto on_error;
1556 	}
1557 	else if( result == 0 )
1558 	{
1559 		Py_IncRef(
1560 		 Py_None );
1561 
1562 		return( Py_None );
1563 	}
1564 	type_object = pyolecf_file_get_item_type_object(
1565 	               item );
1566 
1567 	if( type_object == NULL )
1568 	{
1569 		PyErr_Format(
1570 		 PyExc_IOError,
1571 		 "%s: unable to retrieve item type object.",
1572 		 function );
1573 
1574 		goto on_error;
1575 	}
1576 	item_object = pyolecf_item_new(
1577 	               type_object,
1578 	               item,
1579 	               (PyObject *) pyolecf_file );
1580 
1581 	if( item_object == NULL )
1582 	{
1583 		PyErr_Format(
1584 		 PyExc_MemoryError,
1585 		 "%s: unable to create item object.",
1586 		 function );
1587 
1588 		goto on_error;
1589 	}
1590 	return( item_object );
1591 
1592 on_error:
1593 	if( item != NULL )
1594 	{
1595 		libolecf_item_free(
1596 		 &item,
1597 		 NULL );
1598 	}
1599 	return( NULL );
1600 }
1601 
1602