changeset 231:fe64279df92b

patches from Chris White, Roberto Polli, Justin Greer
author Carl Byington <carl@five-ten-sg.com>
date Thu, 10 Sep 2009 15:21:23 -0700
parents 42b38d65f7e4
children f8dc1b7201ad
files AUTHORS ChangeLog NEWS regression/regression-tests.bash src/libpst.c src/readpst.c xml/libpst.in
diffstat 7 files changed, 111 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/AUTHORS	Thu Sep 10 13:01:08 2009 -0700
+++ b/AUTHORS	Thu Sep 10 15:21:23 2009 -0700
@@ -28,6 +28,8 @@
     Emmanuel Andry <eandry@mandriva.org>
     hggdh <hggdh2@gmail.com>
     bharder <bharder@methodlogic.net>
+    Chris White <chris@soniannetworks.com>
+    Roberto Polli <robipolli@gmail.com>
 
 
 Testing team:
--- a/ChangeLog	Thu Sep 10 13:01:08 2009 -0700
+++ b/ChangeLog	Thu Sep 10 15:21:23 2009 -0700
@@ -1,3 +1,15 @@
+LibPST 0.6.43 (2009-09-10)
+===============================
+    * patches from Justin Greer.
+	add code pages 1200 and 1201 to the list for iconv
+    	add support for 0x0201 indirect blocks that point to 0x0101 blocks
+	add readpst -t option to select output item types
+	fix (remove) extra new line inside headers
+    * cleanup base64 encoding to remove duplicate code.
+    * patch from Chris White to avoid segfault with embedded appointments.
+    * patch from Roberto Polli to add creation of some Thunderbird specific meta files.
+    * patch from Justin Greer to ignore b5 tables at offset zero.
+
 LibPST 0.6.42 (2009-09-03)
 ===============================
     * patch from Fridrich Strba to build with DJGPP DOS cross-compiler.
--- a/NEWS	Thu Sep 10 13:01:08 2009 -0700
+++ b/NEWS	Thu Sep 10 15:21:23 2009 -0700
@@ -1,3 +1,4 @@
+0.6.43  2009-09-10 patches from Justin Greer, Chris White, Roberto Polli
 0.6.42  2009-09-03 patch from Fridrich Strba to build with DJGPP DOS cross-compiler
 0.6.41  2009-06-23 fix ax_python detection - should not use locate command
 0.6.40  2009-06-23 fedora 11 has python2.6, remove pdf version of the man pages
--- a/regression/regression-tests.bash	Thu Sep 10 13:01:08 2009 -0700
+++ b/regression/regression-tests.bash	Thu Sep 10 15:21:23 2009 -0700
@@ -47,7 +47,7 @@
     fn="$2"
     echo $fn
     ba=$(basename "$fn" .pst)
-    jobs=""
+    jobs="-j 0"
     [ -n "$val" ] && jobs="-j 0"
     rm -rf output$n
     mkdir output$n
@@ -67,11 +67,15 @@
 
 rm -rf output* *.err *.log
 
-if [ "$1" == "dii" ]; then
+if [ "$1" == "test" ]; then
+    dopst  19 harris.pst
+
+elif [ "$1" == "dii" ]; then
     dodii 1 ams.pst
     dodii 2 sample_64.pst
     dodii 3 test.pst
     dodii 4 big_mail.pst
+
 elif [ "$1" == "ldif" ]; then
     doldif   1 ams.pst
     doldif   2 sample_64.pst
--- a/src/libpst.c	Thu Sep 10 13:01:08 2009 -0700
+++ b/src/libpst.c	Thu Sep 10 15:21:23 2009 -0700
@@ -1260,27 +1260,28 @@
         // DSN/MDN reports?
         DEBUG_INFO(("DSN/MDN processing\n"));
         list = pst_parse_block(pf, id2_ptr->id->i_id, id2_head);
-        if (!list) {
+        if (list) {
+            for (x=0; x < list->count_objects; x++) {
+                attach = (pst_item_attach*) pst_malloc(sizeof(pst_item_attach));
+                memset(attach, 0, sizeof(pst_item_attach));
+                attach->next = item->attach;
+                item->attach = attach;
+            }
+            if (pst_process(list, item, item->attach)) {
+                DEBUG_WARN(("ERROR pst_process() failed with DSN/MDN attachments\n"));
+                pst_freeItem(item);
+                pst_free_list(list);
+                if (!m_head) pst_free_id2(id2_head);
+                DEBUG_RET();
+                return NULL;
+            }
+            pst_free_list(list);
+        } else {
             DEBUG_WARN(("ERROR error processing main DSN/MDN record\n"));
-            if (!m_head) pst_free_id2(id2_head);
-            DEBUG_RET();
-            return item;
+            // if (!m_head) pst_free_id2(id2_head);
+            // DEBUG_RET();
+            // return item;
         }
-        for (x=0; x < list->count_objects; x++) {
-            attach = (pst_item_attach*) pst_malloc(sizeof(pst_item_attach));
-            memset(attach, 0, sizeof(pst_item_attach));
-            attach->next = item->attach;
-            item->attach = attach;
-        }
-        if (pst_process(list, item, item->attach)) {
-            DEBUG_WARN(("ERROR pst_process() failed with DSN/MDN attachments\n"));
-            pst_freeItem(item);
-            pst_free_list(list);
-            if (!m_head) pst_free_id2(id2_head);
-            DEBUG_RET();
-            return NULL;
-        }
-        pst_free_list(list);
     }
 
     if ((id2_ptr = pst_getID2(id2_head, (uint64_t)0x671))) {
@@ -1592,24 +1593,29 @@
             return NULL;
         }
 
-        if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset5)) {
-            DEBUG_WARN(("internal error (7c.b5.desc offset %#x) in reading block id %#"PRIx64"\n", table_rec.value, block_id));
-            freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
-            DEBUG_RET();
-            return NULL;
+        if (table_rec.value > 0) {
+            if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset5)) {
+                DEBUG_WARN(("internal error (7c.b5.desc offset %#x) in reading block id %#"PRIx64"\n", table_rec.value, block_id));
+                freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
+                DEBUG_RET();
+                return NULL;
+            }
+
+            // this will give the number of records in this block
+            num_mapi_objects = (block_offset5.to - block_offset5.from) / (4 + table_rec.ref_type);
+
+            if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, seven_c_blk.ind2_offset, &block_offset6)) {
+                DEBUG_WARN(("internal error (7c.ind2 offset %#x) in reading block id %#"PRIx64"\n", seven_c_blk.ind2_offset, block_id));
+                freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
+                DEBUG_RET();
+                return NULL;
+            }
+            ind2_ptr = block_offset6.from;
+            ind2_end = block_offset6.to;
         }
-
-        // this will give the number of records in this block
-        num_mapi_objects = (block_offset5.to - block_offset5.from) / (4 + table_rec.ref_type);
-
-        if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, seven_c_blk.ind2_offset, &block_offset6)) {
-            DEBUG_WARN(("internal error (7c.ind2 offset %#x) in reading block id %#"PRIx64"\n", seven_c_blk.ind2_offset, block_id));
-            freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
-            DEBUG_RET();
-            return NULL;
+        else {
+            num_mapi_objects = 0;
         }
-        ind2_ptr = block_offset6.from;
-        ind2_end = block_offset6.to;
         DEBUG_INFO(("7cec block index2 pointer %#x and end %#x\n", ind2_ptr, ind2_end));
     }
     else {
--- a/src/readpst.c	Thu Sep 10 13:01:08 2009 -0700
+++ b/src/readpst.c	Thu Sep 10 15:21:23 2009 -0700
@@ -118,6 +118,7 @@
 // global settings
 int         mode         = MODE_NORMAL;
 int         mode_MH      = 0;   // a submode of MODE_SEPARATE
+int         mode_thunder = 0;   // a submode of MODE_RECURSE
 int         output_mode  = OUTPUT_NORMAL;
 int         contact_mode = CMODE_VCARD;
 int         deleted_mode = DMODE_EXCLUDE;
@@ -387,7 +388,7 @@
     }
 
     // command-line option handling
-    while ((c = getopt(argc, argv, "bc:Dd:hj:kMo:qrSt:Vw"))!= -1) {
+    while ((c = getopt(argc, argv, "bc:Dd:hj:kMo:qrSt:uVw"))!= -1) {
         switch (c) {
         case 'b':
             save_rtf_body = 0;
@@ -435,15 +436,12 @@
             break;
         case 'r':
             mode = MODE_RECURSE;
+            mode_thunder = 0;
             break;
         case 'S':
             mode = MODE_SEPARATE;
             mode_MH = 0;
             break;
-        case 'V':
-            version();
-            exit(0);
-            break;
         case 't':
             // email, appointment, contact, other
             if (!optarg) {
@@ -474,6 +472,14 @@
               temp++;
             }
             break;
+        case 'u':
+            mode = MODE_RECURSE;
+            mode_thunder = 1;
+            break;
+        case 'V':
+            version();
+            exit(0);
+            break;
         case 'w':
             overwrite = 1;
             break;
@@ -632,7 +638,6 @@
     printf("\t-S\t- Separate. Write emails in the separate format\n");
     printf("\t-b\t- Don't save RTF-Body attachments\n");
     printf("\t-c[v|l]\t- Set the Contact output mode. -cv = VCard, -cl = EMail list\n");
-    printf("\t-t[eajc]\t- Set the output type list. e = email, a = attachment, j = journal, c = contact\n");
     printf("\t-d <filename> \t- Debug to file. This is a binary log. Use readpstlog to print it\n");
     printf("\t-h\t- Help. This screen\n");
     printf("\t-j <integer>\t- Number of parallel jobs to run\n");
@@ -640,6 +645,8 @@
     printf("\t-o <dirname>\t- Output 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");
+    printf("\t-t[eajc]\t- Set the output type list. e = email, a = attachment, j = journal, c = contact\n");
+    printf("\t-u\t- Thunderbird mode. Write two extra .size and .type files\n");
     printf("\t-w\t- Overwrite any output mbox files\n");
     printf("\n");
     printf("Only one of -k -M -r -S should be specified\n");
@@ -959,8 +966,6 @@
 {
     pst_index_ll *ptr;
     DEBUG_ENT("write_embedded_message");
-    fprintf(f_output, "\n--%s\n", boundary);
-    fprintf(f_output, "Content-Type: %s\n\n", attach->mimetype.str);
     ptr = pst_getID(pf, attach->i_id);
 
     pst_desc_tree d_ptr;
@@ -976,8 +981,20 @@
     d_ptr.child_tail  = NULL;
 
     pst_item *item = pst_parse_item(pf, &d_ptr, attach->id2_head);
-    write_normal_email(f_output, "", item, MODE_NORMAL, 0, pf, 0, extra_mime_headers);
-    pst_freeItem(item);
+    // It appears that if the embedded message contains an appointment/
+    // calendar item, pst_parse_item returns NULL due to the presence of
+    // an unexpected reference type of 0x1048, which seems to represent
+    // an array of GUIDs representing a CLSID. It's likely that this is
+    // a reference to an internal Outlook COM class.
+    //      Log the skipped item and continue on.
+    if (!item) {
+        DEBUG_WARN(("write_embedded_message: pst_parse_item was unable to parse the embedded message in attachment ID %llu", attach->i_id));
+    } else {
+        fprintf(f_output, "\n--%s\n", boundary);
+        fprintf(f_output, "Content-Type: %s\n\n", attach->mimetype.str);
+        write_normal_email(f_output, "", item, MODE_NORMAL, 0, pf, 0, extra_mime_headers);
+        pst_freeItem(item);
+    }
 
     DEBUG_RET();
 }
@@ -1869,9 +1886,14 @@
     DEBUG_ENT("create_enter_dir");
     if (mode == MODE_KMAIL)
         f->name = mk_kmail_dir(item->file_as.str);
-    else if (mode == MODE_RECURSE)
+    else if (mode == MODE_RECURSE) {
         f->name = mk_recurse_dir(item->file_as.str, f->type);
-    else if (mode == MODE_SEPARATE) {
+        if (mode_thunder) {
+            FILE *type_file = fopen(".type", "w");
+            fprintf(type_file, "%d\n", item->type);
+            fclose(type_file);
+        }
+    } else if (mode == MODE_SEPARATE) {
         // do similar stuff to recurse here.
         mk_separate_dir(item->file_as.str);
         f->name = (char*) pst_malloc(10);
@@ -1944,9 +1966,14 @@
 
     if (mode == MODE_KMAIL)
         close_kmail_dir();
-    else if (mode == MODE_RECURSE)
+    else if (mode == MODE_RECURSE) {
+        if (mode_thunder) {
+            FILE *type_file = fopen(".size", "w");
+            fprintf(type_file, "%i %i\n", f->item_count, f->stored_count);
+            fclose(type_file);
+        }
         close_recurse_dir();
-    else if (mode == MODE_SEPARATE)
+    } else if (mode == MODE_SEPARATE)
         close_separate_dir();
 }
 
--- a/xml/libpst.in	Thu Sep 10 13:01:08 2009 -0700
+++ b/xml/libpst.in	Thu Sep 10 15:21:23 2009 -0700
@@ -67,6 +67,7 @@
                 <arg><option>-q</option></arg>
                 <arg><option>-r</option></arg>
                 <arg><option>-t <replaceable class="parameter">output-type-codes</replaceable></option></arg>
+                <arg><option>-u</option></arg>
                 <arg><option>-w</option></arg>
                 <arg choice='plain'>pstfile</arg>
             </cmdsynopsis>
@@ -186,6 +187,13 @@
                     </para></listitem>
                 </varlistentry>
                 <varlistentry>
+                    <term>-u</term>
+                    <listitem><para>
+                        Sets Thunderbird mode, a submode of recursive mode. This causes
+                        two extra .type and .size meta files to be created.
+                    </para></listitem>
+                </varlistentry>
+                <varlistentry>
                     <term>-w</term>
                     <listitem><para>
                         Overwrite any previous output files. Beware: When used with the -S