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 §or_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