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) {