Mercurial > libpst
diff src/readpst.c @ 25:73e8959cd86b
patches from Arne
author | carl |
---|---|
date | Tue, 21 Feb 2006 22:50:16 -0800 |
parents | e5418051878c |
children | 9eeba3f4ca4b |
line wrap: on
line diff
--- a/src/readpst.c Mon Feb 20 15:14:54 2006 -0800 +++ b/src/readpst.c Tue Feb 21 22:50:16 2006 -0800 @@ -40,6 +40,7 @@ #define OUTPUT_TEMPLATE "%s" #define OUTPUT_KMAIL_DIR_TEMPLATE ".%s.directory" #define KMAIL_INDEX ".%s.index" +#define SEP_MAIL_FILE_TEMPLATE "%i" /* "%09i" */ // max size of the c_time char*. It will store the date of the email #define C_TIME_SIZE 500 @@ -79,6 +80,13 @@ char *rfc2425_datetime_format(FILETIME *ft); char *rfc2445_datetime_format(FILETIME *ft); char *skip_header_prologue(char *headers); +void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst); +void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst); +void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst); +void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]); +void write_appointment(FILE* f_output, pst_item_appointment* appointment, + pst_item_email* email, FILETIME* create_date, FILETIME* modify_date); +void create_enter_dir(struct file_ll* f, char file_as[], int mode, int overwrite); char *prog_name; char *output_dir = "."; char *kmail_chdir = NULL; @@ -120,25 +128,20 @@ pst_file pstfile; pst_desc_ll *d_ptr; char * fname = NULL; - time_t em_time; - char * c_time, *d_log=NULL; + char *d_log=NULL; int c,x; int mode = MODE_NORMAL; + int mode_MH = 0; int output_mode = OUTPUT_NORMAL; int contact_mode = CMODE_VCARD; int overwrite = 0; - int base64_body = 0; // int encrypt = 0; - FILE *fp; - char *enc; // base64 encoded attachment - char *boundary = NULL, *b1, *b2; // the boundary marker between multipart sections char *temp = NULL; //temporary char pointer - int attach_num = 0; int skip_child = 0; struct file_ll *f, *head; prog_name = argv[0]; - while ((c = getopt(argc, argv, "d:hko:qrSVwc:"))!= -1) { + while ((c = getopt(argc, argv, "d:hko:qrMSVwc:"))!= -1) { switch (c) { case 'c': if (optarg!=NULL && optarg[0]=='v') @@ -164,6 +167,10 @@ case 'k': mode = MODE_KMAIL; break; + case 'M': + mode = MODE_SEPERATE; + mode_MH = 1; + break; case 'o': output_dir = optarg; break; @@ -248,54 +255,7 @@ f->skip_count = 0; f->next = NULL; head = f; - if (mode == MODE_KMAIL) - f->name = mk_kmail_dir(item->file_as); - else if (mode == MODE_RECURSE) - f->name = mk_recurse_dir(item->file_as); - else if (mode == MODE_SEPERATE) { - // do similar stuff to recurse here. - mk_seperate_dir(item->file_as, overwrite); - f->name = (char*) xmalloc(10); - sprintf(f->name, "%09i", f->email_count); - } else { - f->name = (char*) malloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE)+1); - sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); - } - - f->dname = (char*) malloc(strlen(item->file_as)+1); - strcpy(f->dname, item->file_as); - - if (overwrite != 1 && mode != MODE_SEPERATE) { - // if overwrite is set to 1 we keep the existing name and don't modify anything - // we don't want to go changing the file name of the SEPERATE items - temp = (char*) malloc (strlen(f->name)+10); //enough room for 10 digits - sprintf(temp, "%s", f->name); - temp = check_filename(temp); - x = 0; - while ((f->output = fopen(temp, "r")) != NULL) { - DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); - DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); - x++; - sprintf(temp, "%s%08d", f->name, x); - DEBUG_MAIN(("main: - trying \"%s\"\n", temp)); - if (x == 99999999) { - DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); - } - fclose(f->output); - } - if (x > 0) { //then the f->name should change - free (f->name); - f->name = temp; - } else { - free (temp); - } - } - if (mode != MODE_SEPERATE) { - f->name = check_filename(f->name); - if ((f->output = fopen(f->name, "w")) == NULL) { - DIE(("main: Could not open file \"%s\" for write\n", f->name)); - } - } + create_enter_dir(f, item->file_as, mode, overwrite); f->type = item->type; if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) { @@ -355,56 +315,7 @@ temp = item->file_as; temp = check_filename(temp); - - if (mode == MODE_KMAIL) - f->name = mk_kmail_dir(item->file_as); //create directory and form filename - else if (mode == MODE_RECURSE) - f->name = mk_recurse_dir(item->file_as); - else if (mode == MODE_SEPERATE) { - // do similar stuff to recurse here. - mk_seperate_dir(item->file_as, overwrite); - f->name = (char*) xmalloc(10); - memset(f->name, 0, 10); - // sprintf(f->name, "%09i", f->email_count); - } else { - f->name = (char*) xmalloc(strlen(item->file_as)+strlen(OUTPUT_TEMPLATE+1)); - sprintf(f->name, OUTPUT_TEMPLATE, item->file_as); - } - - f->dname = (char*) xmalloc(strlen(item->file_as)+1); - strcpy(f->dname, item->file_as); - - if (overwrite != 1) { - temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits - sprintf(temp, "%s", f->name); - x = 0; - temp = check_filename(temp); - while ((f->output = fopen(temp, "r")) != NULL) { - DEBUG_MAIN(("main: need to increase filename cause one already exists with that name\n")); - DEBUG_MAIN(("main: - increasing it to %s%d\n", f->name, x)); - x++; - sprintf(temp, "%s%08d", f->name, x); - DEBUG_MAIN(("main: - trying \"%s\"\n", f->name)); - if (x == 99999999) { - DIE(("main: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); - } - fclose(f->output); - } - if (x > 0) { //then the f->name should change - free (f->name); - f->name = temp; - } else { - free(temp); - } - } - - DEBUG_MAIN(("main: f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); - if (mode != MODE_SEPERATE) { - f->name = check_filename(f->name); - if ((f->output = fopen(f->name, "w")) == NULL) { - DIE(("main: Could not open file \"%s\" for write\n", f->name)); - } - } + create_enter_dir(f, item->file_as, mode, overwrite); if (d_ptr->child != NULL) { d_ptr = d_ptr->child; skip_child = 1; @@ -452,112 +363,11 @@ if (item->contact == NULL) { // this is an incorrect situation. Inform user DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); } else { - if (contact_mode == CMODE_VCARD) { - // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile - fprintf(f->output, "BEGIN:VCARD\n"); - fprintf(f->output, "FN:%s\n", rfc2426_escape(item->contact->fullname)); - fprintf(f->output, "N:%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->surname==NULL?"":item->contact->surname)), - rfc2426_escape((item->contact->first_name==NULL?"":item->contact->first_name)), - rfc2426_escape((item->contact->middle_name==NULL?"":item->contact->middle_name)), - rfc2426_escape((item->contact->display_name_prefix==NULL?"":item->contact->display_name_prefix)), - rfc2426_escape((item->contact->suffix==NULL?"":item->contact->suffix))); - if (item->contact->nickname != NULL) - fprintf(f->output, "NICKNAME:%s\n", rfc2426_escape(item->contact->nickname)); - if (item->contact->address1 != NULL) - fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address1)); - if (item->contact->address2 != NULL) - fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address2)); - if (item->contact->address3 != NULL) - fprintf(f->output, "EMAIL:%s\n", rfc2426_escape(item->contact->address3)); - if (item->contact->birthday != NULL) - fprintf(f->output, "BDAY:%s\n", rfc2425_datetime_format(item->contact->birthday)); - if (item->contact->home_address != NULL) { - fprintf(f->output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->home_po_box!=NULL?item->contact->home_po_box:"")), - "", // extended Address - rfc2426_escape((item->contact->home_street!=NULL?item->contact->home_street:"")), - rfc2426_escape((item->contact->home_city!=NULL?item->contact->home_city:"")), - rfc2426_escape((item->contact->home_state!=NULL?item->contact->home_state:"")), - rfc2426_escape((item->contact->home_postal_code!=NULL?item->contact->home_postal_code:"")), - rfc2426_escape((item->contact->home_country!=NULL?item->contact->home_country:""))); - fprintf(f->output, "LABEL;TYPE=home:%s\n", rfc2426_escape(item->contact->home_address)); - } - if (item->contact->business_address != NULL) { - fprintf(f->output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->business_po_box!=NULL?item->contact->business_po_box:"")), - "", // extended Address - rfc2426_escape((item->contact->business_street!=NULL?item->contact->business_street:"")), - rfc2426_escape((item->contact->business_city!=NULL?item->contact->business_city:"")), - rfc2426_escape((item->contact->business_state!=NULL?item->contact->business_state:"")), - rfc2426_escape((item->contact->business_postal_code!=NULL?item->contact->business_postal_code:"")), - rfc2426_escape((item->contact->business_country!=NULL?item->contact->business_country:""))); - fprintf(f->output, "LABEL;TYPE=work:%s\n", rfc2426_escape(item->contact->business_address)); - } - if (item->contact->other_address != NULL) { - fprintf(f->output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((item->contact->other_po_box!=NULL?item->contact->business_po_box:"")), - "", // extended Address - rfc2426_escape((item->contact->other_street!=NULL?item->contact->other_street:"")), - rfc2426_escape((item->contact->other_city!=NULL?item->contact->other_city:"")), - rfc2426_escape((item->contact->other_state!=NULL?item->contact->other_state:"")), - rfc2426_escape((item->contact->other_postal_code!=NULL?item->contact->other_postal_code:"")), - rfc2426_escape((item->contact->other_country!=NULL?item->contact->other_country:""))); - fprintf(f->output, "ADR;TYPE=postal:%s\n", rfc2426_escape(item->contact->other_address)); - } - if (item->contact->business_fax != NULL) - fprintf(f->output, "TEL;TYPE=work,fax:%s\n", rfc2426_escape(item->contact->business_fax)); - if (item->contact->business_phone != NULL) - fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone)); - if (item->contact->business_phone2 != NULL) - fprintf(f->output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(item->contact->business_phone2)); - if (item->contact->car_phone != NULL) - fprintf(f->output, "TEL;TYPE=car,voice:%s\n", rfc2426_escape(item->contact->car_phone)); - if (item->contact->home_fax != NULL) - fprintf(f->output, "TEL;TYPE=home,fax:%s\n", rfc2426_escape(item->contact->home_fax)); - if (item->contact->home_phone != NULL) - fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone)); - if (item->contact->home_phone2 != NULL) - fprintf(f->output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(item->contact->home_phone2)); - if (item->contact->isdn_phone != NULL) - fprintf(f->output, "TEL;TYPE=isdn:%s\n", rfc2426_escape(item->contact->isdn_phone)); - if (item->contact->mobile_phone != NULL) - fprintf(f->output, "TEL;TYPE=cell,voice:%s\n", rfc2426_escape(item->contact->mobile_phone)); - if (item->contact->other_phone != NULL) - fprintf(f->output, "TEL;TYPE=msg:%s\n", rfc2426_escape(item->contact->other_phone)); - if (item->contact->pager_phone != NULL) - fprintf(f->output, "TEL;TYPE=pager:%s\n", rfc2426_escape(item->contact->pager_phone)); - if (item->contact->primary_fax != NULL) - fprintf(f->output, "TEL;TYPE=fax,pref:%s\n", rfc2426_escape(item->contact->primary_fax)); - if (item->contact->primary_phone != NULL) - fprintf(f->output, "TEL;TYPE=phone,pref:%s\n", rfc2426_escape(item->contact->primary_phone)); - if (item->contact->radio_phone != NULL) - fprintf(f->output, "TEL;TYPE=pcs:%s\n", rfc2426_escape(item->contact->radio_phone)); - if (item->contact->telex != NULL) - fprintf(f->output, "TEL;TYPE=bbs:%s\n", rfc2426_escape(item->contact->telex)); - if (item->contact->job_title != NULL) - fprintf(f->output, "TITLE:%s\n", rfc2426_escape(item->contact->job_title)); - if (item->contact->profession != NULL) - fprintf(f->output, "ROLE:%s\n", rfc2426_escape(item->contact->profession)); - if (item->contact->assistant_name != NULL || item->contact->assistant_phone != NULL) { - fprintf(f->output, "AGENT:BEGIN:VCARD\\n"); - if (item->contact->assistant_name != NULL) - fprintf(f->output, "FN:%s\\n", rfc2426_escape(item->contact->assistant_name)); - if (item->contact->assistant_phone != NULL) - fprintf(f->output, "TEL:%s\\n", rfc2426_escape(item->contact->assistant_phone)); - fprintf(f->output, "END:VCARD\\n\n"); - } - if (item->contact->company_name != NULL) - fprintf(f->output, "ORG:%s\n", rfc2426_escape(item->contact->company_name)); - if (item->comment != NULL) - fprintf(f->output, "NOTE:%s\n", rfc2426_escape(item->comment)); - - fprintf(f->output, "VERSION: 3.0\n"); - fprintf(f->output, "END:VCARD\n\n"); - } else { + if (contact_mode == CMODE_VCARD) + write_vcard(f->output, item->contact, item->comment); + else fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1); } - } } else if (item->email != NULL && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { if (mode == MODE_SEPERATE) { @@ -567,324 +377,7 @@ f->email_count++; DEBUG_MAIN(("main: seen an email\n")); - - // convert the sent date if it exists, or set it to a fixed date - if (item->email->sent_date != NULL) { - em_time = fileTimeToUnixTime(item->email->sent_date, 0); - c_time = ctime(&em_time); - if (c_time != NULL) - c_time[strlen(c_time)-1] = '\0'; //remove end \n - else - c_time = "Fri Dec 28 12:06:21 2001"; - } else - c_time= "Fri Dec 28 12:06:21 2001"; - - // if the boundary is still set from the previous run, then free it - if (boundary != NULL) { - free (boundary); - boundary = NULL; - } - - // we will always look at the header to discover some stuff - if (item->email->header != NULL ) { - // see if there is a boundary variable there - // this search MUST be made case insensitive (DONE). - // Also, some check to find out if we - // are looking at the boundary associated with content-type, and that the content - // type really is "multipart" - if ((b2 = my_stristr(item->email->header, "boundary=")) != NULL) { - b2 += strlen("boundary="); // move boundary to first char of marker - - if (*b2 == '"') { - b2++; - b1 = strchr(b2, '"'); // find terminating quote - } else { - b1 = b2; - while (isgraph(*b1)) // find first char that isn't part of boundary - b1++; - } - - boundary = malloc ((b1-b2)+1); //malloc that length - memset (boundary, 0, (b1-b2)+1); // blank it - strncpy(boundary, b2, b1-b2); // copy boundary to another variable - b1 = b2 = boundary; - while (*b2 != '\0') { // remove any CRs and Tabs - if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { - *b1 = *b2; - b1++; - } - b2++; - } - *b1 = '\0'; - - DEBUG_MAIN(("main: Found boundary of - %s\n", boundary)); - } else { - - DEBUG_MAIN(("main: boundary not found in header\n")); - } - - // also possible to set 7bit encoding detection here. - if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:")) != NULL) { - if ((b2 = strchr(b2, ':')) != NULL) { - b2++; // skip to the : at the end of the string - - while (*b2 == ' ' || *b2 == '\t') - b2++; - if (pst_strincmp(b2, "base64", 6)==0) { - DEBUG_MAIN(("body is base64 encoded\n")); - base64_body = 1; - } - } else { - DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); - } - } - - } - - DEBUG_MAIN(("main: About to print Header\n")); - - if (item != NULL && item->email != NULL && item->email->subject != NULL && - item->email->subject->subj != NULL) { - DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); - } - if (item->email->header != NULL) { - // some of the headers we get from the file are not properly defined. - // they can contain some email stuff too. We will cut off the header - // when we see a \n\n or \r\n\r\n - - removeCR(item->email->header); - - temp = strstr(item->email->header, "\n\n"); - - if (temp != NULL) { - DEBUG_MAIN(("main: Found body text in header\n")); - *temp = '\0'; - } - - if (mode != MODE_SEPERATE) { - char *soh = NULL; // real start of headers. - // don't put rubbish in if we are doing seperate - fprintf(f->output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); - soh = skip_header_prologue(item->email->header); - fprintf(f->output, "%s\n", soh); - } else { - fprintf(f->output, "%s", item->email->header); - } - } else { - //make up our own header! - if (mode != MODE_SEPERATE) { - // don't want this first line for this mode - if (item->email->outlook_sender_name != NULL) { - temp = item->email->outlook_sender_name; - } else { - temp = "(readpst_null)"; - } - fprintf(f->output, "From \"%s\" %s\n", temp, c_time); - } - if ((temp = item->email->outlook_sender) == NULL) - temp = ""; - fprintf(f->output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); - if (item->email->subject != NULL) { - fprintf(f->output, "Subject: %s\n", item->email->subject->subj); - } else { - fprintf(f->output, "Subject: \n"); - } - fprintf(f->output, "To: %s\n", item->email->sentto_address); - if (item->email->cc_address != NULL) { - fprintf(f->output, "Cc: %s\n", item->email->cc_address); - } - if (item->email->sent_date != NULL) { - c_time = (char*) xmalloc(C_TIME_SIZE); - strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); - fprintf(f->output, "Date: %s\n", c_time); - free(c_time); - } - - fprintf(f->output, "MIME-Version: 1.0\n"); - } - if (boundary == NULL && (item->attach ||(item->email->body && item->email->htmlbody) - || item->email->rtf_compressed || item->email->encrypted_body - || item->email->encrypted_htmlbody)) { - // we need to create a boundary here. - DEBUG_EMAIL(("main: must create own boundary. oh dear.\n")); - boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary - boundary[0] = '\0'; - sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); - DEBUG_EMAIL(("main: created boundary is %s\n", boundary)); - - /* If boundary != NULL, then it'll already be printed with existing - * headers. Otherwise, we generate it here, and print it. - */ - if (item->attach != NULL) { - // write the boundary stuff if we have attachments - fprintf(f->output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", - boundary); - } else if (boundary != NULL) { - // else if we have multipart/alternative then tell it so - fprintf(f->output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", - boundary); - } else if (item->email->htmlbody) { - fprintf(f->output, "Content-type: text/html\n"); - } - } - fprintf(f->output, "\n"); - - DEBUG_MAIN(("main: About to print Body\n")); - - if (item->email->body != NULL) { - if (boundary) { - fprintf(f->output, "\n--%s\n", boundary); - fprintf(f->output, "Content-type: text/plain\n"); - if (base64_body) fprintf(f->output, "Content-Transfer-Encoding: base64\n"); - fprintf(f->output, "\n"); - } - removeCR(item->email->body); - if (base64_body) - write_email_body(f->output, base64_encode(item->email->body, - strlen(item->email->body))); - else - write_email_body(f->output, item->email->body); - } - - if (item->email->htmlbody != NULL) { - if (boundary) { - fprintf(f->output, "\n--%s\n", boundary); - fprintf(f->output, "Content-type: text/html\n"); - if (base64_body) fprintf(f->output, "Content-Transfer-Encoding: base64\n"); - fprintf(f->output, "\n"); - } - removeCR(item->email->htmlbody); - if (base64_body) - write_email_body(f->output, base64_encode(item->email->htmlbody, - strlen(item->email->htmlbody))); - else - write_email_body(f->output, item->email->htmlbody); - } - - attach_num = 0; - - if (item->email->rtf_compressed != NULL) { - DEBUG_MAIN(("Adding RTF body as attachment\n")); - item->current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; - item->current_attach->data = lzfu_decompress(item->email->rtf_compressed); - item->current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); - strcpy(item->current_attach->filename2, RTF_ATTACH_NAME); - item->current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); - strcpy(item->current_attach->mimetype, RTF_ATTACH_TYPE); - memcpy(&(item->current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); - LE32_CPU(item->current_attach->size); - // item->email->rtf_compressed = ; - // attach_num++; - } - if (item->email->encrypted_body || item->email->encrypted_htmlbody) { - // if either the body or htmlbody is encrypted, add them as attachments - if (item->email->encrypted_body) { - DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); - item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; - - item->current_attach->data = item->email->encrypted_body; - item->current_attach->size = item->email->encrypted_body_size; - item->email->encrypted_body = NULL; - } - if (item->email->encrypted_htmlbody) { - DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); - item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; - - item->current_attach->data = item->email->encrypted_htmlbody; - item->current_attach->size = item->email->encrypted_htmlbody_size; - item->email->encrypted_htmlbody = NULL; - } - 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"); - } - base64_body = 0; - // attachments - item->current_attach = item->attach; - while (item->current_attach != NULL) { - DEBUG_MAIN(("main: Attempting Attachment encoding\n")); - if (item->current_attach->data == NULL) { - DEBUG_MAIN(("main: Data of attachment is NULL!. Size is supposed to be %i\n", item->current_attach->size)); - } - if (mode == MODE_SEPERATE) { - f->name = check_filename(f->name); - if (item->current_attach->filename2 == NULL) { - temp = xmalloc(strlen(f->name)+15); - sprintf(temp, "%s-attach%i", f->name, attach_num); - } else { - temp = xmalloc(strlen(f->name)+strlen(item->current_attach->filename2)+15); - fp = NULL; x=0; - do { - if (fp != NULL) fclose(fp); - if (x == 0) - sprintf(temp, "%s-%s", f->name, item->current_attach->filename2); - else - sprintf(temp, "%s-%s-%i", f->name, item->current_attach->filename2, x); - } while ((fp = fopen(temp, "r"))!=NULL && ++x < 99999999); - if (x > 99999999) { - DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); - } - } - DEBUG_MAIN(("main: Saving attachment to %s\n", temp)); - if ((fp = fopen(temp, "w")) == NULL) { - WARN(("main: Cannot open attachment save file \"%s\"\n", temp)); - } else { - if (item->current_attach->data != NULL) - fwrite(item->current_attach->data, 1, item->current_attach->size, fp); - else { - pst_attach_to_file(&pstfile, item->current_attach, fp); - } - fclose(fp); - } - } else { - DEBUG_MAIN(("main: Attachment Size is %i\n", item->current_attach->size)); - DEBUG_MAIN(("main: Attachment Pointer is %p\n", item->current_attach->data)); - if (item->current_attach->data != NULL) { - if ((enc = base64_encode (item->current_attach->data, item->current_attach->size)) == NULL) { - DEBUG_MAIN(("main: ERROR base64_encode returned NULL. Must have failed\n")); - item->current_attach = item->current_attach->next; - continue; - } - } - if (boundary) { - fprintf(f->output, "\n--%s\n", boundary); - if (item->current_attach->mimetype == NULL) { - fprintf(f->output, "Content-type: %s\n", MIME_TYPE_DEFAULT); - } else { - fprintf(f->output, "Content-type: %s\n", item->current_attach->mimetype); - } - fprintf(f->output, "Content-transfer-encoding: base64\n"); - if (item->current_attach->filename2 == NULL) { - fprintf(f->output, "Content-Disposition: inline\n\n"); - } else { - fprintf(f->output, "Content-Disposition: attachment; filename=\"%s\"\n\n", - item->current_attach->filename2); - } - } - if (item->current_attach->data != NULL) { - fwrite(enc, 1, strlen(enc), f->output); - DEBUG_MAIN(("Attachment Size after encoding is %i\n", strlen(enc))); - } else { - pst_attach_to_file_base64(&pstfile, item->current_attach, f->output); - } - fprintf(f->output, "\n\n"); - } - item->current_attach = item->current_attach->next; - attach_num++; - } - if (mode != MODE_SEPERATE) { - DEBUG_MAIN(("main: Writing buffer between emails\n")); - if (boundary) - fprintf(f->output, "\n--%s--\n", boundary); - fprintf(f->output, "\n\n"); - } + write_normal_email(f->output, f->name, item, mode, mode_MH, &pstfile); } else if (item->type == PST_TYPE_JOURNAL) { // deal with journal items if (mode == MODE_SEPERATE) { @@ -920,60 +413,7 @@ if (f->type != PST_TYPE_APPOINTMENT) { DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); } - fprintf(f->output, "BEGIN:VEVENT\n"); - if (item->create_date != NULL) - fprintf(f->output, "CREATED:%s\n", rfc2445_datetime_format(item->create_date)); - if (item->modify_date != NULL) - fprintf(f->output, "LAST-MOD:%s\n", rfc2445_datetime_format(item->modify_date)); - if (item->email != NULL && item->email->subject != NULL) - fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); - if (item->email != NULL && item->email->body != NULL) - fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); - if (item->appointment != NULL && item->appointment->start != NULL) - fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->start)); - if (item->appointment != NULL && item->appointment->end != NULL) - fprintf(f->output, "DTEND;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->appointment->end)); - if (item->appointment != NULL && item->appointment->location != NULL) - fprintf(f->output, "LOCATION:%s\n", rfc2426_escape(item->appointment->location)); - if (item->appointment != NULL) { - switch (item->appointment->showas) { - case PST_FREEBUSY_TENTATIVE: - fprintf(f->output, "STATUS:TENTATIVE\n"); - break; - case PST_FREEBUSY_FREE: - // mark as transparent and as confirmed - fprintf(f->output, "TRANSP:TRANSPARENT\n"); - case PST_FREEBUSY_BUSY: - case PST_FREEBUSY_OUT_OF_OFFICE: - fprintf(f->output, "STATUS:CONFIRMED\n"); - break; - } - switch (item->appointment->label) { - case PST_APP_LABEL_NONE: - fprintf(f->output, "CATEGORIES:NONE\n"); break; - case PST_APP_LABEL_IMPORTANT: - fprintf(f->output, "CATEGORIES:IMPORTANT\n"); break; - case PST_APP_LABEL_BUSINESS: - fprintf(f->output, "CATEGORIES:BUSINESS\n"); break; - case PST_APP_LABEL_PERSONAL: - fprintf(f->output, "CATEGORIES:PERSONAL\n"); break; - case PST_APP_LABEL_VACATION: - fprintf(f->output, "CATEGORIES:VACATION\n"); break; - case PST_APP_LABEL_MUST_ATTEND: - fprintf(f->output, "CATEGORIES:MUST-ATTEND\n"); break; - case PST_APP_LABEL_TRAVEL_REQ: - fprintf(f->output, "CATEGORIES:TRAVEL-REQUIRED\n"); break; - case PST_APP_LABEL_NEEDS_PREP: - fprintf(f->output, "CATEGORIES:NEEDS-PREPARATION\n"); break; - case PST_APP_LABEL_BIRTHDAY: - fprintf(f->output, "CATEGORIES:BIRTHDAY\n"); break; - case PST_APP_LABEL_ANNIVERSARY: - fprintf(f->output, "CATEGORIES:ANNIVERSARY\n"); break; - case PST_APP_LABEL_PHONE_CALL: - fprintf(f->output, "CATEGORIES:PHONE-CALL\n"); break; - } - } - fprintf(f->output, "END:VEVENT\n\n"); + write_appointment(f->output, item->appointment, item->email, item->create_date, item->modify_date); } else { f->skip_count++; DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", @@ -985,10 +425,6 @@ } DEBUG_MAIN(("main: Going to next d_ptr\n")); - if (boundary) { - free(boundary); - boundary = NULL; - } check_parent: // _pst_freeItem(item); @@ -1102,6 +538,7 @@ printf("\t-d\t- Debug to file. This is a binary log. Use readlog to print it\n"); printf("\t-h\t- Help. This screen\n"); printf("\t-k\t- KMail. Output in kmail format\n"); + printf("\t-M\t- MH. Write emails in the MH format\n"); printf("\t-o\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); printf("\t-q\t- Quiet. Only print error messages\n"); printf("\t-r\t- Recursive. Output in a recursive format\n"); @@ -1233,7 +670,7 @@ if (y == 0) sprintf(dir_name, "%s", dir); else - sprintf(dir_name, "%s%09i", dir, y); // enough for 9 digits allocated above + sprintf(dir_name, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above dir_name = check_filename(dir_name); DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name)); @@ -1290,12 +727,13 @@ return 0; } int mk_seperate_file(struct file_ll *f) { + const int name_offset = 1; DEBUG_ENT("mk_seperate_file"); DEBUG_MAIN(("mk_seperate_file: opening next file to save email\n")); if (f->email_count > 999999999) { // bigger than nine 9's DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); } - sprintf(f->name, "%09i", f->email_count); + sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); if (f->output != NULL) fclose(f->output); f->output = NULL; @@ -1441,3 +879,604 @@ // vim:sw=4 ts=4: // vim600: set foldlevel=0 foldmethod=marker: +void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst) +{ + FILE *fp = NULL; + int x = 0; + char *temp; + + check_filename(f_name); + if (current_attach->filename2 == NULL) { + temp = xmalloc(strlen(f_name)+15); + sprintf(temp, "%s-attach%i", f_name, attach_num); + } else { + temp = xmalloc(strlen(f_name)+strlen(current_attach->filename2)+15); + do { + if (fp != NULL) fclose(fp); + if (x == 0) + sprintf(temp, "%s-%s", f_name, current_attach->filename2); + else + sprintf(temp, "%s-%s-%i", f_name, current_attach->filename2, x); + } while ((fp = fopen(temp, "r"))!=NULL && ++x < 99999999); + if (x > 99999999) { + DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); + } + } + DEBUG_MAIN(("write_separate_attachment: Saving attachment to %s\n", temp)); + if ((fp = fopen(temp, "w")) == NULL) { + WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp)); + } else { + if (current_attach->data != NULL) + fwrite(current_attach->data, 1, current_attach->size, fp); + else { + pst_attach_to_file(pst, current_attach, fp); + } + fclose(fp); + } +} + +void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst) +{ + char *enc; // base64 encoded attachment + DEBUG_MAIN(("write_inline_attachment: Attachment Size is %i\n", item->current_attach->size)); + DEBUG_MAIN(("write_inline_attachment: Attachment Pointer is %p\n", item->current_attach->data)); + if (current_attach->data != NULL) { + if ((enc = base64_encode (current_attach->data, current_attach->size)) == NULL) { + DEBUG_MAIN(("write_inline_attachment: ERROR base64_encode returned NULL. Must have failed\n")); + current_attach = current_attach->next; + return; + } + } + if (boundary) { + fprintf(f_output, "\n--%s\n", boundary); + if (current_attach->mimetype == NULL) { + fprintf(f_output, "Content-type: %s\n", MIME_TYPE_DEFAULT); + } else { + fprintf(f_output, "Content-type: %s\n", current_attach->mimetype); + } + fprintf(f_output, "Content-transfer-encoding: base64\n"); + if (current_attach->filename2 == NULL) { + fprintf(f_output, "Content-Disposition: inline\n\n"); + } else { + fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", + current_attach->filename2); + } + } + if (current_attach->data != NULL) { + fwrite(enc, 1, strlen(enc), f_output); + DEBUG_MAIN(("Attachment Size after encoding is %i\n", strlen(enc))); + } else { + pst_attach_to_file_base64(pst, current_attach, f_output); + } + fprintf(f_output, "\n\n"); +} + +void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst) +{ + char *boundary = NULL; // the boundary marker between multipart sections + char *temp = NULL; + int attach_num, base64_body = 0; + time_t em_time; + char *c_time; + + // convert the sent date if it exists, or set it to a fixed date + if (item->email->sent_date != NULL) { + em_time = fileTimeToUnixTime(item->email->sent_date, 0); + c_time = ctime(&em_time); + if (c_time != NULL) + c_time[strlen(c_time)-1] = '\0'; //remove end \n + else + c_time = "Fri Dec 28 12:06:21 2001"; + } else + c_time= "Fri Dec 28 12:06:21 2001"; + + // we will always look at the header to discover some stuff + if (item->email->header != NULL ) { + char *b1, *b2; + // see if there is a boundary variable there + // this search MUST be made case insensitive (DONE). + // Also, some check to find out if we + // are looking at the boundary associated with content-type, and that the content + // type really is "multipart" + + removeCR(item->email->header); + + if ((b2 = my_stristr(item->email->header, "boundary=")) != NULL) { + b2 += strlen("boundary="); // move boundary to first char of marker + + if (*b2 == '"') { + b2++; + b1 = strchr(b2, '"'); // find terminating quote + } else { + b1 = b2; + while (isgraph(*b1)) // find first char that isn't part of boundary + b1++; + } + + boundary = malloc ((b1-b2)+1); //malloc that length + memset (boundary, 0, (b1-b2)+1); // blank it + strncpy(boundary, b2, b1-b2); // copy boundary to another variable + b1 = b2 = boundary; + while (*b2 != '\0') { // remove any CRs and Tabs + if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { + *b1 = *b2; + b1++; + } + b2++; + } + *b1 = '\0'; + + DEBUG_MAIN(("write_normal_email: Found boundary of - %s\n", boundary)); + } else { + DEBUG_MAIN(("write_normal_email: boundary not found in header\n")); + } + + // also possible to set 7bit encoding detection here. + if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:")) != NULL) { + if ((b2 = strchr(b2, ':')) != NULL) { + b2++; // skip to the : at the end of the string + + while (*b2 == ' ' || *b2 == '\t') + b2++; + if (pst_strincmp(b2, "base64", 6)==0) { + DEBUG_MAIN(("body is base64 encoded\n")); + base64_body = 1; + } + } else { + DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); + } + } + + } + + DEBUG_MAIN(("write_normal_email: About to print Header\n")); + + if (item != NULL && item->email != NULL && item->email->subject != NULL && + item->email->subject->subj != NULL) { + DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); + } + + if (item->email->header != NULL) { + // some of the headers we get from the file are not properly defined. + // they can contain some email stuff too. We will cut off the header + // when we see a \n\n or \r\n\r\n + temp = strstr(item->email->header, "\n\n"); + + if (temp != NULL) { + DEBUG_MAIN(("write_normal_email: Found body text in header\n")); + temp += 2; // get past the \n\n + *temp = '\0'; + } + + if (mode != MODE_SEPERATE) { + char *soh = NULL; // real start of headers. + // don't put rubbish in if we are doing seperate + fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); + soh = skip_header_prologue(item->email->header); + fprintf(f_output, "%s\n\n", soh); + } else { + fprintf(f_output, "%s\n", item->email->header); + } + } else { + //make up our own header! + if (mode != MODE_SEPERATE) { + // don't want this first line for this mode + if (item->email->outlook_sender_name != NULL) { + temp = item->email->outlook_sender_name; + } else { + temp = "(readpst_null)"; + } + fprintf(f_output, "From \"%s\" %s\n", temp, c_time); + } + if ((temp = item->email->outlook_sender) == NULL) + temp = ""; + fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); + if (item->email->subject != NULL) { + fprintf(f_output, "Subject: %s\n", item->email->subject->subj); + } else { + fprintf(f_output, "Subject: \n"); + } + fprintf(f_output, "To: %s\n", item->email->sentto_address); + if (item->email->cc_address != NULL) { + fprintf(f_output, "Cc: %s\n", item->email->cc_address); + } + if (item->email->sent_date != NULL) { + c_time = (char*) xmalloc(C_TIME_SIZE); + strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); + fprintf(f_output, "Date: %s\n", c_time); + free(c_time); + } + + fprintf(f_output, "MIME-Version: 1.0\n"); + } + + if (boundary == NULL && (item->attach ||(item->email->body && item->email->htmlbody) + || item->email->rtf_compressed || item->email->encrypted_body + || item->email->encrypted_htmlbody)) { + // we need to create a boundary here. + DEBUG_EMAIL(("write_normal_email: must create own boundary. oh dear.\n")); + boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary + boundary[0] = '\0'; + sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); + DEBUG_EMAIL(("write_normal_email: created boundary is %s\n", boundary)); + + /* If boundary != NULL, then it has already been printed with existing + * headers. Otherwise we generate it here and print it. + */ + if (item->attach != NULL) { + // write the boundary stuff if we have attachments + fprintf(f_output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", + boundary); + } else if (boundary != NULL) { + // else if we have multipart/alternative then tell it so + fprintf(f_output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", + boundary); + } else if (item->email->htmlbody) { + fprintf(f_output, "Content-type: text/html\n"); + } + } + + fprintf(f_output, "\n"); + + DEBUG_MAIN(("write_normal_email: About to print Body\n")); + + if (item->email->body != NULL) { + if (boundary) { + fprintf(f_output, "\n--%s\n", boundary); + fprintf(f_output, "Content-type: text/plain\n\n"); + if (base64_body) + fprintf(f_output, "Content-Transfer-Encoding: base64\n"); + } + removeCR(item->email->body); + if (base64_body) + write_email_body(f_output, base64_encode(item->email->body, + strlen(item->email->body))); + else + write_email_body(f_output, item->email->body); + } + + if (item->email->htmlbody != NULL) { + if (boundary) { + fprintf(f_output, "\n--%s\n", boundary); + fprintf(f_output, "Content-type: text/html\n\n"); + if (base64_body) + fprintf(f_output, "Content-Transfer-Encoding: base64\n"); + } + removeCR(item->email->htmlbody); + if (base64_body) + write_email_body(f_output, base64_encode(item->email->htmlbody, + strlen(item->email->htmlbody))); + else + write_email_body(f_output, item->email->htmlbody); + } + + if (item->email->rtf_compressed != NULL) { + DEBUG_MAIN(("Adding RTF body as attachment\n")); + item->current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); + memset(item->current_attach, 0, sizeof(pst_item_attach)); + item->current_attach->next = item->attach; + item->attach = item->current_attach; + item->current_attach->data = lzfu_decompress(item->email->rtf_compressed); + item->current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); + strcpy(item->current_attach->filename2, RTF_ATTACH_NAME); + item->current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); + strcpy(item->current_attach->mimetype, RTF_ATTACH_TYPE); + memcpy(&(item->current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); + LE32_CPU(item->current_attach->size); + // item->email->rtf_compressed = ; + // attach_num++; + } + if (item->email->encrypted_body || item->email->encrypted_htmlbody) { + // if either the body or htmlbody is encrypted, add them as attachments + if (item->email->encrypted_body) { + DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); + item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(item->current_attach, 0, sizeof(pst_item_attach)); + item->current_attach->next = item->attach; + item->attach = item->current_attach; + + item->current_attach->data = item->email->encrypted_body; + item->current_attach->size = item->email->encrypted_body_size; + item->email->encrypted_body = NULL; + } + if (item->email->encrypted_htmlbody) { + DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); + item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(item->current_attach, 0, sizeof(pst_item_attach)); + item->current_attach->next = item->attach; + item->attach = item->current_attach; + + item->current_attach->data = item->email->encrypted_htmlbody; + item->current_attach->size = item->email->encrypted_htmlbody_size; + item->email->encrypted_htmlbody = NULL; + } + 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"); + } + // attachments + attach_num = 0; + for(item->current_attach = item->attach; + item->current_attach; + item->current_attach = item->current_attach->next) { + DEBUG_MAIN(("write_normal_email: Attempting Attachment encoding\n")); + if (item->current_attach->data == NULL) { + DEBUG_MAIN(("write_normal_email: Data of attachment is NULL!. Size is supposed to be %i\n", item->current_attach->size)); + } + attach_num++; + if (mode == MODE_SEPERATE && !mode_MH) + write_separate_attachment(f_name, item->current_attach, attach_num, pst); + else + write_inline_attachment(f_output, item->current_attach, boundary, pst); + } + if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */ + DEBUG_MAIN(("write_normal_email: Writing buffer between emails\n")); + if (boundary) + fprintf(f_output, "\n--%s--\n", boundary); + fprintf(f_output, "\n\n"); + } + if (boundary) + free (boundary); +} + +void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]) +{ + // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile + fprintf(f_output, "BEGIN:VCARD\n"); + fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->fullname)); + fprintf(f_output, "N:%s;%s;%s;%s;%s\n", + rfc2426_escape((contact->surname==NULL?"":contact->surname)), + rfc2426_escape((contact->first_name==NULL?"":contact->first_name)), + rfc2426_escape((contact->middle_name==NULL?"":contact->middle_name)), + rfc2426_escape((contact->display_name_prefix==NULL?"":contact->display_name_prefix)), + rfc2426_escape((contact->suffix==NULL?"":contact->suffix))); + if (contact->nickname != NULL) + fprintf(f_output, "NICKNAME:%s\n", rfc2426_escape(contact->nickname)); + if (contact->address1 != NULL) + fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address1)); + if (contact->address2 != NULL) + fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address2)); + if (contact->address3 != NULL) + fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address3)); + if (contact->birthday != NULL) + fprintf(f_output, "BDAY:%s\n", rfc2425_datetime_format(contact->birthday)); + if (contact->home_address != NULL) { + fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", + rfc2426_escape((contact->home_po_box!=NULL?contact->home_po_box:"")), + "", // extended Address + rfc2426_escape((contact->home_street!=NULL?contact->home_street:"")), + rfc2426_escape((contact->home_city!=NULL?contact->home_city:"")), + rfc2426_escape((contact->home_state!=NULL?contact->home_state:"")), + rfc2426_escape((contact->home_postal_code!=NULL?contact->home_postal_code:"")), + rfc2426_escape((contact->home_country!=NULL?contact->home_country:""))); + fprintf(f_output, "LABEL;TYPE=home:%s\n", rfc2426_escape(contact->home_address)); + } + if (contact->business_address != NULL) { + fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", + rfc2426_escape((contact->business_po_box!=NULL?contact->business_po_box:"")), + "", // extended Address + rfc2426_escape((contact->business_street!=NULL?contact->business_street:"")), + rfc2426_escape((contact->business_city!=NULL?contact->business_city:"")), + rfc2426_escape((contact->business_state!=NULL?contact->business_state:"")), + rfc2426_escape((contact->business_postal_code!=NULL?contact->business_postal_code:"")), + rfc2426_escape((contact->business_country!=NULL?contact->business_country:""))); + fprintf(f_output, "LABEL;TYPE=work:%s\n", rfc2426_escape(contact->business_address)); + } + if (contact->other_address != NULL) { + fprintf(f_output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", + rfc2426_escape((contact->other_po_box != NULL ? + contact->business_po_box:"")), + "", // extended Address + rfc2426_escape((contact->other_street != NULL ? + contact->other_street:"")), + rfc2426_escape((contact->other_city != NULL ? + contact->other_city:"")), + rfc2426_escape((contact->other_state != NULL ? + contact->other_state:"")), + rfc2426_escape((contact->other_postal_code != NULL ? + contact->other_postal_code:"")), + rfc2426_escape((contact->other_country != NULL ? + contact->other_country:""))); + fprintf(f_output, "ADR;TYPE=postal:%s\n", + rfc2426_escape(contact->other_address)); + } + if (contact->business_fax != NULL) + fprintf(f_output, "TEL;TYPE=work,fax:%s\n", + rfc2426_escape(contact->business_fax)); + if (contact->business_phone != NULL) + fprintf(f_output, "TEL;TYPE=work,voice:%s\n", + rfc2426_escape(contact->business_phone)); + if (contact->business_phone2 != NULL) + fprintf(f_output, "TEL;TYPE=work,voice:%s\n", + rfc2426_escape(contact->business_phone2)); + if (contact->car_phone != NULL) + fprintf(f_output, "TEL;TYPE=car,voice:%s\n", + rfc2426_escape(contact->car_phone)); + if (contact->home_fax != NULL) + fprintf(f_output, "TEL;TYPE=home,fax:%s\n", + rfc2426_escape(contact->home_fax)); + if (contact->home_phone != NULL) + fprintf(f_output, "TEL;TYPE=home,voice:%s\n", + rfc2426_escape(contact->home_phone)); + if (contact->home_phone2 != NULL) + fprintf(f_output, "TEL;TYPE=home,voice:%s\n", + rfc2426_escape(contact->home_phone2)); + if (contact->isdn_phone != NULL) + fprintf(f_output, "TEL;TYPE=isdn:%s\n", + rfc2426_escape(contact->isdn_phone)); + if (contact->mobile_phone != NULL) + fprintf(f_output, "TEL;TYPE=cell,voice:%s\n", + rfc2426_escape(contact->mobile_phone)); + if (contact->other_phone != NULL) + fprintf(f_output, "TEL;TYPE=msg:%s\n", + rfc2426_escape(contact->other_phone)); + if (contact->pager_phone != NULL) + fprintf(f_output, "TEL;TYPE=pager:%s\n", + rfc2426_escape(contact->pager_phone)); + if (contact->primary_fax != NULL) + fprintf(f_output, "TEL;TYPE=fax,pref:%s\n", + rfc2426_escape(contact->primary_fax)); + if (contact->primary_phone != NULL) + fprintf(f_output, "TEL;TYPE=phone,pref:%s\n", + rfc2426_escape(contact->primary_phone)); + if (contact->radio_phone != NULL) + fprintf(f_output, "TEL;TYPE=pcs:%s\n", + rfc2426_escape(contact->radio_phone)); + if (contact->telex != NULL) + fprintf(f_output, "TEL;TYPE=bbs:%s\n", + rfc2426_escape(contact->telex)); + if (contact->job_title != NULL) + fprintf(f_output, "TITLE:%s\n", + rfc2426_escape(contact->job_title)); + if (contact->profession != NULL) + fprintf(f_output, "ROLE:%s\n", + rfc2426_escape(contact->profession)); + if (contact->assistant_name != NULL + || contact->assistant_phone != NULL) { + fprintf(f_output, "AGENT:BEGIN:VCARD\\n"); + if (contact->assistant_name != NULL) + fprintf(f_output, "FN:%s\\n", + rfc2426_escape(contact->assistant_name)); + if (contact->assistant_phone != NULL) + fprintf(f_output, "TEL:%s\\n", + rfc2426_escape(contact->assistant_phone)); + } + if (contact->company_name != NULL) + fprintf(f_output, "ORG:%s\n", + rfc2426_escape(contact->company_name)); + if (comment != NULL) + fprintf(f_output, "NOTE:%s\n", rfc2426_escape(comment)); + + fprintf(f_output, "VERSION: 3.0\n"); + fprintf(f_output, "END:VCARD\n\n"); +} + +void write_appointment(FILE* f_output, pst_item_appointment* appointment, + pst_item_email* email, FILETIME* create_date, FILETIME* modify_date) +{ + fprintf(f_output, "BEGIN:VEVENT\n"); + if (create_date != NULL) + fprintf(f_output, "CREATED:%s\n", + rfc2445_datetime_format(create_date)); + if (modify_date != NULL) + fprintf(f_output, "LAST-MOD:%s\n", + rfc2445_datetime_format(modify_date)); + if (email != NULL && email->subject != NULL) + fprintf(f_output, "SUMMARY:%s\n", + rfc2426_escape(email->subject->subj)); + if (email != NULL && email->body != NULL) + fprintf(f_output, "DESCRIPTION:%s\n", + rfc2426_escape(email->body)); + if (appointment != NULL && appointment->start != NULL) + fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", + rfc2445_datetime_format(appointment->start)); + if (appointment != NULL && appointment->end != NULL) + fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n", + rfc2445_datetime_format(appointment->end)); + if (appointment != NULL && appointment->location != NULL) + fprintf(f_output, "LOCATION:%s\n", + rfc2426_escape(appointment->location)); + if (appointment != NULL) { + switch (appointment->showas) { + case PST_FREEBUSY_TENTATIVE: + fprintf(f_output, "STATUS:TENTATIVE\n"); + break; + case PST_FREEBUSY_FREE: + // mark as transparent and as confirmed + fprintf(f_output, "TRANSP:TRANSPARENT\n"); + case PST_FREEBUSY_BUSY: + case PST_FREEBUSY_OUT_OF_OFFICE: + fprintf(f_output, "STATUS:CONFIRMED\n"); + break; + } + switch (appointment->label) { + case PST_APP_LABEL_NONE: + fprintf(f_output, "CATEGORIES:NONE\n"); + break; + case PST_APP_LABEL_IMPORTANT: + fprintf(f_output, "CATEGORIES:IMPORTANT\n"); + break; + case PST_APP_LABEL_BUSINESS: + fprintf(f_output, "CATEGORIES:BUSINESS\n"); + break; + case PST_APP_LABEL_PERSONAL: + fprintf(f_output, "CATEGORIES:PERSONAL\n"); + break; + case PST_APP_LABEL_VACATION: + fprintf(f_output, "CATEGORIES:VACATION\n"); + break; + case PST_APP_LABEL_MUST_ATTEND: + fprintf(f_output, "CATEGORIES:MUST-ATTEND\n"); + break; + case PST_APP_LABEL_TRAVEL_REQ: + fprintf(f_output, "CATEGORIES:TRAVEL-REQUIRED\n"); + break; + case PST_APP_LABEL_NEEDS_PREP: + fprintf(f_output, "CATEGORIES:NEEDS-PREPARATION\n"); + break; + case PST_APP_LABEL_BIRTHDAY: + fprintf(f_output, "CATEGORIES:BIRTHDAY\n"); + break; + case PST_APP_LABEL_ANNIVERSARY: + fprintf(f_output, "CATEGORIES:ANNIVERSARY\n"); + break; + case PST_APP_LABEL_PHONE_CALL: + fprintf(f_output, "CATEGORIES:PHONE-CALL\n"); + break; + } + } + fprintf(f_output, "END:VEVENT\n\n"); +} + +void create_enter_dir(struct file_ll* f, char file_as[], int mode, int overwrite) +{ + if (mode == MODE_KMAIL) + f->name = mk_kmail_dir(file_as); //create directory and form filename + else if (mode == MODE_RECURSE) + f->name = mk_recurse_dir(file_as); + else if (mode == MODE_SEPERATE) { + // do similar stuff to recurse here. + mk_seperate_dir(file_as, overwrite); + f->name = (char*) xmalloc(10); + memset(f->name, 0, 10); + // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count); + } else { + f->name = (char*) xmalloc(strlen(file_as)+strlen(OUTPUT_TEMPLATE+1)); + sprintf(f->name, OUTPUT_TEMPLATE, file_as); + } + + f->dname = (char*) xmalloc(strlen(file_as)+1); + strcpy(f->dname, file_as); + + if (overwrite != 1) { + int x = 0; + char *temp = (char*) xmalloc (strlen(f->name)+10); //enough room for 10 digits + + sprintf(temp, "%s", f->name); + temp = check_filename(temp); + while ((f->output = fopen(temp, "r")) != NULL) { + DEBUG_MAIN(("create_enter_dir: need to increase filename cause one already exists with that name\n")); + DEBUG_MAIN(("create_enter_dir: - increasing it to %s%d\n", f->name, x)); + x++; + sprintf(temp, "%s%08d", f->name, x); + DEBUG_MAIN(("create_enter_dir: - trying \"%s\"\n", f->name)); + if (x == 99999999) { + DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); + } + fclose(f->output); + } + if (x > 0) { //then the f->name should change + free (f->name); + f->name = temp; + } else { + free(temp); + } + } + + DEBUG_MAIN(("create_enter_dir: f->name = %s\nitem->folder_name = %s\n", f->name, file_as)); + if (mode != MODE_SEPERATE) { + f->name = check_filename(f->name); + if ((f->output = fopen(f->name, "w")) == NULL) { + DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name)); + } + } +} +