# HG changeset patch # User Carl Byington # Date 1260549930 28800 # Node ID 67b24d6a45d6d31ac49ddd4ef4117959c30975d2 # Parent fa4042b0a566d39e6d3825f36b49842ee1916103 patch from Hugo DesRosiers to export categories and notes into vcards. extend that patch to export categories into vcalendar appointments also. diff -r fa4042b0a566 -r 67b24d6a45d6 AUTHORS --- a/AUTHORS Sun Sep 20 11:29:48 2009 -0700 +++ b/AUTHORS Fri Dec 11 08:45:30 2009 -0800 @@ -31,6 +31,7 @@ Chris White Roberto Polli Lee Ayres + Hugo DesRosiers Testing team: diff -r fa4042b0a566 -r 67b24d6a45d6 ChangeLog --- a/ChangeLog Sun Sep 20 11:29:48 2009 -0700 +++ b/ChangeLog Fri Dec 11 08:45:30 2009 -0800 @@ -1,3 +1,8 @@ +LibPST 0.6.45 (2009-11-18) +=============================== + * patch from Hugo DesRosiers to export categories and notes into vcards. + * extend that patch to export categories into vcalendar appointments also. + LibPST 0.6.44 (2009-09-20) =============================== * fix --help usage; readpstlog is gone, debug files are now ascii text. diff -r fa4042b0a566 -r 67b24d6a45d6 NEWS --- a/NEWS Sun Sep 20 11:29:48 2009 -0700 +++ b/NEWS Fri Dec 11 08:45:30 2009 -0800 @@ -1,3 +1,4 @@ +0.6.45 2009-11-18 patch from Hugo DesRosiers to export categories and notes into vcards 0.6.44 2009-09-20 patch from Lee Ayres to add file name extensions in separate mode 0.6.43 2009-09-12 patches from Justin Greer, Chris White, Roberto Polli; better rfc822 embedded message decoding 0.6.42 2009-09-03 patch from Fridrich Strba to build with DJGPP DOS cross-compiler diff -r fa4042b0a566 -r 67b24d6a45d6 configure.in --- a/configure.in Sun Sep 20 11:29:48 2009 -0700 +++ b/configure.in Fri Dec 11 08:45:30 2009 -0800 @@ -1,5 +1,5 @@ AC_PREREQ(2.59) -AC_INIT(libpst,0.6.44,carl@five-ten-sg.com) +AC_INIT(libpst,0.6.45,carl@five-ten-sg.com) AC_CONFIG_SRCDIR([src/libpst.c]) AC_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE diff -r fa4042b0a566 -r 67b24d6a45d6 libpst.spec.in --- a/libpst.spec.in Sun Sep 20 11:29:48 2009 -0700 +++ b/libpst.spec.in Fri Dec 11 08:45:30 2009 -0800 @@ -146,6 +146,10 @@ %changelog +* Wed Nov 18 2009 Carl Byington - 0.6.45-1 +- patch from Hugo DesRosiers to export categories and notes into vcards. +- extend that patch to export categories into vcalendar appointments also. + * Sun Sep 20 2009 Carl Byington - 0.6.44-1 - patch from Lee Ayres to add file name extensions in separate mode. - allow mixed items types in a folder in separate mode. diff -r fa4042b0a566 -r 67b24d6a45d6 src/define.h --- a/src/define.h Sun Sep 20 11:29:48 2009 -0700 +++ b/src/define.h Fri Dec 11 08:45:30 2009 -0800 @@ -165,12 +165,12 @@ #define DEBUG_HEXDUMPC(x, s, c) pst_debug_hexdump(__LINE__, __FILE__, (char*)x, s, c, 0) -# define DEBUG_ENT(x) \ +#define DEBUG_ENT(x) \ { \ pst_debug_func(x); \ pst_debug(__LINE__, __FILE__, "Entering function\n"); \ } -# define DEBUG_RET() \ +#define DEBUG_RET() \ { \ pst_debug(__LINE__, __FILE__, "Leaving function\n"); \ pst_debug_func_ret(); \ diff -r fa4042b0a566 -r 67b24d6a45d6 src/libpst.c --- a/src/libpst.c Sun Sep 20 11:29:48 2009 -0700 +++ b/src/libpst.c Fri Dec 11 08:45:30 2009 -0800 @@ -1880,7 +1880,7 @@ LIST_COPY(targ, (char*)) \ } \ else { \ - DEBUG_WARN(("src not 0x1e or 0x1f or 0x102 for string dst\n")); \ + DEBUG_WARN(("src not 0x1e or 0x1f or 0x102 for string dst\n")); \ DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ SAFE_FREE(targ); \ targ = NULL; \ @@ -1889,14 +1889,14 @@ #define LIST_COPY_BOOL(label, targ) { \ if (list->elements[x]->type != 0x0b) { \ - DEBUG_WARN(("src not 0x0b for boolean dst\n")); \ + DEBUG_WARN(("src not 0x0b for boolean dst\n")); \ DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ } \ if (*(int16_t*)list->elements[x]->data) { \ - DEBUG_INFO((label" - True\n")); \ + DEBUG_INFO((label" - True\n")); \ targ = 1; \ } else { \ - DEBUG_INFO((label" - False\n")); \ + DEBUG_INFO((label" - False\n")); \ targ = 0; \ } \ } @@ -1918,7 +1918,7 @@ #define LIST_COPY_INT16_N(targ) { \ if (list->elements[x]->type != 0x02) { \ - DEBUG_WARN(("src not 0x02 for int16 dst\n")); \ + DEBUG_WARN(("src not 0x02 for int16 dst\n")); \ DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ } \ memcpy(&(targ), list->elements[x]->data, sizeof(targ)); \ @@ -1927,12 +1927,12 @@ #define LIST_COPY_INT16(label, targ) { \ LIST_COPY_INT16_N(targ); \ - DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \ + DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \ } #define LIST_COPY_INT32_N(targ) { \ if (list->elements[x]->type != 0x03) { \ - DEBUG_WARN(("src not 0x03 for int32 dst\n")); \ + DEBUG_WARN(("src not 0x03 for int32 dst\n")); \ DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ } \ memcpy(&(targ), list->elements[x]->data, sizeof(targ)); \ @@ -1941,7 +1941,7 @@ #define LIST_COPY_INT32(label, targ) { \ LIST_COPY_INT32_N(targ); \ - DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \ + DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \ } #define LIST_COPY_EMAIL_INT32(label, targ) { \ @@ -1968,7 +1968,7 @@ char *tlabels[] = {__VA_ARGS__}; \ LIST_COPY_INT32_N(targ); \ targ += delta; \ - DEBUG_INFO((label" - %s [%i]\n", \ + DEBUG_INFO((label" - %s [%i]\n", \ (((int)targ < 0) || ((int)targ >= count)) \ ? "**invalid" \ : tlabels[(int)targ], (int)targ)); \ @@ -1988,7 +1988,7 @@ char *tlabels[] = {__VA_ARGS__}; \ LIST_COPY_INT16_N(targ); \ targ += delta; \ - DEBUG_INFO((label" - %s [%i]\n", \ + DEBUG_INFO((label" - %s [%i]\n", \ (((int)targ < 0) || ((int)targ >= count)) \ ? "**invalid" \ : tlabels[(int)targ], (int)targ)); \ @@ -2003,7 +2003,7 @@ LIST_COPY(targ, (pst_entryid*)); \ LE32_CPU(targ->u1); \ LE32_CPU(targ->id); \ - DEBUG_INFO((label" u1=%#x, id=%#x\n", targ->u1, targ->id));\ + DEBUG_INFO((label" u1=%#x, id=%#x\n", targ->u1, targ->id)); \ } #define LIST_COPY_EMAIL_ENTRYID(label, targ) { \ @@ -2022,7 +2022,7 @@ #define LIST_COPY_STR(label, targ) { \ LIST_COPY_CSTR(targ.str); \ targ.is_utf8 = (list->elements[x]->type == 0x1f) ? 1 : 0; \ - DEBUG_INFO((label" - unicode %d - %s\n", targ.is_utf8, targ.str)); \ + DEBUG_INFO((label" - unicode %d - %s\n", targ.is_utf8, targ.str)); \ } #define LIST_COPY_EMAIL_STR(label, targ) { \ @@ -2055,7 +2055,7 @@ memcpy(targ, list->elements[x]->data, list->elements[x]->size); \ LE32_CPU(targ->dwLowDateTime); \ LE32_CPU(targ->dwHighDateTime); \ - DEBUG_INFO((label" - %s", pst_fileTimeToAscii(targ, time_buffer))); \ + DEBUG_INFO((label" - %s", pst_fileTimeToAscii(targ, time_buffer))); \ } #define LIST_COPY_EMAIL_TIME(label, targ) { \ @@ -2094,12 +2094,12 @@ #define LIST_COPY_EMAIL_BIN(label, targ) { \ MALLOC_EMAIL(item); \ LIST_COPY_BIN(targ); \ - DEBUG_INFO((label"\n")); \ + DEBUG_INFO((label"\n")); \ } #define LIST_COPY_APPT_BIN(label, targ) { \ MALLOC_APPOINTMENT(item); \ LIST_COPY_BIN(targ); \ - DEBUG_INFO((label"\n")); \ + DEBUG_INFO((label"\n")); \ DEBUG_HEXDUMP(targ.data, targ.size); \ } @@ -2138,35 +2138,58 @@ switch (list->elements[x]->mapi_id) { case PST_ATTRIB_HEADER: // CUSTOM attribute for saying the Extra Headers if (list->elements[x]->extra) { - pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field)); - memset(ef, 0, sizeof(pst_item_extra_field)); - LIST_COPY_CSTR(ef->value); - if (ef->value) { - ef->field_name = strdup(list->elements[x]->extra); - ef->next = item->extra_fields; - item->extra_fields = ef; - DEBUG_INFO(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value)); - if (strcmp(ef->field_name, "content-type") == 0) { - char *p = strstr(ef->value, "charset=\""); - if (p) { - p += 9; // skip over charset=" - char *pp = strchr(p, '"'); - if (pp) { - *pp = '\0'; - char *set = strdup(p); - *pp = '"'; - if (item->body_charset.str) free(item->body_charset.str); - item->body_charset.str = set; - item->body_charset.is_utf8 = 1; - DEBUG_INFO(("body charset %s from content-type extra field\n", set)); + if (list->elements[x]->type == 0x0101e) { + // an array of strings, rather than a single string + int32_t string_length, i, offset, next_offset; + int32_t p = 0; + int32_t array_element_count = PST_LE_GET_INT32(list->elements[x]->data); p+=4; + for (i = 1; i <= array_element_count; i++) { + pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field)); + memset(ef, 0, sizeof(pst_item_extra_field)); + offset = PST_LE_GET_INT32(list->elements[x]->data + p); p+=4; + next_offset = (i == array_element_count) ? list->elements[x]->size : PST_LE_GET_INT32(list->elements[x]->data + p);; + string_length = next_offset - offset; + ef->value = malloc(string_length + 1); + memcpy(ef->value, list->elements[x]->data + offset, string_length); + ef->value[string_length] = '\0'; + ef->field_name = strdup(list->elements[x]->extra); + ef->next = item->extra_fields; + item->extra_fields = ef; + DEBUG_INFO(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value)); + } + } + else { + // should be a single string + pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field)); + memset(ef, 0, sizeof(pst_item_extra_field)); + LIST_COPY_CSTR(ef->value); + if (ef->value) { + ef->field_name = strdup(list->elements[x]->extra); + ef->next = item->extra_fields; + item->extra_fields = ef; + DEBUG_INFO(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value)); + if (strcmp(ef->field_name, "content-type") == 0) { + char *p = strstr(ef->value, "charset=\""); + if (p) { + p += 9; // skip over charset=" + char *pp = strchr(p, '"'); + if (pp) { + *pp = '\0'; + char *set = strdup(p); + *pp = '"'; + if (item->body_charset.str) free(item->body_charset.str); + item->body_charset.str = set; + item->body_charset.is_utf8 = 1; + DEBUG_INFO(("body charset %s from content-type extra field\n", set)); + } } } } - } - else { - DEBUG_WARN(("What does this mean? Internet header %s value\n", list->elements[x]->extra)); - DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); - free(ef); // caught by valgrind + else { + DEBUG_WARN(("What does this mean? Internet header %s value\n", list->elements[x]->extra)); + DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); + free(ef); // caught by valgrind + } } } break; @@ -3981,7 +4004,6 @@ char *buf3 = NULL; char *buf2 = NULL; char *b_ptr; - int line_count = 0; pst_block_hdr block_hdr; pst_table3_rec table3_rec; //for type 3 (0x0101) blocks diff -r fa4042b0a566 -r 67b24d6a45d6 src/pst2ldif.cpp --- a/src/pst2ldif.cpp Sun Sep 20 11:29:48 2009 -0700 +++ b/src/pst2ldif.cpp Fri Dec 11 08:45:30 2009 -0800 @@ -665,6 +665,7 @@ print_ldif_single("objectClass", ldap_class[i].c_str()); printf("\n"); } + free(ldap_org); // found by cppcheck } process(d_ptr->child); // do the children of TOPF diff -r fa4042b0a566 -r 67b24d6a45d6 src/readpst.c --- a/src/readpst.c Sun Sep 20 11:29:48 2009 -0700 +++ b/src/readpst.c Fri Dec 11 08:45:30 2009 -0800 @@ -58,8 +58,9 @@ void write_schedule_part(FILE* f_output, pst_item* item, const char* sender, const char* boundary); void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf, char** extra_mime_headers); void write_vcard(FILE* f_output, pst_item *item, pst_item_contact* contact, char comment[]); +int write_extra_categories(FILE* f_output, pst_item* item); void write_journal(FILE* f_output, pst_item* item); -void write_appointment(FILE* f_output, pst_item *item, int event_open); +void write_appointment(FILE* f_output, pst_item *item); void create_enter_dir(struct file_ll* f, pst_item *item); void close_enter_dir(struct file_ll *f); @@ -1279,7 +1280,7 @@ if (method) fprintf(f_output, "METHOD:%s\n", method); fprintf(f_output, "BEGIN:VEVENT\n"); if (sender) fprintf(f_output, "ORGANIZER;CN=\"%s\":MAILTO:%s\n", item->email->outlook_sender_name.str, sender); - write_appointment(f_output, item, 1); + write_appointment(f_output, item); fprintf(f_output, "END:VCALENDAR\n"); } @@ -1673,6 +1674,7 @@ pst_convert_utf8_null(item, &contact->assistant_name); pst_convert_utf8_null(item, &contact->assistant_phone); pst_convert_utf8_null(item, &contact->company_name); + pst_convert_utf8_null(item, &item->body); // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile fprintf(f_output, "BEGIN:VCARD\n"); @@ -1756,6 +1758,9 @@ } if (contact->company_name.str) fprintf(f_output, "ORG:%s\n", pst_rfc2426_escape(contact->company_name.str, &result, &resultlen)); if (comment) fprintf(f_output, "NOTE:%s\n", pst_rfc2426_escape(comment, &result, &resultlen)); + if (item->body.str) fprintf(f_output, "NOTE:%s\n", pst_rfc2426_escape(item->body.str, &result, &resultlen)); + + write_extra_categories(f_output, item); fprintf(f_output, "VERSION: 3.0\n"); fprintf(f_output, "END:VCARD\n\n"); @@ -1764,6 +1769,34 @@ } +/** + * write extra vcard or vcalendar categories from the extra keywords fields + * + * @param f_output open file pointer + * @param item pst item containing the keywords + * @return true if we write a categories line + */ +int write_extra_categories(FILE* f_output, pst_item* item) +{ + char* result = NULL; + size_t resultlen = 0; + pst_item_extra_field *ef = item->extra_fields; + const char *fmt = "CATEGORIES:%s"; + int category_started = 0; + while (ef) { + if (strcmp(ef->field_name, "Keywords") == 0) { + fprintf(f_output, fmt, pst_rfc2426_escape(ef->value, &result, &resultlen)); + fmt = ", %s"; + category_started = 1; + } + ef = ef->next; + } + if (category_started) fprintf(f_output, "\n"); + if (result) free(result); + return category_started; +} + + void write_journal(FILE* f_output, pst_item* item) { char* result = NULL; @@ -1792,7 +1825,7 @@ } -void write_appointment(FILE* f_output, pst_item* item, int event_open) +void write_appointment(FILE* f_output, pst_item* item) { char* result = NULL; size_t resultlen = 0; @@ -1804,7 +1837,6 @@ pst_convert_utf8_null(item, &item->body); pst_convert_utf8_null(item, &appointment->location); - if (!event_open) fprintf(f_output, "BEGIN:VEVENT\n"); fprintf(f_output, "DTSTAMP:%s\n", pst_rfc2445_datetime_format_now(sizeof(time_buffer), time_buffer)); if (item->create_date) fprintf(f_output, "CREATED:%s\n", pst_rfc2445_datetime_format(item->create_date, sizeof(time_buffer), time_buffer)); @@ -1865,7 +1897,7 @@ } switch (appointment->label) { case PST_APP_LABEL_NONE: - fprintf(f_output, "CATEGORIES:NONE\n"); + if (!write_extra_categories(f_output, item)) fprintf(f_output, "CATEGORIES:NONE\n"); break; case PST_APP_LABEL_IMPORTANT: fprintf(f_output, "CATEGORIES:IMPORTANT\n");