comparison src/readpst.c @ 77:87216aefc6df

spelling fixup
author Carl Byington <carl@five-ten-sg.com>
date Sat, 07 Jun 2008 15:53:08 -0700
parents 987aa872294e
children 56fa05fd5271
comparison
equal deleted inserted replaced
76:09d0f592be83 77:87216aefc6df
36 int version(); 36 int version();
37 char* mk_kmail_dir(char*); 37 char* mk_kmail_dir(char*);
38 int close_kmail_dir(); 38 int close_kmail_dir();
39 char* mk_recurse_dir(char*); 39 char* mk_recurse_dir(char*);
40 int close_recurse_dir(); 40 int close_recurse_dir();
41 char* mk_seperate_dir(char *dir); 41 char* mk_separate_dir(char *dir);
42 int close_seperate_dir(); 42 int close_separate_dir();
43 int mk_seperate_file(struct file_ll *f); 43 int mk_separate_file(struct file_ll *f);
44 char* my_stristr(char *haystack, char *needle); 44 char* my_stristr(char *haystack, char *needle);
45 void check_filename(char *fname); 45 void check_filename(char *fname);
46 char* skip_header_prologue(char *headers); 46 char* skip_header_prologue(char *headers);
47 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst); 47 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst);
48 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst); 48 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst);
54 void close_enter_dir(struct file_ll *f); 54 void close_enter_dir(struct file_ll *f);
55 55
56 char* prog_name; 56 char* prog_name;
57 char* output_dir = "."; 57 char* output_dir = ".";
58 char* kmail_chdir = NULL; 58 char* kmail_chdir = NULL;
59
59 // Normal mode just creates mbox format files in the current directory. Each file is named 60 // Normal mode just creates mbox format files in the current directory. Each file is named
60 // the same as the folder's name that it represents 61 // the same as the folder's name that it represents
61 #define MODE_NORMAL 0 62 #define MODE_NORMAL 0
63
62 // KMail mode creates a directory structure suitable for being used directly 64 // KMail mode creates a directory structure suitable for being used directly
63 // by the KMail application 65 // by the KMail application
64 #define MODE_KMAIL 1 66 #define MODE_KMAIL 1
67
65 // recurse mode creates a directory structure like the PST file. Each directory 68 // recurse mode creates a directory structure like the PST file. Each directory
66 // contains only one file which stores the emails in mbox format. 69 // contains only one file which stores the emails in mbox format.
67 #define MODE_RECURSE 2 70 #define MODE_RECURSE 2
68 // seperate mode is similar directory structure to RECURSE. The emails are stored in 71
69 // seperate files, numbering from 1 upward. Attachments belonging to the emails are 72 // separate mode creates the same directory structure as recurse. The emails are stored in
73 // separate files, numbering from 1 upward. Attachments belonging to the emails are
70 // saved as email_no-filename (e.g. 1-samplefile.doc or 000001-Attachment2.zip) 74 // saved as email_no-filename (e.g. 1-samplefile.doc or 000001-Attachment2.zip)
71 #define MODE_SEPERATE 3 75 #define MODE_SEPARATE 3
76
72 // Decrypt the whole file (even the parts that aren't encrypted) and ralph it to stdout 77 // Decrypt the whole file (even the parts that aren't encrypted) and ralph it to stdout
73 #define MODE_DECSPEW 4 78 #define MODE_DECSPEW 4
74 79
75 80
76 // Output Normal just prints the standard information about what is going on 81 // Output Normal just prints the standard information about what is going on
77 #define OUTPUT_NORMAL 0 82 #define OUTPUT_NORMAL 0
83
78 // Output Quiet is provided so that only errors are printed 84 // Output Quiet is provided so that only errors are printed
79 #define OUTPUT_QUIET 1 85 #define OUTPUT_QUIET 1
80 86
81 // default mime-type for attachments that have a null mime-type 87 // default mime-type for attachments that have a null mime-type
82 #define MIME_TYPE_DEFAULT "application/octet-stream" 88 #define MIME_TYPE_DEFAULT "application/octet-stream"
139 145
140 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { 146 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) {
141 // deal with a contact 147 // deal with a contact
142 // write them to the file, one per line in this format 148 // write them to the file, one per line in this format
143 // Desc Name <email@address>\n 149 // Desc Name <email@address>\n
144 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 150 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
145 ff.email_count++; 151 ff.email_count++;
146 DEBUG_MAIN(("main: Processing Contact\n")); 152 DEBUG_MAIN(("main: Processing Contact\n"));
147 if (ff.type != PST_TYPE_CONTACT) { 153 if (ff.type != PST_TYPE_CONTACT) {
148 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. Processing anyway\n")); 154 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. Processing anyway\n"));
149 } 155 }
151 write_vcard(ff.output, item->contact, item->comment); 157 write_vcard(ff.output, item->contact, item->comment);
152 else 158 else
153 fprintf(ff.output, "%s <%s>\n", item->contact->fullname, item->contact->address1); 159 fprintf(ff.output, "%s <%s>\n", item->contact->fullname, item->contact->address1);
154 160
155 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { 161 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) {
156 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 162 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
157 ff.email_count++; 163 ff.email_count++;
158 DEBUG_MAIN(("main: Processing Email\n")); 164 DEBUG_MAIN(("main: Processing Email\n"));
159 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) { 165 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) {
160 DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n")); 166 DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n"));
161 } 167 }
162 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body); 168 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body);
163 169
164 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { 170 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) {
165 // deal with journal items 171 // deal with journal items
166 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 172 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
167 ff.email_count++; 173 ff.email_count++;
168 DEBUG_MAIN(("main: Processing Journal Entry\n")); 174 DEBUG_MAIN(("main: Processing Journal Entry\n"));
169 if (ff.type != PST_TYPE_JOURNAL) { 175 if (ff.type != PST_TYPE_JOURNAL) {
170 DEBUG_MAIN(("main: I have a journal entry, but the folder isn't a journal folder. Processing anyway\n")); 176 DEBUG_MAIN(("main: I have a journal entry, but the folder isn't a journal folder. Processing anyway\n"));
171 } 177 }
178 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start)); 184 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start));
179 fprintf(ff.output, "END:VJOURNAL\n\n"); 185 fprintf(ff.output, "END:VJOURNAL\n\n");
180 186
181 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { 187 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) {
182 // deal with Calendar appointments 188 // deal with Calendar appointments
183 if (mode == MODE_SEPERATE) mk_seperate_file(&ff); 189 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
184 ff.email_count++; 190 ff.email_count++;
185 DEBUG_MAIN(("main: Processing Appointment Entry\n")); 191 DEBUG_MAIN(("main: Processing Appointment Entry\n"));
186 if (ff.type != PST_TYPE_APPOINTMENT) { 192 if (ff.type != PST_TYPE_APPOINTMENT) {
187 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); 193 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n"));
188 } 194 }
249 break; 255 break;
250 case 'k': 256 case 'k':
251 mode = MODE_KMAIL; 257 mode = MODE_KMAIL;
252 break; 258 break;
253 case 'M': 259 case 'M':
254 mode = MODE_SEPERATE; 260 mode = MODE_SEPARATE;
255 mode_MH = 1; 261 mode_MH = 1;
256 break; 262 break;
257 case 'o': 263 case 'o':
258 output_dir = optarg; 264 output_dir = optarg;
259 break; 265 break;
262 break; 268 break;
263 case 'r': 269 case 'r':
264 mode = MODE_RECURSE; 270 mode = MODE_RECURSE;
265 break; 271 break;
266 case 'S': 272 case 'S':
267 mode = MODE_SEPERATE; 273 mode = MODE_SEPARATE;
268 break; 274 break;
269 case 'w': 275 case 'w':
270 overwrite = 1; 276 overwrite = 1;
271 break; 277 break;
272 default: 278 default:
407 version(); 413 version();
408 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); 414 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name);
409 printf("OPTIONS:\n"); 415 printf("OPTIONS:\n");
410 printf("\t-C\t- Decrypt the entire file and output on stdout (not typically useful)\n"); 416 printf("\t-C\t- Decrypt the entire file and output on stdout (not typically useful)\n");
411 printf("\t-M\t- MH. Write emails in the MH format\n"); 417 printf("\t-M\t- MH. Write emails in the MH format\n");
412 printf("\t-S\t- Seperate. Write emails in the seperate format\n"); 418 printf("\t-S\t- Separate. Write emails in the separate format\n");
413 printf("\t-V\t- Version. Display program version\n"); 419 printf("\t-V\t- Version. Display program version\n");
414 printf("\t-b\t- Don't save RTF-Body attachments\n"); 420 printf("\t-b\t- Don't save RTF-Body attachments\n");
415 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); 421 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n");
416 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readpstlog to print it\n"); 422 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readpstlog to print it\n");
417 printf("\t-h\t- Help. This screen\n"); 423 printf("\t-h\t- Help. This screen\n");
535 DEBUG_RET(); 541 DEBUG_RET();
536 return 0; 542 return 0;
537 } 543 }
538 544
539 545
540 char *mk_seperate_dir(char *dir) { 546 char *mk_separate_dir(char *dir) {
541 size_t dirsize = strlen(dir) + 10; 547 size_t dirsize = strlen(dir) + 10;
542 char dir_name[dirsize]; 548 char dir_name[dirsize];
543 int x = 0, y = 0; 549 int x = 0, y = 0;
544 550
545 DEBUG_ENT("mk_seperate_dir"); 551 DEBUG_ENT("mk_separate_dir");
546 do { 552 do {
547 if (y == 0) 553 if (y == 0)
548 snprintf(dir_name, dirsize, "%s", dir); 554 snprintf(dir_name, dirsize, "%s", dir);
549 else 555 else
550 snprintf(dir_name, dirsize, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above 556 snprintf(dir_name, dirsize, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above
552 check_filename(dir_name); 558 check_filename(dir_name);
553 DEBUG_MAIN(("about to try creating %s\n", dir_name)); 559 DEBUG_MAIN(("about to try creating %s\n", dir_name));
554 if (D_MKDIR(dir_name)) { 560 if (D_MKDIR(dir_name)) {
555 if (errno != EEXIST) { // if there is an error, and it doesn't already exist 561 if (errno != EEXIST) { // if there is an error, and it doesn't already exist
556 x = errno; 562 x = errno;
557 DIE(("mk_seperate_dir: Cannot create directory %s: %s\n", dir, strerror(x))); 563 DIE(("mk_separate_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
558 } 564 }
559 } else { 565 } else {
560 break; 566 break;
561 } 567 }
562 y++; 568 y++;
563 } while (overwrite == 0); 569 } while (overwrite == 0);
564 570
565 if (chdir(dir_name)) { 571 if (chdir(dir_name)) {
566 x = errno; 572 x = errno;
567 DIE(("mk_seperate_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); 573 DIE(("mk_separate_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
568 } 574 }
569 575
570 if (overwrite) { 576 if (overwrite) {
571 // we should probably delete all files from this directory 577 // we should probably delete all files from this directory
572 #if !defined(WIN32) && !defined(__CYGWIN__) 578 #if !defined(WIN32) && !defined(__CYGWIN__)
573 DIR * sdir = NULL; 579 DIR * sdir = NULL;
574 struct dirent *dirent = NULL; 580 struct dirent *dirent = NULL;
575 struct stat filestat; 581 struct stat filestat;
576 if (!(sdir = opendir("./"))) { 582 if (!(sdir = opendir("./"))) {
577 WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./")); 583 WARN(("mk_separate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./"));
578 } else { 584 } else {
579 while ((dirent = readdir(sdir))) { 585 while ((dirent = readdir(sdir))) {
580 if (lstat(dirent->d_name, &filestat) != -1) 586 if (lstat(dirent->d_name, &filestat) != -1)
581 if (S_ISREG(filestat.st_mode)) { 587 if (S_ISREG(filestat.st_mode)) {
582 if (unlink(dirent->d_name)) { 588 if (unlink(dirent->d_name)) {
583 y = errno; 589 y = errno;
584 DIE(("mk_seperate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y))); 590 DIE(("mk_separate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y)));
585 } 591 }
586 } 592 }
587 } 593 }
588 } 594 }
589 #endif 595 #endif
593 DEBUG_RET(); 599 DEBUG_RET();
594 return NULL; 600 return NULL;
595 } 601 }
596 602
597 603
598 int close_seperate_dir() { 604 int close_separate_dir() {
599 int x; 605 int x;
600 DEBUG_ENT("close_seperate_dir"); 606 DEBUG_ENT("close_separate_dir");
601 if (chdir("..")) { 607 if (chdir("..")) {
602 x = errno; 608 x = errno;
603 DIE(("close_seperate_dir: Cannot go up dir (..): %s\n", strerror(x))); 609 DIE(("close_separate_dir: Cannot go up dir (..): %s\n", strerror(x)));
604 } 610 }
605 DEBUG_RET(); 611 DEBUG_RET();
606 return 0; 612 return 0;
607 } 613 }
608 614
609 615
610 int mk_seperate_file(struct file_ll *f) { 616 int mk_separate_file(struct file_ll *f) {
611 const int name_offset = 1; 617 const int name_offset = 1;
612 DEBUG_ENT("mk_seperate_file"); 618 DEBUG_ENT("mk_separate_file");
613 DEBUG_MAIN(("opening next file to save email\n")); 619 DEBUG_MAIN(("opening next file to save email\n"));
614 if (f->email_count > 999999999) { // bigger than nine 9's 620 if (f->email_count > 999999999) { // bigger than nine 9's
615 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); 621 DIE(("mk_separate_file: The number of emails in this folder has become too high to handle"));
616 } 622 }
617 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); 623 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset);
618 if (f->output) fclose(f->output); 624 if (f->output) fclose(f->output);
619 f->output = NULL; 625 f->output = NULL;
620 check_filename(f->name); 626 check_filename(f->name);
621 if (!(f->output = fopen(f->name, "w"))) { 627 if (!(f->output = fopen(f->name, "w"))) {
622 DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name)); 628 DIE(("mk_separate_file: Cannot open file to save email \"%s\"\n", f->name));
623 } 629 }
624 DEBUG_RET(); 630 DEBUG_RET();
625 return 0; 631 return 0;
626 } 632 }
627 633
890 temp[1] = '\0'; // stop after first \n 896 temp[1] = '\0'; // stop after first \n
891 } 897 }
892 898
893 // Now, write out the header... 899 // Now, write out the header...
894 soh = skip_header_prologue(item->email->header); 900 soh = skip_header_prologue(item->email->header);
895 if (mode != MODE_SEPERATE) { 901 if (mode != MODE_SEPARATE) {
896 // don't put rubbish in if we are doing seperate 902 // don't put rubbish in if we are doing separate
897 if (strncmp(soh, "X-From_: ", 9) == 0 ) { 903 if (strncmp(soh, "X-From_: ", 9) == 0 ) {
898 fputs("From ", f_output); 904 fputs("From ", f_output);
899 soh += 9; 905 soh += 9;
900 } else 906 } else
901 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); 907 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time);
904 len = strlen(soh); 910 len = strlen(soh);
905 if (!len || (soh[len-1] != '\n')) fprintf(f_output, "\n"); 911 if (!len || (soh[len-1] != '\n')) fprintf(f_output, "\n");
906 912
907 } else { 913 } else {
908 //make up our own headers 914 //make up our own headers
909 if (mode != MODE_SEPERATE) { 915 if (mode != MODE_SEPARATE) {
910 // don't want this first line for this mode 916 // don't want this first line for this mode
911 if (item->email->outlook_sender_name) { 917 if (item->email->outlook_sender_name) {
912 temp = item->email->outlook_sender_name; 918 temp = item->email->outlook_sender_name;
913 } else { 919 } else {
914 temp = "(readpst_null)"; 920 temp = "(readpst_null)";
1044 for (current_attach = item->attach; current_attach; current_attach = current_attach->next) { 1050 for (current_attach = item->attach; current_attach; current_attach = current_attach->next) {
1045 DEBUG_EMAIL(("Attempting Attachment encoding\n")); 1051 DEBUG_EMAIL(("Attempting Attachment encoding\n"));
1046 if (!current_attach->data) { 1052 if (!current_attach->data) {
1047 DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size)); 1053 DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size));
1048 } 1054 }
1049 if (mode == MODE_SEPERATE && !mode_MH) 1055 if (mode == MODE_SEPARATE && !mode_MH)
1050 write_separate_attachment(f_name, current_attach, ++attach_num, pst); 1056 write_separate_attachment(f_name, current_attach, ++attach_num, pst);
1051 else 1057 else
1052 write_inline_attachment(f_output, current_attach, boundary, pst); 1058 write_inline_attachment(f_output, current_attach, boundary, pst);
1053 } 1059 }
1054 if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */ 1060 if (mode != MODE_SEPARATE) { /* do not add a boundary after the last attachment for mode_MH */
1055 DEBUG_EMAIL(("Writing buffer between emails\n")); 1061 DEBUG_EMAIL(("Writing buffer between emails\n"));
1056 if (boundary) fprintf(f_output, "\n--%s--\n", boundary); 1062 if (boundary) fprintf(f_output, "\n--%s--\n", boundary);
1057 fprintf(f_output, "\n\n"); 1063 fprintf(f_output, "\n\n");
1058 } 1064 }
1059 if (boundary) free (boundary); 1065 if (boundary) free (boundary);
1245 DEBUG_ENT("create_enter_dir"); 1251 DEBUG_ENT("create_enter_dir");
1246 if (mode == MODE_KMAIL) 1252 if (mode == MODE_KMAIL)
1247 f->name = mk_kmail_dir(item->file_as); //create directory and form filename 1253 f->name = mk_kmail_dir(item->file_as); //create directory and form filename
1248 else if (mode == MODE_RECURSE) 1254 else if (mode == MODE_RECURSE)
1249 f->name = mk_recurse_dir(item->file_as); 1255 f->name = mk_recurse_dir(item->file_as);
1250 else if (mode == MODE_SEPERATE) { 1256 else if (mode == MODE_SEPARATE) {
1251 // do similar stuff to recurse here. 1257 // do similar stuff to recurse here.
1252 mk_seperate_dir(item->file_as); 1258 mk_separate_dir(item->file_as);
1253 f->name = (char*) xmalloc(10); 1259 f->name = (char*) xmalloc(10);
1254 memset(f->name, 0, 10); 1260 memset(f->name, 0, 10);
1255 // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count); 1261 // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count);
1256 } else { 1262 } else {
1257 f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1); 1263 f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1);
1285 free(temp); 1291 free(temp);
1286 } 1292 }
1287 } 1293 }
1288 1294
1289 DEBUG_MAIN(("f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); 1295 DEBUG_MAIN(("f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as));
1290 if (mode != MODE_SEPERATE) { 1296 if (mode != MODE_SEPARATE) {
1291 check_filename(f->name); 1297 check_filename(f->name);
1292 if (!(f->output = fopen(f->name, "w"))) { 1298 if (!(f->output = fopen(f->name, "w"))) {
1293 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name)); 1299 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name));
1294 } 1300 }
1295 } 1301 }
1309 1315
1310 if (mode == MODE_KMAIL) 1316 if (mode == MODE_KMAIL)
1311 close_kmail_dir(); 1317 close_kmail_dir();
1312 else if (mode == MODE_RECURSE) 1318 else if (mode == MODE_RECURSE)
1313 close_recurse_dir(); 1319 close_recurse_dir();
1314 else if (mode == MODE_SEPERATE) 1320 else if (mode == MODE_SEPARATE)
1315 close_seperate_dir(); 1321 close_separate_dir();
1316 } 1322 }
1317 1323