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