changeset 94:997cf1373f9e

fix base64 encoding that could create long lines
author Carl Byington <carl@five-ten-sg.com>
date Tue, 09 Sep 2008 11:11:56 -0700
parents cb14583c119a
children ff1743cbe4aa
files regression/regression-tests.bash src/libpst.c src/libpst.h src/libstrfunc.c src/libstrfunc.h
diffstat 5 files changed, 119 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/regression/regression-tests.bash	Thu Aug 28 15:25:53 2008 -0700
+++ b/regression/regression-tests.bash	Tue Sep 09 11:11:56 2008 -0700
@@ -28,10 +28,13 @@
 fi
 
 $val  ../src/pst2ldif -b 'o=ams-cc.com, c=US' -c 'newPerson' ams.pst >ams.err  2>&1
-$val  ../src/readpst -cv    -o output1 ams.pst                       >out1.err 2>&1
+
+$val  ../src/readpst -cv    -o output1 -d dumper ams.pst             >out1.err 2>&1
+      ../src/readpstlog -f I dumper >ams1.log
+
 $val  ../src/readpst -cl -r -o output2 ams.pst                       >out2.err 2>&1
 $val  ../src/readpst -S     -o output3 ams.pst                       >out3.err 2>&1
-$val  ../src/readpst -M     -o output4 -d dumper ams.pst              >out4.err 2>&1
+$val  ../src/readpst -M     -o output4 -d dumper ams.pst             >out4.err 2>&1
       ../src/readpstlog -f I dumper >ams.log
 
 $val  ../src/readpst        -o output5 -d dumper mbmg.archive.pst    >out5.err 2>&1
@@ -43,8 +46,8 @@
 $val  ../src/readpst -cv    -o output7 -d dumper sample_64.pst       >out7.err 2>&1
       ../src/readpstlog -f I dumper >sample_64.log
 
-$val  ../src/readpst -cv    -o output8 -d dumper big_mail.pst        >out8.err 2>&1
-      ../src/readpstlog -f I dumper >big_mail.log
+#$val  ../src/readpst -cv    -o output8 -d dumper big_mail.pst        >out8.err 2>&1
+#      ../src/readpstlog -f I dumper >big_mail.log
 
 $val  ../src/readpst -cv    -o output9 -d dumper Single2003-read.pst >out9.err 2>&1
       ../src/readpstlog -f I dumper >Single2003-read.log
--- a/src/libpst.c	Thu Aug 28 15:25:53 2008 -0700
+++ b/src/libpst.c	Tue Sep 09 11:11:56 2008 -0700
@@ -268,7 +268,7 @@
 size_t pst_attach_to_mem(pst_file *pf, pst_item_attach *attach, char **b){
     size_t size=0;
     pst_index_ll *ptr;
-    pst_holder h = {b, NULL, 0, "", 0};
+    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);
@@ -289,7 +289,7 @@
 
 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) {
     pst_index_ll *ptr;
-    pst_holder h = {NULL, fp, 0, "", 0};
+    pst_holder h = {NULL, fp, 0};
     size_t size = 0;
     int32_t x;
     DEBUG_ENT("pst_attach_to_file");
@@ -319,7 +319,7 @@
 
 size_t pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE* fp) {
     pst_index_ll *ptr;
-    pst_holder h = {NULL, fp, 1, "", 0};
+    pst_holder h = {NULL, fp, 1};
     size_t size = 0;
     int32_t x;
     char *c;
@@ -338,12 +338,6 @@
             //     }
             // }
             size = pst_ff_getID2data(pf, ptr, &h);
-            // will need to encode any bytes left over
-            c = base64_encode(h.base64_extra_chars, (size_t)h.base64_extra);
-            if (c) {
-                (void)pst_fwrite(c, (size_t)1, strlen(c), fp);
-                free(c);    // caught by valgrind
-            }
         } else {
             DEBUG_WARN(("Couldn't find ID pointer. Cannot save attachment to Base64\n"));
         }
@@ -1241,36 +1235,39 @@
             // each attachment
             attach = item->attach;
             while (attach) {
-              if ((id_ptr = pst_getID2(id2_head, attach->id2_val))) {
-                  // 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.
-                  if ((list = pst_parse_block(pf, id_ptr->id, NULL, NULL)) == NULL) {
-                      DEBUG_WARN(("ERROR error processing an attachment record\n"));
-                      attach = attach->next;
-                      continue;
-                  }
-                  if (pst_process(list, item, attach)) {
-                      DEBUG_WARN(("ERROR pst_process() failed with an attachment\n"));
-                      if (list) pst_free_list(list);
-                      list = NULL;
-                      attach = attach->next;
-                      continue;
-                  }
-                  if (list) pst_free_list(list);
-                  list = NULL;
-                  id_ptr = pst_getID2(id2_head, attach->id2_val);
-                  if (id_ptr) {
-                      // id2_val has been updated to the ID2 value of the datablock containing the
-                      // attachment data
-                      attach->id_val = id_ptr->id;
-                  } else {
-                      DEBUG_WARN(("have not located the correct value for the attachment [%#"PRIx64"]\n", attach->id2_val));
-                  }
-              } else {
-                  DEBUG_WARN(("ERROR cannot locate id2 value %#"PRIx64"\n", attach->id2_val));
-              }
-              attach = attach->next;
+                DEBUG_WARN(("initial attachment id2 %#"PRIx64"\n", attach->id2_val));
+                if ((id_ptr = pst_getID2(id2_head, attach->id2_val))) {
+                    DEBUG_WARN(("initial attachment id2 found id %#"PRIx64"\n", id_ptr->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.
+                    if ((list = pst_parse_block(pf, id_ptr->id, NULL, NULL)) == NULL) {
+                        DEBUG_WARN(("ERROR error processing an attachment record\n"));
+                        attach = attach->next;
+                        continue;
+                    }
+                    if (pst_process(list, item, attach)) {
+                        DEBUG_WARN(("ERROR pst_process() failed with an attachment\n"));
+                        if (list) pst_free_list(list);
+                        list = NULL;
+                        attach = attach->next;
+                        continue;
+                    }
+                    if (list) pst_free_list(list);
+                    list = NULL;
+                    id_ptr = pst_getID2(id2_head, attach->id2_val);
+                    if (id_ptr) {
+                        DEBUG_WARN(("second pass attachment updating id2 found id %#"PRIx64"\n", id_ptr->id));
+                        // id2_val has been updated to the ID2 value of the datablock containing the
+                        // attachment data
+                        attach->id_val = id_ptr->id;
+                    } else {
+                        DEBUG_WARN(("have not located the correct value for the attachment [%#"PRIx64"]\n", attach->id2_val));
+                    }
+                } else {
+                    DEBUG_WARN(("ERROR cannot locate id2 value %#"PRIx64"\n", attach->id2_val));
+                }
+                attach = attach->next;
             }
         }
     }
@@ -1620,6 +1617,7 @@
                     na_ptr->items[x]->extra = mapptr->data;
                 }
                 else {
+                    DEBUG_WARN(("Missing assertion failure\n"));
                     // nothing, should be assertion failure here
                 }
             } else {
@@ -2184,7 +2182,6 @@
                     MALLOC_EMAIL(item);
                     LIST_COPY(item->email->header, (char*));
                     DEBUG_EMAIL(("%s\n", item->email->header));
-                    DEBUG_EMAIL(("NOT PRINTED\n"));
                     break;
                 case 0x0C17: // PR_REPLY_REQUESTED
                     DEBUG_EMAIL(("Reply Requested - "));
@@ -4406,7 +4403,7 @@
 size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_index2_ll *id2_head, char** buf) {
     size_t ret;
     pst_index_ll* ptr;
-    pst_holder h = {buf, NULL, 0, "", 0};
+    pst_holder h = {buf, NULL, 0};
     DEBUG_ENT("pst_ff_getID2block");
     ptr = pst_getID2(id2_head, id2);
 
@@ -4458,6 +4455,9 @@
     uint16_t count, y;
     char *buf3 = NULL, *buf2 = NULL, *t;
     char *b_ptr;
+    int  line_count = 0;
+    char      base64_extra_chars[3];
+    uint32_t  base64_extra = 0;
     pst_block_hdr  block_hdr;
     pst_table3_rec table3_rec;  //for type 3 (0x0101) blocks
 
@@ -4498,6 +4498,7 @@
     }
     count = block_hdr.type;
     b_ptr = buf3 + 8;
+    line_count = 0;
     for (y=0; y<count; y++) {
         b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
         z = pst_ff_getIDblock_dec(pf, table3_rec.id, &buf2);
@@ -4513,17 +4514,23 @@
             DEBUG_READ(("appending read data of size %i onto main buffer from pos %i\n", z, size));
             memcpy(&((*(h->buf))[size]), buf2, z);
         } else if ((h->base64 == 1) && h->fp) {
-            // include any byte left over from the last one encoding
-            buf2 = (char*)realloc(buf2, z+h->base64_extra);
-            memmove(buf2+h->base64_extra, buf2, z);
-            memcpy(buf2, h->base64_extra_chars, h->base64_extra);
-            z += h->base64_extra;
-
-            b = z % 3; // find out how many bytes will be left over after the encoding.
-            // and save them
-            memcpy(h->base64_extra_chars, &(buf2[z-b]), b);
-            h->base64_extra = b;
-            t = base64_encode(buf2, z-b);
+            if (base64_extra) {
+                // include any bytes left over from the last encoding
+                buf2 = (char*)realloc(buf2, z+base64_extra);
+                memmove(buf2+base64_extra, buf2, z);
+                memcpy(buf2, base64_extra_chars, base64_extra);
+                z += base64_extra;
+            }
+
+            // find out how many bytes will be left over after this encoding and save them
+            base64_extra = z % 3;
+            if (base64_extra) {
+                z -= base64_extra;
+                memcpy(base64_extra_chars, buf2+z, base64_extra);
+            }
+
+            // encode this chunk
+            t = base64_encode_multiple(buf2, z, &line_count);
             if (t) {
                 DEBUG_READ(("writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size));
                 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
@@ -4537,6 +4544,14 @@
         }
         size += z;
     }
+    if ((h->base64 == 1) && h->fp && base64_extra) {
+        // need to encode any bytes left over
+        t = base64_encode_multiple(base64_extra_chars, (size_t)base64_extra, &line_count);
+        if (t) {
+            (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
+            free(t);    // caught by valgrind
+        }
+    }
     free(buf3);
     if (buf2) free(buf2);
     DEBUG_RET();
--- a/src/libpst.h	Thu Aug 28 15:25:53 2008 -0700
+++ b/src/libpst.h	Tue Sep 09 11:11:56 2008 -0700
@@ -537,11 +537,9 @@
 
 
 typedef struct pst_holder {
-    char **buf;
-    FILE *    fp;
-    int       base64;
-    char      base64_extra_chars[3];
-    uint32_t  base64_extra;
+    char  **buf;
+    FILE   *fp;
+    int     base64;
 } pst_holder;
 
 
--- a/src/libstrfunc.c	Thu Aug 28 15:25:53 2008 -0700
+++ b/src/libstrfunc.c	Tue Sep 09 11:11:56 2008 -0700
@@ -7,47 +7,61 @@
 #include "libstrfunc.h"
 
 
-static unsigned char _sf_uc_ib[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/==";
+static char base64_code_chars[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/==";
 
-char *base64_encode(void *data, size_t size) {
+void base64_append(char **ou, int *line_count, char data)
+{
+    if (*line_count == 76) {
+        *(*ou)++ = '\n';
+        *line_count = 0;
+    }
+    *(*ou)++ = data;
+    (*line_count)++;
+}
+
+
+char *base64_encode(void *data, size_t size)
+{
+    int line_count = 0;
+    return base64_encode_multiple(data, size, &line_count);
+}
+
+
+char *base64_encode_multiple(void *data, size_t size, int *line_count)
+{
     char *output;
-    register char *ou;
-    register unsigned char *p=(unsigned char *)data;
-    register void * dte = (void*)((char*)data + size);
-    register int nc=0;
+    char *ou;
+    unsigned char *p   = (unsigned char *)data;
+    unsigned char *dte = p + size;
 
-    if ( data == NULL || size == 0 ) return NULL;
+    if (data == NULL || size == 0) return NULL;
 
     ou = output = (char *)malloc(size / 3 * 4 + (size / 57) + 5);
-    if(!output) return NULL;
+    if (!output) return NULL;
 
-    while((char *)dte - (char *)p >= 3) {
+    while((dte-p) >= 3) {
         unsigned char x = p[0];
         unsigned char y = p[1];
         unsigned char z = p[2];
-        ou[0] = _sf_uc_ib[ x >> 2 ];
-        ou[1] = _sf_uc_ib[ ((x & 0x03) << 4) | (y >> 4) ];
-        ou[2] = _sf_uc_ib[ ((y & 0x0F) << 2) | (z >> 6) ];
-        ou[3] = _sf_uc_ib[ z & 0x3F ];
+        base64_append(&ou, line_count, base64_code_chars[ x >> 2 ]);
+        base64_append(&ou, line_count, base64_code_chars[ ((x & 0x03) << 4) | (y >> 4) ]);
+        base64_append(&ou, line_count, base64_code_chars[ ((y & 0x0F) << 2) | (z >> 6) ]);
+        base64_append(&ou, line_count, base64_code_chars[ z & 0x3F ]);
         p+=3;
-        ou+=4;
-        nc+=4;
-        if(!(nc % 76)) *ou++='\n';
     };
-    if ((char *)dte - (char *)p == 2) {
-        *ou++ = _sf_uc_ib[ *p >> 2 ];
-        *ou++ = _sf_uc_ib[ ((*p & 0x03) << 4) | (p[1] >> 4) ];
-        *ou++ = _sf_uc_ib[ ((p[1] & 0x0F) << 2) ];
-        *ou++ = '=';
-    } else if((char *)dte - (char *)p == 1) {
-        *ou++ = _sf_uc_ib[ *p >> 2 ];
-        *ou++ = _sf_uc_ib[ ((*p & 0x03) << 4) ];
-        *ou++ = '=';
-        *ou++ = '=';
+    if ((dte-p) == 2) {
+        base64_append(&ou, line_count, base64_code_chars[ *p >> 2 ]);
+        base64_append(&ou, line_count, base64_code_chars[ ((*p & 0x03) << 4) | (p[1] >> 4) ]);
+        base64_append(&ou, line_count, base64_code_chars[ ((p[1] & 0x0F) << 2) ]);
+        base64_append(&ou, line_count, '=');
+    } else if ((dte-p) == 1) {
+        base64_append(&ou, line_count, base64_code_chars[ *p >> 2 ]);
+        base64_append(&ou, line_count, base64_code_chars[ ((*p & 0x03) << 4) ]);
+        base64_append(&ou, line_count, '=');
+        base64_append(&ou, line_count, '=');
     };
 
     *ou=0;
-
     return output;
 };
 
--- a/src/libstrfunc.h	Thu Aug 28 15:25:53 2008 -0700
+++ b/src/libstrfunc.h	Tue Sep 09 11:11:56 2008 -0700
@@ -1,3 +1,4 @@
 
 char * base64_encode(void *data, size_t size);
+char * base64_encode_multiple(void *data, size_t size, int *line_count);
 void hexdump(char *hbuf, int start, int stop, int ascii);