# HG changeset patch # User carl # Date 1186699594 25200 # Node ID 6fe121a971c9292ec2d30024e63a2cd127d7bb57 # Parent b2f247463b83fc57fc0610988843bc00c3e96a3a valgrind fixes diff -r b2f247463b83 -r 6fe121a971c9 ChangeLog --- a/ChangeLog Sun Jul 15 14:25:34 2007 -0700 +++ b/ChangeLog Thu Aug 09 15:46:34 2007 -0700 @@ -1,3 +1,10 @@ +LibPST 0.5.7 (2007-08-09) +=============================== + + * fix valgrind errors, using uninitialized data. + * improve debug logging and readpstlog for indented listings. + * cleanup documentation. + LibPST 0.5.6 (2007-07-15) =============================== diff -r b2f247463b83 -r 6fe121a971c9 NEWS --- a/NEWS Sun Jul 15 14:25:34 2007 -0700 +++ b/NEWS Thu Aug 09 15:46:34 2007 -0700 @@ -1,5 +1,6 @@ $Id$ +0.5.7 2007-08-09 fix valgrind errors, using uninitialized data 0.5.6 2007-07-15 handle small pst files, better decoding of 7c blocks 0.5.5 2007-07-10 merge changes from Joe Nahmias version 0.5.4 2006-02-25 add MH mode, generated filenames with no leading zeros diff -r b2f247463b83 -r 6fe121a971c9 configure.in --- a/configure.in Sun Jul 15 14:25:34 2007 -0700 +++ b/configure.in Thu Aug 09 15:46:34 2007 -0700 @@ -1,7 +1,7 @@ AC_INIT(configure.in) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(libpst,0.5.6) +AM_INIT_AUTOMAKE(libpst,0.5.7) AC_PATH_PROGS(BASH, bash) AC_LANG_CPLUSPLUS diff -r b2f247463b83 -r 6fe121a971c9 regression/regression-tests.bash --- a/regression/regression-tests.bash Sun Jul 15 14:25:34 2007 -0700 +++ b/regression/regression-tests.bash Thu Aug 09 15:46:34 2007 -0700 @@ -13,9 +13,10 @@ # ../src/readpst -o output5 mbmg.archive.pst ../src/readpst -o output1 -d dumper ams.pst - ../src/readpstlog dumper >dumperams.log + ../src/readpstlog -f I dumper >dumperams.log - ../src/readpst -o output6 -d dumper /tmp/pam.pst - ../src/readpstlog dumper >dumperpam.log +# touch /tmp/pam.pst +# ../src/readpst -o output6 -d dumper /tmp/pam.pst +# ../src/readpstlog -f I dumper >dumperpam.log rm -f dumper diff -r b2f247463b83 -r 6fe121a971c9 src/debug.c --- a/src/debug.c Sun Jul 15 14:25:34 2007 -0700 +++ b/src/debug.c Thu Aug 09 15:46:34 2007 -0700 @@ -258,6 +258,7 @@ if (curr_items == 0) return; // no items to write. index = (int*) xmalloc(index_size); + memset(index, 0, index_size); // valgrind, avoid writing uninitialized data file_pos += index_size; // write the index first, we will re-write it later, but // we want to allocate the space @@ -268,8 +269,9 @@ while (item_ptr) { file_pos = ftell(debug_fp); index[index_ptr++] = file_pos; - size = strlen(item_ptr->function)+strlen(item_ptr->file)+ - strlen(item_ptr->text) + 3; //for the three \0s + size = strlen(item_ptr->function) + + strlen(item_ptr->file) + + strlen(item_ptr->text) + 3; //for the three \0s if (buf) free(buf); buf = xmalloc(size+1); ptr = 0; @@ -387,11 +389,13 @@ struct _debug_file_rec_l lfile_rec; unsigned char rec_type; int index_size = 3 * sizeof(int); - int *index = malloc(index_size); - int index_pos, file_pos; + int index_pos, file_pos, *index; char zero='\0'; if (!debug_fp) return; // no file + index = malloc(index_size); index[0] = 1; // only one item in this index run + index[1] = 0; // valgrind, avoid writing uninitialized data + index[2] = 0; // "" index_pos = ftell(debug_fp); fwrite(index, index_size, 1, debug_fp); index[1] = ftell(debug_fp); @@ -399,11 +403,12 @@ // always use the long rec_type = 'L'; fwrite(&rec_type, 1, sizeof(char), debug_fp); - lfile_rec.type = item->type; - lfile_rec.line = item->line; lfile_rec.funcname = 0; lfile_rec.filename = strlen(item->function)+1; lfile_rec.text = lfile_rec.filename+strlen(item->file)+1; + lfile_rec.end = 0; // valgrind, avoid writing uninitialized data + lfile_rec.line = item->line; + lfile_rec.type = item->type; fwrite(&lfile_rec, sizeof(lfile_rec), 1, debug_fp); file_pos = ftell(debug_fp); @@ -423,12 +428,13 @@ } -void * xmalloc(size_t size) { +void *xmalloc(size_t size) { void *mem = malloc(size); if (!mem) { fprintf(stderr, "xMalloc: Out Of memory [req: %ld]\n", (long)size); exit(1); } + memset(mem, 0, size); // valgrind, some email attachment does not initialize the entire buffer passed to base64 encode return mem; } diff -r b2f247463b83 -r 6fe121a971c9 src/define.h --- a/src/define.h Sun Jul 15 14:25:34 2007 -0700 +++ b/src/define.h Thu Aug 09 15:46:34 2007 -0700 @@ -29,15 +29,16 @@ //number of items to save in memory between writes #define DEBUG_MAX_ITEMS 0 -#define DEBUG_FILE_NO 1 -#define DEBUG_INDEX_NO 2 -#define DEBUG_EMAIL_NO 3 -#define DEBUG_WARN_NO 4 -#define DEBUG_READ_NO 5 -#define DEBUG_INFO_NO 6 -#define DEBUG_MAIN_NO 7 -#define DEBUG_DECRYPT_NO 8 -#define DEBUG_FUNC_NO 10 +#define DEBUG_FILE_NO 1 +#define DEBUG_INDEX_NO 2 +#define DEBUG_EMAIL_NO 3 +#define DEBUG_WARN_NO 4 +#define DEBUG_READ_NO 5 +#define DEBUG_INFO_NO 6 +#define DEBUG_MAIN_NO 7 +#define DEBUG_DECRYPT_NO 8 +#define DEBUG_FUNCENT_NO 9 +#define DEBUG_FUNCRET_NO 10 #define DEBUG_HEXDUMP_NO 11 //variable number of arguments to this macro. will expand them into @@ -161,11 +162,16 @@ _debug_msg_text x;} #ifdef DEBUG_MODE_FUNC -# define DEBUG_ENT(x) \ - {MESSAGEPRINT(("Entering function %s\n",x),DEBUG_FUNC_NO);\ - _debug_func(x);} -# define DEBUG_RET() {MESSAGEPRINT(("Leaving function\n"),DEBUG_FUNC_NO);\ - _debug_func_ret();} +# define DEBUG_ENT(x) \ + { \ + _debug_func(x); \ + MESSAGEPRINT(("Entering function\n"),DEBUG_FUNCENT_NO); \ + } +# define DEBUG_RET() \ + { \ + MESSAGEPRINT(("Leaving function\n"),DEBUG_FUNCRET_NO); \ + _debug_func_ret(); \ + } #else # define DEBUG_ENT(x) {} # define DEBUG_RET() {} diff -r b2f247463b83 -r 6fe121a971c9 src/libpst.c --- a/src/libpst.c Sun Jul 15 14:25:34 2007 -0700 +++ b/src/libpst.c Thu Aug 09 15:46:34 2007 -0700 @@ -723,7 +723,7 @@ } bptr = buf; item_count = (int)(unsigned)(buf[ITEM_COUNT_OFFSET]); - memcpy(&desc_rec, buf+BACKLINK_OFFSET, sizeof(desc_rec)); + memcpy(&desc_rec.d_id, buf+BACKLINK_OFFSET, sizeof(u_int32_t)); // for valgrind, only have 3 ints here, not 4 LE32_CPU(desc_rec.d_id); if (desc_rec.d_id != linku1) { DEBUG_WARN(("Backlink %#x in this node does not match required %#x\n", desc_rec.d_id, linku1)); @@ -1083,14 +1083,14 @@ u_int32_t num_list; u_int32_t cur_list; u_int32_t block_type; - u_int32_t rec_size; + u_int32_t rec_size = 0; u_int32_t ind_ptr; unsigned char* list_start; unsigned char* t_ptr; unsigned char* fr_ptr; unsigned char* to_ptr; unsigned char* ind2_end; - unsigned char* ind2_ptr; + unsigned char* ind2_ptr = NULL; size_t read_size=0; pst_x_attrib_ll *mapptr; @@ -1188,7 +1188,6 @@ to_ptr = block_offset2.to; num_list = (to_ptr - list_start)/sizeof(table_rec); num_recs = 1; // only going to be one object in these blocks - rec_size = 0; // doesn't matter cause there is only one object } else if (block_hdr.type == 0x7CEC) { //type 2 block_type = 2; @@ -1292,6 +1291,7 @@ na_ptr->items = (struct _pst_num_item**) xmalloc(sizeof(struct _pst_num_item)*num_list); na_ptr->count_item = num_list; na_ptr->count_array = num_recs; // each record will have a record of the total number of records + for (x=0; xitems[x] = NULL; x = 0; DEBUG_EMAIL(("going to read %i (%#x) items\n", na_ptr->count_item, na_ptr->count_item)); @@ -3098,26 +3098,25 @@ int32_t _pst_free_list(pst_num_array *list) { - int32_t x = 0; pst_num_array *l; DEBUG_ENT("_pst_free_list"); while (list) { - while (x < list->count_item) { - if (list->items[x]->data) { - free (list->items[x]->data); + int32_t x = 0; + if (list->items) { + while (x < list->count_item) { + if (list->items[x]) { + if (list->items[x]->data) { + free (list->items[x]->data); + } + free (list->items[x]); + } + x++; } - if (list->items[x]) { - free (list->items[x]); - } - x++; - } - if (list->items) { free(list->items); } l = list; list = list->next; free (l); - x = 0; } DEBUG_RET(); return 1; @@ -3831,12 +3830,11 @@ DEBUG_ENT("_pst_ff_getIDblock_dec"); DEBUG_INDEX(("for id %#x\n", id)); r = _pst_ff_getIDblock(pf, id, b); - DEBUG_HEXDUMPC(*b, r, 16); int noenc = (id & 2); // disable encryption if ((pf->encryption) & !(noenc)) { _pst_decrypt(*b, r, pf->encryption); - DEBUG_HEXDUMPC(*b, r, 16); } + DEBUG_HEXDUMPC(*b, r, 16); DEBUG_RET(); return r; } diff -r b2f247463b83 -r 6fe121a971c9 src/libpst.h --- a/src/libpst.h Sun Jul 15 14:25:34 2007 -0700 +++ b/src/libpst.h Thu Aug 09 15:46:34 2007 -0700 @@ -349,7 +349,7 @@ char *filename2; char *mimetype; char *data; - size_t size; + size_t size; int32_t id2_val; int32_t id_val; // calculated from id2_val during creation of record int32_t method; diff -r b2f247463b83 -r 6fe121a971c9 src/libstrfunc.c --- a/src/libstrfunc.c Sun Jul 15 14:25:34 2007 -0700 +++ b/src/libstrfunc.c Thu Aug 09 15:46:34 2007 -0700 @@ -6,9 +6,6 @@ #include #include "libstrfunc.h" -char *_sf_b64_buf=NULL; -size_t _sf_b64_len=0; - static unsigned char _sf_uc_ib[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=="; @@ -26,44 +23,41 @@ #endif //register void *dte=data + size; register int nc=0; - + if ( data == NULL || size == 0 ) - return NULL; - - ou=output=(char *)malloc(size / 3 * 4 + (size / 50) + 5); + return NULL; + + ou=output=(char *)malloc(size / 3 * 4 + (size / 57) + 5); if(!output) - return NULL; - + return NULL; + while((char *)dte - (char *)p >= 3) { - *ou = _sf_uc_ib[ *p >> 2 ]; - ou[1] = _sf_uc_ib[ ((*p & 0x03) << 4) | (p[1] >> 4) ]; - ou[2] = _sf_uc_ib[ ((p[1] & 0x0F) << 2) | (p[2] >> 6) ]; - ou[3] = _sf_uc_ib[ p[2] & 0x3F ]; - - p+=3; - ou+=4; - - nc+=4; - if(!(nc % 76)) *ou++='\n'; + 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 ]; + 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++ = '='; + *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++ = '='; + *ou++ = _sf_uc_ib[ *p >> 2 ]; + *ou++ = _sf_uc_ib[ ((*p & 0x03) << 4) ]; + *ou++ = '='; + *ou++ = '='; }; - + *ou=0; - - _sf_b64_len = (ou - output); - - if(_sf_b64_buf) - free(_sf_b64_buf); - return _sf_b64_buf=output; + + return output; }; diff -r b2f247463b83 -r 6fe121a971c9 src/lzfu.c --- a/src/lzfu.c Sun Jul 15 14:25:34 2007 -0700 +++ b/src/lzfu.c Thu Aug 09 15:46:34 2007 -0700 @@ -1,12 +1,12 @@ /* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "define.h" @@ -25,103 +25,104 @@ #include "lzfu.h" -#define LZFU_COMPRESSED 0x75465a4c -#define LZFU_UNCOMPRESSED 0x414c454d +#define LZFU_COMPRESSED 0x75465a4c +#define LZFU_UNCOMPRESSED 0x414c454d // initital dictionary -#define LZFU_INITDICT "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \ - "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \ - "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \ - "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \ - "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \ - "\\tx" +#define LZFU_INITDICT "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \ + "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \ + "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \ + "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \ + "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \ + "\\tx" // initial length of dictionary #define LZFU_INITLENGTH 207 // header for compressed rtf typedef struct _lzfuheader { - uint32_t cbSize; - uint32_t cbRawSize; - uint32_t dwMagic; - uint32_t dwCRC; + uint32_t cbSize; + uint32_t cbRawSize; + uint32_t dwMagic; + uint32_t dwCRC; } lzfuheader; -/** - We always need to add 0x10 to the buffer offset because we need to skip past the header info +/** + We always need to add 0x10 to the buffer offset because we need to skip past the header info */ -unsigned char* lzfu_decompress (unsigned char* rtfcomp) { - // the dictionary buffer - unsigned char dict[4096]; - // the dictionary pointer - unsigned int dict_length=0; - // the header of the lzfu block - lzfuheader lzfuhdr; - // container for the data blocks - unsigned char flags; - // temp value for determining the bits in the flag - unsigned char flag_mask; - unsigned int i, in_size; - unsigned char *out_buf; - unsigned int out_ptr = 0; +unsigned char* lzfu_decompress (unsigned char* rtfcomp, size_t *size) { + // the dictionary buffer + unsigned char dict[4096]; + // the dictionary pointer + unsigned int dict_length=0; + // the header of the lzfu block + lzfuheader lzfuhdr; + // container for the data blocks + unsigned char flags; + // temp value for determining the bits in the flag + unsigned char flag_mask; + unsigned int i, in_size; + unsigned char *out_buf; + unsigned int out_ptr = 0; - memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH); - dict_length = LZFU_INITLENGTH; - memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr)); - LE32_CPU(lzfuhdr.cbSize); LE32_CPU(lzfuhdr.cbRawSize); - LE32_CPU(lzfuhdr.dwMagic); LE32_CPU(lzfuhdr.dwCRC); - /* printf("total size: %d\n", lzfuhdr.cbSize+4); - printf("raw size : %d\n", lzfuhdr.cbRawSize); - printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no")); - printf("CRC : %#x\n", lzfuhdr.dwCRC); - printf("\n");*/ - out_buf = (unsigned char*)xmalloc(lzfuhdr.cbRawSize+20); //plus 4 cause we have 2x'}' and a \0 - in_size = 0; - // we add plus one here cause when referencing an array, the index is always one less - // (ie, when accessing 2 element array, highest index is [1]) - while (in_size+0x11 < lzfuhdr.cbSize) { - memcpy(&flags, &(rtfcomp[in_size+0x10]), 1); - in_size += 1; + memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH); + dict_length = LZFU_INITLENGTH; + memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr)); + LE32_CPU(lzfuhdr.cbSize); LE32_CPU(lzfuhdr.cbRawSize); + LE32_CPU(lzfuhdr.dwMagic); LE32_CPU(lzfuhdr.dwCRC); + /* printf("total size: %d\n", lzfuhdr.cbSize+4); + printf("raw size : %d\n", lzfuhdr.cbRawSize); + printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no")); + printf("CRC : %#x\n", lzfuhdr.dwCRC); + printf("\n");*/ + out_buf = (unsigned char*)xmalloc(lzfuhdr.cbRawSize+20); //plus 4 cause we have 2x'}' and a \0 + in_size = 0; + // we add plus one here cause when referencing an array, the index is always one less + // (ie, when accessing 2 element array, highest index is [1]) + while (in_size+0x11 < lzfuhdr.cbSize) { + memcpy(&flags, &(rtfcomp[in_size+0x10]), 1); + in_size += 1; - flag_mask = 1; - while (flag_mask != 0 && in_size+0x11 < lzfuhdr.cbSize) { - if (flag_mask & flags) { - // read 2 bytes from input - unsigned short int blkhdr, offset, length; - memcpy(&blkhdr, &(rtfcomp[in_size+0x10]), 2); - LE16_CPU(blkhdr); - in_size += 2; - /* swap the upper and lower bytes of blkhdr */ - blkhdr = (((blkhdr&0xFF00)>>8)+ - ((blkhdr&0x00FF)<<8)); - /* the offset is the first 24 bits of the 32 bit value */ - offset = (blkhdr&0xFFF0)>>4; - /* the length of the dict entry are the last 8 bits */ - length = (blkhdr&0x000F)+2; - // add the value we are about to print to the dictionary - for (i=0; i < length; i++) { - unsigned char c1; - c1 = dict[(offset+i)%4096]; - dict[dict_length]=c1; - dict_length = (dict_length+1) % 4096; - out_buf[out_ptr++] = c1; + flag_mask = 1; + while (flag_mask != 0 && in_size+0x11 < lzfuhdr.cbSize) { + if (flag_mask & flags) { + // read 2 bytes from input + unsigned short int blkhdr, offset, length; + memcpy(&blkhdr, &(rtfcomp[in_size+0x10]), 2); + LE16_CPU(blkhdr); + in_size += 2; + /* swap the upper and lower bytes of blkhdr */ + blkhdr = (((blkhdr&0xFF00)>>8)+ + ((blkhdr&0x00FF)<<8)); + /* the offset is the first 24 bits of the 32 bit value */ + offset = (blkhdr&0xFFF0)>>4; + /* the length of the dict entry are the last 8 bits */ + length = (blkhdr&0x000F)+2; + // add the value we are about to print to the dictionary + for (i=0; i < length; i++) { + unsigned char c1; + c1 = dict[(offset+i)%4096]; + dict[dict_length]=c1; + dict_length = (dict_length+1) % 4096; + out_buf[out_ptr++] = c1; + } + } else { + // uncompressed chunk (single byte) + char c1 = rtfcomp[in_size+0x10]; + in_size ++; + dict[dict_length] = c1; + dict_length = (dict_length+1)%4096; + out_buf[out_ptr++] = c1; + } + flag_mask <<= 1; + } } - } else { - // uncompressed chunk (single byte) - char c1 = rtfcomp[in_size+0x10]; - in_size ++; - dict[dict_length] = c1; - dict_length = (dict_length+1)%4096; - out_buf[out_ptr++] = c1; - } - flag_mask <<= 1; - } - } - // the compressed version doesn't appear to drop the closing braces onto the doc. - // we should do that - out_buf[out_ptr++] = '}'; - out_buf[out_ptr++] = '}'; - out_buf[out_ptr++] = '\0'; - return out_buf; + // the compressed version doesn't appear to drop the closing braces onto the doc. + // we should do that + out_buf[out_ptr++] = '}'; + out_buf[out_ptr++] = '}'; + out_buf[out_ptr++] = '\0'; + *size = out_ptr; + return out_buf; } diff -r b2f247463b83 -r 6fe121a971c9 src/lzfu.h --- a/src/lzfu.h Sun Jul 15 14:25:34 2007 -0700 +++ b/src/lzfu.h Thu Aug 09 15:46:34 2007 -0700 @@ -1,4 +1,4 @@ #ifndef LZFU_H #define LZFU_H -unsigned char* lzfu_decompress (unsigned char* rtfcomp); +unsigned char* lzfu_decompress (unsigned char* rtfcomp, size_t *size); #endif diff -r b2f247463b83 -r 6fe121a971c9 src/readpst.c --- a/src/readpst.c Sun Jul 15 14:25:34 2007 -0700 +++ b/src/readpst.c Thu Aug 09 15:46:34 2007 -0700 @@ -1005,6 +1005,7 @@ if (current_attach->data) { fwrite(enc, 1, strlen(enc), f_output); DEBUG_EMAIL(("Attachment Size after encoding is %i\n", strlen(enc))); + free(enc); // caught by valgrind } else { pst_attach_to_file_base64(pst, current_attach, f_output); } @@ -1202,25 +1203,36 @@ fprintf(f_output, "\n"); } removeCR(item->email->body); - if (base64_body) - write_email_body(f_output, base64_encode(item->email->body, strlen(item->email->body))); - else + if (base64_body) { + char *enc = base64_encode(item->email->body, strlen(item->email->body)); + if (enc) { + write_email_body(f_output, enc); + free(enc); + } + } + else { write_email_body(f_output, item->email->body); + } } if (item->email->htmlbody) { if (boundary) { fprintf(f_output, "\n--%s\n", boundary); fprintf(f_output, "Content-type: text/html\n"); - if (base64_body) - fprintf(f_output, "Content-Transfer-Encoding: base64\n"); + if (base64_body) fprintf(f_output, "Content-Transfer-Encoding: base64\n"); fprintf(f_output, "\n"); } removeCR(item->email->htmlbody); - if (base64_body) - write_email_body(f_output, base64_encode(item->email->htmlbody, strlen(item->email->htmlbody))); - else + if (base64_body) { + char *enc = base64_encode(item->email->htmlbody, strlen(item->email->htmlbody)); + if (enc) { + write_email_body(f_output, enc); + free(enc); + } + } + else { write_email_body(f_output, item->email->htmlbody); + } } if (item->email->rtf_compressed && save_rtf) { @@ -1229,7 +1241,7 @@ memset(current_attach, 0, sizeof(pst_item_attach)); current_attach->next = item->attach; item->attach = current_attach; - current_attach->data = lzfu_decompress(item->email->rtf_compressed); + current_attach->data = lzfu_decompress(item->email->rtf_compressed, ¤t_attach->size); current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); strcpy(current_attach->filename2, RTF_ATTACH_NAME); current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); @@ -1265,7 +1277,6 @@ } // attachments - base64_body = 0; attach_num = 0; for (current_attach = item->attach; current_attach; @@ -1323,19 +1334,28 @@ fprintf(f_output, "LABEL;TYPE=home:%s\n", rfc2426_escape(contact->home_address)); } if (contact->business_address) { - fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", - (!contact->business_po_box) ? "" : rfc2426_escape(contact->business_po_box), - "", // extended Address - (!contact->business_street) ? "" : rfc2426_escape(contact->business_street), - (!contact->business_city) ? "" : rfc2426_escape(contact->business_city), - (!contact->business_state) ? "" : rfc2426_escape(contact->business_state), - (!contact->business_postal_code) ? "" : rfc2426_escape(contact->business_postal_code), - (!contact->business_country) ? "" : rfc2426_escape(contact->business_country)); + // these should be equivalent, but valgrind complains about the single large fprintf + // + char *ab = (!contact->business_po_box ) ? "" : rfc2426_escape(contact->business_po_box ); + char *ac = (!contact->business_street ) ? "" : rfc2426_escape(contact->business_street ); + char *ad = (!contact->business_city ) ? "" : rfc2426_escape(contact->business_city ); + char *ae = (!contact->business_state ) ? "" : rfc2426_escape(contact->business_state ); + char *af = (!contact->business_postal_code) ? "" : rfc2426_escape(contact->business_postal_code); + char *ag = (!contact->business_country ) ? "" : rfc2426_escape(contact->business_country ); + fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", ab, "", ac, ad, ae, af, ag); + //fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", + // (!contact->business_po_box) ? "" : rfc2426_escape(contact->business_po_box), + // "", // extended Address + // (!contact->business_street) ? "" : rfc2426_escape(contact->business_street), + // (!contact->business_city) ? "" : rfc2426_escape(contact->business_city), + // (!contact->business_state) ? "" : rfc2426_escape(contact->business_state), + // (!contact->business_postal_code) ? "" : rfc2426_escape(contact->business_postal_code), + // (!contact->business_country) ? "" : rfc2426_escape(contact->business_country)); fprintf(f_output, "LABEL;TYPE=work:%s\n", rfc2426_escape(contact->business_address)); } if (contact->other_address) { fprintf(f_output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", - (!contact->other_po_box) ? "" : rfc2426_escape(contact->business_po_box), + (!contact->other_po_box) ? "" : rfc2426_escape(contact->other_po_box), "", // extended Address (!contact->other_street) ? "" : rfc2426_escape(contact->other_street), (!contact->other_city) ? "" : rfc2426_escape(contact->other_city), diff -r b2f247463b83 -r 6fe121a971c9 src/readpstlog.c --- a/src/readpstlog.c Sun Jul 15 14:25:34 2007 -0700 +++ b/src/readpstlog.c Thu Aug 09 15:46:34 2007 -0700 @@ -20,191 +20,230 @@ int is_in(int a, int *b, int c); int main(int argc, char** argv) { - int *i=NULL, x, ptr, stop=0, flag; - char *fname, *buf, format, rec_type; - unsigned char version; - int *show_type=NULL, show_size=0; - int *ex_type=NULL, ex_size=0; - unsigned int funcname, filename, text, end, dtype, line, c; - FILE *fp; - struct _debug_file_rec_m mfile_rec; - struct _debug_file_rec_l lfile_rec; + int level = 0; + int *i=NULL, x, ptr, stop=0, flag; + char *fname, *buf, rec_type; + unsigned char version; + int *show_type=NULL, show_size=0; + int *ex_type=NULL, ex_size=0; + unsigned int funcname, filename, text, end, dtype, line, c; + FILE *fp; + struct _debug_file_rec_m mfile_rec; + struct _debug_file_rec_l lfile_rec; + char format = 'D'; // default + while ((c = getopt(argc, argv, "f:t:x:")) != -1) { + switch(c) { + case 'f': + // change the output format + format = toupper(optarg[0]); + break; + case 't': + //change the type of statements shown + show_size = split_args(optarg, &show_type); + // type = atoi(optarg); + break; + case 'x': + // change the type of statements excluded + ex_size = split_args(optarg, &ex_type); + break; + } + } + if (argc > optind) { + fname = argv[optind++]; + } else { + usage(); + exit(2); + } - while ((c = getopt(argc, argv, "f:t:x:")) != -1) { - switch(c) { - case 'f': - // change the output format - format = toupper(optarg[0]); - break; - case 't': - //change the type of statements shown - show_size = split_args(optarg, &show_type); - // type = atoi(optarg); - break; - case 'x': - // change the type of statements excluded - ex_size = split_args(optarg, &ex_type); - break; - } - } - if (argc > optind) { - fname = argv[optind++]; - } else { - usage(); - exit(2); - } + fp = fopen(fname, "rb"); + if (fp == NULL) { + printf("Error. couldn't open debug file\n"); + return 2; + } + if (get(&version, sizeof(char), 1, fp)==0) { + printf("Error. could not read version byte from front of file"); + return 3; + } - fp = fopen(fname, "rb"); - if (fp == NULL) { - printf("Error. couldn't open debug file\n"); - return 2; - } - if (get(&version, sizeof(char), 1, fp)==0) { - printf("Error. could not read version byte from front of file"); - return 3; - } + if (version > DEBUG_VERSION) { + printf("Version number is higher than the format I know about."); + return 4; + } - if (version > DEBUG_VERSION) { - printf("Version number is higher than the format I know about."); - return 4; - } - - buf = (char*) xmalloc(BUF_SIZE); + buf = (char*) xmalloc(BUF_SIZE); - while (!stop) { - if (fread(&x, sizeof(int), 1, fp)<=0) { - break; - } - ptr = 0; - if (x > 0) { - if (i != NULL) - free(i); - i = (int*)xmalloc(sizeof(int)*(x+1)); - // plus 1 cause we want to read the offset of the next index - if (get(i, sizeof(int), x+1, fp)==0) { - // we have reached the end of the debug file - printf("oh dear. we must now end\n"); - break; - } - while (ptr < x) { - fseek(fp,i[ptr++], SEEK_SET); - get(&rec_type, 1, sizeof(char), fp); - if (rec_type == 'L') { - get(&lfile_rec, sizeof(lfile_rec), 1, fp); - funcname=lfile_rec.funcname; - filename=lfile_rec.filename; - text = lfile_rec.text; - end = lfile_rec.end; - dtype = lfile_rec.type; - line = lfile_rec.line; - } else if (rec_type == 'M') { - get(&mfile_rec, sizeof(mfile_rec), 1, fp); - funcname = mfile_rec.funcname; - filename = mfile_rec.filename; - text = mfile_rec.text; - end = mfile_rec.end; - dtype = mfile_rec.type; - line = mfile_rec.line; - } - if ((show_type == NULL || is_in(dtype, show_type, show_size)) - && (ex_type == NULL || !is_in(dtype, ex_type, ex_size))) { - c = 0; flag = 0; - while (c < end) { - if (c + (BUF_SIZE-1) < end) { - get(buf, 1, BUF_SIZE-1, fp); - buf[BUF_SIZE-1] = '\0'; - c += BUF_SIZE-1; - } else { - get(buf, 1, end-c, fp); - buf[end-c] = '\0'; - c = end; - } - if (flag == 0) { - if (format=='T') { // text format - printf("%s[%d]: %s", &buf[funcname], line, &buf[text]); - } else { - printf("Type: %d\nFile[line]: %s[%d]\nFunction:%s\nText:%s", dtype, - &buf[filename], line, &buf[funcname], &buf[text]); - } - flag = 1; - } else { - printf("%s", buf); - } - } - printf("\n"); + while (!stop) { + if (fread(&x, sizeof(int), 1, fp)<=0) break; + ptr = 0; + if (x > 0) { + if (i) free(i); + i = (int*)xmalloc(sizeof(int)*(x+1)); + // plus 1 cause we want to read the offset of the next index + if (get(i, sizeof(int), x+1, fp)==0) { + // we have reached the end of the debug file + printf("oh dear. we must now end\n"); + break; + } + while (ptr < x) { + fseek(fp,i[ptr++], SEEK_SET); + get(&rec_type, 1, sizeof(char), fp); + if (rec_type == 'L') { + get(&lfile_rec, sizeof(lfile_rec), 1, fp); + funcname=lfile_rec.funcname; + filename=lfile_rec.filename; + text = lfile_rec.text; + end = lfile_rec.end; + dtype = lfile_rec.type; + line = lfile_rec.line; + } else if (rec_type == 'M') { + get(&mfile_rec, sizeof(mfile_rec), 1, fp); + funcname = mfile_rec.funcname; + filename = mfile_rec.filename; + text = mfile_rec.text; + end = mfile_rec.end; + dtype = mfile_rec.type; + line = mfile_rec.line; + } + if (dtype == DEBUG_FUNCENT_NO) level++; + if ((show_type == NULL || is_in(dtype, show_type, show_size)) && + (ex_type == NULL || !is_in(dtype, ex_type, ex_size))) { + c = 0; flag = 0; + while (c < end) { + int ii = (level-1) * 4; + if (ii < 0) ii = 0; + if (ii > 64) ii = 64; + char indent[ii+1]; + memset(indent, ' ', ii); + indent[ii] = '\0'; + if (c + (BUF_SIZE-1) < end) { + get(buf, 1, BUF_SIZE-1, fp); + buf[BUF_SIZE-1] = '\0'; + c += BUF_SIZE-1; + } else { + get(buf, 1, end-c, fp); + buf[end-c] = '\0'; + c = end; + } + if (flag == 0) { + if (format == 'I') { // indented text format + char *b = buf+text; + printf("%s %s/%s[%d]: ", indent, &buf[filename], &buf[funcname], line); + while (b) { + char *p = strchr(b, '\n'); + if (p) { + *p = '\0'; + printf("%s\n%s ", b, indent); + b = p + 1; + } + else { + printf("%s", b); + b = NULL; + } + } + } + else if (format == 'T') { // text format + printf("%s/%s[%d]: %s", &buf[filename], &buf[funcname], line, &buf[text]); + } else { + printf("Type: %d\nFile[line]: %s[%d]\nFunction:%s\nText:%s", dtype, + &buf[filename], line, &buf[funcname], &buf[text]); + } + flag = 1; + } else { + if (format == 'I') { + char *b = buf; + while (b) { + char *p = strchr(b, '\n'); + if (p) { + *p = '\0'; + printf("%s\n%s ", b, indent); + b = p + 1; + } + else { + printf("%s", b); + b = NULL; + } + } + } + else printf("%s", buf); + } + } + printf("\n"); + } + if (dtype == DEBUG_FUNCRET_NO) level--; + } + if (fseek(fp, i[ptr], SEEK_SET)==-1) { + printf("finished\n"); + break; + } + } else { + printf("...no more items\n"); + break; + } } - } - if (fseek(fp, i[ptr], SEEK_SET)==-1) { - printf("finished\n"); - break; - } - } else { - printf("...no more items\n"); - break; - } - } - free(buf); - fclose(fp); - return 0; + free(buf); + fclose(fp); + return 0; } - + size_t get(void * buf, int size, unsigned int count, FILE *fp) { - size_t z; - if ((z=fread(buf,size, count, fp)) < count) { - printf("Read Failed! (size=%d, count=%d,z=%ld)\n", size, count, (long)z); - exit(1); - } - return z; + size_t z; + if ((z=fread(buf,size, count, fp)) < count) { + printf("Read Failed! (size=%d, count=%d,z=%ld)\n", size, count, (long)z); + exit(1); + } + return z; } int usage() { - printf("readlog -t[show_type] -x[exclude_type] -f[format] filename\n"); - printf("\tformat:\n\t\tt: Text log format\n"); - printf("\tshow_type:\n\t\tcomma separated list of types to show " - "[ie, 2,4,1,6]\n"); - printf("\texclude_type:\n\t\tcomma separated list of types to exclude " - "[ie, 1,5,3,7]\n"); - return 0; + printf("readlog -t[show_type] -x[exclude_type] -f[format] filename\n"); + printf("\tformat:\n\t\tt: text log format\n"); + printf("\t\ti: indented text log format\n"); + printf("\tshow_type:\n\t\tcomma separated list of types to show " + "[ie, 2,4,1,6]\n"); + printf("\texclude_type:\n\t\tcomma separated list of types to exclude " + "[ie, 1,5,3,7]\n"); + return 0; } + int split_args(char *args, int **targ) { - int count = 1, *i, x, z; - char *tmp = args, *y; - if (*targ != NULL) { - free(*targ); - } - // find the number of tokens in the string. Starting - // from 1 cause there will always be one - while ((tmp = strchr(tmp, ',')) != NULL) { - tmp++; count++; - } - *targ = (int*)xmalloc(count * sizeof(int)); - i = *targ; // for convienience - tmp = args; - z = 0; - for (x = 0; x < count; x++) { - y = strtok(tmp, ","); - tmp = NULL; // must be done after first call - if (y != NULL) { - i[x] = atoi(y); - z++; - } - } - return z; + int count = 1, *i, x, z; + char *tmp = args, *y; + if (*targ != NULL) { + free(*targ); + } + // find the number of tokens in the string. Starting + // from 1 cause there will always be one + while ((tmp = strchr(tmp, ',')) != NULL) { + tmp++; count++; + } + *targ = (int*)xmalloc(count * sizeof(int)); + i = *targ; // for convienience + tmp = args; + z = 0; + for (x = 0; x < count; x++) { + y = strtok(tmp, ","); + tmp = NULL; // must be done after first call + if (y != NULL) { + i[x] = atoi(y); + z++; + } + } + return z; } + // checks to see if the first arg is in the array of the second arg, // the size of which is specified with the third arg. If the second -// arg is NULL, then it is obvious that it ain't there. +// arg is NULL, then it is obvious that it is not there. int is_in(int a, int *b, int c){ - int d = 0; - if (b == NULL || c == 0) { // no array or no items in array - return 0; - } - while (d < c) { - if (a == b[d]) - return 1; - d++; - } - return 0; + int d = 0; + if (b == NULL || c == 0) { // no array or no items in array + return 0; + } + while (d < c) { + if (a == b[d]) return 1; + d++; + } + return 0; } diff -r b2f247463b83 -r 6fe121a971c9 xml/libpst.in --- a/xml/libpst.in Sun Jul 15 14:25:34 2007 -0700 +++ b/xml/libpst.in Thu Aug 09 15:46:34 2007 -0700 @@ -245,7 +245,8 @@ -f format Sets the format of the text log output. Currently, the only valid output - format is T, for text; anything else gives the default. + formats are T, for single line text, D for the default default multi line + format, and I for an indented style with single line text. @@ -320,9 +321,15 @@ + 9 + + Function entries + + + 10 - Function calls + Function exits @@ -1056,7 +1063,7 @@ 1009 RTF Compressed body 1010 RTF whitespace prefix count 1011 RTF whitespace tailing count -1013 HTML Email Body. Does not exist if the email doesn't have a HTML version +1013 HTML Email Body. Does not exist if the email doesn't have an HTML version 1035 Message ID 1042 In-Reply-To or Parent's Message ID 1046 Return Path @@ -1070,7 +1077,7 @@ 35df Valid Folder Mask 35e0 binary record found in first item. Contains the reference to "Top of Personal Folder" item 35e3 binary record with a reference to "Deleted Items" item -35e7 binary record with a refernece to "Search Root" item +35e7 binary record with a reference to "Search Root" item 3602 the number of emails stored in a folder 3603 the number of unread emails in a folder 360a Has Subfolders @@ -1165,10 +1172,10 @@ 3a64 Other Address Post Office box 65e3 Entry ID 67f2 Attachment ID2 value -67ff Password checksum [0x67FF] +67ff Password checksum 6f02 Secure HTML Body 6f04 Secure Text Body -7c07 Top of folders RecID [0x7c07] +7c07 Top of folders RecID 8000 Contain extra bits of information that have been taken from the email's header. I call them extra lines 8005 Contact Fullname 801a Home Address @@ -1180,9 +1187,9 @@ 8085 Email Address 1 Record 8092 Email Address 2 Transport 8093 Email Address 2 Address -8094 DEBUG_EMAIL (("Email Address 2 Description +8094 Email Address 2 Description 8095 Email Address 2 Record -80a2 DEBUG_EMAIL (("Email Address 3 Transport +80a2 Email Address 3 Transport 80a3 Email Address 3 Address 80a4 Email Address 3 Description 80a5 Email Address 3 Record