Mercurial > libpst
comparison src/readpst.c @ 25:73e8959cd86b
patches from Arne
author | carl |
---|---|
date | Tue, 21 Feb 2006 22:50:16 -0800 |
parents | e5418051878c |
children | 9eeba3f4ca4b |
comparison
equal
deleted
inserted
replaced
24:f4643b609bdf | 25:73e8959cd86b |
---|---|
38 #include "timeconv.h" | 38 #include "timeconv.h" |
39 #include "lzfu.h" | 39 #include "lzfu.h" |
40 #define OUTPUT_TEMPLATE "%s" | 40 #define OUTPUT_TEMPLATE "%s" |
41 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" | 41 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" |
42 #define KMAIL_INDEX ".%s.index" | 42 #define KMAIL_INDEX ".%s.index" |
43 #define SEP_MAIL_FILE_TEMPLATE "%i" /* "%09i" */ | |
43 | 44 |
44 // max size of the c_time char*. It will store the date of the email | 45 // max size of the c_time char*. It will store the date of the email |
45 #define C_TIME_SIZE 500 | 46 #define C_TIME_SIZE 500 |
46 #define PERM_DIRS 0777 | 47 #define PERM_DIRS 0777 |
47 | 48 |
77 char *rfc2426_escape(char *str); | 78 char *rfc2426_escape(char *str); |
78 int32_t chr_count(char *str, char x); | 79 int32_t chr_count(char *str, char x); |
79 char *rfc2425_datetime_format(FILETIME *ft); | 80 char *rfc2425_datetime_format(FILETIME *ft); |
80 char *rfc2445_datetime_format(FILETIME *ft); | 81 char *rfc2445_datetime_format(FILETIME *ft); |
81 char *skip_header_prologue(char *headers); | 82 char *skip_header_prologue(char *headers); |
83 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst); | |
84 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst); | |
85 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst); | |
86 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]); | |
87 void write_appointment(FILE* f_output, pst_item_appointment* appointment, | |
88 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date); | |
89 void create_enter_dir(struct file_ll* f, char file_as[], int mode, int overwrite); | |
82 char *prog_name; | 90 char *prog_name; |
83 char *output_dir = "."; | 91 char *output_dir = "."; |
84 char *kmail_chdir = NULL; | 92 char *kmail_chdir = NULL; |
85 // Normal mode just creates mbox format files in the current directory. Each file is named | 93 // Normal mode just creates mbox format files in the current directory. Each file is named |
86 // the same as the folder's name that it represents | 94 // the same as the folder's name that it represents |
118 int main(int argc, char** argv) { | 126 int main(int argc, char** argv) { |
119 pst_item *item = NULL; | 127 pst_item *item = NULL; |
120 pst_file pstfile; | 128 pst_file pstfile; |
121 pst_desc_ll *d_ptr; | 129 pst_desc_ll *d_ptr; |
122 char * fname = NULL; | 130 char * fname = NULL; |
123 time_t em_time; | 131 char *d_log=NULL; |
124 char * c_time, *d_log=NULL; | |
125 int c,x; | 132 int c,x; |
126 int mode = MODE_NORMAL; | 133 int mode = MODE_NORMAL; |
134 int mode_MH = 0; | |
127 int output_mode = OUTPUT_NORMAL; | 135 int output_mode = OUTPUT_NORMAL; |
128 int contact_mode = CMODE_VCARD; | 136 int contact_mode = CMODE_VCARD; |
129 int overwrite = 0; | 137 int overwrite = 0; |
130 int base64_body = 0; | |
131 // int encrypt = 0; | 138 // int encrypt = 0; |
132 FILE *fp; | |
133 char *enc; // base64 encoded attachment | |
134 char *boundary = NULL, *b1, *b2; // the boundary marker between multipart sections | |
135 char *temp = NULL; //temporary char pointer | 139 char *temp = NULL; //temporary char pointer |
136 int attach_num = 0; | |
137 int skip_child = 0; | 140 int skip_child = 0; |
138 struct file_ll *f, *head; | 141 struct file_ll *f, *head; |
139 prog_name = argv[0]; | 142 prog_name = argv[0]; |
140 | 143 |
141 while ((c = getopt(argc, argv, "d:hko:qrSVwc:"))!= -1) { | 144 while ((c = getopt(argc, argv, "d:hko:qrMSVwc:"))!= -1) { |
142 switch (c) { | 145 switch (c) { |
143 case 'c': | 146 case 'c': |
144 if (optarg!=NULL && optarg[0]=='v') | 147 if (optarg!=NULL && optarg[0]=='v') |
145 contact_mode=CMODE_VCARD; | 148 contact_mode=CMODE_VCARD; |
146 else if (optarg!=NULL && optarg[0]=='l') | 149 else if (optarg!=NULL && optarg[0]=='l') |
162 exit(0); | 165 exit(0); |
163 break; | 166 break; |
164 case 'k': | 167 case 'k': |
165 mode = MODE_KMAIL; | 168 mode = MODE_KMAIL; |
166 break; | 169 break; |
170 case 'M': | |
171 mode = MODE_SEPERATE; | |
172 mode_MH = 1; | |
173 break; | |
167 case 'o': | 174 case 'o': |
168 output_dir = optarg; | 175 output_dir = optarg; |
169 break; | 176 break; |
170 case 'q': | 177 case 'q': |
171 output_mode = OUTPUT_QUIET; | 178 output_mode = OUTPUT_QUIET; |
246 memset(f, 0, sizeof(struct file_ll)); | 253 memset(f, 0, sizeof(struct file_ll)); |
247 f->email_count = 0; | 254 f->email_count = 0; |
248 f->skip_count = 0; | 255 f->skip_count = 0; |
249 f->next = NULL; | 256 f->next = NULL; |
250 head = f; | 257 head = f; |
251 if (mode == MODE_KMAIL) | 258 create_enter_dir(f, item->file_as, mode, overwrite); |
252 f->name = mk_kmail_dir(item->file_as); | |
253 else if (mode == MODE_RECURSE) | |
254 f->name = mk_recurse_dir(item->file_as); | |
255 else if (mode == MODE_SEPERATE) { | |
256 // do similar stuff to recurse here. | |
257 mk_seperate_dir(item->file_as, overwrite); | |
258 f->name = (char*) xmalloc(10); | |
259 sprintf(f->name, "%09i", f->email_count); | |
260 } else { | |
261 f->name = (char*) malloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1); | |
262 sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); | |
263 } | |
264 | |
265 f->dname = (char*) malloc(strlen(item->file_as)+1); | |
266 strcpy(f->dname, item->file_as); | |
267 | |
268 if (overwrite != 1 && mode != MODE_SEPERATE) { | |
269 // if overwrite is set to 1 we keep the existing name and don't modify anything | |
270 // we don't want to go changing the file name of the SEPERATE items | |
271 temp = (char*) malloc (strlen(f->name)+10); //enough room for 10 digits | |
272 sprintf(temp, "%s", f->name); | |
273 temp = check_filename(temp); | |
274 x = 0; | |
275 while ((f->output = fopen(temp, "r")) != NULL) { | |
276 DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); | |
277 DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); | |
278 x++; | |
279 sprintf(temp, "%s%08d", f->name, x); | |
280 DEBUG_MAIN(("main: - trying \"%s\"\n", temp)); | |
281 if (x == 99999999) { | |
282 DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); | |
283 } | |
284 fclose(f->output); | |
285 } | |
286 if (x > 0) { //then the f->name should change | |
287 free (f->name); | |
288 f->name = temp; | |
289 } else { | |
290 free (temp); | |
291 } | |
292 } | |
293 if (mode != MODE_SEPERATE) { | |
294 f->name = check_filename(f->name); | |
295 if ((f->output = fopen(f->name, "w")) == NULL) { | |
296 DIE(("main: Could not open file \"%s\" for write\n", f->name)); | |
297 } | |
298 } | |
299 f->type = item->type; | 259 f->type = item->type; |
300 | 260 |
301 if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) { | 261 if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) { |
302 DIE(("Top of folders record not found. Cannot continue\n")); | 262 DIE(("Top of folders record not found. Cannot continue\n")); |
303 } | 263 } |
353 f->stored_count = item->folder->email_count; | 313 f->stored_count = item->folder->email_count; |
354 head = f; | 314 head = f; |
355 | 315 |
356 temp = item->file_as; | 316 temp = item->file_as; |
357 temp = check_filename(temp); | 317 temp = check_filename(temp); |
358 | 318 create_enter_dir(f, item->file_as, mode, overwrite); |
359 if (mode == MODE_KMAIL) | |
360 f->name = mk_kmail_dir(item->file_as); //create directory and form filename | |
361 else if (mode == MODE_RECURSE) | |
362 f->name = mk_recurse_dir(item->file_as); | |
363 else if (mode == MODE_SEPERATE) { | |
364 // do similar stuff to recurse here. | |
365 mk_seperate_dir(item->file_as, overwrite); | |
366 f->name = (char*) xmalloc(10); | |
367 memset(f->name, 0, 10); | |
368 // sprintf(f->name, "%09i", f->email_count); | |
369 } else { | |
370 f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE+1)); | |
371 sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); | |
372 } | |
373 | |
374 f->dname = (char*) xmalloc(strlen(item->file_as)+1); | |
375 strcpy(f->dname, item->file_as); | |
376 | |
377 if (overwrite != 1) { | |
378 temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits | |
379 sprintf(temp, "%s", f->name); | |
380 x = 0; | |
381 temp = check_filename(temp); | |
382 while ((f->output = fopen(temp, "r")) != NULL) { | |
383 DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); | |
384 DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); | |
385 x++; | |
386 sprintf(temp, "%s%08d", f->name, x); | |
387 DEBUG_MAIN(("main: - trying \"%s\"\n", f->name)); | |
388 if (x == 99999999) { | |
389 DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); | |
390 } | |
391 fclose(f->output); | |
392 } | |
393 if (x > 0) { //then the f->name should change | |
394 free (f->name); | |
395 f->name = temp; | |
396 } else { | |
397 free(temp); | |
398 } | |
399 } | |
400 | |
401 DEBUG_MAIN(("main: f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); | |
402 if (mode != MODE_SEPERATE) { | |
403 f->name = check_filename(f->name); | |
404 if ((f->output = fopen(f->name, "w")) == NULL) { | |
405 DIE(("main: Could not open file \"%s\" for write\n", f->name)); | |
406 } | |
407 } | |
408 if (d_ptr->child != NULL) { | 319 if (d_ptr->child != NULL) { |
409 d_ptr = d_ptr->child; | 320 d_ptr = d_ptr->child; |
410 skip_child = 1; | 321 skip_child = 1; |
411 } else { | 322 } else { |
412 DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n")); | 323 DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n")); |
450 DEBUG_MAIN(("main: Processing anyway\n")); | 361 DEBUG_MAIN(("main: Processing anyway\n")); |
451 } | 362 } |
452 if (item->contact == NULL) { // this is an incorrect situation. Inform user | 363 if (item->contact == NULL) { // this is an incorrect situation. Inform user |
453 DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); | 364 DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); |
454 } else { | 365 } else { |
455 if (contact_mode == CMODE_VCARD) { | 366 if (contact_mode == CMODE_VCARD) |
456 // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile | 367 write_vcard(f->output, item->contact, item->comment); |
457 fprintf(f->output, "BEGIN:VCARD\n"); | 368 else |
458 fprintf(f->output, "FN:%s\n", rfc2426_escape(item->contact->fullname)); | |
459 fprintf(f->output, "N:%s;%s;%s;%s;%s\n", | |
460 rfc2426_escape((item->contact->surname==NULL?"":item->contact->surname)), | |
461 rfc2426_escape((item->contact->first_name==NULL?"":item->contact->first_name)), | |
462 rfc2426_escape((item->contact->middle_name==NULL?"":item->contact->middle_name)), | |
463 rfc2426_escape((item->contact->display_name_prefix==NULL?"":item->contact->display_name_prefix)), | |
464 rfc2426_escape((item->contact->suffix==NULL?"":item->contact->suffix))); | |
465 if (item->contact->nickname != NULL) | |
466 fprintf(f->output, "NICKNAME:%s\n", rfc2426_escape(item->contact->nickname)); | |
467 if (item->contact->address1 != NULL) | |
468 fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address1)); | |
469 if (item->contact->address2 != NULL) | |
470 fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address2)); | |
471 if (item->contact->address3 != NULL) | |
472 fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address3)); | |
473 if (item->contact->birthday != NULL) | |
474 fprintf(f->output, "BDAY:%s\n", rfc2425_datetime_format(item->contact->birthday)); | |
475 if (item->contact->home_address != NULL) { | |
476 fprintf(f->output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", | |
477 rfc2426_escape((item->contact->home_po_box!=NULL?item->contact->home_po_box:"")), | |
478 "", // extended Address | |
479 rfc2426_escape((item->contact->home_street!=NULL?item->contact->home_street:"")), | |
480 rfc2426_escape((item->contact->home_city!=NULL?item->contact->home_city:"")), | |
481 rfc2426_escape((item->contact->home_state!=NULL?item->contact->home_state:"")), | |
482 rfc2426_escape((item->contact->home_postal_code!=NULL?item->contact->home_postal_code:"")), | |
483 rfc2426_escape((item->contact->home_country!=NULL?item->contact->home_country:""))); | |
484 fprintf(f->output, "LABEL;TYPE=home:%s\n", rfc2426_escape(item->contact->home_address)); | |
485 } | |
486 if (item->contact->business_address != NULL) { | |
487 fprintf(f->output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", | |
488 rfc2426_escape((item->contact->business_po_box!=NULL?item->contact->business_po_box:"")), | |
489 "", // extended Address | |
490 rfc2426_escape((item->contact->business_street!=NULL?item->contact->business_street:"")), | |
491 rfc2426_escape((item->contact->business_city!=NULL?item->contact->business_city:"")), | |
492 rfc2426_escape((item->contact->business_state!=NULL?item->contact->business_state:"")), | |
493 rfc2426_escape((item->contact->business_postal_code!=NULL?item->contact->business_postal_code:"")), | |
494 rfc2426_escape((item->contact->business_country!=NULL?item->contact->business_country:""))); | |
495 fprintf(f->output, "LABEL;TYPE=work:%s\n", rfc2426_escape(item->contact->business_address)); | |
496 } | |
497 if (item->contact->other_address != NULL) { | |
498 fprintf(f->output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", | |
499 rfc2426_escape((item->contact->other_po_box!=NULL?item->contact->business_po_box:"")), | |
500 "", // extended Address | |
501 rfc2426_escape((item->contact->other_street!=NULL?item->contact->other_street:"")), | |
502 rfc2426_escape((item->contact->other_city!=NULL?item->contact->other_city:"")), | |
503 rfc2426_escape((item->contact->other_state!=NULL?item->contact->other_state:"")), | |
504 rfc2426_escape((item->contact->other_postal_code!=NULL?item->contact->other_postal_code:"")), | |
505 rfc2426_escape((item->contact->other_country!=NULL?item->contact->other_country:""))); | |
506 fprintf(f->output, "ADR;TYPE=postal:%s\n", rfc2426_escape(item->contact->other_address)); | |
507 } | |
508 if (item->contact->business_fax != NULL) | |
509 fprintf(f->output, "TEL;TYPE=work,fax:%s\n", rfc2426_escape(item->contact->business_fax)); | |
510 if (item->contact->business_phone != NULL) | |
511 fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone)); | |
512 if (item->contact->business_phone2 != NULL) | |
513 fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone2)); | |
514 if (item->contact->car_phone != NULL) | |
515 fprintf(f->output, "TEL;TYPE=car,voice:%s\n", rfc2426_escape(item->contact->car_phone)); | |
516 if (item->contact->home_fax != NULL) | |
517 fprintf(f->output, "TEL;TYPE=home,fax:%s\n", rfc2426_escape(item->contact->home_fax)); | |
518 if (item->contact->home_phone != NULL) | |
519 fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone)); | |
520 if (item->contact->home_phone2 != NULL) | |
521 fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone2)); | |
522 if (item->contact->isdn_phone != NULL) | |
523 fprintf(f->output, "TEL;TYPE=isdn:%s\n", rfc2426_escape(item->contact->isdn_phone)); | |
524 if (item->contact->mobile_phone != NULL) | |
525 fprintf(f->output, "TEL;TYPE=cell,voice:%s\n", rfc2426_escape(item->contact->mobile_phone)); | |
526 if (item->contact->other_phone != NULL) | |
527 fprintf(f->output, "TEL;TYPE=msg:%s\n", rfc2426_escape(item->contact->other_phone)); | |
528 if (item->contact->pager_phone != NULL) | |
529 fprintf(f->output, "TEL;TYPE=pager:%s\n", rfc2426_escape(item->contact->pager_phone)); | |
530 if (item->contact->primary_fax != NULL) | |
531 fprintf(f->output, "TEL;TYPE=fax,pref:%s\n", rfc2426_escape(item->contact->primary_fax)); | |
532 if (item->contact->primary_phone != NULL) | |
533 fprintf(f->output, "TEL;TYPE=phone,pref:%s\n", rfc2426_escape(item->contact->primary_phone)); | |
534 if (item->contact->radio_phone != NULL) | |
535 fprintf(f->output, "TEL;TYPE=pcs:%s\n", rfc2426_escape(item->contact->radio_phone)); | |
536 if (item->contact->telex != NULL) | |
537 fprintf(f->output, "TEL;TYPE=bbs:%s\n", rfc2426_escape(item->contact->telex)); | |
538 if (item->contact->job_title != NULL) | |
539 fprintf(f->output, "TITLE:%s\n", rfc2426_escape(item->contact->job_title)); | |
540 if (item->contact->profession != NULL) | |
541 fprintf(f->output, "ROLE:%s\n", rfc2426_escape(item->contact->profession)); | |
542 if (item->contact->assistant_name != NULL || item->contact->assistant_phone != NULL) { | |
543 fprintf(f->output, "AGENT:BEGIN:VCARD\\n"); | |
544 if (item->contact->assistant_name != NULL) | |
545 fprintf(f->output, "FN:%s\\n", rfc2426_escape(item->contact->assistant_name)); | |
546 if (item->contact->assistant_phone != NULL) | |
547 fprintf(f->output, "TEL:%s\\n", rfc2426_escape(item->contact->assistant_phone)); | |
548 fprintf(f->output, "END:VCARD\\n\n"); | |
549 } | |
550 if (item->contact->company_name != NULL) | |
551 fprintf(f->output, "ORG:%s\n", rfc2426_escape(item->contact->company_name)); | |
552 if (item->comment != NULL) | |
553 fprintf(f->output, "NOTE:%s\n", rfc2426_escape(item->comment)); | |
554 | |
555 fprintf(f->output, "VERSION: 3.0\n"); | |
556 fprintf(f->output, "END:VCARD\n\n"); | |
557 } else { | |
558 fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1); | 369 fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1); |
559 } | 370 } |
560 } | |
561 } else if (item->email != NULL && | 371 } else if (item->email != NULL && |
562 (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { | 372 (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { |
563 if (mode == MODE_SEPERATE) { | 373 if (mode == MODE_SEPERATE) { |
564 mk_seperate_file(f); | 374 mk_seperate_file(f); |
565 } | 375 } |
566 | 376 |
567 f->email_count++; | 377 f->email_count++; |
568 | 378 |
569 DEBUG_MAIN(("main: seen an email\n")); | 379 DEBUG_MAIN(("main: seen an email\n")); |
570 | 380 write_normal_email(f->output, f->name, item, mode, mode_MH, &pstfile); |
571 // convert the sent date if it exists, or set it to a fixed date | |
572 if (item->email->sent_date != NULL) { | |
573 em_time = fileTimeToUnixTime(item->email->sent_date, 0); | |
574 c_time = ctime(&em_time); | |
575 if (c_time != NULL) | |
576 c_time[strlen(c_time)-1] = '\0'; //remove end \n | |
577 else | |
578 c_time = "Fri Dec 28 12:06:21 2001"; | |
579 } else | |
580 c_time= "Fri Dec 28 12:06:21 2001"; | |
581 | |
582 // if the boundary is still set from the previous run, then free it | |
583 if (boundary != NULL) { | |
584 free (boundary); | |
585 boundary = NULL; | |
586 } | |
587 | |
588 // we will always look at the header to discover some stuff | |
589 if (item->email->header != NULL ) { | |
590 // see if there is a boundary variable there | |
591 // this search MUST be made case insensitive (DONE). | |
592 // Also, some check to find out if we | |
593 // are looking at the boundary associated with content-type, and that the content | |
594 // type really is "multipart" | |
595 if ((b2 = my_stristr(item->email->header, "boundary=")) != NULL) { | |
596 b2 += strlen("boundary="); // move boundary to first char of marker | |
597 | |
598 if (*b2 == '"') { | |
599 b2++; | |
600 b1 = strchr(b2, '"'); // find terminating quote | |
601 } else { | |
602 b1 = b2; | |
603 while (isgraph(*b1)) // find first char that isn't part of boundary | |
604 b1++; | |
605 } | |
606 | |
607 boundary = malloc ((b1-b2)+1); //malloc that length | |
608 memset (boundary, 0, (b1-b2)+1); // blank it | |
609 strncpy(boundary, b2, b1-b2); // copy boundary to another variable | |
610 b1 = b2 = boundary; | |
611 while (*b2 != '\0') { // remove any CRs and Tabs | |
612 if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { | |
613 *b1 = *b2; | |
614 b1++; | |
615 } | |
616 b2++; | |
617 } | |
618 *b1 = '\0'; | |
619 | |
620 DEBUG_MAIN(("main: Found boundary of - %s\n", boundary)); | |
621 } else { | |
622 | |
623 DEBUG_MAIN(("main: boundary not found in header\n")); | |
624 } | |
625 | |
626 // also possible to set 7bit encoding detection here. | |
627 if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:")) != NULL) { | |
628 if ((b2 = strchr(b2, ':')) != NULL) { | |
629 b2++; // skip to the : at the end of the string | |
630 | |
631 while (*b2 == ' ' || *b2 == '\t') | |
632 b2++; | |
633 if (pst_strincmp(b2, "base64", 6)==0) { | |
634 DEBUG_MAIN(("body is base64 encoded\n")); | |
635 base64_body = 1; | |
636 } | |
637 } else { | |
638 DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); | |
639 } | |
640 } | |
641 | |
642 } | |
643 | |
644 DEBUG_MAIN(("main: About to print Header\n")); | |
645 | |
646 if (item != NULL && item->email != NULL && item->email->subject != NULL && | |
647 item->email->subject->subj != NULL) { | |
648 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); | |
649 } | |
650 if (item->email->header != NULL) { | |
651 // some of the headers we get from the file are not properly defined. | |
652 // they can contain some email stuff too. We will cut off the header | |
653 // when we see a \n\n or \r\n\r\n | |
654 | |
655 removeCR(item->email->header); | |
656 | |
657 temp = strstr(item->email->header, "\n\n"); | |
658 | |
659 if (temp != NULL) { | |
660 DEBUG_MAIN(("main: Found body text in header\n")); | |
661 *temp = '\0'; | |
662 } | |
663 | |
664 if (mode != MODE_SEPERATE) { | |
665 char *soh = NULL; // real start of headers. | |
666 // don't put rubbish in if we are doing seperate | |
667 fprintf(f->output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); | |
668 soh = skip_header_prologue(item->email->header); | |
669 fprintf(f->output, "%s\n", soh); | |
670 } else { | |
671 fprintf(f->output, "%s", item->email->header); | |
672 } | |
673 } else { | |
674 //make up our own header! | |
675 if (mode != MODE_SEPERATE) { | |
676 // don't want this first line for this mode | |
677 if (item->email->outlook_sender_name != NULL) { | |
678 temp = item->email->outlook_sender_name; | |
679 } else { | |
680 temp = "(readpst_null)"; | |
681 } | |
682 fprintf(f->output, "From \"%s\" %s\n", temp, c_time); | |
683 } | |
684 if ((temp = item->email->outlook_sender) == NULL) | |
685 temp = ""; | |
686 fprintf(f->output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); | |
687 if (item->email->subject != NULL) { | |
688 fprintf(f->output, "Subject: %s\n", item->email->subject->subj); | |
689 } else { | |
690 fprintf(f->output, "Subject: \n"); | |
691 } | |
692 fprintf(f->output, "To: %s\n", item->email->sentto_address); | |
693 if (item->email->cc_address != NULL) { | |
694 fprintf(f->output, "Cc: %s\n", item->email->cc_address); | |
695 } | |
696 if (item->email->sent_date != NULL) { | |
697 c_time = (char*) xmalloc(C_TIME_SIZE); | |
698 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); | |
699 fprintf(f->output, "Date: %s\n", c_time); | |
700 free(c_time); | |
701 } | |
702 | |
703 fprintf(f->output, "MIME-Version: 1.0\n"); | |
704 } | |
705 if (boundary == NULL && (item->attach ||(item->email->body && item->email->htmlbody) | |
706 || item->email->rtf_compressed || item->email->encrypted_body | |
707 || item->email->encrypted_htmlbody)) { | |
708 // we need to create a boundary here. | |
709 DEBUG_EMAIL(("main: must create own boundary. oh dear.\n")); | |
710 boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary | |
711 boundary[0] = '\0'; | |
712 sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); | |
713 DEBUG_EMAIL(("main: created boundary is %s\n", boundary)); | |
714 | |
715 /* If boundary != NULL, then it'll already be printed with existing | |
716 * headers. Otherwise, we generate it here, and print it. | |
717 */ | |
718 if (item->attach != NULL) { | |
719 // write the boundary stuff if we have attachments | |
720 fprintf(f->output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", | |
721 boundary); | |
722 } else if (boundary != NULL) { | |
723 // else if we have multipart/alternative then tell it so | |
724 fprintf(f->output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", | |
725 boundary); | |
726 } else if (item->email->htmlbody) { | |
727 fprintf(f->output, "Content-type: text/html\n"); | |
728 } | |
729 } | |
730 fprintf(f->output, "\n"); | |
731 | |
732 DEBUG_MAIN(("main: About to print Body\n")); | |
733 | |
734 if (item->email->body != NULL) { | |
735 if (boundary) { | |
736 fprintf(f->output, "\n--%s\n", boundary); | |
737 fprintf(f->output, "Content-type: text/plain\n"); | |
738 if (base64_body) fprintf(f->output, "Content-Transfer-Encoding: base64\n"); | |
739 fprintf(f->output, "\n"); | |
740 } | |
741 removeCR(item->email->body); | |
742 if (base64_body) | |
743 write_email_body(f->output, base64_encode(item->email->body, | |
744 strlen(item->email->body))); | |
745 else | |
746 write_email_body(f->output, item->email->body); | |
747 } | |
748 | |
749 if (item->email->htmlbody != NULL) { | |
750 if (boundary) { | |
751 fprintf(f->output, "\n--%s\n", boundary); | |
752 fprintf(f->output, "Content-type: text/html\n"); | |
753 if (base64_body) fprintf(f->output, "Content-Transfer-Encoding: base64\n"); | |
754 fprintf(f->output, "\n"); | |
755 } | |
756 removeCR(item->email->htmlbody); | |
757 if (base64_body) | |
758 write_email_body(f->output, base64_encode(item->email->htmlbody, | |
759 strlen(item->email->htmlbody))); | |
760 else | |
761 write_email_body(f->output, item->email->htmlbody); | |
762 } | |
763 | |
764 attach_num = 0; | |
765 | |
766 if (item->email->rtf_compressed != NULL) { | |
767 DEBUG_MAIN(("Adding RTF body as attachment\n")); | |
768 item->current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); | |
769 memset(item->current_attach, 0, sizeof(pst_item_attach)); | |
770 item->current_attach->next = item->attach; | |
771 item->attach = item->current_attach; | |
772 item->current_attach->data = lzfu_decompress(item->email->rtf_compressed); | |
773 item->current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); | |
774 strcpy(item->current_attach->filename2, RTF_ATTACH_NAME); | |
775 item->current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); | |
776 strcpy(item->current_attach->mimetype, RTF_ATTACH_TYPE); | |
777 memcpy(&(item->current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); | |
778 LE32_CPU(item->current_attach->size); | |
779 // item->email->rtf_compressed = ; | |
780 // attach_num++; | |
781 } | |
782 if (item->email->encrypted_body || item->email->encrypted_htmlbody) { | |
783 // if either the body or htmlbody is encrypted, add them as attachments | |
784 if (item->email->encrypted_body) { | |
785 DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); | |
786 item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); | |
787 memset(item->current_attach, 0, sizeof(pst_item_attach)); | |
788 item->current_attach->next = item->attach; | |
789 item->attach = item->current_attach; | |
790 | |
791 item->current_attach->data = item->email->encrypted_body; | |
792 item->current_attach->size = item->email->encrypted_body_size; | |
793 item->email->encrypted_body = NULL; | |
794 } | |
795 if (item->email->encrypted_htmlbody) { | |
796 DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); | |
797 item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); | |
798 memset(item->current_attach, 0, sizeof(pst_item_attach)); | |
799 item->current_attach->next = item->attach; | |
800 item->attach = item->current_attach; | |
801 | |
802 item->current_attach->data = item->email->encrypted_htmlbody; | |
803 item->current_attach->size = item->email->encrypted_htmlbody_size; | |
804 item->email->encrypted_htmlbody = NULL; | |
805 } | |
806 write_email_body(f->output, "The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n"); | |
807 } | |
808 base64_body = 0; | |
809 // attachments | |
810 item->current_attach = item->attach; | |
811 while (item->current_attach != NULL) { | |
812 DEBUG_MAIN(("main: Attempting Attachment encoding\n")); | |
813 if (item->current_attach->data == NULL) { | |
814 DEBUG_MAIN(("main: Data of attachment is NULL!. Size is supposed to be %i\n", item->current_attach->size)); | |
815 } | |
816 if (mode == MODE_SEPERATE) { | |
817 f->name = check_filename(f->name); | |
818 if (item->current_attach->filename2 == NULL) { | |
819 temp = xmalloc(strlen(f->name)+15); | |
820 sprintf(temp, "%s-attach%i", f->name, attach_num); | |
821 } else { | |
822 temp = xmalloc(strlen(f->name)+strlen(item->current_attach->filename2)+15); | |
823 fp = NULL; x=0; | |
824 do { | |
825 if (fp != NULL) fclose(fp); | |
826 if (x == 0) | |
827 sprintf(temp, "%s-%s", f->name, item->current_attach->filename2); | |
828 else | |
829 sprintf(temp, "%s-%s-%i", f->name, item->current_attach->filename2, x); | |
830 } while ((fp = fopen(temp, "r"))!=NULL && ++x < 99999999); | |
831 if (x > 99999999) { | |
832 DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); | |
833 } | |
834 } | |
835 DEBUG_MAIN(("main: Saving attachment to %s\n", temp)); | |
836 if ((fp = fopen(temp, "w")) == NULL) { | |
837 WARN(("main: Cannot open attachment save file \"%s\"\n", temp)); | |
838 } else { | |
839 if (item->current_attach->data != NULL) | |
840 fwrite(item->current_attach->data, 1, item->current_attach->size, fp); | |
841 else { | |
842 pst_attach_to_file(&pstfile, item->current_attach, fp); | |
843 } | |
844 fclose(fp); | |
845 } | |
846 } else { | |
847 DEBUG_MAIN(("main: Attachment Size is %i\n", item->current_attach->size)); | |
848 DEBUG_MAIN(("main: Attachment Pointer is %p\n", item->current_attach->data)); | |
849 if (item->current_attach->data != NULL) { | |
850 if ((enc = base64_encode (item->current_attach->data, item->current_attach->size)) == NULL) { | |
851 DEBUG_MAIN(("main: ERROR base64_encode returned NULL. Must have failed\n")); | |
852 item->current_attach = item->current_attach->next; | |
853 continue; | |
854 } | |
855 } | |
856 if (boundary) { | |
857 fprintf(f->output, "\n--%s\n", boundary); | |
858 if (item->current_attach->mimetype == NULL) { | |
859 fprintf(f->output, "Content-type: %s\n", MIME_TYPE_DEFAULT); | |
860 } else { | |
861 fprintf(f->output, "Content-type: %s\n", item->current_attach->mimetype); | |
862 } | |
863 fprintf(f->output, "Content-transfer-encoding: base64\n"); | |
864 if (item->current_attach->filename2 == NULL) { | |
865 fprintf(f->output, "Content-Disposition: inline\n\n"); | |
866 } else { | |
867 fprintf(f->output, "Content-Disposition: attachment; filename=\"%s\"\n\n", | |
868 item->current_attach->filename2); | |
869 } | |
870 } | |
871 if (item->current_attach->data != NULL) { | |
872 fwrite(enc, 1, strlen(enc), f->output); | |
873 DEBUG_MAIN(("Attachment Size after encoding is %i\n", strlen(enc))); | |
874 } else { | |
875 pst_attach_to_file_base64(&pstfile, item->current_attach, f->output); | |
876 } | |
877 fprintf(f->output, "\n\n"); | |
878 } | |
879 item->current_attach = item->current_attach->next; | |
880 attach_num++; | |
881 } | |
882 if (mode != MODE_SEPERATE) { | |
883 DEBUG_MAIN(("main: Writing buffer between emails\n")); | |
884 if (boundary) | |
885 fprintf(f->output, "\n--%s--\n", boundary); | |
886 fprintf(f->output, "\n\n"); | |
887 } | |
888 } else if (item->type == PST_TYPE_JOURNAL) { | 381 } else if (item->type == PST_TYPE_JOURNAL) { |
889 // deal with journal items | 382 // deal with journal items |
890 if (mode == MODE_SEPERATE) { | 383 if (mode == MODE_SEPERATE) { |
891 mk_seperate_file(f); | 384 mk_seperate_file(f); |
892 } | 385 } |
918 | 411 |
919 DEBUG_MAIN(("main: Processing Appointment Entry\n")); | 412 DEBUG_MAIN(("main: Processing Appointment Entry\n")); |
920 if (f->type != PST_TYPE_APPOINTMENT) { | 413 if (f->type != PST_TYPE_APPOINTMENT) { |
921 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); | 414 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); |
922 } | 415 } |
923 fprintf(f->output, "BEGIN:VEVENT\n"); | 416 write_appointment(f->output, item->appointment, item->email, item->create_date, item->modify_date); |
924 if (item->create_date != NULL) | |
925 fprintf(f->output, "CREATED:%s\n", rfc2445_datetime_format(item->create_date)); | |
926 if (item->modify_date != NULL) | |
927 fprintf(f->output, "LAST-MOD:%s\n", rfc2445_datetime_format(item->modify_date)); | |
928 if (item->email != NULL && item->email->subject != NULL) | |
929 fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); | |
930 if (item->email != NULL && item->email->body != NULL) | |
931 fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); | |
932 if (item->appointment != NULL && item->appointment->start != NULL) | |
933 fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->start)); | |
934 if (item->appointment != NULL && item->appointment->end != NULL) | |
935 fprintf(f->output, "DTEND;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->end)); | |
936 if (item->appointment != NULL && item->appointment->location != NULL) | |
937 fprintf(f->output, "LOCATION:%s\n", rfc2426_escape(item->appointment->location)); | |
938 if (item->appointment != NULL) { | |
939 switch (item->appointment->showas) { | |
940 case PST_FREEBUSY_TENTATIVE: | |
941 fprintf(f->output, "STATUS:TENTATIVE\n"); | |
942 break; | |
943 case PST_FREEBUSY_FREE: | |
944 // mark as transparent and as confirmed | |
945 fprintf(f->output, "TRANSP:TRANSPARENT\n"); | |
946 case PST_FREEBUSY_BUSY: | |
947 case PST_FREEBUSY_OUT_OF_OFFICE: | |
948 fprintf(f->output, "STATUS:CONFIRMED\n"); | |
949 break; | |
950 } | |
951 switch (item->appointment->label) { | |
952 case PST_APP_LABEL_NONE: | |
953 fprintf(f->output, "CATEGORIES:NONE\n"); break; | |
954 case PST_APP_LABEL_IMPORTANT: | |
955 fprintf(f->output, "CATEGORIES:IMPORTANT\n"); break; | |
956 case PST_APP_LABEL_BUSINESS: | |
957 fprintf(f->output, "CATEGORIES:BUSINESS\n"); break; | |
958 case PST_APP_LABEL_PERSONAL: | |
959 fprintf(f->output, "CATEGORIES:PERSONAL\n"); break; | |
960 case PST_APP_LABEL_VACATION: | |
961 fprintf(f->output, "CATEGORIES:VACATION\n"); break; | |
962 case PST_APP_LABEL_MUST_ATTEND: | |
963 fprintf(f->output, "CATEGORIES:MUST-ATTEND\n"); break; | |
964 case PST_APP_LABEL_TRAVEL_REQ: | |
965 fprintf(f->output, "CATEGORIES:TRAVEL-REQUIRED\n"); break; | |
966 case PST_APP_LABEL_NEEDS_PREP: | |
967 fprintf(f->output, "CATEGORIES:NEEDS-PREPARATION\n"); break; | |
968 case PST_APP_LABEL_BIRTHDAY: | |
969 fprintf(f->output, "CATEGORIES:BIRTHDAY\n"); break; | |
970 case PST_APP_LABEL_ANNIVERSARY: | |
971 fprintf(f->output, "CATEGORIES:ANNIVERSARY\n"); break; | |
972 case PST_APP_LABEL_PHONE_CALL: | |
973 fprintf(f->output, "CATEGORIES:PHONE-CALL\n"); break; | |
974 } | |
975 } | |
976 fprintf(f->output, "END:VEVENT\n\n"); | |
977 } else { | 417 } else { |
978 f->skip_count++; | 418 f->skip_count++; |
979 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", | 419 DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", |
980 item->type, item->ascii_type)); | 420 item->type, item->ascii_type)); |
981 } | 421 } |
983 f->skip_count++; | 423 f->skip_count++; |
984 DEBUG_MAIN(("main: A NULL item was seen\n")); | 424 DEBUG_MAIN(("main: A NULL item was seen\n")); |
985 } | 425 } |
986 | 426 |
987 DEBUG_MAIN(("main: Going to next d_ptr\n")); | 427 DEBUG_MAIN(("main: Going to next d_ptr\n")); |
988 if (boundary) { | |
989 free(boundary); | |
990 boundary = NULL; | |
991 } | |
992 | 428 |
993 check_parent: | 429 check_parent: |
994 // _pst_freeItem(item); | 430 // _pst_freeItem(item); |
995 while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) { | 431 while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) { |
996 DEBUG_MAIN(("main: Going to Parent\n")); | 432 DEBUG_MAIN(("main: Going to Parent\n")); |
1100 printf("OPTIONS:\n"); | 536 printf("OPTIONS:\n"); |
1101 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); | 537 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n"); |
1102 printf("\t-d\t- Debug to file. This is a binary log. Use readlog to print it\n"); | 538 printf("\t-d\t- Debug to file. This is a binary log. Use readlog to print it\n"); |
1103 printf("\t-h\t- Help. This screen\n"); | 539 printf("\t-h\t- Help. This screen\n"); |
1104 printf("\t-k\t- KMail. Output in kmail format\n"); | 540 printf("\t-k\t- KMail. Output in kmail format\n"); |
541 printf("\t-M\t- MH. Write emails in the MH format\n"); | |
1105 printf("\t-o\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); | 542 printf("\t-o\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); |
1106 printf("\t-q\t- Quiet. Only print error messages\n"); | 543 printf("\t-q\t- Quiet. Only print error messages\n"); |
1107 printf("\t-r\t- Recursive. Output in a recursive format\n"); | 544 printf("\t-r\t- Recursive. Output in a recursive format\n"); |
1108 printf("\t-S\t- Seperate. Write emails in the seperate format\n"); | 545 printf("\t-S\t- Seperate. Write emails in the seperate format\n"); |
1109 printf("\t-V\t- Version. Display program version\n"); | 546 printf("\t-V\t- Version. Display program version\n"); |
1231 | 668 |
1232 do { | 669 do { |
1233 if (y == 0) | 670 if (y == 0) |
1234 sprintf(dir_name, "%s", dir); | 671 sprintf(dir_name, "%s", dir); |
1235 else | 672 else |
1236 sprintf(dir_name, "%s%09i", dir, y); // enough for 9 digits allocated above | 673 sprintf(dir_name, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above |
1237 | 674 |
1238 dir_name = check_filename(dir_name); | 675 dir_name = check_filename(dir_name); |
1239 DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name)); | 676 DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name)); |
1240 if (D_MKDIR(dir_name)) { | 677 if (D_MKDIR(dir_name)) { |
1241 if (errno != EEXIST) { // if there is an error, and it doesn't already exist | 678 if (errno != EEXIST) { // if there is an error, and it doesn't already exist |
1288 } | 725 } |
1289 DEBUG_RET(); | 726 DEBUG_RET(); |
1290 return 0; | 727 return 0; |
1291 } | 728 } |
1292 int mk_seperate_file(struct file_ll *f) { | 729 int mk_seperate_file(struct file_ll *f) { |
730 const int name_offset = 1; | |
1293 DEBUG_ENT("mk_seperate_file"); | 731 DEBUG_ENT("mk_seperate_file"); |
1294 DEBUG_MAIN(("mk_seperate_file: opening next file to save email\n")); | 732 DEBUG_MAIN(("mk_seperate_file: opening next file to save email\n")); |
1295 if (f->email_count > 999999999) { // bigger than nine 9's | 733 if (f->email_count > 999999999) { // bigger than nine 9's |
1296 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); | 734 DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); |
1297 } | 735 } |
1298 sprintf(f->name, "%09i", f->email_count); | 736 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); |
1299 if (f->output != NULL) | 737 if (f->output != NULL) |
1300 fclose(f->output); | 738 fclose(f->output); |
1301 f->output = NULL; | 739 f->output = NULL; |
1302 f->name = check_filename(f->name); | 740 f->name = check_filename(f->name); |
1303 if ((f->output = fopen(f->name, "w")) == NULL) { | 741 if ((f->output = fopen(f->name, "w")) == NULL) { |
1439 return headers; | 877 return headers; |
1440 } | 878 } |
1441 | 879 |
1442 // vim:sw=4 ts=4: | 880 // vim:sw=4 ts=4: |
1443 // vim600: set foldlevel=0 foldmethod=marker: | 881 // vim600: set foldlevel=0 foldmethod=marker: |
882 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst) | |
883 { | |
884 FILE *fp = NULL; | |
885 int x = 0; | |
886 char *temp; | |
887 | |
888 check_filename(f_name); | |
889 if (current_attach->filename2 == NULL) { | |
890 temp = xmalloc(strlen(f_name)+15); | |
891 sprintf(temp, "%s-attach%i", f_name, attach_num); | |
892 } else { | |
893 temp = xmalloc(strlen(f_name)+strlen(current_attach->filename2)+15); | |
894 do { | |
895 if (fp != NULL) fclose(fp); | |
896 if (x == 0) | |
897 sprintf(temp, "%s-%s", f_name, current_attach->filename2); | |
898 else | |
899 sprintf(temp, "%s-%s-%i", f_name, current_attach->filename2, x); | |
900 } while ((fp = fopen(temp, "r"))!=NULL && ++x < 99999999); | |
901 if (x > 99999999) { | |
902 DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); | |
903 } | |
904 } | |
905 DEBUG_MAIN(("write_separate_attachment: Saving attachment to %s\n", temp)); | |
906 if ((fp = fopen(temp, "w")) == NULL) { | |
907 WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp)); | |
908 } else { | |
909 if (current_attach->data != NULL) | |
910 fwrite(current_attach->data, 1, current_attach->size, fp); | |
911 else { | |
912 pst_attach_to_file(pst, current_attach, fp); | |
913 } | |
914 fclose(fp); | |
915 } | |
916 } | |
917 | |
918 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst) | |
919 { | |
920 char *enc; // base64 encoded attachment | |
921 DEBUG_MAIN(("write_inline_attachment: Attachment Size is %i\n", item->current_attach->size)); | |
922 DEBUG_MAIN(("write_inline_attachment: Attachment Pointer is %p\n", item->current_attach->data)); | |
923 if (current_attach->data != NULL) { | |
924 if ((enc = base64_encode (current_attach->data, current_attach->size)) == NULL) { | |
925 DEBUG_MAIN(("write_inline_attachment: ERROR base64_encode returned NULL. Must have failed\n")); | |
926 current_attach = current_attach->next; | |
927 return; | |
928 } | |
929 } | |
930 if (boundary) { | |
931 fprintf(f_output, "\n--%s\n", boundary); | |
932 if (current_attach->mimetype == NULL) { | |
933 fprintf(f_output, "Content-type: %s\n", MIME_TYPE_DEFAULT); | |
934 } else { | |
935 fprintf(f_output, "Content-type: %s\n", current_attach->mimetype); | |
936 } | |
937 fprintf(f_output, "Content-transfer-encoding: base64\n"); | |
938 if (current_attach->filename2 == NULL) { | |
939 fprintf(f_output, "Content-Disposition: inline\n\n"); | |
940 } else { | |
941 fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", | |
942 current_attach->filename2); | |
943 } | |
944 } | |
945 if (current_attach->data != NULL) { | |
946 fwrite(enc, 1, strlen(enc), f_output); | |
947 DEBUG_MAIN(("Attachment Size after encoding is %i\n", strlen(enc))); | |
948 } else { | |
949 pst_attach_to_file_base64(pst, current_attach, f_output); | |
950 } | |
951 fprintf(f_output, "\n\n"); | |
952 } | |
953 | |
954 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst) | |
955 { | |
956 char *boundary = NULL; // the boundary marker between multipart sections | |
957 char *temp = NULL; | |
958 int attach_num, base64_body = 0; | |
959 time_t em_time; | |
960 char *c_time; | |
961 | |
962 // convert the sent date if it exists, or set it to a fixed date | |
963 if (item->email->sent_date != NULL) { | |
964 em_time = fileTimeToUnixTime(item->email->sent_date, 0); | |
965 c_time = ctime(&em_time); | |
966 if (c_time != NULL) | |
967 c_time[strlen(c_time)-1] = '\0'; //remove end \n | |
968 else | |
969 c_time = "Fri Dec 28 12:06:21 2001"; | |
970 } else | |
971 c_time= "Fri Dec 28 12:06:21 2001"; | |
972 | |
973 // we will always look at the header to discover some stuff | |
974 if (item->email->header != NULL ) { | |
975 char *b1, *b2; | |
976 // see if there is a boundary variable there | |
977 // this search MUST be made case insensitive (DONE). | |
978 // Also, some check to find out if we | |
979 // are looking at the boundary associated with content-type, and that the content | |
980 // type really is "multipart" | |
981 | |
982 removeCR(item->email->header); | |
983 | |
984 if ((b2 = my_stristr(item->email->header, "boundary=")) != NULL) { | |
985 b2 += strlen("boundary="); // move boundary to first char of marker | |
986 | |
987 if (*b2 == '"') { | |
988 b2++; | |
989 b1 = strchr(b2, '"'); // find terminating quote | |
990 } else { | |
991 b1 = b2; | |
992 while (isgraph(*b1)) // find first char that isn't part of boundary | |
993 b1++; | |
994 } | |
995 | |
996 boundary = malloc ((b1-b2)+1); //malloc that length | |
997 memset (boundary, 0, (b1-b2)+1); // blank it | |
998 strncpy(boundary, b2, b1-b2); // copy boundary to another variable | |
999 b1 = b2 = boundary; | |
1000 while (*b2 != '\0') { // remove any CRs and Tabs | |
1001 if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { | |
1002 *b1 = *b2; | |
1003 b1++; | |
1004 } | |
1005 b2++; | |
1006 } | |
1007 *b1 = '\0'; | |
1008 | |
1009 DEBUG_MAIN(("write_normal_email: Found boundary of - %s\n", boundary)); | |
1010 } else { | |
1011 DEBUG_MAIN(("write_normal_email: boundary not found in header\n")); | |
1012 } | |
1013 | |
1014 // also possible to set 7bit encoding detection here. | |
1015 if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:")) != NULL) { | |
1016 if ((b2 = strchr(b2, ':')) != NULL) { | |
1017 b2++; // skip to the : at the end of the string | |
1018 | |
1019 while (*b2 == ' ' || *b2 == '\t') | |
1020 b2++; | |
1021 if (pst_strincmp(b2, "base64", 6)==0) { | |
1022 DEBUG_MAIN(("body is base64 encoded\n")); | |
1023 base64_body = 1; | |
1024 } | |
1025 } else { | |
1026 DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); | |
1027 } | |
1028 } | |
1029 | |
1030 } | |
1031 | |
1032 DEBUG_MAIN(("write_normal_email: About to print Header\n")); | |
1033 | |
1034 if (item != NULL && item->email != NULL && item->email->subject != NULL && | |
1035 item->email->subject->subj != NULL) { | |
1036 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); | |
1037 } | |
1038 | |
1039 if (item->email->header != NULL) { | |
1040 // some of the headers we get from the file are not properly defined. | |
1041 // they can contain some email stuff too. We will cut off the header | |
1042 // when we see a \n\n or \r\n\r\n | |
1043 temp = strstr(item->email->header, "\n\n"); | |
1044 | |
1045 if (temp != NULL) { | |
1046 DEBUG_MAIN(("write_normal_email: Found body text in header\n")); | |
1047 temp += 2; // get past the \n\n | |
1048 *temp = '\0'; | |
1049 } | |
1050 | |
1051 if (mode != MODE_SEPERATE) { | |
1052 char *soh = NULL; // real start of headers. | |
1053 // don't put rubbish in if we are doing seperate | |
1054 fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); | |
1055 soh = skip_header_prologue(item->email->header); | |
1056 fprintf(f_output, "%s\n\n", soh); | |
1057 } else { | |
1058 fprintf(f_output, "%s\n", item->email->header); | |
1059 } | |
1060 } else { | |
1061 //make up our own header! | |
1062 if (mode != MODE_SEPERATE) { | |
1063 // don't want this first line for this mode | |
1064 if (item->email->outlook_sender_name != NULL) { | |
1065 temp = item->email->outlook_sender_name; | |
1066 } else { | |
1067 temp = "(readpst_null)"; | |
1068 } | |
1069 fprintf(f_output, "From \"%s\" %s\n", temp, c_time); | |
1070 } | |
1071 if ((temp = item->email->outlook_sender) == NULL) | |
1072 temp = ""; | |
1073 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); | |
1074 if (item->email->subject != NULL) { | |
1075 fprintf(f_output, "Subject: %s\n", item->email->subject->subj); | |
1076 } else { | |
1077 fprintf(f_output, "Subject: \n"); | |
1078 } | |
1079 fprintf(f_output, "To: %s\n", item->email->sentto_address); | |
1080 if (item->email->cc_address != NULL) { | |
1081 fprintf(f_output, "Cc: %s\n", item->email->cc_address); | |
1082 } | |
1083 if (item->email->sent_date != NULL) { | |
1084 c_time = (char*) xmalloc(C_TIME_SIZE); | |
1085 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); | |
1086 fprintf(f_output, "Date: %s\n", c_time); | |
1087 free(c_time); | |
1088 } | |
1089 | |
1090 fprintf(f_output, "MIME-Version: 1.0\n"); | |
1091 } | |
1092 | |
1093 if (boundary == NULL && (item->attach ||(item->email->body && item->email->htmlbody) | |
1094 || item->email->rtf_compressed || item->email->encrypted_body | |
1095 || item->email->encrypted_htmlbody)) { | |
1096 // we need to create a boundary here. | |
1097 DEBUG_EMAIL(("write_normal_email: must create own boundary. oh dear.\n")); | |
1098 boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary | |
1099 boundary[0] = '\0'; | |
1100 sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); | |
1101 DEBUG_EMAIL(("write_normal_email: created boundary is %s\n", boundary)); | |
1102 | |
1103 /* If boundary != NULL, then it has already been printed with existing | |
1104 * headers. Otherwise we generate it here and print it. | |
1105 */ | |
1106 if (item->attach != NULL) { | |
1107 // write the boundary stuff if we have attachments | |
1108 fprintf(f_output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", | |
1109 boundary); | |
1110 } else if (boundary != NULL) { | |
1111 // else if we have multipart/alternative then tell it so | |
1112 fprintf(f_output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", | |
1113 boundary); | |
1114 } else if (item->email->htmlbody) { | |
1115 fprintf(f_output, "Content-type: text/html\n"); | |
1116 } | |
1117 } | |
1118 | |
1119 fprintf(f_output, "\n"); | |
1120 | |
1121 DEBUG_MAIN(("write_normal_email: About to print Body\n")); | |
1122 | |
1123 if (item->email->body != NULL) { | |
1124 if (boundary) { | |
1125 fprintf(f_output, "\n--%s\n", boundary); | |
1126 fprintf(f_output, "Content-type: text/plain\n\n"); | |
1127 if (base64_body) | |
1128 fprintf(f_output, "Content-Transfer-Encoding: base64\n"); | |
1129 } | |
1130 removeCR(item->email->body); | |
1131 if (base64_body) | |
1132 write_email_body(f_output, base64_encode(item->email->body, | |
1133 strlen(item->email->body))); | |
1134 else | |
1135 write_email_body(f_output, item->email->body); | |
1136 } | |
1137 | |
1138 if (item->email->htmlbody != NULL) { | |
1139 if (boundary) { | |
1140 fprintf(f_output, "\n--%s\n", boundary); | |
1141 fprintf(f_output, "Content-type: text/html\n\n"); | |
1142 if (base64_body) | |
1143 fprintf(f_output, "Content-Transfer-Encoding: base64\n"); | |
1144 } | |
1145 removeCR(item->email->htmlbody); | |
1146 if (base64_body) | |
1147 write_email_body(f_output, base64_encode(item->email->htmlbody, | |
1148 strlen(item->email->htmlbody))); | |
1149 else | |
1150 write_email_body(f_output, item->email->htmlbody); | |
1151 } | |
1152 | |
1153 if (item->email->rtf_compressed != NULL) { | |
1154 DEBUG_MAIN(("Adding RTF body as attachment\n")); | |
1155 item->current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); | |
1156 memset(item->current_attach, 0, sizeof(pst_item_attach)); | |
1157 item->current_attach->next = item->attach; | |
1158 item->attach = item->current_attach; | |
1159 item->current_attach->data = lzfu_decompress(item->email->rtf_compressed); | |
1160 item->current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); | |
1161 strcpy(item->current_attach->filename2, RTF_ATTACH_NAME); | |
1162 item->current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); | |
1163 strcpy(item->current_attach->mimetype, RTF_ATTACH_TYPE); | |
1164 memcpy(&(item->current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); | |
1165 LE32_CPU(item->current_attach->size); | |
1166 // item->email->rtf_compressed = ; | |
1167 // attach_num++; | |
1168 } | |
1169 if (item->email->encrypted_body || item->email->encrypted_htmlbody) { | |
1170 // if either the body or htmlbody is encrypted, add them as attachments | |
1171 if (item->email->encrypted_body) { | |
1172 DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); | |
1173 item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); | |
1174 memset(item->current_attach, 0, sizeof(pst_item_attach)); | |
1175 item->current_attach->next = item->attach; | |
1176 item->attach = item->current_attach; | |
1177 | |
1178 item->current_attach->data = item->email->encrypted_body; | |
1179 item->current_attach->size = item->email->encrypted_body_size; | |
1180 item->email->encrypted_body = NULL; | |
1181 } | |
1182 if (item->email->encrypted_htmlbody) { | |
1183 DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); | |
1184 item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); | |
1185 memset(item->current_attach, 0, sizeof(pst_item_attach)); | |
1186 item->current_attach->next = item->attach; | |
1187 item->attach = item->current_attach; | |
1188 | |
1189 item->current_attach->data = item->email->encrypted_htmlbody; | |
1190 item->current_attach->size = item->email->encrypted_htmlbody_size; | |
1191 item->email->encrypted_htmlbody = NULL; | |
1192 } | |
1193 write_email_body(f_output, "The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n"); | |
1194 } | |
1195 // attachments | |
1196 attach_num = 0; | |
1197 for(item->current_attach = item->attach; | |
1198 item->current_attach; | |
1199 item->current_attach = item->current_attach->next) { | |
1200 DEBUG_MAIN(("write_normal_email: Attempting Attachment encoding\n")); | |
1201 if (item->current_attach->data == NULL) { | |
1202 DEBUG_MAIN(("write_normal_email: Data of attachment is NULL!. Size is supposed to be %i\n", item->current_attach->size)); | |
1203 } | |
1204 attach_num++; | |
1205 if (mode == MODE_SEPERATE && !mode_MH) | |
1206 write_separate_attachment(f_name, item->current_attach, attach_num, pst); | |
1207 else | |
1208 write_inline_attachment(f_output, item->current_attach, boundary, pst); | |
1209 } | |
1210 if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */ | |
1211 DEBUG_MAIN(("write_normal_email: Writing buffer between emails\n")); | |
1212 if (boundary) | |
1213 fprintf(f_output, "\n--%s--\n", boundary); | |
1214 fprintf(f_output, "\n\n"); | |
1215 } | |
1216 if (boundary) | |
1217 free (boundary); | |
1218 } | |
1219 | |
1220 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]) | |
1221 { | |
1222 // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile | |
1223 fprintf(f_output, "BEGIN:VCARD\n"); | |
1224 fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->fullname)); | |
1225 fprintf(f_output, "N:%s;%s;%s;%s;%s\n", | |
1226 rfc2426_escape((contact->surname==NULL?"":contact->surname)), | |
1227 rfc2426_escape((contact->first_name==NULL?"":contact->first_name)), | |
1228 rfc2426_escape((contact->middle_name==NULL?"":contact->middle_name)), | |
1229 rfc2426_escape((contact->display_name_prefix==NULL?"":contact->display_name_prefix)), | |
1230 rfc2426_escape((contact->suffix==NULL?"":contact->suffix))); | |
1231 if (contact->nickname != NULL) | |
1232 fprintf(f_output, "NICKNAME:%s\n", rfc2426_escape(contact->nickname)); | |
1233 if (contact->address1 != NULL) | |
1234 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address1)); | |
1235 if (contact->address2 != NULL) | |
1236 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address2)); | |
1237 if (contact->address3 != NULL) | |
1238 fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address3)); | |
1239 if (contact->birthday != NULL) | |
1240 fprintf(f_output, "BDAY:%s\n", rfc2425_datetime_format(contact->birthday)); | |
1241 if (contact->home_address != NULL) { | |
1242 fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", | |
1243 rfc2426_escape((contact->home_po_box!=NULL?contact->home_po_box:"")), | |
1244 "", // extended Address | |
1245 rfc2426_escape((contact->home_street!=NULL?contact->home_street:"")), | |
1246 rfc2426_escape((contact->home_city!=NULL?contact->home_city:"")), | |
1247 rfc2426_escape((contact->home_state!=NULL?contact->home_state:"")), | |
1248 rfc2426_escape((contact->home_postal_code!=NULL?contact->home_postal_code:"")), | |
1249 rfc2426_escape((contact->home_country!=NULL?contact->home_country:""))); | |
1250 fprintf(f_output, "LABEL;TYPE=home:%s\n", rfc2426_escape(contact->home_address)); | |
1251 } | |
1252 if (contact->business_address != NULL) { | |
1253 fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", | |
1254 rfc2426_escape((contact->business_po_box!=NULL?contact->business_po_box:"")), | |
1255 "", // extended Address | |
1256 rfc2426_escape((contact->business_street!=NULL?contact->business_street:"")), | |
1257 rfc2426_escape((contact->business_city!=NULL?contact->business_city:"")), | |
1258 rfc2426_escape((contact->business_state!=NULL?contact->business_state:"")), | |
1259 rfc2426_escape((contact->business_postal_code!=NULL?contact->business_postal_code:"")), | |
1260 rfc2426_escape((contact->business_country!=NULL?contact->business_country:""))); | |
1261 fprintf(f_output, "LABEL;TYPE=work:%s\n", rfc2426_escape(contact->business_address)); | |
1262 } | |
1263 if (contact->other_address != NULL) { | |
1264 fprintf(f_output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", | |
1265 rfc2426_escape((contact->other_po_box != NULL ? | |
1266 contact->business_po_box:"")), | |
1267 "", // extended Address | |
1268 rfc2426_escape((contact->other_street != NULL ? | |
1269 contact->other_street:"")), | |
1270 rfc2426_escape((contact->other_city != NULL ? | |
1271 contact->other_city:"")), | |
1272 rfc2426_escape((contact->other_state != NULL ? | |
1273 contact->other_state:"")), | |
1274 rfc2426_escape((contact->other_postal_code != NULL ? | |
1275 contact->other_postal_code:"")), | |
1276 rfc2426_escape((contact->other_country != NULL ? | |
1277 contact->other_country:""))); | |
1278 fprintf(f_output, "ADR;TYPE=postal:%s\n", | |
1279 rfc2426_escape(contact->other_address)); | |
1280 } | |
1281 if (contact->business_fax != NULL) | |
1282 fprintf(f_output, "TEL;TYPE=work,fax:%s\n", | |
1283 rfc2426_escape(contact->business_fax)); | |
1284 if (contact->business_phone != NULL) | |
1285 fprintf(f_output, "TEL;TYPE=work,voice:%s\n", | |
1286 rfc2426_escape(contact->business_phone)); | |
1287 if (contact->business_phone2 != NULL) | |
1288 fprintf(f_output, "TEL;TYPE=work,voice:%s\n", | |
1289 rfc2426_escape(contact->business_phone2)); | |
1290 if (contact->car_phone != NULL) | |
1291 fprintf(f_output, "TEL;TYPE=car,voice:%s\n", | |
1292 rfc2426_escape(contact->car_phone)); | |
1293 if (contact->home_fax != NULL) | |
1294 fprintf(f_output, "TEL;TYPE=home,fax:%s\n", | |
1295 rfc2426_escape(contact->home_fax)); | |
1296 if (contact->home_phone != NULL) | |
1297 fprintf(f_output, "TEL;TYPE=home,voice:%s\n", | |
1298 rfc2426_escape(contact->home_phone)); | |
1299 if (contact->home_phone2 != NULL) | |
1300 fprintf(f_output, "TEL;TYPE=home,voice:%s\n", | |
1301 rfc2426_escape(contact->home_phone2)); | |
1302 if (contact->isdn_phone != NULL) | |
1303 fprintf(f_output, "TEL;TYPE=isdn:%s\n", | |
1304 rfc2426_escape(contact->isdn_phone)); | |
1305 if (contact->mobile_phone != NULL) | |
1306 fprintf(f_output, "TEL;TYPE=cell,voice:%s\n", | |
1307 rfc2426_escape(contact->mobile_phone)); | |
1308 if (contact->other_phone != NULL) | |
1309 fprintf(f_output, "TEL;TYPE=msg:%s\n", | |
1310 rfc2426_escape(contact->other_phone)); | |
1311 if (contact->pager_phone != NULL) | |
1312 fprintf(f_output, "TEL;TYPE=pager:%s\n", | |
1313 rfc2426_escape(contact->pager_phone)); | |
1314 if (contact->primary_fax != NULL) | |
1315 fprintf(f_output, "TEL;TYPE=fax,pref:%s\n", | |
1316 rfc2426_escape(contact->primary_fax)); | |
1317 if (contact->primary_phone != NULL) | |
1318 fprintf(f_output, "TEL;TYPE=phone,pref:%s\n", | |
1319 rfc2426_escape(contact->primary_phone)); | |
1320 if (contact->radio_phone != NULL) | |
1321 fprintf(f_output, "TEL;TYPE=pcs:%s\n", | |
1322 rfc2426_escape(contact->radio_phone)); | |
1323 if (contact->telex != NULL) | |
1324 fprintf(f_output, "TEL;TYPE=bbs:%s\n", | |
1325 rfc2426_escape(contact->telex)); | |
1326 if (contact->job_title != NULL) | |
1327 fprintf(f_output, "TITLE:%s\n", | |
1328 rfc2426_escape(contact->job_title)); | |
1329 if (contact->profession != NULL) | |
1330 fprintf(f_output, "ROLE:%s\n", | |
1331 rfc2426_escape(contact->profession)); | |
1332 if (contact->assistant_name != NULL | |
1333 || contact->assistant_phone != NULL) { | |
1334 fprintf(f_output, "AGENT:BEGIN:VCARD\\n"); | |
1335 if (contact->assistant_name != NULL) | |
1336 fprintf(f_output, "FN:%s\\n", | |
1337 rfc2426_escape(contact->assistant_name)); | |
1338 if (contact->assistant_phone != NULL) | |
1339 fprintf(f_output, "TEL:%s\\n", | |
1340 rfc2426_escape(contact->assistant_phone)); | |
1341 } | |
1342 if (contact->company_name != NULL) | |
1343 fprintf(f_output, "ORG:%s\n", | |
1344 rfc2426_escape(contact->company_name)); | |
1345 if (comment != NULL) | |
1346 fprintf(f_output, "NOTE:%s\n", rfc2426_escape(comment)); | |
1347 | |
1348 fprintf(f_output, "VERSION: 3.0\n"); | |
1349 fprintf(f_output, "END:VCARD\n\n"); | |
1350 } | |
1351 | |
1352 void write_appointment(FILE* f_output, pst_item_appointment* appointment, | |
1353 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date) | |
1354 { | |
1355 fprintf(f_output, "BEGIN:VEVENT\n"); | |
1356 if (create_date != NULL) | |
1357 fprintf(f_output, "CREATED:%s\n", | |
1358 rfc2445_datetime_format(create_date)); | |
1359 if (modify_date != NULL) | |
1360 fprintf(f_output, "LAST-MOD:%s\n", | |
1361 rfc2445_datetime_format(modify_date)); | |
1362 if (email != NULL && email->subject != NULL) | |
1363 fprintf(f_output, "SUMMARY:%s\n", | |
1364 rfc2426_escape(email->subject->subj)); | |
1365 if (email != NULL && email->body != NULL) | |
1366 fprintf(f_output, "DESCRIPTION:%s\n", | |
1367 rfc2426_escape(email->body)); | |
1368 if (appointment != NULL && appointment->start != NULL) | |
1369 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", | |
1370 rfc2445_datetime_format(appointment->start)); | |
1371 if (appointment != NULL && appointment->end != NULL) | |
1372 fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n", | |
1373 rfc2445_datetime_format(appointment->end)); | |
1374 if (appointment != NULL && appointment->location != NULL) | |
1375 fprintf(f_output, "LOCATION:%s\n", | |
1376 rfc2426_escape(appointment->location)); | |
1377 if (appointment != NULL) { | |
1378 switch (appointment->showas) { | |
1379 case PST_FREEBUSY_TENTATIVE: | |
1380 fprintf(f_output, "STATUS:TENTATIVE\n"); | |
1381 break; | |
1382 case PST_FREEBUSY_FREE: | |
1383 // mark as transparent and as confirmed | |
1384 fprintf(f_output, "TRANSP:TRANSPARENT\n"); | |
1385 case PST_FREEBUSY_BUSY: | |
1386 case PST_FREEBUSY_OUT_OF_OFFICE: | |
1387 fprintf(f_output, "STATUS:CONFIRMED\n"); | |
1388 break; | |
1389 } | |
1390 switch (appointment->label) { | |
1391 case PST_APP_LABEL_NONE: | |
1392 fprintf(f_output, "CATEGORIES:NONE\n"); | |
1393 break; | |
1394 case PST_APP_LABEL_IMPORTANT: | |
1395 fprintf(f_output, "CATEGORIES:IMPORTANT\n"); | |
1396 break; | |
1397 case PST_APP_LABEL_BUSINESS: | |
1398 fprintf(f_output, "CATEGORIES:BUSINESS\n"); | |
1399 break; | |
1400 case PST_APP_LABEL_PERSONAL: | |
1401 fprintf(f_output, "CATEGORIES:PERSONAL\n"); | |
1402 break; | |
1403 case PST_APP_LABEL_VACATION: | |
1404 fprintf(f_output, "CATEGORIES:VACATION\n"); | |
1405 break; | |
1406 case PST_APP_LABEL_MUST_ATTEND: | |
1407 fprintf(f_output, "CATEGORIES:MUST-ATTEND\n"); | |
1408 break; | |
1409 case PST_APP_LABEL_TRAVEL_REQ: | |
1410 fprintf(f_output, "CATEGORIES:TRAVEL-REQUIRED\n"); | |
1411 break; | |
1412 case PST_APP_LABEL_NEEDS_PREP: | |
1413 fprintf(f_output, "CATEGORIES:NEEDS-PREPARATION\n"); | |
1414 break; | |
1415 case PST_APP_LABEL_BIRTHDAY: | |
1416 fprintf(f_output, "CATEGORIES:BIRTHDAY\n"); | |
1417 break; | |
1418 case PST_APP_LABEL_ANNIVERSARY: | |
1419 fprintf(f_output, "CATEGORIES:ANNIVERSARY\n"); | |
1420 break; | |
1421 case PST_APP_LABEL_PHONE_CALL: | |
1422 fprintf(f_output, "CATEGORIES:PHONE-CALL\n"); | |
1423 break; | |
1424 } | |
1425 } | |
1426 fprintf(f_output, "END:VEVENT\n\n"); | |
1427 } | |
1428 | |
1429 void create_enter_dir(struct file_ll* f, char file_as[], int mode, int overwrite) | |
1430 { | |
1431 if (mode == MODE_KMAIL) | |
1432 f->name = mk_kmail_dir(file_as); //create directory and form filename | |
1433 else if (mode == MODE_RECURSE) | |
1434 f->name = mk_recurse_dir(file_as); | |
1435 else if (mode == MODE_SEPERATE) { | |
1436 // do similar stuff to recurse here. | |
1437 mk_seperate_dir(file_as, overwrite); | |
1438 f->name = (char*) xmalloc(10); | |
1439 memset(f->name, 0, 10); | |
1440 // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count); | |
1441 } else { | |
1442 f->name = (char*) xmalloc(strlen(file_as)+strlen(OUTPUT_TEMPLATE+1)); | |
1443 sprintf(f->name, OUTPUT_TEMPLATE, file_as); | |
1444 } | |
1445 | |
1446 f->dname = (char*) xmalloc(strlen(file_as)+1); | |
1447 strcpy(f->dname, file_as); | |
1448 | |
1449 if (overwrite != 1) { | |
1450 int x = 0; | |
1451 char *temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits | |
1452 | |
1453 sprintf(temp, "%s", f->name); | |
1454 temp = check_filename(temp); | |
1455 while ((f->output = fopen(temp, "r")) != NULL) { | |
1456 DEBUG_MAIN(("create_enter_dir: need to increase filename cause one already exists with that name\n")); | |
1457 DEBUG_MAIN(("create_enter_dir: - increasing it to %s%d\n", f->name, x)); | |
1458 x++; | |
1459 sprintf(temp, "%s%08d", f->name, x); | |
1460 DEBUG_MAIN(("create_enter_dir: - trying \"%s\"\n", f->name)); | |
1461 if (x == 99999999) { | |
1462 DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); | |
1463 } | |
1464 fclose(f->output); | |
1465 } | |
1466 if (x > 0) { //then the f->name should change | |
1467 free (f->name); | |
1468 f->name = temp; | |
1469 } else { | |
1470 free(temp); | |
1471 } | |
1472 } | |
1473 | |
1474 DEBUG_MAIN(("create_enter_dir: f->name = %s\nitem->folder_name = %s\n", f->name, file_as)); | |
1475 if (mode != MODE_SEPERATE) { | |
1476 f->name = check_filename(f->name); | |
1477 if ((f->output = fopen(f->name, "w")) == NULL) { | |
1478 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name)); | |
1479 } | |
1480 } | |
1481 } | |
1482 |