Mercurial > libpst
diff src/readpst.c @ 167:40e9de445038
improve consistency checking when fetching items from the pst file.
avoid putting mixed item types into the same output folder.
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 18 Mar 2009 22:31:18 -0700 |
parents | ab384fed78c5 |
children | c1a2fd06ffe6 |
line wrap: on
line diff
--- a/src/readpst.c Tue Mar 17 12:14:43 2009 -0700 +++ b/src/readpst.c Wed Mar 18 22:31:18 2009 -0700 @@ -21,7 +21,7 @@ char *dname; FILE * output; int32_t stored_count; - int32_t email_count; + int32_t item_count; int32_t skip_count; int32_t type; }; @@ -130,99 +130,120 @@ memset(&ff, 0, sizeof(ff)); create_enter_dir(&ff, outeritem); - while (d_ptr) { + for (; d_ptr; d_ptr = d_ptr->next) { DEBUG_MAIN(("main: New item record\n")); if (!d_ptr->desc) { + ff.skip_count++; DEBUG_WARN(("main: ERROR item's desc record is NULL\n")); - ff.skip_count++; + continue; } - else { - DEBUG_MAIN(("main: Desc Email ID %#"PRIx64" [d_ptr->d_id = %#"PRIx64"]\n", d_ptr->desc->i_id, d_ptr->d_id)); + DEBUG_MAIN(("main: Desc Email ID %#"PRIx64" [d_ptr->d_id = %#"PRIx64"]\n", d_ptr->desc->i_id, d_ptr->d_id)); + + item = pst_parse_item(&pstfile, d_ptr, NULL); + DEBUG_MAIN(("main: About to process item\n")); - item = pst_parse_item(&pstfile, d_ptr, NULL); - DEBUG_MAIN(("main: About to process item\n")); - if (item && item->subject.str) { - DEBUG_EMAIL(("item->subject = %s\n", item->subject.str)); - } - if (item) { - if (item->folder && d_ptr->child && item->file_as.str && (deleted_mode == DMODE_INCLUDE || strcasecmp(item->file_as.str, "Deleted Items"))) { - //if this is a non-empty folder other than deleted items, we want to recurse into it - if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as.str); - process(item, d_ptr->child); + if (!item) { + ff.skip_count++; + DEBUG_MAIN(("main: A NULL item was seen\n")); + continue; + } + + if (item->subject.str) { + DEBUG_EMAIL(("item->subject = %s\n", item->subject.str)); + } - } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { - if (mode == MODE_SEPARATE) mk_separate_file(&ff); - ff.email_count++; - DEBUG_MAIN(("main: Processing Contact\n")); - if (ff.type != PST_TYPE_CONTACT) { - DEBUG_MAIN(("main: I have a contact, but the folder type %"PRIi32" isn't a contacts folder. Processing anyway\n", ff.type)); - } - if (contact_mode == CMODE_VCARD) { - pst_convert_utf8_null(item, &item->comment); - write_vcard(ff.output, item, item->contact, item->comment.str); - } - else { - pst_convert_utf8(item, &item->contact->fullname); - pst_convert_utf8(item, &item->contact->address1); - fprintf(ff.output, "%s <%s>\n", item->contact->fullname.str, item->contact->address1.str); - } + if (item->folder && item->file_as.str) { + DEBUG_MAIN(("Processing Folder \"%s\"\n", item->file_as.str)); + if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as.str); + ff.item_count++; + if (d_ptr->child && (deleted_mode == DMODE_INCLUDE || strcasecmp(item->file_as.str, "Deleted Items"))) { + //if this is a non-empty folder other than deleted items, we want to recurse into it + process(item, d_ptr->child); + } - } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { - char *extra_mime_headers = NULL; - if (mode == MODE_SEPARATE) mk_separate_file(&ff); - ff.email_count++; - DEBUG_MAIN(("main: Processing Email\n")); - if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) { - DEBUG_MAIN(("main: I have an email type %"PRIi32", but the folder type %"PRIi32" isn't an email folder. Processing anyway\n", item->type, ff.type)); - } - write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, &extra_mime_headers); + } else if (item->contact && (item->type == PST_TYPE_CONTACT)) { + if (!ff.type) ff.type = item->type; + DEBUG_MAIN(("main: Processing Contact\n")); + if (ff.type != PST_TYPE_CONTACT) { + ff.skip_count++; + DEBUG_MAIN(("main: I have a contact, but the folder type %"PRIi32" isn't a contacts folder. Skipping it\n", ff.type)); + } + else { + ff.item_count++; + if (mode == MODE_SEPARATE) mk_separate_file(&ff); + if (contact_mode == CMODE_VCARD) { + pst_convert_utf8_null(item, &item->comment); + write_vcard(ff.output, item, item->contact, item->comment.str); + } + else { + pst_convert_utf8(item, &item->contact->fullname); + pst_convert_utf8(item, &item->contact->address1); + fprintf(ff.output, "%s <%s>\n", item->contact->fullname.str, item->contact->address1.str); + } + } - } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { - if (mode == MODE_SEPARATE) mk_separate_file(&ff); - ff.email_count++; - DEBUG_MAIN(("main: Processing Journal Entry\n")); - if (ff.type != PST_TYPE_JOURNAL) { - DEBUG_MAIN(("main: I have a journal entry, but the folder type %"PRIi32" isn't a journal folder. Processing anyway\n", ff.type)); - } - fprintf(ff.output, "BEGIN:VJOURNAL\n"); - if (item->subject.str) { - pst_convert_utf8(item, &item->subject); - fprintf(ff.output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); - } - if (item->body.str) { - pst_convert_utf8(item, &item->body); - fprintf(ff.output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->body.str)); - } - if (item->journal->start) - fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start)); - fprintf(ff.output, "END:VJOURNAL\n\n"); + } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { + if (!ff.type) ff.type = item->type; + DEBUG_MAIN(("main: Processing Email\n")); + if ((ff.type != PST_TYPE_NOTE) && (ff.type != PST_TYPE_REPORT)) { + ff.skip_count++; + DEBUG_MAIN(("main: I have an email type %"PRIi32", but the folder type %"PRIi32" isn't an email folder. Skipping it\n", item->type, ff.type)); + } + else { + char *extra_mime_headers = NULL; + ff.item_count++; + if (mode == MODE_SEPARATE) mk_separate_file(&ff); + write_normal_email(ff.output, ff.name, item, mode, mode_MH, &pstfile, save_rtf_body, &extra_mime_headers); + } - } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { - if (mode == MODE_SEPARATE) mk_separate_file(&ff); - ff.email_count++; - DEBUG_MAIN(("main: Processing Appointment Entry\n")); - if (ff.type != PST_TYPE_APPOINTMENT) { - DEBUG_MAIN(("main: I have an appointment, but folder type %"PRIi32" isn't an appointment folder. Processing anyway\n", ff.type)); - } - write_appointment(ff.output, item, item->appointment, item->create_date, item->modify_date); - - } else if (item->message_store) { - // there should only be one message_store, and we have already done it - DEBUG_MAIN(("item with message store content, type %i %s folder type %i, skipping it\n", item->type, item->ascii_type, ff.type)); + } else if (item->journal && (item->type == PST_TYPE_JOURNAL)) { + if (!ff.type) ff.type = item->type; + DEBUG_MAIN(("main: Processing Journal Entry\n")); + if (ff.type != PST_TYPE_JOURNAL) { + ff.skip_count++; + DEBUG_MAIN(("main: I have a journal entry, but the folder type %"PRIi32" isn't a journal folder. Skipping it\n", ff.type)); + } + else { + ff.item_count++; + if (mode == MODE_SEPARATE) mk_separate_file(&ff); + fprintf(ff.output, "BEGIN:VJOURNAL\n"); + if (item->subject.str) { + pst_convert_utf8(item, &item->subject); + fprintf(ff.output, "SUMMARY:%s\n", pst_rfc2426_escape(item->subject.str)); + } + if (item->body.str) { + pst_convert_utf8(item, &item->body); + fprintf(ff.output, "DESCRIPTION:%s\n", pst_rfc2426_escape(item->body.str)); + } + if (item->journal->start) + fprintf(ff.output, "DTSTART;VALUE=DATE-TIME:%s\n", pst_rfc2445_datetime_format(item->journal->start)); + fprintf(ff.output, "END:VJOURNAL\n\n"); + } - } else { - // these all seem to be things that MS agrees are not included in the item count - //ff.skip_count++; - DEBUG_MAIN(("main: Unknown item type %i (%s) name (%s)\n", - item->type, item->ascii_type, item->file_as.str)); - } - pst_freeItem(item); - } else { + } else if (item->appointment && (item->type == PST_TYPE_APPOINTMENT)) { + if (!ff.type) ff.type = item->type; + DEBUG_MAIN(("main: Processing Appointment Entry\n")); + if (ff.type != PST_TYPE_APPOINTMENT) { ff.skip_count++; - DEBUG_MAIN(("main: A NULL item was seen\n")); + DEBUG_MAIN(("main: I have an appointment, but the folder type %"PRIi32" isn't an appointment folder. Skipping it\n", ff.type)); + } + else { + ff.item_count++; + if (mode == MODE_SEPARATE) mk_separate_file(&ff); + write_appointment(ff.output, item, item->appointment, item->create_date, item->modify_date); } - d_ptr = d_ptr->next; + + } else if (item->message_store) { + // there should only be one message_store, and we have already done it + ff.skip_count++; + DEBUG_MAIN(("item with message store content, type %i %s folder type %i, skipping it\n", item->type, item->ascii_type, ff.type)); + + } else { + ff.skip_count++; + DEBUG_MAIN(("main: Unknown item type %i (%s) name (%s)\n", + item->type, item->ascii_type, item->file_as.str)); } + pst_freeItem(item); } close_enter_dir(&ff); DEBUG_RET(); @@ -665,10 +686,10 @@ const int name_offset = 1; DEBUG_ENT("mk_separate_file"); DEBUG_MAIN(("opening next file to save email\n")); - if (f->email_count > 999999999) { // bigger than nine 9's + if (f->item_count > 999999999) { // bigger than nine 9's DIE(("mk_separate_file: The number of emails in this folder has become too high to handle")); } - sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); + sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->item_count + name_offset); if (f->output) fclose(f->output); f->output = NULL; check_filename(f->name); @@ -732,7 +753,7 @@ : attach->filename1.str; DEBUG_ENT("write_separate_attachment"); - if (!attach->data) { + if (!attach->data.data) { // make sure we can fetch data from the id pst_index_ll *ptr = pst_getID(pst, attach->i_id); if (!ptr) { @@ -765,8 +786,8 @@ if (!(fp = fopen(temp, "w"))) { WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp)); } else { - if (attach->data) - pst_fwrite(attach->data, (size_t)1, attach->size, fp); + if (attach->data.data) + pst_fwrite(attach->data.data, (size_t)1, attach->data.size, fp); else { (void)pst_attach_to_file(pst, attach, fp); } @@ -810,9 +831,9 @@ char *attach_filename; char *enc = NULL; // base64 encoded attachment DEBUG_ENT("write_inline_attachment"); - DEBUG_EMAIL(("Attachment Size is %"PRIu64", id %#"PRIx64"\n", (uint64_t)attach->size, attach->i_id)); - if (attach->data) { - enc = base64_encode (attach->data, attach->size); + DEBUG_EMAIL(("Attachment Size is %"PRIu64", id %#"PRIx64"\n", (uint64_t)attach->data.size, attach->i_id)); + if (attach->data.data) { + enc = base64_encode (attach->data.data, attach->data.size); if (!enc) { DEBUG_EMAIL(("ERROR base64_encode returned NULL. Must have failed\n")); DEBUG_RET(); @@ -846,7 +867,7 @@ fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", attach_filename); } - if (attach->data) { + if (attach->data.data) { pst_fwrite(enc, 1, strlen(enc), f_output); DEBUG_EMAIL(("Attachment Size after encoding is %i\n", strlen(enc))); free(enc); // caught by valgrind @@ -1256,9 +1277,9 @@ // multipart/report for DSN/MDN reports fprintf(f_output, "Content-Type: multipart/report; report-type=%s;\n\tboundary=\"%s\"\n", body_report, boundary); } - else if (item->attach || (item->email->rtf_compressed && save_rtf) - || item->email->encrypted_body - || item->email->encrypted_htmlbody) { + else if (item->attach || (item->email->rtf_compressed.data && save_rtf) + || item->email->encrypted_body.data + || item->email->encrypted_htmlbody.data) { // use multipart/mixed if we have attachments fprintf(f_output, "Content-Type: multipart/mixed;\n\tboundary=\"%s\"\n", boundary); } else { @@ -1282,43 +1303,43 @@ write_body_part(f_output, &item->email->htmlbody, "text/html", body_charset, boundary, pst); } - if (item->email->rtf_compressed && save_rtf) { + if (item->email->rtf_compressed.data && save_rtf) { pst_item_attach* attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); DEBUG_EMAIL(("Adding RTF body as attachment\n")); memset(attach, 0, sizeof(pst_item_attach)); attach->next = item->attach; item->attach = attach; - attach->data = lzfu_decompress(item->email->rtf_compressed, item->email->rtf_compressed_size, &attach->size); + attach->data.data = lzfu_decompress(item->email->rtf_compressed.data, item->email->rtf_compressed.size, &attach->data.size); attach->filename2.str = strdup(RTF_ATTACH_NAME); attach->filename2.is_utf8 = 1; attach->mimetype.str = strdup(RTF_ATTACH_TYPE); attach->mimetype.is_utf8 = 1; } - if (item->email->encrypted_body || item->email->encrypted_htmlbody) { + if (item->email->encrypted_body.data || item->email->encrypted_htmlbody.data) { // if either the body or htmlbody is encrypted, add them as attachments - if (item->email->encrypted_body) { + if (item->email->encrypted_body.data) { pst_item_attach* attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); DEBUG_EMAIL(("Adding Encrypted Body as attachment\n")); attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); memset(attach, 0, sizeof(pst_item_attach)); attach->next = item->attach; item->attach = attach; - attach->data = item->email->encrypted_body; - attach->size = item->email->encrypted_body_size; - item->email->encrypted_body = NULL; + attach->data.data = item->email->encrypted_body.data; + attach->data.size = item->email->encrypted_body.size; + item->email->encrypted_body.data = NULL; } - if (item->email->encrypted_htmlbody) { + if (item->email->encrypted_htmlbody.data) { pst_item_attach* attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); DEBUG_EMAIL(("Adding encrypted HTML body as attachment\n")); attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); memset(attach, 0, sizeof(pst_item_attach)); attach->next = item->attach; item->attach = attach; - attach->data = item->email->encrypted_htmlbody; - attach->size = item->email->encrypted_htmlbody_size; - item->email->encrypted_htmlbody = NULL; + attach->data.data = item->email->encrypted_htmlbody.data; + attach->data.size = item->email->encrypted_htmlbody.size; + item->email->encrypted_htmlbody.data = 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"); } @@ -1332,12 +1353,12 @@ pst_convert_utf8_null(item, &attach->filename2); pst_convert_utf8_null(item, &attach->mimetype); DEBUG_EMAIL(("Attempting Attachment encoding\n")); - if (!attach->data && attach->mimetype.str && !strcmp(attach->mimetype.str, RFC822)) { + if (!attach->data.data && attach->mimetype.str && !strcmp(attach->mimetype.str, RFC822)) { DEBUG_EMAIL(("seem to have special embedded message attachment\n")); find_rfc822_headers(extra_mime_headers); write_embedded_message(f_output, attach, boundary, pst, extra_mime_headers); } - else if (attach->data || attach->i_id) { + else if (attach->data.data || attach->i_id) { if (mode == MODE_SEPARATE && !mode_MH) write_separate_attachment(f_name, attach, ++attach_num, pst); else @@ -1585,10 +1606,10 @@ void create_enter_dir(struct file_ll* f, pst_item *item) { pst_convert_utf8(item, &item->file_as); - f->email_count = 0; + f->item_count = 0; f->skip_count = 0; f->type = item->type; - f->stored_count = (item->folder) ? item->folder->email_count : 0; + f->stored_count = (item->folder) ? item->folder->item_count : 0; DEBUG_ENT("create_enter_dir"); if (mode == MODE_KMAIL) @@ -1600,7 +1621,6 @@ mk_separate_dir(item->file_as.str); 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(item->file_as.str)+strlen(OUTPUT_TEMPLATE)+1); sprintf(f->name, OUTPUT_TEMPLATE, item->file_as.str); @@ -1647,10 +1667,10 @@ void close_enter_dir(struct file_ll *f) { - DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); + DEBUG_MAIN(("main: processed item count for folder %s is %i, skipped %i, total %i \n", + f->dname, f->item_count, f->skip_count, f->stored_count)); if (output_mode != OUTPUT_QUIET) - printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", - f->dname, f->email_count, f->skip_count, f->stored_count); + printf("\t\"%s\" - %i items done.\n", f->dname, f->item_count); if (f->output) fclose(f->output); free(f->name); free(f->dname);