Mercurial > libpst
comparison src/readpst.c @ 308:97c53c6868ab
add -m option to readpst to create Outlook .msg files
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sun, 13 Dec 2009 14:48:20 -0800 |
parents | 67b24d6a45d6 |
children | a6df6ffc3ff5 |
comparison
equal
deleted
inserted
replaced
243:0199af9730b2 | 308:97c53c6868ab |
---|---|
5 * dave.s@earthcorp.com | 5 * dave.s@earthcorp.com |
6 */ | 6 */ |
7 | 7 |
8 #include "define.h" | 8 #include "define.h" |
9 #include "lzfu.h" | 9 #include "lzfu.h" |
10 #include "msg.h" | |
10 | 11 |
11 #define OUTPUT_TEMPLATE "%s" | 12 #define OUTPUT_TEMPLATE "%s" |
12 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" | 13 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" |
13 #define KMAIL_INDEX ".%s.index" | 14 #define KMAIL_INDEX ".%s.index" |
14 #define SEP_MAIL_FILE_TEMPLATE "%i%s" | 15 #define SEP_MAIL_FILE_TEMPLATE "%i%s" |
37 int close_kmail_dir(); | 38 int close_kmail_dir(); |
38 char* mk_recurse_dir(char* dir, int32_t folder_type); | 39 char* mk_recurse_dir(char* dir, int32_t folder_type); |
39 int close_recurse_dir(); | 40 int close_recurse_dir(); |
40 char* mk_separate_dir(char *dir); | 41 char* mk_separate_dir(char *dir); |
41 int close_separate_dir(); | 42 int close_separate_dir(); |
42 int mk_separate_file(struct file_ll *f, char *extension); | 43 int mk_separate_file(struct file_ll *f, char *extension, int openit); |
43 char* my_stristr(char *haystack, char *needle); | 44 char* my_stristr(char *haystack, char *needle); |
44 void check_filename(char *fname); | 45 void check_filename(char *fname); |
45 void write_separate_attachment(char f_name[], pst_item_attach* attach, int attach_num, pst_file* pst); | 46 void write_separate_attachment(char f_name[], pst_item_attach* attach, int attach_num, pst_file* pst); |
46 void write_embedded_message(FILE* f_output, pst_item_attach* attach, char *boundary, pst_file* pf, char** extra_mime_headers); | 47 void write_embedded_message(FILE* f_output, pst_item_attach* attach, char *boundary, pst_file* pf, char** extra_mime_headers); |
47 void write_inline_attachment(FILE* f_output, pst_item_attach* attach, char *boundary, pst_file* pst); | 48 void write_inline_attachment(FILE* f_output, pst_item_attach* attach, char *boundary, pst_file* pst); |
118 | 119 |
119 // global settings | 120 // global settings |
120 int mode = MODE_NORMAL; | 121 int mode = MODE_NORMAL; |
121 int mode_MH = 0; // a submode of MODE_SEPARATE | 122 int mode_MH = 0; // a submode of MODE_SEPARATE |
122 int mode_EX = 0; // a submode of MODE_SEPARATE | 123 int mode_EX = 0; // a submode of MODE_SEPARATE |
124 int mode_MSG = 0; // a submode of MODE_SEPARATE | |
123 int mode_thunder = 0; // a submode of MODE_RECURSE | 125 int mode_thunder = 0; // a submode of MODE_RECURSE |
124 int output_mode = OUTPUT_NORMAL; | 126 int output_mode = OUTPUT_NORMAL; |
125 int contact_mode = CMODE_VCARD; | 127 int contact_mode = CMODE_VCARD; |
126 int deleted_mode = DMODE_EXCLUDE; | 128 int deleted_mode = DMODE_EXCLUDE; |
127 int output_type_mode = 0xff; // Default to all. | 129 int output_type_mode = 0xff; // Default to all. |
288 ff.skip_count++; | 290 ff.skip_count++; |
289 DEBUG_INFO(("I have a contact, but the folder type %"PRIi32" isn't a contacts folder. Skipping it\n", ff.type)); | 291 DEBUG_INFO(("I have a contact, but the folder type %"PRIi32" isn't a contacts folder. Skipping it\n", ff.type)); |
290 } | 292 } |
291 else { | 293 else { |
292 ff.item_count++; | 294 ff.item_count++; |
293 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".vcf" : ""); | 295 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".vcf" : "", 1); |
294 if (contact_mode == CMODE_VCARD) { | 296 if (contact_mode == CMODE_VCARD) { |
295 pst_convert_utf8_null(item, &item->comment); | 297 pst_convert_utf8_null(item, &item->comment); |
296 write_vcard(ff.output, item, item->contact, item->comment.str); | 298 write_vcard(ff.output, item, item->contact, item->comment.str); |
297 } | 299 } |
298 else { | 300 else { |
316 DEBUG_INFO(("I have an email type %"PRIi32", but the folder type %"PRIi32" isn't an email folder. Skipping it\n", item->type, ff.type)); | 318 DEBUG_INFO(("I have an email type %"PRIi32", but the folder type %"PRIi32" isn't an email folder. Skipping it\n", item->type, ff.type)); |
317 } | 319 } |
318 else { | 320 else { |
319 char *extra_mime_headers = NULL; | 321 char *extra_mime_headers = NULL; |
320 ff.item_count++; | 322 ff.item_count++; |
321 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".eml" : ""); | 323 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".eml" : "", 1); |
322 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, &extra_mime_headers); | 324 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, &extra_mime_headers); |
325 if ((mode == MODE_SEPARATE) && (mode_MSG)) { | |
326 mk_separate_file(&ff, ".msg", 0); | |
327 write_msg_email(ff.name, item, &pstfile); | |
328 } | |
323 } | 329 } |
324 } | 330 } |
325 | 331 |
326 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { | 332 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { |
327 DEBUG_INFO(("Processing Journal Entry\n")); | 333 DEBUG_INFO(("Processing Journal Entry\n")); |
335 ff.skip_count++; | 341 ff.skip_count++; |
336 DEBUG_INFO(("I have a journal entry, but the folder type %"PRIi32" isn't a journal folder. Skipping it\n", ff.type)); | 342 DEBUG_INFO(("I have a journal entry, but the folder type %"PRIi32" isn't a journal folder. Skipping it\n", ff.type)); |
337 } | 343 } |
338 else { | 344 else { |
339 ff.item_count++; | 345 ff.item_count++; |
340 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".ics" : ""); | 346 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".ics" : "", 1); |
341 write_journal(ff.output, item); | 347 write_journal(ff.output, item); |
342 fprintf(ff.output, "\n"); | 348 fprintf(ff.output, "\n"); |
343 } | 349 } |
344 } | 350 } |
345 | 351 |
355 ff.skip_count++; | 361 ff.skip_count++; |
356 DEBUG_INFO(("I have an appointment, but the folder type %"PRIi32" isn't an appointment folder. Skipping it\n", ff.type)); | 362 DEBUG_INFO(("I have an appointment, but the folder type %"PRIi32" isn't an appointment folder. Skipping it\n", ff.type)); |
357 } | 363 } |
358 else { | 364 else { |
359 ff.item_count++; | 365 ff.item_count++; |
360 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".ics" : ""); | 366 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".ics" : "", 1); |
361 write_schedule_part_data(ff.output, item, NULL, NULL); | 367 write_schedule_part_data(ff.output, item, NULL, NULL); |
362 fprintf(ff.output, "\n"); | 368 fprintf(ff.output, "\n"); |
363 } | 369 } |
364 } | 370 } |
365 | 371 |
397 printf("cannot compile regex pattern to find content charset in html bodies\n"); | 403 printf("cannot compile regex pattern to find content charset in html bodies\n"); |
398 exit(3); | 404 exit(3); |
399 } | 405 } |
400 | 406 |
401 // command-line option handling | 407 // command-line option handling |
402 while ((c = getopt(argc, argv, "bc:Dd:ehj:kMo:qrSt:uVw"))!= -1) { | 408 while ((c = getopt(argc, argv, "bc:Dd:emhj:kMo:qrSt:uVw"))!= -1) { |
403 switch (c) { | 409 switch (c) { |
404 case 'b': | 410 case 'b': |
405 save_rtf_body = 0; | 411 save_rtf_body = 0; |
406 break; | 412 break; |
407 case 'c': | 413 case 'c': |
435 case 'k': | 441 case 'k': |
436 mode = MODE_KMAIL; | 442 mode = MODE_KMAIL; |
437 break; | 443 break; |
438 case 'M': | 444 case 'M': |
439 mode = MODE_SEPARATE; | 445 mode = MODE_SEPARATE; |
440 mode_MH = 1; | 446 mode_MH = 1; |
441 mode_EX = 0; | 447 mode_EX = 0; |
448 mode_MSG = 0; | |
442 break; | 449 break; |
443 case 'e': | 450 case 'e': |
444 mode = MODE_SEPARATE; | 451 mode = MODE_SEPARATE; |
445 mode_MH = 1; | 452 mode_MH = 1; |
446 mode_EX = 1; | 453 mode_EX = 1; |
454 mode_MSG = 0; | |
455 file_name_len = 14; | |
456 break; | |
457 case 'm': | |
458 mode = MODE_SEPARATE; | |
459 mode_MH = 1; | |
460 mode_EX = 1; | |
461 mode_MSG = 1; | |
447 file_name_len = 14; | 462 file_name_len = 14; |
448 break; | 463 break; |
449 case 'o': | 464 case 'o': |
450 output_dir = optarg; | 465 output_dir = optarg; |
451 break; | 466 break; |
456 mode = MODE_RECURSE; | 471 mode = MODE_RECURSE; |
457 mode_thunder = 0; | 472 mode_thunder = 0; |
458 break; | 473 break; |
459 case 'S': | 474 case 'S': |
460 mode = MODE_SEPARATE; | 475 mode = MODE_SEPARATE; |
461 mode_MH = 0; | 476 mode_MH = 0; |
462 mode_EX = 0; | 477 mode_EX = 0; |
478 mode_MSG = 0; | |
463 break; | 479 break; |
464 case 't': | 480 case 't': |
465 // email, appointment, contact, other | 481 // email, appointment, contact, other |
466 if (!optarg) { | 482 if (!optarg) { |
467 usage(); | 483 usage(); |
660 printf("\t-d <filename> \t- Debug to file.\n"); | 676 printf("\t-d <filename> \t- Debug to file.\n"); |
661 printf("\t-e\t- As with -M, but include extensions on output files\n"); | 677 printf("\t-e\t- As with -M, but include extensions on output files\n"); |
662 printf("\t-h\t- Help. This screen\n"); | 678 printf("\t-h\t- Help. This screen\n"); |
663 printf("\t-j <integer>\t- Number of parallel jobs to run\n"); | 679 printf("\t-j <integer>\t- Number of parallel jobs to run\n"); |
664 printf("\t-k\t- KMail. Output in kmail format\n"); | 680 printf("\t-k\t- KMail. Output in kmail format\n"); |
681 printf("\t-m\t- As with -e, but write .msg files also\n"); | |
665 printf("\t-o <dirname>\t- Output directory to write files to. CWD is changed *after* opening pst file\n"); | 682 printf("\t-o <dirname>\t- Output directory to write files to. CWD is changed *after* opening pst file\n"); |
666 printf("\t-q\t- Quiet. Only print error messages\n"); | 683 printf("\t-q\t- Quiet. Only print error messages\n"); |
667 printf("\t-r\t- Recursive. Output in a recursive format\n"); | 684 printf("\t-r\t- Recursive. Output in a recursive format\n"); |
668 printf("\t-t[eajc]\t- Set the output type list. e = email, a = attachment, j = journal, c = contact\n"); | 685 printf("\t-t[eajc]\t- Set the output type list. e = email, a = attachment, j = journal, c = contact\n"); |
669 printf("\t-u\t- Thunderbird mode. Write two extra .size and .type files\n"); | 686 printf("\t-u\t- Thunderbird mode. Write two extra .size and .type files\n"); |
670 printf("\t-w\t- Overwrite any output mbox files\n"); | 687 printf("\t-w\t- Overwrite any output mbox files\n"); |
671 printf("\n"); | 688 printf("\n"); |
672 printf("Only one of -k -M -r -S should be specified\n"); | 689 printf("Only one of -M -S -e -k -m -r should be specified\n"); |
673 DEBUG_RET(); | 690 DEBUG_RET(); |
674 } | 691 } |
675 | 692 |
676 | 693 |
677 void version() { | 694 void version() { |
868 DEBUG_RET(); | 885 DEBUG_RET(); |
869 return 0; | 886 return 0; |
870 } | 887 } |
871 | 888 |
872 | 889 |
873 int mk_separate_file(struct file_ll *f, char *extension) { | 890 int mk_separate_file(struct file_ll *f, char *extension, int openit) { |
874 const int name_offset = 1; | 891 const int name_offset = 1; |
875 DEBUG_ENT("mk_separate_file"); | 892 DEBUG_ENT("mk_separate_file"); |
876 DEBUG_INFO(("opening next file to save email\n")); | 893 DEBUG_INFO(("opening next file to save email\n")); |
877 if (f->item_count > 999999999) { // bigger than nine 9's | 894 if (f->item_count > 999999999) { // bigger than nine 9's |
878 DIE(("mk_separate_file: The number of emails in this folder has become too high to handle\n")); | 895 DIE(("mk_separate_file: The number of emails in this folder has become too high to handle\n")); |
879 } | 896 } |
880 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->item_count + name_offset, extension); | 897 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->item_count + name_offset, extension); |
881 if (f->output) fclose(f->output); | 898 if (f->output) fclose(f->output); |
882 f->output = NULL; | 899 f->output = NULL; |
883 check_filename(f->name); | 900 check_filename(f->name); |
884 if (!(f->output = fopen(f->name, "w"))) { | 901 if (openit) { |
885 DIE(("mk_separate_file: Cannot open file to save email \"%s\"\n", f->name)); | 902 if (!(f->output = fopen(f->name, "w"))) { |
903 DIE(("mk_separate_file: Cannot open file to save email \"%s\"\n", f->name)); | |
904 } | |
886 } | 905 } |
887 DEBUG_RET(); | 906 DEBUG_RET(); |
888 return 0; | 907 return 0; |
889 } | 908 } |
890 | 909 |