changeset 164:ab384fed78c5

Compensate for iconv conversion to utf-7 that produces strings that are not null terminated. Don't produce empty attachment files in separate mode.
author Carl Byington <carl@five-ten-sg.com>
date Mon, 16 Mar 2009 18:31:39 -0700
parents 03fbb0269f3c
children 6194e4a10406
files ChangeLog regression/regression-tests.bash src/dumpblocks.c src/getidblock.c src/libpst.c src/libpst.h src/lspst.c src/readpst.c src/vbuf.c
diffstat 9 files changed, 123 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Mar 16 12:43:31 2009 -0700
+++ b/ChangeLog	Mon Mar 16 18:31:39 2009 -0700
@@ -4,6 +4,9 @@
     * fix fedora 11 type mismatch warning (actually an error in this case).
     * fix large file support, some sytems require config.h to be included
       earlier in the compilation.
+    * compensate for iconv conversion to utf-7 that produces strings that
+      are not null terminated.
+    * don't produce empty attachment files in separate mode.
 
 LibPST 0.6.32 (2009-03-14)
 ===============================
--- a/regression/regression-tests.bash	Mon Mar 16 12:43:31 2009 -0700
+++ b/regression/regression-tests.bash	Mon Mar 16 18:31:39 2009 -0700
@@ -38,7 +38,7 @@
     mkdir output$n
     #    ../src/readpst -cv -o output$n $fn >$ba.err 2>&1
     #           readpst -cv -o output$n -d dumper $fn >$ba.err 2>&1
-    $val ../src/readpst -r -cv -o output$n -d dumper $fn >$ba.err 2>&1
+    $val ../src/readpst -S -cv -o output$n -d dumper $fn >$ba.err 2>&1
          ../src/readpstlog -f I dumper >$ba.log
 
     #../src/getidblock -d -p $fn 0 >$ba.fulldump
@@ -50,12 +50,14 @@
 
 
 val="valgrind --leak-check=full"
-#val=''
+val=''
 
 pushd ..
 make || exit
 popd
 
+rm -rf output* *.err *.log
+
 if [ "$1" == "dii" ]; then
     dodii 1 ams.pst
     dodii 2 sample_64.pst
@@ -82,8 +84,9 @@
     #doldif  18 test-mac.pst
     #doldif  19 harris.pst
 else
+    dopst  20 spam.pst
+    exit
     dopst   1 ams.pst
-    exit
     dopst   2 sample_64.pst
     dopst   3 test.pst
     dopst   4 big_mail.pst
--- a/src/dumpblocks.c	Mon Mar 16 12:43:31 2009 -0700
+++ b/src/dumpblocks.c	Mon Mar 16 18:31:39 2009 -0700
@@ -56,16 +56,16 @@
     printf("Saving blocks\n");
     while (ptr != NULL) {
         /*    if (pstfile.encryption == PST_ENC) {
-           c = pst_ff_getIDblock_dec(&pstfile, ptr->id, buf);
+           c = pst_ff_getIDblock_dec(&pstfile, ptr->i_id, buf);
            } else { */
-        if ((ptr->id & 0x02) == 0 && pstfile.encryption == PST_ENC) {
-            c = pst_ff_getIDblock_dec(&pstfile, ptr->id, &buf);
+        if ((ptr->i_id & 0x02) == 0 && pstfile.encryption == PST_ENC) {
+            c = pst_ff_getIDblock_dec(&pstfile, ptr->i_id, &buf);
         } else {
-            c = pst_ff_getIDblock(&pstfile, ptr->id, &buf);
+            c = pst_ff_getIDblock(&pstfile, ptr->i_id, &buf);
         }
 
         if (c > 0) {
-            snprintf(outname, OUT_BUF, "%#"PRIx64, ptr->id);
+            snprintf(outname, OUT_BUF, "%#"PRIx64, ptr->i_id);
             if ((fp = fopen(outname, "wb")) == NULL) {
                 printf("Failed to open file %s\n", outname);
                 continue;
@@ -73,7 +73,7 @@
             pst_fwrite(buf, 1, c, fp);
             fclose(fp);
         } else {
-            printf("Failed to read block id %#"PRIx64"\n", ptr->id);
+            printf("Failed to read block i_id %#"PRIx64"\n", ptr->i_id);
         }
         ptr = ptr->next;
     }
--- a/src/getidblock.c	Mon Mar 16 12:43:31 2009 -0700
+++ b/src/getidblock.c	Mon Mar 16 18:31:39 2009 -0700
@@ -17,44 +17,44 @@
 }
 
 
-void dumper(uint64_t id);
-void dumper(uint64_t id)
+void dumper(uint64_t i_id);
+void dumper(uint64_t i_id)
 {
     char *buf = NULL;
     size_t readSize;
     pst_desc_ll *ptr;
 
-    DEBUG_MAIN(("\n\n\nLooking at block index1 id %#"PRIx64"\n", id));
+    DEBUG_MAIN(("\n\n\nLooking at block index1 id %#"PRIx64"\n", i_id));
 
-    if ((readSize = pst_ff_getIDblock_dec(&pstfile, id, &buf)) <= 0 || buf == 0) {
+    if ((readSize = pst_ff_getIDblock_dec(&pstfile, i_id, &buf)) <= 0 || buf == 0) {
         DIE(("Error loading block\n"));
     }
 
-    DEBUG_MAIN(("Printing block id %#"PRIx64", size %#"PRIx64"\n", id, (uint64_t)readSize));
+    DEBUG_MAIN(("Printing block id %#"PRIx64", size %#"PRIx64"\n", i_id, (uint64_t)readSize));
     if (binary) {
         if (fwrite(buf, 1, readSize, stdout) != 0) {
             DIE(("Error occured during writing of buf to stdout\n"));
         }
     } else {
-        printf("Block id %#"PRIx64", size %#"PRIx64"\n", id, (uint64_t)readSize);
+        printf("Block id %#"PRIx64", size %#"PRIx64"\n", i_id, (uint64_t)readSize);
         pst_debug_hexdumper(stdout, buf, readSize, 0x10, 0);
     }
     if (buf) free(buf);
 
     if (process) {
-        DEBUG_MAIN(("Parsing block id %#"PRIx64"\n", id));
+        DEBUG_MAIN(("Parsing block id %#"PRIx64"\n", i_id));
         ptr = pstfile.d_head;
         while (ptr) {
-            if (ptr->assoc_tree && ptr->assoc_tree->id == id)
+            if (ptr->assoc_tree && ptr->assoc_tree->i_id == i_id)
                 break;
-            if (ptr->desc && ptr->desc->id == id)
+            if (ptr->desc && ptr->desc->i_id == i_id)
                 break;
             ptr = pst_getNextDptr(ptr);
         }
         if (!ptr) {
             ptr = (pst_desc_ll *) xmalloc(sizeof(pst_desc_ll));
             memset(ptr, 0, sizeof(pst_desc_ll));
-            ptr->desc = pst_getID(&pstfile, id);
+            ptr->desc = pst_getID(&pstfile, i_id);
         }
         pst_item *item = pst_parse_item(&pstfile, ptr, NULL);
         if (item) pst_freeItem(item);
@@ -67,8 +67,8 @@
 {
     while (ptr) {
         DEBUG_MAIN(("\n\n\nLooking at block desc id %#"PRIx64"\n", ptr->d_id));
-        if (ptr->desc       && ptr->desc->id)       dumper(ptr->desc->id);
-        if (ptr->assoc_tree && ptr->assoc_tree->id) dumper(ptr->assoc_tree->id);
+        if (ptr->desc       && ptr->desc->i_id)       dumper(ptr->desc->i_id);
+        if (ptr->assoc_tree && ptr->assoc_tree->i_id) dumper(ptr->assoc_tree->i_id);
         if (ptr->child) dump_desc(ptr->child);
         ptr = ptr->next;
     }
@@ -79,7 +79,7 @@
 {
     // pass the id number to display on the command line
     char *fname, *sid;
-    uint64_t id;
+    uint64_t i_id;
     int c;
 
     DEBUG_INIT("getidblock.log");
@@ -109,7 +109,7 @@
     }
     fname = argv[optind];
     sid   = argv[optind + 1];
-    id    = (uint64_t)strtoll(sid, NULL, 0);
+    i_id  = (uint64_t)strtoll(sid, NULL, 0);
 
     DEBUG_MAIN(("Opening file\n"));
     memset(&pstfile, 0, sizeof(pstfile));
@@ -122,13 +122,13 @@
         DIE(("Error loading file index\n"));
     }
 
-    if (id) {
-        dumper(id);
+    if (i_id) {
+        dumper(i_id);
     }
     else {
         pst_index_ll *ptr = pstfile.i_head;
         while (ptr) {
-            dumper(ptr->id);
+            dumper(ptr->i_id);
             ptr = ptr->next;
         }
         dump_desc(pstfile.d_head);
--- a/src/libpst.c	Mon Mar 16 12:43:31 2009 -0700
+++ b/src/libpst.c	Mon Mar 16 18:31:39 2009 -0700
@@ -409,8 +409,8 @@
     pst_index_ll *ptr;
     pst_holder h = {b, NULL, 0};
     DEBUG_ENT("pst_attach_to_mem");
-    if (attach->id_val != (uint64_t)-1) {
-        ptr = pst_getID(pf, attach->id_val);
+    if (attach->i_id != (uint64_t)-1) {
+        ptr = pst_getID(pf, attach->i_id);
         if (ptr) {
             size = pst_ff_getID2data(pf, ptr, &h);
         } else {
@@ -431,8 +431,8 @@
     pst_holder h = {NULL, fp, 0};
     size_t size = 0;
     DEBUG_ENT("pst_attach_to_file");
-    if (attach->id_val != (uint64_t)-1) {
-        ptr = pst_getID(pf, attach->id_val);
+    if (attach->i_id != (uint64_t)-1) {
+        ptr = pst_getID(pf, attach->i_id);
         if (ptr) {
             size = pst_ff_getID2data(pf, ptr, &h);
         } else {
@@ -454,8 +454,8 @@
     pst_holder h = {NULL, fp, 1};
     size_t size = 0;
     DEBUG_ENT("pst_attach_to_file_base64");
-    if (attach->id_val != (uint64_t)-1) {
-        ptr = pst_getID(pf, attach->id_val);
+    if (attach->i_id != (uint64_t)-1) {
+        ptr = pst_getID(pf, attach->i_id);
         if (ptr) {
             size = pst_ff_getID2data(pf, ptr, &h);
         } else {
@@ -550,7 +550,7 @@
         DEBUG_WARN(("Have not been able to fetch any id2 values for item 0x61. Brace yourself!\n"));
     }
 
-    na = pst_parse_block(pf, p->desc->id, id2_head);
+    na = pst_parse_block(pf, p->desc->i_id, id2_head);
     if (!na) {
         DEBUG_WARN(("Cannot process desc block for item 0x61. Not loading extended Attributes\n"));
         pst_free_id2(id2_head);
@@ -894,7 +894,7 @@
                 }
             }
             i_ptr = (pst_index_ll*) xmalloc(sizeof(pst_index_ll));
-            i_ptr->id     = index.id;
+            i_ptr->i_id   = index.id;
             i_ptr->offset = index.offset;
             i_ptr->u1     = index.u1;
             i_ptr->size   = index.size;
@@ -1092,9 +1092,9 @@
     }
     pst_printID2ptr(id2_head);
 
-    list = pst_parse_block(pf, d_ptr->desc->id, id2_head);
+    list = pst_parse_block(pf, d_ptr->desc->i_id, id2_head);
     if (!list) {
-        DEBUG_WARN(("pst_parse_block() returned an error for d_ptr->desc->id [%#"PRIx64"]\n", d_ptr->desc->id));
+        DEBUG_WARN(("pst_parse_block() returned an error for d_ptr->desc->i_id [%#"PRIx64"]\n", d_ptr->desc->i_id));
         if (!m_head) pst_free_id2(id2_head);
         DEBUG_RET();
         return NULL;
@@ -1116,7 +1116,7 @@
     if ((id2_ptr = pst_getID2(id2_head, (uint64_t)0x692))) {
         // DSN/MDN reports?
         DEBUG_EMAIL(("DSN/MDN processing\n"));
-        list = pst_parse_block(pf, id2_ptr->id->id, id2_head);
+        list = pst_parse_block(pf, id2_ptr->id->i_id, id2_head);
         if (!list) {
             DEBUG_WARN(("ERROR error processing main DSN/MDN record\n"));
             if (!m_head) pst_free_id2(id2_head);
@@ -1142,7 +1142,7 @@
 
     if ((id2_ptr = pst_getID2(id2_head, (uint64_t)0x671))) {
         DEBUG_EMAIL(("ATTACHMENT processing attachment\n"));
-        list = pst_parse_block(pf, id2_ptr->id->id, id2_head);
+        list = pst_parse_block(pf, id2_ptr->id->i_id, id2_head);
         if (!list) {
             DEBUG_WARN(("ERROR error processing main attachment record\n"));
             if (!m_head) pst_free_id2(id2_head);
@@ -1172,11 +1172,11 @@
         while (attach) {
             DEBUG_WARN(("initial attachment id2 %#"PRIx64"\n", attach->id2_val));
             if ((id2_ptr = pst_getID2(id2_head, attach->id2_val))) {
-                DEBUG_WARN(("initial attachment id2 found id %#"PRIx64"\n", id2_ptr->id->id));
+                DEBUG_WARN(("initial attachment id2 found id %#"PRIx64"\n", id2_ptr->id->i_id));
                 // id_ptr is a record describing the attachment
                 // we pass NULL instead of id2_head cause we don't want it to
                 // load all the extra stuff here.
-                list = pst_parse_block(pf, id2_ptr->id->id, NULL);
+                list = pst_parse_block(pf, id2_ptr->id->i_id, NULL);
                 if (!list) {
                     DEBUG_WARN(("ERROR error processing an attachment record\n"));
                     attach = attach->next;
@@ -1194,10 +1194,10 @@
                 pst_free_list(list);
                 id2_ptr = pst_getID2(id2_head, attach->id2_val);
                 if (id2_ptr) {
-                    DEBUG_WARN(("second pass attachment updating id2 found id %#"PRIx64"\n", id2_ptr->id->id));
+                    DEBUG_WARN(("second pass attachment updating id2 found i_id %#"PRIx64"\n", id2_ptr->id->i_id));
                     // id2_val has been updated to the ID2 value of the datablock containing the
                     // attachment data
-                    attach->id_val   = id2_ptr->id->id;
+                    attach->i_id     = id2_ptr->id->i_id;
                     attach->id2_head = deep_copy(id2_ptr->child);
                 } else {
                     DEBUG_WARN(("have not located the correct value for the attachment [%#"PRIx64"]\n", attach->id2_val));
@@ -1662,30 +1662,29 @@
                 if (table_rec.ref_type == (uint16_t)0x1f) {
                     // there is more to do for the type 0x1f unicode strings
                     size_t rc;
-                    static vbuf *strbuf = NULL;
-                    static vbuf *unibuf = NULL;
-                    if (!strbuf) strbuf=vballoc((size_t)1024);
-                    if (!unibuf) unibuf=vballoc((size_t)1024);
+                    static vbuf *utf16buf = NULL;
+                    static vbuf *utf8buf  = NULL;
+                    if (!utf16buf) utf16buf = vballoc((size_t)1024);
+                    if (!utf8buf)  utf8buf  = vballoc((size_t)1024);
 
                     // splint barfed on the following lines
-                    //VBUF_STATIC(strbuf, 1024);
-                    //VBUF_STATIC(unibuf, 1024);
+                    //VBUF_STATIC(utf16buf, 1024);
+                    //VBUF_STATIC(utf8buf, 1024);
 
                     //need UTF-16 zero-termination
-                    vbset(strbuf, mo_ptr->elements[x]->data, mo_ptr->elements[x]->size);
-                    vbappend(strbuf, "\0\0", (size_t)2);
+                    vbset(utf16buf, mo_ptr->elements[x]->data, mo_ptr->elements[x]->size);
+                    vbappend(utf16buf, "\0\0", (size_t)2);
                     DEBUG_INDEX(("Iconv in:\n"));
-                    DEBUG_HEXDUMPC(strbuf->b, strbuf->dlen, 0x10);
-                    rc = vb_utf16to8(unibuf, strbuf->b, strbuf->dlen);
+                    DEBUG_HEXDUMPC(utf16buf->b, utf16buf->dlen, 0x10);
+                    rc = vb_utf16to8(utf8buf, utf16buf->b, utf16buf->dlen);
                     if (rc == (size_t)-1) {
-                        free(unibuf->b);
                         DEBUG_EMAIL(("Failed to convert utf-16 to utf-8\n"));
                     }
                     else {
                         free(mo_ptr->elements[x]->data);
-                        mo_ptr->elements[x]->size = unibuf->dlen;
-                        mo_ptr->elements[x]->data = xmalloc(unibuf->dlen);
-                        memcpy(mo_ptr->elements[x]->data, unibuf->b, unibuf->dlen);
+                        mo_ptr->elements[x]->size = utf8buf->dlen;
+                        mo_ptr->elements[x]->data = xmalloc(utf8buf->dlen);
+                        memcpy(mo_ptr->elements[x]->data, utf8buf->b, utf8buf->dlen);
                     }
                     DEBUG_INDEX(("Iconv out:\n"));
                     DEBUG_HEXDUMPC(mo_ptr->elements[x]->data, mo_ptr->elements[x]->size, 0x10);
@@ -3061,7 +3060,7 @@
     }
 
     DEBUG_INDEX(("ID %#"PRIx64" is likely to be a description record. Count is %i (offset %#"PRIx64")\n",
-            list->id, block_head.count, list->offset));
+            list->i_id, block_head.count, list->offset));
     x = 0;
     b_ptr = buf + ((pf->do_read64) ? 0x08 : 0x04);
     while (x < block_head.count) {
@@ -3071,7 +3070,7 @@
             DEBUG_WARN(("%#"PRIx64" - Not Found\n", id2_rec.id));
         } else {
             DEBUG_INDEX(("%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %"PRIi64"(%#"PRIx64")\n",
-                         i_ptr->id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size));
+                         i_ptr->i_id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size));
             // add it to the tree
             i2_ptr = (pst_id2_ll*) xmalloc(sizeof(pst_id2_ll));
             i2_ptr->id2   = id2_rec.id2;
@@ -3393,25 +3392,25 @@
 }
 
 
-pst_index_ll* pst_getID(pst_file* pf, uint64_t id) {
+pst_index_ll* pst_getID(pst_file* pf, uint64_t i_id) {
     pst_index_ll *ptr;
     DEBUG_ENT("pst_getID");
-    if (id == 0) {
+    if (i_id == 0) {
         DEBUG_RET();
         return NULL;
     }
 
-    //if (id & 1) DEBUG_INDEX(("have odd id bit %#"PRIx64"\n", id));
-    //if (id & 2) DEBUG_INDEX(("have two id bit %#"PRIx64"\n", id));
-    id -= (id & 1);
-
-    DEBUG_INDEX(("Trying to find %#"PRIx64"\n", id));
+    //if (i_id & 1) DEBUG_INDEX(("have odd id bit %#"PRIx64"\n", i_id));
+    //if (i_id & 2) DEBUG_INDEX(("have two id bit %#"PRIx64"\n", i_id));
+    i_id -= (i_id & 1);
+
+    DEBUG_INDEX(("Trying to find %#"PRIx64"\n", i_id));
     ptr = pf->i_head;
-    while (ptr && (ptr->id != id)) {
+    while (ptr && (ptr->i_id != i_id)) {
         ptr = ptr->next;
     }
-    if (ptr) {DEBUG_INDEX(("Found Value %#"PRIx64"\n", id));            }
-    else     {DEBUG_INDEX(("ERROR: Value %#"PRIx64" not found\n", id)); }
+    if (ptr) {DEBUG_INDEX(("Found Value %#"PRIx64"\n", i_id));            }
+    else     {DEBUG_INDEX(("ERROR: Value %#"PRIx64" not found\n", i_id)); }
     DEBUG_RET();
     return ptr;
 }
@@ -3433,7 +3432,7 @@
         ptr = ptr->next;
     }
     if (ptr && ptr->id) {
-        DEBUG_INDEX(("Found value %#"PRIx64"\n", ptr->id->id));
+        DEBUG_INDEX(("Found value %#"PRIx64"\n", ptr->id->i_id));
         DEBUG_RET();
         return ptr;
     }
@@ -3474,8 +3473,8 @@
     DEBUG_ENT("pst_printDptr");
     while (ptr) {
         DEBUG_INDEX(("%#"PRIx64" [%i] desc=%#"PRIx64", assoc tree=%#"PRIx64"\n", ptr->d_id, ptr->no_child,
-                    (ptr->desc       ? ptr->desc->id       : (uint64_t)0),
-                    (ptr->assoc_tree ? ptr->assoc_tree->id : (uint64_t)0)));
+                    (ptr->desc       ? ptr->desc->i_id       : (uint64_t)0),
+                    (ptr->assoc_tree ? ptr->assoc_tree->i_id : (uint64_t)0)));
         if (ptr->child) {
             pst_printDptr(pf, ptr->child);
         }
@@ -3489,7 +3488,7 @@
     pst_index_ll *ptr = pf->i_head;
     DEBUG_ENT("pst_printIDptr");
     while (ptr) {
-        DEBUG_INDEX(("%#"PRIx64" offset=%#"PRIx64" size=%#"PRIx64"\n", ptr->id, ptr->offset, ptr->size));
+        DEBUG_INDEX(("%#"PRIx64" offset=%#"PRIx64" size=%#"PRIx64"\n", ptr->i_id, ptr->offset, ptr->size));
         ptr = ptr->next;
     }
     DEBUG_RET();
@@ -3499,7 +3498,7 @@
 void pst_printID2ptr(pst_id2_ll *ptr) {
     DEBUG_ENT("pst_printID2ptr");
     while (ptr) {
-        DEBUG_INDEX(("%#"PRIx64" id=%#"PRIx64"\n", ptr->id2, (ptr->id ? ptr->id->id : (uint64_t)0)));
+        DEBUG_INDEX(("%#"PRIx64" id=%#"PRIx64"\n", ptr->id2, (ptr->id ? ptr->id->i_id : (uint64_t)0)));
         if (ptr->child) pst_printID2ptr(ptr->child);
         ptr = ptr->next;
     }
@@ -3739,8 +3738,8 @@
     size_t ret;
     char *b = NULL, *t;
     DEBUG_ENT("pst_ff_getID2data");
-    if (!(ptr->id & 0x02)) {
-        ret = pst_ff_getIDblock_dec(pf, ptr->id, &b);
+    if (!(ptr->i_id & 0x02)) {
+        ret = pst_ff_getIDblock_dec(pf, ptr->i_id, &b);
         if (h->buf) {
             *(h->buf) = b;
         } else if ((h->base64 == 1) && h->fp) {
@@ -3760,7 +3759,7 @@
     } else {
         // here we will assume it is a block that points to others
         DEBUG_READ(("Assuming it is a multi-block record because of it's id\n"));
-        ret = pst_ff_compile_ID(pf, ptr->id, h, (size_t)0);
+        ret = pst_ff_compile_ID(pf, ptr->i_id, h, (size_t)0);
     }
     DEBUG_RET();
     return ret;
--- a/src/libpst.h	Mon Mar 16 12:43:31 2009 -0700
+++ b/src/libpst.h	Mon Mar 16 18:31:39 2009 -0700
@@ -127,7 +127,7 @@
 
 
 typedef struct pst_index_tree32 {
-    uint32_t id;
+    uint32_t i_id;
     uint32_t offset;
     uint32_t size;
     int32_t  u1;
@@ -136,7 +136,7 @@
 
 
 typedef struct pst_index_tree {
-    uint64_t id;
+    uint64_t i_id;
     uint64_t offset;
     uint64_t size;
     int64_t  u1;
@@ -405,7 +405,7 @@
     size_t      size;
     uint64_t    id2_val;
     /** calculated from id2_val during creation of record */
-    uint64_t    id_val;
+    uint64_t    i_id;
     /** deep copy from child */
     pst_id2_ll *id2_head;
     /** 0=no attachment, 1=attach by value, 2=attach by reference, 3=attach by reference resolve, 4=attach by reference only, 5=embedded message, 6=OLE */
@@ -630,9 +630,9 @@
 int            pst_getBlockOffsetPointer(pst_file *pf, pst_id2_ll *i2_head, pst_subblocks *subblocks, uint32_t offset, pst_block_offset_pointer *p);
 int            pst_getBlockOffset(char *buf, size_t read_size, uint32_t i_offset, uint32_t offset, pst_block_offset *p);
 pst_id2_ll* pst_build_id2(pst_file *pf, pst_index_ll* list);
-pst_index_ll*  pst_getID(pst_file* pf, uint64_t id);
+pst_index_ll*  pst_getID(pst_file* pf, uint64_t i_id);
 pst_id2_ll* pst_getID2(pst_id2_ll * ptr, uint64_t id);
-pst_desc_ll*   pst_getDptr(pst_file *pf, uint64_t id);
+pst_desc_ll*   pst_getDptr(pst_file *pf, uint64_t d_id);
 size_t         pst_read_block_size(pst_file *pf, int64_t offset, size_t size, char **buf);
 int            pst_decrypt(uint64_t id, char *buf, size_t size, unsigned char type);
 uint64_t       pst_getIntAt(pst_file *pf, char *buf);
--- a/src/lspst.c	Mon Mar 16 12:43:31 2009 -0700
+++ b/src/lspst.c	Mon Mar 16 18:31:39 2009 -0700
@@ -59,7 +59,7 @@
             ff.skip_count++;
         }
         else {
-            DEBUG_MAIN(("main: Desc Email ID %"PRIx64" [d_ptr->d_id = %"PRIx64"]\n", d_ptr->desc->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 @ %p.\n", item));
--- a/src/readpst.c	Mon Mar 16 12:43:31 2009 -0700
+++ b/src/readpst.c	Mon Mar 16 18:31:39 2009 -0700
@@ -137,7 +137,7 @@
             ff.skip_count++;
         }
         else {
-            DEBUG_MAIN(("main: Desc Email ID %#"PRIx64" [d_ptr->d_id = %#"PRIx64"]\n", d_ptr->desc->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"));
@@ -410,6 +410,7 @@
 void write_email_body(FILE *f, char *body) {
     char *n = body;
     DEBUG_ENT("write_email_body");
+    DEBUG_INFO(("buffer pointer %p\n", body));
     while (n) {
         if (strncmp(body, "From ", 5) == 0)
             fprintf(f, ">");
@@ -731,6 +732,16 @@
                                                     : attach->filename1.str;
     DEBUG_ENT("write_separate_attachment");
 
+    if (!attach->data) {
+        // make sure we can fetch data from the id
+        pst_index_ll *ptr = pst_getID(pst, attach->i_id);
+        if (!ptr) {
+            DEBUG_WARN(("Couldn't find i_id %#"PRIx64". Cannot save attachment to file\n", attach->i_id));
+            DEBUG_RET();
+            return;
+        }
+    }
+
     check_filename(f_name);
     if (!attach_filename) {
         // generate our own (dummy) filename for the attachement
@@ -755,7 +766,7 @@
         WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp));
     } else {
         if (attach->data)
-            pst_fwrite(attach->data, 1, attach->size, fp);
+            pst_fwrite(attach->data, (size_t)1, attach->size, fp);
         else {
             (void)pst_attach_to_file(pst, attach, fp);
         }
@@ -772,7 +783,7 @@
     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->id_val);
+    ptr = pst_getID(pf, attach->i_id);
 
     pst_desc_ll d_ptr;
     d_ptr.d_id        = 0;
@@ -799,7 +810,7 @@
     char *attach_filename;
     char *enc = NULL; // base64 encoded attachment
     DEBUG_ENT("write_inline_attachment");
-    DEBUG_EMAIL(("Attachment Size is %i, pointer %p, id %d\n", attach->size, attach->data, attach->id_val));
+    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);
         if (!enc) {
@@ -810,7 +821,7 @@
     }
     else {
         // make sure we can fetch data from the id
-        pst_index_ll *ptr = pst_getID(pst, attach->id_val);
+        pst_index_ll *ptr = pst_getID(pst, attach->i_id);
         if (!ptr) {
             DEBUG_WARN(("Couldn't find ID pointer. Cannot save attachment to file\n"));
             DEBUG_RET();
@@ -1023,7 +1034,7 @@
         size_t rc;
         DEBUG_EMAIL(("Convert %s utf-8 to %s\n", mime, charset));
         vbuf *newer = vballoc(2);
-        rc = vb_utf8to8bit(newer, body->str, strlen(body->str) + 1, charset);
+        rc = vb_utf8to8bit(newer, body->str, strlen(body->str), charset);
         if (rc == (size_t)-1) {
             // unable to convert, change the charset to utf8
             free(newer->b);
@@ -1031,6 +1042,9 @@
             charset = "utf-8";
         }
         else {
+            // null terminate the output string
+            vbgrow(newer, 1);
+            newer->b[newer->dlen] = '\0';
             free(body->str);
             body->str = newer->b;
         }
@@ -1323,10 +1337,12 @@
                 find_rfc822_headers(extra_mime_headers);
                 write_embedded_message(f_output, attach, boundary, pst, extra_mime_headers);
             }
-            else if (mode == MODE_SEPARATE && !mode_MH)
-                write_separate_attachment(f_name, attach, ++attach_num, pst);
-            else
-                write_inline_attachment(f_output, attach, boundary, pst);
+            else if (attach->data || attach->i_id) {
+                if (mode == MODE_SEPARATE && !mode_MH)
+                    write_separate_attachment(f_name, attach, ++attach_num, pst);
+                else
+                    write_inline_attachment(f_output, attach, boundary, pst);
+            }
         }
     }
 
--- a/src/vbuf.c	Mon Mar 16 12:43:31 2009 -0700
+++ b/src/vbuf.c	Mon Mar 16 18:31:39 2009 -0700
@@ -100,11 +100,10 @@
     size_t icresult     = (size_t)-1;
     size_t outbytesleft = 0;
     char *outbuf        = NULL;
+    int   myerrno;
 
     ASSERT(unicode_up, "vb_utf16to8() called before unicode started.");
-
-    if (2 > dest->blen) vbresize(dest, 2);
-    dest->dlen = 0;
+    vbresize(dest, iblen);
 
     //Bad Things can happen if a non-zero-terminated utf16 string comes through here
     if (!utf16_is_terminated(inbuf, iblen))
@@ -114,12 +113,13 @@
         outbytesleft = dest->blen - dest->dlen;
         outbuf = dest->b + dest->dlen;
         icresult = iconv(i16to8, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
+        myerrno  = errno;
         dest->dlen = outbuf - dest->b;
-        vbgrow(dest, inbytesleft);
-    } while ((size_t)-1 == icresult && E2BIG == errno);
+        if (inbytesleft) vbgrow(dest, inbytesleft);
+    } while ((size_t)-1 == icresult && E2BIG == myerrno);
 
     if (icresult == (size_t)-1) {
-        DEBUG_WARN(("iconv failure: %s\n", strerror(errno)));
+        DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
         unicode_init();
         return (size_t)-1;
     }
@@ -158,20 +158,21 @@
     size_t icresult     = (size_t)-1;
     size_t outbytesleft = 0;
     char *outbuf        = NULL;
+    int   myerrno;
 
     vbresize(dest, 2*iblen);
-    dest->dlen = 0;
 
     do {
         outbytesleft = dest->blen - dest->dlen;
         outbuf = dest->b + dest->dlen;
         icresult = iconv(conversion, (ICONV_CONST char**)&inbuf, &inbytesleft, &outbuf, &outbytesleft);
+        myerrno  = errno;
         dest->dlen = outbuf - dest->b;
         if (inbytesleft) vbgrow(dest, 2*inbytesleft);
-    } while ((size_t)-1 == icresult && E2BIG == errno);
+    } while ((size_t)-1 == icresult && E2BIG == myerrno);
 
     if (icresult == (size_t)-1) {
-        WARN(("iconv failure: %s\n", strerror(errno)));
+        DEBUG_WARN(("iconv failure: %s\n", strerror(myerrno)));
         unicode_init();
         return (size_t)-1;
     }
@@ -287,7 +288,6 @@
 void vbset(vbuf * vb, void *b, size_t len)      // set vbuf b size=len, resize if necessary, relen = how much to over-allocate
 {
     vbresize(vb, len);
-
     memcpy(vb->b, b, len);
     vb->dlen = len;
 }