# HG changeset patch # User carl # Date 1184113048 25200 # Node ID b88ceb81dba2f1ddd182d3e0cff0fa59a5f696de # Parent 45eccad4b606ea80b04d5a2ade679240a2019b8e mege changes from Joe Nahmias diff -r 45eccad4b606 -r b88ceb81dba2 AUTHORS --- a/AUTHORS Sat Feb 25 16:16:15 2006 -0800 +++ b/AUTHORS Tue Jul 10 17:17:28 2007 -0700 @@ -1,6 +1,8 @@ Dave Smith With contributions by: - Joseph Nahmias + Joseph Nahmias Carl Byington Arne Ahrend + Nigel Horne + Chris Hall diff -r 45eccad4b606 -r b88ceb81dba2 ChangeLog --- a/ChangeLog Sat Feb 25 16:16:15 2006 -0800 +++ b/ChangeLog Tue Jul 10 17:17:28 2007 -0700 @@ -1,3 +1,20 @@ +LibPST 0.5.5 (2007-07-10) +=============================== + + * merge the following changes from Joe Nahmias version: + * Lots of memory fixes. Thanks to Nigel Horne for his assistance + tracking these down! + * Fixed creation of vCards from contacts, thanks to Nigel Horne for + his help with this! + * fix for MIME multipart/alternative attachments. + * added -c options to readpst manpage. + * use 8.3 attachment filename if long filename isn't available. + * new -b option to skip rtf-body.rtf attachments. + * fix format of From header lines in mbox files. + * Add more appointment fields, thanks to Chris Hall for tracking + them down! + + LibPST 0.5.4 (2006-02-25) =============================== diff -r 45eccad4b606 -r b88ceb81dba2 NEWS --- a/NEWS Sat Feb 25 16:16:15 2006 -0800 +++ b/NEWS Tue Jul 10 17:17:28 2007 -0700 @@ -1,5 +1,6 @@ $Id$ +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 0.5.3 2006-02-20 switch to gnu autoconf/automake 0.5.2 2006-02-18 add pst2ldif, fix btree processing in libpst.c diff -r 45eccad4b606 -r b88ceb81dba2 configure.in --- a/configure.in Sat Feb 25 16:16:15 2006 -0800 +++ b/configure.in Tue Jul 10 17:17:28 2007 -0700 @@ -1,13 +1,33 @@ AC_INIT(configure.in) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(libpst,0.5.4) +AM_INIT_AUTOMAKE(libpst,0.5.5) AC_PATH_PROGS(BASH, bash) AC_LANG_CPLUSPLUS AC_PROG_CXX AC_PROG_LIBTOOL +# The following lines adds the --enable-pst-debug option to configure: +# +# Give the user the choice to enter one of these: +# --enable-pst-debug +# --enable-pst-debug=yes +# --enable-pst-debug=no +# +AC_MSG_CHECKING([whether we are enabling pst debug code]) +AC_ARG_ENABLE(pst-debug, + AC_HELP_STRING([--enable-pst-debug], [enable pst debug code]), + [if test "${enable_pst_debug}" = "no" ; then + AC_MSG_RESULT([no]) + else + AC_DEFINE(DEBUG_ALL, 1, Define to 1 to enable pst debug code) + AC_MSG_RESULT([yes]) + fi], + # Default value for configure + AC_MSG_RESULT([no]) + ) + AC_OUTPUT( \ Makefile \ libpst.spec \ diff -r 45eccad4b606 -r b88ceb81dba2 libpst.spec.in --- a/libpst.spec.in Sat Feb 25 16:16:15 2006 -0800 +++ b/libpst.spec.in Tue Jul 10 17:17:28 2007 -0700 @@ -4,7 +4,7 @@ Name: @PACKAGE@ Version: @VERSION@ Release: %{?custom_release}%{!?custom_release:1} -Copyright: GPL +License: GPL Group: System Environment/Daemons Source: http://www.five-ten-sg.com/@PACKAGE@/packages/@PACKAGE@-@VERSION@.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot @@ -67,6 +67,9 @@ %changelog -* Sun Feb 19 2006 Carl Byington 1.0 +* Tue Jul 10 2007 Carl Byington 0.5.5 +- merge changes from Joe Nahmias version + +* Sun Feb 19 2006 Carl Byington 0.5.3 - initial spec file using autoconf and http://www.fedora.us/docs/rpm-packaging-guidelines.html diff -r 45eccad4b606 -r b88ceb81dba2 package --- a/package Sat Feb 25 16:16:15 2006 -0800 +++ b/package Tue Jul 10 17:17:28 2007 -0700 @@ -12,18 +12,6 @@ ./configure >/dev/null (cd xml; make; make distclean) cp -a html/*html $web -if [ "$1" == "test" ]; then - make - pst=/home/ldap/outlook.pst - rm -f pst2ldif.log my.log - src/pst2ldif -b 'o=ams-cc.com, c=US' -c 'newPerson' $pst >ams.ldif - src/readpstlog pst2ldif.log | less >my.log - hexdump -C -v $pst >pst.dump - chown --recursive carl:carl * - exit -else - rm -f pst2ldif.log my.log ams.ldif pst.dump -fi make distcheck >$distlog 2>&1 if [ $? -eq 0 ]; then @@ -41,20 +29,28 @@ cd .. # build rpm on target - target=host62 - scp $BALL $target:/tmp - ssh $target "cd /tmp; rpmbuild -ta $BALL" + target5=pmg2 + scp $BALL $target5:/tmp + ssh $target5 "cd /tmp; rpmbuild -ta $BALL" + + # build rpm on target + target4=host62 + scp $BALL $target4:/tmp + ssh $target4 "cd /tmp; rpmbuild -ta $BALL" # add packages to the web site wp=$web/packages wp4=$wp/centos4 - mkdir -p $wp4 + wp5=$wp/centos5 + mkdir -p $wp4 $wp5 rp=/usr/src/redhat mv -f $BALL $wp - scp $target:$rp/SRPMS/$NAME-$VER*rpm $wp - scp $target:$rp/RPMS/i386/$NAME-$VER*rpm $wp4 - (cd $web; chown --recursive web:web .; ls -alR) + scp $target4:$rp/SRPMS/$NAME-$VER*rpm $wp + scp $target4:$rp/RPMS/i386/$NAME-$VER*rpm $wp4 + scp $target5:$rp/RPMS/i386/$NAME-$VER*rpm $wp5 + (cd $web; chown --recursive web:web *; ls -alR) rpm -ql -p $wp4/$NAME-$VER*6.rpm + rpm -ql -p $wp5/$NAME-$VER*6.rpm fi else tail -10 $distlog diff -r 45eccad4b606 -r b88ceb81dba2 src/debug.c --- a/src/debug.c Sat Feb 25 16:16:15 2006 -0800 +++ b/src/debug.c Tue Jul 10 17:17:28 2007 -0700 @@ -29,13 +29,13 @@ void _debug_init(char *fname); void _debug_msg_info (int line, char *file, int type); void _debug_msg(char* fmt, ...); -void _debug_hexdump(char *x, int y, int cols); +void _debug_hexdump(unsigned char *x, int y, int cols); void _debug_func(char *function); void _debug_func_ret(); void _debug_close(); void _debug_write(); void _debug_write_msg(struct _debug_item *item, char *fmt, va_list *ap, int size); -void _debug_write_hex(struct _debug_item *item, char *buf, int size, int col); +void _debug_write_hex(struct _debug_item *item, unsigned char *buf, int size, int col); void * xmalloc(size_t size); // the largest text size we will store in memory. Otherwise we @@ -159,13 +159,16 @@ #else f = vsnprintf(x, 1, fmt, ap); #endif + va_end(ap); // must be called after vsnprintf() if (f > 0 && f < MAX_MESSAGE_SIZE) { info_ptr->text = (char*) xmalloc(f+1); + va_start(ap, fmt); if ((g = vsnprintf(info_ptr->text, f, fmt, ap)) == -1) { fprintf(stderr, "_debug_msg: Dieing! vsnprintf returned -1 for format \"%s\"\n", fmt); exit(-2); } + va_end(ap); info_ptr->text[g] = '\0'; if (f != g) { fprintf(stderr, "_debug_msg: f != g\n"); @@ -175,7 +178,9 @@ temp = info_ptr; _debug_write(); // dump the current messages info_ptr = temp; + va_start(ap, fmt); _debug_write_msg(info_ptr, fmt, &ap, f); + va_end(ap); free(info_ptr->function); free(info_ptr->file); free(info_ptr); @@ -185,7 +190,6 @@ fprintf(stderr, "_debug_msg: error getting requested size of debug message\n"); info_ptr->text = "ERROR Saving\n"; } - va_end(ap); if (item_head == NULL) item_head = info_ptr; @@ -202,7 +206,7 @@ } } -void _debug_hexdump(char *x, int y, int cols) { +void _debug_hexdump(unsigned char *x, int y, int cols) { struct _debug_item *temp; if (debug_fp == NULL) return; @@ -261,7 +265,7 @@ void _debug_write() { size_t size, ptr, funcname, filename, text, end; - char *buf, rec_type; + char *buf = NULL, rec_type; long index_pos = ftell (debug_fp), file_pos = index_pos; // add 2. One for the pointer to the next index, // one for the count of this index @@ -287,6 +291,7 @@ index[index_ptr++] = file_pos; 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; funcname=ptr; @@ -318,6 +323,7 @@ fwrite(&mfile_rec, sizeof(mfile_rec), 1, debug_fp); } fwrite(buf, 1, ptr, debug_fp); + if (buf) free(buf); buf = NULL; item_head = item_ptr->next; free(item_ptr->function); free(item_ptr->file); @@ -334,6 +340,7 @@ fseek(debug_fp, 0, SEEK_END); item_ptr = item_head = item_tail = NULL; free(index); + if (buf) free(buf); buf = NULL; } void _debug_write_msg(struct _debug_item *item, char *fmt, va_list *ap, int size) { @@ -394,7 +401,7 @@ // that should do it... } -void _debug_write_hex(struct _debug_item *item, char *buf, int size, int col) { +void _debug_write_hex(struct _debug_item *item, unsigned char *buf, int size, int col) { struct _debug_file_rec_l lfile_rec; unsigned char rec_type; int index_size = 3 * sizeof(int); diff -r 45eccad4b606 -r b88ceb81dba2 src/define.h --- a/src/define.h Sat Feb 25 16:16:15 2006 -0800 +++ b/src/define.h Tue Jul 10 17:17:28 2007 -0700 @@ -5,9 +5,9 @@ * dave.s@earthcorp.com */ -// last one wins -#define DEBUG_ALL -#undef DEBUG_ALL +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif #ifndef DEFINEH_H #define DEFINEH_H @@ -60,7 +60,7 @@ void _debug_init(char *fname); void _debug_msg_info (int line, char *file, int type); void _debug_msg_text(char* fmt, ...); -void _debug_hexdump(char *x, int y, int cols); +void _debug_hexdump(unsigned char *x, int y, int cols); void _debug_func(char *function); void _debug_func_ret(); void _debug_close(void); diff -r 45eccad4b606 -r b88ceb81dba2 src/libpst.c --- a/src/libpst.c Sat Feb 25 16:16:15 2006 -0800 +++ b/src/libpst.c Tue Jul 10 17:17:28 2007 -0700 @@ -119,13 +119,8 @@ int32_t pst_open(pst_file *pf, char *name, char *mode) { u_int32_t sig; - // unsigned char ind_type; DEBUG_ENT("pst_open"); -#ifdef _MSC_VER - // set the default open mode for windows - _fmode = _O_BINARY; -#endif //_MSC_VER if (!pf) { WARN (("cannot be passed a NULL pst_file\n")); @@ -134,21 +129,24 @@ } memset(pf, 0, sizeof(pst_file)); +#ifdef _MSC_VER + // set the default open mode for windows + _fmode = _O_BINARY; +#endif //_MSC_VER if ((pf->fp = fopen(name, mode)) == NULL) { WARN(("cannot open PST file. Error\n")); DEBUG_RET(); return -1; } + + // Check pst file magic if (fread(&sig, sizeof(sig), 1, pf->fp) == 0) { fclose(pf->fp); WARN(("cannot read signature from PST file. Closing on error\n")); DEBUG_RET(); return -1; } - - // architecture independant byte-swapping (little, big, pdp) - LE32_CPU(sig); - + LE32_CPU(sig); // architecture independant byte-swapping (little, big, pdp) DEBUG_INFO(("sig = %X\n", sig)); if (sig != PST_SIGNATURE) { fclose(pf->fp); @@ -156,6 +154,8 @@ DEBUG_RET(); return -1; } + + // read index type _pst_getAtPos(pf->fp, INDEX_TYPE_OFFSET, &(pf->ind_type), sizeof(unsigned char)); DEBUG_INFO(("index_type = %i\n", pf->ind_type)); if (pf->ind_type != 0x0E) { @@ -164,6 +164,7 @@ return -1; } + // read encryption setting _pst_getAtPos(pf->fp, ENC_OFFSET, &(pf->encryption), sizeof(unsigned char)); DEBUG_INFO(("encrypt = %i\n", pf->encryption)); @@ -240,8 +241,9 @@ size = _pst_ff_getID2data(pf, ptr, &h); } else { DEBUG_WARN(("Couldn't find ID pointer. Cannot handle attachment\n")); + size = 0; } - attach->size = size; // may aswell update it to what is correct for this instance + attach->size = size; // may as well update it to what is correct for this instance } else { size = attach->size; } @@ -261,6 +263,7 @@ size = _pst_ff_getID2data(pf, ptr, &h); } else { DEBUG_WARN(("Couldn't find ID pointer. Cannot save attachment to file\n")); + size = 0; } attach->size = size; } else { @@ -285,15 +288,16 @@ size = _pst_ff_getID2data(pf, ptr, &h); // will need to encode any bytes left over c = base64_encode(h.base64_extra_chars, h.base64_extra); - pst_fwrite(c, 1, strlen(c), fp); + if (c) pst_fwrite(c, 1, strlen(c), fp); } else { DEBUG_WARN (("Couldn't find ID pointer. Cannot save attachement to Base64\n")); + size = 0; } attach->size = size; } else { // encode the attachment to the file c = base64_encode(attach->data, attach->size); - pst_fwrite(c, 1, strlen(c), fp); + if (c) pst_fwrite(c, 1, strlen(c), fp); size = attach->size; } DEBUG_RET(); @@ -350,13 +354,11 @@ // for PST files this will load up ID2 0x61 and check it's "list" attribute. pst_desc_ll *p; pst_num_array *na; - // pst_index_ll *list; - pst_index2_ll *list2;//, *t; + pst_index2_ll *list2; unsigned char * buffer=NULL, *headerbuffer=NULL;//, *tc; pst_x_attrib xattrib; int32_t bptr = 0, bsize, hsize, tint, err=0, x; pst_x_attrib_ll *ptr, *p_head=NULL, *p_sh=NULL, *p_sh2=NULL; - char *wt; DEBUG_ENT("pst_loadExtendedAttributes"); if ((p = _pst_getDptr(pf, 0x61)) == NULL) { @@ -390,6 +392,7 @@ } if (!buffer) { + if (na) _pst_free_list(na); DEBUG_WARN(("No extended attributes buffer found. Not processing\n")); DEBUG_RET(); return 0; @@ -414,6 +417,7 @@ if (xattrib.type & 0x0001) { // if the Bit 1 is set // pointer to Unicode field in buffer if (xattrib.extended < hsize) { + char *wt; // copy the size of the header. It is 32 bit int memcpy(&tint, &(headerbuffer[xattrib.extended]), sizeof(tint)); LE32_CPU(tint); @@ -421,6 +425,7 @@ memset(wt, 0, tint+2); memcpy(wt, &(headerbuffer[xattrib.extended+sizeof(tint)]), tint); ptr->data = _pst_wide_to_single(wt, tint); + free(wt); DEBUG_INDEX(("Read string (converted from UTF-16): %s\n", ptr->data)); } else { DEBUG_INDEX(("Cannot read outside of buffer [%i !< %i]\n", xattrib.extended, hsize)); @@ -463,8 +468,8 @@ LE16_CPU(xattrib.map); bptr += sizeof(xattrib); } - if (buffer) free(buffer); - if (headerbuffer) free(headerbuffer); + if (list2) _pst_free_id2(list2); + if (na) _pst_free_list(na); pf->x_head = p_head; DEBUG_RET(); return 1; @@ -981,12 +986,14 @@ if (!d_ptr->desc) { DEBUG_WARN(("why is d_ptr->desc == NULL? I don't want to do anything else with this record\n")); + if (id2_head) _pst_free_id2(id2_head); DEBUG_RET(); return NULL; } if ((list = _pst_parse_block(pf, d_ptr->desc->id, id2_head)) == NULL) { DEBUG_WARN(("_pst_parse_block() returned an error for d_ptr->desc->id [%#x]\n", d_ptr->desc->id)); + if (id2_head) _pst_free_id2(id2_head); DEBUG_RET(); return NULL; } @@ -996,11 +1003,13 @@ if (_pst_process(list, item)) { DEBUG_WARN(("_pst_process() returned non-zero value. That is an error\n")); - _pst_free_list(list); + if (item) free(item); + if (list) _pst_free_list(list); + if (id2_head) _pst_free_id2(id2_head); DEBUG_RET(); return NULL; } else { - _pst_free_list(list); + if (list) _pst_free_list(list); list = NULL; //_pst_process will free the items in the list } @@ -1015,8 +1024,10 @@ DEBUG_EMAIL(("ATTACHEMENT processing attachement\n")); if ((list = _pst_parse_block(pf, id_ptr->id, id2_head)) == NULL) { DEBUG_WARN(("ERROR error processing main attachment record\n")); - // DEBUG_RET(); - // return NULL; + if (item) free(item); + if (id2_head) _pst_free_id2(id2_head); + DEBUG_RET(); + return NULL; } else { x = 0; @@ -1030,11 +1041,14 @@ if (_pst_process(list, item)) { DEBUG_WARN(("ERROR _pst_process() failed with attachments\n")); - _pst_free_list(list); + if (item) free(item); + if (list) _pst_free_list(list); + if (id2_head) _pst_free_id2(id2_head); DEBUG_RET(); return NULL; } - _pst_free_list(list); + if (list) _pst_free_list(list); + list = NULL; // now we will have initial information of each attachment stored in item->attach... // we must now read the secondary record for each based on the id2 val associated with @@ -1052,11 +1066,13 @@ } if (_pst_process(list, item)) { DEBUG_WARN(("ERROR _pst_process() failed with an attachment\n")); - _pst_free_list(list); + if (list) _pst_free_list(list); + list = NULL; attach = attach->next; continue; } - _pst_free_list(list); + if (list) _pst_free_list(list); + list = NULL; if ((id_ptr = _pst_getID2(id2_head, attach->id2_val))) { // id2_val has been updated to the ID2 value of the datablock containing the // attachment data @@ -1073,6 +1089,7 @@ } _pst_free_id2(id2_head); + id2_head = NULL; DEBUG_RET(); return item; } @@ -1281,7 +1298,8 @@ fr_ptr += sizeof(table2_rec); } else { WARN(("Missing code for block_type %i\n", block_type)); - if (buf) free(buf); + if (buf) free(buf); + if (na_head) _pst_free_list(na_head); DEBUG_RET(); return NULL; } @@ -1377,7 +1395,7 @@ } // plus one for good luck (and strings) we will null terminate all reads - na_ptr->items[x]->data = (char*) xmalloc(size+1); + na_ptr->items[x]->data = (unsigned char*) xmalloc(size+1); memcpy(na_ptr->items[x]->data, &(buf[t_ptr]), size); na_ptr->items[x]->data[size] = '\0'; // null terminate buffer @@ -1407,6 +1425,8 @@ na_ptr->items[x]->type = table_rec.ref_type; } else { WARN(("ERROR Unknown ref_type %#x\n", table_rec.ref_type)); + if (buf) free(buf); + if (na_head) _pst_free_list(na_head); DEBUG_RET(); return NULL; } @@ -3002,6 +3022,17 @@ DEBUG_EMAIL(("Phone Call\n")); break; } break; + case 0x8215: // All day appointment flag + DEBUG_EMAIL(("All day flag - ")); + MALLOC_APPOINTMENT(item); + if (*(int16_t*)list->items[x]->data != 0) { + DEBUG_EMAIL(("True\n")); + item->appointment->all_day = 1; + } else { + DEBUG_EMAIL(("False\n")); + item->appointment->all_day = 0; + } + break; case 0x8234: // TimeZone as String DEBUG_EMAIL(("TimeZone of times - ")); MALLOC_APPOINTMENT(item); @@ -3243,6 +3274,7 @@ pst_index_ll *i_ptr = NULL; pst_index2_ll *i2_ptr = NULL; DEBUG_ENT("_pst_build_id2"); + if (head_ptr) { head = head_ptr; while (head_ptr) head_ptr = (tail = head_ptr)->next; @@ -3250,6 +3282,7 @@ if (_pst_read_block_size(pf, list->offset, list->size, &buf, PST_NO_ENC, 0) < list->size) { //an error occured in block read WARN(("block read error occured. offset = %#x, size = %#x\n", list->offset, list->size)); + if (buf) free(buf); DEBUG_RET(); return NULL; } @@ -3261,6 +3294,7 @@ if (block_head.type != 0x0002) { // some sort of constant? WARN(("Unknown constant [%#x] at start of id2 values [offset %#x].\n", block_head.type, list->offset)); + if (buf) free(buf); DEBUG_RET(); return NULL; } @@ -3513,7 +3547,7 @@ } -int32_t _pst_getBlockOffset(char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset *p) { +int32_t _pst_getBlockOffset(unsigned char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset *p) { int32_t of1 = offset>>4; DEBUG_ENT("_pst_getBlockOffset"); if (!p || !buf || (i_offset == 0) || (i_offset+2+of1+sizeof(*p) > read_size)) { @@ -3679,8 +3713,10 @@ unsigned char fdepth; pst_index_ll *ptr = NULL; size_t rsize, z; + DEBUG_ENT("_pst_read_block_size"); DEBUG_READ(("Reading block from %#x, %i bytes\n", offset, size)); + fpos = ftell(pf->fp); fseek(pf->fp, offset, SEEK_SET); if (*buf) { @@ -3688,7 +3724,7 @@ free(*buf); } - *buf = (void*) xmalloc(size+1); //plus one so that we can NULL terminate it later + *buf = (void*) xmalloc(size+1); //plus one so that we can NUL terminate it later rsize = fread(*buf, 1, size, pf->fp); if (rsize != size) { DEBUG_WARN(("Didn't read all that I could. fread returned less [%i instead of %i]\n", rsize, size)); @@ -3894,7 +3930,7 @@ *(h->buf) = b; } else if ((h->base64 == 1) && h->fp) { t = base64_encode(b, ret); - pst_fwrite(t, 1, strlen(t), h->fp); + if (t) pst_fwrite(t, 1, strlen(t), h->fp); free(b); } else if (h->fp) { pst_fwrite(b, 1, ret, h->fp); @@ -3923,8 +3959,10 @@ unsigned char fdepth; DEBUG_ENT("_pst_ff_compile_ID"); - if ((a = _pst_ff_getIDblock(pf, id, &buf3))==0) + if ((a = _pst_ff_getIDblock(pf, id, &buf3))==0) { + if (buf3) free(buf3); return 0; + } if ((buf3[0] != 0x1)) { // if bit 8 is set) { // if ((buf3)[0] != 0x1 && (buf3)[1] > 4) { DEBUG_WARN(("WARNING: buffer doesn't start with 0x1, but I expected it to or doesn't have it's two-bit set!\n")); @@ -3934,7 +3972,7 @@ *(h->buf) = buf3; else if (h->base64 == 1 && h->fp) { t = base64_encode(buf3, a); - pst_fwrite(t, 1, strlen(t), h->fp); + if (t) pst_fwrite(t, 1, strlen(t), h->fp); free(buf3); } else if (h->fp) { pst_fwrite(buf3, 1, a, h->fp); @@ -3978,7 +4016,7 @@ memcpy(h->base64_extra_chars, &(buf2[z-b]), b); h->base64_extra = b; t = base64_encode(buf2, z-b); - pst_fwrite(t, 1, strlen(t), h->fp); + if (t) pst_fwrite(t, 1, strlen(t), h->fp); DEBUG_READ(("writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size)); } diff -r 45eccad4b606 -r b88ceb81dba2 src/libpst.h --- a/src/libpst.h Sat Feb 25 16:16:15 2006 -0800 +++ b/src/libpst.h Tue Jul 10 17:17:28 2007 -0700 @@ -378,6 +378,7 @@ char *timezonestring; int32_t showas; int32_t label; + int32_t all_day; } pst_item_appointment; typedef struct _pst_item { @@ -420,10 +421,10 @@ int32_t index1_count; int32_t index2; int32_t index2_count; - FILE * fp; - size_t size; - unsigned char encryption; - unsigned char ind_type; + FILE * fp; // file pointer to opened PST file + size_t size; // pst file size + unsigned char encryption; // pst encryption setting + unsigned char ind_type; // pst index type } pst_file; typedef struct _pst_block_offset { @@ -477,7 +478,7 @@ int32_t _pst_free_id (pst_index_ll *head); int32_t _pst_free_desc (pst_desc_ll *head); int32_t _pst_free_xattrib(pst_x_attrib_ll *x); -int32_t _pst_getBlockOffset(char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset *p); +int32_t _pst_getBlockOffset(unsigned char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset *p); pst_index2_ll * _pst_build_id2(pst_file *pf, pst_index_ll* list, pst_index2_ll* head_ptr); pst_index_ll * _pst_getID(pst_file* pf, u_int32_t id); pst_index_ll * _pst_getID2(pst_index2_ll * ptr, u_int32_t id); diff -r 45eccad4b606 -r b88ceb81dba2 src/libstrfunc.c --- a/src/libstrfunc.c Sat Feb 25 16:16:15 2006 -0800 +++ b/src/libstrfunc.c Tue Jul 10 17:17:28 2007 -0700 @@ -27,7 +27,7 @@ //register void *dte=data + size; register int nc=0; - if(data == NULL) + if ( data == NULL || size == 0 ) return NULL; ou=output=(char *)malloc(size / 3 * 4 + (size / 50) + 5); diff -r 45eccad4b606 -r b88ceb81dba2 src/lspst.c --- a/src/lspst.c Sat Feb 25 16:16:15 2006 -0800 +++ b/src/lspst.c Tue Jul 10 17:17:28 2007 -0700 @@ -37,8 +37,8 @@ char *rfc2426_escape(char *str); char *rfc2445_datetime_format(FILETIME *ft); // }}}1 -#ifndef DEBUG_MAIN - #define DEBUG_MAIN(x) debug_print x; +#ifndef LSPST_DEBUG_MAIN + #define LSPST_DEBUG_MAIN(x) debug_print x; #endif // int main(int argc, char** argv) {{{1 int main(int argc, char** argv) { @@ -49,7 +49,7 @@ pst_desc_ll *d_ptr; char *temp = NULL; //temporary char pointer int skip_child = 0; - struct file_ll *f, *head; + struct file_ll *f = NULL, *head = NULL; // }}}2 if (argc <= 1) @@ -92,12 +92,12 @@ head->dname = (char*) malloc(strlen(item->file_as)+1); strcpy(head->dname, item->file_as); head->type = item->type; - DEBUG_MAIN(("head @ %p: name = '%s', dname = '%s', next = %p.\n", head, head->name, head->dname, head->next)); + LSPST_DEBUG_MAIN(("head @ %p: name = '%s', dname = '%s', next = %p.\n", head, head->name, head->dname, head->next)); if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) { DIE(("Top of folders record not found. Cannot continue\n")); } - DEBUG_MAIN(("d_ptr(TOF) = %p.\n", d_ptr)); + LSPST_DEBUG_MAIN(("d_ptr(TOF) = %p.\n", d_ptr)); if (item){ _pst_freeItem(item); @@ -105,21 +105,21 @@ } d_ptr = d_ptr->child; // do the children of TOPF - DEBUG_MAIN(("d_ptr(TOF->child) = %p.\n", d_ptr)); + LSPST_DEBUG_MAIN(("d_ptr(TOF->child) = %p.\n", d_ptr)); - DEBUG_MAIN(("main: About to do email stuff\n")); + LSPST_DEBUG_MAIN(("main: About to do email stuff\n")); while (d_ptr != NULL) { // Process d_ptr {{{2 - DEBUG_MAIN(("main: New item record, d_ptr = %p.\n", d_ptr)); + LSPST_DEBUG_MAIN(("main: New item record, d_ptr = %p.\n", d_ptr)); if (d_ptr->desc == NULL) { DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n")); f->skip_count++; goto check_parent; } - DEBUG_MAIN(("main: Desc Email ID %x [d_ptr->id = %x]\n", d_ptr->desc->id, d_ptr->id)); + LSPST_DEBUG_MAIN(("main: Desc Email ID %x [d_ptr->id = %x]\n", d_ptr->desc->id, d_ptr->id)); item = _pst_parse_item(&pstfile, d_ptr); - DEBUG_MAIN(("main: About to process item @ %p.\n", item)); + LSPST_DEBUG_MAIN(("main: About to process item @ %p.\n", item)); if (item != NULL) { // there should only be one message_store, and we have already @@ -136,7 +136,7 @@ printf("\t%s/", item->file_as); printf("\n"); - DEBUG_MAIN(("main: I think I may try to go into folder \"%s\"\n", item->file_as)); + LSPST_DEBUG_MAIN(("main: I think I may try to go into folder \"%s\"\n", item->file_as)); f = (struct file_ll*) malloc(sizeof(struct file_ll)); memset(f, 0, sizeof(struct file_ll)); f->next = head; @@ -148,14 +148,14 @@ f->dname = (char*) xmalloc(strlen(item->file_as)+1); strcpy(f->dname, item->file_as); - DEBUG_MAIN(("main: f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); + LSPST_DEBUG_MAIN(("main: f->name = %s\nitem->folder_name = %s\n", f->name, item->file_as)); canonicalize_filename(f->name); if (d_ptr->child != NULL) { d_ptr = d_ptr->child; skip_child = 1; } else { - DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n")); + LSPST_DEBUG_MAIN(("main: Folder has NO children. Creating directory, and closing again\n")); // printf("\tNo items to process in folder \"%s\", should have been %i\n", f->dname, f->stored_count); head = f->next; if (f->output != NULL) @@ -173,13 +173,13 @@ } else if (item->contact != NULL) { // Process Contact item {{{3 if (f->type != PST_TYPE_CONTACT) { - DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " + LSPST_DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " "Will process anyway\n")); } if (item->type != PST_TYPE_CONTACT) { - DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" + LSPST_DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" " it is a contact. Type is \"%s\"\n", item->ascii_type)); - DEBUG_MAIN(("main: Processing anyway\n")); + LSPST_DEBUG_MAIN(("main: Processing anyway\n")); } printf("Contact"); @@ -200,7 +200,7 @@ } else if (item->type == PST_TYPE_JOURNAL) { // Process Journal item {{{3 if (f->type != PST_TYPE_JOURNAL) { - DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); + LSPST_DEBUG_MAIN(("main: I have a journal entry, but folder isn't specified as a journal type. Processing...\n")); } printf("Journal\t%s\n", rfc2426_escape(item->email->subject->subj)); @@ -209,37 +209,42 @@ // Process Calendar Appointment item {{{3 // deal with Calendar appointments - DEBUG_MAIN(("main: Processing Appointment Entry\n")); + LSPST_DEBUG_MAIN(("main: Processing Appointment Entry\n")); if (f->type != PST_TYPE_APPOINTMENT) { - DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); + LSPST_DEBUG_MAIN(("main: I have an appointment, but folder isn't specified as an appointment type. Processing...\n")); } printf("Appointment"); if (item->email != NULL && item->email->subject != NULL) printf("\tSUMMARY: %s", rfc2426_escape(item->email->subject->subj)); - if (item->appointment != NULL && item->appointment->start != NULL) - printf("\tSTART: %s", rfc2445_datetime_format(item->appointment->start)); + if (item->appointment != NULL) { + if (item->appointment->start != NULL) + printf("\tSTART: %s", rfc2445_datetime_format(item->appointment->start)); + if (item->appointment->end != NULL) + printf("\tEND: %s", rfc2445_datetime_format(item->appointment->end)); + printf("\tALL DAY: %s", (item->appointment->all_day==1 ? "Yes" : "No")); + } printf("\n"); // }}}3 } else { f->skip_count++; - DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", \ + LSPST_DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", \ item->type, item->ascii_type)); } } else { f->skip_count++; - DEBUG_MAIN(("main: A NULL item was seen\n")); + LSPST_DEBUG_MAIN(("main: A NULL item was seen\n")); } check_parent: // _pst_freeItem(item); while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) { - DEBUG_MAIN(("main: Going to Parent\n")); + LSPST_DEBUG_MAIN(("main: Going to Parent\n")); head = f->next; if (f->output != NULL) fclose(f->output); - DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); + LSPST_DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); /* printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", \ f->dname, f->email_count, f->skip_count, f->stored_count); @@ -250,7 +255,7 @@ free(f); f = head; if (head == NULL) { //we can't go higher. Must be at start? - DEBUG_MAIN(("main: We are now trying to go above the highest level. We must be finished\n")); + LSPST_DEBUG_MAIN(("main: We are now trying to go above the highest level. We must be finished\n")); break; //from main while loop } d_ptr = d_ptr->parent; @@ -258,7 +263,7 @@ } if (item != NULL) { - DEBUG_MAIN(("main: Freeing memory used by item\n")); + LSPST_DEBUG_MAIN(("main: Freeing memory used by item\n")); _pst_freeItem(item); item = NULL; } @@ -268,11 +273,11 @@ else skip_child = 0; - if (d_ptr == NULL) { DEBUG_MAIN(("main: d_ptr is now NULL\n")); } + if (d_ptr == NULL) { LSPST_DEBUG_MAIN(("main: d_ptr is now NULL\n")); } // }}}2 } // end while(d_ptr != NULL) - DEBUG_MAIN(("main: Finished.\n")); + LSPST_DEBUG_MAIN(("main: Finished.\n")); // Cleanup {{{2 pst_close(&pstfile); diff -r 45eccad4b606 -r b88ceb81dba2 src/readpst.c --- a/src/readpst.c Sat Feb 25 16:16:15 2006 -0800 +++ b/src/readpst.c Tue Jul 10 17:17:28 2007 -0700 @@ -62,6 +62,7 @@ int32_t type; struct file_ll *next; }; + void write_email_body(FILE *f, char *body); char *removeCR (char *c); int32_t usage(); @@ -82,10 +83,10 @@ char *skip_header_prologue(char *headers); void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst); void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst); -void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst); +void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst, int save_rtf); void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]); void write_appointment(FILE* f_output, pst_item_appointment* appointment, - pst_item_email* email, FILETIME* create_date, FILETIME* modify_date); + pst_item_email* email, FILETIME* create_date, FILETIME* modify_date); void create_enter_dir(struct file_ll* f, char file_as[], int mode, int overwrite); char *prog_name; char *output_dir = "."; @@ -135,18 +136,25 @@ int output_mode = OUTPUT_NORMAL; int contact_mode = CMODE_VCARD; int overwrite = 0; - // int encrypt = 0; - char *temp = NULL; //temporary char pointer - int skip_child = 0; - struct file_ll *f, *head; + char *enc = NULL; // base64 encoded attachment + char *boundary = NULL, *b1, *b2; // the boundary marker between multipart sections + char *temp = NULL; //temporary char pointer + char *attach_filename = NULL; + int skip_child = 0; + struct file_ll *f, *head; + int save_rtf_body = 1; prog_name = argv[0]; - while ((c = getopt(argc, argv, "d:hko:qrMSVwc:"))!= -1) { + // command-line option handling + while ((c = getopt(argc, argv, "bd:hko:qrMSVwc:"))!= -1) { switch (c) { + case 'b': + save_rtf_body = 0; + break; case 'c': - if (optarg!=NULL && optarg[0]=='v') + if (optarg && optarg[0]=='v') contact_mode=CMODE_VCARD; - else if (optarg!=NULL && optarg[0]=='l') + else if (optarg && optarg[0]=='l') contact_mode=CMODE_LIST; else { usage(); @@ -195,7 +203,7 @@ #ifdef DEBUG_ALL // initialize log file - if (d_log == NULL) + if (!d_log) d_log = "readpst.log"; DEBUG_INIT(d_log); DEBUG_REGISTER_CLOSE(); @@ -229,14 +237,14 @@ if (output_mode != OUTPUT_QUIET) printf("About to start processing first record...\n"); d_ptr = pstfile.d_head; // first record is main record - if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->message_store == NULL) { + if (!(item = _pst_parse_item(&pstfile, d_ptr)) || !item->message_store) { DIE(("main: Could not get root record\n")); } // default the file_as to the same as the main filename if it doesn't exist - if (item->file_as == NULL) { - if ((temp = strrchr(fname, '/')) == NULL) - if ((temp = strrchr(fname, '\\')) == NULL) + if (!item->file_as) { + if (!(temp = strrchr(fname, '/'))) + if (!(temp = strrchr(fname, '\\'))) temp = fname; else temp++; // get past the "\\" @@ -258,7 +266,7 @@ create_enter_dir(f, item->file_as, mode, overwrite); f->type = item->type; - if ((d_ptr = pst_getTopOfFolders(&pstfile, item)) == NULL) { + if (!(d_ptr = pst_getTopOfFolders(&pstfile, item))) { DIE(("Top of folders record not found. Cannot continue\n")); } @@ -267,18 +275,18 @@ item = NULL; } - /* if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->folder == NULL) { - DEBUG_MAIN(("main: Could not get \"Top Of Personal Folder\" record\n")); - return -2; - }*/ + /* if ((item = _pst_parse_item(&pstfile, d_ptr)) == NULL || item->folder == NULL) { + DEBUG_MAIN(("main: Could not get \"Top Of Personal Folder\" record\n")); + return -2; + }*/ d_ptr = d_ptr->child; // do the children of TOPF if (output_mode != OUTPUT_QUIET) printf("Processing items...\n"); DEBUG_MAIN(("main: About to do email stuff\n")); - while (d_ptr != NULL) { + while (d_ptr) { DEBUG_MAIN(("main: New item record\n")); - if (d_ptr->desc == NULL) { + if (!d_ptr->desc) { DEBUG_WARN(("main: ERROR ?? item's desc record is NULL\n")); f->skip_count++; goto check_parent; @@ -287,19 +295,18 @@ item = _pst_parse_item(&pstfile, d_ptr); DEBUG_MAIN(("main: About to process item\n")); - if (item != NULL && item->email != NULL && item->email->subject != NULL && - item->email->subject->subj != NULL) { + if (item && item->email && item->email->subject && + item->email->subject->subj) { // DEBUG_EMAIL(("item->email->subject = %p\n", item->email->subject)); // DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); } - if (item != NULL) { - if (item->message_store != NULL) { + if (item) { + if (item->message_store) { // there should only be one message_store, and we have already done it DIE(("main: A second message_store has been found. Sorry, this must be an error.\n")); } - - if (item->folder != NULL) { + if (item->folder) { // if this is a folder, we want to recurse into it if (output_mode != OUTPUT_QUIET) printf("Processing Folder \"%s\"\n", item->file_as); // f->email_count++; @@ -316,7 +323,7 @@ temp = item->file_as; temp = check_filename(temp); create_enter_dir(f, item->file_as, mode, overwrite); - if (d_ptr->child != NULL) { + if (d_ptr->child) { d_ptr = d_ptr->child; skip_child = 1; } else { @@ -324,7 +331,7 @@ if (output_mode != OUTPUT_QUIET) printf("\tNo items to process in folder \"%s\", should have been %i\n", f->dname, f->stored_count); head = f->next; - if (f->output != NULL) + if (f->output) fclose(f->output); if (mode == MODE_KMAIL) close_kmail_dir(); @@ -341,7 +348,7 @@ _pst_freeItem(item); item = NULL; // just for the odd situations! goto check_parent; - } else if (item->contact != NULL) { + } else if (item->contact) { // deal with a contact // write them to the file, one per line in this format // Desc Name \n @@ -353,14 +360,14 @@ DEBUG_MAIN(("main: Processing Contact\n")); if (f->type != PST_TYPE_CONTACT) { DEBUG_MAIN(("main: I have a contact, but the folder isn't a contacts folder. " - "Will process anyway\n")); + "Will process anyway\n")); } if (item->type != PST_TYPE_CONTACT) { DEBUG_MAIN(("main: I have an item that has contact info, but doesn't say that" - " it is a contact. Type is \"%s\"\n", item->ascii_type)); + " it is a contact. Type is \"%s\"\n", item->ascii_type)); DEBUG_MAIN(("main: Processing anyway\n")); } - if (item->contact == NULL) { // this is an incorrect situation. Inform user + if (!item->contact) { // this is an incorrect situation. Inform user DEBUG_MAIN(("main: ERROR. This contact has not been fully parsed. one of the pre-requisties is NULL\n")); } else { if (contact_mode == CMODE_VCARD) @@ -368,8 +375,7 @@ else fprintf(f->output, "%s <%s>\n", item->contact->fullname, item->contact->address1); } - } else if (item->email != NULL && - (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { + } else if (item->email && (item->type == PST_TYPE_NOTE || item->type == PST_TYPE_REPORT)) { if (mode == MODE_SEPERATE) { mk_seperate_file(f); } @@ -377,7 +383,7 @@ f->email_count++; DEBUG_MAIN(("main: seen an email\n")); - write_normal_email(f->output, f->name, item, mode, mode_MH, &pstfile); + write_normal_email(f->output, f->name, item, mode, mode_MH, &pstfile, save_rtf_body); } else if (item->type == PST_TYPE_JOURNAL) { // deal with journal items if (mode == MODE_SEPERATE) { @@ -395,11 +401,11 @@ item->ascii_type)); }*/ fprintf(f->output, "BEGIN:VJOURNAL\n"); - if (item->email->subject != NULL) + if (item->email->subject) fprintf(f->output, "SUMMARY:%s\n", rfc2426_escape(item->email->subject->subj)); - if (item->email->body != NULL) + if (item->email->body) fprintf(f->output, "DESCRIPTION:%s\n", rfc2426_escape(item->email->body)); - if (item->journal->start != NULL) + if (item->journal->start) fprintf(f->output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(item->journal->start)); fprintf(f->output, "END:VJOURNAL\n\n"); } else if (item->type == PST_TYPE_APPOINTMENT) { @@ -417,7 +423,7 @@ } else { f->skip_count++; DEBUG_MAIN(("main: Unknown item type. %i. Ascii1=\"%s\"\n", - item->type, item->ascii_type)); + item->type, item->ascii_type)); } } else { f->skip_count++; @@ -428,15 +434,15 @@ check_parent: // _pst_freeItem(item); - while (!skip_child && d_ptr->next == NULL && d_ptr->parent != NULL) { + while (!skip_child && !d_ptr->next && d_ptr->parent) { DEBUG_MAIN(("main: Going to Parent\n")); head = f->next; - if (f->output != NULL) + if (f->output) fclose(f->output); DEBUG_MAIN(("main: Email Count for folder %s is %i\n", f->dname, f->email_count)); if (output_mode != OUTPUT_QUIET) printf("\t\"%s\" - %i items done, skipped %i, should have been %i\n", - f->dname, f->email_count, f->skip_count, f->stored_count); + f->dname, f->email_count, f->skip_count, f->stored_count); if (mode == MODE_KMAIL) close_kmail_dir(); else if (mode == MODE_RECURSE) @@ -447,7 +453,7 @@ free(f->dname); free(f); f = head; - if (head == NULL) { //we can't go higher. Must be at start? + if (!head) { //we can't go higher. Must be at start? DEBUG_MAIN(("main: We are now trying to go above the highest level. We must be finished\n")); break; //from main while loop } @@ -455,7 +461,7 @@ skip_child = 0; } - if (item != NULL) { + if (item) { DEBUG_MAIN(("main: Freeing memory used by item\n")); _pst_freeItem(item); item = NULL; @@ -466,7 +472,7 @@ else skip_child = 0; - if (d_ptr == NULL) { + if (!d_ptr) { DEBUG_MAIN(("main: d_ptr is now NULL\n")); } } @@ -474,9 +480,9 @@ DEBUG_MAIN(("main: Finished.\n")); pst_close(&pstfile); - // fclose(pstfile.fp); - while (f != NULL) { - if (f->output != NULL) + // fclose(pstfile.fp); + while (f) { + if (f->output) fclose(f->output); free(f->name); free(f->dname); @@ -497,11 +503,13 @@ return 0; } + + void write_email_body(FILE *f, char *body) { char *n = body; - // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body)); + // DEBUG_MAIN(("write_email_body(): \"%s\"\n", body)); DEBUG_ENT("write_email_body"); - while (n != NULL) { + while (n) { if (strncmp(body, "From ", 5) == 0) fprintf(f, ">"); if ((n = strchr(body, '\n'))) { @@ -514,6 +522,8 @@ fwrite(body, strlen(body), 1, f); DEBUG_RET(); } + + char *removeCR (char *c) { // converts /r/n to /n char *a, *b; @@ -529,17 +539,20 @@ DEBUG_RET(); return c; } + + int usage() { DEBUG_ENT("usage"); version(); printf("Usage: %s [OPTIONS] {PST FILENAME}\n", prog_name); printf("OPTIONS:\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-d\t- Debug to file. This is a binary log. Use readlog to print it\n"); + printf("\t-d \t- Debug to file. This is a binary log. Use readlog to print it\n"); printf("\t-h\t- Help. This screen\n"); printf("\t-k\t- KMail. Output in kmail format\n"); printf("\t-M\t- MH. Write emails in the MH format\n"); - printf("\t-o\t- Output Dir. Directory to write files to. CWD is changed *after* opening pst file\n"); + printf("\t-o \t- Output Dir. 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-S\t- Seperate. Write emails in the seperate format\n"); @@ -548,6 +561,8 @@ DEBUG_RET(); return 0; } + + int version() { DEBUG_ENT("version"); printf("ReadPST v%s\n", VERSION); @@ -564,6 +579,8 @@ DEBUG_RET(); return 0; } + + char *mk_kmail_dir(char *fname) { //change to that directory //make a directory based on OUTPUT_KMAIL_DIR_TEMPLATE @@ -572,7 +589,7 @@ char *dir, *out_name, *index; int x; DEBUG_ENT("mk_kmail_dir"); - if (kmail_chdir != NULL && chdir(kmail_chdir)) { + if (kmail_chdir && chdir(kmail_chdir)) { x = errno; DIE(("mk_kmail_dir: Cannot change to directory %s: %s\n", kmail_chdir, strerror(x))); } @@ -601,11 +618,13 @@ DEBUG_RET(); return out_name; } + + int close_kmail_dir() { // change .. int x; DEBUG_ENT("close_kmail_dir"); - if (kmail_chdir != NULL) { //only free kmail_chdir if not NULL. do not change directory + if (kmail_chdir) { //only free kmail_chdir if not NULL. do not change directory free(kmail_chdir); kmail_chdir = NULL; } else { @@ -617,6 +636,8 @@ DEBUG_RET(); return 0; } + + // this will create a directory by that name, then make an mbox file inside // that dir. any subsequent dirs will be created by name, and they will // contain mbox files @@ -640,6 +661,8 @@ DEBUG_RET(); return out_name; } + + int close_recurse_dir() { int x; DEBUG_ENT("close_recurse_dir"); @@ -650,16 +673,18 @@ DEBUG_RET(); return 0; } + + char *mk_seperate_dir(char *dir, int overwrite) { -#if !defined(WIN32) && !defined(__CYGWIN__) - DIR * sdir = NULL; - struct dirent *dirent = NULL; - struct stat *filestat = xmalloc(sizeof(struct stat)); -#endif + DEBUG_ENT("mk_seperate_dir"); + #if !defined(WIN32) && !defined(__CYGWIN__) + DIR * sdir = NULL; + struct dirent *dirent = NULL; + struct stat *filestat = xmalloc(sizeof(struct stat)); + #endif char *dir_name = NULL; int x = 0, y = 0; - DEBUG_ENT("mk_seperate_dir"); /*#if defined(WIN32) || defined(__CYGWIN__) DIE(("mk_seperate_dir: Win32 applications cannot use this function yet.\n")); #endif*/ @@ -673,7 +698,7 @@ sprintf(dir_name, "%s" SEP_MAIL_FILE_TEMPLATE, dir, y); // enough for 9 digits allocated above dir_name = check_filename(dir_name); - DEBUG_MAIN(("mk_seperate_dir: about to try creating %s\n", dir_name)); + DEBUG_MAIN(("about to try creating %s\n", dir_name)); if (D_MKDIR(dir_name)) { if (errno != EEXIST) { // if there is an error, and it doesn't already exist x = errno; @@ -693,10 +718,10 @@ if (overwrite) { // we should probably delete all files from this directory #if !defined(WIN32) && !defined(__CYGWIN__) - if ((sdir = opendir("./")) == NULL) { + if (!(sdir = opendir("./"))) { WARN(("mk_seperate_dir: Cannot open dir \"%s\" for deletion of old contents\n", "./")); } else { - while ((dirent = readdir(sdir)) != NULL) { + while ((dirent = readdir(sdir))) { if (lstat(dirent->d_name, filestat) != -1) if (S_ISREG(filestat->st_mode)) { if (unlink(dirent->d_name)) { @@ -710,12 +735,14 @@ } // overwrite will never change during this function, it is just there so that - // if overwrite is set, we only go through this loop once. + // if overwrite is set, we only go through this loop once. // we don't return a filename here cause it isn't necessary. DEBUG_RET(); return NULL; } + + int close_seperate_dir() { int x; DEBUG_ENT("close_seperate_dir"); @@ -726,35 +753,39 @@ DEBUG_RET(); return 0; } + + int mk_seperate_file(struct file_ll *f) { const int name_offset = 1; DEBUG_ENT("mk_seperate_file"); - DEBUG_MAIN(("mk_seperate_file: opening next file to save email\n")); + DEBUG_MAIN(("opening next file to save email\n")); if (f->email_count > 999999999) { // bigger than nine 9's DIE(("mk_seperate_file: The number of emails in this folder has become too high to handle")); } sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count + name_offset); - if (f->output != NULL) + if (f->output) fclose(f->output); f->output = NULL; f->name = check_filename(f->name); - if ((f->output = fopen(f->name, "w")) == NULL) { + if (!(f->output = fopen(f->name, "w"))) { DIE(("mk_seperate_file: Cannot open file to save email \"%s\"\n", f->name)); } DEBUG_RET(); return 0; } + + char *my_stristr(char *haystack, char *needle) { -// my_stristr varies from strstr in that its searches are case-insensitive + // my_stristr varies from strstr in that its searches are case-insensitive char *x=haystack, *y=needle, *z = NULL; DEBUG_ENT("my_stristr"); - if (haystack == NULL || needle == NULL) + if (!haystack || !needle) return NULL; while (*y != '\0' && *x != '\0') { if (tolower(*y) == tolower(*x)) { // move y on one y++; - if (z == NULL) { + if (!z) { z = x; // store first position in haystack where a match is made } } else { @@ -766,49 +797,61 @@ DEBUG_RET(); return z; } + + char *check_filename(char *fname) { char *t = fname; DEBUG_ENT("check_filename"); - if (t == NULL) { + if (!t) { DEBUG_RET(); return fname; } - while ((t = strpbrk(t, "/\\:")) != NULL) { + while ((t = strpbrk(t, "/\\:"))) { // while there are characters in the second string that we don't want *t = '_'; //replace them with an underscore } DEBUG_RET(); return fname; } + + char *rfc2426_escape(char *str) { static char* buf = NULL; char *ret, *a, *b; int x = 0, y, z; DEBUG_ENT("rfc2426_escape"); - if (str == NULL) + if (!str) ret = str; else { // calculate space required to escape all the following characters - x = strlen(str) +(y=(chr_count(str, ',')*2) + (chr_count(str, '\\')*2) + (chr_count(str, ';')*2) + (chr_count(str, '\n')*2)); + y = chr_count(str, ',') + + chr_count(str, '\\') + + chr_count(str, ';') + + chr_count(str, '\n'); z = chr_count(str, '\r'); + x = strlen(str) + y - z + 1; // don't forget room for the NUL if (y == 0 && z == 0) // there isn't any extra space required ret = str; else { - buf = (char*) realloc(buf, x+1); + buf = (char*) realloc(buf, x); a = str; b = buf; while (*a != '\0') { - switch(*a) { + switch (*a) { case ',' : case '\\': case ';' : - case '\n': - *(b++)='\\'; - *b=*a; + *(b++) = '\\'; + *b = *a; break; - case '\r': + case '\n': // newlines are encoded as "\n" + *(b++) = '\\'; + *b = 'n'; + break; + case '\r': // skip cr + b--; break; default: *b=*a; @@ -816,13 +859,15 @@ b++; a++; } - *b = '\0'; + *b = '\0'; // NUL-terminate the string (buf) ret = buf; } } DEBUG_RET(); return ret; } + + int chr_count(char *str, char x) { int r = 0; while (*str != '\0') { @@ -832,11 +877,13 @@ } return r; } + + char *rfc2425_datetime_format(FILETIME *ft) { static char * buffer = NULL; struct tm *stm = NULL; DEBUG_ENT("rfc2425_datetime_format"); - if (buffer == NULL) + if (!buffer) buffer = malloc(30); // should be enough for the date as defined below stm = fileTimeToStructTM(ft); @@ -847,11 +894,13 @@ DEBUG_RET(); return buffer; } + + char *rfc2445_datetime_format(FILETIME *ft) { static char* buffer = NULL; struct tm *stm = NULL; DEBUG_ENT("rfc2445_datetime_format"); - if (buffer == NULL) + if (!buffer) buffer = malloc(30); // should be enough stm = fileTimeToStructTM(ft); if (strftime(buffer, 30, "%Y%m%dT%H%M%SZ", stm)==0) { @@ -860,110 +909,131 @@ DEBUG_RET(); return buffer; } + + // The sole purpose of this function is to bypass the pseudo-header prologue // that Microsoft Outlook inserts at the beginning of the internet email // headers for emails stored in their "Personal Folders" files. char *skip_header_prologue(char *headers) { const char *bad = "Microsoft Mail Internet Headers"; - if ( strncmp(headers, bad, strlen(bad)) == 0 ) { // Found the offensive header prologue - char *pc; - - pc = strchr(headers, '\n'); + char *pc = strchr(headers, '\n'); return pc + 1; } - return headers; } -// vim:sw=4 ts=4: -// vim600: set foldlevel=0 foldmethod=marker: + void write_separate_attachment(char f_name[], pst_item_attach* current_attach, int attach_num, pst_file* pst) { + DEBUG_ENT("write_separate_attachment"); FILE *fp = NULL; int x = 0; - char *temp; + char *temp = NULL; + + // If there is a long filename (filename2) use that, otherwise + // use the 8.3 filename (filename1) + char *attach_filename = (current_attach->filename2) ? current_attach->filename2 + : current_attach->filename1; check_filename(f_name); - if (current_attach->filename2 == NULL) { + if (!attach_filename) { + // generate our own (dummy) filename for the attachement temp = xmalloc(strlen(f_name)+15); sprintf(temp, "%s-attach%i", f_name, attach_num); } else { - temp = xmalloc(strlen(f_name)+strlen(current_attach->filename2)+15); + // have an attachment name, make sure it's unique + temp = xmalloc(strlen(f_name)+strlen(attach_filename)+15); do { - if (fp != NULL) fclose(fp); + if (fp) fclose(fp); if (x == 0) - sprintf(temp, "%s-%s", f_name, current_attach->filename2); + sprintf(temp, "%s-%s", f_name, attach_filename); else - sprintf(temp, "%s-%s-%i", f_name, current_attach->filename2, x); - } while ((fp = fopen(temp, "r"))!=NULL && ++x < 99999999); + sprintf(temp, "%s-%s-%i", f_name, attach_filename, x); + } while ((fp = fopen(temp, "r")) && ++x < 99999999); if (x > 99999999) { DIE(("error finding attachment name. exhausted possibilities to %s\n", temp)); } } - DEBUG_MAIN(("write_separate_attachment: Saving attachment to %s\n", temp)); - if ((fp = fopen(temp, "w")) == NULL) { + DEBUG_EMAIL(("Saving attachment to %s\n", temp)); + if (!(fp = fopen(temp, "w"))) { WARN(("write_separate_attachment: Cannot open attachment save file \"%s\"\n", temp)); } else { - if (current_attach->data != NULL) + if (current_attach->data) fwrite(current_attach->data, 1, current_attach->size, fp); else { pst_attach_to_file(pst, current_attach, fp); } fclose(fp); } + if (temp) free(temp); + DEBUG_RET(); } + void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst) { + DEBUG_ENT("write_inline_attachment"); char *enc; // base64 encoded attachment - DEBUG_MAIN(("write_inline_attachment: Attachment Size is %i\n", current_attach->size)); - DEBUG_MAIN(("write_inline_attachment: Attachment Pointer is %p\n", current_attach->data)); - if (current_attach->data != NULL) { - if ((enc = base64_encode (current_attach->data, current_attach->size)) == NULL) { - DEBUG_MAIN(("write_inline_attachment: ERROR base64_encode returned NULL. Must have failed\n")); + DEBUG_EMAIL(("Attachment Size is %i\n", current_attach->size)); + DEBUG_EMAIL(("Attachment Pointer is %p\n", current_attach->data)); + if (current_attach->data) { + enc = base64_encode (current_attach->data, current_attach->size); + if (!enc) { + DEBUG_EMAIL(("ERROR base64_encode returned NULL. Must have failed\n")); return; } } if (boundary) { + char *attach_filename; fprintf(f_output, "\n--%s\n", boundary); - if (current_attach->mimetype == NULL) { + if (!current_attach->mimetype) { fprintf(f_output, "Content-type: %s\n", MIME_TYPE_DEFAULT); } else { fprintf(f_output, "Content-type: %s\n", current_attach->mimetype); } fprintf(f_output, "Content-transfer-encoding: base64\n"); - if (current_attach->filename2 == NULL) { + // If there is a long filename (filename2) use that, otherwise + // use the 8.3 filename (filename1) + if (current_attach->filename2) { + attach_filename = current_attach->filename2; + } else { + attach_filename = current_attach->filename1; + } + if (!attach_filename) { fprintf(f_output, "Content-Disposition: inline\n\n"); } else { - fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", - current_attach->filename2); + fprintf(f_output, "Content-Disposition: attachment; filename=\"%s\"\n\n", attach_filename); } } - if (current_attach->data != NULL) { + if (current_attach->data) { fwrite(enc, 1, strlen(enc), f_output); - DEBUG_MAIN(("Attachment Size after encoding is %i\n", strlen(enc))); + DEBUG_EMAIL(("Attachment Size after encoding is %i\n", strlen(enc))); } else { pst_attach_to_file_base64(pst, current_attach, f_output); } fprintf(f_output, "\n\n"); + DEBUG_RET(); } -void write_normal_email(FILE* f_output, char f_name[], pst_item* item, int mode, int mode_MH, pst_file* pst) + +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 *boundary = NULL; // the boundary marker between multipart sections + DEBUG_ENT("write_normal_email"); + char *boundary = NULL; // the boundary marker between multipart sections + int boundary_created = 0; // we have not (yet) created a new boundary char *temp = NULL; int attach_num, base64_body = 0; time_t em_time; char *c_time; - pst_item_attach* current_attach; + pst_item_attach* current_attach; // convert the sent date if it exists, or set it to a fixed date - if (item->email->sent_date != NULL) { + if (item->email->sent_date) { em_time = fileTimeToUnixTime(item->email->sent_date, 0); c_time = ctime(&em_time); - if (c_time != NULL) + if (c_time) c_time[strlen(c_time)-1] = '\0'; //remove end \n else c_time = "Fri Dec 28 12:06:21 2001"; @@ -971,19 +1041,20 @@ c_time= "Fri Dec 28 12:06:21 2001"; // we will always look at the header to discover some stuff - if (item->email->header != NULL ) { + if (item->email->header ) { char *b1, *b2; // see if there is a boundary variable there // this search MUST be made case insensitive (DONE). - // Also, some check to find out if we - // are looking at the boundary associated with content-type, and that the content - // type really is "multipart" + // Also, we should check to find out if we are looking + // at the boundary associated with content-type, and that + // the content type really is multipart removeCR(item->email->header); - if ((b2 = my_stristr(item->email->header, "boundary=")) != NULL) { + if ((b2 = my_stristr(item->email->header, "boundary="))) { + int len; b2 += strlen("boundary="); // move boundary to first char of marker - + if (*b2 == '"') { b2++; b1 = strchr(b2, '"'); // find terminating quote @@ -992,10 +1063,10 @@ while (isgraph(*b1)) // find first char that isn't part of boundary b1++; } - - boundary = malloc ((b1-b2)+1); //malloc that length - memset (boundary, 0, (b1-b2)+1); // blank it - strncpy(boundary, b2, b1-b2); // copy boundary to another variable + len = b1 - b2; + boundary = malloc(len+1); //malloc that length + strncpy(boundary, b2, len); // copy boundary to another variable + boundary[len] = '\0'; b1 = b2 = boundary; while (*b2 != '\0') { // remove any CRs and Tabs if (*b2 != '\n' && *b2 != '\r' && *b2 != '\t') { @@ -1005,379 +1076,378 @@ b2++; } *b1 = '\0'; - - DEBUG_MAIN(("write_normal_email: Found boundary of - %s\n", boundary)); + + DEBUG_EMAIL(("Found boundary of - %s\n", boundary)); } else { - DEBUG_MAIN(("write_normal_email: boundary not found in header\n")); + DEBUG_EMAIL(("boundary not found in header\n")); } // also possible to set 7bit encoding detection here. - if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:")) != NULL) { - if ((b2 = strchr(b2, ':')) != NULL) { + if ((b2 = my_stristr(item->email->header, "Content-Transfer-Encoding:"))) { + if ((b2 = strchr(b2, ':'))) { b2++; // skip to the : at the end of the string - + while (*b2 == ' ' || *b2 == '\t') b2++; if (pst_strincmp(b2, "base64", 6)==0) { - DEBUG_MAIN(("body is base64 encoded\n")); + DEBUG_EMAIL(("body is base64 encoded\n")); base64_body = 1; } } else { DEBUG_WARN(("found a ':' during the my_stristr, but not after that..\n")); } } - } - DEBUG_MAIN(("write_normal_email: About to print Header\n")); - - if (item != NULL && item->email != NULL && item->email->subject != NULL && - item->email->subject->subj != NULL) { - DEBUG_EMAIL(("item->email->subject->subj = %p\n", item->email->subject->subj)); + if (!boundary && (item->attach || (item->email->body && item->email->htmlbody) + || item->email->rtf_compressed || item->email->encrypted_body + || item->email->encrypted_htmlbody)) { + // we need to create a boundary here. + DEBUG_EMAIL(("must create own boundary. oh dear.\n")); + boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary + boundary[0] = '\0'; + sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); + DEBUG_EMAIL(("created boundary is %s\n", boundary)); + boundary_created = 1; } - if (item->email->header != NULL) { + DEBUG_EMAIL(("About to print Header\n")); + + if (item && item->email && item->email->subject && item->email->subject->subj) { + DEBUG_EMAIL(("item->email->subject->subj = %s\n", item->email->subject->subj)); + } + + if (item->email->header) { + int len; + char *soh = NULL; // real start of headers. + // some of the headers we get from the file are not properly defined. // they can contain some email stuff too. We will cut off the header // when we see a \n\n or \r\n\r\n + removeCR(item->email->header); temp = strstr(item->email->header, "\n\n"); - if (temp != NULL) { - DEBUG_MAIN(("write_normal_email: Found body text in header\n")); - *temp = '\0'; - } else { - temp = item->email->header + strlen(item->email->header) - 1; - if(*temp == '\n') - *temp = '\0'; + if (temp) { + DEBUG_EMAIL(("Found body text in header\n")); + temp[1] = '\0'; // stop after first \n } - + + // Now, write out the header... + soh = skip_header_prologue(item->email->header); if (mode != MODE_SEPERATE) { - char *soh = NULL; // real start of headers. // don't put rubbish in if we are doing seperate - fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); - soh = skip_header_prologue(item->email->header); - fprintf(f_output, "%s\n", soh); - } else { - fprintf(f_output, "%s\n", item->email->header); + if (strncmp(soh, "X-From_: ", 9) == 0 ) { + fputs("From ", f_output); + soh += 9; + } else + fprintf(f_output, "From \"%s\" %s\n", item->email->outlook_sender_name, c_time); } + fprintf(f_output, "%s", soh); + len = strlen(soh); + if (!len || (soh[len-1] != '\n')) fprintf(f_output, "\n"); + } else { //make up our own header! if (mode != MODE_SEPERATE) { // don't want this first line for this mode - if (item->email->outlook_sender_name != NULL) { + if (item->email->outlook_sender_name) { temp = item->email->outlook_sender_name; } else { temp = "(readpst_null)"; } fprintf(f_output, "From \"%s\" %s\n", temp, c_time); } - if ((temp = item->email->outlook_sender) == NULL) - temp = ""; + + temp = item->email->outlook_sender; + if (!temp) temp = ""; fprintf(f_output, "From: \"%s\" <%s>\n", item->email->outlook_sender_name, temp); - if (item->email->subject != NULL) { + + if (item->email->subject) { fprintf(f_output, "Subject: %s\n", item->email->subject->subj); } else { fprintf(f_output, "Subject: \n"); } + fprintf(f_output, "To: %s\n", item->email->sentto_address); - if (item->email->cc_address != NULL) { + if (item->email->cc_address) { fprintf(f_output, "Cc: %s\n", item->email->cc_address); } - if (item->email->sent_date != NULL) { + + if (item->email->sent_date) { c_time = (char*) xmalloc(C_TIME_SIZE); strftime(c_time, C_TIME_SIZE, "%a, %d %b %Y %H:%M:%S %z", gmtime(&em_time)); fprintf(f_output, "Date: %s\n", c_time); free(c_time); } - - fprintf(f_output, "MIME-Version: 1.0\n"); } - if (boundary == NULL && (item->attach ||(item->email->body && item->email->htmlbody) - || item->email->rtf_compressed || item->email->encrypted_body - || item->email->encrypted_htmlbody)) { - // we need to create a boundary here. - DEBUG_EMAIL(("write_normal_email: must create own boundary. oh dear.\n")); - boundary = malloc(50 * sizeof(char)); // allow 50 chars for boundary - boundary[0] = '\0'; - sprintf(boundary, "--boundary-LibPST-iamunique-%i_-_-", rand()); - DEBUG_EMAIL(("write_normal_email: created boundary is %s\n", boundary)); - - /* If boundary != NULL, then it has already been printed with existing - * headers. Otherwise we generate it here and print it. - */ - if (item->attach != NULL) { + fprintf(f_output, "MIME-Version: 1.0\n"); + if (boundary && boundary_created) { + // if we created the boundary, then it has NOT already been printed + // in the headers above. + if (item->attach) { // write the boundary stuff if we have attachments - fprintf(f_output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", - boundary); - } else if (boundary != NULL) { + fprintf(f_output, "Content-type: multipart/mixed;\n\tboundary=\"%s\"\n", boundary); + } else if (boundary) { // else if we have multipart/alternative then tell it so - fprintf(f_output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", - boundary); + fprintf(f_output, "Content-type: multipart/alternative;\n\tboundary=\"%s\"\n", boundary); } else if (item->email->htmlbody) { fprintf(f_output, "Content-type: text/html\n"); } } - - fprintf(f_output, "\n"); + fprintf(f_output, "\n"); // start the body + DEBUG_EMAIL(("About to print Body\n")); - DEBUG_MAIN(("write_normal_email: About to print Body\n")); - - if (item->email->body != NULL) { + if (item->email->body) { if (boundary) { fprintf(f_output, "\n--%s\n", boundary); - fprintf(f_output, "Content-type: text/plain\n\n"); + fprintf(f_output, "Content-type: text/plain\n"); if (base64_body) fprintf(f_output, "Content-Transfer-Encoding: base64\n"); + 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))); + write_email_body(f_output, base64_encode(item->email->body, strlen(item->email->body))); else write_email_body(f_output, item->email->body); } - - if (item->email->htmlbody != NULL) { + + if (item->email->htmlbody) { if (boundary) { fprintf(f_output, "\n--%s\n", boundary); - fprintf(f_output, "Content-type: text/html\n\n"); + fprintf(f_output, "Content-type: text/html\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))); + write_email_body(f_output, base64_encode(item->email->htmlbody, strlen(item->email->htmlbody))); else write_email_body(f_output, item->email->htmlbody); } - if (item->email->rtf_compressed != NULL) { - DEBUG_MAIN(("Adding RTF body as attachment\n")); - current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); - 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->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); - strcpy(current_attach->filename2, RTF_ATTACH_NAME); - current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); - strcpy(current_attach->mimetype, RTF_ATTACH_TYPE); - memcpy(&(current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); - LE32_CPU(current_attach->size); - // item->email->rtf_compressed = ; - // attach_num++; + if (item->email->rtf_compressed && save_rtf) { + DEBUG_EMAIL(("Adding RTF body as attachment\n")); + current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); + 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->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); + strcpy(current_attach->filename2, RTF_ATTACH_NAME); + current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); + strcpy(current_attach->mimetype, RTF_ATTACH_TYPE); + memcpy(&(current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); + LE32_CPU(current_attach->size); } + if (item->email->encrypted_body || item->email->encrypted_htmlbody) { // if either the body or htmlbody is encrypted, add them as attachments if (item->email->encrypted_body) { - DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); - current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(current_attach, 0, sizeof(pst_item_attach)); - current_attach->next = item->attach; - item->attach = current_attach; - - current_attach->data = item->email->encrypted_body; - current_attach->size = item->email->encrypted_body_size; + DEBUG_EMAIL(("Adding Encrypted Body as attachment\n")); + current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(current_attach, 0, sizeof(pst_item_attach)); + current_attach->next = item->attach; + item->attach = current_attach; + current_attach->data = item->email->encrypted_body; + current_attach->size = item->email->encrypted_body_size; item->email->encrypted_body = NULL; } + if (item->email->encrypted_htmlbody) { - DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); - current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(current_attach, 0, sizeof(pst_item_attach)); - current_attach->next = item->attach; - item->attach = current_attach; - - current_attach->data = item->email->encrypted_htmlbody; - current_attach->size = item->email->encrypted_htmlbody_size; + DEBUG_EMAIL(("Adding encrypted HTML body as attachment\n")); + current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(current_attach, 0, sizeof(pst_item_attach)); + current_attach->next = item->attach; + item->attach = current_attach; + current_attach->data = item->email->encrypted_htmlbody; + current_attach->size = item->email->encrypted_htmlbody_size; item->email->encrypted_htmlbody = NULL; } write_email_body(f_output, "The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n"); } + // attachments + base64_body = 0; attach_num = 0; - for(current_attach = item->attach; - current_attach; - current_attach = current_attach->next) { - DEBUG_MAIN(("write_normal_email: Attempting Attachment encoding\n")); - if (current_attach->data == NULL) { - DEBUG_MAIN(("write_normal_email: Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size)); + for (current_attach = item->attach; + current_attach; + current_attach = current_attach->next) { + DEBUG_EMAIL(("Attempting Attachment encoding\n")); + if (!current_attach->data) { + DEBUG_EMAIL(("Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size)); } - attach_num++; if (mode == MODE_SEPERATE && !mode_MH) - write_separate_attachment(f_name, current_attach, attach_num, pst); + write_separate_attachment(f_name, current_attach, ++attach_num, pst); else - write_inline_attachment(f_output, current_attach, boundary, pst); + write_inline_attachment(f_output, current_attach, boundary, pst); } if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */ - DEBUG_MAIN(("write_normal_email: Writing buffer between emails\n")); - if (boundary) - fprintf(f_output, "\n--%s--\n", boundary); + DEBUG_EMAIL(("Writing buffer between emails\n")); + if (boundary) fprintf(f_output, "\n--%s--\n", boundary); fprintf(f_output, "\n\n"); } - if (boundary) - free (boundary); + if (boundary) free (boundary); + DEBUG_RET(); } + void write_vcard(FILE* f_output, pst_item_contact* contact, char comment[]) { + DEBUG_ENT("write_vcard"); // the specification I am following is (hopefully) RFC2426 vCard Mime Directory Profile fprintf(f_output, "BEGIN:VCARD\n"); fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->fullname)); fprintf(f_output, "N:%s;%s;%s;%s;%s\n", - rfc2426_escape((contact->surname==NULL?"":contact->surname)), - rfc2426_escape((contact->first_name==NULL?"":contact->first_name)), - rfc2426_escape((contact->middle_name==NULL?"":contact->middle_name)), - rfc2426_escape((contact->display_name_prefix==NULL?"":contact->display_name_prefix)), - rfc2426_escape((contact->suffix==NULL?"":contact->suffix))); - if (contact->nickname != NULL) + (!contact->surname) ? "" : rfc2426_escape(contact->surname), + (!contact->first_name) ? "" : rfc2426_escape(contact->first_name), + (!contact->middle_name) ? "" : rfc2426_escape(contact->middle_name), + (!contact->display_name_prefix) ? "" : rfc2426_escape(contact->display_name_prefix), + (!contact->suffix) ? "" : rfc2426_escape(contact->suffix)); + if (contact->nickname) fprintf(f_output, "NICKNAME:%s\n", rfc2426_escape(contact->nickname)); - if (contact->address1 != NULL) + if (contact->address1) fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address1)); - if (contact->address2 != NULL) + if (contact->address2) fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address2)); - if (contact->address3 != NULL) + if (contact->address3) fprintf(f_output, "EMAIL:%s\n", rfc2426_escape(contact->address3)); - if (contact->birthday != NULL) + if (contact->birthday) fprintf(f_output, "BDAY:%s\n", rfc2425_datetime_format(contact->birthday)); - if (contact->home_address != NULL) { + if (contact->home_address) { fprintf(f_output, "ADR;TYPE=home:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((contact->home_po_box!=NULL?contact->home_po_box:"")), - "", // extended Address - rfc2426_escape((contact->home_street!=NULL?contact->home_street:"")), - rfc2426_escape((contact->home_city!=NULL?contact->home_city:"")), - rfc2426_escape((contact->home_state!=NULL?contact->home_state:"")), - rfc2426_escape((contact->home_postal_code!=NULL?contact->home_postal_code:"")), - rfc2426_escape((contact->home_country!=NULL?contact->home_country:""))); + (!contact->home_po_box) ? "" : rfc2426_escape(contact->home_po_box), + "", // extended Address + (!contact->home_street) ? "" : rfc2426_escape(contact->home_street), + (!contact->home_city) ? "" : rfc2426_escape(contact->home_city), + (!contact->home_state) ? "" : rfc2426_escape(contact->home_state), + (!contact->home_postal_code) ? "" : rfc2426_escape(contact->home_postal_code), + (!contact->home_country) ? "" : rfc2426_escape(contact->home_country)); fprintf(f_output, "LABEL;TYPE=home:%s\n", rfc2426_escape(contact->home_address)); } - if (contact->business_address != NULL) { + if (contact->business_address) { fprintf(f_output, "ADR;TYPE=work:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((contact->business_po_box!=NULL?contact->business_po_box:"")), + (!contact->business_po_box) ? "" : rfc2426_escape(contact->business_po_box), "", // extended Address - rfc2426_escape((contact->business_street!=NULL?contact->business_street:"")), - rfc2426_escape((contact->business_city!=NULL?contact->business_city:"")), - rfc2426_escape((contact->business_state!=NULL?contact->business_state:"")), - rfc2426_escape((contact->business_postal_code!=NULL?contact->business_postal_code:"")), - rfc2426_escape((contact->business_country!=NULL?contact->business_country:""))); + (!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 != NULL) { + if (contact->other_address) { fprintf(f_output, "ADR;TYPE=postal:%s;%s;%s;%s;%s;%s;%s\n", - rfc2426_escape((contact->other_po_box != NULL ? - contact->business_po_box:"")), + (!contact->other_po_box) ? "" : rfc2426_escape(contact->business_po_box), "", // extended Address - rfc2426_escape((contact->other_street != NULL ? - contact->other_street:"")), - rfc2426_escape((contact->other_city != NULL ? - contact->other_city:"")), - rfc2426_escape((contact->other_state != NULL ? - contact->other_state:"")), - rfc2426_escape((contact->other_postal_code != NULL ? - contact->other_postal_code:"")), - rfc2426_escape((contact->other_country != NULL ? - contact->other_country:""))); - fprintf(f_output, "ADR;TYPE=postal:%s\n", - rfc2426_escape(contact->other_address)); + (!contact->other_street) ? "" : rfc2426_escape(contact->other_street), + (!contact->other_city) ? "" : rfc2426_escape(contact->other_city), + (!contact->other_state) ? "" : rfc2426_escape(contact->other_state), + (!contact->other_postal_code) ? "" : rfc2426_escape(contact->other_postal_code), + (!contact->other_country) ? "" : rfc2426_escape(contact->other_country)); + fprintf(f_output, "LABEL;TYPE=postal:%s\n", rfc2426_escape(contact->other_address)); } - if (contact->business_fax != NULL) + if (contact->business_fax) fprintf(f_output, "TEL;TYPE=work,fax:%s\n", rfc2426_escape(contact->business_fax)); - if (contact->business_phone != NULL) + if (contact->business_phone) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(contact->business_phone)); - if (contact->business_phone2 != NULL) + if (contact->business_phone2) fprintf(f_output, "TEL;TYPE=work,voice:%s\n", rfc2426_escape(contact->business_phone2)); - if (contact->car_phone != NULL) + if (contact->car_phone) fprintf(f_output, "TEL;TYPE=car,voice:%s\n", rfc2426_escape(contact->car_phone)); - if (contact->home_fax != NULL) + if (contact->home_fax) fprintf(f_output, "TEL;TYPE=home,fax:%s\n", rfc2426_escape(contact->home_fax)); - if (contact->home_phone != NULL) + if (contact->home_phone) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(contact->home_phone)); - if (contact->home_phone2 != NULL) + if (contact->home_phone2) fprintf(f_output, "TEL;TYPE=home,voice:%s\n", rfc2426_escape(contact->home_phone2)); - if (contact->isdn_phone != NULL) + if (contact->isdn_phone) fprintf(f_output, "TEL;TYPE=isdn:%s\n", rfc2426_escape(contact->isdn_phone)); - if (contact->mobile_phone != NULL) + if (contact->mobile_phone) fprintf(f_output, "TEL;TYPE=cell,voice:%s\n", rfc2426_escape(contact->mobile_phone)); - if (contact->other_phone != NULL) + if (contact->other_phone) fprintf(f_output, "TEL;TYPE=msg:%s\n", rfc2426_escape(contact->other_phone)); - if (contact->pager_phone != NULL) + if (contact->pager_phone) fprintf(f_output, "TEL;TYPE=pager:%s\n", rfc2426_escape(contact->pager_phone)); - if (contact->primary_fax != NULL) + if (contact->primary_fax) fprintf(f_output, "TEL;TYPE=fax,pref:%s\n", rfc2426_escape(contact->primary_fax)); - if (contact->primary_phone != NULL) + if (contact->primary_phone) fprintf(f_output, "TEL;TYPE=phone,pref:%s\n", rfc2426_escape(contact->primary_phone)); - if (contact->radio_phone != NULL) + if (contact->radio_phone) fprintf(f_output, "TEL;TYPE=pcs:%s\n", rfc2426_escape(contact->radio_phone)); - if (contact->telex != NULL) + if (contact->telex) fprintf(f_output, "TEL;TYPE=bbs:%s\n", rfc2426_escape(contact->telex)); - if (contact->job_title != NULL) + if (contact->job_title) fprintf(f_output, "TITLE:%s\n", rfc2426_escape(contact->job_title)); - if (contact->profession != NULL) + if (contact->profession) fprintf(f_output, "ROLE:%s\n", rfc2426_escape(contact->profession)); - if (contact->assistant_name != NULL - || contact->assistant_phone != NULL) { - fprintf(f_output, "AGENT:BEGIN:VCARD\\n"); - if (contact->assistant_name != NULL) - fprintf(f_output, "FN:%s\\n", + if (contact->assistant_name + || contact->assistant_phone) { + fprintf(f_output, "AGENT:BEGIN:VCARD\n"); + if (contact->assistant_name) + fprintf(f_output, "FN:%s\n", rfc2426_escape(contact->assistant_name)); - if (contact->assistant_phone != NULL) - fprintf(f_output, "TEL:%s\\n", + if (contact->assistant_phone) + fprintf(f_output, "TEL:%s\n", rfc2426_escape(contact->assistant_phone)); } - if (contact->company_name != NULL) + if (contact->company_name) fprintf(f_output, "ORG:%s\n", rfc2426_escape(contact->company_name)); - if (comment != NULL) + if (comment) fprintf(f_output, "NOTE:%s\n", rfc2426_escape(comment)); fprintf(f_output, "VERSION: 3.0\n"); fprintf(f_output, "END:VCARD\n\n"); + DEBUG_RET(); } + void write_appointment(FILE* f_output, pst_item_appointment* appointment, - pst_item_email* email, FILETIME* create_date, FILETIME* modify_date) + pst_item_email* email, FILETIME* create_date, FILETIME* modify_date) { fprintf(f_output, "BEGIN:VEVENT\n"); - if (create_date != NULL) + if (create_date) fprintf(f_output, "CREATED:%s\n", rfc2445_datetime_format(create_date)); - if (modify_date != NULL) + if (modify_date) fprintf(f_output, "LAST-MOD:%s\n", rfc2445_datetime_format(modify_date)); - if (email != NULL && email->subject != NULL) + if (email && email->subject) fprintf(f_output, "SUMMARY:%s\n", rfc2426_escape(email->subject->subj)); - if (email != NULL && email->body != NULL) + if (email && email->body) fprintf(f_output, "DESCRIPTION:%s\n", rfc2426_escape(email->body)); - if (appointment != NULL && appointment->start != NULL) + if (appointment && appointment->start) fprintf(f_output, "DTSTART;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(appointment->start)); - if (appointment != NULL && appointment->end != NULL) + if (appointment && appointment->end) fprintf(f_output, "DTEND;VALUE=DATE-TIME:%s\n", rfc2445_datetime_format(appointment->end)); - if (appointment != NULL && appointment->location != NULL) + if (appointment && appointment->location) fprintf(f_output, "LOCATION:%s\n", rfc2426_escape(appointment->location)); - if (appointment != NULL) { + if (appointment) { switch (appointment->showas) { case PST_FREEBUSY_TENTATIVE: fprintf(f_output, "STATUS:TENTATIVE\n"); @@ -1429,8 +1499,10 @@ fprintf(f_output, "END:VEVENT\n\n"); } + void create_enter_dir(struct file_ll* f, char file_as[], int mode, int overwrite) { + DEBUG_ENT("create_enter_dir"); if (mode == MODE_KMAIL) f->name = mk_kmail_dir(file_as); //create directory and form filename else if (mode == MODE_RECURSE) @@ -1442,7 +1514,7 @@ memset(f->name, 0, 10); // sprintf(f->name, SEP_MAIL_FILE_TEMPLATE, f->email_count); } else { - f->name = (char*) xmalloc(strlen(file_as)+strlen(OUTPUT_TEMPLATE+1)); + f->name = (char*) xmalloc(strlen(file_as)+strlen(OUTPUT_TEMPLATE)+1); sprintf(f->name, OUTPUT_TEMPLATE, file_as); } @@ -1455,12 +1527,12 @@ sprintf(temp, "%s", f->name); temp = check_filename(temp); - while ((f->output = fopen(temp, "r")) != NULL) { - DEBUG_MAIN(("create_enter_dir: need to increase filename cause one already exists with that name\n")); - DEBUG_MAIN(("create_enter_dir: - increasing it to %s%d\n", f->name, x)); + while ((f->output = fopen(temp, "r"))) { + DEBUG_MAIN(("need to increase filename because one already exists with that name\n")); + DEBUG_MAIN(("- increasing it to %s%d\n", f->name, x)); x++; sprintf(temp, "%s%08d", f->name, x); - DEBUG_MAIN(("create_enter_dir: - trying \"%s\"\n", f->name)); + DEBUG_MAIN(("- trying \"%s\"\n", f->name)); if (x == 99999999) { DIE(("create_enter_dir: Why can I not create a folder %s? I have tried %i extensions...\n", f->name, x)); } @@ -1474,12 +1546,13 @@ } } - DEBUG_MAIN(("create_enter_dir: f->name = %s\nitem->folder_name = %s\n", f->name, file_as)); + DEBUG_MAIN(("f->name = %s\nitem->folder_name = %s\n", f->name, file_as)); if (mode != MODE_SEPERATE) { f->name = check_filename(f->name); - if ((f->output = fopen(f->name, "w")) == NULL) { + if (!(f->output = fopen(f->name, "w"))) { DIE(("create_enter_dir: Could not open file \"%s\" for write\n", f->name)); } } + DEBUG_RET(); } diff -r 45eccad4b606 -r b88ceb81dba2 xml/libpst.in --- a/xml/libpst.in Sat Feb 25 16:16:15 2006 -0800 +++ b/xml/libpst.in Tue Jul 10 17:17:28 2007 -0700 @@ -2,17 +2,24 @@ @PACKAGE@ Utilities - Version @VERSION@ Packages - The various source and binary packages are available at http://www.five-ten-sg.com/@PACKAGE@/packages/ - The most recent documentation is available at http://www.five-ten-sg.com/@PACKAGE@/ - + + This is a fork of the libpst project at SourceForge. Another fork + is located at http://alioth.debian.org/projects/libpst/ + + + The various source and binary packages are available at http://www.five-ten-sg.com/@PACKAGE@/packages/ + The most recent documentation is available at http://www.five-ten-sg.com/@PACKAGE@/ + + - 2006-02-20 + 2007-07-10 @@ -30,6 +37,7 @@ Synopsis readpst + @@ -57,6 +65,12 @@ Options + -b + + Do not save the attachments for the RTF format of the email body. + + + -c format Set the Contact output mode. Use -cv for vcard format or -cl for an email list. @@ -73,7 +87,7 @@ -h - Show summary of options. Subsequent options are then ignored. + Show summary of options and exit. @@ -129,7 +143,7 @@ -V - Show program version. Subsequent options are then ignored. + Show program version and exit. @@ -191,7 +205,7 @@ - 2006-02-20 + 2007-07-10 @@ -359,7 +373,7 @@ - 2006-02-20 + 2007-07-10 @@ -474,7 +488,7 @@ - 2006-02-20 + 2007-07-10