Mercurial > libpst
comparison src/readpst.c @ 363:3a1d25c579c6 stable-0-6-68
allow folders containing multiple item types; better detection of valid internet headers
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 29 Aug 2016 09:50:24 -0700 |
parents | 6abc3054cba2 |
children | e4c414ff8fa2 |
comparison
equal
deleted
inserted
replaced
362:c42273d817c7 | 363:3a1d25c579c6 |
---|---|
16 | 16 |
17 // max size of the c_time char*. It will store the date of the email | 17 // max size of the c_time char*. It will store the date of the email |
18 #define C_TIME_SIZE 500 | 18 #define C_TIME_SIZE 500 |
19 | 19 |
20 struct file_ll { | 20 struct file_ll { |
21 char *name; | 21 char *name[PST_TYPE_MAX]; |
22 char *dname; | 22 char *dname; |
23 FILE * output; | 23 FILE * output[PST_TYPE_MAX]; |
24 int32_t stored_count; | 24 int32_t stored_count; |
25 int32_t item_count; | 25 int32_t item_count; |
26 int32_t skip_count; | 26 int32_t skip_count; |
27 int32_t type; | |
28 }; | 27 }; |
29 | 28 |
30 int grim_reaper(); | 29 int grim_reaper(); |
31 pid_t try_fork(char* folder); | 30 pid_t try_fork(char* folder); |
32 void process(pst_item *outeritem, pst_desc_tree *d_ptr); | 31 void process(pst_item *outeritem, pst_desc_tree *d_ptr); |
34 void removeCR(char *c); | 33 void removeCR(char *c); |
35 void usage(); | 34 void usage(); |
36 void version(); | 35 void version(); |
37 char* mk_kmail_dir(char* fname); | 36 char* mk_kmail_dir(char* fname); |
38 int close_kmail_dir(); | 37 int close_kmail_dir(); |
39 char* mk_recurse_dir(char* dir, int32_t folder_type); | 38 void mk_recurse_dir(char* dir); |
40 int close_recurse_dir(); | 39 int close_recurse_dir(); |
41 char* mk_separate_dir(char *dir); | 40 void mk_separate_dir(char *dir); |
42 int close_separate_dir(); | 41 int close_separate_dir(); |
43 void mk_separate_file(struct file_ll *f, char *extension, int openit); | 42 void mk_separate_file(struct file_ll *f, int32_t t, char *extension, int openit); |
44 void close_separate_file(struct file_ll *f); | 43 void close_separate_file(struct file_ll *f); |
45 char* my_stristr(char *haystack, char *needle); | 44 char* my_stristr(char *haystack, char *needle); |
46 void check_filename(char *fname); | 45 void check_filename(char *fname); |
47 int acceptable_ext(pst_item_attach* attach); | 46 int acceptable_ext(pst_item_attach* attach); |
48 void write_separate_attachment(char f_name[], pst_item_attach* attach, int attach_num, pst_file* pst); | 47 void write_separate_attachment(char f_name[], pst_item_attach* attach, int attach_num, pst_file* pst); |
242 { | 241 { |
243 struct file_ll ff; | 242 struct file_ll ff; |
244 pst_item *item = NULL; | 243 pst_item *item = NULL; |
245 | 244 |
246 DEBUG_ENT("process"); | 245 DEBUG_ENT("process"); |
247 memset(&ff, 0, sizeof(ff)); | |
248 create_enter_dir(&ff, outeritem); | 246 create_enter_dir(&ff, outeritem); |
249 | 247 |
250 for (; d_ptr; d_ptr = d_ptr->next) { | 248 for (; d_ptr; d_ptr = d_ptr->next) { |
251 DEBUG_INFO(("New item record\n")); | 249 DEBUG_INFO(("New item record\n")); |
252 if (!d_ptr->desc) { | 250 if (!d_ptr->desc) { |
306 if (!(output_type_mode & OTMODE_CONTACT)) { | 304 if (!(output_type_mode & OTMODE_CONTACT)) { |
307 ff.skip_count++; | 305 ff.skip_count++; |
308 DEBUG_INFO(("skipping contact: not in output type list\n")); | 306 DEBUG_INFO(("skipping contact: not in output type list\n")); |
309 } | 307 } |
310 else { | 308 else { |
311 if (!ff.type) ff.type = item->type; | 309 ff.item_count++; |
312 if ((ff.type != PST_TYPE_CONTACT) && (mode != MODE_SEPARATE)) { | 310 if (mode == MODE_SEPARATE) mk_separate_file(&ff, PST_TYPE_CONTACT, (mode_EX) ? ".vcf" : "", 1); |
313 ff.skip_count++; | 311 if (contact_mode == CMODE_VCARD) { |
314 DEBUG_INFO(("I have a contact, but the folder type %"PRIi32" isn't a contacts folder. Skipping it\n", ff.type)); | 312 pst_convert_utf8_null(item, &item->comment); |
313 write_vcard(ff.output[PST_TYPE_CONTACT], item, item->contact, item->comment.str); | |
315 } | 314 } |
316 else { | 315 else { |
317 ff.item_count++; | 316 pst_convert_utf8(item, &item->contact->fullname); |
318 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".vcf" : "", 1); | 317 pst_convert_utf8(item, &item->contact->address1); |
319 if (contact_mode == CMODE_VCARD) { | 318 fprintf(ff.output[PST_TYPE_CONTACT], "%s <%s>\n", item->contact->fullname.str, item->contact->address1.str); |
320 pst_convert_utf8_null(item, &item->comment); | |
321 write_vcard(ff.output, item, item->contact, item->comment.str); | |
322 } | |
323 else { | |
324 pst_convert_utf8(item, &item->contact->fullname); | |
325 pst_convert_utf8(item, &item->contact->address1); | |
326 fprintf(ff.output, "%s <%s>\n", item->contact->fullname.str, item->contact->address1.str); | |
327 } | |
328 if (mode == MODE_SEPARATE) close_separate_file(&ff); | |
329 } | 319 } |
320 if (mode == MODE_SEPARATE) close_separate_file(&ff); | |
330 } | 321 } |
331 | 322 |
332 } else if (item->email && ((item->type == PST_TYPE_NOTE) || (item->type == PST_TYPE_SCHEDULE) || (item->type == PST_TYPE_REPORT))) { | 323 } else if (item->email && ((item->type == PST_TYPE_NOTE) || (item->type == PST_TYPE_SCHEDULE) || (item->type == PST_TYPE_REPORT))) { |
333 DEBUG_INFO(("Processing Email\n")); | 324 DEBUG_INFO(("Processing Email\n")); |
334 if (!(output_type_mode & OTMODE_EMAIL)) { | 325 if (!(output_type_mode & OTMODE_EMAIL)) { |
335 ff.skip_count++; | 326 ff.skip_count++; |
336 DEBUG_INFO(("skipping email: not in output type list\n")); | 327 DEBUG_INFO(("skipping email: not in output type list\n")); |
337 } | 328 } |
338 else { | 329 else { |
339 if (!ff.type) ff.type = item->type; | 330 char *extra_mime_headers = NULL; |
340 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_SCHEDULE) && (ff.type != PST_TYPE_REPORT) && (mode != MODE_SEPARATE)) { | 331 ff.item_count++; |
341 ff.skip_count++; | 332 if (mode == MODE_SEPARATE) { |
342 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)); | 333 // process this single email message, possibly forking |
334 pid_t parent = getpid(); | |
335 pid_t child = try_fork(item->file_as.str); | |
336 if (child == 0) { | |
337 // we are the child process, or the original parent if no children were available | |
338 pid_t me = getpid(); | |
339 mk_separate_file(&ff, PST_TYPE_NOTE, (mode_EX) ? ".eml" : "", 1); | |
340 write_normal_email(ff.output[PST_TYPE_NOTE], ff.name[PST_TYPE_NOTE], item, mode, mode_MH, &pstfile, save_rtf_body, PST_TYPE_NOTE, &extra_mime_headers); | |
341 close_separate_file(&ff); | |
342 if (mode_MSG) { | |
343 mk_separate_file(&ff, PST_TYPE_NOTE, ".msg", 0); | |
344 write_msg_email(ff.name[PST_TYPE_NOTE], item, &pstfile); | |
345 } | |
346 #ifdef HAVE_FORK | |
347 #ifdef HAVE_SEMAPHORE_H | |
348 if (me != parent) { | |
349 // we really were a child, forked for the sole purpose of processing this message | |
350 // free my child count slot before really exiting, since | |
351 // all I am doing here is waiting for my children to exit | |
352 sem_post(global_children); | |
353 grim_reaper(1); // wait for all my child processes to exit - there should not be any | |
354 exit(0); // really exit | |
355 } | |
356 #endif | |
357 #endif | |
358 } | |
343 } | 359 } |
344 else { | 360 else { |
345 char *extra_mime_headers = NULL; | 361 // process this single email message, cannot fork since not separate mode |
346 ff.item_count++; | 362 write_normal_email(ff.output[PST_TYPE_NOTE], ff.name[PST_TYPE_NOTE], item, mode, mode_MH, &pstfile, save_rtf_body, 0, &extra_mime_headers); |
347 if (mode == MODE_SEPARATE) { | |
348 // process this single email message, possibly forking | |
349 pid_t parent = getpid(); | |
350 pid_t child = try_fork(item->file_as.str); | |
351 if (child == 0) { | |
352 // we are the child process, or the original parent if no children were available | |
353 pid_t me = getpid(); | |
354 mk_separate_file(&ff, (mode_EX) ? ".eml" : "", 1); | |
355 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, 0, &extra_mime_headers); | |
356 close_separate_file(&ff); | |
357 if (mode_MSG) { | |
358 mk_separate_file(&ff, ".msg", 0); | |
359 write_msg_email(ff.name, item, &pstfile); | |
360 } | |
361 #ifdef HAVE_FORK | |
362 #ifdef HAVE_SEMAPHORE_H | |
363 if (me != parent) { | |
364 // we really were a child, forked for the sole purpose of processing this message | |
365 // free my child count slot before really exiting, since | |
366 // all I am doing here is waiting for my children to exit | |
367 sem_post(global_children); | |
368 grim_reaper(1); // wait for all my child processes to exit - there should not be any | |
369 exit(0); // really exit | |
370 } | |
371 #endif | |
372 #endif | |
373 } | |
374 } | |
375 else { | |
376 // process this single email message, cannot fork since not separate mode | |
377 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, 0, &extra_mime_headers); | |
378 } | |
379 } | 363 } |
380 } | 364 } |
381 | 365 |
382 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { | 366 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { |
383 DEBUG_INFO(("Processing Journal Entry\n")); | 367 DEBUG_INFO(("Processing Journal Entry\n")); |
384 if (!(output_type_mode & OTMODE_JOURNAL)) { | 368 if (!(output_type_mode & OTMODE_JOURNAL)) { |
385 ff.skip_count++; | 369 ff.skip_count++; |
386 DEBUG_INFO(("skipping journal entry: not in output type list\n")); | 370 DEBUG_INFO(("skipping journal entry: not in output type list\n")); |
387 } | 371 } |
388 else { | 372 else { |
389 if (!ff.type) ff.type = item->type; | 373 ff.item_count++; |
390 if ((ff.type != PST_TYPE_JOURNAL) && (mode != MODE_SEPARATE)) { | 374 if (mode == MODE_SEPARATE) mk_separate_file(&ff, PST_TYPE_JOURNAL, (mode_EX) ? ".ics" : "", 1); |
391 ff.skip_count++; | 375 write_journal(ff.output[PST_TYPE_JOURNAL], item); |
392 DEBUG_INFO(("I have a journal entry, but the folder type %"PRIi32" isn't a journal folder. Skipping it\n", ff.type)); | 376 fprintf(ff.output[PST_TYPE_JOURNAL], "\n"); |
393 } | 377 if (mode == MODE_SEPARATE) close_separate_file(&ff); |
394 else { | |
395 ff.item_count++; | |
396 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".ics" : "", 1); | |
397 write_journal(ff.output, item); | |
398 fprintf(ff.output, "\n"); | |
399 if (mode == MODE_SEPARATE) close_separate_file(&ff); | |
400 } | |
401 } | 378 } |
402 | 379 |
403 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { | 380 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { |
404 DEBUG_INFO(("Processing Appointment Entry\n")); | 381 DEBUG_INFO(("Processing Appointment Entry\n")); |
405 if (!(output_type_mode & OTMODE_APPOINTMENT)) { | 382 if (!(output_type_mode & OTMODE_APPOINTMENT)) { |
406 ff.skip_count++; | 383 ff.skip_count++; |
407 DEBUG_INFO(("skipping appointment: not in output type list\n")); | 384 DEBUG_INFO(("skipping appointment: not in output type list\n")); |
408 } | 385 } |
409 else { | 386 else { |
410 if (!ff.type) ff.type = item->type; | 387 ff.item_count++; |
411 if ((ff.type != PST_TYPE_APPOINTMENT) && (mode != MODE_SEPARATE)) { | 388 if (mode == MODE_SEPARATE) mk_separate_file(&ff, PST_TYPE_APPOINTMENT, (mode_EX) ? ".ics" : "", 1); |
412 ff.skip_count++; | 389 write_schedule_part_data(ff.output[PST_TYPE_APPOINTMENT], item, NULL, NULL); |
413 DEBUG_INFO(("I have an appointment, but the folder type %"PRIi32" isn't an appointment folder. Skipping it\n", ff.type)); | 390 fprintf(ff.output[PST_TYPE_APPOINTMENT], "\n"); |
414 } | 391 if (mode == MODE_SEPARATE) close_separate_file(&ff); |
415 else { | |
416 ff.item_count++; | |
417 if (mode == MODE_SEPARATE) mk_separate_file(&ff, (mode_EX) ? ".ics" : "", 1); | |
418 write_schedule_part_data(ff.output, item, NULL, NULL); | |
419 fprintf(ff.output, "\n"); | |
420 if (mode == MODE_SEPARATE) close_separate_file(&ff); | |
421 } | |
422 } | 392 } |
423 | 393 |
424 } else if (item->message_store) { | 394 } else if (item->message_store) { |
425 // there should only be one message_store, and we have already done it | 395 // there should only be one message_store, and we have already done it |
426 ff.skip_count++; | 396 ff.skip_count++; |
427 DEBUG_WARN(("item with message store content, type %i %s folder type %i, skipping it\n", item->type, item->ascii_type, ff.type)); | 397 DEBUG_WARN(("item with message store content, type %i %s, skipping it\n", item->type, item->ascii_type)); |
428 | 398 |
429 } else { | 399 } else { |
430 ff.skip_count++; | 400 ff.skip_count++; |
431 DEBUG_WARN(("Unknown item type %i (%s) name (%s)\n", | 401 DEBUG_WARN(("Unknown item type %i (%s) name (%s)\n", |
432 item->type, item->ascii_type, item->file_as.str)); | 402 item->type, item->ascii_type, item->file_as.str)); |
845 DEBUG_RET(); | 815 DEBUG_RET(); |
846 return 0; | 816 return 0; |
847 } | 817 } |
848 | 818 |
849 | 819 |
850 // this will create a directory by that name, | 820 char *item_type_to_name(int32_t item_type) { |
851 // then make an mbox file inside that directory. | 821 char *name; |
852 char *mk_recurse_dir(char *dir, int32_t folder_type) { | 822 switch (item_type) { |
823 case PST_TYPE_APPOINTMENT: | |
824 name = "calendar"; | |
825 break; | |
826 case PST_TYPE_CONTACT: | |
827 name = "contacts"; | |
828 break; | |
829 case PST_TYPE_JOURNAL: | |
830 name = "journal"; | |
831 break; | |
832 case PST_TYPE_STICKYNOTE: | |
833 case PST_TYPE_TASK: | |
834 case PST_TYPE_NOTE: | |
835 case PST_TYPE_OTHER: | |
836 case PST_TYPE_REPORT: | |
837 default: | |
838 name = "mbox"; | |
839 break; | |
840 } | |
841 return name; | |
842 } | |
843 | |
844 | |
845 int32_t reduced_item_type(int32_t item_type) { | |
846 int32_t reduced; | |
847 switch (item_type) { | |
848 case PST_TYPE_APPOINTMENT: | |
849 case PST_TYPE_CONTACT: | |
850 case PST_TYPE_JOURNAL: | |
851 reduced = item_type; | |
852 break; | |
853 case PST_TYPE_STICKYNOTE: | |
854 case PST_TYPE_TASK: | |
855 case PST_TYPE_NOTE: | |
856 case PST_TYPE_OTHER: | |
857 case PST_TYPE_REPORT: | |
858 default: | |
859 reduced = PST_TYPE_NOTE; | |
860 break; | |
861 } | |
862 return reduced; | |
863 } | |
864 | |
865 | |
866 // this will create a directory by that name | |
867 void mk_recurse_dir(char *dir) { | |
853 int x; | 868 int x; |
854 char *out_name; | |
855 DEBUG_ENT("mk_recurse_dir"); | 869 DEBUG_ENT("mk_recurse_dir"); |
856 check_filename(dir); | 870 check_filename(dir); |
857 if (D_MKDIR (dir)) { | 871 if (D_MKDIR (dir)) { |
858 if (errno != EEXIST) { // not an error because it exists | 872 if (errno != EEXIST) { // not an error because it exists |
859 x = errno; | 873 x = errno; |
862 } | 876 } |
863 if (chdir (dir)) { | 877 if (chdir (dir)) { |
864 x = errno; | 878 x = errno; |
865 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); | 879 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x))); |
866 } | 880 } |
867 switch (folder_type) { | 881 DEBUG_RET(); |
868 case PST_TYPE_APPOINTMENT: | |
869 out_name = strdup("calendar"); | |
870 break; | |
871 case PST_TYPE_CONTACT: | |
872 out_name = strdup("contacts"); | |
873 break; | |
874 case PST_TYPE_JOURNAL: | |
875 out_name = strdup("journal"); | |
876 break; | |
877 case PST_TYPE_STICKYNOTE: | |
878 case PST_TYPE_TASK: | |
879 case PST_TYPE_NOTE: | |
880 case PST_TYPE_OTHER: | |
881 case PST_TYPE_REPORT: | |
882 default: | |
883 out_name = strdup("mbox"); | |
884 break; | |
885 } | |
886 DEBUG_RET(); | |
887 return out_name; | |
888 } | 882 } |
889 | 883 |
890 | 884 |
891 int close_recurse_dir() { | 885 int close_recurse_dir() { |
892 int x; | 886 int x; |
898 DEBUG_RET(); | 892 DEBUG_RET(); |
899 return 0; | 893 return 0; |
900 } | 894 } |
901 | 895 |
902 | 896 |
903 char *mk_separate_dir(char *dir) { | 897 void mk_separate_dir(char *dir) { |
904 size_t dirsize = strlen(dir) + 10; | 898 size_t dirsize = strlen(dir) + 10; |
905 char dir_name[dirsize]; | 899 char dir_name[dirsize]; |
906 int x = 0, y = 0; | 900 int x = 0, y = 0; |
907 | 901 |
908 DEBUG_ENT("mk_separate_dir"); | 902 DEBUG_ENT("mk_separate_dir"); |
951 closedir(sdir); // cppcheck detected leak | 945 closedir(sdir); // cppcheck detected leak |
952 } | 946 } |
953 #endif | 947 #endif |
954 } | 948 } |
955 | 949 |
956 // we don't return a filename here cause it isn't necessary. | 950 DEBUG_RET(); |
957 DEBUG_RET(); | |
958 return NULL; | |
959 } | 951 } |
960 | 952 |
961 | 953 |
962 int close_separate_dir() { | 954 int close_separate_dir() { |
963 int x; | 955 int x; |
969 DEBUG_RET(); | 961 DEBUG_RET(); |
970 return 0; | 962 return 0; |
971 } | 963 } |
972 | 964 |
973 | 965 |
974 void mk_separate_file(struct file_ll *f, char *extension, int openit) { | 966 void mk_separate_file(struct file_ll *f, int32_t t, char *extension, int openit) { |
975 DEBUG_ENT("mk_separate_file"); | 967 DEBUG_ENT("mk_separate_file"); |
976 DEBUG_INFO(("opening next file to save email\n")); | 968 DEBUG_INFO(("opening next file to save email\n")); |
977 if (f->item_count > 999999999) { // bigger than nine 9's | 969 if (f->item_count > 999999999) { // bigger than nine 9's |
978 DIE(("mk_separate_file: The number of emails in this folder has become too high to handle\n")); | 970 DIE(("mk_separate_file: The number of emails in this folder has become too high to handle\n")); |
979 } | 971 } |
980 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->item_count, extension); | 972 sprintf(f->name[t], SEP_MAIL_FILE_TEMPLATE, f->item_count, extension); |
981 check_filename(f->name); | 973 check_filename(f->name[t]); |
982 if (openit) { | 974 if (openit) { |
983 if (!(f->output = fopen(f->name, "w"))) { | 975 if (!(f->output[t] = fopen(f->name[t], "w"))) { |
984 DIE(("mk_separate_file: Cannot open file to save email \"%s\"\n", f->name)); | 976 DIE(("mk_separate_file: Cannot open file to save email \"%s\"\n", f->name[t])); |
985 } | 977 } |
986 } | 978 } |
987 DEBUG_RET(); | 979 DEBUG_RET(); |
988 } | 980 } |
989 | 981 |
990 | 982 |
991 void close_separate_file(struct file_ll *f) { | 983 void close_separate_file(struct file_ll *f) { |
984 int32_t t; | |
992 DEBUG_ENT("close_separate_file"); | 985 DEBUG_ENT("close_separate_file"); |
993 if (f->output) { | 986 for (t=0; t<PST_TYPE_MAX; t++) { |
994 struct stat st; | 987 if (f->output[t]) { |
995 fclose(f->output); | 988 struct stat st; |
996 stat(f->name, &st); | 989 fclose(f->output[t]); |
997 if (!st.st_size) { | 990 stat(f->name[t], &st); |
998 DEBUG_WARN(("removing empty output file %s\n", f->name)); | 991 if (!st.st_size) { |
999 remove(f->name); | 992 DEBUG_WARN(("removing empty output file %s\n", f->name[t])); |
1000 } | 993 remove(f->name[t]); |
1001 f->output = NULL; | 994 } |
995 f->output[t] = NULL; | |
996 } | |
1002 } | 997 } |
1003 DEBUG_RET(); | 998 DEBUG_RET(); |
1004 } | 999 } |
1005 | 1000 |
1006 | 1001 |
1225 // message body, so we only use them if they seem to be real rfc822 headers. | 1220 // message body, so we only use them if they seem to be real rfc822 headers. |
1226 // this list is composed of ones that we have seen in real pst files. | 1221 // this list is composed of ones that we have seen in real pst files. |
1227 // there are surely others. the problem is - given an arbitrary character | 1222 // there are surely others. the problem is - given an arbitrary character |
1228 // string, is it a valid (or even reasonable) set of rfc822 headers? | 1223 // string, is it a valid (or even reasonable) set of rfc822 headers? |
1229 if (header) { | 1224 if (header) { |
1230 if ((strncasecmp(header, "X-Barracuda-URL: ", 17) == 0) || | 1225 if ((strncasecmp(header, "Content-Type: ", 14) == 0) || |
1231 (strncasecmp(header, "X-ASG-Debug-ID: ", 16) == 0) || | 1226 (strncasecmp(header, "Date: ", 6) == 0) || |
1232 (strncasecmp(header, "Return-Path: ", 13) == 0) || | 1227 (strncasecmp(header, "From: ", 6) == 0) || |
1233 (strncasecmp(header, "Received: ", 10) == 0) || | 1228 (strncasecmp(header, "MIME-Version: ", 14) == 0) || |
1234 (strncasecmp(header, "Subject: ", 9) == 0) || | 1229 (strncasecmp(header, "Microsoft Mail Internet Headers", 31) == 0) || |
1235 (strncasecmp(header, "Date: ", 6) == 0) || | 1230 (strncasecmp(header, "Received: ", 10) == 0) || |
1236 (strncasecmp(header, "From: ", 6) == 0) || | 1231 (strncasecmp(header, "Return-Path: ", 13) == 0) || |
1237 (strncasecmp(header, "X-x: ", 5) == 0) || | 1232 (strncasecmp(header, "Subject: ", 9) == 0) || |
1238 (strncasecmp(header, "Microsoft Mail Internet Headers", 31) == 0)) { | 1233 (strncasecmp(header, "To: ", 4) == 0) || |
1239 return 1; | 1234 (strncasecmp(header, "X-ASG-Debug-ID: ", 16) == 0) || |
1235 (strncasecmp(header, "X-Barracuda-URL: ", 17) == 0) || | |
1236 (strncasecmp(header, "X-x: ", 5) == 0)) { | |
1237 return 1; | |
1240 } | 1238 } |
1241 else { | 1239 else { |
1242 if (strlen(header) > 2) { | 1240 if (strlen(header) > 2) { |
1243 DEBUG_INFO(("Ignore bogus headers = %s\n", header)); | 1241 DEBUG_INFO(("Ignore bogus headers = %s\n", header)); |
1244 } | 1242 } |
2174 } | 2172 } |
2175 | 2173 |
2176 | 2174 |
2177 void create_enter_dir(struct file_ll* f, pst_item *item) | 2175 void create_enter_dir(struct file_ll* f, pst_item *item) |
2178 { | 2176 { |
2177 memset(f, 0, sizeof(*f)); | |
2178 f->stored_count = (item->folder) ? item->folder->item_count : 0; | |
2179 pst_convert_utf8(item, &item->file_as); | 2179 pst_convert_utf8(item, &item->file_as); |
2180 f->type = item->type; | 2180 f->dname = (char*) pst_malloc(strlen(item->file_as.str)+1); |
2181 f->stored_count = (item->folder) ? item->folder->item_count : 0; | 2181 strcpy(f->dname, item->file_as.str); |
2182 | 2182 |
2183 DEBUG_ENT("create_enter_dir"); | 2183 DEBUG_ENT("create_enter_dir"); |
2184 if (mode == MODE_KMAIL) | 2184 if (mode == MODE_KMAIL) |
2185 f->name = mk_kmail_dir(item->file_as.str); | 2185 f->name[0] = mk_kmail_dir(item->file_as.str); |
2186 else if (mode == MODE_RECURSE) { | 2186 else if (mode == MODE_RECURSE) { |
2187 f->name = mk_recurse_dir(item->file_as.str, f->type); | 2187 int32_t t; |
2188 mk_recurse_dir(item->file_as.str); | |
2189 for (t=0; t<PST_TYPE_MAX; t++) { | |
2190 if (t == reduced_item_type(t)) { | |
2191 f->name[t] = strdup(item_type_to_name(t)); | |
2192 } | |
2193 } | |
2188 if (mode_thunder) { | 2194 if (mode_thunder) { |
2189 FILE *type_file = fopen(".type", "w"); | 2195 FILE *type_file = fopen(".type", "w"); |
2190 fprintf(type_file, "%d\n", item->type); | 2196 fprintf(type_file, "%d\n", item->type); |
2191 fclose(type_file); | 2197 fclose(type_file); |
2192 } | 2198 } |
2193 } else if (mode == MODE_SEPARATE) { | 2199 } else if (mode == MODE_SEPARATE) { |
2194 // do similar stuff to recurse here. | 2200 // do similar stuff to recurse here. |
2195 mk_separate_dir(item->file_as.str); | 2201 mk_separate_dir(item->file_as.str); |
2196 f->name = (char*) pst_malloc(file_name_len); | 2202 f->name[0] = (char*) pst_malloc(file_name_len); |
2197 memset(f->name, 0, file_name_len); | 2203 memset(f->name[0], 0, file_name_len); |
2198 } else { | 2204 } else { |
2199 f->name = (char*) pst_malloc(strlen(item->file_as.str)+strlen(OUTPUT_TEMPLATE)+1); | 2205 f->name[0] = (char*) pst_malloc(strlen(item->file_as.str)+strlen(OUTPUT_TEMPLATE)+1); |
2200 sprintf(f->name, OUTPUT_TEMPLATE, item->file_as.str); | 2206 sprintf(f->name[0], OUTPUT_TEMPLATE, item->file_as.str); |
2201 } | 2207 } |
2202 | 2208 |
2203 f->dname = (char*) pst_malloc(strlen(item->file_as.str)+1); | |
2204 strcpy(f->dname, item->file_as.str); | |
2205 | |
2206 if (overwrite != 1) { | |
2207 int x = 0; | |
2208 char *temp = (char*) pst_malloc (strlen(f->name)+10); //enough room for 10 digits | |
2209 | |
2210 sprintf(temp, "%s", f->name); | |
2211 check_filename(temp); | |
2212 while ((f->output = fopen(temp, "r"))) { | |
2213 DEBUG_INFO(("need to increase filename because one already exists with that name\n")); | |
2214 DEBUG_INFO(("- increasing it to %s%d\n", f->name, x)); | |
2215 x++; | |
2216 sprintf(temp, "%s%08d", f->name, x); | |
2217 DEBUG_INFO(("- trying \"%s\"\n", f->name)); | |
2218 if (x == 99999999) { | |
2219 DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); | |
2220 } | |
2221 fclose(f->output); | |
2222 } | |
2223 if (x > 0) { //then the f->name should change | |
2224 free (f->name); | |
2225 f->name = temp; | |
2226 } else { | |
2227 free(temp); | |
2228 } | |
2229 } | |
2230 | |
2231 DEBUG_INFO(("f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as.str)); | |
2232 if (mode != MODE_SEPARATE) { | 2209 if (mode != MODE_SEPARATE) { |
2233 check_filename(f->name); | 2210 int32_t t; |
2234 if (!(f->output = fopen(f->name, "w"))) { | 2211 for (t=0; t<PST_TYPE_MAX; t++) { |
2235 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name)); | 2212 if (f->name[t]) { |
2213 if (!overwrite) { | |
2214 int x = 0; | |
2215 char *temp = (char*) pst_malloc (strlen(f->name[t])+10); //enough room for 10 digits | |
2216 | |
2217 sprintf(temp, "%s", f->name[t]); | |
2218 check_filename(temp); | |
2219 while ((f->output[t] = fopen(temp, "r"))) { | |
2220 DEBUG_INFO(("need to increase filename because one already exists with that name\n")); | |
2221 DEBUG_INFO(("- increasing it to %s%d\n", f->name, x)); | |
2222 x++; | |
2223 sprintf(temp, "%s%08d", f->name, x); | |
2224 DEBUG_INFO(("- trying \"%s\"\n", f->name)); | |
2225 if (x == 99999999) { | |
2226 DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); | |
2227 } | |
2228 fclose(f->output[t]); | |
2229 } | |
2230 if (x > 0) { //then the f->name should change | |
2231 free (f->name[t]); | |
2232 f->name[t] = temp; | |
2233 } else { | |
2234 free(temp); | |
2235 } | |
2236 } | |
2237 check_filename(f->name[t]); | |
2238 if (!(f->output[t] = fopen(f->name[t], "w"))) { | |
2239 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name[t])); | |
2240 } | |
2241 DEBUG_INFO(("f->name = %s\nitem->folder_name = %s\n", f->name[t], item->file_as.str)); | |
2242 } | |
2236 } | 2243 } |
2237 } | 2244 } |
2238 DEBUG_RET(); | 2245 DEBUG_RET(); |
2239 } | 2246 } |
2240 | 2247 |
2241 | 2248 |
2242 void close_enter_dir(struct file_ll *f) | 2249 void close_enter_dir(struct file_ll *f) |
2243 { | 2250 { |
2251 int32_t t; | |
2244 DEBUG_INFO(("processed item count for folder %s is %i, skipped %i, total %i \n", | 2252 DEBUG_INFO(("processed item count for folder %s is %i, skipped %i, total %i \n", |
2245 f->dname, f->item_count, f->skip_count, f->stored_count)); | 2253 f->dname, f->item_count, f->skip_count, f->stored_count)); |
2246 if (output_mode != OUTPUT_QUIET) { | 2254 if (output_mode != OUTPUT_QUIET) { |
2247 pst_debug_lock(); | 2255 pst_debug_lock(); |
2248 printf("\t\"%s\" - %i items done, %i items skipped.\n", f->dname, f->item_count, f->skip_count); | 2256 printf("\t\"%s\" - %i items done, %i items skipped.\n", f->dname, f->item_count, f->skip_count); |
2249 fflush(stdout); | 2257 fflush(stdout); |
2250 pst_debug_unlock(); | 2258 pst_debug_unlock(); |
2251 } | 2259 } |
2252 if (f->output) { | 2260 for (t=0; t<PST_TYPE_MAX; t++) { |
2253 if (mode == MODE_SEPARATE) DEBUG_WARN(("close_enter_dir finds open separate file\n")); | 2261 if (f->output[t]) { |
2254 struct stat st; | 2262 if (mode == MODE_SEPARATE) DEBUG_WARN(("close_enter_dir finds open separate file\n")); |
2255 fclose(f->output); | 2263 struct stat st; |
2256 stat(f->name, &st); | 2264 fclose(f->output[t]); |
2257 if (!st.st_size) { | 2265 stat(f->name[t], &st); |
2258 DEBUG_WARN(("removing empty output file %s\n", f->name)); | 2266 if (!st.st_size) { |
2259 remove(f->name); | 2267 DEBUG_WARN(("removing empty output file %s\n", f->name[t])); |
2260 } | 2268 remove(f->name[t]); |
2261 f->output = NULL; | 2269 } |
2262 } | 2270 f->output[t] = NULL; |
2263 free(f->name); | 2271 } |
2272 free(f->name[t]); | |
2273 f->name[t] = NULL; | |
2274 } | |
2264 free(f->dname); | 2275 free(f->dname); |
2265 | 2276 |
2266 if (mode == MODE_KMAIL) | 2277 if (mode == MODE_KMAIL) |
2267 close_kmail_dir(); | 2278 close_kmail_dir(); |
2268 else if (mode == MODE_RECURSE) { | 2279 else if (mode == MODE_RECURSE) { |