changeset 242:67b24d6a45d6 stable-0-6-45

patch from Hugo DesRosiers to export categories and notes into vcards. extend that patch to export categories into vcalendar appointments also.
author Carl Byington <carl@five-ten-sg.com>
date Fri, 11 Dec 2009 08:45:30 -0800
parents fa4042b0a566
children 0199af9730b2
files AUTHORS ChangeLog NEWS configure.in libpst.spec.in src/define.h src/libpst.c src/pst2ldif.cpp src/readpst.c
diffstat 9 files changed, 116 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- 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 <chris@soniannetworks.com>
     Roberto Polli <robipolli@gmail.com>
     Lee Ayres <ayres@interhack.com>
+    Hugo DesRosiers <info@akralogic.com>
 
 
 Testing team:
--- 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.
--- 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
--- 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
--- 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 <carl@five-ten-sg.com> - 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 <carl@five-ten-sg.com> - 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.
--- 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();                                   \
--- 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
 
--- 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
--- 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");