comparison src/readpst.c @ 100:1e4a7610d525

fixes from Justin Greer to add -D option to include deleted items, to add missing email headers, to fix bug in my_stristr()
author Carl Byington <carl@five-ten-sg.com>
date Thu, 02 Oct 2008 15:29:36 -0700
parents 56fa05fd5271
children 39ba19372732
comparison
equal deleted inserted replaced
99:b7f456946c5b 100:1e4a7610d525
89 89
90 // output mode for contacts 90 // output mode for contacts
91 #define CMODE_VCARD 0 91 #define CMODE_VCARD 0
92 #define CMODE_LIST 1 92 #define CMODE_LIST 1
93 93
94 // output mode for deleted items
95 #define DMODE_EXCLUDE 0
96 #define DMODE_INCLUDE 1
97
94 // output settings for RTF bodies 98 // output settings for RTF bodies
95 // filename for the attachment 99 // filename for the attachment
96 #define RTF_ATTACH_NAME "rtf-body.rtf" 100 #define RTF_ATTACH_NAME "rtf-body.rtf"
97 // mime type for the attachment 101 // mime type for the attachment
98 #define RTF_ATTACH_TYPE "application/rtf" 102 #define RTF_ATTACH_TYPE "application/rtf"
100 // global settings 104 // global settings
101 int mode = MODE_NORMAL; 105 int mode = MODE_NORMAL;
102 int mode_MH = 0; 106 int mode_MH = 0;
103 int output_mode = OUTPUT_NORMAL; 107 int output_mode = OUTPUT_NORMAL;
104 int contact_mode = CMODE_VCARD; 108 int contact_mode = CMODE_VCARD;
109 int deleted_mode = DMODE_EXCLUDE;
105 int overwrite = 0; 110 int overwrite = 0;
106 int save_rtf_body = 1; 111 int save_rtf_body = 1;
107 pst_file pstfile; 112 pst_file pstfile;
108 113
109 114
131 if (item && item->email && item->email->subject && item->email->subject->subj) { 136 if (item && item->email && item->email->subject && item->email->subject->subj) {
132 DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject)); 137 DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject));
133 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); 138 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj));
134 } 139 }
135 if (item) { 140 if (item) {
136 if (item->folder && d_ptr->child && strcasecmp(item->file_as, "Deleted Items")) { 141 if (item->folder && d_ptr->child && (deleted_mode == DMODE_INCLUDE || strcasecmp(item->file_as, "Deleted Items"))) {
137 //if this is a non-empty folder other than deleted items, we want to recurse into it 142 //if this is a non-empty folder other than deleted items, we want to recurse into it
138 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as); 143 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as);
139 process(item, d_ptr->child); 144 process(item, d_ptr->child);
140 145
141 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { 146 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) {
221 int c,x; 226 int c,x;
222 char *temp = NULL; //temporary char pointer 227 char *temp = NULL; //temporary char pointer
223 prog_name = argv[0]; 228 prog_name = argv[0];
224 229
225 // command-line option handling 230 // command-line option handling
226 while ((c = getopt(argc, argv, "bCc:d:hko:qrSMVw"))!= -1) { 231 while ((c = getopt(argc, argv, "bCc:Dd:hko:qrSMVw"))!= -1) {
227 switch (c) { 232 switch (c) {
228 case 'b': 233 case 'b':
229 save_rtf_body = 0; 234 save_rtf_body = 0;
230 break; 235 break;
231 case 'C': 236 case 'C':
238 contact_mode=CMODE_LIST; 243 contact_mode=CMODE_LIST;
239 else { 244 else {
240 usage(); 245 usage();
241 exit(0); 246 exit(0);
242 } 247 }
248 break;
249 case 'D':
250 deleted_mode = DMODE_INCLUDE;
243 break; 251 break;
244 case 'd': 252 case 'd':
245 d_log = optarg; 253 d_log = optarg;
246 break; 254 break;
247 case 'h': 255 case 'h':
411 DEBUG_ENT("usage"); 419 DEBUG_ENT("usage");
412 version(); 420 version();
413 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); 421 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name);
414 printf("OPTIONS:\n"); 422 printf("OPTIONS:\n");
415 printf("\t-C\t- Decrypt (compressible encryption) the entire file and output on stdout (not typically useful)\n"); 423 printf("\t-C\t- Decrypt (compressible encryption) the entire file and output on stdout (not typically useful)\n");
424 printf("\t-D\t- Include deleted items in output\n");
416 printf("\t-M\t- MH. Write emails in the MH format\n"); 425 printf("\t-M\t- MH. Write emails in the MH format\n");
417 printf("\t-S\t- Separate. Write emails in the separate format\n"); 426 printf("\t-S\t- Separate. Write emails in the separate format\n");
418 printf("\t-V\t- Version. Display program version\n"); 427 printf("\t-V\t- Version. Display program version\n");
419 printf("\t-b\t- Don't save RTF-Body attachments\n"); 428 printf("\t-b\t- Don't save RTF-Body attachments\n");
420 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); 429 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n");
651 z = NULL; // reset the haystack storage point 660 z = NULL; // reset the haystack storage point
652 } 661 }
653 x++; // advance the search in the haystack 662 x++; // advance the search in the haystack
654 } 663 }
655 DEBUG_RET(); 664 DEBUG_RET();
665 // If the haystack ended before our search finished, it's not a match.
666 if (*y != '\0') return NULL;
656 return z; 667 return z;
657 } 668 }
658 669
659 670
660 void check_filename(char *fname) { 671 void check_filename(char *fname) {
788 char *temp = NULL; 799 char *temp = NULL;
789 int attach_num, base64_body = 0; 800 int attach_num, base64_body = 0;
790 time_t em_time; 801 time_t em_time;
791 char *c_time; 802 char *c_time;
792 pst_item_attach* current_attach; 803 pst_item_attach* current_attach;
804 int has_from, has_subject, has_to, has_cc, has_bcc, has_date;
805 has_from = has_subject = has_to = has_cc = has_bcc = has_date = 0;
793 DEBUG_ENT("write_normal_email"); 806 DEBUG_ENT("write_normal_email");
794 807
795 // convert the sent date if it exists, or set it to a fixed date 808 // convert the sent date if it exists, or set it to a fixed date
796 if (item->email->sent_date) { 809 if (item->email->sent_date) {
797 em_time = fileTimeToUnixTime(item->email->sent_date, 0); 810 em_time = fileTimeToUnixTime(item->email->sent_date, 0);
858 } 871 }
859 } else { 872 } else {
860 DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); 873 DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n"));
861 } 874 }
862 } 875 }
876
877 // Check if the header block has all the necessary headers.
878 if (my_stristr(item->email->header, "\nFrom:") || (strncasecmp(item->email->header, "From: ", 6) == 0) || my_stristr(item->email->header, "\nX-From:")) {
879 DEBUG_EMAIL(("header block has From header\n"));
880 has_from = 1;
881 }
882 if (my_stristr(item->email->header, "\nTo:") || (strncasecmp(item->email->header, "To: ", 4) == 0)) {
883 DEBUG_EMAIL(("header block has To header\n"));
884 has_to = 1;
885 }
886 if (my_stristr(item->email->header, "\nSubject:") || (strncasecmp(item->email->header, "Subject: ", 9) == 0)) {
887 DEBUG_EMAIL(("header block has Subject header\n"));
888 has_subject = 1;
889 }
890 if (my_stristr(item->email->header, "\nDate:") || (strncasecmp(item->email->header, "Date: ", 6) == 0)) {
891 DEBUG_EMAIL(("header block has Date header\n"));
892 has_date = 1;
893 }
894 if (my_stristr(item->email->header, "\nCC:") || (strncasecmp(item->email->header, "CC: ", 4) == 0)) {
895 DEBUG_EMAIL(("header block has CC header\n"));
896 has_cc = 1;
897 }
898 if (my_stristr(item->email->header, "\nBCC:") || (strncasecmp(item->email->header, "BCC: ", 5) == 0)) {
899 DEBUG_EMAIL(("header block has BCC header\n"));
900 has_bcc = 1;
901 }
863 } 902 }
864 903
865 if (!boundary && (item->attach || (item->email->body && item->email->htmlbody) 904 if (!boundary && (item->attach || (item->email->body && item->email->htmlbody)
866 || item->email->rtf_compressed || item->email->encrypted_body 905 || item->email->rtf_compressed || item->email->encrypted_body
867 || item->email->encrypted_htmlbody)) { 906 || item->email->encrypted_htmlbody)) {
868 // we need to create a boundary here. 907 // we need to create a boundary here.
869 DEBUG_EMAIL(("must create own boundary. oh dear.\n")); 908 DEBUG_EMAIL(("must create own boundary. oh dear.\n"));
870 boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary 909 boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary
871 boundary[0] = '\0'; 910 boundary[0] = '\0';
872 sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); 911 sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand());
873 DEBUG_EMAIL(("created boundary is %s\n", boundary)); 912 DEBUG_EMAIL(("created boundary is %s\n", boundary));
874 boundary_created = 1; 913 boundary_created = 1;
875 } 914 }
876 915
877 DEBUG_EMAIL(("About to print Header\n")); 916 DEBUG_EMAIL(("About to print Header\n"));
878 917
879 if (item && item->email && item->email->subject && item->email->subject->subj) { 918 if (item && item->email && item->email->subject && item->email->subject->subj) {
891 temp = strstr(item->email->header, "\n\n"); 930 temp = strstr(item->email->header, "\n\n");
892 931
893 if (temp) { 932 if (temp) {
894 DEBUG_EMAIL(("Found body text in header\n")); 933 DEBUG_EMAIL(("Found body text in header\n"));
895 temp[1] = '\0'; // stop after first \n 934 temp[1] = '\0'; // stop after first \n
935 }
936
937 // Write out any fields that weren't included in the header.
938 if (!has_from) {
939 temp = item->email->outlook_sender;
940 if (!temp) temp = "";
941 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp);
942 }
943
944 if (!has_subject) {
945 if (item->email->subject && item->email->subject->subj) {
946 fprintf(f_output, "Subject: %s\n", item->email->subject->subj);
947 } else {
948 fprintf(f_output, "Subject: \n");
949 }
950 }
951
952 if (!has_to && item->email->sentto_address) {
953 fprintf(f_output, "To: %s\n", item->email->sentto_address);
954 }
955
956 if (!has_cc && item->email->cc_address) {
957 fprintf(f_output, "Cc: %s\n", item->email->cc_address);
958 }
959
960 if (!has_bcc && item->email->bcc_address) {
961 fprintf(f_output, "Bcc: %s\n", item->email->bcc_address);
962 }
963
964 if (!has_date && item->email->sent_date) {
965 char c_time[C_TIME_SIZE];
966 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time));
967 fprintf(f_output, "Date: %s\n", c_time);
896 } 968 }
897 969
898 // Now, write out the header... 970 // Now, write out the header...
899 soh = skip_header_prologue(item->email->header); 971 soh = skip_header_prologue(item->email->header);
900 if (mode != MODE_SEPARATE) { 972 if (mode != MODE_SEPARATE) {
923 995
924 temp = item->email->outlook_sender; 996 temp = item->email->outlook_sender;
925 if (!temp) temp = ""; 997 if (!temp) temp = "";
926 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); 998 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp);
927 999
928 if (item->email->subject) { 1000 if (item->email->subject && item->email->subject->subj) {
929 fprintf(f_output, "Subject: %s\n", item->email->subject->subj); 1001 fprintf(f_output, "Subject: %s\n", item->email->subject->subj);
930 } else { 1002 } else {
931 fprintf(f_output, "Subject: \n"); 1003 fprintf(f_output, "Subject: \n");
932 } 1004 }
933 1005
934 fprintf(f_output, "To: %s\n", item->email->sentto_address); 1006 if (item->email->sentto_address) {
1007 fprintf(f_output, "To: %s\n", item->email->sentto_address);
1008 }
1009
935 if (item->email->cc_address) { 1010 if (item->email->cc_address) {
936 fprintf(f_output, "Cc: %s\n", item->email->cc_address); 1011 fprintf(f_output, "Cc: %s\n", item->email->cc_address);
937 } 1012 }
938 1013
939 if (item->email->sent_date) { 1014 if (item->email->sent_date) {