00001
00002
00003
00004
00005
00006
00007
00008 #include "define.h"
00009 #include "lzfu.h"
00010
00011 #define OUTPUT_TEMPLATE "%s"
00012 #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory"
00013 #define KMAIL_INDEX ".%s.index"
00014 #define SEP_MAIL_FILE_TEMPLATE "%i"
00015
00016
00017 #define C_TIME_SIZE 500
00018
00019 struct file_ll {
00020 char *name;
00021 char *dname;
00022 FILE * output;
00023 int32_t stored_count;
00024 int32_t email_count;
00025 int32_t skip_count;
00026 int32_t type;
00027 };
00028
00029 void process(pst_item *outeritem, pst_desc_ll *d_ptr);
00030 void write_email_body(FILE *f, char *body);
00031 void removeCR(char *c);
00032 void usage();
00033 void version();
00034 char* mk_kmail_dir(char*);
00035 int close_kmail_dir();
00036 char* mk_recurse_dir(char*);
00037 int close_recurse_dir();
00038 char* mk_separate_dir(char *dir);
00039 int close_separate_dir();
00040 int mk_separate_file(struct file_ll *f);
00041 char* my_stristr(char *haystack, char *needle);
00042 void check_filename(char *fname);
00043 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst);
00044 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char *boundary, pst_file* pst);
00045 void header_has_field(char *header, char *field, int *flag);
00046 char* header_get_field(char *header, char *field);
00047 void header_strip_field(char *header, char *field);
00048 int test_base64(char *body);
00049 void find_html_charset(char *html, char *charset, size_t charsetlen);
00050 void write_body_part(FILE* f_output, char *body, char *mime, char *charset, char *boundary);
00051 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf);
00052 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]);
00053 void write_appointment(FILE* f_output, pst_item_appointment* appointment,
00054 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date);
00055 void create_enter_dir(struct file_ll* f, pst_item *item);
00056 void close_enter_dir(struct file_ll *f);
00057
00058 const char* prog_name;
00059 char* output_dir = ".";
00060 char* kmail_chdir = NULL;
00061
00062
00063
00064 #define MODE_NORMAL 0
00065
00066
00067
00068 #define MODE_KMAIL 1
00069
00070
00071
00072 #define MODE_RECURSE 2
00073
00074
00075
00076
00077 #define MODE_SEPARATE 3
00078
00079
00080 #define MODE_DECSPEW 4
00081
00082
00083
00084 #define OUTPUT_NORMAL 0
00085
00086
00087 #define OUTPUT_QUIET 1
00088
00089
00090 #define MIME_TYPE_DEFAULT "application/octet-stream"
00091
00092
00093 #define CMODE_VCARD 0
00094 #define CMODE_LIST 1
00095
00096
00097 #define DMODE_EXCLUDE 0
00098 #define DMODE_INCLUDE 1
00099
00100
00101
00102 #define RTF_ATTACH_NAME "rtf-body.rtf"
00103
00104 #define RTF_ATTACH_TYPE "application/rtf"
00105
00106
00107 int mode = MODE_NORMAL;
00108 int mode_MH = 0;
00109 int output_mode = OUTPUT_NORMAL;
00110 int contact_mode = CMODE_VCARD;
00111 int deleted_mode = DMODE_EXCLUDE;
00112 int overwrite = 0;
00113 int save_rtf_body = 1;
00114 pst_file pstfile;
00115 regex_t meta_charset_pattern;
00116
00117
00118 void process(pst_item *outeritem, pst_desc_ll *d_ptr)
00119 {
00120 struct file_ll ff;
00121 pst_item *item = NULL;
00122
00123 DEBUG_ENT("process");
00124 memset(&ff, 0, sizeof(ff));
00125 create_enter_dir(&ff, outeritem);
00126
00127 while (d_ptr) {
00128 DEBUG_MAIN(("main: New item record\n"));
00129 if (!d_ptr->desc) {
00130 DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n"));
00131 ff.skip_count++;
00132 }
00133 else {
00134 DEBUG_MAIN(("main: Desc Email ID %#x [d_ptr->id = %#x]\n", d_ptr->desc->id, d_ptr->id));
00135
00136 item = pst_parse_item(&pstfile, d_ptr);
00137 DEBUG_MAIN(("main: About to process item\n"));
00138 if (item && item->email && item->email->subject && item->email->subject->subj) {
00139 DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject));
00140 DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj));
00141 }
00142 if (item) {
00143 if (item->folder && d_ptr->child && (deleted_mode == DMODE_INCLUDE || strcasecmp(item->file_as, "Deleted Items"))) {
00144
00145 if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as);
00146 process(item, d_ptr->child);
00147
00148 } else if (item->contact && (item->type == PST_TYPE_CONTACT)) {
00149
00150
00151
00152 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
00153 ff.email_count++;
00154 DEBUG_MAIN(("main: Processing Contact\n"));
00155 if (ff.type != PST_TYPE_CONTACT) {
00156 DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. Processing anyway\n"));
00157 }
00158 if (contact_mode == CMODE_VCARD)
00159 write_vcard(ff.output, item->contact, item->comment);
00160 else
00161 fprintf(ff.output, "%s <%s>\n", item->contact->fullname, item->contact->address1);
00162
00163 } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT || item->type == PST_TYPE_OTHER)) {
00164 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
00165 ff.email_count++;
00166 DEBUG_MAIN(("main: Processing Email\n"));
00167 if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT) && (ff.type != PST_TYPE_OTHER)) {
00168 DEBUG_MAIN(("main: I have an email, but the folder isn't an email folder. Processing anyway\n"));
00169 }
00170 write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body);
00171
00172 } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) {
00173
00174 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
00175 ff.email_count++;
00176 DEBUG_MAIN(("main: Processing Journal Entry\n"));
00177 if (ff.type != PST_TYPE_JOURNAL) {
00178 DEBUG_MAIN(("main: I have a journal entry, but the folder isn't a journal folder. Processing anyway\n"));
00179 }
00180 fprintf(ff.output, "BEGIN:VJOURNAL\n");
00181 if (item->email && item->email->subject && item->email->subject->subj)
00182 fprintf(ff.output, "SUMMARY:%s\n", pst_rfc2426_escape(item->email->subject->subj));
00183 if (item->email && item->email->body)
00184 fprintf(ff.output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->email->body));
00185 if (item->journal->start)
00186 fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start));
00187 fprintf(ff.output, "END:VJOURNAL\n\n");
00188
00189 } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) {
00190
00191 if (mode == MODE_SEPARATE) mk_separate_file(&ff);
00192 ff.email_count++;
00193 DEBUG_MAIN(("main: Processing Appointment Entry\n"));
00194 if (ff.type != PST_TYPE_APPOINTMENT) {
00195 DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n"));
00196 }
00197 write_appointment(ff.output, item->appointment, item->email, item->create_date, item->modify_date);
00198
00199 } else if (item->message_store) {
00200
00201 DEBUG_MAIN(("item with message store content, type %i %s folder type %i, skipping it\n", item->type, item->ascii_type, ff.type));
00202
00203 } else {
00204
00205
00206 DEBUG_MAIN(("main: Unknown item type %i (%s) name (%s)\n",
00207 item->type, item->ascii_type, item->file_as));
00208 }
00209 pst_freeItem(item);
00210 } else {
00211 ff.skip_count++;
00212 DEBUG_MAIN(("main: A NULL item was seen\n"));
00213 }
00214 d_ptr = d_ptr->next;
00215 }
00216 }
00217 close_enter_dir(&ff);
00218 DEBUG_RET();
00219 }
00220
00221
00222
00223 int main(int argc, char* const* argv) {
00224 pst_item *item = NULL;
00225 pst_desc_ll *d_ptr;
00226 char * fname = NULL;
00227 char *d_log = NULL;
00228 int c,x;
00229 char *temp = NULL;
00230 prog_name = argv[0];
00231
00232 time_t now = time(NULL);
00233 srand((unsigned)now);
00234
00235 if (regcomp(&meta_charset_pattern, "<meta[^>]*content=\"[^>]*charset=([^>\";]*)[\";]", REG_ICASE | REG_EXTENDED)) {
00236 printf("cannot compile regex pattern to find content charset in html bodies\n");
00237 exit(3);
00238 }
00239
00240
00241 while ((c = getopt(argc, argv, "bCc:Dd:hko:qrSMVw"))!= -1) {
00242 switch (c) {
00243 case 'b':
00244 save_rtf_body = 0;
00245 break;
00246 case 'C':
00247 mode = MODE_DECSPEW;
00248 break;
00249 case 'c':
00250 if (optarg && optarg[0]=='v')
00251 contact_mode=CMODE_VCARD;
00252 else if (optarg && optarg[0]=='l')
00253 contact_mode=CMODE_LIST;
00254 else {
00255 usage();
00256 exit(0);
00257 }
00258 break;
00259 case 'D':
00260 deleted_mode = DMODE_INCLUDE;
00261 break;
00262 case 'd':
00263 d_log = optarg;
00264 break;
00265 case 'h':
00266 usage();
00267 exit(0);
00268 break;
00269 case 'V':
00270 version();
00271 exit(0);
00272 break;
00273 case 'k':
00274 mode = MODE_KMAIL;
00275 break;
00276 case 'M':
00277 mode = MODE_SEPARATE;
00278 mode_MH = 1;
00279 break;
00280 case 'o':
00281 output_dir = optarg;
00282 break;
00283 case 'q':
00284 output_mode = OUTPUT_QUIET;
00285 break;
00286 case 'r':
00287 mode = MODE_RECURSE;
00288 break;
00289 case 'S':
00290 mode = MODE_SEPARATE;
00291 break;
00292 case 'w':
00293 overwrite = 1;
00294 break;
00295 default:
00296 usage();
00297 exit(1);
00298 break;
00299 }
00300 }
00301
00302 if (argc > optind) {
00303 fname = argv[optind];
00304 } else {
00305 usage();
00306 exit(2);
00307 }
00308
00309 #ifdef DEBUG_ALL
00310
00311 if (!d_log) d_log = "readpst.log";
00312 #endif // defined DEBUG_ALL
00313 DEBUG_INIT(d_log);
00314 DEBUG_REGISTER_CLOSE();
00315 DEBUG_ENT("main");
00316
00317 if (mode == MODE_DECSPEW) {
00318 FILE *fp;
00319 char buf[1024];
00320 size_t l = 0;
00321 if (NULL == (fp = fopen(fname, "rb"))) {
00322 fprintf(stderr, "Couldn't open file %s\n", fname );
00323 DEBUG_RET();
00324 return 1;
00325 }
00326
00327 while (0 != (l = fread(buf, 1, 1024, fp))) {
00328 if (0 != pst_decrypt(0, buf, l, PST_COMP_ENCRYPT))
00329 fprintf(stderr, "pst_decrypt() failed (I'll try to continue)\n");
00330
00331 if (l != pst_fwrite(buf, 1, l, stdout)) {
00332 fprintf(stderr, "Couldn't output to stdout?\n");
00333 DEBUG_RET();
00334 return 1;
00335 }
00336 }
00337 DEBUG_RET();
00338 return 0;
00339 }
00340
00341 if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n");
00342
00343 RET_DERROR(pst_open(&pstfile, fname), 1, ("Error opening File\n"));
00344 RET_DERROR(pst_load_index(&pstfile), 2, ("Index Error\n"));
00345
00346 pst_load_extended_attributes(&pstfile);
00347
00348 if (chdir(output_dir)) {
00349 x = errno;
00350 pst_close(&pstfile);
00351 DEBUG_RET();
00352 DIE(("main: Cannot change to output dir %s: %s\n", output_dir, strerror(x)));
00353 }
00354
00355 if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n");
00356
00357 d_ptr = pstfile.d_head;
00358 item = pst_parse_item(&pstfile, d_ptr);
00359 if (!item || !item->message_store) {
00360 DEBUG_RET();
00361 DIE(("main: Could not get root record\n"));
00362 }
00363
00364
00365 if (!item->file_as) {
00366 if (!(temp = strrchr(fname, '/')))
00367 if (!(temp = strrchr(fname, '\\')))
00368 temp = fname;
00369 else
00370 temp++;
00371 else
00372 temp++;
00373 item->file_as = (char*)xmalloc(strlen(temp)+1);
00374 strcpy(item->file_as, temp);
00375 DEBUG_MAIN(("file_as was blank, so am using %s\n", item->file_as));
00376 }
00377 DEBUG_MAIN(("main: Root Folder Name: %s\n", item->file_as));
00378
00379 d_ptr = pst_getTopOfFolders(&pstfile, item);
00380 if (!d_ptr) {
00381 DEBUG_RET();
00382 DIE(("Top of folders record not found. Cannot continue\n"));
00383 }
00384
00385 process(item, d_ptr->child);
00386 pst_freeItem(item);
00387 pst_close(&pstfile);
00388 DEBUG_RET();
00389 regfree(&meta_charset_pattern);
00390 return 0;
00391 }
00392
00393
00394 void write_email_body(FILE *f, char *body) {
00395 char *n = body;
00396
00397 DEBUG_ENT("write_email_body");
00398 while (n) {
00399 if (strncmp(body, "From ", 5) == 0)
00400 fprintf(f, ">");
00401 if ((n = strchr(body, '\n'))) {
00402 n++;
00403 pst_fwrite(body, n-body, 1, f);
00404 body = n;
00405 }
00406 }
00407 pst_fwrite(body, strlen(body), 1, f);
00408 DEBUG_RET();
00409 }
00410
00411
00412 void removeCR (char *c) {
00413
00414 char *a, *b;
00415 DEBUG_ENT("removeCR");
00416 a = b = c;
00417 while (*a != '\0') {
00418 *b = *a;
00419 if (*a != '\r') b++;
00420 a++;
00421 }
00422 *b = '\0';
00423 DEBUG_RET();
00424 }
00425
00426
00427 void usage() {
00428 DEBUG_ENT("usage");
00429 version();
00430 printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name);
00431 printf("OPTIONS:\n");
00432 printf("\t-V\t- Version. Display program version\n");
00433 printf("\t-C\t- Decrypt (compressible encryption) the entire file and output on stdout (not typically useful)\n");
00434 printf("\t-D\t- Include deleted items in output\n");
00435 printf("\t-M\t- MH. Write emails in the MH format\n");
00436 printf("\t-S\t- Separate. Write emails in the separate format\n");
00437 printf("\t-b\t- Don't save RTF-Body attachments\n");
00438 printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n");
00439 printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readpstlog to print it\n");
00440 printf("\t-h\t- Help. This screen\n");
00441 printf("\t-k\t- KMail. Output in kmail format\n");
00442 printf("\t-o <dirname>\t- Output directory to write files to. CWD is changed *after* opening pst file\n");
00443 printf("\t-q\t- Quiet. Only print error messages\n");
00444 printf("\t-r\t- Recursive. Output in a recursive format\n");
00445 printf("\t-w\t- Overwrite any output mbox files\n");
00446 DEBUG_RET();
00447 }
00448
00449
00450 void version() {
00451 DEBUG_ENT("version");
00452 printf("ReadPST / LibPST v%s\n", VERSION);
00453 #if BYTE_ORDER == BIG_ENDIAN
00454 printf("Big Endian implementation being used.\n");
00455 #elif BYTE_ORDER == LITTLE_ENDIAN
00456 printf("Little Endian implementation being used.\n");
00457 #else
00458 # error "Byte order not supported by this library"
00459 #endif
00460 #ifdef __GNUC__
00461 printf("GCC %d.%d : %s %s\n", __GNUC__, __GNUC_MINOR__, __DATE__, __TIME__);
00462 #endif
00463 DEBUG_RET();
00464 }
00465
00466
00467 char *mk_kmail_dir(char *fname) {
00468
00469
00470
00471
00472 char *dir, *out_name, *index;
00473 int x;
00474 DEBUG_ENT("mk_kmail_dir");
00475 if (kmail_chdir && chdir(kmail_chdir)) {
00476 x = errno;
00477 DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x)));
00478 }
00479 dir = malloc(strlen(fname)+strlen(OUTPUT_KMAIL_DIR_TEMPLATE)+1);
00480 sprintf(dir, OUTPUT_KMAIL_DIR_TEMPLATE, fname);
00481 check_filename(dir);
00482 if (D_MKDIR(dir)) {
00483
00484 if (errno != EEXIST) {
00485 x = errno;
00486 DIE(("mk_kmail_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
00487 }
00488 }
00489 kmail_chdir = realloc(kmail_chdir, strlen(dir)+1);
00490 strcpy(kmail_chdir, dir);
00491 free (dir);
00492
00493
00494 index = malloc(strlen(fname)+strlen(KMAIL_INDEX)+1);
00495 sprintf(index, KMAIL_INDEX, fname);
00496 unlink(index);
00497 free(index);
00498
00499 out_name = malloc(strlen(fname)+strlen(OUTPUT_TEMPLATE)+1);
00500 sprintf(out_name, OUTPUT_TEMPLATE, fname);
00501 DEBUG_RET();
00502 return out_name;
00503 }
00504
00505
00506 int close_kmail_dir() {
00507
00508 int x;
00509 DEBUG_ENT("close_kmail_dir");
00510 if (kmail_chdir) {
00511 free(kmail_chdir);
00512 kmail_chdir = NULL;
00513 } else {
00514 if (chdir("..")) {
00515 x = errno;
00516 DIE(("close_kmail_dir: Cannot move up dir (..): %s\n", strerror(x)));
00517 }
00518 }
00519 DEBUG_RET();
00520 return 0;
00521 }
00522
00523
00524
00525
00526
00527 char *mk_recurse_dir(char *dir) {
00528 int x;
00529 char *out_name;
00530 DEBUG_ENT("mk_recurse_dir");
00531 check_filename(dir);
00532 if (D_MKDIR (dir)) {
00533 if (errno != EEXIST) {
00534 x = errno;
00535 DIE(("mk_recurse_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
00536 }
00537 }
00538 if (chdir (dir)) {
00539 x = errno;
00540 DIE(("mk_recurse_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
00541 }
00542 out_name = malloc(strlen("mbox")+1);
00543 strcpy(out_name, "mbox");
00544 DEBUG_RET();
00545 return out_name;
00546 }
00547
00548
00549 int close_recurse_dir() {
00550 int x;
00551 DEBUG_ENT("close_recurse_dir");
00552 if (chdir("..")) {
00553 x = errno;
00554 DIE(("close_recurse_dir: Cannot go up dir (..): %s\n", strerror(x)));
00555 }
00556 DEBUG_RET();
00557 return 0;
00558 }
00559
00560
00561 char *mk_separate_dir(char *dir) {
00562 size_t dirsize = strlen(dir) + 10;
00563 char dir_name[dirsize];
00564 int x = 0, y = 0;
00565
00566 DEBUG_ENT("mk_separate_dir");
00567 do {
00568 if (y == 0)
00569 snprintf(dir_name, dirsize, "%s", dir);
00570 else
00571 snprintf(dir_name, dirsize, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y);
00572
00573 check_filename(dir_name);
00574 DEBUG_MAIN(("about to try creating %s\n", dir_name));
00575 if (D_MKDIR(dir_name)) {
00576 if (errno != EEXIST) {
00577 x = errno;
00578 DIE(("mk_separate_dir: Cannot create directory %s: %s\n", dir, strerror(x)));
00579 }
00580 } else {
00581 break;
00582 }
00583 y++;
00584 } while (overwrite == 0);
00585
00586 if (chdir(dir_name)) {
00587 x = errno;
00588 DIE(("mk_separate_dir: Cannot change to directory %s: %s\n", dir, strerror(x)));
00589 }
00590
00591 if (overwrite) {
00592
00593 #if !defined(WIN32) && !defined(__CYGWIN__)
00594 DIR * sdir = NULL;
00595 struct dirent *dirent = NULL;
00596 struct stat filestat;
00597 if (!(sdir = opendir("./"))) {
00598 WARN(("mk_separate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./"));
00599 } else {
00600 while ((dirent = readdir(sdir))) {
00601 if (lstat(dirent->d_name, &filestat) != -1)
00602 if (S_ISREG(filestat.st_mode)) {
00603 if (unlink(dirent->d_name)) {
00604 y = errno;
00605 DIE(("mk_separate_dir: unlink returned error on file %s: %s\n", dirent->d_name, strerror(y)));
00606 }
00607 }
00608 }
00609 }
00610 #endif
00611 }
00612
00613
00614 DEBUG_RET();
00615 return NULL;
00616 }
00617
00618
00619 int close_separate_dir() {
00620 int x;
00621 DEBUG_ENT("close_separate_dir");
00622 if (chdir("..")) {
00623 x = errno;
00624 DIE(("close_separate_dir: Cannot go up dir (..): %s\n", strerror(x)));
00625 }
00626 DEBUG_RET();
00627 return 0;
00628 }
00629
00630
00631 int mk_separate_file(struct file_ll *f) {
00632 const int name_offset = 1;
00633 DEBUG_ENT("mk_separate_file");
00634 DEBUG_MAIN(("opening next file to save email\n"));
00635 if (f->email_count > 999999999) {
00636 DIE(("mk_separate_file: The number of emails in this folder has become too high to handle"));
00637 }
00638 sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset);
00639 if (f->output) fclose(f->output);
00640 f->output = NULL;
00641 check_filename(f->name);
00642 if (!(f->output = fopen(f->name, "w"))) {
00643 DIE(("mk_separate_file: Cannot open file to save email \"%s\"\n", f->name));
00644 }
00645 DEBUG_RET();
00646 return 0;
00647 }
00648
00649
00650 char *my_stristr(char *haystack, char *needle) {
00651
00652 char *x=haystack, *y=needle, *z = NULL;
00653 if (!haystack || !needle) {
00654 return NULL;
00655 }
00656 while (*y != '\0' && *x != '\0') {
00657 if (tolower(*y) == tolower(*x)) {
00658
00659 y++;
00660 if (!z) {
00661 z = x;
00662 }
00663 } else {
00664 y = needle;
00665 z = NULL;
00666 }
00667 x++;
00668 }
00669
00670 if (*y != '\0') return NULL;
00671 return z;
00672 }
00673
00674
00675 void check_filename(char *fname) {
00676 char *t = fname;
00677 DEBUG_ENT("check_filename");
00678 if (!t) {
00679 DEBUG_RET();
00680 return;
00681 }
00682 while ((t = strpbrk(t, "/\\:"))) {
00683
00684 *t = '_';
00685 }
00686 DEBUG_RET();
00687 }
00688
00689
00690 void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst)
00691 {
00692 FILE *fp = NULL;
00693 int x = 0;
00694 char *temp = NULL;
00695
00696
00697
00698 char *attach_filename = (current_attach->filename2) ? current_attach->filename2
00699 : current_attach->filename1;
00700 DEBUG_ENT("write_separate_attachment");
00701
00702 check_filename(f_name);
00703 if (!attach_filename) {
00704
00705 temp = xmalloc(strlen(f_name)+15);
00706 sprintf(temp, "%s-attach%i", f_name, attach_num);
00707 } else {
00708
00709 temp = xmalloc(strlen(f_name)+strlen(attach_filename)+15);
00710 do {
00711 if (fp) fclose(fp);
00712 if (x == 0)
00713 sprintf(temp, "%s-%s", f_name, attach_filename);
00714 else
00715 sprintf(temp, "%s-%s-%i", f_name, attach_filename, x);
00716 } while ((fp = fopen(temp, "r")) && ++x < 99999999);
00717 if (x > 99999999) {
00718 DIE(("error finding attachment name. exhausted possibilities to %s\n", temp));
00719 }
00720 }
00721 DEBUG_EMAIL(("Saving attachment to %s\n", temp));
00722 if (!(fp = fopen(temp, "w"))) {
00723 WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp));
00724 } else {
00725 if (current_attach->data)
00726 pst_fwrite(current_attach->data, 1, current_attach->size, fp);
00727 else {
00728 (void)pst_attach_to_file(pst, current_attach, fp);
00729 }
00730 fclose(fp);
00731 }
00732 if (temp) free(temp);
00733 DEBUG_RET();
00734 }
00735
00736
00737 void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char *boundary, pst_file* pst)
00738 {
00739 char *attach_filename;
00740 char *enc = NULL;
00741 DEBUG_ENT("write_inline_attachment");
00742 DEBUG_EMAIL(("Attachment Size is %i\n", current_attach->size));
00743 DEBUG_EMAIL(("Attachment Pointer is %p\n", current_attach->data));
00744 if (current_attach->data) {
00745 enc = base64_encode (current_attach->data, current_attach->size);
00746 if (!enc) {
00747 DEBUG_EMAIL(("ERROR base64_encode returned NULL. Must have failed\n"));
00748 DEBUG_RET();
00749 return;
00750 }
00751 }
00752
00753 fprintf(f_output, "\n--%s\n", boundary);
00754 if (!current_attach->mimetype) {
00755 fprintf(f_output, "Content-Type: %s\n", MIME_TYPE_DEFAULT);
00756 } else {
00757 fprintf(f_output, "Content-Type: %s\n", current_attach->mimetype);
00758 }
00759 fprintf(f_output, "Content-Transfer-Encoding: base64\n");
00760
00761
00762 if (current_attach->filename2) {
00763 attach_filename = current_attach->filename2;
00764 } else {
00765 attach_filename = current_attach->filename1;
00766 }
00767 if (!attach_filename) {
00768 fprintf(f_output, "Content-Disposition: inline\n\n");
00769 } else {
00770 fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", attach_filename);
00771 }
00772
00773 if (current_attach->data) {
00774 pst_fwrite(enc, 1, strlen(enc), f_output);
00775 DEBUG_EMAIL(("Attachment Size after encoding is %i\n", strlen(enc)));
00776 free(enc);
00777 } else {
00778 (void)pst_attach_to_file_base64(pst, current_attach, f_output);
00779 }
00780 fprintf(f_output, "\n\n");
00781 DEBUG_RET();
00782 }
00783
00784
00785 void header_has_field(char *header, char *field, int *flag)
00786 {
00787 if (my_stristr(header, field) || (strncasecmp(header, field+1, strlen(field)-1) == 0)) {
00788 DEBUG_EMAIL(("header block has %s header\n", field+1));
00789 *flag = 1;
00790 }
00791 }
00792
00793
00794 char* header_get_field(char *header, char *field)
00795 {
00796 char *t = my_stristr(header, field);
00797 if (!t && (strncasecmp(header, field+1, strlen(field)-1) == 0)) t = header;
00798 return t;
00799 }
00800
00801
00802 void header_strip_field(char *header, char *field)
00803 {
00804 char *e;
00805 char *t = header_get_field(header, field);
00806 if (t) {
00807 e = strchr(t+1, '\n');
00808 while (e && ((e[1] == ' ') || (e[1] == '\t'))) {
00809 e = strchr(e+1, '\n');
00810 }
00811 if (e) {
00812 if (t == header) e++;
00813 while (*e != '\0') {
00814 *t = *e;
00815 t++;
00816 e++;
00817 }
00818 *t = '\0';
00819 }
00820 else {
00821
00822 *t = '\0';
00823 }
00824 }
00825 }
00826
00827
00828 int test_base64(char *body)
00829 {
00830 int b64 = 0;
00831 uint8_t *b = (uint8_t *)body;
00832 while (*b != 0) {
00833 if ((*b < 32) && (*b != 9) && (*b != 10)) {
00834 DEBUG_EMAIL(("found base64 byte %d\n", (int)*b));
00835 DEBUG_HEXDUMPC(body, strlen(body), 0x10);
00836 b64 = 1;
00837 break;
00838 }
00839 b++;
00840 }
00841 return b64;
00842 }
00843
00844
00845 void find_html_charset(char *html, char *charset, size_t charsetlen)
00846 {
00847 const int index = 1;
00848 const int nmatch = index+1;
00849 regmatch_t match[nmatch];
00850 int rc = regexec(&meta_charset_pattern, html, nmatch, match, 0);
00851 if (rc == 0) {
00852 int s = match[index].rm_so;
00853 int e = match[index].rm_eo;
00854 if (s != -1) {
00855 char save = html[e];
00856 html[e] = '\0';
00857 snprintf(charset, charsetlen, "%s", html+s);
00858 html[e] = save;
00859 DEBUG_EMAIL(("charset %s from html text\n", charset));
00860 }
00861 else {
00862 DEBUG_EMAIL(("matching %d %d %d %d", match[0].rm_so, match[0].rm_eo, match[1].rm_so, match[1].rm_eo));
00863 DEBUG_HEXDUMPC(html, strlen(html), 0x10);
00864 }
00865 }
00866 else {
00867 DEBUG_EMAIL(("regexec returns %d\n", rc));
00868 }
00869 }
00870
00871
00872 void write_body_part(FILE* f_output, char *body, char *mime, char *charset, char *boundary)
00873 {
00874 char *needfree = NULL;
00875 if (strcasecmp("utf-8", charset)) {
00876
00877 size_t rc;
00878 DEBUG_EMAIL(("Convert %s utf-8 to %s\n", mime, charset));
00879 vbuf *newer = vballoc(2);
00880 rc = vb_utf8to8bit(newer, body, strlen(body) + 1, charset);
00881 if (rc == (size_t)-1) {
00882
00883 free(newer->b);
00884 DEBUG_EMAIL(("Failed to convert %s utf-8 to %s\n", mime, charset));
00885 }
00886 else {
00887 needfree = body = newer->b;
00888 }
00889 free(newer);
00890 }
00891 removeCR(body);
00892 int base64 = test_base64(body);
00893 fprintf(f_output, "\n--%s\n", boundary);
00894 fprintf(f_output, "Content-Type: %s; charset=\"%s\"\n", mime, charset);
00895 if (base64) fprintf(f_output, "Content-Transfer-Encoding: base64\n");
00896 fprintf(f_output, "\n");
00897 if (base64) {
00898 char *enc = base64_encode(body, strlen(body));
00899 if (enc) {
00900 write_email_body(f_output, enc);
00901 fprintf(f_output, "\n");
00902 free(enc);
00903 }
00904 }
00905 else {
00906 write_email_body(f_output, body);
00907 }
00908 if (needfree) free(needfree);
00909 }
00910
00911
00912 void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf)
00913 {
00914 char boundary[60];
00915 char body_charset[60];
00916 char sender[60];
00917 int sender_known = 0;
00918 char *temp = NULL;
00919 int attach_num;
00920 time_t em_time;
00921 char *c_time;
00922 int has_from, has_subject, has_to, has_cc, has_bcc, has_date;
00923 has_from = has_subject = has_to = has_cc = has_bcc = has_date = 0;
00924 DEBUG_ENT("write_normal_email");
00925
00926
00927 snprintf(body_charset, sizeof(body_charset), "%s", (item->email->body_charset) ? item->email->body_charset : "utf-8");
00928
00929
00930 if (item->email->sender_address && strchr(item->email->sender_address, '@')) {
00931 temp = item->email->sender_address;
00932 sender_known = 1;
00933 }
00934 else {
00935 temp = "MAILER-DAEMON";
00936 }
00937 snprintf(sender, sizeof(sender), "%s", temp);
00938
00939
00940 if (item->email->sent_date) {
00941 em_time = fileTimeToUnixTime(item->email->sent_date, 0);
00942 c_time = ctime(&em_time);
00943 if (c_time)
00944 c_time[strlen(c_time)-1] = '\0';
00945 else
00946 c_time = "Fri Dec 28 12:06:21 2001";
00947 } else
00948 c_time= "Fri Dec 28 12:06:21 2001";
00949
00950
00951 snprintf(boundary, sizeof(boundary), "--boundary-LibPST-iamunique-%i_-_-", rand());
00952
00953
00954 if (item->email->header ) {
00955 char *t;
00956 removeCR(item->email->header);
00957
00958
00959
00960
00961 temp = strstr(item->email->header, "\n\n");
00962 if (temp) {
00963 temp[1] = '\0';
00964 DEBUG_EMAIL(("Found body text in header %s\n", temp+2));
00965 }
00966
00967
00968 header_has_field(item->email->header, "\nFrom: ", &has_from);
00969 header_has_field(item->email->header, "\nTo: ", &has_to);
00970 header_has_field(item->email->header, "\nSubject: ", &has_subject);
00971 header_has_field(item->email->header, "\nDate: ", &has_date);
00972 header_has_field(item->email->header, "\nCC: ", &has_cc);
00973 header_has_field(item->email->header, "\nBCC: ", &has_bcc);
00974
00975
00976 t = header_get_field(item->email->header, "\nContent-Type: ");
00977 if (t) {
00978
00979 t++;
00980 char *n = strchr(t, '\n');
00981 char *s = my_stristr(t, "; charset=");
00982 if (n && s && (s < n)) {
00983 char *e;
00984 char save;
00985 s += 10;
00986 if (*s == '"') {
00987 s++;
00988 e = strchr(s, '"');
00989 }
00990 else {
00991 e = strchr(s, ';');
00992 }
00993 if (!e || (e > n)) e = n;
00994 save = *e;
00995 *e = '\0';
00996 snprintf(body_charset, sizeof(body_charset), "%s", s);
00997 *e = save;
00998 DEBUG_EMAIL(("body charset %s from headers\n", body_charset));
00999 }
01000 }
01001
01002
01003 if (!sender_known) {
01004 t = header_get_field(item->email->header, "\nFrom: ");
01005 if (t) {
01006
01007 t++;
01008 char *n = strchr(t, '\n');
01009 char *s = strchr(t, '<');
01010 char *e = strchr(t, '>');
01011 if (s && e && n && (s < e) && (e < n)) {
01012 char save = *e;
01013 *e = '\0';
01014 snprintf(sender, sizeof(sender), "%s", s+1);
01015 *e = save;
01016 }
01017 }
01018 }
01019
01020
01021 header_strip_field(item->email->header, "\nMicrosoft Mail Internet Headers");
01022 header_strip_field(item->email->header, "\nMIME-Version: ");
01023 header_strip_field(item->email->header, "\nContent-Type: ");
01024 header_strip_field(item->email->header, "\nContent-Transfer-Encoding: ");
01025 header_strip_field(item->email->header, "\nContent-class: ");
01026 header_strip_field(item->email->header, "\nX-MimeOLE: ");
01027 header_strip_field(item->email->header, "\nBcc: ");
01028 }
01029
01030 DEBUG_EMAIL(("About to print Header\n"));
01031
01032 if (item && item->email && item->email->subject && item->email->subject->subj) {
01033 DEBUG_EMAIL(("item->email->subject->subj = %s\n", item->email->subject->subj));
01034 }
01035
01036 if (item->email->header) {
01037 int len;
01038 char *soh = item->email->header;
01039
01040 if (mode != MODE_SEPARATE) {
01041
01042 if (strncmp(soh, "X-From_: ", 9) == 0 ) {
01043 fputs("From ", f_output);
01044 soh += 9;
01045 } else
01046 fprintf(f_output, "From %s %s\n", sender, c_time);
01047 }
01048
01049
01050 fprintf(f_output, "%s", soh);
01051 len = strlen(soh);
01052 if (!len || (soh[len-1] != '\n')) fprintf(f_output, "\n");
01053
01054 } else {
01055
01056 if (mode != MODE_SEPARATE) {
01057
01058 fprintf(f_output, "From %s %s\n", sender, c_time);
01059 }
01060 }
01061
01062
01063 if (!has_from) {
01064 fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, sender);
01065 }
01066
01067 if (!has_subject) {
01068 if (item->email->subject && item->email->subject->subj) {
01069 fprintf(f_output, "Subject: %s\n", item->email->subject->subj);
01070 } else {
01071 fprintf(f_output, "Subject: \n");
01072 }
01073 }
01074
01075 if (!has_to && item->email->sentto_address) {
01076 fprintf(f_output, "To: %s\n", item->email->sentto_address);
01077 }
01078
01079 if (!has_cc && item->email->cc_address) {
01080 fprintf(f_output, "Cc: %s\n", item->email->cc_address);
01081 }
01082
01083 if (!has_bcc && item->email->bcc_address) {
01084 fprintf(f_output, "Bcc: %s\n", item->email->bcc_address);
01085 }
01086
01087 if (!has_date && item->email->sent_date) {
01088 char c_time[C_TIME_SIZE];
01089 strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time));
01090 fprintf(f_output, "Date: %s\n", c_time);
01091 }
01092
01093
01094 fprintf(f_output, "MIME-Version: 1.0\n");
01095 if (item->attach || (item->email->rtf_compressed && save_rtf)
01096 || item->email->encrypted_body
01097 || item->email->encrypted_htmlbody) {
01098
01099 fprintf(f_output, "Content-Type: multipart/mixed;\n\tboundary=\"%s\"\n", boundary);
01100 } else {
01101
01102 fprintf(f_output, "Content-Type: multipart/alternative;\n\tboundary=\"%s\"\n", boundary);
01103 }
01104 fprintf(f_output, "\n");
01105
01106
01107 if (item->email->body) {
01108 write_body_part(f_output, item->email->body, "text/plain", body_charset, boundary);
01109 }
01110
01111 if (item->email->htmlbody) {
01112 find_html_charset(item->email->htmlbody, body_charset, sizeof(body_charset));
01113 write_body_part(f_output, item->email->htmlbody, "text/html", body_charset, boundary);
01114 }
01115
01116 if (item->email->rtf_compressed && save_rtf) {
01117 pst_item_attach* attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach));
01118 DEBUG_EMAIL(("Adding RTF body as attachment\n"));
01119 memset(attach, 0, sizeof(pst_item_attach));
01120 attach->next = item->attach;
01121 item->attach = attach;
01122 attach->data = lzfu_decompress(item->email->rtf_compressed, item->email->rtf_compressed_size, &attach->size);
01123 attach->filename2 = strdup(RTF_ATTACH_NAME);
01124 attach->mimetype = strdup(RTF_ATTACH_TYPE);
01125 }
01126
01127 if (item->email->encrypted_body || item->email->encrypted_htmlbody) {
01128
01129 if (item->email->encrypted_body) {
01130 pst_item_attach* attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach));
01131 DEBUG_EMAIL(("Adding Encrypted Body as attachment\n"));
01132 attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach));
01133 memset(attach, 0, sizeof(pst_item_attach));
01134 attach->next = item->attach;
01135 item->attach = attach;
01136 attach->data = item->email->encrypted_body;
01137 attach->size = item->email->encrypted_body_size;
01138 item->email->encrypted_body = NULL;
01139 }
01140
01141 if (item->email->encrypted_htmlbody) {
01142 pst_item_attach* attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach));
01143 DEBUG_EMAIL(("Adding encrypted HTML body as attachment\n"));
01144 attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach));
01145 memset(attach, 0, sizeof(pst_item_attach));
01146 attach->next = item->attach;
01147 item->attach = attach;
01148 attach->data = item->email->encrypted_htmlbody;
01149 attach->size = item->email->encrypted_htmlbody_size;
01150 item->email->encrypted_htmlbody = NULL;
01151 }
01152 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");
01153 }
01154
01155
01156 {
01157 pst_item_attach* attach;
01158 attach_num = 0;
01159 for (attach = item->attach; attach; attach = attach->next) {
01160 DEBUG_EMAIL(("Attempting Attachment encoding\n"));
01161 if (!attach->data) {
01162 DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", attach->size));
01163 }
01164 if (mode == MODE_SEPARATE && !mode_MH)
01165 write_separate_attachment(f_name, attach, ++attach_num, pst);
01166 else
01167 write_inline_attachment(f_output, attach, boundary, pst);
01168 }
01169 }
01170
01171
01172 if (mode != MODE_SEPARATE) {
01173 DEBUG_EMAIL(("Writing buffer between emails\n"));
01174 fprintf(f_output, "\n--%s--\n", boundary);
01175 fprintf(f_output, "\n\n");
01176 }
01177 DEBUG_RET();
01178 }
01179
01180
01181 void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[])
01182 {
01183
01184
01185
01186
01187 DEBUG_ENT("write_vcard");
01188
01189 fprintf(f_output, "BEGIN:VCARD\n");
01190 fprintf(f_output, "FN:%s\n", pst_rfc2426_escape(contact->fullname));
01191
01192
01193 fprintf(f_output, "N:%s;", (!contact->surname) ? "" : pst_rfc2426_escape(contact->surname));
01194 fprintf(f_output, "%s;", (!contact->first_name) ? "" : pst_rfc2426_escape(contact->first_name));
01195 fprintf(f_output, "%s;", (!contact->middle_name) ? "" : pst_rfc2426_escape(contact->middle_name));
01196 fprintf(f_output, "%s;", (!contact->display_name_prefix) ? "" : pst_rfc2426_escape(contact->display_name_prefix));
01197 fprintf(f_output, "%s\n", (!contact->suffix) ? "" : pst_rfc2426_escape(contact->suffix));
01198
01199 if (contact->nickname)
01200 fprintf(f_output, "NICKNAME:%s\n", pst_rfc2426_escape(contact->nickname));
01201 if (contact->address1)
01202 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address1));
01203 if (contact->address2)
01204 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address2));
01205 if (contact->address3)
01206 fprintf(f_output, "EMAIL:%s\n", pst_rfc2426_escape(contact->address3));
01207 if (contact->birthday)
01208 fprintf(f_output, "BDAY:%s\n", pst_rfc2425_datetime_format(contact->birthday));
01209
01210 if (contact->home_address) {
01211
01212 fprintf(f_output, "ADR;TYPE=home:%s;", (!contact->home_po_box) ? "" : pst_rfc2426_escape(contact->home_po_box));
01213 fprintf(f_output, "%s;", "");
01214 fprintf(f_output, "%s;", (!contact->home_street) ? "" : pst_rfc2426_escape(contact->home_street));
01215 fprintf(f_output, "%s;", (!contact->home_city) ? "" : pst_rfc2426_escape(contact->home_city));
01216 fprintf(f_output, "%s;", (!contact->home_state) ? "" : pst_rfc2426_escape(contact->home_state));
01217 fprintf(f_output, "%s;", (!contact->home_postal_code) ? "" : pst_rfc2426_escape(contact->home_postal_code));
01218 fprintf(f_output, "%s\n", (!contact->home_country) ? "" : pst_rfc2426_escape(contact->home_country));
01219 fprintf(f_output, "LABEL;TYPE=home:%s\n", pst_rfc2426_escape(contact->home_address));
01220 }
01221
01222 if (contact->business_address) {
01223
01224 fprintf(f_output, "ADR;TYPE=work:%s;", (!contact->business_po_box) ? "" : pst_rfc2426_escape(contact->business_po_box));
01225 fprintf(f_output, "%s;", "");
01226 fprintf(f_output, "%s;", (!contact->business_street) ? "" : pst_rfc2426_escape(contact->business_street));
01227 fprintf(f_output, "%s;", (!contact->business_city) ? "" : pst_rfc2426_escape(contact->business_city));
01228 fprintf(f_output, "%s;", (!contact->business_state) ? "" : pst_rfc2426_escape(contact->business_state));
01229 fprintf(f_output, "%s;", (!contact->business_postal_code) ? "" : pst_rfc2426_escape(contact->business_postal_code));
01230 fprintf(f_output, "%s\n", (!contact->business_country) ? "" : pst_rfc2426_escape(contact->business_country));
01231 fprintf(f_output, "LABEL;TYPE=work:%s\n", pst_rfc2426_escape(contact->business_address));
01232 }
01233
01234 if (contact->other_address) {
01235
01236 fprintf(f_output, "ADR;TYPE=postal:%s;",(!contact->other_po_box) ? "" : pst_rfc2426_escape(contact->other_po_box));
01237 fprintf(f_output, "%s;", "");
01238 fprintf(f_output, "%s;", (!contact->other_street) ? "" : pst_rfc2426_escape(contact->other_street));
01239 fprintf(f_output, "%s;", (!contact->other_city) ? "" : pst_rfc2426_escape(contact->other_city));
01240 fprintf(f_output, "%s;", (!contact->other_state) ? "" : pst_rfc2426_escape(contact->other_state));
01241 fprintf(f_output, "%s;", (!contact->other_postal_code) ? "" : pst_rfc2426_escape(contact->other_postal_code));
01242 fprintf(f_output, "%s\n", (!contact->other_country) ? "" : pst_rfc2426_escape(contact->other_country));
01243 fprintf(f_output, "LABEL;TYPE=postal:%s\n", pst_rfc2426_escape(contact->other_address));
01244 }
01245
01246 if (contact->business_fax) fprintf(f_output, "TEL;TYPE=work,fax:%s\n", pst_rfc2426_escape(contact->business_fax));
01247 if (contact->business_phone) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", pst_rfc2426_escape(contact->business_phone));
01248 if (contact->business_phone2) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", pst_rfc2426_escape(contact->business_phone2));
01249 if (contact->car_phone) fprintf(f_output, "TEL;TYPE=car,voice:%s\n", pst_rfc2426_escape(contact->car_phone));
01250 if (contact->home_fax) fprintf(f_output, "TEL;TYPE=home,fax:%s\n", pst_rfc2426_escape(contact->home_fax));
01251 if (contact->home_phone) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", pst_rfc2426_escape(contact->home_phone));
01252 if (contact->home_phone2) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", pst_rfc2426_escape(contact->home_phone2));
01253 if (contact->isdn_phone) fprintf(f_output, "TEL;TYPE=isdn:%s\n", pst_rfc2426_escape(contact->isdn_phone));
01254 if (contact->mobile_phone) fprintf(f_output, "TEL;TYPE=cell,voice:%s\n", pst_rfc2426_escape(contact->mobile_phone));
01255 if (contact->other_phone) fprintf(f_output, "TEL;TYPE=msg:%s\n", pst_rfc2426_escape(contact->other_phone));
01256 if (contact->pager_phone) fprintf(f_output, "TEL;TYPE=pager:%s\n", pst_rfc2426_escape(contact->pager_phone));
01257 if (contact->primary_fax) fprintf(f_output, "TEL;TYPE=fax,pref:%s\n", pst_rfc2426_escape(contact->primary_fax));
01258 if (contact->primary_phone) fprintf(f_output, "TEL;TYPE=phone,pref:%s\n", pst_rfc2426_escape(contact->primary_phone));
01259 if (contact->radio_phone) fprintf(f_output, "TEL;TYPE=pcs:%s\n", pst_rfc2426_escape(contact->radio_phone));
01260 if (contact->telex) fprintf(f_output, "TEL;TYPE=bbs:%s\n", pst_rfc2426_escape(contact->telex));
01261 if (contact->job_title) fprintf(f_output, "TITLE:%s\n", pst_rfc2426_escape(contact->job_title));
01262 if (contact->profession) fprintf(f_output, "ROLE:%s\n", pst_rfc2426_escape(contact->profession));
01263 if (contact->assistant_name || contact->assistant_phone) {
01264 fprintf(f_output, "AGENT:BEGIN:VCARD\n");
01265 if (contact->assistant_name) fprintf(f_output, "FN:%s\n", pst_rfc2426_escape(contact->assistant_name));
01266 if (contact->assistant_phone) fprintf(f_output, "TEL:%s\n", pst_rfc2426_escape(contact->assistant_phone));
01267 }
01268 if (contact->company_name) fprintf(f_output, "ORG:%s\n", pst_rfc2426_escape(contact->company_name));
01269 if (comment) fprintf(f_output, "NOTE:%s\n", pst_rfc2426_escape(comment));
01270
01271 fprintf(f_output, "VERSION: 3.0\n");
01272 fprintf(f_output, "END:VCARD\n\n");
01273 DEBUG_RET();
01274 }
01275
01276
01277 void write_appointment(FILE* f_output, pst_item_appointment* appointment,
01278 pst_item_email* email, FILETIME* create_date, FILETIME* modify_date)
01279 {
01280 fprintf(f_output, "BEGIN:VEVENT\n");
01281 if (create_date)
01282 fprintf(f_output, "CREATED:%s\n",
01283 pst_rfc2445_datetime_format(create_date));
01284 if (modify_date)
01285 fprintf(f_output, "LAST-MOD:%s\n",
01286 pst_rfc2445_datetime_format(modify_date));
01287 if (email && email->subject)
01288 fprintf(f_output, "SUMMARY:%s\n",
01289 pst_rfc2426_escape(email->subject->subj));
01290 if (email && email->body)
01291 fprintf(f_output, "DESCRIPTION:%s\n",
01292 pst_rfc2426_escape(email->body));
01293 if (appointment && appointment->start)
01294 fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n",
01295 pst_rfc2445_datetime_format(appointment->start));
01296 if (appointment && appointment->end)
01297 fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n",
01298 pst_rfc2445_datetime_format(appointment->end));
01299 if (appointment && appointment->location)
01300 fprintf(f_output, "LOCATION:%s\n",
01301 pst_rfc2426_escape(appointment->location));
01302 if (appointment) {
01303 switch (appointment->showas) {
01304 case PST_FREEBUSY_TENTATIVE:
01305 fprintf(f_output, "STATUS:TENTATIVE\n");
01306 break;
01307 case PST_FREEBUSY_FREE:
01308
01309 fprintf(f_output, "TRANSP:TRANSPARENT\n");
01310 case PST_FREEBUSY_BUSY:
01311 case PST_FREEBUSY_OUT_OF_OFFICE:
01312 fprintf(f_output, "STATUS:CONFIRMED\n");
01313 break;
01314 }
01315 switch (appointment->label) {
01316 case PST_APP_LABEL_NONE:
01317 fprintf(f_output, "CATEGORIES:NONE\n");
01318 break;
01319 case PST_APP_LABEL_IMPORTANT:
01320 fprintf(f_output, "CATEGORIES:IMPORTANT\n");
01321 break;
01322 case PST_APP_LABEL_BUSINESS:
01323 fprintf(f_output, "CATEGORIES:BUSINESS\n");
01324 break;
01325 case PST_APP_LABEL_PERSONAL:
01326 fprintf(f_output, "CATEGORIES:PERSONAL\n");
01327 break;
01328 case PST_APP_LABEL_VACATION:
01329 fprintf(f_output, "CATEGORIES:VACATION\n");
01330 break;
01331 case PST_APP_LABEL_MUST_ATTEND:
01332 fprintf(f_output, "CATEGORIES:MUST-ATTEND\n");
01333 break;
01334 case PST_APP_LABEL_TRAVEL_REQ:
01335 fprintf(f_output, "CATEGORIES:TRAVEL-REQUIRED\n");
01336 break;
01337 case PST_APP_LABEL_NEEDS_PREP:
01338 fprintf(f_output, "CATEGORIES:NEEDS-PREPARATION\n");
01339 break;
01340 case PST_APP_LABEL_BIRTHDAY:
01341 fprintf(f_output, "CATEGORIES:BIRTHDAY\n");
01342 break;
01343 case PST_APP_LABEL_ANNIVERSARY:
01344 fprintf(f_output, "CATEGORIES:ANNIVERSARY\n");
01345 break;
01346 case PST_APP_LABEL_PHONE_CALL:
01347 fprintf(f_output, "CATEGORIES:PHONE-CALL\n");
01348 break;
01349 }
01350 }
01351 fprintf(f_output, "END:VEVENT\n\n");
01352 }
01353
01354
01355 void create_enter_dir(struct file_ll* f, pst_item *item)
01356 {
01357 f->email_count = 0;
01358 f->skip_count = 0;
01359 f->type = item->type;
01360 f->stored_count = (item->folder) ? item->folder->email_count : 0;
01361
01362 DEBUG_ENT("create_enter_dir");
01363 if (mode == MODE_KMAIL)
01364 f->name = mk_kmail_dir(item->file_as);
01365 else if (mode == MODE_RECURSE)
01366 f->name = mk_recurse_dir(item->file_as);
01367 else if (mode == MODE_SEPARATE) {
01368
01369 mk_separate_dir(item->file_as);
01370 f->name = (char*) xmalloc(10);
01371 memset(f->name, 0, 10);
01372
01373 } else {
01374 f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1);
01375 sprintf(f->name, OUTPUT_TEMPLATE, item->file_as);
01376 }
01377
01378 f->dname = (char*) xmalloc(strlen(item->file_as)+1);
01379 strcpy(f->dname, item->file_as);
01380
01381 if (overwrite != 1) {
01382 int x = 0;
01383 char *temp = (char*) xmalloc (strlen(f->name)+10);
01384
01385 sprintf(temp, "%s", f->name);
01386 check_filename(temp);
01387 while ((f->output = fopen(temp, "r"))) {
01388 DEBUG_MAIN(("need to increase filename because one already exists with that name\n"));
01389 DEBUG_MAIN(("- increasing it to %s%d\n", f->name, x));
01390 x++;
01391 sprintf(temp, "%s%08d", f->name, x);
01392 DEBUG_MAIN(("- trying \"%s\"\n", f->name));
01393 if (x == 99999999) {
01394 DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x));
01395 }
01396 fclose(f->output);
01397 }
01398 if (x > 0) {
01399 free (f->name);
01400 f->name = temp;
01401 } else {
01402 free(temp);
01403 }
01404 }
01405
01406 DEBUG_MAIN(("f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as));
01407 if (mode != MODE_SEPARATE) {
01408 check_filename(f->name);
01409 if (!(f->output = fopen(f->name, "w"))) {
01410 DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name));
01411 }
01412 }
01413 DEBUG_RET();
01414 }
01415
01416
01417 void close_enter_dir(struct file_ll *f)
01418 {
01419 DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count));
01420 if (output_mode != OUTPUT_QUIET)
01421 printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n",
01422 f->dname, f->email_count, f->skip_count, f->stored_count);
01423 if (f->output) fclose(f->output);
01424 free(f->name);
01425 free(f->dname);
01426
01427 if (mode == MODE_KMAIL)
01428 close_kmail_dir();
01429 else if (mode == MODE_RECURSE)
01430 close_recurse_dir();
01431 else if (mode == MODE_SEPARATE)
01432 close_separate_dir();
01433 }
01434