1 /*
2 * Extracts items from a Personal Folder File (OST, PAB and PST)
3 *
4 * Copyright (C) 2008-2018, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This software 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 software 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 software. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <memory.h>
24 #include <narrow_string.h>
25 #include <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28
29 #if defined( HAVE_UNISTD_H )
30 #include <unistd.h>
31 #endif
32
33 #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
34 #include <stdlib.h>
35 #endif
36
37 #include "export_handle.h"
38 #include "log_handle.h"
39 #include "pffinput.h"
40 #include "pfftools_getopt.h"
41 #include "pfftools_libcerror.h"
42 #include "pfftools_libclocale.h"
43 #include "pfftools_libcnotify.h"
44 #include "pfftools_libcpath.h"
45 #include "pfftools_libpff.h"
46 #include "pfftools_output.h"
47 #include "pfftools_signal.h"
48 #include "pfftools_unused.h"
49
50 export_handle_t *pffexport_export_handle = NULL;
51 libpff_file_t *pffexport_file = NULL;
52 int pffexport_abort = 0;
53
54 /* Prints the executable usage information
55 */
usage_fprint(FILE * stream)56 void usage_fprint(
57 FILE *stream )
58 {
59 if( stream == NULL )
60 {
61 return;
62 }
63 fprintf( stream, "Use pffexport to export items stored in a Personal Folder File (OST, PAB\n"
64 "and PST).\n\n" );
65
66 fprintf( stream, "Usage: pffexport [ -c codepage ] [ -f format ] [ -l logfile ] [ -m mode ]\n"
67 " [ -t target ] [ -dhqvV ] source\n\n" );
68
69 fprintf( stream, "\tsource: the source file\n\n" );
70
71 fprintf( stream, "\t-c: codepage of ASCII strings, options: ascii, windows-874,\n"
72 "\t windows-932, windows-936, windows-949, windows-950,\n"
73 "\t windows-1250, windows-1251, windows-1252 (default),\n"
74 "\t windows-1253, windows-1254, windows-1255, windows-1256\n"
75 "\t windows-1257 or windows-1258\n" );
76 fprintf( stream, "\t-d: dumps the item values in a separate file: ItemValues.txt\n" );
77 fprintf( stream, "\t-f: preferred output format, options: all, html, rtf,\n"
78 "\t text (default)\n" );
79 fprintf( stream, "\t-h: shows this help\n" );
80 fprintf( stream, "\t-l: logs information about the exported items\n" );
81 fprintf( stream, "\t-m: export mode, option: all, debug, items (default), recovered.\n"
82 "\t 'all' exports the (allocated) items, orphan and recovered\n"
83 "\t items. 'debug' exports all the (allocated) items, also those\n"
84 "\t outside the the root folder. 'items' exports the (allocated)\n"
85 "\t items. 'recovered' exports the orphan and recovered items.\n" );
86 fprintf( stream, "\t-q: quiet shows minimal status information\n" );
87 fprintf( stream, "\t-t: specify the basename of the target directory to export to\n"
88 "\t (default is the source filename) pffexport will add the\n"
89 "\t following suffixes to the basename: .export, .orphans,\n"
90 "\t .recovered\n" );
91 fprintf( stream, "\t-v: verbose output to stderr\n" );
92 fprintf( stream, "\t-V: print version\n" );
93 }
94
95 /* Signal handler for pffexport
96 */
pffexport_signal_handler(pfftools_signal_t signal PFFTOOLS_ATTRIBUTE_UNUSED)97 void pffexport_signal_handler(
98 pfftools_signal_t signal PFFTOOLS_ATTRIBUTE_UNUSED )
99 {
100 libcerror_error_t *error = NULL;
101 static char *function = "pffexport_signal_handler";
102
103 PFFTOOLS_UNREFERENCED_PARAMETER( signal )
104
105 pffexport_abort = 1;
106
107 if( pffexport_export_handle != NULL )
108 {
109 if( export_handle_signal_abort(
110 pffexport_export_handle,
111 &error ) != 1 )
112 {
113 libcnotify_printf(
114 "%s: unable to signal export handle to abort.\n",
115 function );
116
117 libcnotify_print_error_backtrace(
118 error );
119 libcerror_error_free(
120 &error );
121 }
122 }
123 if( pffexport_file != NULL )
124 {
125 if( libpff_file_signal_abort(
126 pffexport_file,
127 &error ) != 1 )
128 {
129 libcnotify_printf(
130 "%s: unable to signal file to abort.\n",
131 function );
132
133 libcnotify_print_error_backtrace(
134 error );
135 libcerror_error_free(
136 &error );
137 }
138 }
139 /* Force stdin to close otherwise any function reading it will remain blocked
140 */
141 #if defined( WINAPI ) && !defined( __CYGWIN__ )
142 if( _close(
143 0 ) != 0 )
144 #else
145 if( close(
146 0 ) != 0 )
147 #endif
148 {
149 libcnotify_printf(
150 "%s: unable to close stdin.\n",
151 function );
152 }
153 }
154
155 /* The main program
156 */
157 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
wmain(int argc,wchar_t * const argv[])158 int wmain( int argc, wchar_t * const argv[] )
159 #else
160 int main( int argc, char * const argv[] )
161 #endif
162 {
163 libcerror_error_t *error = NULL;
164 log_handle_t *log_handle = NULL;
165 system_character_t *log_filename = NULL;
166 system_character_t *option_ascii_codepage = NULL;
167 system_character_t *option_export_mode = NULL;
168 system_character_t *option_preferred_export_format = NULL;
169 system_character_t *option_target_path = NULL;
170 system_character_t *path_separator = NULL;
171 system_character_t *source = NULL;
172 char *program = "pffexport";
173 system_integer_t option = 0;
174 size_t source_length = 0;
175 uint8_t dump_item_values = 0;
176 uint8_t print_status_information = 1;
177 int result = 0;
178 int verbose = 0;
179
180 libcnotify_stream_set(
181 stderr,
182 NULL );
183 libcnotify_verbose_set(
184 1 );
185
186 if( libclocale_initialize(
187 "pfftools",
188 &error ) != 1 )
189 {
190 fprintf(
191 stderr,
192 "Unable to initialize locale values.\n" );
193
194 goto on_error;
195 }
196 if( pfftools_output_initialize(
197 _IONBF,
198 &error ) != 1 )
199 {
200 fprintf(
201 stderr,
202 "Unable to initialize output settings.\n" );
203
204 goto on_error;
205 }
206 pffoutput_version_fprint(
207 stdout,
208 program );
209
210 while( ( option = pfftools_getopt(
211 argc,
212 argv,
213 _SYSTEM_STRING( "c:df:hl:m:qt:vV" ) ) ) != (system_integer_t) -1 )
214 {
215 switch( option )
216 {
217 case (system_integer_t) '?':
218 default:
219 fprintf(
220 stderr,
221 "Invalid argument: %" PRIs_SYSTEM "\n",
222 argv[ optind - 1 ] );
223
224 usage_fprint(
225 stdout );
226
227 return( EXIT_FAILURE );
228
229 case (system_integer_t) 'c':
230 option_ascii_codepage = optarg;
231
232 break;
233
234 case (system_integer_t) 'd':
235 dump_item_values = 1;
236
237 break;
238
239 case (system_integer_t) 'f':
240 option_preferred_export_format = optarg;
241
242 break;
243
244 case (system_integer_t) 'h':
245 usage_fprint(
246 stdout );
247
248 return( EXIT_SUCCESS );
249
250 case (system_integer_t) 'l':
251 log_filename = optarg;
252
253 break;
254
255 case (system_integer_t) 'm':
256 option_export_mode = optarg;
257
258 break;
259
260 case (system_integer_t) 'q':
261 print_status_information = 0;
262
263 break;
264
265 case (system_integer_t) 't':
266 option_target_path = optarg;
267
268 break;
269
270 case (system_integer_t) 'v':
271 verbose = 1;
272
273 break;
274
275 case (system_integer_t) 'V':
276 pffoutput_copyright_fprint(
277 stdout );
278
279 return( EXIT_SUCCESS );
280 }
281 }
282 if( optind == argc )
283 {
284 fprintf(
285 stderr,
286 "Missing source file.\n" );
287
288 usage_fprint(
289 stdout );
290
291 return( EXIT_FAILURE );
292 }
293 source = argv[ optind ];
294
295 if( option_target_path == NULL )
296 {
297 source_length = system_string_length(
298 source );
299
300 path_separator = system_string_search_character_reverse(
301 source,
302 (system_character_t) LIBCPATH_SEPARATOR,
303 source_length );
304
305 if( path_separator == NULL )
306 {
307 path_separator = source;
308 }
309 else
310 {
311 path_separator++;
312 }
313 option_target_path = path_separator;
314 }
315 libcnotify_verbose_set(
316 verbose );
317 libpff_notify_set_stream(
318 stderr,
319 NULL );
320 libpff_notify_set_verbose(
321 verbose );
322
323 if( export_handle_initialize(
324 &pffexport_export_handle,
325 &error ) != 1 )
326 {
327 fprintf(
328 stderr,
329 "Unable to create export handle.\n" );
330
331 goto on_error;
332 }
333 pffexport_export_handle->print_status_information = print_status_information;
334
335 if( option_export_mode != NULL )
336 {
337 result = export_handle_set_export_mode(
338 pffexport_export_handle,
339 option_export_mode,
340 &error );
341
342 if( result == -1 )
343 {
344 fprintf(
345 stderr,
346 "Unable to set export mode.\n" );
347
348 goto on_error;
349 }
350 else if( result == 0 )
351 {
352 fprintf(
353 stderr,
354 "Unsupported export mode defaulting to: items.\n" );
355 }
356 }
357 pffexport_export_handle->dump_item_values = dump_item_values;
358
359 if( option_preferred_export_format != NULL )
360 {
361 result = export_handle_set_preferred_export_format(
362 pffexport_export_handle,
363 option_preferred_export_format,
364 &error );
365
366 if( result == -1 )
367 {
368 fprintf(
369 stderr,
370 "Unable to set preferred export format.\n" );
371
372 goto on_error;
373 }
374 else if( result == 0 )
375 {
376 fprintf(
377 stderr,
378 "Unsupported preferred export format defaulting to: text.\n" );
379 }
380 }
381 if( option_ascii_codepage != NULL )
382 {
383 result = export_handle_set_ascii_codepage(
384 pffexport_export_handle,
385 option_ascii_codepage,
386 &error );
387
388 if( result == -1 )
389 {
390 fprintf(
391 stderr,
392 "Unable to set ASCII codepage in export handle.\n" );
393
394 goto on_error;
395 }
396 else if( result == 0 )
397 {
398 fprintf(
399 stderr,
400 "Unsupported ASCII codepage defaulting to: windows-1252.\n" );
401 }
402 }
403 if( export_handle_set_target_path(
404 pffexport_export_handle,
405 option_target_path,
406 &error ) != 1 )
407 {
408 fprintf(
409 stderr,
410 "Unable to set target path.\n" );
411
412 goto on_error;
413 }
414 result = export_handle_create_items_export_path(
415 pffexport_export_handle,
416 &error );
417
418 if( result == -1 )
419 {
420 fprintf(
421 stderr,
422 "Unable to create items export path.\n" );
423
424 goto on_error;
425 }
426 else if( result == 0 )
427 {
428 fprintf(
429 stderr,
430 "%" PRIs_SYSTEM " already exists.\n",
431 pffexport_export_handle->items_export_path );
432
433 goto on_error;
434 }
435 result = export_handle_create_orphans_export_path(
436 pffexport_export_handle,
437 &error );
438
439 if( result == -1 )
440 {
441 fprintf(
442 stderr,
443 "Unable to create orphans export path.\n" );
444
445 goto on_error;
446 }
447 else if( result == 0 )
448 {
449 fprintf(
450 stderr,
451 "%" PRIs_SYSTEM " already exists.\n",
452 pffexport_export_handle->orphans_export_path );
453
454 goto on_error;
455 }
456 result = export_handle_create_recovered_export_path(
457 pffexport_export_handle,
458 &error );
459
460 if( result == -1 )
461 {
462 fprintf(
463 stderr,
464 "Unable to create recovered export path.\n" );
465
466 goto on_error;
467 }
468 else if( result == 0 )
469 {
470 fprintf(
471 stderr,
472 "%" PRIs_SYSTEM " already exists.\n",
473 pffexport_export_handle->recovered_export_path );
474
475 goto on_error;
476 }
477 if( log_handle_initialize(
478 &log_handle,
479 &error ) != 1 )
480 {
481 fprintf(
482 stderr,
483 "Unable to create log handle.\n" );
484
485 goto on_error;
486 }
487 if( log_handle_open(
488 log_handle,
489 log_filename,
490 &error ) != 1 )
491 {
492 fprintf(
493 stderr,
494 "Unable to open log file: %" PRIs_SYSTEM ".\n",
495 log_filename );
496
497 goto on_error;
498 }
499 if( libpff_file_initialize(
500 &pffexport_file,
501 &error ) != 1 )
502 {
503 fprintf(
504 stderr,
505 "Unable to create file.\n" );
506
507 goto on_error;
508 }
509 if( libpff_file_set_ascii_codepage(
510 pffexport_file,
511 pffexport_export_handle->ascii_codepage,
512 &error ) != 1 )
513 {
514 fprintf(
515 stderr,
516 "Unable to set ASCII codepage.\n" );
517
518 goto on_error;
519 }
520 if( pfftools_signal_attach(
521 pffexport_signal_handler,
522 &error ) != 1 )
523 {
524 fprintf(
525 stderr,
526 "Unable to attach signal handler.\n" );
527
528 goto on_error;
529 }
530 fprintf(
531 stdout,
532 "Opening file.\n" );
533
534 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
535 if( libpff_file_open_wide(
536 pffexport_file,
537 source,
538 LIBPFF_OPEN_READ,
539 &error ) != 1 )
540 #else
541 if( libpff_file_open(
542 pffexport_file,
543 source,
544 LIBPFF_OPEN_READ,
545 &error ) != 1 )
546 #endif
547 {
548 fprintf(
549 stderr,
550 "Error opening file: %" PRIs_SYSTEM ".\n",
551 source );
552
553 goto on_error;
554 }
555 if( export_handle_export_file(
556 pffexport_export_handle,
557 pffexport_file,
558 log_handle,
559 &error ) != 1 )
560 {
561 fprintf(
562 stderr,
563 "Unable to export file.\n" );
564
565 goto on_error;
566 }
567 if( libpff_file_close(
568 pffexport_file,
569 &error ) != 0 )
570 {
571 fprintf(
572 stderr,
573 "Unable to close file.\n" );
574
575 goto on_error;
576 }
577 if( pfftools_signal_detach(
578 &error ) != 1 )
579 {
580 fprintf(
581 stderr,
582 "Unable to detach signal handler.\n" );
583
584 goto on_error;
585 }
586 if( libpff_file_free(
587 &pffexport_file,
588 &error ) != 1 )
589 {
590 fprintf(
591 stderr,
592 "Unable to free file.\n" );
593
594 goto on_error;
595 }
596 if( log_handle_close(
597 log_handle,
598 &error ) != 0 )
599 {
600 fprintf(
601 stderr,
602 "Unable to close log file.\n" );
603
604 goto on_error;
605 }
606 if( log_handle_free(
607 &log_handle,
608 &error ) != 1 )
609 {
610 fprintf(
611 stderr,
612 "Unable to free log handle.\n" );
613
614 goto on_error;
615 }
616 if( export_handle_free(
617 &pffexport_export_handle,
618 &error ) != 1 )
619 {
620 fprintf(
621 stderr,
622 "Unable to free export handle.\n" );
623
624 goto on_error;
625 }
626 if( pffexport_abort != 0 )
627 {
628 fprintf(
629 stdout,
630 "Export aborted.\n" );
631
632 return( EXIT_FAILURE );
633 }
634 fprintf(
635 stdout,
636 "Export completed.\n" );
637
638 return( EXIT_SUCCESS );
639
640 on_error:
641 if( error != NULL )
642 {
643 libcnotify_print_error_backtrace(
644 error );
645 libcerror_error_free(
646 &error );
647 }
648 if( pffexport_file != NULL )
649 {
650 libpff_file_close(
651 pffexport_file,
652 NULL );
653 libpff_file_free(
654 &pffexport_file,
655 NULL );
656 }
657 if( log_handle != NULL )
658 {
659 log_handle_close(
660 log_handle,
661 NULL );
662 log_handle_free(
663 &log_handle,
664 NULL );
665 }
666 if( pffexport_export_handle != NULL )
667 {
668 export_handle_free(
669 &pffexport_export_handle,
670 NULL );
671 }
672 return( EXIT_FAILURE );
673 }
674
675