Main Page | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

libpst.c

Go to the documentation of this file.
00001 /***
00002  * libpst.c
00003  * Part of the LibPST project
00004  * Written by David Smith
00005  *            dave.s@earthcorp.com
00006  */
00007 #include "define.h"
00008 #include "libstrfunc.h"
00009 #include "vbuf.h"
00010 #include "libpst.h"
00011 #include "timeconv.h"
00012 
00013 #define ASSERT(x) { if(!(x)) raise( SIGSEGV ); }
00014 
00015 
00016 #define INDEX_TYPE32            0x0E
00017 #define INDEX_TYPE64            0x17
00018 #define INDEX_TYPE_OFFSET       (off_t)0x0A
00019 
00020 #define FILE_SIZE_POINTER32     (off_t)0xA8
00021 #define INDEX_POINTER32         (off_t)0xC4
00022 #define INDEX_BACK32            (off_t)0xC0
00023 #define SECOND_POINTER32        (off_t)0xBC
00024 #define SECOND_BACK32           (off_t)0xB8
00025 #define ENC_TYPE32              (off_t)0x1CD
00026 
00027 #define FILE_SIZE_POINTER64     (off_t)0xB8
00028 #define INDEX_POINTER64         (off_t)0xF0
00029 #define INDEX_BACK64            (off_t)0xE8
00030 #define SECOND_POINTER64        (off_t)0xE0
00031 #define SECOND_BACK64           (off_t)0xD8
00032 #define ENC_TYPE64              (off_t)0x201
00033 
00034 #define FILE_SIZE_POINTER ((pf->do_read64) ? FILE_SIZE_POINTER64 : FILE_SIZE_POINTER32)
00035 #define INDEX_POINTER     ((pf->do_read64) ? INDEX_POINTER64     : INDEX_POINTER32)
00036 #define INDEX_BACK        ((pf->do_read64) ? INDEX_BACK64        : INDEX_BACK32)
00037 #define SECOND_POINTER    ((pf->do_read64) ? SECOND_POINTER64    : SECOND_POINTER32)
00038 #define SECOND_BACK       ((pf->do_read64) ? SECOND_BACK64       : SECOND_BACK32)
00039 #define ENC_TYPE          ((pf->do_read64) ? ENC_TYPE64          : ENC_TYPE32)
00040 
00041 #define PST_SIGNATURE 0x4E444221
00042 
00043 
00044 struct pst_table_ptr_struct32{
00045   uint32_t start;
00046   uint32_t u1;
00047   uint32_t offset;
00048 };
00049 
00050 
00051 struct pst_table_ptr_structn{
00052   uint64_t start;
00053   uint64_t u1;
00054   uint64_t offset;
00055 };
00056 
00057 
00058 typedef struct pst_block_header {
00059     uint16_t type;
00060     uint16_t count;
00061 } pst_block_header;
00062 
00063 
00064 typedef struct pst_id2_assoc32 {
00065     uint32_t id2;
00066     uint32_t id;
00067     uint32_t table2;
00068 } pst_id2_assoc32;
00069 
00070 
00071 typedef struct pst_id2_assoc {
00072     uint32_t id2;       // only 32 bit here?
00073     uint16_t unknown1;
00074     uint16_t unknown2;
00075     uint64_t id;
00076     uint64_t table2;
00077 } pst_id2_assoc;
00078 
00079 
00080 typedef struct pst_table3_rec32 {
00081     uint32_t id;
00082 } pst_table3_rec32; //for type 3 (0x0101) blocks
00083 
00084 
00085 typedef struct pst_table3_rec {
00086     uint64_t id;
00087 } pst_table3_rec;   //for type 3 (0x0101) blocks
00088 
00089 
00090 typedef struct pst_block_hdr {
00091     uint16_t index_offset;
00092     uint16_t type;
00093     uint32_t offset;
00094 } pst_block_hdr;
00095 
00096 
00097 // for "compressible" encryption, just a simple substitution cipher
00098 // this is an array of the un-encrypted values. the un-encrypted value is in the position
00099 // of the encrypted value. ie the encrypted value 0x13 represents 0x02
00100 static unsigned char comp_enc [] = {
00101     0x47, 0xf1, 0xb4, 0xe6, 0x0b, 0x6a, 0x72, 0x48, 0x85, 0x4e, 0x9e, 0xeb, 0xe2, 0xf8, 0x94, 0x53,
00102     0xe0, 0xbb, 0xa0, 0x02, 0xe8, 0x5a, 0x09, 0xab, 0xdb, 0xe3, 0xba, 0xc6, 0x7c, 0xc3, 0x10, 0xdd,
00103     0x39, 0x05, 0x96, 0x30, 0xf5, 0x37, 0x60, 0x82, 0x8c, 0xc9, 0x13, 0x4a, 0x6b, 0x1d, 0xf3, 0xfb,
00104     0x8f, 0x26, 0x97, 0xca, 0x91, 0x17, 0x01, 0xc4, 0x32, 0x2d, 0x6e, 0x31, 0x95, 0xff, 0xd9, 0x23,
00105     0xd1, 0x00, 0x5e, 0x79, 0xdc, 0x44, 0x3b, 0x1a, 0x28, 0xc5, 0x61, 0x57, 0x20, 0x90, 0x3d, 0x83,
00106     0xb9, 0x43, 0xbe, 0x67, 0xd2, 0x46, 0x42, 0x76, 0xc0, 0x6d, 0x5b, 0x7e, 0xb2, 0x0f, 0x16, 0x29,
00107     0x3c, 0xa9, 0x03, 0x54, 0x0d, 0xda, 0x5d, 0xdf, 0xf6, 0xb7, 0xc7, 0x62, 0xcd, 0x8d, 0x06, 0xd3,
00108     0x69, 0x5c, 0x86, 0xd6, 0x14, 0xf7, 0xa5, 0x66, 0x75, 0xac, 0xb1, 0xe9, 0x45, 0x21, 0x70, 0x0c,
00109     0x87, 0x9f, 0x74, 0xa4, 0x22, 0x4c, 0x6f, 0xbf, 0x1f, 0x56, 0xaa, 0x2e, 0xb3, 0x78, 0x33, 0x50,
00110     0xb0, 0xa3, 0x92, 0xbc, 0xcf, 0x19, 0x1c, 0xa7, 0x63, 0xcb, 0x1e, 0x4d, 0x3e, 0x4b, 0x1b, 0x9b,
00111     0x4f, 0xe7, 0xf0, 0xee, 0xad, 0x3a, 0xb5, 0x59, 0x04, 0xea, 0x40, 0x55, 0x25, 0x51, 0xe5, 0x7a,
00112     0x89, 0x38, 0x68, 0x52, 0x7b, 0xfc, 0x27, 0xae, 0xd7, 0xbd, 0xfa, 0x07, 0xf4, 0xcc, 0x8e, 0x5f,
00113     0xef, 0x35, 0x9c, 0x84, 0x2b, 0x15, 0xd5, 0x77, 0x34, 0x49, 0xb6, 0x12, 0x0a, 0x7f, 0x71, 0x88,
00114     0xfd, 0x9d, 0x18, 0x41, 0x7d, 0x93, 0xd8, 0x58, 0x2c, 0xce, 0xfe, 0x24, 0xaf, 0xde, 0xb8, 0x36,
00115     0xc8, 0xa1, 0x80, 0xa6, 0x99, 0x98, 0xa8, 0x2f, 0x0e, 0x81, 0x65, 0x73, 0xe4, 0xc2, 0xa2, 0x8a,
00116     0xd4, 0xe1, 0x11, 0xd0, 0x08, 0x8b, 0x2a, 0xf2, 0xed, 0x9a, 0x64, 0x3f, 0xc1, 0x6c, 0xf9, 0xec
00117 };
00118 
00119 // for "strong" encryption, we have the two additional tables
00120 static unsigned char comp_high1 [] = {
00121     0x41, 0x36, 0x13, 0x62, 0xa8, 0x21, 0x6e, 0xbb, 0xf4, 0x16, 0xcc, 0x04, 0x7f, 0x64, 0xe8, 0x5d,
00122     0x1e, 0xf2, 0xcb, 0x2a, 0x74, 0xc5, 0x5e, 0x35, 0xd2, 0x95, 0x47, 0x9e, 0x96, 0x2d, 0x9a, 0x88,
00123     0x4c, 0x7d, 0x84, 0x3f, 0xdb, 0xac, 0x31, 0xb6, 0x48, 0x5f, 0xf6, 0xc4, 0xd8, 0x39, 0x8b, 0xe7,
00124     0x23, 0x3b, 0x38, 0x8e, 0xc8, 0xc1, 0xdf, 0x25, 0xb1, 0x20, 0xa5, 0x46, 0x60, 0x4e, 0x9c, 0xfb,
00125     0xaa, 0xd3, 0x56, 0x51, 0x45, 0x7c, 0x55, 0x00, 0x07, 0xc9, 0x2b, 0x9d, 0x85, 0x9b, 0x09, 0xa0,
00126     0x8f, 0xad, 0xb3, 0x0f, 0x63, 0xab, 0x89, 0x4b, 0xd7, 0xa7, 0x15, 0x5a, 0x71, 0x66, 0x42, 0xbf,
00127     0x26, 0x4a, 0x6b, 0x98, 0xfa, 0xea, 0x77, 0x53, 0xb2, 0x70, 0x05, 0x2c, 0xfd, 0x59, 0x3a, 0x86,
00128     0x7e, 0xce, 0x06, 0xeb, 0x82, 0x78, 0x57, 0xc7, 0x8d, 0x43, 0xaf, 0xb4, 0x1c, 0xd4, 0x5b, 0xcd,
00129     0xe2, 0xe9, 0x27, 0x4f, 0xc3, 0x08, 0x72, 0x80, 0xcf, 0xb0, 0xef, 0xf5, 0x28, 0x6d, 0xbe, 0x30,
00130     0x4d, 0x34, 0x92, 0xd5, 0x0e, 0x3c, 0x22, 0x32, 0xe5, 0xe4, 0xf9, 0x9f, 0xc2, 0xd1, 0x0a, 0x81,
00131     0x12, 0xe1, 0xee, 0x91, 0x83, 0x76, 0xe3, 0x97, 0xe6, 0x61, 0x8a, 0x17, 0x79, 0xa4, 0xb7, 0xdc,
00132     0x90, 0x7a, 0x5c, 0x8c, 0x02, 0xa6, 0xca, 0x69, 0xde, 0x50, 0x1a, 0x11, 0x93, 0xb9, 0x52, 0x87,
00133     0x58, 0xfc, 0xed, 0x1d, 0x37, 0x49, 0x1b, 0x6a, 0xe0, 0x29, 0x33, 0x99, 0xbd, 0x6c, 0xd9, 0x94,
00134     0xf3, 0x40, 0x54, 0x6f, 0xf0, 0xc6, 0x73, 0xb8, 0xd6, 0x3e, 0x65, 0x18, 0x44, 0x1f, 0xdd, 0x67,
00135     0x10, 0xf1, 0x0c, 0x19, 0xec, 0xae, 0x03, 0xa1, 0x14, 0x7b, 0xa9, 0x0b, 0xff, 0xf8, 0xa3, 0xc0,
00136     0xa2, 0x01, 0xf7, 0x2e, 0xbc, 0x24, 0x68, 0x75, 0x0d, 0xfe, 0xba, 0x2f, 0xb5, 0xd0, 0xda, 0x3d
00137 };
00138 
00139 static unsigned char comp_high2 [] = {
00140     0x14, 0x53, 0x0f, 0x56, 0xb3, 0xc8, 0x7a, 0x9c, 0xeb, 0x65, 0x48, 0x17, 0x16, 0x15, 0x9f, 0x02,
00141     0xcc, 0x54, 0x7c, 0x83, 0x00, 0x0d, 0x0c, 0x0b, 0xa2, 0x62, 0xa8, 0x76, 0xdb, 0xd9, 0xed, 0xc7,
00142     0xc5, 0xa4, 0xdc, 0xac, 0x85, 0x74, 0xd6, 0xd0, 0xa7, 0x9b, 0xae, 0x9a, 0x96, 0x71, 0x66, 0xc3,
00143     0x63, 0x99, 0xb8, 0xdd, 0x73, 0x92, 0x8e, 0x84, 0x7d, 0xa5, 0x5e, 0xd1, 0x5d, 0x93, 0xb1, 0x57,
00144     0x51, 0x50, 0x80, 0x89, 0x52, 0x94, 0x4f, 0x4e, 0x0a, 0x6b, 0xbc, 0x8d, 0x7f, 0x6e, 0x47, 0x46,
00145     0x41, 0x40, 0x44, 0x01, 0x11, 0xcb, 0x03, 0x3f, 0xf7, 0xf4, 0xe1, 0xa9, 0x8f, 0x3c, 0x3a, 0xf9,
00146     0xfb, 0xf0, 0x19, 0x30, 0x82, 0x09, 0x2e, 0xc9, 0x9d, 0xa0, 0x86, 0x49, 0xee, 0x6f, 0x4d, 0x6d,
00147     0xc4, 0x2d, 0x81, 0x34, 0x25, 0x87, 0x1b, 0x88, 0xaa, 0xfc, 0x06, 0xa1, 0x12, 0x38, 0xfd, 0x4c,
00148     0x42, 0x72, 0x64, 0x13, 0x37, 0x24, 0x6a, 0x75, 0x77, 0x43, 0xff, 0xe6, 0xb4, 0x4b, 0x36, 0x5c,
00149     0xe4, 0xd8, 0x35, 0x3d, 0x45, 0xb9, 0x2c, 0xec, 0xb7, 0x31, 0x2b, 0x29, 0x07, 0x68, 0xa3, 0x0e,
00150     0x69, 0x7b, 0x18, 0x9e, 0x21, 0x39, 0xbe, 0x28, 0x1a, 0x5b, 0x78, 0xf5, 0x23, 0xca, 0x2a, 0xb0,
00151     0xaf, 0x3e, 0xfe, 0x04, 0x8c, 0xe7, 0xe5, 0x98, 0x32, 0x95, 0xd3, 0xf6, 0x4a, 0xe8, 0xa6, 0xea,
00152     0xe9, 0xf3, 0xd5, 0x2f, 0x70, 0x20, 0xf2, 0x1f, 0x05, 0x67, 0xad, 0x55, 0x10, 0xce, 0xcd, 0xe3,
00153     0x27, 0x3b, 0xda, 0xba, 0xd7, 0xc2, 0x26, 0xd4, 0x91, 0x1d, 0xd2, 0x1c, 0x22, 0x33, 0xf8, 0xfa,
00154     0xf1, 0x5a, 0xef, 0xcf, 0x90, 0xb6, 0x8b, 0xb5, 0xbd, 0xc0, 0xbf, 0x08, 0x97, 0x1e, 0x6c, 0xe2,
00155     0x61, 0xe0, 0xc6, 0xc1, 0x59, 0xab, 0xbb, 0x58, 0xde, 0x5f, 0xdf, 0x60, 0x79, 0x7e, 0xb2, 0x8a
00156 };
00157 
00158 int pst_open(pst_file *pf, char *name) {
00159     int32_t sig;
00160 
00161     unicode_init();
00162 
00163     DEBUG_ENT("pst_open");
00164 
00165     if (!pf) {
00166         WARN (("cannot be passed a NULL pst_file\n"));
00167         DEBUG_RET();
00168         return -1;
00169     }
00170     memset(pf, 0, sizeof(*pf));
00171 
00172     if ((pf->fp = fopen(name, "rb")) == NULL) {
00173         WARN(("cannot open PST file. Error\n"));
00174         DEBUG_RET();
00175         return -1;
00176     }
00177 
00178     // Check pst file magic
00179     if (pst_getAtPos(pf, 0, &sig, sizeof(sig)) != sizeof(sig)) {
00180         (void)fclose(pf->fp);
00181         WARN(("cannot read signature from PST file. Closing on error\n"));
00182         DEBUG_RET();
00183         return -1;
00184     }
00185     LE32_CPU(sig);
00186     DEBUG_INFO(("sig = %X\n", sig));
00187     if (sig != (int32_t)PST_SIGNATURE) {
00188         (void)fclose(pf->fp);
00189         WARN(("not a PST file that I know. Closing with error\n"));
00190         DEBUG_RET();
00191         return -1;
00192     }
00193 
00194     // read index type
00195     (void)pst_getAtPos(pf, INDEX_TYPE_OFFSET, &(pf->ind_type), sizeof(pf->ind_type));
00196     DEBUG_INFO(("index_type = %i\n", pf->ind_type));
00197     switch (pf->ind_type) {
00198         case INDEX_TYPE32 :
00199             pf->do_read64 = 0;
00200             break;
00201         case INDEX_TYPE64 :
00202             pf->do_read64 = 1;
00203             break;
00204         default:
00205             (void)fclose(pf->fp);
00206             WARN(("unknown .pst format, possibly newer than Outlook 2003 PST file?\n"));
00207             DEBUG_RET();
00208             return -1;
00209     }
00210 
00211     // read encryption setting
00212     (void)pst_getAtPos(pf, ENC_TYPE, &(pf->encryption), sizeof(pf->encryption));
00213     DEBUG_INFO(("encrypt = %i\n", pf->encryption));
00214 
00215     pf->index2_back  = pst_getIntAtPos(pf, SECOND_BACK);
00216     pf->index2       = pst_getIntAtPos(pf, SECOND_POINTER);
00217     pf->size         = pst_getIntAtPos(pf, FILE_SIZE_POINTER);
00218     DEBUG_INFO(("Pointer2 is %#"PRIx64", back pointer2 is %#"PRIx64"\n", pf->index2, pf->index2_back));
00219 
00220     pf->index1_back  = pst_getIntAtPos(pf, INDEX_BACK);
00221     pf->index1       = pst_getIntAtPos(pf, INDEX_POINTER);
00222     DEBUG_INFO(("Pointer1 is %#"PRIx64", back pointer2 is %#"PRIx64"\n", pf->index1, pf->index1_back));
00223 
00224     DEBUG_RET();
00225     return 0;
00226 }
00227 
00228 
00229 int pst_close(pst_file *pf) {
00230     DEBUG_ENT("pst_close");
00231     if (!pf->fp) {
00232         WARN(("cannot close NULL fp\n"));
00233         DEBUG_RET();
00234         return -1;
00235     }
00236     if (fclose(pf->fp)) {
00237         WARN(("fclose returned non-zero value\n"));
00238         DEBUG_RET();
00239         return -1;
00240     }
00241     // we must free the id linklist and the desc tree
00242     pst_free_id (pf->i_head);
00243     pst_free_desc (pf->d_head);
00244     pst_free_xattrib (pf->x_head);
00245     DEBUG_RET();
00246     return 0;
00247 }
00248 
00249 
00250 pst_desc_ll* pst_getTopOfFolders(pst_file *pf, pst_item *root) {
00251     pst_desc_ll *ret;
00252     DEBUG_ENT("pst_getTopOfFolders");
00253     if (!root || !root->message_store) {
00254         DEBUG_INDEX(("There isn't a top of folder record here.\n"));
00255         ret = NULL;
00256     } else if (!root->message_store->top_of_personal_folder) {
00257         // this is the OST way
00258         // ASSUMPTION: Top Of Folders record in PST files is *always* descid 0x2142
00259         ret = pst_getDptr(pf, (uint64_t)0x2142);
00260     } else {
00261         ret = pst_getDptr(pf, root->message_store->top_of_personal_folder->id);
00262     }
00263     DEBUG_RET();
00264     return ret;
00265 }
00266 
00267 
00268 size_t pst_attach_to_mem(pst_file *pf, pst_item_attach *attach, char **b){
00269     size_t size=0;
00270     pst_index_ll *ptr;
00271     pst_holder h = {b, NULL, 0, "", 0};
00272     DEBUG_ENT("pst_attach_to_mem");
00273     if (attach->id_val != (uint64_t)-1) {
00274         ptr = pst_getID(pf, attach->id_val);
00275         if (ptr) {
00276             size = pst_ff_getID2data(pf, ptr, &h);
00277         } else {
00278             DEBUG_WARN(("Couldn't find ID pointer. Cannot handle attachment\n"));
00279             size = 0;
00280         }
00281         attach->size = size; // may as well update it to what is correct for this instance
00282     } else {
00283         size = attach->size;
00284     }
00285     DEBUG_RET();
00286     return size;
00287 }
00288 
00289 
00290 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) {
00291     pst_index_ll *ptr;
00292     pst_holder h = {NULL, fp, 0, "", 0};
00293     size_t size;
00294     DEBUG_ENT("pst_attach_to_file");
00295     if (attach->id_val != (uint64_t)-1) {
00296         ptr = pst_getID(pf, attach->id_val);
00297         if (ptr) {
00298             size = pst_ff_getID2data(pf, ptr, &h);
00299         } else {
00300             DEBUG_WARN(("Couldn't find ID pointer. Cannot save attachment to file\n"));
00301             size = 0;
00302         }
00303         attach->size = size;
00304     } else {
00305         // save the attachment to file
00306         size = attach->size;
00307         (void)pst_fwrite(attach->data, (size_t)1, size, fp);
00308     }
00309     DEBUG_RET();
00310     return size;
00311 }
00312 
00313 
00314 size_t pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE* fp) {
00315     pst_index_ll *ptr;
00316     pst_holder h = {NULL, fp, 1, "", 0};
00317     size_t size;
00318     char *c;
00319     DEBUG_ENT("pst_attach_to_file_base64");
00320     if (attach->id_val != (uint64_t)-1) {
00321         ptr = pst_getID(pf, attach->id_val);
00322         if (ptr) {
00323             size = pst_ff_getID2data(pf, ptr, &h);
00324             // will need to encode any bytes left over
00325             c = base64_encode(h.base64_extra_chars, (size_t)h.base64_extra);
00326             if (c) {
00327                 (void)pst_fwrite(c, (size_t)1, strlen(c), fp);
00328                 free(c);    // caught by valgrind
00329             }
00330         } else {
00331             DEBUG_WARN (("Couldn't find ID pointer. Cannot save attachment to Base64\n"));
00332             size = 0;
00333         }
00334         attach->size = size;
00335     } else {
00336         // encode the attachment to the file
00337         c = base64_encode(attach->data, attach->size);
00338         if (c) {
00339             (void)pst_fwrite(c, (size_t)1, strlen(c), fp);
00340             free(c);    // caught by valgrind
00341         }
00342         size = attach->size;
00343     }
00344     DEBUG_RET();
00345     return size;
00346 }
00347 
00348 
00349 int pst_load_index (pst_file *pf) {
00350     int  x;
00351     uint64_t y;
00352     DEBUG_ENT("pst_load_index");
00353     if (!pf) {
00354         WARN(("Cannot load index for a NULL pst_file\n"));
00355         DEBUG_RET();
00356         return -1;
00357     }
00358 
00359     x = pst_build_id_ptr(pf, pf->index1, 0, pf->index1_back, 0, UINT64_MAX);
00360     DEBUG_INDEX(("build id ptr returns %i\n", x));
00361 
00362     y = 0;
00363     x = pst_build_desc_ptr(pf, pf->index2, 0, pf->index2_back, &y, (uint64_t)0x21, UINT64_MAX);
00364     DEBUG_INDEX(("build desc ptr returns %i\n", x));
00365 
00366     DEBUG_CODE((void)pst_printDptr(pf, pf->d_head););
00367     DEBUG_RET();
00368     return 0;
00369 }
00370 
00371 
00372 pst_desc_ll* pst_getNextDptr(pst_desc_ll* d) {
00373     pst_desc_ll* r = NULL;
00374     DEBUG_ENT("pst_getNextDptr");
00375     if (d) {
00376         if ((r = d->child) == NULL) {
00377             while (!d->next && d->parent) d = d->parent;
00378             r = d->next;
00379         }
00380     }
00381     DEBUG_RET();
00382     return r;
00383 }
00384 
00385 
00386 typedef struct pst_x_attrib {
00387     uint16_t extended;
00388     uint16_t zero;
00389     uint16_t type;
00390     uint16_t map;
00391 } pst_x_attrib;
00392 
00393 
00394 int pst_load_extended_attributes(pst_file *pf) {
00395     // for PST files this will load up ID2 0x61 and check it's "list" attribute.
00396     pst_desc_ll *p;
00397     pst_num_array *na;
00398     pst_index2_ll *id2_head = NULL;
00399     char *buffer=NULL, *headerbuffer=NULL;
00400     size_t bsize=0, hsize=0, bptr=0;
00401     pst_x_attrib xattrib;
00402     int32_t tint, err=0, x;
00403     pst_x_attrib_ll *ptr, *p_head=NULL, *p_sh=NULL, *p_sh2=NULL;
00404 
00405     DEBUG_ENT("pst_loadExtendedAttributes");
00406     p = pst_getDptr(pf, (uint64_t)0x61);
00407     if (!p) {
00408         DEBUG_WARN(("Cannot find DescID 0x61 for loading the Extended Attributes\n"));
00409         DEBUG_RET();
00410         return 0;
00411     }
00412 
00413     if (!p->desc) {
00414         DEBUG_WARN(("desc is NULL for item 0x61. Cannot load Extended Attributes\n"));
00415         DEBUG_RET();
00416         return 0;
00417     }
00418 
00419     if (p->list_index) {
00420         id2_head = pst_build_id2(pf, p->list_index, NULL);
00421         pst_printID2ptr(id2_head);
00422     } else {
00423         DEBUG_WARN(("Have not been able to fetch any id2 values for item 0x61. Brace yourself!\n"));
00424     }
00425 
00426     na = pst_parse_block(pf, p->desc->id, id2_head, NULL);
00427     if (!na) {
00428         DEBUG_WARN(("Cannot process desc block for item 0x61. Not loading extended Attributes\n"));
00429         if (id2_head) pst_free_id2(id2_head);
00430         DEBUG_RET();
00431         return 0;
00432     }
00433 
00434     x = 0;
00435     while (x < na->count_item) {
00436         if (na->items[x]->id == (uint32_t)0x0003) {
00437             buffer = na->items[x]->data;
00438             bsize = na->items[x]->size;
00439         } else if (na->items[x]->id == (uint32_t)0x0004) {
00440             headerbuffer = na->items[x]->data;
00441             hsize = na->items[x]->size;
00442         } else {
00443             // leave them null
00444         }
00445         x++;
00446     }
00447 
00448     if (!buffer) {
00449         if (na) pst_free_list(na);
00450         DEBUG_WARN(("No extended attributes buffer found. Not processing\n"));
00451         DEBUG_RET();
00452         return 0;
00453     }
00454 
00455     memcpy(&xattrib, &(buffer[bptr]), sizeof(xattrib));
00456     LE16_CPU(xattrib.extended);
00457     LE16_CPU(xattrib.zero);
00458     LE16_CPU(xattrib.type);
00459     LE16_CPU(xattrib.map);
00460     bptr += sizeof(xattrib);
00461 
00462     while (xattrib.type != 0 && bptr < bsize) {
00463         ptr = (pst_x_attrib_ll*) xmalloc(sizeof(*ptr));
00464         memset(ptr, 0, sizeof(*ptr));
00465         ptr->type = xattrib.type;
00466         ptr->map  = xattrib.map+0x8000;
00467         ptr->next = NULL;
00468         DEBUG_INDEX(("xattrib: ext = %#hx, zero = %#hx, type = %#hx, map = %#hx\n",
00469              xattrib.extended, xattrib.zero, xattrib.type, xattrib.map));
00470         err=0;
00471         if (xattrib.type & 0x0001) { // if the Bit 1 is set
00472             // pointer to Unicode field in buffer
00473             if (xattrib.extended < hsize) {
00474                 char *wt;
00475                 // copy the size of the header. It is 32 bit int
00476                 memcpy(&tint, &(headerbuffer[xattrib.extended]), sizeof(tint));
00477                 LE32_CPU(tint);
00478                 wt = (char*) xmalloc((size_t)(tint+2)); // plus 2 for a uni-code zero
00479                 memset(wt, 0, (size_t)(tint+2));
00480                 memcpy(wt, &(headerbuffer[xattrib.extended+sizeof(tint)]), (size_t)tint);
00481                 ptr->data = pst_wide_to_single(wt, (size_t)tint);
00482                 free(wt);
00483                 DEBUG_INDEX(("Read string (converted from UTF-16): %s\n", ptr->data));
00484             } else {
00485                 DEBUG_INDEX(("Cannot read outside of buffer [%i !< %i]\n", xattrib.extended, hsize));
00486             }
00487             ptr->mytype = PST_MAP_HEADER;
00488         } else {
00489             // contains the attribute code to map to.
00490             ptr->data = (uint32_t*)xmalloc(sizeof(uint32_t));
00491             memset(ptr->data, 0, sizeof(uint32_t));
00492             *((uint32_t*)ptr->data) = xattrib.extended;
00493             ptr->mytype = PST_MAP_ATTRIB;
00494             DEBUG_INDEX(("Mapped attribute %#x to %#x\n", ptr->map, *((int32_t*)ptr->data)));
00495         }
00496 
00497         if (err==0) {
00498             // add it to the list
00499             p_sh = p_head;
00500             p_sh2 = NULL;
00501             while (p_sh && ptr->map > p_sh->map) {
00502                 p_sh2 = p_sh;
00503                 p_sh = p_sh->next;
00504             }
00505             if (!p_sh2) {
00506                 // needs to go before first item
00507                 ptr->next = p_head;
00508                 p_head = ptr;
00509             } else {
00510                 // it will go after p_sh2
00511                 ptr->next = p_sh2->next;
00512                 p_sh2->next = ptr;
00513             }
00514         } else {
00515             free(ptr);
00516             ptr = NULL;
00517         }
00518         memcpy(&xattrib, &(buffer[bptr]), sizeof(xattrib));
00519         LE16_CPU(xattrib.extended);
00520         LE16_CPU(xattrib.zero);
00521         LE16_CPU(xattrib.type);
00522         LE16_CPU(xattrib.map);
00523         bptr += sizeof(xattrib);
00524     }
00525     if (id2_head) pst_free_id2(id2_head);
00526     if (na)       pst_free_list(na);
00527     pf->x_head = p_head;
00528     DEBUG_RET();
00529     return 1;
00530 }
00531 
00532 
00533 #define ITEM_COUNT_OFFSET32        0x1f0    // count byte
00534 #define LEVEL_INDICATOR_OFFSET32   0x1f3    // node or leaf
00535 #define BACKLINK_OFFSET32          0x1f8    // backlink u1 value
00536 #define ITEM_SIZE32                12
00537 #define DESC_SIZE32                16
00538 #define INDEX_COUNT_MAX32          41       // max active items
00539 #define DESC_COUNT_MAX32           31       // max active items
00540 
00541 #define ITEM_COUNT_OFFSET64        0x1e8    // count byte
00542 #define LEVEL_INDICATOR_OFFSET64   0x1eb    // node or leaf
00543 #define BACKLINK_OFFSET64          0x1f8    // backlink u1 value
00544 #define ITEM_SIZE64                24
00545 #define DESC_SIZE64                32
00546 #define INDEX_COUNT_MAX64          20       // max active items
00547 #define DESC_COUNT_MAX64           15       // max active items
00548 
00549 #define BLOCK_SIZE                 512      // index blocks
00550 #define DESC_BLOCK_SIZE            512      // descriptor blocks
00551 #define ITEM_COUNT_OFFSET        (size_t)((pf->do_read64) ? ITEM_COUNT_OFFSET64      : ITEM_COUNT_OFFSET32)
00552 #define LEVEL_INDICATOR_OFFSET   (size_t)((pf->do_read64) ? LEVEL_INDICATOR_OFFSET64 : LEVEL_INDICATOR_OFFSET32)
00553 #define BACKLINK_OFFSET          (size_t)((pf->do_read64) ? BACKLINK_OFFSET64        : BACKLINK_OFFSET32)
00554 #define ITEM_SIZE                (size_t)((pf->do_read64) ? ITEM_SIZE64              : ITEM_SIZE32)
00555 #define DESC_SIZE                (size_t)((pf->do_read64) ? DESC_SIZE64              : DESC_SIZE32)
00556 #define INDEX_COUNT_MAX         (int32_t)((pf->do_read64) ? INDEX_COUNT_MAX64        : INDEX_COUNT_MAX32)
00557 #define DESC_COUNT_MAX          (int32_t)((pf->do_read64) ? DESC_COUNT_MAX64         : DESC_COUNT_MAX32)
00558 
00559 
00560 static size_t pst_decode_desc(pst_file *pf, pst_descn *desc, char *buf);
00561 static size_t pst_decode_desc(pst_file *pf, pst_descn *desc, char *buf) {
00562     size_t r;
00563     if (pf->do_read64) {
00564         DEBUG_INDEX(("Decoding desc64\n"));
00565         DEBUG_HEXDUMPC(buf, sizeof(pst_descn), 0x10);
00566         memcpy(desc, buf, sizeof(pst_descn));
00567         LE64_CPU(desc->d_id);
00568         LE64_CPU(desc->desc_id);
00569         LE64_CPU(desc->list_id);
00570         LE32_CPU(desc->parent_id);
00571         LE32_CPU(desc->u1);
00572         r = sizeof(pst_descn);
00573     }
00574     else {
00575         pst_desc32 d32;
00576         DEBUG_INDEX(("Decoding desc32\n"));
00577         DEBUG_HEXDUMPC(buf, sizeof(pst_desc32), 0x10);
00578         memcpy(&d32, buf, sizeof(pst_desc32));
00579         LE32_CPU(d32.d_id);
00580         LE32_CPU(d32.desc_id);
00581         LE32_CPU(d32.list_id);
00582         LE32_CPU(d32.parent_id);
00583         desc->d_id      = d32.d_id;
00584         desc->desc_id   = d32.desc_id;
00585         desc->list_id   = d32.list_id;
00586         desc->parent_id = d32.parent_id;
00587         desc->u1        = 0;
00588         r = sizeof(pst_desc32);
00589     }
00590     return r;
00591 }
00592 
00593 
00594 static size_t pst_decode_table(pst_file *pf, struct pst_table_ptr_structn *table, char *buf);
00595 static size_t pst_decode_table(pst_file *pf, struct pst_table_ptr_structn *table, char *buf) {
00596     size_t r;
00597     if (pf->do_read64) {
00598         DEBUG_INDEX(("Decoding table64\n"));
00599         DEBUG_HEXDUMPC(buf, sizeof(struct pst_table_ptr_structn), 0x10);
00600         memcpy(table, buf, sizeof(struct pst_table_ptr_structn));
00601         LE64_CPU(table->start);
00602         LE64_CPU(table->u1);
00603         LE64_CPU(table->offset);
00604         r =sizeof(struct pst_table_ptr_structn);
00605     }
00606     else {
00607         struct pst_table_ptr_struct32 t32;
00608         DEBUG_INDEX(("Decoding table32\n"));
00609         DEBUG_HEXDUMPC(buf, sizeof( struct pst_table_ptr_struct32), 0x10);
00610         memcpy(&t32, buf, sizeof(struct pst_table_ptr_struct32));
00611         LE32_CPU(t32.start);
00612         LE32_CPU(t32.u1);
00613         LE32_CPU(t32.offset);
00614         table->start  = t32.start;
00615         table->u1     = t32.u1;
00616         table->offset = t32.offset;
00617         r = sizeof(struct pst_table_ptr_struct32);
00618     }
00619     return r;
00620 }
00621 
00622 
00623 static size_t pst_decode_index(pst_file *pf, pst_index *index, char *buf);
00624 static size_t pst_decode_index(pst_file *pf, pst_index *index, char *buf) {
00625     size_t r;
00626     if (pf->do_read64) {
00627         DEBUG_INDEX(("Decoding index64\n"));
00628         DEBUG_HEXDUMPC(buf, sizeof(pst_index), 0x10);
00629         memcpy(index, buf, sizeof(pst_index));
00630         LE64_CPU(index->id);
00631         LE64_CPU(index->offset);
00632         LE16_CPU(index->size);
00633         LE16_CPU(index->u0);
00634         LE16_CPU(index->u1);
00635         r = sizeof(pst_index);
00636     } else {
00637         pst_index32 index32;
00638         DEBUG_INDEX(("Decoding index32\n"));
00639         DEBUG_HEXDUMPC(buf, sizeof(pst_index32), 0x10);
00640         memcpy(&index32, buf, sizeof(pst_index32));
00641         LE32_CPU(index32.id);
00642         LE32_CPU(index32.offset);
00643         LE16_CPU(index32.size);
00644         LE16_CPU(index32.u1);
00645         index->id     = index32.id;
00646         index->offset = index32.offset;
00647         index->size   = index32.size;
00648         index->u1     = index32.u1;
00649         r = sizeof(pst_index32);
00650     }
00651     return r;
00652 }
00653 
00654 
00655 static size_t pst_decode_assoc(pst_file *pf, pst_id2_assoc *assoc, char *buf);
00656 static size_t pst_decode_assoc(pst_file *pf, pst_id2_assoc *assoc, char *buf) {
00657     size_t r;
00658     if (pf->do_read64) {
00659         DEBUG_INDEX(("Decoding assoc64\n"));
00660         DEBUG_HEXDUMPC(buf, sizeof(pst_id2_assoc), 0x10);
00661         memcpy(assoc, buf, sizeof(pst_id2_assoc));
00662         LE32_CPU(assoc->id2);
00663         LE64_CPU(assoc->id);
00664         LE64_CPU(assoc->table2);
00665         r = sizeof(pst_id2_assoc);
00666     } else {
00667         pst_id2_assoc32 assoc32;
00668         DEBUG_INDEX(("Decoding assoc32\n"));
00669         DEBUG_HEXDUMPC(buf, sizeof(pst_id2_assoc32), 0x10);
00670         memcpy(&assoc32, buf, sizeof(pst_id2_assoc32));
00671         LE32_CPU(assoc32.id2);
00672         LE32_CPU(assoc32.id);
00673         LE32_CPU(assoc32.table2);
00674         assoc->id2    = assoc32.id2;
00675         assoc->id     = assoc32.id;
00676         assoc->table2 = assoc32.table2;
00677         r = sizeof(pst_id2_assoc32);
00678     }
00679     return r;
00680 }
00681 
00682 
00683 static size_t pst_decode_type3(pst_file *pf, pst_table3_rec *table3_rec, char *buf);
00684 static size_t pst_decode_type3(pst_file *pf, pst_table3_rec *table3_rec, char *buf) {
00685     size_t r;
00686     if (pf->do_read64) {
00687         DEBUG_INDEX(("Decoding table3 64\n"));
00688         DEBUG_HEXDUMPC(buf, sizeof(pst_table3_rec), 0x10);
00689         memcpy(table3_rec, buf, sizeof(pst_table3_rec));
00690         LE64_CPU(table3_rec->id);
00691         r = sizeof(pst_table3_rec);
00692     } else {
00693         pst_table3_rec32 table3_rec32;
00694         DEBUG_INDEX(("Decoding table3 32\n"));
00695         DEBUG_HEXDUMPC(buf, sizeof(pst_table3_rec32), 0x10);
00696         memcpy(&table3_rec32, buf, sizeof(pst_table3_rec32));
00697         LE32_CPU(table3_rec32.id);
00698         table3_rec->id  = table3_rec32.id;
00699         r = sizeof(pst_table3_rec32);
00700     }
00701     return r;
00702 }
00703 
00704 
00705 int pst_build_id_ptr(pst_file *pf, off_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val) {
00706     struct pst_table_ptr_structn table, table2;
00707     pst_index_ll *i_ptr=NULL;
00708     pst_index index;
00709     int32_t x, item_count;
00710     uint64_t old = start_val;
00711     char *buf = NULL, *bptr;
00712 
00713     DEBUG_ENT("pst_build_id_ptr");
00714     DEBUG_INDEX(("offset %#"PRIx64" depth %i linku1 %#"PRIx64" start %#"PRIx64" end %#"PRIx64"\n", offset, depth, linku1, start_val, end_val));
00715     if (end_val <= start_val) {
00716         DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64", end:%#"PRIx64"]\n", start_val, end_val));
00717         DEBUG_RET();
00718         return -1;
00719     }
00720     DEBUG_INDEX(("Reading index block\n"));
00721     if (pst_read_block_size(pf, offset, BLOCK_SIZE, &buf) < BLOCK_SIZE) {
00722         DEBUG_WARN(("Failed to read %i bytes\n", BLOCK_SIZE));
00723         if (buf) free(buf);
00724         DEBUG_RET();
00725         return -1;
00726     }
00727     bptr = buf;
00728     DEBUG_HEXDUMPC(buf, BLOCK_SIZE, ITEM_SIZE32);
00729     item_count = (int32_t)(unsigned)(buf[ITEM_COUNT_OFFSET]);
00730     if (item_count > INDEX_COUNT_MAX) {
00731         DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, INDEX_COUNT_MAX));
00732         if (buf) free(buf);
00733         DEBUG_RET();
00734         return -1;
00735     }
00736     index.id = pst_getIntAt(pf, buf+BACKLINK_OFFSET);
00737     if (index.id != linku1) {
00738         DEBUG_WARN(("Backlink %#"PRIx64" in this node does not match required %#"PRIx64"\n", index.id, linku1));
00739         if (buf) free(buf);
00740         DEBUG_RET();
00741         return -1;
00742     }
00743 
00744     if (buf[LEVEL_INDICATOR_OFFSET] == '\0') {
00745         // this node contains leaf pointers
00746         x = 0;
00747         while (x < item_count) {
00748             bptr += pst_decode_index(pf, &index, bptr);
00749             x++;
00750             if (index.id == 0) break;
00751             DEBUG_INDEX(("[%i]%i Item [id = %#"PRIx64", offset = %#"PRIx64", u1 = %#x, size = %i(%#x)]\n",
00752                         depth, x, index.id, index.offset, index.u1, index.size, index.size));
00753             // if (index.id & 0x02) DEBUG_INDEX(("two-bit set!!\n"));
00754             if ((index.id >= end_val) || (index.id < old)) {
00755                 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n"));
00756                 if (buf) free(buf);
00757                 DEBUG_RET();
00758                 return -1;
00759             }
00760             old = index.id;
00761             if (x == (int32_t)1) {   // first entry
00762                 if ((start_val) && (index.id != start_val)) {
00763                     DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n"));
00764                     if (buf) free(buf);
00765                     DEBUG_RET();
00766                     return -1;
00767                 }
00768             }
00769             i_ptr = (pst_index_ll*) xmalloc(sizeof(pst_index_ll));
00770             i_ptr->id     = index.id;
00771             i_ptr->offset = index.offset;
00772             i_ptr->u1     = index.u1;
00773             i_ptr->size   = index.size;
00774             i_ptr->next   = NULL;
00775             if (pf->i_tail)  pf->i_tail->next = i_ptr;
00776             if (!pf->i_head) pf->i_head = i_ptr;
00777             pf->i_tail = i_ptr;
00778         }
00779     } else {
00780         // this node contains node pointers
00781         x = 0;
00782         while (x < item_count) {
00783             bptr += pst_decode_table(pf, &table, bptr);
00784             x++;
00785             if (table.start == 0) break;
00786             if (x < item_count) {
00787                 (void)pst_decode_table(pf, &table2, bptr);
00788             }
00789             else {
00790                 table2.start = end_val;
00791             }
00792             DEBUG_INDEX(("[%i] %i Index Table [start id = %#"PRIx64", u1 = %#"PRIx64", offset = %#"PRIx64", end id = %#"PRIx64"]\n",
00793                         depth, x, table.start, table.u1, table.offset, table2.start));
00794             if ((table.start >= end_val) || (table.start < old)) {
00795                 DEBUG_WARN(("This table isn't right. Must be corruption, or I got it wrong!\n"));
00796                 if (buf) free(buf);
00797                 DEBUG_RET();
00798                 return -1;
00799             }
00800             old = table.start;
00801             if (x == (int32_t)1) {  // first entry
00802                 if ((start_val) && (table.start != start_val)) {
00803                     DEBUG_WARN(("This table isn't right. Must be corruption, or I got it wrong!\n"));
00804                     if (buf) free(buf);
00805                     DEBUG_RET();
00806                     return -1;
00807                 }
00808             }
00809             (void)pst_build_id_ptr(pf, table.offset, depth+1, table.u1, table.start, table2.start);
00810         }
00811     }
00812     if (buf) free (buf);
00813     DEBUG_RET();
00814     return 0;
00815 }
00816 
00817 
00824 struct cache_list_node {
00825     pst_desc_ll *ptr;
00827     uint64_t parent;
00828     struct cache_list_node *next;
00829     struct cache_list_node *prev;
00830 };
00831 static struct cache_list_node *cache_head;
00832 static struct cache_list_node *cache_tail;
00833 static struct cache_list_node *lostfound_head;
00834 static int cache_count;
00835 
00836 
00840 static void record_descriptor(pst_file *pf, pst_desc_ll *d_ptr, uint64_t parent_id);
00841 static void record_descriptor(pst_file *pf, pst_desc_ll *d_ptr, uint64_t parent_id) {
00842     struct cache_list_node *lostfound_ptr = NULL;
00843     struct cache_list_node *cache_ptr     = NULL;
00844     pst_desc_ll            *parent        = NULL;
00845 
00846     if (parent_id == 0 || parent_id == d_ptr->id) {
00847         // add top level node to the descriptor tree
00848         if (parent_id == 0) {
00849             DEBUG_INDEX(("No Parent\n"));
00850         } else {
00851             DEBUG_INDEX(("Record is its own parent. What is this world coming to?\n"));
00852         }
00853         if (pf->d_tail)  pf->d_tail->next = d_ptr;
00854         if (!pf->d_head) pf->d_head = d_ptr;
00855         d_ptr->prev = pf->d_tail;
00856         pf->d_tail  = d_ptr;
00857     } else {
00858         DEBUG_INDEX(("Searching for parent\n"));
00859         // check in the cache for the parent
00860         cache_ptr = cache_head;
00861         while (cache_ptr && (cache_ptr->ptr->id != parent_id)) {
00862             cache_ptr = cache_ptr->next;
00863         }
00864         if (!cache_ptr && (parent = pst_getDptr(pf, parent_id)) == NULL) {
00865             // check in the lost/found list
00866             lostfound_ptr = lostfound_head;
00867             while (lostfound_ptr && (lostfound_ptr->ptr->id != parent_id)) {
00868                 lostfound_ptr = lostfound_ptr->next;
00869             }
00870             if (!lostfound_ptr) {
00871                 DEBUG_WARN(("ERROR -- cannot find parent with id %#"PRIx64". Adding to lost/found\n", parent_id));
00872                 lostfound_ptr = (struct cache_list_node*) xmalloc(sizeof(struct cache_list_node));
00873                 lostfound_ptr->prev   = NULL;
00874                 lostfound_ptr->next   = lostfound_head;
00875                 lostfound_ptr->parent = parent_id;
00876                 lostfound_ptr->ptr    = d_ptr;
00877                 lostfound_head = lostfound_ptr;
00878             } else {
00879                 parent = lostfound_ptr->ptr;
00880                 DEBUG_INDEX(("Found parent (%#"PRIx64") in Lost and Found\n", parent->id));
00881             }
00882         }
00883 
00884         if (cache_ptr || parent) {
00885             if (cache_ptr)
00886                 // parent is already in the cache
00887                 parent = cache_ptr->ptr;
00888             else {
00889                 //add the parent to the cache
00890                 DEBUG_INDEX(("Cache addition\n"));
00891                 cache_ptr = (struct cache_list_node*) xmalloc(sizeof(struct cache_list_node));
00892                 cache_ptr->prev = NULL;
00893                 cache_ptr->next = cache_head;
00894                 cache_ptr->ptr  = parent;
00895                 if (cache_head)  cache_head->prev = cache_ptr;
00896                 if (!cache_tail) cache_tail = cache_ptr;
00897                 cache_head = cache_ptr;
00898                 cache_count++;
00899                 if (cache_count > 100) {
00900                     DEBUG_INDEX(("trimming quick cache\n"));
00901                     //remove one from the end
00902                     cache_ptr  = cache_tail;
00903                     cache_tail = cache_ptr->prev;
00904                     if (cache_tail) cache_tail->next = NULL;
00905                     free (cache_ptr);
00906                     cache_count--;
00907                 }
00908             }
00909             DEBUG_INDEX(("Found a parent\n"));
00910             parent->no_child++;
00911             d_ptr->parent = parent;
00912             if (parent->child_tail)  parent->child_tail->next = d_ptr;
00913             if (!parent->child)      parent->child = d_ptr;
00914             d_ptr->prev = parent->child_tail;
00915             parent->child_tail = d_ptr;
00916         }
00917     }
00918 }
00919 
00920 int pst_build_desc_ptr (pst_file *pf, off_t offset, int32_t depth, uint64_t linku1, uint64_t *high_id, uint64_t start_val, uint64_t end_val) {
00921     struct pst_table_ptr_structn table, table2;
00922     pst_descn desc_rec;
00923     pst_desc_ll *d_ptr=NULL, *parent=NULL;
00924     int32_t x, item_count;
00925     uint64_t old = start_val;
00926     char *buf = NULL, *bptr;
00927     struct cache_list_node *cache_ptr = NULL;
00928     struct cache_list_node *lostfound_ptr = NULL;
00929     struct cache_list_node *lostfound_shd = NULL;
00930     struct cache_list_node *lostfound_tmp = NULL;
00931 
00932     if (depth == 0) {
00933         // initialize the linked list and lost/found list.
00934         cache_head     = NULL;
00935         cache_tail     = NULL;
00936         lostfound_head = NULL;
00937         cache_count    = 0;
00938     }
00939 
00940     DEBUG_ENT("pst_build_desc_ptr");
00941     DEBUG_INDEX(("offset %#"PRIx64" depth %i linku1 %#"PRIx64" start %#"PRIx64" end %#"PRIx64"\n", offset, depth, linku1, start_val, end_val));
00942     if (end_val <= start_val) {
00943         DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64", end:%#"PRIx64"]\n", start_val, end_val));
00944         DEBUG_RET();
00945         return -1;
00946     }
00947     DEBUG_INDEX(("Reading desc block\n"));
00948     if (pst_read_block_size(pf, offset, DESC_BLOCK_SIZE, &buf) < DESC_BLOCK_SIZE) {
00949         DEBUG_WARN(("Failed to read %i bytes\n", DESC_BLOCK_SIZE));
00950         if (buf) free(buf);
00951         DEBUG_RET();
00952         return -1;
00953     }
00954     bptr = buf;
00955     item_count = (int32_t)(unsigned)(buf[ITEM_COUNT_OFFSET]);
00956 
00957     desc_rec.d_id = pst_getIntAt(pf, buf+BACKLINK_OFFSET);
00958     if (desc_rec.d_id != linku1) {
00959         DEBUG_WARN(("Backlink %#"PRIx64" in this node does not match required %#"PRIx64"\n", desc_rec.d_id, linku1));
00960         if (buf) free(buf);
00961         DEBUG_RET();
00962         return -1;
00963     }
00964     if (buf[LEVEL_INDICATOR_OFFSET] == '\0') {
00965         // this node contains leaf pointers
00966         DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, DESC_SIZE32);
00967         if (item_count > DESC_COUNT_MAX) {
00968             DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, DESC_COUNT_MAX));
00969             if (buf) free(buf);
00970             DEBUG_RET();
00971             return -1;
00972         }
00973         x = 0;
00974         while (x < item_count) {
00975             bptr += pst_decode_desc(pf, &desc_rec, bptr);
00976             x++;
00977             if (desc_rec.d_id == 0) break;
00978             DEBUG_INDEX(("[%i] Item(%#x) = [d_id = %#"PRIx64", desc_id = %#"PRIx64", list_id = %#"PRIx64", parent_id = %#x]\n",
00979                         depth, x, desc_rec.d_id, desc_rec.desc_id, desc_rec.list_id, desc_rec.parent_id));
00980             if ((desc_rec.d_id >= end_val) || (desc_rec.d_id < old)) {
00981                 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n"));
00982                 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, 16);
00983                 if (buf) free(buf);
00984                 DEBUG_RET();
00985                 return -1;
00986             }
00987             old = desc_rec.d_id;
00988             if (x == (int32_t)1) {   // first entry
00989                 if (start_val && (desc_rec.d_id != start_val)) {
00990                     DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n"));
00991                     if (buf) free(buf);
00992                     DEBUG_RET();
00993                     return -1;
00994                 }
00995             }
00996             // When duplicates found, just update the info.... perhaps this is correct functionality
00997             DEBUG_INDEX(("Searching for existing record\n"));
00998             if (desc_rec.d_id <= *high_id && (d_ptr = pst_getDptr(pf, desc_rec.d_id))) {
00999                 uint64_t bigzero = 0;
01000                 DEBUG_INDEX(("Updating Existing Values\n"));
01001                 d_ptr->list_index = pst_getID(pf, desc_rec.list_id);
01002                 d_ptr->desc = pst_getID(pf, desc_rec.desc_id);
01003                 DEBUG_INDEX(("\tdesc = %#"PRIx64"\tlist_index=%#"PRIx64"\n",
01004                         (d_ptr->desc==NULL       ? bigzero : d_ptr->desc->id),
01005                         (d_ptr->list_index==NULL ? bigzero : d_ptr->list_index->id)));
01006                 if (d_ptr->parent && desc_rec.parent_id != d_ptr->parent->id) {
01007                     DEBUG_INDEX(("WARNING -- Parent of record has changed. Moving it\n"));
01008                     //hmmm, we must move the record.
01009                     // first we must remove from current location
01010                     //   change previous record to point next to our next
01011                     //     if no previous, then use parent's child
01012                     //     if no parent then change pf->d_head;
01013                     //   change next's prev to our prev
01014                     //     if no next then change parent's child_tail
01015                     //     if no parent then change pf->d_tail
01016                     if (d_ptr->prev)
01017                         d_ptr->prev->next = d_ptr->next;
01018                     else if (d_ptr->parent)
01019                         d_ptr->parent->child = d_ptr->next;
01020                     else
01021                         pf->d_head = d_ptr->next;
01022 
01023                     if (d_ptr->next)
01024                         d_ptr->next->prev = d_ptr->prev;
01025                     else if (d_ptr->parent)
01026                         d_ptr->parent->child_tail = d_ptr->prev;
01027                     else
01028                         pf->d_tail = d_ptr->prev;
01029 
01030                     d_ptr->prev   = NULL;
01031                     d_ptr->next   = NULL;
01032                     d_ptr->parent = NULL;
01033                     record_descriptor(pf, d_ptr, desc_rec.parent_id);   // add to the global tree
01034                 }
01035             } else {
01036                 if (*high_id < desc_rec.d_id) {
01037                     DEBUG_INDEX(("Updating New High\n"));
01038                     *high_id = desc_rec.d_id;
01039                 }
01040                 DEBUG_INDEX(("New Record\n"));
01041                 d_ptr             = (pst_desc_ll*) xmalloc(sizeof(pst_desc_ll));
01042                 d_ptr->id         = desc_rec.d_id;
01043                 d_ptr->list_index = pst_getID(pf, desc_rec.list_id);
01044                 d_ptr->desc       = pst_getID(pf, desc_rec.desc_id);
01045                 d_ptr->prev       = NULL;
01046                 d_ptr->next       = NULL;
01047                 d_ptr->parent     = NULL;
01048                 d_ptr->child      = NULL;
01049                 d_ptr->child_tail = NULL;
01050                 d_ptr->no_child   = 0;
01051                 record_descriptor(pf, d_ptr, desc_rec.parent_id);   // add to the global tree
01052 
01053             }
01054             // check here to see if d_ptr is the parent of any of the items in the lost / found list
01055             lostfound_ptr = lostfound_head;
01056             lostfound_shd = NULL;
01057             while (lostfound_ptr) {
01058                 if (lostfound_ptr->parent == d_ptr->id) {
01059                     DEBUG_INDEX(("Found a child  (%#"PRIx64") of the current record. Joining to main structure.\n", lostfound_ptr->ptr->id));
01060                     parent = d_ptr;
01061                     d_ptr = lostfound_ptr->ptr;
01062                     parent->no_child++;
01063                     d_ptr->parent = parent;
01064                     if (parent->child_tail) parent->child_tail->next = d_ptr;
01065                     if (!parent->child)     parent->child = d_ptr;
01066                     d_ptr->prev = parent->child_tail;
01067                     parent->child_tail = d_ptr;
01068                     if (!lostfound_shd) lostfound_head      = lostfound_ptr->next;
01069                     else                lostfound_shd->next = lostfound_ptr->next;
01070                     lostfound_tmp = lostfound_ptr->next;
01071                     free(lostfound_ptr);
01072                     lostfound_ptr = lostfound_tmp;
01073                 } else {
01074                     lostfound_shd = lostfound_ptr;
01075                     lostfound_ptr = lostfound_ptr->next;
01076                 }
01077             }
01078         }
01079     } else {
01080         // this node contains node pointers
01081         DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, ITEM_SIZE32);
01082         if (item_count > INDEX_COUNT_MAX) {
01083             DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, INDEX_COUNT_MAX));
01084             if (buf) free(buf);
01085             DEBUG_RET();
01086             return -1;
01087         }
01088         x = 0;
01089         while (x < item_count) {
01090             bptr += pst_decode_table(pf, &table, bptr);
01091             x++;
01092             if (table.start == 0) break;
01093             if (x < item_count) {
01094                 (void)pst_decode_table(pf, &table2, bptr);
01095             }
01096             else {
01097                 table2.start = end_val;
01098             }
01099             DEBUG_INDEX(("[%i] %i Descriptor Table [start id = %#"PRIx64", u1 = %#"PRIx64", offset = %#"PRIx64", end id = %#"PRIx64"]\n",
01100                         depth, x, table.start, table.u1, table.offset, table2.start));
01101             if ((table.start >= end_val) || (table.start < old)) {
01102                 DEBUG_WARN(("This table isn't right. Must be corruption, or I got it wrong!\n"));
01103                 if (buf) free(buf);
01104                 DEBUG_RET();
01105                 return -1;
01106             }
01107             old = table.start;
01108             if (x == (int32_t)1) {   // first entry
01109                 if (start_val && (table.start != start_val)) {
01110                     DEBUG_WARN(("This table isn't right. Must be corruption, or I got it wrong!\n"));
01111                     if (buf) free(buf);
01112                     DEBUG_RET();
01113                     return -1;
01114                 }
01115             }
01116             (void)pst_build_desc_ptr(pf, table.offset, depth+1, table.u1, high_id, table.start, table2.start);
01117         }
01118     }
01119     if (depth == 0) {
01120         // free the quick cache
01121         while (cache_head) {
01122             cache_ptr = cache_head->next;
01123             free(cache_head);
01124             cache_head = cache_ptr;
01125         }
01126         // free the lost and found
01127         while (lostfound_head) {
01128             lostfound_ptr = lostfound_head->next;
01129             WARN(("unused lost/found item with parent %#"PRIx64"))", lostfound_head->parent));
01130             free(lostfound_head);
01131             lostfound_head = lostfound_ptr;
01132         }
01133     }
01134     if (buf) free(buf);
01135     DEBUG_RET();
01136     return 0;
01137 }
01138 
01139 
01140 pst_item* pst_parse_item(pst_file *pf, pst_desc_ll *d_ptr) {
01141     pst_num_array * list;
01142     pst_index2_ll *id2_head = NULL;
01143     pst_index_ll *id_ptr = NULL;
01144     pst_item *item = NULL;
01145     pst_item_attach *attach = NULL;
01146     int32_t x;
01147     DEBUG_ENT("pst_parse_item");
01148     if (!d_ptr) {
01149         DEBUG_WARN(("you cannot pass me a NULL! I don't want it!\n"));
01150         DEBUG_RET();
01151         return NULL;
01152     }
01153 
01154     if (!d_ptr->desc) {
01155         DEBUG_WARN(("why is d_ptr->desc == NULL? I don't want to do anything else with this record\n"));
01156         DEBUG_RET();
01157         return NULL;
01158     }
01159 
01160     if (d_ptr->list_index) {
01161         id2_head = pst_build_id2(pf, d_ptr->list_index, NULL);
01162         (void)pst_printID2ptr(id2_head);
01163     } else {
01164         DEBUG_WARN(("Have not been able to fetch any id2 values for this item. Brace yourself!\n"));
01165     }
01166 
01167     list = pst_parse_block(pf, d_ptr->desc->id, id2_head, NULL);
01168     if (!list) {
01169         DEBUG_WARN(("pst_parse_block() returned an error for d_ptr->desc->id [%#"PRIx64"]\n", d_ptr->desc->id));
01170         if (id2_head) pst_free_id2(id2_head);
01171         DEBUG_RET();
01172         return NULL;
01173     }
01174 
01175     item = (pst_item*) xmalloc(sizeof(pst_item));
01176     memset(item, 0, sizeof(pst_item));
01177 
01178     if (pst_process(list, item, NULL)) {
01179         DEBUG_WARN(("pst_process() returned non-zero value. That is an error\n"));
01180         if (item)     pst_freeItem(item);
01181         if (list)     pst_free_list(list);
01182         if (id2_head) pst_free_id2(id2_head);
01183         DEBUG_RET();
01184         return NULL;
01185     }
01186     if (list) pst_free_list(list);
01187     list = NULL; //pst_process will free the items in the list
01188 
01189     if ((id_ptr = pst_getID2(id2_head, (uint64_t)0x671))) {
01190         // attachments exist - so we will process them
01191         while (item->attach) {
01192             attach = item->attach->next;
01193             free(item->attach);
01194             item->attach = attach;
01195         }
01196 
01197         DEBUG_EMAIL(("ATTACHMENT processing attachment\n"));
01198         if ((list = pst_parse_block(pf, id_ptr->id, id2_head, NULL)) == NULL) {
01199             DEBUG_WARN(("ERROR error processing main attachment record\n"));
01200             //if (item) pst_freeItem(item);
01201             if (id2_head) pst_free_id2(id2_head);
01202             DEBUG_RET();
01203             //return NULL;
01204             return item;
01205         }
01206         else {
01207             x = 0;
01208             while (x < list->count_array) {
01209                 attach = (pst_item_attach*) xmalloc (sizeof(pst_item_attach));
01210                 memset (attach, 0, sizeof(pst_item_attach));
01211                 attach->next = item->attach;
01212                 item->attach = attach;
01213                 x++;
01214             }
01215 
01216             if (pst_process(list, item, item->attach)) {
01217                 DEBUG_WARN(("ERROR pst_process() failed with attachments\n"));
01218                 if (item)     pst_freeItem(item);
01219                 if (list)     pst_free_list(list);
01220                 if (id2_head) pst_free_id2(id2_head);
01221                 DEBUG_RET();
01222                 return NULL;
01223             }
01224             if (list) pst_free_list(list);
01225             list = NULL;
01226 
01227             // now we will have initial information of each attachment stored in item->attach...
01228             // we must now read the secondary record for each based on the id2 val associated with
01229             // each attachment
01230             attach = item->attach;
01231             while (attach) {
01232               if ((id_ptr = pst_getID2(id2_head, attach->id2_val))) {
01233                   // id_ptr is a record describing the attachment
01234                   // we pass NULL instead of id2_head cause we don't want it to
01235                   // load all the extra stuff here.
01236                   if ((list = pst_parse_block(pf, id_ptr->id, NULL, NULL)) == NULL) {
01237                       DEBUG_WARN(("ERROR error processing an attachment record\n"));
01238                       attach = attach->next;
01239                       continue;
01240                   }
01241                   if (pst_process(list, item, attach)) {
01242                       DEBUG_WARN(("ERROR pst_process() failed with an attachment\n"));
01243                       if (list) pst_free_list(list);
01244                       list = NULL;
01245                       attach = attach->next;
01246                       continue;
01247                   }
01248                   if (list) pst_free_list(list);
01249                   list = NULL;
01250                   id_ptr = pst_getID2(id2_head, attach->id2_val);
01251                   if (id_ptr) {
01252                       // id2_val has been updated to the ID2 value of the datablock containing the
01253                       // attachment data
01254                       attach->id_val = id_ptr->id;
01255                   } else {
01256                       DEBUG_WARN(("have not located the correct value for the attachment [%#"PRIx64"]\n", attach->id2_val));
01257                   }
01258               } else {
01259                   DEBUG_WARN(("ERROR cannot locate id2 value %#"PRIx64"\n", attach->id2_val));
01260               }
01261               attach = attach->next;
01262             }
01263         }
01264     }
01265 
01266     if (id2_head) pst_free_id2(id2_head);
01267     DEBUG_RET();
01268     return item;
01269 }
01270 
01271 
01272 static void freeall(pst_subblocks *subs, pst_block_offset_pointer *p1,
01273                                          pst_block_offset_pointer *p2,
01274                                          pst_block_offset_pointer *p3,
01275                                          pst_block_offset_pointer *p4,
01276                                          pst_block_offset_pointer *p5,
01277                                          pst_block_offset_pointer *p6,
01278                                          pst_block_offset_pointer *p7);
01279 static void freeall(pst_subblocks *subs, pst_block_offset_pointer *p1,
01280                                          pst_block_offset_pointer *p2,
01281                                          pst_block_offset_pointer *p3,
01282                                          pst_block_offset_pointer *p4,
01283                                          pst_block_offset_pointer *p5,
01284                                          pst_block_offset_pointer *p6,
01285                                          pst_block_offset_pointer *p7) {
01286     size_t i;
01287     for (i=0; i<subs->subblock_count; i++) {
01288         if (subs->subs[i].buf) free(subs->subs[i].buf);
01289     }
01290     free(subs->subs);
01291     if (p1->needfree) free(p1->from);
01292     if (p2->needfree) free(p2->from);
01293     if (p3->needfree) free(p3->from);
01294     if (p4->needfree) free(p4->from);
01295     if (p5->needfree) free(p5->from);
01296     if (p6->needfree) free(p6->from);
01297     if (p7->needfree) free(p7->from);
01298 }
01299 
01300 
01301 pst_num_array * pst_parse_block(pst_file *pf, uint64_t block_id, pst_index2_ll *i2_head, pst_num_array *na_head) {
01302     char  *buf       = NULL;
01303     size_t read_size = 0;
01304     pst_subblocks  subblocks;
01305     pst_num_array *na_ptr = NULL;
01306     pst_block_offset_pointer block_offset1;
01307     pst_block_offset_pointer block_offset2;
01308     pst_block_offset_pointer block_offset3;
01309     pst_block_offset_pointer block_offset4;
01310     pst_block_offset_pointer block_offset5;
01311     pst_block_offset_pointer block_offset6;
01312     pst_block_offset_pointer block_offset7;
01313     int32_t  x;
01314     int      num_recs;
01315     int      count_rec;
01316     int32_t  num_list;
01317     int32_t  cur_list;
01318     int      block_type;
01319     uint32_t rec_size = 0;
01320     char*    list_start;
01321     char*    fr_ptr;
01322     char*    to_ptr;
01323     char*    ind2_end = NULL;
01324     char*    ind2_ptr = NULL;
01325     pst_x_attrib_ll *mapptr;
01326     pst_block_hdr    block_hdr;
01327     pst_table3_rec   table3_rec;  //for type 3 (0x0101) blocks
01328 
01329     struct {
01330         unsigned char seven_c;
01331         unsigned char item_count;
01332         uint16_t u1;
01333         uint16_t u2;
01334         uint16_t u3;
01335         uint16_t rec_size;
01336         uint32_t b_five_offset;
01337         uint32_t ind2_offset;
01338         uint16_t u7;
01339         uint16_t u8;
01340     } seven_c_blk;
01341 
01342     struct _type_d_rec {
01343         uint32_t id;
01344         uint32_t u1;
01345     } * type_d_rec;
01346 
01347     struct {
01348         uint16_t type;
01349         uint16_t ref_type;
01350         uint32_t value;
01351     } table_rec;    //for type 1 (0xBCEC) blocks
01352 
01353     struct {
01354         uint16_t ref_type;
01355         uint16_t type;
01356         uint16_t ind2_off;
01357         uint8_t  size;
01358         uint8_t  slot;
01359     } table2_rec;   //for type 2 (0x7CEC) blocks
01360 
01361     DEBUG_ENT("pst_parse_block");
01362     if ((read_size = pst_ff_getIDblock_dec(pf, block_id, &buf)) == 0) {
01363         WARN(("Error reading block id %#"PRIx64"\n", block_id));
01364         if (buf) free (buf);
01365         DEBUG_RET();
01366         return NULL;
01367     }
01368 
01369     block_offset1.needfree = 0;
01370     block_offset2.needfree = 0;
01371     block_offset3.needfree = 0;
01372     block_offset4.needfree = 0;
01373     block_offset5.needfree = 0;
01374     block_offset6.needfree = 0;
01375     block_offset7.needfree = 0;
01376 
01377     memcpy(&block_hdr, buf, sizeof(block_hdr));
01378     LE16_CPU(block_hdr.index_offset);
01379     LE16_CPU(block_hdr.type);
01380     LE32_CPU(block_hdr.offset);
01381     DEBUG_EMAIL(("block header (index_offset=%#hx, type=%#hx, offset=%#hx)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
01382 
01383     if (block_hdr.index_offset == (uint16_t)0x0101) { //type 3
01384         size_t i;
01385         char *b_ptr = buf + 8;
01386         subblocks.subblock_count = block_hdr.type;
01387         subblocks.subs = malloc(sizeof(pst_subblock) * subblocks.subblock_count);
01388         for (i=0; i<subblocks.subblock_count; i++) {
01389             b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
01390             subblocks.subs[i].buf       = NULL;
01391             subblocks.subs[i].read_size = pst_ff_getIDblock_dec(pf, table3_rec.id, &subblocks.subs[i].buf);
01392             if (subblocks.subs[i].buf) {
01393                 memcpy(&block_hdr, subblocks.subs[i].buf, sizeof(block_hdr));
01394                 LE16_CPU(block_hdr.index_offset);
01395                 subblocks.subs[i].i_offset = block_hdr.index_offset;
01396             }
01397             else {
01398                 subblocks.subs[i].read_size = 0;
01399                 subblocks.subs[i].i_offset  = 0;
01400             }
01401         }
01402         free(buf);
01403         memcpy(&block_hdr, subblocks.subs[0].buf, sizeof(block_hdr));
01404         LE16_CPU(block_hdr.index_offset);
01405         LE16_CPU(block_hdr.type);
01406         LE32_CPU(block_hdr.offset);
01407         DEBUG_EMAIL(("block header (index_offset=%#hx, type=%#hx, offset=%#hx)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
01408     }
01409     else {
01410         // setup the subblock descriptors, but we only have one block
01411         subblocks.subblock_count = (size_t)1;
01412         subblocks.subs = malloc(sizeof(pst_subblock));
01413         subblocks.subs[0].buf       = buf;
01414         subblocks.subs[0].read_size = read_size;
01415         subblocks.subs[0].i_offset  = block_hdr.index_offset;
01416     }
01417 
01418     if (block_hdr.type == (uint16_t)0xBCEC) { //type 1
01419         block_type = 1;
01420 
01421         if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, block_hdr.offset, &block_offset1)) {
01422             DEBUG_WARN(("internal error (bc.b5 offset %#x) in reading block id %#x\n", block_hdr.offset, block_id));
01423             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01424             DEBUG_RET();
01425             return NULL;
01426         }
01427         memcpy(&table_rec, block_offset1.from, sizeof(table_rec));
01428         LE16_CPU(table_rec.type);
01429         LE16_CPU(table_rec.ref_type);
01430         LE32_CPU(table_rec.value);
01431         DEBUG_EMAIL(("table_rec (type=%#hx, ref_type=%#hx, value=%#x)\n", table_rec.type, table_rec.ref_type, table_rec.value));
01432 
01433         if ((table_rec.type != (uint16_t)0x02B5) || (table_rec.ref_type != 6)) {
01434             WARN(("Unknown second block constant - %#hx %#hx for id %#"PRIx64"\n", table_rec.type, table_rec.ref_type, block_id));
01435             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01436             DEBUG_RET();
01437             return NULL;
01438         }
01439 
01440         if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset2)) {
01441             DEBUG_WARN(("internal error (bc.b5.desc offset) in reading block id %#x\n", table_rec.value, block_id));
01442             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01443             DEBUG_RET();
01444             return NULL;
01445         }
01446         list_start = block_offset2.from;
01447         to_ptr     = block_offset2.to;
01448         num_list = (to_ptr - list_start)/sizeof(table_rec);
01449         num_recs = 1; // only going to be one object in these blocks
01450     }
01451     else if (block_hdr.type == (uint16_t)0x7CEC) { //type 2
01452         block_type = 2;
01453 
01454         if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, block_hdr.offset, &block_offset3)) {
01455             DEBUG_WARN(("internal error (7c.7c offset %#x) in reading block id %#x\n", block_hdr.offset, block_id));
01456             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01457             DEBUG_RET();
01458             return NULL;
01459         }
01460         fr_ptr = block_offset3.from; //now got pointer to "7C block"
01461         memset(&seven_c_blk, 0, sizeof(seven_c_blk));
01462         memcpy(&seven_c_blk, fr_ptr, sizeof(seven_c_blk));
01463         LE16_CPU(seven_c_blk.u1);
01464         LE16_CPU(seven_c_blk.u2);
01465         LE16_CPU(seven_c_blk.u3);
01466         LE16_CPU(seven_c_blk.rec_size);
01467         LE32_CPU(seven_c_blk.b_five_offset);
01468         LE32_CPU(seven_c_blk.ind2_offset);
01469         LE16_CPU(seven_c_blk.u7);
01470         LE16_CPU(seven_c_blk.u8);
01471 
01472         list_start = fr_ptr + sizeof(seven_c_blk); // the list of item numbers start after this record
01473 
01474         if (seven_c_blk.seven_c != 0x7C) { // this would mean it isn't a 7C block!
01475             WARN(("Error. There isn't a 7C where I want to see 7C!\n"));
01476             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01477             DEBUG_RET();
01478             return NULL;
01479         }
01480 
01481         rec_size = seven_c_blk.rec_size;
01482         num_list = (int32_t)(unsigned)seven_c_blk.item_count;
01483 
01484         if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, seven_c_blk.b_five_offset, &block_offset4)) {
01485             DEBUG_WARN(("internal error (7c.b5 offset %#x) in reading block id %#x\n", seven_c_blk.b_five_offset, block_id));
01486             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01487             DEBUG_RET();
01488             return NULL;
01489         }
01490         memcpy(&table_rec, block_offset4.from, sizeof(table_rec));
01491         LE16_CPU(table_rec.type);
01492         LE16_CPU(table_rec.ref_type);
01493         LE32_CPU(table_rec.value);
01494         DEBUG_EMAIL(("table_rec (type=%#hx, ref_type=%#hx, value=%#x)\n", table_rec.type, table_rec.ref_type, table_rec.value));
01495 
01496         if (table_rec.type != (uint16_t)0x04B5) { // different constant than a type 1 record
01497             WARN(("Unknown second block constant - %#hx for id %#"PRIx64"\n", table_rec.type, block_id));
01498             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01499             DEBUG_RET();
01500             return NULL;
01501         }
01502 
01503         if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset5)) {
01504             DEBUG_WARN(("internal error (7c.b5.desc offset %#x) in reading block id %#"PRIx64"\n", table_rec.value, block_id));
01505             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01506             DEBUG_RET();
01507             return NULL;
01508         }
01509 
01510         // this will give the number of records in this block
01511         num_recs = (block_offset5.to - block_offset5.from) / (4 + table_rec.ref_type);
01512 
01513         if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, seven_c_blk.ind2_offset, &block_offset6)) {
01514             DEBUG_WARN(("internal error (7c.ind2 offset %#x) in reading block id %#x\n", seven_c_blk.ind2_offset, block_id));
01515             freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01516             DEBUG_RET();
01517             return NULL;
01518         }
01519         ind2_ptr = block_offset6.from;
01520         ind2_end = block_offset6.to;
01521     }
01522     else {
01523         WARN(("ERROR: Unknown block constant - %#hx for id %#"PRIx64"\n", block_hdr.type, block_id));
01524         freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01525         DEBUG_RET();
01526         return NULL;
01527     }
01528 
01529     DEBUG_EMAIL(("Mallocing number of records %i\n", num_recs));
01530     for (count_rec=0; count_rec<num_recs; count_rec++) {
01531         na_ptr = (pst_num_array*) xmalloc(sizeof(pst_num_array));
01532         memset(na_ptr, 0, sizeof(pst_num_array));
01533         na_ptr->next = na_head;
01534         na_head = na_ptr;
01535         // allocate an array of count num_recs to contain sizeof(pst_num_item)
01536         na_ptr->items       = (pst_num_item**) xmalloc(sizeof(pst_num_item)*num_list);
01537         na_ptr->count_item  = num_list;
01538         na_ptr->orig_count  = num_list;
01539         na_ptr->count_array = (int32_t)num_recs; // each record will have a record of the total number of records
01540         for (x=0; x<num_list; x++) na_ptr->items[x] = NULL;
01541         x = 0;
01542 
01543         DEBUG_EMAIL(("going to read %i (%#x) items\n", na_ptr->count_item, na_ptr->count_item));
01544 
01545         fr_ptr = list_start; // initialize fr_ptr to the start of the list.
01546         for (cur_list=0; cur_list<num_list; cur_list++) { //we will increase fr_ptr as we progress through index
01547             char* value_pointer = NULL;     // needed for block type 2 with values larger than 4 bytes
01548             size_t value_size = 0;
01549             if (block_type == 1) {
01550                 memcpy(&table_rec, fr_ptr, sizeof(table_rec));
01551                 LE16_CPU(table_rec.type);
01552                 LE16_CPU(table_rec.ref_type);
01553                 //LE32_CPU(table_rec.value);    // done later, some may be order invariant
01554                 fr_ptr += sizeof(table_rec);
01555             } else if (block_type == 2) {
01556                 // we will copy the table2_rec values into a table_rec record so that we can keep the rest of the code
01557                 memcpy(&table2_rec, fr_ptr, sizeof(table2_rec));
01558                 LE16_CPU(table2_rec.ref_type);
01559                 LE16_CPU(table2_rec.type);
01560                 LE16_CPU(table2_rec.ind2_off);
01561 
01562                 // table_rec and table2_rec are arranged differently, so assign the values across
01563                 table_rec.type     = table2_rec.type;
01564                 table_rec.ref_type = table2_rec.ref_type;
01565                 table_rec.value    = 0;
01566                 if ((ind2_end - ind2_ptr) >= (int)(table2_rec.ind2_off + table2_rec.size)) {
01567                     size_t n = table2_rec.size;
01568                     size_t m = sizeof(table_rec.value);
01569                     if (n <= m) {
01570                         memcpy(&table_rec.value, ind2_ptr + table2_rec.ind2_off, n);
01571                     }
01572                     else {
01573                         value_pointer = ind2_ptr + table2_rec.ind2_off;
01574                         value_size    = n;
01575                     }
01576                     //LE32_CPU(table_rec.value);    // done later, some may be order invariant
01577                 }
01578                 else {
01579                     DEBUG_WARN (("Trying to read outside buffer, buffer size %#x, offset %#x, data size %#x\n",
01580                                 read_size, ind2_end-ind2_ptr+table2_rec.ind2_off, table2_rec.size));
01581                 }
01582                 fr_ptr += sizeof(table2_rec);
01583             } else {
01584                 WARN(("Missing code for block_type %i\n", block_type));
01585                 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01586                 if (na_head) pst_free_list(na_head);
01587                 DEBUG_RET();
01588                 return NULL;
01589             }
01590             DEBUG_EMAIL(("reading block %i (type=%#x, ref_type=%#x, value=%#x)\n",
01591                 x, table_rec.type, table_rec.ref_type, table_rec.value));
01592 
01593             if (!na_ptr->items[x]) {
01594                 na_ptr->items[x] = (pst_num_item*) xmalloc(sizeof(pst_num_item));
01595             }
01596             memset(na_ptr->items[x], 0, sizeof(pst_num_item)); //init it
01597 
01598             // check here to see if the id of the attribute is a mapped one
01599             mapptr = pf->x_head;
01600             while (mapptr && (mapptr->map < table_rec.type)) mapptr = mapptr->next;
01601             if (mapptr && (mapptr->map == table_rec.type)) {
01602                 if (mapptr->mytype == PST_MAP_ATTRIB) {
01603                     na_ptr->items[x]->id = *((uint32_t*)mapptr->data);
01604                     DEBUG_EMAIL(("Mapped attrib %#x to %#x\n", table_rec.type, na_ptr->items[x]->id));
01605                 } else if (mapptr->mytype == PST_MAP_HEADER) {
01606                     DEBUG_EMAIL(("Internet Header mapping found %#x\n", table_rec.type));
01607                     na_ptr->items[x]->id = (uint32_t)PST_ATTRIB_HEADER;
01608                     na_ptr->items[x]->extra = mapptr->data;
01609                 }
01610                 else {
01611                     // nothing, should be assertion failure here
01612                 }
01613             } else {
01614                 na_ptr->items[x]->id = table_rec.type;
01615             }
01616             na_ptr->items[x]->type = 0; // checked later before it is set
01617             /* Reference Types
01618                 0x0002 - Signed 16bit value
01619                 0x0003 - Signed 32bit value
01620                 0x0004 - 4-byte floating point
01621                 0x0005 - Floating point double
01622                 0x0006 - Signed 64-bit int
01623                 0x0007 - Application Time
01624                 0x000A - 32-bit error value
01625                 0x000B - Boolean (non-zero = true)
01626                 0x000D - Embedded Object
01627                 0x0014 - 8-byte signed integer (64-bit)
01628                 0x001E - Null terminated String
01629                 0x001F - Unicode string
01630                 0x0040 - Systime - Filetime structure
01631                 0x0048 - OLE Guid
01632                 0x0102 - Binary data
01633                 0x1003 - Array of 32bit values
01634                 0x1014 - Array of 64bit values
01635                 0x101E - Array of Strings
01636                 0x1102 - Array of Binary data
01637             */
01638 
01639             if (table_rec.ref_type == (uint16_t)0x0002 ||
01640                 table_rec.ref_type == (uint16_t)0x0003 ||
01641                 table_rec.ref_type == (uint16_t)0x000b) {
01642                 //contains 32 bits of data
01643                 na_ptr->items[x]->size = sizeof(int32_t);
01644                 na_ptr->items[x]->type = table_rec.ref_type;
01645                 na_ptr->items[x]->data = xmalloc(sizeof(int32_t));
01646                 memcpy(na_ptr->items[x]->data, &(table_rec.value), sizeof(int32_t));
01647                 // are we missing an LE32_CPU() call here? table_rec.value is still
01648                 // in the original order.
01649 
01650             } else if (table_rec.ref_type == (uint16_t)0x0005 ||
01651                        table_rec.ref_type == (uint16_t)0x000d ||
01652                        table_rec.ref_type == (uint16_t)0x0014 ||
01653                        table_rec.ref_type == (uint16_t)0x001e ||
01654                        table_rec.ref_type == (uint16_t)0x001f ||
01655                        table_rec.ref_type == (uint16_t)0x0040 ||
01656                        table_rec.ref_type == (uint16_t)0x0048 ||
01657                        table_rec.ref_type == (uint16_t)0x0102 ||
01658                        table_rec.ref_type == (uint16_t)0x1003 ||
01659                        table_rec.ref_type == (uint16_t)0x1014 ||
01660                        table_rec.ref_type == (uint16_t)0x101e ||
01661                        table_rec.ref_type == (uint16_t)0x101f ||
01662                        table_rec.ref_type == (uint16_t)0x1102) {
01663                 //contains index reference to data
01664                 LE32_CPU(table_rec.value);
01665                 if (value_pointer) {
01666                     // in a type 2 block, with a value that is more than 4 bytes
01667                     // directly stored in this block.
01668                     na_ptr->items[x]->size = value_size;
01669                     na_ptr->items[x]->type = table_rec.ref_type;
01670                     na_ptr->items[x]->data = xmalloc(value_size);
01671                     memcpy(na_ptr->items[x]->data, value_pointer, value_size);
01672                 }
01673                 else if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset7)) {
01674                     if ((table_rec.value & 0xf) == (uint32_t)0xf) {
01675                         DEBUG_WARN(("failed to get block offset for table_rec.value of %#x to be read later.\n", table_rec.value));
01676                         na_ptr->items[x]->size = 0;
01677                         na_ptr->items[x]->data = NULL;
01678                         na_ptr->items[x]->type = table_rec.value;
01679                     }
01680                     else {
01681                         if (table_rec.value) {
01682                             DEBUG_WARN(("failed to get block offset for table_rec.value of %#x\n", table_rec.value));
01683                         }
01684                         na_ptr->count_item --; //we will be skipping a row
01685                         continue;
01686                     }
01687                 }
01688                 else {
01689                     value_size = (size_t)(block_offset7.to - block_offset7.from);
01690                     na_ptr->items[x]->size = value_size;
01691                     na_ptr->items[x]->type = table_rec.ref_type;
01692                     na_ptr->items[x]->data = xmalloc(value_size+1);
01693                     memcpy(na_ptr->items[x]->data, block_offset7.from, value_size);
01694                     na_ptr->items[x]->data[value_size] = '\0';  // it might be a string, null terminate it.
01695                 }
01696                 if (table_rec.ref_type == (uint16_t)0xd) {
01697                     // there is still more to do for the type of 0xD embedded objects
01698                     type_d_rec = (struct _type_d_rec*) na_ptr->items[x]->data;
01699                     LE32_CPU(type_d_rec->id);
01700                     na_ptr->items[x]->size = pst_ff_getID2block(pf, type_d_rec->id, i2_head, &(na_ptr->items[x]->data));
01701                     if (!na_ptr->items[x]->size){
01702                         DEBUG_WARN(("not able to read the ID2 data. Setting to be read later. %#x\n", type_d_rec->id));
01703                         na_ptr->items[x]->type = type_d_rec->id;    // fetch before freeing data, alias pointer
01704                         free(na_ptr->items[x]->data);
01705                         na_ptr->items[x]->data = NULL;
01706                     }
01707                 }
01708                 if (table_rec.ref_type == (uint16_t)0x1f) {
01709                     // there is more to do for the type 0x1f unicode strings
01710                     static vbuf *strbuf = NULL;
01711                     static vbuf *unibuf = NULL;
01712                     if (!strbuf) strbuf=vballoc((size_t)1024);
01713                     if (!unibuf) unibuf=vballoc((size_t)1024);
01714 
01715                     // splint barfed on the following lines
01716                     //VBUF_STATIC(strbuf, 1024);
01717                     //VBUF_STATIC(unibuf, 1024);
01718 
01719                     //need UTF-16 zero-termination
01720                     vbset(strbuf, na_ptr->items[x]->data, na_ptr->items[x]->size);
01721                     vbappend(strbuf, "\0\0", (size_t)2);
01722                     DEBUG_INDEX(("Iconv in:\n"));
01723                     DEBUG_HEXDUMPC(strbuf->b, strbuf->dlen, 0x10);
01724                     (void)vb_utf16to8(unibuf, strbuf->b, strbuf->dlen);
01725                     free(na_ptr->items[x]->data);
01726                     na_ptr->items[x]->size = unibuf->dlen;
01727                     na_ptr->items[x]->data = xmalloc(unibuf->dlen);
01728                     memcpy(na_ptr->items[x]->data, unibuf->b, unibuf->dlen);
01729                     DEBUG_INDEX(("Iconv out:\n"));
01730                     DEBUG_HEXDUMPC(na_ptr->items[x]->data, na_ptr->items[x]->size, 0x10);
01731                 }
01732                 if (na_ptr->items[x]->type == 0) na_ptr->items[x]->type = table_rec.ref_type;
01733             } else {
01734                 WARN(("ERROR Unknown ref_type %#hx\n", table_rec.ref_type));
01735                 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01736                 if (na_head) pst_free_list(na_head);
01737                 DEBUG_RET();
01738                 return NULL;
01739             }
01740             x++;
01741         }
01742         DEBUG_EMAIL(("increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n", rec_size, rec_size, ind2_ptr, ind2_ptr+rec_size));
01743         ind2_ptr += rec_size;
01744     }
01745     freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01746     DEBUG_RET();
01747     return na_head;
01748 }
01749 
01750 
01751 // This version of free does NULL check first
01752 #define SAFE_FREE(x) {if (x) free(x);}
01753 
01754 
01755 // check if item->email is NULL, and init if so
01756 #define MALLOC_EMAIL(x)        { if (!x->email)         { x->email         = (pst_item_email*)         xmalloc(sizeof(pst_item_email));         memset(x->email,         0, sizeof(pst_item_email)        );} }
01757 #define MALLOC_FOLDER(x)       { if (!x->folder)        { x->folder        = (pst_item_folder*)        xmalloc(sizeof(pst_item_folder));        memset(x->folder,        0, sizeof(pst_item_folder)       );} }
01758 #define MALLOC_CONTACT(x)      { if (!x->contact)       { x->contact       = (pst_item_contact*)       xmalloc(sizeof(pst_item_contact));       memset(x->contact,       0, sizeof(pst_item_contact)      );} }
01759 #define MALLOC_MESSAGESTORE(x) { if (!x->message_store) { x->message_store = (pst_item_message_store*) xmalloc(sizeof(pst_item_message_store)); memset(x->message_store, 0, sizeof(pst_item_message_store));} }
01760 #define MALLOC_JOURNAL(x)      { if (!x->journal)       { x->journal       = (pst_item_journal*)       xmalloc(sizeof(pst_item_journal));       memset(x->journal,       0, sizeof(pst_item_journal)      );} }
01761 #define MALLOC_APPOINTMENT(x)  { if (!x->appointment)   { x->appointment   = (pst_item_appointment*)   xmalloc(sizeof(pst_item_appointment));   memset(x->appointment,   0, sizeof(pst_item_appointment)  );} }
01762 // malloc space and copy the current item's data null terminated
01763 #define LIST_COPY(targ, type) {                               \
01764     targ = type realloc(targ, list->items[x]->size+1);        \
01765     memcpy(targ, list->items[x]->data, list->items[x]->size); \
01766     memset(((char*)targ)+list->items[x]->size, 0, (size_t)1); \
01767 }
01768 // malloc space and copy the item filetime
01769 #define LIST_COPY_TIME(targ) {                                \
01770     targ = (FILETIME*) realloc(targ, sizeof(FILETIME));       \
01771     memcpy(targ, list->items[x]->data, list->items[x]->size); \
01772     LE32_CPU(targ->dwLowDateTime);                            \
01773     LE32_CPU(targ->dwHighDateTime);                           \
01774 }
01775 // malloc space and copy the current item's data and size
01776 #define LIST_COPY_SIZE(targ, type, mysize) {        \
01777     mysize = list->items[x]->size;                  \
01778     if (mysize) {                                   \
01779         targ = type realloc(targ, mysize);          \
01780         memcpy(targ, list->items[x]->data, mysize); \
01781     }                                               \
01782     else {                                          \
01783         SAFE_FREE(targ);                            \
01784         targ = NULL;                                \
01785     }                                               \
01786 }
01787 
01788 #define NULL_CHECK(x) { if (!x) { DEBUG_EMAIL(("NULL_CHECK: Null Found\n")); break;} }
01789 
01790 #define MOVE_NEXT(targ) { \
01791     if (next){\
01792         if (!targ) {\
01793             DEBUG_EMAIL(("MOVE_NEXT: Target is NULL. Will stop processing this option\n"));\
01794             break;\
01795         }\
01796         targ = targ->next;\
01797         if (!targ) {\
01798             DEBUG_EMAIL(("MOVE_NEXT: Target is NULL after next. Will stop processing this option\n"));\
01799             break;\
01800         }\
01801         next=0;\
01802     }\
01803 }
01804 
01805 
01806 int pst_process(pst_num_array *list , pst_item *item, pst_item_attach *attach) {
01807     int32_t x, t;
01808     int next = 0;
01809     pst_item_extra_field *ef;
01810 
01811     DEBUG_ENT("pst_process");
01812     if (!item) {
01813         DEBUG_EMAIL(("item cannot be NULL.\n"));
01814         DEBUG_RET();
01815         return -1;
01816     }
01817 
01818     while (list) {
01819         x = 0;
01820         while (x < list->count_item) {
01821             // check here to see if the id is one that is mapped.
01822             DEBUG_EMAIL(("#%d - id: %#x type: %#x length: %#x\n", x, list->items[x]->id, list->items[x]->type, list->items[x]->size));
01823 
01824             switch (list->items[x]->id) {
01825                 case PST_ATTRIB_HEADER: // CUSTOM attribute for saying the Extra Headers
01826                     DEBUG_EMAIL(("Extra Field - "));
01827                     if (list->items[x]->extra) {
01828                         ef = (pst_item_extra_field*) xmalloc(sizeof(pst_item_extra_field));
01829                         memset(ef, 0, sizeof(pst_item_extra_field));
01830                         ef->field_name = (char*) xmalloc(strlen(list->items[x]->extra)+1);
01831                         strcpy(ef->field_name, list->items[x]->extra);
01832                         LIST_COPY(ef->value, (char*));
01833                         ef->next = item->extra_fields;
01834                         item->extra_fields = ef;
01835                         DEBUG_EMAIL(("\"%s\" = \"%s\"\n", ef->field_name, ef->value));
01836                     }
01837                     else {
01838                         DEBUG_EMAIL(("NULL extra field\n"));
01839                     }
01840                     break;
01841                 case 0x0002: // PR_ALTERNATE_RECIPIENT_ALLOWED
01842                     // If set to true, the sender allows this email to be autoforwarded
01843                     DEBUG_EMAIL(("AutoForward allowed - "));
01844                     MALLOC_EMAIL(item);
01845                     if (*(int16_t*)list->items[x]->data) {
01846                         DEBUG_EMAIL(("True\n"));
01847                         item->email->autoforward = 1;
01848                     } else {
01849                         DEBUG_EMAIL(("False\n"));
01850                         item->email->autoforward = -1;
01851                     }
01852                     break;
01853                 case 0x0003: // Extended Attributes table
01854                     DEBUG_EMAIL(("Extended Attributes Table - NOT PROCESSED\n"));
01855                     break;
01856                 case 0x0017: // PR_IMPORTANCE
01857                     // How important the sender deems it to be
01858                     // 0 - Low
01859                     // 1 - Normal
01860                     // 2 - High
01861 
01862                     DEBUG_EMAIL(("Importance Level - "));
01863                     MALLOC_EMAIL(item);
01864                     memcpy(&(item->email->importance), list->items[x]->data, sizeof(item->email->importance));
01865                     LE32_CPU(item->email->importance);
01866                     t = item->email->importance;
01867                     DEBUG_EMAIL(("%s [%i]\n", ((int)t==0?"Low":((int)t==1?"Normal":"High")), t));
01868                     break;
01869                 case 0x001A: // PR_MESSAGE_CLASS Ascii type of messages - NOT FOLDERS
01870                     // must be case insensitive
01871                     DEBUG_EMAIL(("IPM.x - "));
01872                     LIST_COPY(item->ascii_type, (char*));
01873                     if (pst_strincmp("IPM.Note", item->ascii_type, 8) == 0)
01874                         // the string begins with IPM.Note...
01875                         item->type = PST_TYPE_NOTE;
01876                     else if (pst_stricmp("IPM", item->ascii_type) == 0)
01877                         // the whole string is just IPM
01878                         item->type = PST_TYPE_NOTE;
01879                     else if (pst_strincmp("IPM.Contact", item->ascii_type, 11) == 0)
01880                         // the string begins with IPM.Contact...
01881                         item->type = PST_TYPE_CONTACT;
01882                     else if (pst_strincmp("REPORT.IPM.Note", item->ascii_type, 15) == 0)
01883                         // the string begins with the above
01884                         item->type = PST_TYPE_REPORT;
01885                     else if (pst_strincmp("IPM.Activity", item->ascii_type, 12) == 0)
01886                         item->type = PST_TYPE_JOURNAL;
01887                     else if (pst_strincmp("IPM.Appointment", item->ascii_type, 15) == 0)
01888                         item->type = PST_TYPE_APPOINTMENT;
01889                     else if (pst_strincmp("IPM.Task", item->ascii_type, 8) == 0)
01890                         item->type = PST_TYPE_TASK;
01891                     else
01892                         item->type = PST_TYPE_OTHER;
01893 
01894                     DEBUG_EMAIL(("%s\n", item->ascii_type));
01895                     break;
01896                 case 0x0023: // PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED
01897                     // set if the sender wants a delivery report from all recipients
01898                     DEBUG_EMAIL(("Global Delivery Report - "));
01899                     MALLOC_EMAIL(item);
01900                     if (*(int16_t*)list->items[x]->data) {
01901                         DEBUG_EMAIL(("True\n"));
01902                         item->email->delivery_report = 1;
01903                     } else {
01904                         DEBUG_EMAIL(("False\n"));
01905                         item->email->delivery_report = 0;
01906                     }
01907                     break;
01908                 case 0x0026: // PR_PRIORITY
01909                     // Priority of a message
01910                     // -1 NonUrgent
01911                     //  0 Normal
01912                     //  1 Urgent
01913                     DEBUG_EMAIL(("Priority - "));
01914                     MALLOC_EMAIL(item);
01915                     memcpy(&(item->email->priority), list->items[x]->data, sizeof(item->email->priority));
01916                     LE32_CPU(item->email->priority);
01917                     t = item->email->priority;
01918                     DEBUG_EMAIL(("%s [%i]\n", (t<0?"NonUrgent":(t==0?"Normal":"Urgent")), t));
01919                     break;
01920                 case 0x0029: // PR_READ_RECEIPT_REQUESTED
01921                     DEBUG_EMAIL(("Read Receipt - "));
01922                     MALLOC_EMAIL(item);
01923                     if (*(int16_t*)list->items[x]->data) {
01924                         DEBUG_EMAIL(("True\n"));
01925                         item->email->read_receipt = 1;
01926                     } else {
01927                         DEBUG_EMAIL(("False\n"));
01928                         item->email->read_receipt = 0;
01929                     }
01930                     break;
01931                 case 0x002B: // PR_RECIPIENT_REASSIGNMENT_PROHIBITED
01932                     DEBUG_EMAIL(("Reassignment Prohibited (Private) - "));
01933                     if (*(int16_t*)list->items[x]->data) {
01934                         DEBUG_EMAIL(("True\n"));
01935                         item->private_member = 1;
01936                     } else {
01937                         DEBUG_EMAIL(("False\n"));
01938                         item->private_member = 0;
01939                     }
01940                     break;
01941                 case 0x002E: // PR_ORIGINAL_SENSITIVITY
01942                     // the sensitivity of the message before being replied to or forwarded
01943                     // 0 - None
01944                     // 1 - Personal
01945                     // 2 - Private
01946                     // 3 - Company Confidential
01947                     DEBUG_EMAIL(("Original Sensitivity - "));
01948                     MALLOC_EMAIL(item);
01949                     memcpy(&(item->email->orig_sensitivity), list->items[x]->data, sizeof(item->email->orig_sensitivity));
01950                     LE32_CPU(item->email->orig_sensitivity);
01951                     t = item->email->orig_sensitivity;
01952                     DEBUG_EMAIL(("%s [%i]\n", ((int)t==0?"None":((int)t==1?"Personal":
01953                                         ((int)t==2?"Private":"Company Confidential"))), t));
01954                     break;
01955                 case 0x0036: // PR_SENSITIVITY
01956                     // sender's opinion of the sensitivity of an email
01957                     // 0 - None
01958                     // 1 - Personal
01959                     // 2 - Private
01960                     // 3 - Company Confidiential
01961                     DEBUG_EMAIL(("Sensitivity - "));
01962                     MALLOC_EMAIL(item);
01963                     memcpy(&(item->email->sensitivity), list->items[x]->data, sizeof(item->email->sensitivity));
01964                     LE32_CPU(item->email->sensitivity);
01965                     t = item->email->sensitivity;
01966                     DEBUG_EMAIL(("%s [%i]\n", ((int)t==0?"None":((int)t==1?"Personal":
01967                                         ((int)t==2?"Private":"Company Confidential"))), t));
01968                     break;
01969                 case 0x0037: // PR_SUBJECT raw subject
01970                     DEBUG_EMAIL(("Raw Subject - "));
01971                     MALLOC_EMAIL(item);
01972                     item->email->subject = (pst_item_email_subject*) realloc(item->email->subject, sizeof(pst_item_email_subject));
01973                     memset(item->email->subject, 0, sizeof(pst_item_email_subject));
01974                     DEBUG_EMAIL((" [size = %i] ", list->items[x]->size));
01975                     if (list->items[x]->size > 0) {
01976                         if (isprint(list->items[x]->data[0])) {
01977                             // then there are no control bytes at the front
01978                             item->email->subject->off1 = 0;
01979                             item->email->subject->off2 = 0;
01980                             item->email->subject->subj = realloc(item->email->subject->subj, list->items[x]->size+1);
01981                             memset(item->email->subject->subj, 0, list->items[x]->size+1);
01982                             memcpy(item->email->subject->subj, list->items[x]->data, list->items[x]->size);
01983                         } else {
01984                             DEBUG_EMAIL(("Raw Subject has control codes\n"));
01985                             // there might be some control bytes in the first and second bytes
01986                             item->email->subject->off1 = (int)(unsigned)list->items[x]->data[0];
01987                             item->email->subject->off2 = (int)(unsigned)list->items[x]->data[1];
01988                             item->email->subject->subj = realloc(item->email->subject->subj, list->items[x]->size-1);
01989                             memset(item->email->subject->subj, 0, list->items[x]->size-1);
01990                             memcpy(item->email->subject->subj, &(list->items[x]->data[2]), list->items[x]->size-2);
01991                         }
01992                         DEBUG_EMAIL(("%s\n", item->email->subject->subj));
01993                     } else {
01994                         // obviously outlook has decided not to be straight with this one.
01995                         item->email->subject->off1 = 0;
01996                         item->email->subject->off2 = 0;
01997                         item->email->subject = NULL;
01998                         DEBUG_EMAIL(("NULL subject detected\n"));
01999                     }
02000                     break;
02001                 case 0x0039: // PR_CLIENT_SUBMIT_TIME Date Email Sent/Created
02002                     DEBUG_EMAIL(("Date sent - "));
02003                     MALLOC_EMAIL(item);
02004                     LIST_COPY_TIME(item->email->sent_date);
02005                     DEBUG_EMAIL(("%s", fileTimeToAscii(item->email->sent_date)));
02006                     break;
02007                 case 0x003B: // PR_SENT_REPRESENTING_SEARCH_KEY Sender address 1
02008                     DEBUG_EMAIL(("Sent on behalf of address 1 - "));
02009                     MALLOC_EMAIL(item);
02010                     LIST_COPY(item->email->outlook_sender, (char*));
02011                     DEBUG_EMAIL(("%s\n", item->email->outlook_sender));
02012                     break;
02013                 case 0x003F: // PR_RECEIVED_BY_ENTRYID Structure containing Recipient
02014                     DEBUG_EMAIL(("Recipient Structure 1 -- NOT HANDLED\n"));
02015                     break;
02016                 case 0x0040: // PR_RECEIVED_BY_NAME Name of Recipient Structure
02017                     DEBUG_EMAIL(("Received By Name 1 -- NOT HANDLED\n"));
02018                     break;
02019                 case 0x0041: // PR_SENT_REPRESENTING_ENTRYID Structure containing Sender
02020                     DEBUG_EMAIL(("Sent on behalf of Structure 1 -- NOT HANDLED\n"));
02021                     break;
02022                 case 0x0042: // PR_SENT_REPRESENTING_NAME Name of Sender Structure
02023                     DEBUG_EMAIL(("Sent on behalf of Structure Name - "));
02024                     MALLOC_EMAIL(item);
02025                     LIST_COPY(item->email->outlook_sender_name, (char*));
02026                     DEBUG_EMAIL(("%s\n", item->email->outlook_sender_name));
02027                     break;
02028                 case 0x0043: // PR_RCVD_REPRESENTING_ENTRYID Recipient Structure 2
02029                     DEBUG_EMAIL(("Received on behalf of Structure -- NOT HANDLED\n"));
02030                     break;
02031                 case 0x0044: // PR_RCVD_REPRESENTING_NAME Name of Recipient Structure 2
02032                     DEBUG_EMAIL(("Received on behalf of Structure Name -- NOT HANDLED\n"));
02033                     MALLOC_EMAIL(item);
02034                     LIST_COPY(item->email->outlook_recipient_name, (char*));
02035                     DEBUG_EMAIL(("%s\n", item->email->outlook_recipient_name));
02036                     break;
02037                 case 0x004F: // PR_REPLY_RECIPIENT_ENTRIES Reply-To Structure
02038                     DEBUG_EMAIL(("Reply-To Structure -- NOT HANDLED\n"));
02039                     break;
02040                 case 0x0050: // PR_REPLY_RECIPIENT_NAMES Name of Reply-To Structure
02041                     DEBUG_EMAIL(("Name of Reply-To Structure -"));
02042                     MALLOC_EMAIL(item);
02043                     LIST_COPY(item->email->reply_to, (char*));
02044                     DEBUG_EMAIL(("%s\n", item->email->reply_to));
02045                     break;
02046                 case 0x0051: // PR_RECEIVED_BY_SEARCH_KEY Recipient Address 1
02047                     DEBUG_EMAIL(("Recipient's Address 1 (Search Key) - "));
02048                     MALLOC_EMAIL(item);
02049                     LIST_COPY (item->email->outlook_recipient, (char*));
02050                     DEBUG_EMAIL(("%s\n", item->email->outlook_recipient));
02051                     break;
02052                 case 0x0052: // PR_RCVD_REPRESENTING_SEARCH_KEY Recipient Address 2
02053                     DEBUG_EMAIL(("Received on behalf of Address (Search Key) - "));
02054                     MALLOC_EMAIL(item);
02055                     LIST_COPY(item->email->outlook_recipient2, (char*));
02056                     DEBUG_EMAIL(("%s\n", item->email->outlook_recipient2));
02057                     break;
02058                 case 0x0057: // PR_MESSAGE_TO_ME
02059                     // this user is listed explicitly in the TO address
02060                     DEBUG_EMAIL(("My address in TO field - "));
02061                     MALLOC_EMAIL(item);
02062                     if (*(int16_t*)list->items[x]->data) {
02063                         DEBUG_EMAIL(("True\n"));
02064                         item->email->message_to_me = 1;
02065                     } else {
02066                         DEBUG_EMAIL(("False\n"));
02067                         item->email->message_to_me = 0;
02068                     }
02069                     break;
02070                 case 0x0058: // PR_MESSAGE_CC_ME
02071                     // this user is listed explicitly in the CC address
02072                     DEBUG_EMAIL(("My address in CC field - "));
02073                     MALLOC_EMAIL(item);
02074                     if (*(int16_t*)list->items[x]->data) {
02075                         DEBUG_EMAIL(("True\n"));
02076                         item->email->message_cc_me = 1;
02077                     } else {
02078                         DEBUG_EMAIL(("False\n"));
02079                         item->email->message_cc_me = 0;
02080                     }
02081                     break;
02082                 case 0x0059: // PR_MESSAGE_RECIP_ME
02083                     // this user appears in TO, CC or BCC address list
02084                     DEBUG_EMAIL(("Message addressed to me - "));
02085                     MALLOC_EMAIL(item);
02086                     if (*(int16_t*)list->items[x]->data) {
02087                         DEBUG_EMAIL(("True\n"));
02088                         item->email->message_recip_me = 1;
02089                     } else {
02090                         DEBUG_EMAIL(("False\n"));
02091                         item->email->message_recip_me = 0;
02092                     }
02093                     break;
02094                 case 0x0063: // PR_RESPONSE_REQUESTED
02095                     DEBUG_EMAIL(("Response requested - "));
02096                     if (*(int16_t*)list->items[x]->data) {
02097                         DEBUG_EMAIL(("True\n"));
02098                         item->response_requested = 1;
02099                     } else {
02100                         DEBUG_EMAIL(("False\n"));
02101                         item->response_requested = 0;
02102                     }
02103                     break;
02104                 case 0x0064: // PR_SENT_REPRESENTING_ADDRTYPE Access method for Sender Address
02105                     DEBUG_EMAIL(("Sent on behalf of address type - "));
02106                     MALLOC_EMAIL(item);
02107                     LIST_COPY(item->email->sender_access, (char*));
02108                     DEBUG_EMAIL(("%s\n", item->email->sender_access));
02109                     break;
02110                 case 0x0065: // PR_SENT_REPRESENTING_EMAIL_ADDRESS Sender Address
02111                     DEBUG_EMAIL(("Sent on behalf of Address - "));
02112                     MALLOC_EMAIL(item);
02113                     LIST_COPY(item->email->sender_address, (char*));
02114                     DEBUG_EMAIL(("%s\n", item->email->sender_address));
02115                     break;
02116                 case 0x0070: // PR_CONVERSATION_TOPIC Processed Subject
02117                     DEBUG_EMAIL(("Processed Subject (Conversation Topic) - "));
02118                     MALLOC_EMAIL(item);
02119                     LIST_COPY(item->email->proc_subject, (char*));
02120                     DEBUG_EMAIL(("%s\n", item->email->proc_subject));
02121                     break;
02122                 case 0x0071: // PR_CONVERSATION_INDEX
02123                     DEBUG_EMAIL(("Conversation Index - "));
02124                     MALLOC_EMAIL(item);
02125                     memcpy(&(item->email->conv_index), list->items[x]->data, sizeof(item->email->conv_index));
02126                     DEBUG_EMAIL(("%i\n", item->email->conv_index));
02127                     break;
02128                 case 0x0072: // PR_ORIGINAL_DISPLAY_BCC
02129                     DEBUG_EMAIL(("Original display bcc - "));
02130                     MALLOC_EMAIL(item);
02131                     LIST_COPY(item->email->original_bcc, (char*));
02132                     DEBUG_EMAIL(("%s\n", item->email->original_bcc));
02133                     break;
02134                 case 0x0073: // PR_ORIGINAL_DISPLAY_CC
02135                     DEBUG_EMAIL(("Original display cc - "));
02136                     MALLOC_EMAIL(item);
02137                     LIST_COPY(item->email->original_cc, (char*));
02138                     DEBUG_EMAIL(("%s\n", item->email->original_cc));
02139                     break;
02140                 case 0x0074: // PR_ORIGINAL_DISPLAY_TO
02141                     DEBUG_EMAIL(("Original display to - "));
02142                     MALLOC_EMAIL(item);
02143                     LIST_COPY(item->email->original_to, (char*));
02144                     DEBUG_EMAIL(("%s\n", item->email->original_to));
02145                     break;
02146                 case 0x0075: // PR_RECEIVED_BY_ADDRTYPE Recipient Access Method
02147                     DEBUG_EMAIL(("Received by Address type - "));
02148                     MALLOC_EMAIL(item);
02149                     LIST_COPY(item->email->recip_access, (char*));
02150                     DEBUG_EMAIL(("%s\n", item->email->recip_access));
02151                     break;
02152                 case 0x0076: // PR_RECEIVED_BY_EMAIL_ADDRESS Recipient Address
02153                     DEBUG_EMAIL(("Received by Address - "));
02154                     MALLOC_EMAIL(item);
02155                     LIST_COPY(item->email->recip_address, (char*));
02156                     DEBUG_EMAIL(("%s\n", item->email->recip_address));
02157                     break;
02158                 case 0x0077: // PR_RCVD_REPRESENTING_ADDRTYPE Recipient Access Method 2
02159                     DEBUG_EMAIL(("Received on behalf of Address type - "));
02160                     MALLOC_EMAIL(item);
02161                     LIST_COPY(item->email->recip2_access, (char*));
02162                     DEBUG_EMAIL(("%s\n", item->email->recip2_access));
02163                     break;
02164                 case 0x0078: // PR_RCVD_REPRESENTING_EMAIL_ADDRESS Recipient Address 2
02165                     DEBUG_EMAIL(("Received on behalf of Address -"));
02166                     MALLOC_EMAIL(item);
02167                     LIST_COPY(item->email->recip2_address, (char*));
02168                     DEBUG_EMAIL(("%s\n", item->email->recip2_address));
02169                     break;
02170                 case 0x007D: // PR_TRANSPORT_MESSAGE_HEADERS Internet Header
02171                     DEBUG_EMAIL(("Internet Header - "));
02172                     MALLOC_EMAIL(item);
02173                     LIST_COPY(item->email->header, (char*));
02174                     DEBUG_EMAIL(("%s\n", item->email->header));
02175                     DEBUG_EMAIL(("NOT PRINTED\n"));
02176                     break;
02177                 case 0x0C17: // PR_REPLY_REQUESTED
02178                     DEBUG_EMAIL(("Reply Requested - "));
02179                     MALLOC_EMAIL(item);
02180                     if (*(int16_t*)list->items[x]->data) {
02181                         DEBUG_EMAIL(("True\n"));
02182                         item->email->reply_requested = 1;
02183                     } else {
02184                         DEBUG_EMAIL(("False\n"));
02185                         item->email->reply_requested = 0;
02186                     }
02187                     break;
02188                 case 0x0C19: // PR_SENDER_ENTRYID Sender Structure 2
02189                     DEBUG_EMAIL(("Sender Structure 2 -- NOT HANDLED\n"));
02190                     break;
02191                 case 0x0C1A: // PR_SENDER_NAME Name of Sender Structure 2
02192                     DEBUG_EMAIL(("Name of Sender Structure 2 -- NOT HANDLED\n"));
02193                     break;
02194                 case 0x0C1D: // PR_SENDER_SEARCH_KEY Name of Sender Address 2
02195                     DEBUG_EMAIL(("Name of Sender Address 2 (Sender search key) - "));
02196                     MALLOC_EMAIL(item);
02197                     LIST_COPY(item->email->outlook_sender2, (char*));
02198                     DEBUG_EMAIL(("%s\n", item->email->outlook_sender2));
02199                     break;
02200                 case 0x0C1E: // PR_SENDER_ADDRTYPE Sender Address 2 access method
02201                     DEBUG_EMAIL(("Sender Address type - "));
02202                     MALLOC_EMAIL(item);
02203                     LIST_COPY(item->email->sender2_access, (char*));
02204                     DEBUG_EMAIL(("%s\n", item->email->sender2_access));
02205                     break;
02206                 case 0x0C1F: // PR_SENDER_EMAIL_ADDRESS Sender Address 2
02207                     DEBUG_EMAIL(("Sender Address - "));
02208                     MALLOC_EMAIL(item);
02209                     LIST_COPY(item->email->sender2_address, (char*));
02210                     DEBUG_EMAIL(("%s\n", item->email->sender2_address));
02211                     break;
02212                 case 0x0E01: // PR_DELETE_AFTER_SUBMIT
02213                     // I am not too sure how this works
02214                     DEBUG_EMAIL(("Delete after submit - "));
02215                     MALLOC_EMAIL(item);
02216                     if (*(int16_t*)list->items[x]->data) {
02217                         DEBUG_EMAIL(("True\n"));
02218                         item->email->delete_after_submit = 1;
02219                     } else {
02220                         DEBUG_EMAIL(("False\n"));
02221                         item->email->delete_after_submit = 0;
02222                     }
02223                     break;
02224                 case 0x0E02: // PR_DISPLAY_BCC BCC Addresses
02225                     DEBUG_EMAIL(("Display BCC Addresses - "));
02226                     MALLOC_EMAIL(item);
02227                     LIST_COPY(item->email->bcc_address, (char*));
02228                     DEBUG_EMAIL(("%s\n", item->email->bcc_address));
02229                     break;
02230                 case 0x0E03: // PR_DISPLAY_CC CC Addresses
02231                     DEBUG_EMAIL(("Display CC Addresses - "));
02232                     MALLOC_EMAIL(item);
02233                     LIST_COPY(item->email->cc_address, (char*));
02234                     DEBUG_EMAIL(("%s\n", item->email->cc_address));
02235                     break;
02236                 case 0x0E04: // PR_DISPLAY_TO Address Sent-To
02237                     DEBUG_EMAIL(("Display Sent-To Address - "));
02238                     MALLOC_EMAIL(item);
02239                     LIST_COPY(item->email->sentto_address, (char*));
02240                     DEBUG_EMAIL(("%s\n", item->email->sentto_address));
02241                     break;
02242                 case 0x0E06: // PR_MESSAGE_DELIVERY_TIME Date 3 - Email Arrival Date
02243                     DEBUG_EMAIL(("Date 3 (Delivery Time) - "));
02244                     MALLOC_EMAIL(item);
02245                     LIST_COPY_TIME(item->email->arrival_date);
02246                     DEBUG_EMAIL(("%s", fileTimeToAscii(item->email->arrival_date)));
02247                     break;
02248                 case 0x0E07: // PR_MESSAGE_FLAGS Email Flag
02249                     // 0x01 - Read
02250                     // 0x02 - Unmodified
02251                     // 0x04 - Submit
02252                     // 0x08 - Unsent
02253                     // 0x10 - Has Attachments
02254                     // 0x20 - From Me
02255                     // 0x40 - Associated
02256                     // 0x80 - Resend
02257                     // 0x100 - RN Pending
02258                     // 0x200 - NRN Pending
02259                     DEBUG_EMAIL(("Message Flags - "));
02260                     MALLOC_EMAIL(item);
02261                     memcpy(&(item->email->flag), list->items[x]->data, sizeof(item->email->flag));
02262                     LE32_CPU(item->email->flag);
02263                     DEBUG_EMAIL(("%i\n", item->email->flag));
02264                     break;
02265                 case 0x0E08: // PR_MESSAGE_SIZE Total size of a message object
02266                     DEBUG_EMAIL(("Message Size - "));
02267                     memcpy(&(item->message_size), list->items[x]->data, sizeof(item->message_size));
02268                     LE32_CPU(item->message_size);
02269                     DEBUG_EMAIL(("%i [%#x]\n", item->message_size, item->message_size));
02270                     break;
02271                 case 0x0E0A: // PR_SENTMAIL_ENTRYID
02272                     // folder that this message is sent to after submission
02273                     DEBUG_EMAIL(("Sentmail EntryID - "));
02274                     MALLOC_EMAIL(item);
02275                     LIST_COPY(item->email->sentmail_folder, (pst_entryid*));
02276                     LE32_CPU(item->email->sentmail_folder->id);
02277                     DEBUG_EMAIL(("[id = %#x]\n", item->email->sentmail_folder->id));
02278                     break;
02279                 case 0x0E1F: // PR_RTF_IN_SYNC
02280                     // True means that the rtf version is same as text body
02281                     // False means rtf version is more up-to-date than text body
02282                     // if this value doesn't exist, text body is more up-to-date than rtf and
02283                     //   cannot update to the rtf
02284                     DEBUG_EMAIL(("Compressed RTF in Sync - "));
02285                     MALLOC_EMAIL(item);
02286                     if (*(int16_t*)list->items[x]->data) {
02287                         DEBUG_EMAIL(("True\n"));
02288                         item->email->rtf_in_sync = 1;
02289                     } else {
02290                         DEBUG_EMAIL(("False\n"));
02291                         item->email->rtf_in_sync = 0;
02292                     }
02293                     break;
02294                 case 0x0E20: // PR_ATTACH_SIZE binary Attachment data in record
02295                     DEBUG_EMAIL(("Attachment Size - "));
02296                     NULL_CHECK(attach);
02297                     MOVE_NEXT(attach);
02298                     t = (*(int32_t*)list->items[x]->data);
02299                     LE32_CPU(t);
02300                     attach->size = (size_t)t;
02301                     DEBUG_EMAIL(("%i\n", attach->size));
02302                     break;
02303                 case 0x0FF9: // PR_RECORD_KEY Record Header 1
02304                     DEBUG_EMAIL(("Record Key 1 - "));
02305                     LIST_COPY(item->record_key, (char*));
02306                     item->record_key_size = list->items[x]->size;
02307                     DEBUG_EMAIL_HEXPRINT(item->record_key, item->record_key_size);
02308                     DEBUG_EMAIL(("\n"));
02309                     break;
02310                 case 0x1000: // PR_BODY Plain Text body
02311                     DEBUG_EMAIL(("Plain Text body - "));
02312                     MALLOC_EMAIL(item);
02313                     LIST_COPY(item->email->body, (char*));
02314                     //DEBUG_EMAIL("%s\n", item->email->body);
02315                     DEBUG_EMAIL(("NOT PRINTED\n"));
02316                     break;
02317                 case 0x1006: // PR_RTF_SYNC_BODY_CRC
02318                     DEBUG_EMAIL(("RTF Sync Body CRC - "));
02319                     MALLOC_EMAIL(item);
02320                     memcpy(&(item->email->rtf_body_crc), list->items[x]->data, sizeof(item->email->rtf_body_crc));
02321                     LE32_CPU(item->email->rtf_body_crc);
02322                     DEBUG_EMAIL(("%#x\n", item->email->rtf_body_crc));
02323                     break;
02324                 case 0x1007: // PR_RTF_SYNC_BODY_COUNT
02325                     // a count of the *significant* charcters in the rtf body. Doesn't count
02326                     // whitespace and other ignorable characters
02327                     DEBUG_EMAIL(("RTF Sync Body character count - "));
02328                     MALLOC_EMAIL(item);
02329                     memcpy(&(item->email->rtf_body_char_count), list->items[x]->data, sizeof(item->email->rtf_body_char_count));
02330                     LE32_CPU(item->email->rtf_body_char_count);
02331                     DEBUG_EMAIL(("%i [%#x]\n", item->email->rtf_body_char_count, item->email->rtf_body_char_count));
02332                     break;
02333                 case 0x1008: // PR_RTF_SYNC_BODY_TAG
02334                     // the first couple of lines of RTF body so that after modification, then beginning can
02335                     // once again be found
02336                     DEBUG_EMAIL(("RTF Sync body tag - "));
02337                     MALLOC_EMAIL(item);
02338                     LIST_COPY(item->email->rtf_body_tag, (char*));
02339                     DEBUG_EMAIL(("%s\n", item->email->rtf_body_tag));
02340                     break;
02341                 case 0x1009: // PR_RTF_COMPRESSED
02342                     // rtf data is lzw compressed
02343                     DEBUG_EMAIL(("RTF Compressed body - "));
02344                     MALLOC_EMAIL(item);
02345                     LIST_COPY_SIZE(item->email->rtf_compressed, (char*), item->email->rtf_compressed_size);
02346                     //DEBUG_EMAIL_HEXPRINT((char*)item->email->rtf_compressed, item->email->rtf_compressed_size);
02347                     break;
02348                 case 0x1010: // PR_RTF_SYNC_PREFIX_COUNT
02349                     // a count of the ignored characters before the first significant character
02350                     DEBUG_EMAIL(("RTF whitespace prefix count - "));
02351                     MALLOC_EMAIL(item);
02352                     memcpy(&(item->email->rtf_ws_prefix_count), list->items[x]->data, sizeof(item->email->rtf_ws_prefix_count));
02353                     DEBUG_EMAIL(("%i\n", item->email->rtf_ws_prefix_count));
02354                     break;
02355                 case 0x1011: // PR_RTF_SYNC_TRAILING_COUNT
02356                     // a count of the ignored characters after the last significant character
02357                     DEBUG_EMAIL(("RTF whitespace tailing count - "));
02358                     MALLOC_EMAIL(item);
02359                     memcpy(&(item->email->rtf_ws_trailing_count), list->items[x]->data, sizeof(item->email->rtf_ws_trailing_count));
02360                     DEBUG_EMAIL(("%i\n", item->email->rtf_ws_trailing_count));
02361                     break;
02362                 case 0x1013: // HTML body
02363                     DEBUG_EMAIL(("HTML body - "));
02364                     MALLOC_EMAIL(item);
02365                     LIST_COPY(item->email->htmlbody, (char*));
02366                     //  DEBUG_EMAIL(("%s\n", item->email->htmlbody));
02367                     DEBUG_EMAIL(("NOT PRINTED\n"));
02368                     break;
02369                 case 0x1035: // Message ID
02370                     DEBUG_EMAIL(("Message ID - "));
02371                     MALLOC_EMAIL(item);
02372                     LIST_COPY(item->email->messageid, (char*));
02373                     DEBUG_EMAIL(("%s\n", item->email->messageid));
02374                     break;
02375                 case 0x1042: // in-reply-to
02376                     DEBUG_EMAIL(("In-Reply-To - "));
02377                     MALLOC_EMAIL(item);
02378                     LIST_COPY(item->email->in_reply_to, (char*));
02379                     DEBUG_EMAIL(("%s\n", item->email->in_reply_to));
02380                     break;
02381                 case 0x1046: // Return Path
02382                     DEBUG_EMAIL(("Return Path - "));
02383                     MALLOC_EMAIL(item);
02384                     LIST_COPY(item->email->return_path_address, (char*));
02385                     DEBUG_EMAIL(("%s\n", item->email->return_path_address));
02386                     break;
02387                 case 0x3001: // PR_DISPLAY_NAME File As
02388                     DEBUG_EMAIL(("Display Name - "));
02389                     LIST_COPY(item->file_as, (char*));
02390                     DEBUG_EMAIL(("%s\n", item->file_as));
02391                     break;
02392                 case 0x3002: // PR_ADDRTYPE
02393                     DEBUG_EMAIL(("Address Type - "));
02394                     MALLOC_CONTACT(item);
02395                     LIST_COPY(item->contact->address1_transport, (char*));
02396                     DEBUG_EMAIL(("|%s|\n", item->contact->address1_transport));
02397                     break;
02398                 case 0x3003: // PR_EMAIL_ADDRESS
02399                     // Contact's email address
02400                     DEBUG_EMAIL(("Contact Address - "));
02401                     MALLOC_CONTACT(item);
02402                     LIST_COPY(item->contact->address1, (char*));
02403                     DEBUG_EMAIL(("|%s|\n", item->contact->address1));
02404                     break;
02405                 case 0x3004: // PR_COMMENT Comment for item - usually folders
02406                     DEBUG_EMAIL(("Comment - "));
02407                     LIST_COPY(item->comment, (char*));
02408                     DEBUG_EMAIL(("%s\n", item->comment));
02409                     break;
02410                 case 0x3007: // PR_CREATION_TIME Date 4 - Creation Date?
02411                     DEBUG_EMAIL(("Date 4 (Item Creation Date) - "));
02412                     LIST_COPY_TIME(item->create_date);
02413                     DEBUG_EMAIL(("%s", fileTimeToAscii(item->create_date)));
02414                     break;
02415                 case 0x3008: // PR_LAST_MODIFICATION_TIME Date 5 - Modify Date
02416                     DEBUG_EMAIL(("Date 5 (Modify Date) - "));
02417                     LIST_COPY_TIME(item->modify_date);
02418                     DEBUG_EMAIL(("%s", fileTimeToAscii(item->modify_date)));
02419                     break;
02420                 case 0x300B: // PR_SEARCH_KEY Record Header 2
02421                     DEBUG_EMAIL(("Record Search 2 -- NOT HANDLED\n"));
02422                     break;
02423                 case 0x35DF: // PR_VALID_FOLDER_MASK
02424                     // States which folders are valid for this message store
02425                     // FOLDER_IPM_SUBTREE_VALID 0x1
02426                     // FOLDER_IPM_INBOX_VALID   0x2
02427                     // FOLDER_IPM_OUTBOX_VALID  0x4
02428                     // FOLDER_IPM_WASTEBOX_VALID 0x8
02429                     // FOLDER_IPM_SENTMAIL_VALID 0x10
02430                     // FOLDER_VIEWS_VALID        0x20
02431                     // FOLDER_COMMON_VIEWS_VALID 0x40
02432                     // FOLDER_FINDER_VALID       0x80
02433                     DEBUG_EMAIL(("Valid Folder Mask - "));
02434                     MALLOC_MESSAGESTORE(item);
02435                     memcpy(&(item->message_store->valid_mask), list->items[x]->data, sizeof(item->message_store->valid_mask));
02436                     LE32_CPU(item->message_store->valid_mask);
02437                     DEBUG_EMAIL(("%i\n", item->message_store->valid_mask));
02438                     break;
02439                 case 0x35E0: // PR_IPM_SUBTREE_ENTRYID Top of Personal Folder Record
02440                     DEBUG_EMAIL(("Top of Personal Folder Record - "));
02441                     MALLOC_MESSAGESTORE(item);
02442                     LIST_COPY(item->message_store->top_of_personal_folder, (pst_entryid*));
02443                     LE32_CPU(item->message_store->top_of_personal_folder->id);
02444                     DEBUG_EMAIL(("[id = %#x]\n", item->message_store->top_of_personal_folder->id));
02445                     break;
02446                 case 0x35E2: // PR_IPM_OUTBOX_ENTRYID
02447                     DEBUG_EMAIL(("Default Outbox Folder record - "));
02448                     MALLOC_MESSAGESTORE(item);
02449                     LIST_COPY(item->message_store->default_outbox_folder, (pst_entryid*));
02450                     LE32_CPU(item->message_store->default_outbox_folder->id);
02451                     DEBUG_EMAIL(("[id = %#x]\n", item->message_store->default_outbox_folder->id));
02452                     break;
02453                 case 0x35E3: // PR_IPM_WASTEBASKET_ENTRYID
02454                     DEBUG_EMAIL(("Deleted Items Folder record - "));
02455                     MALLOC_MESSAGESTORE(item);
02456                     LIST_COPY(item->message_store->deleted_items_folder, (pst_entryid*));
02457                     LE32_CPU(item->message_store->deleted_items_folder->id);
02458                     DEBUG_EMAIL(("[id = %#x]\n", item->message_store->deleted_items_folder->id));
02459                     break;
02460                 case 0x35E4: // PR_IPM_SENTMAIL_ENTRYID
02461                     DEBUG_EMAIL(("Sent Items Folder record - "));
02462                     MALLOC_MESSAGESTORE(item);
02463                     LIST_COPY(item->message_store->sent_items_folder, (pst_entryid*));
02464                     LE32_CPU(item->message_store->sent_items_folder->id);
02465                     DEBUG_EMAIL(("[id = %#x]\n", item->message_store->sent_items_folder->id));
02466                     break;
02467                 case 0x35E5: // PR_VIEWS_ENTRYID
02468                     DEBUG_EMAIL(("User Views Folder record - "));
02469                     MALLOC_MESSAGESTORE(item);
02470                     LIST_COPY(item->message_store->user_views_folder, (pst_entryid*));
02471                     LE32_CPU(item->message_store->user_views_folder->id);
02472                     DEBUG_EMAIL(("[id = %#x]\n", item->message_store->user_views_folder->id));
02473                     break;
02474                 case 0x35E6: // PR_COMMON_VIEWS_ENTRYID
02475                     DEBUG_EMAIL(("Common View Folder record - "));
02476                     MALLOC_MESSAGESTORE(item);
02477                     LIST_COPY(item->message_store->common_view_folder, (pst_entryid*));
02478                     LE32_CPU(item->message_store->common_view_folder->id);
02479                     DEBUG_EMAIL(("[id = %#x]\n", item->message_store->common_view_folder->id));
02480                     break;
02481                 case 0x35E7: // PR_FINDER_ENTRYID
02482                     DEBUG_EMAIL(("Search Root Folder record - "));
02483                     MALLOC_MESSAGESTORE(item);
02484                     LIST_COPY(item->message_store->search_root_folder, (pst_entryid*));
02485                     LE32_CPU(item->message_store->search_root_folder->id);
02486                     DEBUG_EMAIL(("[id = %#x]\n", item->message_store->search_root_folder->id));
02487                     break;
02488                 case 0x3602: // PR_CONTENT_COUNT Number of emails stored in a folder
02489                     DEBUG_EMAIL(("Folder Email Count - "));
02490                     MALLOC_FOLDER(item);
02491                     memcpy(&(item->folder->email_count), list->items[x]->data, sizeof(item->folder->email_count));
02492                     LE32_CPU(item->folder->email_count);
02493                     DEBUG_EMAIL(("%i\n", item->folder->email_count));
02494                     break;
02495                 case 0x3603: // PR_CONTENT_UNREAD Number of unread emails
02496                     DEBUG_EMAIL(("Unread Email Count - "));
02497                     MALLOC_FOLDER(item);
02498                     memcpy(&(item->folder->unseen_email_count), list->items[x]->data, sizeof(item->folder->unseen_email_count));
02499                     LE32_CPU(item->folder->unseen_email_count);
02500                     DEBUG_EMAIL(("%i\n", item->folder->unseen_email_count));
02501                     break;
02502                 case 0x360A: // PR_SUBFOLDERS Has children
02503                     DEBUG_EMAIL(("Has Subfolders - "));
02504                     MALLOC_FOLDER(item);
02505                     if (*(int16_t*)list->items[x]->data) {
02506                         DEBUG_EMAIL(("True\n"));
02507                         item->folder->subfolder = 1;
02508                     } else {
02509                         DEBUG_EMAIL(("False\n"));
02510                         item->folder->subfolder = 0;
02511                     }
02512                     break;
02513                 case 0x3613: // PR_CONTAINER_CLASS IPF.x
02514                     DEBUG_EMAIL(("IPF.x - "));
02515                     LIST_COPY(item->ascii_type, (char*));
02516                     if (strncmp("IPF.Note", item->ascii_type, 8) == 0)
02517                         item->type = PST_TYPE_NOTE;
02518                     else if (strncmp("IPF.Contact", item->ascii_type, 11) == 0)
02519                         item->type = PST_TYPE_CONTACT;
02520                     else if (strncmp("IPF.Journal", item->ascii_type, 11) == 0)
02521                         item->type = PST_TYPE_JOURNAL;
02522                     else if (strncmp("IPF.Appointment", item->ascii_type, 15) == 0)
02523                         item->type = PST_TYPE_APPOINTMENT;
02524                     else if (strncmp("IPF.StickyNote", item->ascii_type, 14) == 0)
02525                         item->type = PST_TYPE_STICKYNOTE;
02526                     else if (strncmp("IPF.Task", item->ascii_type, 8) == 0)
02527                         item->type = PST_TYPE_TASK;
02528                     else
02529                         item->type = PST_TYPE_OTHER;
02530 
02531                     DEBUG_EMAIL(("%s [%i]\n", item->ascii_type, item->type));
02532                     break;
02533                 case 0x3617: // PR_ASSOC_CONTENT_COUNT
02534                     // associated content are items that are attached to this folder
02535                     // but are hidden from users
02536                     DEBUG_EMAIL(("Associate Content count - "));
02537                     MALLOC_FOLDER(item);
02538                     memcpy(&(item->folder->assoc_count), list->items[x]->data, sizeof(item->folder->assoc_count));
02539                     LE32_CPU(item->folder->assoc_count);
02540                     DEBUG_EMAIL(("%i [%#x]\n", item->folder->assoc_count, item->folder->assoc_count));
02541                     break;
02542                 case 0x3701: // PR_ATTACH_DATA_OBJ binary data of attachment
02543                     DEBUG_EMAIL(("Binary Data [Size %i] - ", list->items[x]->size));
02544                     NULL_CHECK(attach);
02545                     MOVE_NEXT(attach);
02546                     if (!list->items[x]->data) { //special case
02547                         attach->id2_val = list->items[x]->type;
02548                         DEBUG_EMAIL(("Seen a Reference. The data hasn't been loaded yet. [%#"PRIx64"][%#x]\n",
02549                                  attach->id2_val, list->items[x]->type));
02550                     } else {
02551                         LIST_COPY(attach->data, (char*));
02552                         attach->size = list->items[x]->size;
02553                         DEBUG_EMAIL(("NOT PRINTED\n"));
02554                     }
02555                     break;
02556                 case 0x3704: // PR_ATTACH_FILENAME Attachment filename (8.3)
02557                     DEBUG_EMAIL(("Attachment Filename - "));
02558                     NULL_CHECK(attach);
02559                     MOVE_NEXT(attach);
02560                     LIST_COPY(attach->filename1, (char*));
02561                     DEBUG_EMAIL(("%s\n", attach->filename1));
02562                     break;
02563                 case 0x3705: // PR_ATTACH_METHOD
02564                     // 0 - No Attachment
02565                     // 1 - Attach by Value
02566                     // 2 - Attach by reference
02567                     // 3 - Attach by ref resolve
02568                     // 4 - Attach by ref only
02569                     // 5 - Embedded Message
02570                     // 6 - OLE
02571                     DEBUG_EMAIL(("Attachment method - "));
02572                     NULL_CHECK(attach);
02573                     MOVE_NEXT(attach);
02574                     memcpy(&(attach->method), list->items[x]->data, sizeof(attach->method));
02575                     LE32_CPU(attach->method);
02576                     t = attach->method;
02577                     DEBUG_EMAIL(("%s [%i]\n", (t==0?"No Attachment":
02578                                    (t==1?"Attach By Value":
02579                                     (t==2?"Attach By Reference":
02580                                      (t==3?"Attach by Ref. Resolve":
02581                                       (t==4?"Attach by Ref. Only":
02582                                        (t==5?"Embedded Message":"OLE")))))),t));
02583                     break;
02584                 case 0x3707: // PR_ATTACH_LONG_FILENAME Attachment filename (long?)
02585                     DEBUG_EMAIL(("Attachment Filename long - "));
02586                     NULL_CHECK(attach);
02587                     MOVE_NEXT(attach);
02588                     LIST_COPY(attach->filename2, (char*));
02589                     DEBUG_EMAIL(("%s\n", attach->filename2));
02590                     break;
02591                 case 0x370B: // PR_RENDERING_POSITION
02592                     // position in characters that the attachment appears in the plain text body
02593                     DEBUG_EMAIL(("Attachment Position - "));
02594                     NULL_CHECK(attach);
02595                     MOVE_NEXT(attach);
02596                     memcpy(&(attach->position), list->items[x]->data, sizeof(attach->position));
02597                     LE32_CPU(attach->position);
02598                     DEBUG_EMAIL(("%i [%#x]\n", attach->position));
02599                     break;
02600                 case 0x370E: // PR_ATTACH_MIME_TAG Mime type of encoding
02601                     DEBUG_EMAIL(("Attachment mime encoding - "));
02602                     NULL_CHECK(attach);
02603                     MOVE_NEXT(attach);
02604                     LIST_COPY(attach->mimetype, (char*));
02605                     DEBUG_EMAIL(("%s\n", attach->mimetype));
02606                     break;
02607                 case 0x3710: // PR_ATTACH_MIME_SEQUENCE
02608                     // sequence number for mime parts. Includes body
02609                     DEBUG_EMAIL(("Attachment Mime Sequence - "));
02610                     NULL_CHECK(attach);
02611                     MOVE_NEXT(attach);
02612                     memcpy(&(attach->sequence), list->items[x]->data, sizeof(attach->sequence));
02613                     LE32_CPU(attach->sequence);
02614                     DEBUG_EMAIL(("%i\n", attach->sequence));
02615                     break;
02616                 case 0x3A00: // PR_ACCOUNT
02617                     DEBUG_EMAIL(("Contact's Account name - "));
02618                     MALLOC_CONTACT(item);
02619                     LIST_COPY(item->contact->account_name, (char*));
02620                     DEBUG_EMAIL(("%s\n", item->contact->account_name));
02621                     break;
02622                 case 0x3A01: // PR_ALTERNATE_RECIPIENT
02623                     DEBUG_EMAIL(("Contact Alternate Recipient - NOT PROCESSED\n"));
02624                     break;
02625                 case 0x3A02: // PR_CALLBACK_TELEPHONE_NUMBER
02626                     DEBUG_EMAIL(("Callback telephone number - "));
02627                     MALLOC_CONTACT(item);
02628                     LIST_COPY(item->contact->callback_phone, (char*));
02629                     DEBUG_EMAIL(("%s\n", item->contact->callback_phone));
02630                     break;
02631                 case 0x3A03: // PR_CONVERSION_PROHIBITED
02632                     DEBUG_EMAIL(("Message Conversion Prohibited - "));
02633                     MALLOC_EMAIL(item);
02634                     if (*(int16_t*)list->items[x]->data) {
02635                         DEBUG_EMAIL(("True\n"));
02636                         item->email->conversion_prohib = 1;
02637                     } else {
02638                         DEBUG_EMAIL(("False\n"));
02639                         item->email->conversion_prohib = 0;
02640                     }
02641                     break;
02642                 case 0x3A05: // PR_GENERATION suffix
02643                     DEBUG_EMAIL(("Contacts Suffix - "));
02644                     MALLOC_CONTACT(item);
02645                     LIST_COPY(item->contact->suffix, (char*));
02646                     DEBUG_EMAIL(("%s\n", item->contact->suffix));
02647                     break;
02648                 case 0x3A06: // PR_GIVEN_NAME Contact's first name
02649                     DEBUG_EMAIL(("Contacts First Name - "));
02650                     MALLOC_CONTACT(item);
02651                     LIST_COPY(item->contact->first_name, (char*));
02652                     DEBUG_EMAIL(("%s\n", item->contact->first_name));
02653                     break;
02654                 case 0x3A07: // PR_GOVERNMENT_ID_NUMBER
02655                     DEBUG_EMAIL(("Contacts Government ID Number - "));
02656                     MALLOC_CONTACT(item);
02657                     LIST_COPY(item->contact->gov_id, (char*));
02658                     DEBUG_EMAIL(("%s\n", item->contact->gov_id));
02659                     break;
02660                 case 0x3A08: // PR_BUSINESS_TELEPHONE_NUMBER
02661                     DEBUG_EMAIL(("Business Telephone Number - "));
02662                     MALLOC_CONTACT(item);
02663                     LIST_COPY(item->contact->business_phone, (char*));
02664                     DEBUG_EMAIL(("%s\n", item->contact->business_phone));
02665                     break;
02666                 case 0x3A09: // PR_HOME_TELEPHONE_NUMBER
02667                     DEBUG_EMAIL(("Home Telephone Number - "));
02668                     MALLOC_CONTACT(item);
02669                     LIST_COPY(item->contact->home_phone, (char*));
02670                     DEBUG_EMAIL(("%s\n", item->contact->home_phone));
02671                     break;
02672                 case 0x3A0A: // PR_INITIALS Contact's Initials
02673                     DEBUG_EMAIL(("Contacts Initials - "));
02674                     MALLOC_CONTACT(item);
02675                     LIST_COPY(item->contact->initials, (char*));
02676                     DEBUG_EMAIL(("%s\n", item->contact->initials));
02677                     break;
02678                 case 0x3A0B: // PR_KEYWORD
02679                     DEBUG_EMAIL(("Keyword - "));
02680                     MALLOC_CONTACT(item);
02681                     LIST_COPY(item->contact->keyword, (char*));
02682                     DEBUG_EMAIL(("%s\n", item->contact->keyword));
02683                     break;
02684                 case 0x3A0C: // PR_LANGUAGE
02685                     DEBUG_EMAIL(("Contact's Language - "));
02686                     MALLOC_CONTACT(item);
02687                     LIST_COPY(item->contact->language, (char*));
02688                     DEBUG_EMAIL(("%s\n", item->contact->language));
02689                     break;
02690                 case 0x3A0D: // PR_LOCATION
02691                     DEBUG_EMAIL(("Contact's Location - "));
02692                     MALLOC_CONTACT(item);
02693                     LIST_COPY(item->contact->location, (char*));
02694                     DEBUG_EMAIL(("%s\n", item->contact->location));
02695                     break;
02696                 case 0x3A0E: // PR_MAIL_PERMISSION - Can the recipient receive and send email
02697                     DEBUG_EMAIL(("Mail Permission - "));
02698                     MALLOC_CONTACT(item);
02699                     if (*(int16_t*)list->items[x]->data) {
02700                         DEBUG_EMAIL(("True\n"));
02701                         item->contact->mail_permission = 1;
02702                     } else {
02703                         DEBUG_EMAIL(("False\n"));
02704                         item->contact->mail_permission = 0;
02705                     }
02706                     break;
02707                 case 0x3A0F: // PR_MHS_COMMON_NAME
02708                     DEBUG_EMAIL(("MHS Common Name - "));
02709                     MALLOC_EMAIL(item);
02710                     LIST_COPY(item->email->common_name, (char*));
02711                     DEBUG_EMAIL(("%s\n", item->email->common_name));
02712                     break;
02713                 case 0x3A10: // PR_ORGANIZATIONAL_ID_NUMBER
02714                     DEBUG_EMAIL(("Organizational ID # - "));
02715                     MALLOC_CONTACT(item);
02716                     LIST_COPY(item->contact->org_id, (char*));
02717                     DEBUG_EMAIL(("%s\n", item->contact->org_id));
02718                     break;
02719                 case 0x3A11: // PR_SURNAME Contact's Surname
02720                     DEBUG_EMAIL(("Contacts Surname - "));
02721                     MALLOC_CONTACT(item);
02722                     LIST_COPY(item->contact->surname, (char*));
02723                     DEBUG_EMAIL(("%s\n", item->contact->surname));
02724                     break;
02725                 case 0x3A12: // PR_ORIGINAL_ENTRY_ID
02726                     DEBUG_EMAIL(("Original Entry ID - NOT PROCESSED\n"));
02727                     break;
02728                 case 0x3A13: // PR_ORIGINAL_DISPLAY_NAME
02729                     DEBUG_EMAIL(("Original Display Name - NOT PROCESSED\n"));
02730                     break;
02731                 case 0x3A14: // PR_ORIGINAL_SEARCH_KEY
02732                     DEBUG_EMAIL(("Original Search Key - NOT PROCESSED\n"));
02733                     break;
02734                 case 0x3A15: // PR_POSTAL_ADDRESS
02735                     DEBUG_EMAIL(("Default Postal Address - "));
02736                     MALLOC_CONTACT(item);
02737                     LIST_COPY(item->contact->def_postal_address, (char*));
02738                     DEBUG_EMAIL(("%s\n", item->contact->def_postal_address));
02739                     break;
02740                 case 0x3A16: // PR_COMPANY_NAME
02741                     DEBUG_EMAIL(("Company Name - "));
02742                     MALLOC_CONTACT(item);
02743                     LIST_COPY(item->contact->company_name, (char*));
02744                     DEBUG_EMAIL(("%s\n", item->contact->company_name));
02745                     break;
02746                 case 0x3A17: // PR_TITLE - Job Title
02747                     DEBUG_EMAIL(("Job Title - "));
02748                     MALLOC_CONTACT(item);
02749                     LIST_COPY(item->contact->job_title, (char*));
02750                     DEBUG_EMAIL(("%s\n", item->contact->job_title));
02751                     break;
02752                 case 0x3A18: // PR_DEPARTMENT_NAME
02753                     DEBUG_EMAIL(("Department Name - "));
02754                     MALLOC_CONTACT(item);
02755                     LIST_COPY(item->contact->department, (char*));
02756                     DEBUG_EMAIL(("%s\n", item->contact->department));
02757                     break;
02758                 case 0x3A19: // PR_OFFICE_LOCATION
02759                     DEBUG_EMAIL(("Office Location - "));
02760                     MALLOC_CONTACT(item);
02761                     LIST_COPY(item->contact->office_loc, (char*));
02762                     DEBUG_EMAIL(("%s\n", item->contact->office_loc));
02763                     break;
02764                 case 0x3A1A: // PR_PRIMARY_TELEPHONE_NUMBER
02765                     DEBUG_EMAIL(("Primary Telephone - "));
02766                     MALLOC_CONTACT(item);
02767                     LIST_COPY(item->contact->primary_phone, (char*));
02768                     DEBUG_EMAIL(("%s\n", item->contact->primary_phone));
02769                     break;
02770                 case 0x3A1B: // PR_BUSINESS2_TELEPHONE_NUMBER
02771                     DEBUG_EMAIL(("Business Phone Number 2 - "));
02772                     MALLOC_CONTACT(item);
02773                     LIST_COPY(item->contact->business_phone2, (char*));
02774                     DEBUG_EMAIL(("%s\n", item->contact->business_phone2));
02775                     break;
02776                 case 0x3A1C: // PR_MOBILE_TELEPHONE_NUMBER
02777                     DEBUG_EMAIL(("Mobile Phone Number - "));
02778                     MALLOC_CONTACT(item);
02779                     LIST_COPY(item->contact->mobile_phone, (char*));
02780                     DEBUG_EMAIL(("%s\n", item->contact->mobile_phone));
02781                     break;
02782                 case 0x3A1D: // PR_RADIO_TELEPHONE_NUMBER
02783                     DEBUG_EMAIL(("Radio Phone Number - "));
02784                     MALLOC_CONTACT(item);
02785                     LIST_COPY(item->contact->radio_phone, (char*));
02786                     DEBUG_EMAIL(("%s\n", item->contact->radio_phone));
02787                     break;
02788                 case 0x3A1E: // PR_CAR_TELEPHONE_NUMBER
02789                     DEBUG_EMAIL(("Car Phone Number - "));
02790                     MALLOC_CONTACT(item);
02791                     LIST_COPY(item->contact->car_phone, (char*));
02792                     DEBUG_EMAIL(("%s\n", item->contact->car_phone));
02793                     break;
02794                 case 0x3A1F: // PR_OTHER_TELEPHONE_NUMBER
02795                     DEBUG_EMAIL(("Other Phone Number - "));
02796                     MALLOC_CONTACT(item);
02797                     LIST_COPY(item->contact->other_phone, (char*));
02798                     DEBUG_EMAIL(("%s\n", item->contact->other_phone));
02799                     break;
02800                 case 0x3A20: // PR_TRANSMITTABLE_DISPLAY_NAME
02801                     DEBUG_EMAIL(("Transmittable Display Name - "));
02802                     MALLOC_CONTACT(item);
02803                     LIST_COPY(item->contact->transmittable_display_name, (char*));
02804                     DEBUG_EMAIL(("%s\n", item->contact->transmittable_display_name));
02805                     break;
02806                 case 0x3A21: // PR_PAGER_TELEPHONE_NUMBER
02807                     DEBUG_EMAIL(("Pager Phone Number - "));
02808                     MALLOC_CONTACT(item);
02809                     LIST_COPY(item->contact->pager_phone, (char*));
02810                     DEBUG_EMAIL(("%s\n", item->contact->pager_phone));
02811                     break;
02812                 case 0x3A22: // PR_USER_CERTIFICATE
02813                     DEBUG_EMAIL(("User Certificate - NOT PROCESSED"));
02814                     break;
02815                 case 0x3A23: // PR_PRIMARY_FAX_NUMBER
02816                     DEBUG_EMAIL(("Primary Fax Number - "));
02817                     MALLOC_CONTACT(item);
02818                     LIST_COPY(item->contact->primary_fax, (char*));
02819                     DEBUG_EMAIL(("%s\n", item->contact->primary_fax));
02820                     break;
02821                 case 0x3A24: // PR_BUSINESS_FAX_NUMBER
02822                     DEBUG_EMAIL(("Business Fax Number - "));
02823                     MALLOC_CONTACT(item);
02824                     LIST_COPY(item->contact->business_fax, (char*));
02825                     DEBUG_EMAIL(("%s\n", item->contact->business_fax));
02826                     break;
02827                 case 0x3A25: // PR_HOME_FAX_NUMBER
02828                     DEBUG_EMAIL(("Home Fax Number - "));
02829                     MALLOC_CONTACT(item);
02830                     LIST_COPY(item->contact->home_fax, (char*));
02831                     DEBUG_EMAIL(("%s\n", item->contact->home_fax));
02832                     break;
02833                 case 0x3A26: // PR_BUSINESS_ADDRESS_COUNTRY
02834                     DEBUG_EMAIL(("Business Address Country - "));
02835                     MALLOC_CONTACT(item);
02836                     LIST_COPY(item->contact->business_country, (char*));
02837                     DEBUG_EMAIL(("%s\n", item->contact->business_country));
02838                     break;
02839                 case 0x3A27: // PR_BUSINESS_ADDRESS_CITY
02840                     DEBUG_EMAIL(("Business Address City - "));
02841                     MALLOC_CONTACT(item);
02842                     LIST_COPY(item->contact->business_city, (char*));
02843                     DEBUG_EMAIL(("%s\n", item->contact->business_city));
02844                     break;
02845                 case 0x3A28: // PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE
02846                     DEBUG_EMAIL(("Business Address State - "));
02847                     MALLOC_CONTACT(item);
02848                     LIST_COPY(item->contact->business_state, (char*));
02849                     DEBUG_EMAIL(("%s\n", item->contact->business_state));
02850                     break;
02851                 case 0x3A29: // PR_BUSINESS_ADDRESS_STREET
02852                     DEBUG_EMAIL(("Business Address Street - "));
02853                     MALLOC_CONTACT(item);
02854                     LIST_COPY(item->contact->business_street, (char*));
02855                     DEBUG_EMAIL(("%s\n", item->contact->business_street));
02856                     break;
02857                 case 0x3A2A: // PR_BUSINESS_POSTAL_CODE
02858                     DEBUG_EMAIL(("Business Postal Code - "));
02859                     MALLOC_CONTACT(item);
02860                     LIST_COPY(item->contact->business_postal_code, (char*));
02861                     DEBUG_EMAIL(("%s\n", item->contact->business_postal_code));
02862                     break;
02863                 case 0x3A2B: // PR_BUSINESS_PO_BOX
02864                     DEBUG_EMAIL(("Business PO Box - "));
02865                     MALLOC_CONTACT(item);
02866                     LIST_COPY(item->contact->business_po_box, (char*));
02867                     DEBUG_EMAIL(("%s\n", item->contact->business_po_box));
02868                     break;
02869                 case 0x3A2C: // PR_TELEX_NUMBER
02870                     DEBUG_EMAIL(("Telex Number - "));
02871                     MALLOC_CONTACT(item);
02872                     LIST_COPY(item->contact->telex, (char*));
02873                     DEBUG_EMAIL(("%s\n", item->contact->telex));
02874                     break;
02875                 case 0x3A2D: // PR_ISDN_NUMBER
02876                     DEBUG_EMAIL(("ISDN Number - "));
02877                     MALLOC_CONTACT(item);
02878                     LIST_COPY(item->contact->isdn_phone, (char*));
02879                     DEBUG_EMAIL(("%s\n", item->contact->isdn_phone));
02880                     break;
02881                 case 0x3A2E: // PR_ASSISTANT_TELEPHONE_NUMBER
02882                     DEBUG_EMAIL(("Assistant Phone Number - "));
02883                     MALLOC_CONTACT(item);
02884                     LIST_COPY(item->contact->assistant_phone, (char*));
02885                     DEBUG_EMAIL(("%s\n", item->contact->assistant_phone));
02886                     break;
02887                 case 0x3A2F: // PR_HOME2_TELEPHONE_NUMBER
02888                     DEBUG_EMAIL(("Home Phone 2 - "));
02889                     MALLOC_CONTACT(item);
02890                     LIST_COPY(item->contact->home_phone2, (char*));
02891                     DEBUG_EMAIL(("%s\n", item->contact->home_phone2));
02892                     break;
02893                 case 0x3A30: // PR_ASSISTANT
02894                     DEBUG_EMAIL(("Assistant's Name - "));
02895                     MALLOC_CONTACT(item);
02896                     LIST_COPY(item->contact->assistant_name, (char*));
02897                     DEBUG_EMAIL(("%s\n", item->contact->assistant_name));
02898                     break;
02899                 case 0x3A40: // PR_SEND_RICH_INFO
02900                     DEBUG_EMAIL(("Can receive Rich Text - "));
02901                     MALLOC_CONTACT(item);
02902                     if (*(int16_t*)list->items[x]->data) {
02903                         DEBUG_EMAIL(("True\n"));
02904                         item->contact->rich_text = 1;
02905                     } else {
02906                         DEBUG_EMAIL(("False\n"));
02907                         item->contact->rich_text = 0;
02908                     }
02909                     break;
02910                 case 0x3A41: // PR_WEDDING_ANNIVERSARY
02911                     DEBUG_EMAIL(("Wedding Anniversary - "));
02912                     MALLOC_CONTACT(item);
02913                     LIST_COPY_TIME(item->contact->wedding_anniversary);
02914                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->contact->wedding_anniversary)));
02915                     break;
02916                 case 0x3A42: // PR_BIRTHDAY
02917                     DEBUG_EMAIL(("Birthday - "));
02918                     MALLOC_CONTACT(item);
02919                     LIST_COPY_TIME(item->contact->birthday);
02920                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->contact->birthday)));
02921                     break;
02922                 case 0x3A43: // PR_HOBBIES
02923                     DEBUG_EMAIL(("Hobbies - "));
02924                     MALLOC_CONTACT(item);
02925                     LIST_COPY(item->contact->hobbies, (char*));
02926                     DEBUG_EMAIL(("%s\n", item->contact->hobbies));
02927                     break;
02928                 case 0x3A44: // PR_MIDDLE_NAME
02929                     DEBUG_EMAIL(("Middle Name - "));
02930                     MALLOC_CONTACT(item);
02931                     LIST_COPY(item->contact->middle_name, (char*));
02932                     DEBUG_EMAIL(("%s\n", item->contact->middle_name));
02933                     break;
02934                 case 0x3A45: // PR_DISPLAY_NAME_PREFIX
02935                     DEBUG_EMAIL(("Display Name Prefix (Title) - "));
02936                     MALLOC_CONTACT(item);
02937                     LIST_COPY(item->contact->display_name_prefix, (char*));
02938                     DEBUG_EMAIL(("%s\n", item->contact->display_name_prefix));
02939                     break;
02940                 case 0x3A46: // PR_PROFESSION
02941                     DEBUG_EMAIL(("Profession - "));
02942                     MALLOC_CONTACT(item);
02943                     LIST_COPY(item->contact->profession, (char*));
02944                     DEBUG_EMAIL(("%s\n", item->contact->profession));
02945                     break;
02946                 case 0x3A47: // PR_PREFERRED_BY_NAME
02947                     DEBUG_EMAIL(("Preferred By Name - "));
02948                     MALLOC_CONTACT(item);
02949                     LIST_COPY(item->contact->pref_name, (char*));
02950                     DEBUG_EMAIL(("%s\n", item->contact->pref_name));
02951                     break;
02952                 case 0x3A48: // PR_SPOUSE_NAME
02953                     DEBUG_EMAIL(("Spouse's Name - "));
02954                     MALLOC_CONTACT(item);
02955                     LIST_COPY(item->contact->spouse_name, (char*));
02956                     DEBUG_EMAIL(("%s\n", item->contact->spouse_name));
02957                     break;
02958                 case 0x3A49: // PR_COMPUTER_NETWORK_NAME
02959                     DEBUG_EMAIL(("Computer Network Name - "));
02960                     MALLOC_CONTACT(item);
02961                     LIST_COPY(item->contact->computer_name, (char*));
02962                     DEBUG_EMAIL(("%s\n", item->contact->computer_name));
02963                     break;
02964                 case 0x3A4A: // PR_CUSTOMER_ID
02965                     DEBUG_EMAIL(("Customer ID - "));
02966                     MALLOC_CONTACT(item);
02967                     LIST_COPY(item->contact->customer_id, (char*));
02968                     DEBUG_EMAIL(("%s\n", item->contact->customer_id));
02969                     break;
02970                 case 0x3A4B: // PR_TTYTDD_PHONE_NUMBER
02971                     DEBUG_EMAIL(("TTY/TDD Phone - "));
02972                     MALLOC_CONTACT(item);
02973                     LIST_COPY(item->contact->ttytdd_phone, (char*));
02974                     DEBUG_EMAIL(("%s\n", item->contact->ttytdd_phone));
02975                     break;
02976                 case 0x3A4C: // PR_FTP_SITE
02977                     DEBUG_EMAIL(("Ftp Site - "));
02978                     MALLOC_CONTACT(item);
02979                     LIST_COPY(item->contact->ftp_site, (char*));
02980                     DEBUG_EMAIL(("%s\n", item->contact->ftp_site));
02981                     break;
02982                 case 0x3A4D: // PR_GENDER
02983                     DEBUG_EMAIL(("Gender - "));
02984                     MALLOC_CONTACT(item);
02985                     memcpy(&item->contact->gender, list->items[x]->data, sizeof(item->contact->gender));
02986                     LE16_CPU(item->contact->gender);
02987                     switch(item->contact->gender) {
02988                         case 0:
02989                             DEBUG_EMAIL(("Unspecified\n"));
02990                             break;
02991                         case 1:
02992                             DEBUG_EMAIL(("Female\n"));
02993                             break;
02994                         case 2:
02995                             DEBUG_EMAIL(("Male\n"));
02996                             break;
02997                         default:
02998                             DEBUG_EMAIL(("Error processing\n"));
02999                     }
03000                     break;
03001                 case 0x3A4E: // PR_MANAGER_NAME
03002                     DEBUG_EMAIL(("Manager's Name - "));
03003                     MALLOC_CONTACT(item);
03004                     LIST_COPY(item->contact->manager_name, (char*));
03005                     DEBUG_EMAIL(("%s\n", item->contact->manager_name));
03006                     break;
03007                 case 0x3A4F: // PR_NICKNAME
03008                     DEBUG_EMAIL(("Nickname - "));
03009                     MALLOC_CONTACT(item);
03010                     LIST_COPY(item->contact->nickname, (char*));
03011                     DEBUG_EMAIL(("%s\n", item->contact->nickname));
03012                     break;
03013                 case 0x3A50: // PR_PERSONAL_HOME_PAGE
03014                     DEBUG_EMAIL(("Personal Home Page - "));
03015                     MALLOC_CONTACT(item);
03016                     LIST_COPY(item->contact->personal_homepage, (char*));
03017                     DEBUG_EMAIL(("%s\n", item->contact->personal_homepage));
03018                     break;
03019                 case 0x3A51: // PR_BUSINESS_HOME_PAGE
03020                     DEBUG_EMAIL(("Business Home Page - "));
03021                     MALLOC_CONTACT(item);
03022                     LIST_COPY(item->contact->business_homepage, (char*));
03023                     DEBUG_EMAIL(("%s\n", item->contact->business_homepage));
03024                     break;
03025                 case 0x3A57: // PR_COMPANY_MAIN_PHONE_NUMBER
03026                     DEBUG_EMAIL(("Company Main Phone - "));
03027                     MALLOC_CONTACT(item);
03028                     LIST_COPY(item->contact->company_main_phone, (char*));
03029                     DEBUG_EMAIL(("%s\n", item->contact->company_main_phone));
03030                     break;
03031                 case 0x3A58: // PR_CHILDRENS_NAMES
03032                     DEBUG_EMAIL(("Children's Names - NOT PROCESSED\n"));
03033                     break;
03034                 case 0x3A59: // PR_HOME_ADDRESS_CITY
03035                     DEBUG_EMAIL(("Home Address City - "));
03036                     MALLOC_CONTACT(item);
03037                     LIST_COPY(item->contact->home_city, (char*));
03038                     DEBUG_EMAIL(("%s\n", item->contact->home_city));
03039                     break;
03040                 case 0x3A5A: // PR_HOME_ADDRESS_COUNTRY
03041                     DEBUG_EMAIL(("Home Address Country - "));
03042                     MALLOC_CONTACT(item);
03043                     LIST_COPY(item->contact->home_country, (char*));
03044                     DEBUG_EMAIL(("%s\n", item->contact->home_country));
03045                     break;
03046                 case 0x3A5B: // PR_HOME_ADDRESS_POSTAL_CODE
03047                     DEBUG_EMAIL(("Home Address Postal Code - "));
03048                     MALLOC_CONTACT(item);
03049                     LIST_COPY(item->contact->home_postal_code, (char*));
03050                     DEBUG_EMAIL(("%s\n", item->contact->home_postal_code));
03051                     break;
03052                 case 0x3A5C: // PR_HOME_ADDRESS_STATE_OR_PROVINCE
03053                     DEBUG_EMAIL(("Home Address State or Province - "));
03054                     MALLOC_CONTACT(item);
03055                     LIST_COPY(item->contact->home_state, (char*));
03056                     DEBUG_EMAIL(("%s\n", item->contact->home_state));
03057                     break;
03058                 case 0x3A5D: // PR_HOME_ADDRESS_STREET
03059                     DEBUG_EMAIL(("Home Address Street - "));
03060                     MALLOC_CONTACT(item);
03061                     LIST_COPY(item->contact->home_street, (char*));
03062                     DEBUG_EMAIL(("%s\n", item->contact->home_street));
03063                     break;
03064                 case 0x3A5E: // PR_HOME_ADDRESS_POST_OFFICE_BOX
03065                     DEBUG_EMAIL(("Home Address Post Office Box - "));
03066                     MALLOC_CONTACT(item);
03067                     LIST_COPY(item->contact->home_po_box, (char*));
03068                     DEBUG_EMAIL(("%s\n", item->contact->home_po_box));
03069                     break;
03070                 case 0x3A5F: // PR_OTHER_ADDRESS_CITY
03071                     DEBUG_EMAIL(("Other Address City - "));
03072                     MALLOC_CONTACT(item);
03073                     LIST_COPY(item->contact->other_city, (char*));
03074                     DEBUG_EMAIL(("%s\n", item->contact->other_city));
03075                     break;
03076                 case 0x3A60: // PR_OTHER_ADDRESS_COUNTRY
03077                     DEBUG_EMAIL(("Other Address Country - "));
03078                     MALLOC_CONTACT(item);
03079                     LIST_COPY(item->contact->other_country, (char*));
03080                     DEBUG_EMAIL(("%s\n", item->contact->other_country));
03081                     break;
03082                 case 0x3A61: // PR_OTHER_ADDRESS_POSTAL_CODE
03083                     DEBUG_EMAIL(("Other Address Postal Code - "));
03084                     MALLOC_CONTACT(item);
03085                     LIST_COPY(item->contact->other_postal_code, (char*));
03086                     DEBUG_EMAIL(("%s\n", item->contact->other_postal_code));
03087                     break;
03088                 case 0x3A62: // PR_OTHER_ADDRESS_STATE_OR_PROVINCE
03089                     DEBUG_EMAIL(("Other Address State - "));
03090                     MALLOC_CONTACT(item);
03091                     LIST_COPY(item->contact->other_state, (char*));
03092                     DEBUG_EMAIL(("%s\n", item->contact->other_state));
03093                     break;
03094                 case 0x3A63: // PR_OTHER_ADDRESS_STREET
03095                     DEBUG_EMAIL(("Other Address Street - "));
03096                     MALLOC_CONTACT(item);
03097                     LIST_COPY(item->contact->other_street, (char*));
03098                     DEBUG_EMAIL(("%s\n", item->contact->other_street));
03099                     break;
03100                 case 0x3A64: // PR_OTHER_ADDRESS_POST_OFFICE_BOX
03101                     DEBUG_EMAIL(("Other Address Post Office box - "));
03102                     MALLOC_CONTACT(item);
03103                     LIST_COPY(item->contact->other_po_box, (char*));
03104                     DEBUG_EMAIL(("%s\n", item->contact->other_po_box));
03105                     break;
03106                 case 0x65E3: // Entry ID?
03107                     DEBUG_EMAIL(("Entry ID - "));
03108                     item->record_key = (char*) xmalloc(16+1);
03109                     memcpy(item->record_key, &(list->items[x]->data[1]), 16); //skip first byte
03110                     item->record_key[16]='\0';
03111                     item->record_key_size=16;
03112                     DEBUG_EMAIL_HEXPRINT((char*)item->record_key, 16);
03113                     break;
03114                 case 0x67F2: // ID2 value of the attachments proper record
03115                     DEBUG_EMAIL(("Attachment ID2 value - "));
03116                     if (attach) {
03117                         uint32_t tempid;
03118                         MOVE_NEXT(attach);
03119                         memcpy(&(tempid), list->items[x]->data, sizeof(tempid));
03120                         LE32_CPU(tempid);
03121                         attach->id2_val = tempid;
03122                         DEBUG_EMAIL(("%#"PRIx64"\n", attach->id2_val));
03123                     } else {
03124                         DEBUG_EMAIL(("NOT AN ATTACHMENT: %#x\n", list->items[x]->id));
03125                     }
03126                     break;
03127                 case 0x67FF: // Extra Property Identifier (Password CheckSum)
03128                     DEBUG_EMAIL(("Password checksum [0x67FF] - "));
03129                     MALLOC_MESSAGESTORE(item);
03130                     memcpy(&(item->message_store->pwd_chksum), list->items[x]->data, sizeof(item->message_store->pwd_chksum));
03131                     DEBUG_EMAIL(("%#x\n", item->message_store->pwd_chksum));
03132                     break;
03133                 case 0x6F02: // Secure HTML Body
03134                     DEBUG_EMAIL(("Secure HTML Body - "));
03135                     MALLOC_EMAIL(item);
03136                     LIST_COPY(item->email->encrypted_htmlbody, (char*));
03137                     item->email->encrypted_htmlbody_size = list->items[x]->size;
03138                     DEBUG_EMAIL(("Not Printed\n"));
03139                     break;
03140                 case 0x6F04: // Secure Text Body
03141                     DEBUG_EMAIL(("Secure Text Body - "));
03142                     MALLOC_EMAIL(item);
03143                     LIST_COPY(item->email->encrypted_body, (char*));
03144                     item->email->encrypted_body_size = list->items[x]->size;
03145                     DEBUG_EMAIL(("Not Printed\n"));
03146                     break;
03147                 case 0x7C07: // top of folders ENTRYID
03148                     DEBUG_EMAIL(("Top of folders RecID [0x7c07] - "));
03149                     MALLOC_MESSAGESTORE(item);
03150                     item->message_store->top_of_folder = (pst_entryid*) xmalloc(sizeof(pst_entryid));
03151                     memcpy(item->message_store->top_of_folder, list->items[x]->data, sizeof(pst_entryid));
03152                     LE32_CPU(item->message_store->top_of_folder->u1);
03153                     LE32_CPU(item->message_store->top_of_folder->id);
03154                     DEBUG_EMAIL(("u1 %#x id %#x\n", item->message_store->top_of_folder->u1, item->message_store->top_of_folder->id));
03155                     DEBUG_EMAIL_HEXPRINT((char*)item->message_store->top_of_folder->entryid, 16);
03156                     break;
03157                 case 0x8005: // Contact's Fullname
03158                     DEBUG_EMAIL(("Contact Fullname - "));
03159                     MALLOC_CONTACT(item);
03160                     LIST_COPY(item->contact->fullname, (char*));
03161                     DEBUG_EMAIL(("%s\n", item->contact->fullname));
03162                     break;
03163                 case 0x801A: // Full Home Address
03164                     DEBUG_EMAIL(("Home Address - "));
03165                     MALLOC_CONTACT(item);
03166                     LIST_COPY(item->contact->home_address, (char*));
03167                     DEBUG_EMAIL(("%s\n", item->contact->home_address));
03168                     break;
03169                 case 0x801B: // Full Business Address
03170                     DEBUG_EMAIL(("Business Address - "));
03171                     MALLOC_CONTACT(item);
03172                     LIST_COPY(item->contact->business_address, (char*));
03173                     DEBUG_EMAIL(("%s\n", item->contact->business_address));
03174                     break;
03175                 case 0x801C: // Full Other Address
03176                     DEBUG_EMAIL(("Other Address - "));
03177                     MALLOC_CONTACT(item);
03178                     LIST_COPY(item->contact->other_address, (char*));
03179                     DEBUG_EMAIL(("%s\n", item->contact->other_address));
03180                     break;
03181                 case 0x8045: // Work address street
03182                     DEBUG_EMAIL(("Work address street - "));
03183                     MALLOC_CONTACT(item);
03184                     LIST_COPY(item->contact->work_address_street, (char*));
03185                     DEBUG_EMAIL(("%s\n", item->contact->work_address_street));
03186                     break;
03187                 case 0x8046: // Work address city
03188                     DEBUG_EMAIL(("Work address city - "));
03189                     MALLOC_CONTACT(item);
03190                     LIST_COPY(item->contact->work_address_city, (char*));
03191                     DEBUG_EMAIL(("%s\n", item->contact->work_address_city));
03192                     break;
03193                 case 0x8047: // Work address state
03194                     DEBUG_EMAIL(("Work address state - "));
03195                     MALLOC_CONTACT(item);
03196                     LIST_COPY(item->contact->work_address_state, (char*));
03197                     DEBUG_EMAIL(("%s\n", item->contact->work_address_state));
03198                     break;
03199                 case 0x8048: // Work address postalcode
03200                     DEBUG_EMAIL(("Work address postalcode - "));
03201                     MALLOC_CONTACT(item);
03202                     LIST_COPY(item->contact->work_address_postalcode, (char*));
03203                     DEBUG_EMAIL(("%s\n", item->contact->work_address_postalcode));
03204                     break;
03205                 case 0x8049: // Work address country
03206                     DEBUG_EMAIL(("Work address country - "));
03207                     MALLOC_CONTACT(item);
03208                     LIST_COPY(item->contact->work_address_country, (char*));
03209                     DEBUG_EMAIL(("%s\n", item->contact->work_address_country));
03210                     break;
03211                 case 0x804A: // Work address postofficebox
03212                     DEBUG_EMAIL(("Work address postofficebox - "));
03213                     MALLOC_CONTACT(item);
03214                     LIST_COPY(item->contact->work_address_postofficebox, (char*));
03215                     DEBUG_EMAIL(("%s\n", item->contact->work_address_postofficebox));
03216                     break;
03217                 case 0x8082: // Email Address 1 Transport
03218                     DEBUG_EMAIL(("Email Address 1 Transport - "));
03219                     MALLOC_CONTACT(item);
03220                     LIST_COPY(item->contact->address1_transport, (char*));
03221                     DEBUG_EMAIL(("|%s|\n", item->contact->address1_transport));
03222                     break;
03223                 case 0x8083: // Email Address 1 Address
03224                     DEBUG_EMAIL(("Email Address 1 Address - "));
03225                     MALLOC_CONTACT(item);
03226                     LIST_COPY(item->contact->address1, (char*));
03227                     DEBUG_EMAIL(("|%s|\n", item->contact->address1));
03228                     break;
03229                 case 0x8084: // Email Address 1 Description
03230                     DEBUG_EMAIL(("Email Address 1 Description - "));
03231                     MALLOC_CONTACT(item);
03232                     LIST_COPY(item->contact->address1_desc, (char*));
03233                     DEBUG_EMAIL(("|%s|\n", item->contact->address1_desc));
03234                     break;
03235                 case 0x8085: // Email Address 1 Record
03236                     DEBUG_EMAIL(("Email Address 1 Record - "));
03237                     MALLOC_CONTACT(item);
03238                     LIST_COPY(item->contact->address1a, (char*));
03239                     DEBUG_EMAIL(("|%s|\n", item->contact->address1a));
03240                     break;
03241                 case 0x8092: // Email Address 2 Transport
03242                     DEBUG_EMAIL(("Email Address 2 Transport - "));
03243                     MALLOC_CONTACT(item);
03244                     LIST_COPY(item->contact->address2_transport, (char*));
03245                     DEBUG_EMAIL(("|%s|\n", item->contact->address2_transport));
03246                     break;
03247                 case 0x8093: // Email Address 2 Address
03248                     DEBUG_EMAIL(("Email Address 2 Address - "));
03249                     MALLOC_CONTACT(item);
03250                     LIST_COPY(item->contact->address2, (char*));
03251                     DEBUG_EMAIL(("|%s|\n", item->contact->address2));
03252                     break;
03253                 case 0x8094: // Email Address 2 Description
03254                     DEBUG_EMAIL (("Email Address 2 Description - "));
03255                     MALLOC_CONTACT(item);
03256                     LIST_COPY(item->contact->address2_desc, (char*));
03257                     DEBUG_EMAIL(("|%s|\n", item->contact->address2_desc));
03258                     break;
03259                 case 0x8095: // Email Address 2 Record
03260                     DEBUG_EMAIL(("Email Address 2 Record - "));
03261                     MALLOC_CONTACT(item);
03262                     LIST_COPY(item->contact->address2a, (char*));
03263                     DEBUG_EMAIL(("|%s|\n", item->contact->address2a));
03264                     break;
03265                 case 0x80A2: // Email Address 3 Transport
03266                     DEBUG_EMAIL (("Email Address 3 Transport - "));
03267                     MALLOC_CONTACT(item);
03268                     LIST_COPY(item->contact->address3_transport, (char*));
03269                     DEBUG_EMAIL(("|%s|\n", item->contact->address3_transport));
03270                     break;
03271                 case 0x80A3: // Email Address 3 Address
03272                     DEBUG_EMAIL(("Email Address 3 Address - "));
03273                     MALLOC_CONTACT(item);
03274                     LIST_COPY(item->contact->address3, (char*));
03275                     DEBUG_EMAIL(("|%s|\n", item->contact->address3));
03276                     break;
03277                 case 0x80A4: // Email Address 3 Description
03278                     DEBUG_EMAIL(("Email Address 3 Description - "));
03279                     MALLOC_CONTACT(item);
03280                     LIST_COPY(item->contact->address3_desc, (char*));
03281                     DEBUG_EMAIL(("|%s|\n", item->contact->address3_desc));
03282                     break;
03283                 case 0x80A5: // Email Address 3 Record
03284                     DEBUG_EMAIL(("Email Address 3 Record - "));
03285                     MALLOC_CONTACT(item);
03286                     LIST_COPY(item->contact->address3a, (char*));
03287                     DEBUG_EMAIL(("|%s|\n", item->contact->address3a));
03288                     break;
03289                 case 0x80D8: // Internet Free/Busy
03290                     DEBUG_EMAIL(("Internet Free/Busy - "));
03291                     MALLOC_CONTACT(item);
03292                     LIST_COPY(item->contact->free_busy_address, (char*));
03293                     DEBUG_EMAIL(("%s\n", item->contact->free_busy_address));
03294                     break;
03295                 case 0x8205: // Show on Free/Busy as
03296                     // 0: Free
03297                     // 1: Tentative
03298                     // 2: Busy
03299                     // 3: Out Of Office
03300                     DEBUG_EMAIL(("Appointment shows as - "));
03301                     MALLOC_APPOINTMENT(item);
03302                     memcpy(&(item->appointment->showas), list->items[x]->data, sizeof(item->appointment->showas));
03303                     LE32_CPU(item->appointment->showas);
03304                     switch (item->appointment->showas) {
03305                         case PST_FREEBUSY_FREE:
03306                             DEBUG_EMAIL(("Free\n")); break;
03307                         case PST_FREEBUSY_TENTATIVE:
03308                             DEBUG_EMAIL(("Tentative\n")); break;
03309                         case PST_FREEBUSY_BUSY:
03310                             DEBUG_EMAIL(("Busy\n")); break;
03311                         case PST_FREEBUSY_OUT_OF_OFFICE:
03312                             DEBUG_EMAIL(("Out Of Office\n")); break;
03313                         default:
03314                             DEBUG_EMAIL(("Unknown Value: %d\n", item->appointment->showas)); break;
03315                     }
03316                     break;
03317                 case 0x8208: // Location of an appointment
03318                     DEBUG_EMAIL(("Appointment Location - "));
03319                     MALLOC_APPOINTMENT(item);
03320                     LIST_COPY(item->appointment->location, (char*));
03321                     DEBUG_EMAIL(("%s\n", item->appointment->location));
03322                     break;
03323                 case 0x820d: // Appointment start
03324                     DEBUG_EMAIL(("Appointment Date Start - "));
03325                     MALLOC_APPOINTMENT(item);
03326                     LIST_COPY_TIME(item->appointment->start);
03327                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->appointment->start)));
03328                     break;
03329                 case 0x820e: // Appointment end
03330                     DEBUG_EMAIL(("Appointment Date End - "));
03331                     MALLOC_APPOINTMENT(item);
03332                     LIST_COPY_TIME(item->appointment->end);
03333                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->appointment->end)));
03334                     break;
03335                 case 0x8214: // Label for an appointment
03336                     DEBUG_EMAIL(("Label for appointment - "));
03337                     MALLOC_APPOINTMENT(item);
03338                     memcpy(&(item->appointment->label), list->items[x]->data, sizeof(item->appointment->label));
03339                     LE32_CPU(item->appointment->label);
03340                     switch (item->appointment->label) {
03341                         case PST_APP_LABEL_NONE:
03342                             DEBUG_EMAIL(("None\n")); break;
03343                         case PST_APP_LABEL_IMPORTANT:
03344                             DEBUG_EMAIL(("Important\n")); break;
03345                         case PST_APP_LABEL_BUSINESS:
03346                             DEBUG_EMAIL(("Business\n")); break;
03347                         case PST_APP_LABEL_PERSONAL:
03348                             DEBUG_EMAIL(("Personal\n")); break;
03349                         case PST_APP_LABEL_VACATION:
03350                             DEBUG_EMAIL(("Vacation\n")); break;
03351                         case PST_APP_LABEL_MUST_ATTEND:
03352                             DEBUG_EMAIL(("Must Attend\n")); break;
03353                         case PST_APP_LABEL_TRAVEL_REQ:
03354                             DEBUG_EMAIL(("Travel Required\n")); break;
03355                         case PST_APP_LABEL_NEEDS_PREP:
03356                             DEBUG_EMAIL(("Needs Preparation\n")); break;
03357                         case PST_APP_LABEL_BIRTHDAY:
03358                             DEBUG_EMAIL(("Birthday\n")); break;
03359                         case PST_APP_LABEL_ANNIVERSARY:
03360                             DEBUG_EMAIL(("Anniversary\n")); break;
03361                         case PST_APP_LABEL_PHONE_CALL:
03362                             DEBUG_EMAIL(("Phone Call\n")); break;
03363                     }
03364                     break;
03365                 case 0x8215: // All day appointment flag
03366                     DEBUG_EMAIL(("All day flag - "));
03367                     MALLOC_APPOINTMENT(item);
03368                     if (*(int16_t*)list->items[x]->data) {
03369                         DEBUG_EMAIL(("True\n"));
03370                         item->appointment->all_day = 1;
03371                     } else {
03372                         DEBUG_EMAIL(("False\n"));
03373                         item->appointment->all_day = 0;
03374                     }
03375                     break;
03376                 case 0x8231: // Recurrence type
03377                     // 1: Daily
03378                     // 2: Weekly
03379                     // 3: Monthly
03380                     // 4: Yearly
03381                     DEBUG_EMAIL(("Appointment reccurs - "));
03382                     MALLOC_APPOINTMENT(item);
03383                     memcpy(&(item->appointment->recurrence_type), list->items[x]->data, sizeof(item->appointment->recurrence_type));
03384                     LE32_CPU(item->appointment->recurrence_type);
03385                     switch (item->appointment->recurrence_type) {
03386                         case PST_APP_RECUR_DAILY:
03387                             DEBUG_EMAIL(("Daily\n")); break;
03388                         case PST_APP_RECUR_WEEKLY:
03389                             DEBUG_EMAIL(("Weekly\n")); break;
03390                         case PST_APP_RECUR_MONTHLY:
03391                             DEBUG_EMAIL(("Monthly\n")); break;
03392                         case PST_APP_RECUR_YEARLY:
03393                             DEBUG_EMAIL(("Yearly\n")); break;
03394                         default:
03395                             DEBUG_EMAIL(("Unknown Value: %d\n", item->appointment->recurrence_type)); break;
03396                     }
03397                     break;
03398                 case 0x8232: // Recurrence description
03399                     DEBUG_EMAIL(("Appointment recurrence description - "));
03400                     MALLOC_APPOINTMENT(item);
03401                     LIST_COPY(item->appointment->recurrence, (char*));
03402                     DEBUG_EMAIL(("%s\n", item->appointment->recurrence));
03403                     break;
03404                 case 0x8234: // TimeZone as String
03405                     DEBUG_EMAIL(("TimeZone of times - "));
03406                     MALLOC_APPOINTMENT(item);
03407                     LIST_COPY(item->appointment->timezonestring, (char*));
03408                     DEBUG_EMAIL(("%s\n", item->appointment->timezonestring));
03409                     break;
03410                 case 0x8235: // Recurrence start date
03411                     DEBUG_EMAIL(("Recurrence Start Date - "));
03412                     MALLOC_APPOINTMENT(item);
03413                     LIST_COPY_TIME(item->appointment->recurrence_start);
03414                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->appointment->recurrence_start)));
03415                     break;
03416                 case 0x8236: // Recurrence end date
03417                     DEBUG_EMAIL(("Recurrence End Date - "));
03418                     MALLOC_APPOINTMENT(item);
03419                     LIST_COPY_TIME(item->appointment->recurrence_end);
03420                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->appointment->recurrence_end)));
03421                     break;
03422                 case 0x8501: // Reminder minutes before appointment start
03423                     DEBUG_EMAIL(("Alarm minutes - "));
03424                     MALLOC_APPOINTMENT(item);
03425                     memcpy(&(item->appointment->alarm_minutes), list->items[x]->data, sizeof(item->appointment->alarm_minutes));
03426                     LE32_CPU(item->appointment->alarm_minutes);
03427                     DEBUG_EMAIL(("%i\n", item->appointment->alarm_minutes));
03428                     break;
03429                 case 0x8503: // Reminder alarm
03430                     DEBUG_EMAIL(("Reminder alarm - "));
03431                     MALLOC_APPOINTMENT(item);
03432                     if (*(int16_t*)list->items[x]->data) {
03433                         DEBUG_EMAIL(("True\n"));
03434                         item->appointment->alarm = 1;
03435                     } else {
03436                         DEBUG_EMAIL(("False\n"));
03437                         item->appointment->alarm = 0;
03438                     }
03439                     break;
03440                 case 0x8516: // Common start
03441                     DEBUG_EMAIL(("Common Start Date - "));
03442                     DEBUG_EMAIL(("%s\n", fileTimeToAscii((FILETIME*)list->items[x]->data)));
03443                     break;
03444                 case 0x8517: // Common end
03445                     DEBUG_EMAIL(("Common End Date - "));
03446                     DEBUG_EMAIL(("%s\n", fileTimeToAscii((FILETIME*)list->items[x]->data)));
03447                     break;
03448                 case 0x851f: // Play reminder sound filename
03449                     DEBUG_EMAIL(("Appointment reminder sound filename - "));
03450                     MALLOC_APPOINTMENT(item);
03451                     LIST_COPY(item->appointment->alarm_filename, (char*));
03452                     DEBUG_EMAIL(("%s\n", item->appointment->alarm_filename));
03453                     break;
03454                 case 0x8530: // Followup
03455                     DEBUG_EMAIL(("Followup String - "));
03456                     MALLOC_CONTACT(item);
03457                     LIST_COPY(item->contact->followup, (char*));
03458                     DEBUG_EMAIL(("%s\n", item->contact->followup));
03459                     break;
03460                 case 0x8534: // Mileage
03461                     DEBUG_EMAIL(("Mileage - "));
03462                     MALLOC_CONTACT(item);
03463                     LIST_COPY(item->contact->mileage, (char*));
03464                     DEBUG_EMAIL(("%s\n", item->contact->mileage));
03465                     break;
03466                 case 0x8535: // Billing Information
03467                     DEBUG_EMAIL(("Billing Information - "));
03468                     MALLOC_CONTACT(item);
03469                     LIST_COPY(item->contact->billing_information, (char*));
03470                     DEBUG_EMAIL(("%s\n", item->contact->billing_information));
03471                     break;
03472                 case 0x8554: // Outlook Version
03473                     DEBUG_EMAIL(("Outlook Version - "));
03474                     LIST_COPY(item->outlook_version, (char*));
03475                     DEBUG_EMAIL(("%s\n", item->outlook_version));
03476                     break;
03477                 case 0x8560: // Appointment Reminder Time
03478                     DEBUG_EMAIL(("Appointment Reminder Time - "));
03479                     MALLOC_APPOINTMENT(item);
03480                     LIST_COPY_TIME(item->appointment->reminder);
03481                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->appointment->reminder)));
03482                     break;
03483                 case 0x8700: // Journal Type
03484                     DEBUG_EMAIL(("Journal Entry Type - "));
03485                     MALLOC_JOURNAL(item);
03486                     LIST_COPY(item->journal->type, (char*));
03487                     DEBUG_EMAIL(("%s\n", item->journal->type));
03488                     break;
03489                 case 0x8706: // Journal Start date/time
03490                     DEBUG_EMAIL(("Start Timestamp - "));
03491                     MALLOC_JOURNAL(item);
03492                     LIST_COPY_TIME(item->journal->start);
03493                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->journal->start)));
03494                     break;
03495                 case 0x8708: // Journal End date/time
03496                     DEBUG_EMAIL(("End Timestamp - "));
03497                     MALLOC_JOURNAL(item);
03498                     LIST_COPY_TIME(item->journal->end);
03499                     DEBUG_EMAIL(("%s\n", fileTimeToAscii(item->journal->end)));
03500                     break;
03501                 case 0x8712: // Title?
03502                     DEBUG_EMAIL(("Journal Entry Type - "));
03503                     MALLOC_JOURNAL(item);
03504                     LIST_COPY(item->journal->type, (char*));
03505                     DEBUG_EMAIL(("%s\n", item->journal->type));
03506                     break;
03507                 default:
03508                     if (list->items[x]->type == (uint32_t)0x0002) {
03509                         DEBUG_EMAIL(("Unknown type %#x 16bit int = %hi\n", list->items[x]->id,
03510                             *(int16_t*)list->items[x]->data));
03511 
03512                     } else if (list->items[x]->type == (uint32_t)0x0003) {
03513                         DEBUG_EMAIL(("Unknown type %#x 32bit int = %i\n", list->items[x]->id,
03514                             *(int32_t*)list->items[x]->data));
03515 
03516                     } else if (list->items[x]->type == (uint32_t)0x0004) {
03517                         DEBUG_EMAIL(("Unknown type %#x 4-byte floating [size = %#x]\n", list->items[x]->id,
03518                             list->items[x]->size));
03519                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03520 
03521                     } else if (list->items[x]->type == (uint32_t)0x0005) {
03522                         DEBUG_EMAIL(("Unknown type %#x double floating [size = %#x]\n", list->items[x]->id,
03523                             list->items[x]->size));
03524                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03525 
03526                     } else if (list->items[x]->type == (uint32_t)0x0006) {
03527                         DEBUG_EMAIL(("Unknown type %#x signed 64bit int = %lli\n", list->items[x]->id,
03528                             *(int64_t*)list->items[x]->data));
03529                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03530 
03531                     } else if (list->items[x]->type == (uint32_t)0x0007) {
03532                         DEBUG_EMAIL(("Unknown type %#x application time [size = %#x]\n", list->items[x]->id,
03533                             list->items[x]->size));
03534                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03535 
03536                     } else if (list->items[x]->type == (uint32_t)0x000a) {
03537                         DEBUG_EMAIL(("Unknown type %#x 32bit error value = %i\n", list->items[x]->id,
03538                             *(int32_t*)list->items[x]->data));
03539 
03540                     } else if (list->items[x]->type == (uint32_t)0x000b) {
03541                         DEBUG_EMAIL(("Unknown type %#x 16bit boolean = %s [%hi]\n", list->items[x]->id,
03542                             (*((int16_t*)list->items[x]->data)!=0?"True":"False"),
03543                             *((int16_t*)list->items[x]->data)));
03544 
03545                     } else if (list->items[x]->type == (uint32_t)0x000d) {
03546                         DEBUG_EMAIL(("Unknown type %#x Embedded object [size = %#x]\n", list->items[x]->id,
03547                             list->items[x]->size));
03548                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03549 
03550                     } else if (list->items[x]->type == (uint32_t)0x0014) {
03551                         DEBUG_EMAIL(("Unknown type %#x signed 64bit int = %lli\n", list->items[x]->id,
03552                             *(int64_t*)list->items[x]->data));
03553                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03554 
03555                     } else if (list->items[x]->type == (uint32_t)0x001e) {
03556                         DEBUG_EMAIL(("Unknown type %#x String Data = \"%s\"\n", list->items[x]->id,
03557                             list->items[x]->data));
03558 
03559                     } else if (list->items[x]->type == (uint32_t)0x001f) {
03560                         DEBUG_EMAIL(("Unknown type %#x Unicode String Data [size = %#x]\n", list->items[x]->id,
03561                             list->items[x]->size));
03562                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03563 
03564                     } else if (list->items[x]->type == (uint32_t)0x0040) {
03565                         DEBUG_EMAIL(("Unknown type %#x Date = \"%s\"\n", list->items[x]->id,
03566                             fileTimeToAscii((FILETIME*)list->items[x]->data)));
03567 
03568                     } else if (list->items[x]->type == (uint32_t)0x0048) {
03569                         DEBUG_EMAIL(("Unknown type %#x OLE GUID [size = %#x]\n", list->items[x]->id,
03570                             list->items[x]->size));
03571                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03572 
03573                     } else if (list->items[x]->type == (uint32_t)0x0102) {
03574                         DEBUG_EMAIL(("Unknown type %#x Binary Data [size = %#x]\n", list->items[x]->id,
03575                             list->items[x]->size));
03576                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03577 
03578                     } else if (list->items[x]->type == (uint32_t)0x1003) {
03579                         DEBUG_EMAIL(("Unknown type %#x Array of 32 bit values [size = %#x]\n", list->items[x]->id,
03580                             list->items[x]->size));
03581                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03582 
03583                     } else if (list->items[x]->type == (uint32_t)0x1014) {
03584                         DEBUG_EMAIL(("Unknown type %#x Array of 64 bit values [siize = %#x]\n", list->items[x]->id,
03585                             list->items[x]->size));
03586                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03587 
03588                     } else if (list->items[x]->type == (uint32_t)0x101E) {
03589                         DEBUG_EMAIL(("Unknown type %#x Array of Strings [size = %#x]\n", list->items[x]->id,
03590                             list->items[x]->size));
03591                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03592 
03593                     } else if (list->items[x]->type == (uint32_t)0x101F) {
03594                         DEBUG_EMAIL(("Unknown type %#x Array of Unicode Strings [size = %#x]\n", list->items[x]->id,
03595                             list->items[x]->size));
03596                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03597 
03598                     } else if (list->items[x]->type == (uint32_t)0x1102) {
03599                         DEBUG_EMAIL(("Unknown type %#x Array of binary data blobs [size = %#x]\n", list->items[x]->id,
03600                             list->items[x]->size));
03601                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03602 
03603                     } else {
03604                         DEBUG_EMAIL(("Unknown type %#x Not Printable [%#x]\n", list->items[x]->id,
03605                             list->items[x]->type));
03606                         DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size);
03607                     }
03608 
03609                     if (list->items[x]->data) {
03610                         free(list->items[x]->data);
03611                         list->items[x]->data = NULL;
03612                     }
03613             }
03614             x++;
03615         }
03616         x = 0;
03617         list = list->next;
03618         next = 1;
03619     }
03620     DEBUG_RET();
03621     return 0;
03622 }
03623 
03624 
03625 void pst_free_list(pst_num_array *list) {
03626     pst_num_array *l;
03627     DEBUG_ENT("pst_free_list");
03628     while (list) {
03629         if (list->items) {
03630             int32_t x;
03631             for (x=0; x < list->orig_count; x++) {
03632                 if (list->items[x]) {
03633                     if (list->items[x]->data) free(list->items[x]->data);
03634                     free(list->items[x]);
03635                 }
03636             }
03637             free(list->items);
03638         }
03639         l = list;
03640         list = list->next;
03641         free (l);
03642     }
03643     DEBUG_RET();
03644 }
03645 
03646 
03647 void pst_free_id2(pst_index2_ll * head) {
03648     pst_index2_ll *t;
03649     DEBUG_ENT("pst_free_id2");
03650     while (head) {
03651         t = head->next;
03652         free (head);
03653         head = t;
03654     }
03655     DEBUG_RET();
03656 }
03657 
03658 
03659 void pst_free_id (pst_index_ll *head) {
03660     pst_index_ll *t;
03661     DEBUG_ENT("pst_free_id");
03662     while (head) {
03663         t = head->next;
03664         free(head);
03665         head = t;
03666     }
03667     DEBUG_RET();
03668 }
03669 
03670 
03671 void pst_free_desc (pst_desc_ll *head) {
03672     pst_desc_ll *t;
03673     DEBUG_ENT("pst_free_desc");
03674     while (head) {
03675         while (head->child) {
03676             head = head->child;
03677         }
03678 
03679         // point t to the next item
03680         t = head->next;
03681         if (!t && head->parent) {
03682             t = head->parent;
03683             t->child = NULL; // set the child to NULL so we don't come back here again!
03684         }
03685 
03686         if (head) free(head);
03687         else      DIE(("head is NULL"));
03688 
03689         head = t;
03690     }
03691     DEBUG_RET();
03692 }
03693 
03694 
03695 void pst_free_xattrib(pst_x_attrib_ll *x) {
03696     pst_x_attrib_ll *t;
03697     DEBUG_ENT("pst_free_xattrib");
03698     while (x) {
03699         if (x->data) free(x->data);
03700         t = x->next;
03701         free(x);
03702         x = t;
03703     }
03704     DEBUG_RET();
03705 }
03706 
03707 
03708 pst_index2_ll * pst_build_id2(pst_file *pf, pst_index_ll* list, pst_index2_ll* head_ptr) {
03709     pst_block_header block_head;
03710     pst_index2_ll *head = NULL, *tail = NULL;
03711     uint16_t x = 0;
03712     char *b_ptr = NULL;
03713     char *buf = NULL;
03714     pst_id2_assoc id2_rec;
03715     pst_index_ll *i_ptr = NULL;
03716     pst_index2_ll *i2_ptr = NULL;
03717     DEBUG_ENT("pst_build_id2");
03718 
03719     if (head_ptr) {
03720         head = head_ptr;
03721         while (head_ptr) head_ptr = (tail = head_ptr)->next;
03722     }
03723     if (pst_read_block_size(pf, list->offset, list->size, &buf) < list->size) {
03724         //an error occured in block read
03725         WARN(("block read error occured. offset = %#"PRIx64", size = %#"PRIx64"\n", list->offset, list->size));
03726         if (buf) free(buf);
03727         DEBUG_RET();
03728         return NULL;
03729     }
03730     DEBUG_HEXDUMPC(buf, list->size, 16);
03731 
03732     memcpy(&block_head, buf, sizeof(block_head));
03733     LE16_CPU(block_head.type);
03734     LE16_CPU(block_head.count);
03735 
03736     if (block_head.type != (uint16_t)0x0002) { // some sort of constant?
03737         WARN(("Unknown constant [%#hx] at start of id2 values [offset %#"PRIx64"].\n", block_head.type, list->offset));
03738         if (buf) free(buf);
03739         DEBUG_RET();
03740         return NULL;
03741     }
03742 
03743     DEBUG_INDEX(("ID %#"PRIx64" is likely to be a description record. Count is %i (offset %#"PRIx64")\n",
03744             list->id, block_head.count, list->offset));
03745     x = 0;
03746     b_ptr = buf + ((pf->do_read64) ? 0x08 : 0x04);
03747     while (x < block_head.count) {
03748         b_ptr += pst_decode_assoc(pf, &id2_rec, b_ptr);
03749         DEBUG_INDEX(("\tid2 = %#x, id = %#"PRIx64", table2 = %#"PRIx64"\n", id2_rec.id2, id2_rec.id, id2_rec.table2));
03750         if ((i_ptr = pst_getID(pf, id2_rec.id)) == NULL) {
03751             DEBUG_WARN(("\t\t%#"PRIx64" - Not Found\n", id2_rec.id));
03752         } else {
03753             DEBUG_INDEX(("\t\t%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %lli(%#"PRIx64")\n", i_ptr->id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size));
03754             // add it to the linked list
03755             i2_ptr = (pst_index2_ll*) xmalloc(sizeof(pst_index2_ll));
03756             i2_ptr->id2  = id2_rec.id2;
03757             i2_ptr->id   = i_ptr;
03758             i2_ptr->next = NULL;
03759             if (!head) head = i2_ptr;
03760             if (tail)  tail->next = i2_ptr;
03761             tail = i2_ptr;
03762             if (id2_rec.table2 != 0) {
03763                 if ((i_ptr = pst_getID(pf, id2_rec.table2)) == NULL) {
03764                     DEBUG_WARN(("\tTable2 [%#x] not found\n", id2_rec.table2));
03765                 }
03766                 else {
03767                     DEBUG_INDEX(("\tGoing deeper for table2 [%#x]\n", id2_rec.table2));
03768                     if ((i2_ptr = pst_build_id2(pf, i_ptr, head))) {
03769                     //  DEBUG_INDEX(("pst_build_id2(): \t\tAdding new list onto end of current\n"));
03770                     //  if (!head)
03771                     //    head = i2_ptr;
03772                     //  if (tail)
03773                     //    tail->next = i2_ptr;
03774                     //  while (i2_ptr->next)
03775                     //    i2_ptr = i2_ptr->next;
03776                     //    tail = i2_ptr;
03777                     }
03778                     // need to re-establish tail
03779                     DEBUG_INDEX(("Returned from depth\n"));
03780                     if (tail) {
03781                         while (tail->next) tail = tail->next;
03782                     }
03783                 }
03784             }
03785         }
03786         x++;
03787     }
03788     if (buf) free (buf);
03789     DEBUG_RET();
03790     return head;
03791 }
03792 
03793 
03794 void pst_freeItem(pst_item *item) {
03795     pst_item_attach *t;
03796     pst_item_extra_field *et;
03797 
03798     DEBUG_ENT("pst_freeItem");
03799     if (item) {
03800         if (item->email) {
03801             SAFE_FREE(item->email->arrival_date);
03802             SAFE_FREE(item->email->body);
03803             SAFE_FREE(item->email->cc_address);
03804             SAFE_FREE(item->email->bcc_address);
03805             SAFE_FREE(item->email->common_name);
03806             SAFE_FREE(item->email->encrypted_body);
03807             SAFE_FREE(item->email->encrypted_htmlbody);
03808             SAFE_FREE(item->email->header);
03809             SAFE_FREE(item->email->htmlbody);
03810             SAFE_FREE(item->email->in_reply_to);
03811             SAFE_FREE(item->email->messageid);
03812             SAFE_FREE(item->email->original_bcc);
03813             SAFE_FREE(item->email->original_cc);
03814             SAFE_FREE(item->email->original_to);
03815             SAFE_FREE(item->email->outlook_recipient);
03816             SAFE_FREE(item->email->outlook_recipient_name);
03817             SAFE_FREE(item->email->outlook_recipient2);
03818             SAFE_FREE(item->email->outlook_sender);
03819             SAFE_FREE(item->email->outlook_sender_name);
03820             SAFE_FREE(item->email->outlook_sender2);
03821             SAFE_FREE(item->email->proc_subject);
03822             SAFE_FREE(item->email->recip_access);
03823             SAFE_FREE(item->email->recip_address);
03824             SAFE_FREE(item->email->recip2_access);
03825             SAFE_FREE(item->email->recip2_address);
03826             SAFE_FREE(item->email->reply_to);
03827             SAFE_FREE(item->email->rtf_body_tag);
03828             SAFE_FREE(item->email->rtf_compressed);
03829             SAFE_FREE(item->email->return_path_address);
03830             SAFE_FREE(item->email->sender_access);
03831             SAFE_FREE(item->email->sender_address);
03832             SAFE_FREE(item->email->sender2_access);
03833             SAFE_FREE(item->email->sender2_address);
03834             SAFE_FREE(item->email->sent_date);
03835             SAFE_FREE(item->email->sentmail_folder);
03836             SAFE_FREE(item->email->sentto_address);
03837             if (item->email->subject)
03838                 SAFE_FREE(item->email->subject->subj);
03839             SAFE_FREE(item->email->subject);
03840             free(item->email);
03841         }
03842         if (item->folder) {
03843             free(item->folder);
03844         }
03845         if (item->message_store) {
03846             SAFE_FREE(item->message_store->top_of_personal_folder);
03847             SAFE_FREE(item->message_store->default_outbox_folder);
03848             SAFE_FREE(item->message_store->deleted_items_folder);
03849             SAFE_FREE(item->message_store->sent_items_folder);
03850             SAFE_FREE(item->message_store->user_views_folder);
03851             SAFE_FREE(item->message_store->common_view_folder);
03852             SAFE_FREE(item->message_store->search_root_folder);
03853             SAFE_FREE(item->message_store->top_of_folder);
03854             free(item->message_store);
03855         }
03856         if (item->contact) {
03857             SAFE_FREE(item->contact->access_method);
03858             SAFE_FREE(item->contact->account_name);
03859             SAFE_FREE(item->contact->address1);
03860             SAFE_FREE(item->contact->address1a);
03861             SAFE_FREE(item->contact->address1_desc);
03862             SAFE_FREE(item->contact->address1_transport);
03863             SAFE_FREE(item->contact->address2);
03864             SAFE_FREE(item->contact->address2a);
03865             SAFE_FREE(item->contact->address2_desc);
03866             SAFE_FREE(item->contact->address2_transport);
03867             SAFE_FREE(item->contact->address3);
03868             SAFE_FREE(item->contact->address3a);
03869             SAFE_FREE(item->contact->address3_desc);
03870             SAFE_FREE(item->contact->address3_transport);
03871             SAFE_FREE(item->contact->assistant_name);
03872             SAFE_FREE(item->contact->assistant_phone);
03873             SAFE_FREE(item->contact->billing_information);
03874             SAFE_FREE(item->contact->birthday);
03875             SAFE_FREE(item->contact->business_address);
03876             SAFE_FREE(item->contact->business_city);
03877             SAFE_FREE(item->contact->business_country);
03878             SAFE_FREE(item->contact->business_fax);
03879             SAFE_FREE(item->contact->business_homepage);
03880             SAFE_FREE(item->contact->business_phone);
03881             SAFE_FREE(item->contact->business_phone2);
03882             SAFE_FREE(item->contact->business_po_box);
03883             SAFE_FREE(item->contact->business_postal_code);
03884             SAFE_FREE(item->contact->business_state);
03885             SAFE_FREE(item->contact->business_street);
03886             SAFE_FREE(item->contact->callback_phone);
03887             SAFE_FREE(item->contact->car_phone);
03888             SAFE_FREE(item->contact->company_main_phone);
03889             SAFE_FREE(item->contact->company_name);
03890             SAFE_FREE(item->contact->computer_name);
03891             SAFE_FREE(item->contact->customer_id);
03892             SAFE_FREE(item->contact->def_postal_address);
03893             SAFE_FREE(item->contact->department);
03894             SAFE_FREE(item->contact->display_name_prefix);
03895             SAFE_FREE(item->contact->first_name);
03896             SAFE_FREE(item->contact->followup);
03897             SAFE_FREE(item->contact->free_busy_address);
03898             SAFE_FREE(item->contact->ftp_site);
03899             SAFE_FREE(item->contact->fullname);
03900             SAFE_FREE(item->contact->gov_id);
03901             SAFE_FREE(item->contact->hobbies);
03902             SAFE_FREE(item->contact->home_address);
03903             SAFE_FREE(item->contact->home_city);
03904             SAFE_FREE(item->contact->home_country);
03905             SAFE_FREE(item->contact->home_fax);
03906             SAFE_FREE(item->contact->home_po_box);
03907             SAFE_FREE(item->contact->home_phone);
03908             SAFE_FREE(item->contact->home_phone2);
03909             SAFE_FREE(item->contact->home_postal_code);
03910             SAFE_FREE(item->contact->home_state);
03911             SAFE_FREE(item->contact->home_street);
03912             SAFE_FREE(item->contact->initials);
03913             SAFE_FREE(item->contact->isdn_phone);
03914             SAFE_FREE(item->contact->job_title);
03915             SAFE_FREE(item->contact->keyword);
03916             SAFE_FREE(item->contact->language);
03917             SAFE_FREE(item->contact->location);
03918             SAFE_FREE(item->contact->manager_name);
03919             SAFE_FREE(item->contact->middle_name);
03920             SAFE_FREE(item->contact->mileage);
03921             SAFE_FREE(item->contact->mobile_phone);
03922             SAFE_FREE(item->contact->nickname);
03923             SAFE_FREE(item->contact->office_loc);
03924             SAFE_FREE(item->contact->org_id);
03925             SAFE_FREE(item->contact->other_address);
03926             SAFE_FREE(item->contact->other_city);
03927             SAFE_FREE(item->contact->other_country);
03928             SAFE_FREE(item->contact->other_phone);
03929             SAFE_FREE(item->contact->other_po_box);
03930             SAFE_FREE(item->contact->other_postal_code);
03931             SAFE_FREE(item->contact->other_state);
03932             SAFE_FREE(item->contact->other_street);
03933             SAFE_FREE(item->contact->pager_phone);
03934             SAFE_FREE(item->contact->personal_homepage);
03935             SAFE_FREE(item->contact->pref_name);
03936             SAFE_FREE(item->contact->primary_fax);
03937             SAFE_FREE(item->contact->primary_phone);
03938             SAFE_FREE(item->contact->profession);
03939             SAFE_FREE(item->contact->radio_phone);
03940             SAFE_FREE(item->contact->spouse_name);
03941             SAFE_FREE(item->contact->suffix);
03942             SAFE_FREE(item->contact->surname);
03943             SAFE_FREE(item->contact->telex);
03944             SAFE_FREE(item->contact->transmittable_display_name);
03945             SAFE_FREE(item->contact->ttytdd_phone);
03946             SAFE_FREE(item->contact->wedding_anniversary);
03947             SAFE_FREE(item->contact->work_address_street);
03948             SAFE_FREE(item->contact->work_address_city);
03949             SAFE_FREE(item->contact->work_address_state);
03950             SAFE_FREE(item->contact->work_address_postalcode);
03951             SAFE_FREE(item->contact->work_address_country);
03952             SAFE_FREE(item->contact->work_address_postofficebox);
03953             free(item->contact);
03954         }
03955         while (item->attach) {
03956             SAFE_FREE(item->attach->filename1);
03957             SAFE_FREE(item->attach->filename2);
03958             SAFE_FREE(item->attach->mimetype);
03959             SAFE_FREE(item->attach->data);
03960             t = item->attach->next;
03961             free(item->attach);
03962             item->attach = t;
03963         }
03964         while (item->extra_fields) {
03965             SAFE_FREE(item->extra_fields->field_name);
03966             SAFE_FREE(item->extra_fields->value);
03967             et = item->extra_fields->next;
03968             free(item->extra_fields);
03969             item->extra_fields = et;
03970         }
03971         if (item->journal) {
03972             SAFE_FREE(item->journal->end);
03973             SAFE_FREE(item->journal->start);
03974             SAFE_FREE(item->journal->type);
03975             free(item->journal);
03976         }
03977         if (item->appointment) {
03978             SAFE_FREE(item->appointment->location);
03979             SAFE_FREE(item->appointment->reminder);
03980             SAFE_FREE(item->appointment->alarm_filename);
03981             SAFE_FREE(item->appointment->start);
03982             SAFE_FREE(item->appointment->end);
03983             SAFE_FREE(item->appointment->timezonestring);
03984             SAFE_FREE(item->appointment->recurrence);
03985             SAFE_FREE(item->appointment->recurrence_start);
03986             SAFE_FREE(item->appointment->recurrence_end);
03987             free(item->appointment);
03988         }
03989         SAFE_FREE(item->ascii_type);
03990         SAFE_FREE(item->comment);
03991         SAFE_FREE(item->create_date);
03992         SAFE_FREE(item->file_as);
03993         SAFE_FREE(item->modify_date);
03994         SAFE_FREE(item->outlook_version);
03995         SAFE_FREE(item->record_key);
03996         free(item);
03997     }
03998     DEBUG_RET();
03999 }
04000 
04001 
04008 int pst_getBlockOffsetPointer(pst_file *pf, pst_index2_ll *i2_head, pst_subblocks *subblocks, uint32_t offset, pst_block_offset_pointer *p) {
04009     size_t size;
04010     pst_block_offset block_offset;
04011     DEBUG_ENT("pst_getBlockOffsetPointer");
04012     if (p->needfree) free(p->from);
04013     p->from     = NULL;
04014     p->to       = NULL;
04015     p->needfree = 0;
04016     if (!offset) {
04017         // no data
04018         p->from = p->to = NULL;
04019     }
04020     else if ((offset & 0xf) == (uint32_t)0xf) {
04021         // external index reference
04022         DEBUG_WARN(("Found id2 %#x value. Will follow it\n", offset));
04023         size = pst_ff_getID2block(pf, offset, i2_head, &(p->from));
04024         if (size) {
04025             p->to = p->from + size;
04026             p->needfree = 1;
04027         }
04028         else {
04029             if (p->from) {
04030                 DEBUG_WARN(("size zero but non-null pointer\n"));
04031                 free(p->from);
04032             }
04033             p->from = p->to = NULL;
04034         }
04035     }
04036     else {
04037         // internal index reference
04038         size_t subindex  = offset >> 16;
04039         size_t suboffset = offset & 0xffff;
04040         if (subindex < subblocks->subblock_count) {
04041             if (pst_getBlockOffset(subblocks->subs[subindex].buf,
04042                                    subblocks->subs[subindex].read_size,
04043                                    subblocks->subs[subindex].i_offset,
04044                                    suboffset, &block_offset)) {
04045                 p->from = subblocks->subs[subindex].buf + block_offset.from;
04046                 p->to   = subblocks->subs[subindex].buf + block_offset.to;
04047             }
04048         }
04049     }
04050     DEBUG_RET();
04051     return (p->from) ? 0 : 1;
04052 }
04053 
04054 
04055 int pst_getBlockOffset(char *buf, size_t read_size, uint32_t i_offset, uint32_t offset, pst_block_offset *p) {
04056     uint32_t low = offset & 0xf;
04057     uint32_t of1 = offset >> 4;
04058     DEBUG_ENT("pst_getBlockOffset");
04059     if (!p || !buf || !i_offset || low || (i_offset+2+of1+sizeof(*p) > read_size)) {
04060         DEBUG_WARN(("p is NULL or buf is NULL or offset is 0 or offset has low bits or beyond read size (%p, %p, %#x, %i, %i)\n", p, buf, offset, read_size, i_offset));
04061         DEBUG_RET();
04062         return 0;
04063     }
04064     memcpy(&(p->from), &(buf[(i_offset+2)+of1]), sizeof(p->from));
04065     memcpy(&(p->to), &(buf[(i_offset+2)+of1+sizeof(p->from)]), sizeof(p->to));
04066     LE16_CPU(p->from);
04067     LE16_CPU(p->to);
04068     DEBUG_WARN(("get block offset finds from=%i(%#x), to=%i(%#x)\n", p->from, p->from, p->to, p->to));
04069     if (p->from > p->to) {
04070         DEBUG_WARN(("get block offset from > to"));
04071         DEBUG_RET();
04072         return 0;
04073     }
04074     DEBUG_RET();
04075     return 1;
04076 }
04077 
04078 
04079 pst_index_ll* pst_getID(pst_file* pf, uint64_t id) {
04080     pst_index_ll *ptr;
04081     DEBUG_ENT("pst_getID");
04082     if (id == 0) {
04083         DEBUG_RET();
04084         return NULL;
04085     }
04086 
04087     //if (id & 1) DEBUG_INDEX(("have odd id bit %#"PRIx64"\n", id));
04088     //if (id & 2) DEBUG_INDEX(("have two id bit %#"PRIx64"\n", id));
04089     id -= (id & 1);
04090 
04091     DEBUG_INDEX(("Trying to find %#"PRIx64"\n", id));
04092     ptr = pf->i_head;
04093     while (ptr && (ptr->id != id)) {
04094         ptr = ptr->next;
04095     }
04096     if (ptr) {DEBUG_INDEX(("Found Value %#"PRIx64"\n", id));            }
04097     else     {DEBUG_INDEX(("ERROR: Value %#"PRIx64" not found\n", id)); }
04098     DEBUG_RET();
04099     return ptr;
04100 }
04101 
04102 
04103 pst_index_ll * pst_getID2(pst_index2_ll *ptr, uint64_t id) {
04104     DEBUG_ENT("pst_getID2");
04105     DEBUG_INDEX(("Head = %p id = %#"PRIx64"\n", ptr, id));
04106     while (ptr && (ptr->id2 != id)) {
04107         ptr = ptr->next;
04108     }
04109     if (ptr) {
04110         if (ptr->id) {DEBUG_INDEX(("Found value %#"PRIx64"\n", ptr->id->id));   }
04111         else         {DEBUG_INDEX(("Found value, though it is NULL!\n"));}
04112         DEBUG_RET();
04113         return ptr->id;
04114     }
04115     DEBUG_INDEX(("ERROR Not Found\n"));
04116     DEBUG_RET();
04117     return NULL;
04118 }
04119 
04120 
04129 pst_desc_ll* pst_getDptr(pst_file *pf, uint64_t id) {
04130     pst_desc_ll *ptr = pf->d_head;
04131     DEBUG_ENT("pst_getDptr");
04132     while (ptr && (ptr->id != id)) {
04133         if (ptr->child) {
04134             ptr = ptr->child;
04135             continue;
04136         }
04137         while (!ptr->next && ptr->parent) {
04138             ptr = ptr->parent;
04139         }
04140         ptr = ptr->next;
04141     }
04142     DEBUG_RET();
04143     return ptr; // will be NULL or record we are looking for
04144 }
04145 
04146 
04147 void pst_printDptr(pst_file *pf, pst_desc_ll *ptr) {
04148     DEBUG_ENT("pst_printDptr");
04149     while (ptr) {
04150         DEBUG_INDEX(("%#x [%i] desc=%#x, list=%#x\n", ptr->id, ptr->no_child,
04151                     (ptr->desc==NULL?0:ptr->desc->id),
04152                     (ptr->list_index==NULL?0:ptr->list_index->id)));
04153         if (ptr->child) {
04154             pst_printDptr(pf, ptr->child);
04155         }
04156         ptr = ptr->next;
04157     }
04158     DEBUG_RET();
04159 }
04160 
04161 
04162 void pst_printIDptr(pst_file* pf) {
04163     pst_index_ll *ptr = pf->i_head;
04164     DEBUG_ENT("pst_printIDptr");
04165     while (ptr) {
04166         DEBUG_INDEX(("%#x offset=%#x size=%#x\n", ptr->id, ptr->offset, ptr->size));
04167         ptr = ptr->next;
04168     }
04169     DEBUG_RET();
04170 }
04171 
04172 
04173 void pst_printID2ptr(pst_index2_ll *ptr) {
04174     DEBUG_ENT("pst_printID2ptr");
04175     while (ptr) {
04176         DEBUG_INDEX(("%#x id=%#x\n", ptr->id2, (ptr->id!=NULL?ptr->id->id:0)));
04177         ptr = ptr->next;
04178     }
04179     DEBUG_RET();
04180 }
04181 
04182 
04192 size_t pst_read_block_size(pst_file *pf, off_t offset, size_t size, char **buf) {
04193     size_t rsize;
04194     DEBUG_ENT("pst_read_block_size");
04195     DEBUG_READ(("Reading block from %#"PRIx64", %x bytes\n", offset, size));
04196 
04197     if (*buf) {
04198         DEBUG_READ(("Freeing old memory\n"));
04199         free(*buf);
04200     }
04201     *buf = (char*) xmalloc(size);
04202 
04203     rsize = pst_getAtPos(pf, offset, *buf, size);
04204     if (rsize != size) {
04205         DEBUG_WARN(("Didn't read all the data. fread returned less [%i instead of %i]\n", rsize, size));
04206         if (feof(pf->fp)) {
04207             DEBUG_WARN(("We tried to read past the end of the file at [offset %#"PRIx64", size %#x]\n", offset, size));
04208         } else if (ferror(pf->fp)) {
04209             DEBUG_WARN(("Error is set on file stream.\n"));
04210         } else {
04211             DEBUG_WARN(("I can't tell why it failed\n"));
04212         }
04213     }
04214 
04215     DEBUG_RET();
04216     return rsize;
04217 }
04218 
04219 
04220 int pst_decrypt(uint64_t id, char *buf, size_t size, unsigned char type) {
04221     size_t x = 0;
04222     unsigned char y;
04223     DEBUG_ENT("pst_decrypt");
04224     if (!buf) {
04225         DEBUG_RET();
04226         return -1;
04227     }
04228 
04229     if (type == PST_COMP_ENCRYPT) {
04230         x = 0;
04231         while (x < size) {
04232             y = (unsigned char)(buf[x]);
04233             buf[x] = (char)comp_enc[y]; // transpose from encrypt array
04234             x++;
04235         }
04236 
04237     } else if (type == PST_ENCRYPT) {
04238         // The following code was based on the information at
04239         // http://www.passcape.com/outlook_passwords.htm
04240         uint16_t salt = (uint16_t) (((id & 0x00000000ffff0000) >> 16) ^ (id & 0x000000000000ffff));
04241         x = 0;
04242         while (x < size) {
04243             uint8_t losalt = (salt & 0x00ff);
04244             uint8_t hisalt = (salt & 0xff00) >> 8;
04245             y = (unsigned char)buf[x];
04246             y += losalt;
04247             y = comp_high1[y];
04248             y += hisalt;
04249             y = comp_high2[y];
04250             y -= hisalt;
04251             y = comp_enc[y];
04252             y -= losalt;
04253             buf[x] = (char)y;
04254             x++;
04255             salt++;
04256         }
04257 
04258     } else {
04259         WARN(("Unknown encryption: %i. Cannot decrypt\n", type));
04260         DEBUG_RET();
04261         return -1;
04262     }
04263     DEBUG_RET();
04264     return 0;
04265 }
04266 
04267 
04268 uint64_t pst_getIntAt(pst_file *pf, char *buf) {
04269     uint64_t buf64;
04270     uint32_t buf32;
04271     if (pf->do_read64) {
04272         memcpy(&buf64, buf, sizeof(buf64));
04273         LE64_CPU(buf64);
04274         return buf64;
04275     }
04276     else {
04277         memcpy(&buf32, buf, sizeof(buf32));
04278         LE32_CPU(buf32);
04279         return buf32;
04280     }
04281 }
04282 
04283 
04284 uint64_t pst_getIntAtPos(pst_file *pf, off_t pos ) {
04285     uint64_t buf64;
04286     uint32_t buf32;
04287     if (pf->do_read64) {
04288         (void)pst_getAtPos(pf, pos, &buf64, sizeof(buf64));
04289         LE64_CPU(buf64);
04290         return buf64;
04291     }
04292     else {
04293         (void)pst_getAtPos(pf, pos, &buf32, sizeof(buf32));
04294         LE32_CPU(buf32);
04295         return buf32;
04296     }
04297 }
04298 
04309 size_t pst_getAtPos(pst_file *pf, off_t pos, void* buf, size_t size) {
04310     size_t rc;
04311     DEBUG_ENT("pst_getAtPos");
04312 //  pst_block_recorder **t = &pf->block_head;
04313 //  pst_block_recorder *p = pf->block_head;
04314 //  while (p && ((p->offset+p->size) <= pos)) {
04315 //      t = &p->next;
04316 //      p = p->next;
04317 //  }
04318 //  if (p && (p->offset <= pos) && (pos < (p->offset+p->size))) {
04319 //      // bump the count
04320 //      p->readcount++;
04321 //  } else {
04322 //      // add a new block
04323 //      pst_block_recorder *tail = *t;
04324 //      p = (pst_block_recorder*)xmalloc(sizeof(*p));
04325 //      *t = p;
04326 //      p->next      = tail;
04327 //      p->offset    = pos;
04328 //      p->size      = size;
04329 //      p->readcount = 1;
04330 //  }
04331 //  DEBUG_MAIN(("pst file old offset %#"PRIx64" old size %#x read count %i offset %#"PRIx64" size %#x\n",
04332 //              p->offset, p->size, p->readcount, pos, size));
04333 
04334     if (fseeko(pf->fp, pos, SEEK_SET) == -1) {
04335         DEBUG_RET();
04336         return 0;
04337     }
04338     rc = fread(buf, (size_t)1, size, pf->fp);
04339     DEBUG_RET();
04340     return rc;
04341 }
04342 
04343 
04353 size_t pst_ff_getIDblock_dec(pst_file *pf, uint64_t id, char **buf) {
04354     size_t r;
04355     int noenc = (int)(id & 2);   // disable encryption
04356     DEBUG_ENT("pst_ff_getIDblock_dec");
04357     DEBUG_INDEX(("for id %#x\n", id));
04358     r = pst_ff_getIDblock(pf, id, buf);
04359     if ((pf->encryption) && !(noenc)) {
04360         (void)pst_decrypt(id, *buf, r, pf->encryption);
04361     }
04362     DEBUG_HEXDUMPC(*buf, r, 16);
04363     DEBUG_RET();
04364     return r;
04365 }
04366 
04367 
04376 size_t pst_ff_getIDblock(pst_file *pf, uint64_t id, char** buf) {
04377     pst_index_ll *rec;
04378     size_t rsize;
04379     DEBUG_ENT("pst_ff_getIDblock");
04380     rec = pst_getID(pf, id);
04381     if (!rec) {
04382         DEBUG_INDEX(("Cannot find ID %#"PRIx64"\n", id));
04383         DEBUG_RET();
04384         return 0;
04385     }
04386     DEBUG_INDEX(("id = %#"PRIx64", record size = %#x, offset = %#x\n", id, rec->size, rec->offset));
04387     rsize = pst_read_block_size(pf, rec->offset, rec->size, buf);
04388     DEBUG_RET();
04389     return rsize;
04390 }
04391 
04392 
04393 #define PST_PTR_BLOCK_SIZE 0x120
04394 size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_index2_ll *id2_head, char** buf) {
04395     size_t ret;
04396     pst_index_ll* ptr;
04397     pst_holder h = {buf, NULL, 0, "", 0};
04398     DEBUG_ENT("pst_ff_getID2block");
04399     ptr = pst_getID2(id2_head, id2);
04400 
04401     if (!ptr) {
04402         DEBUG_INDEX(("Cannot find id2 value %#x\n", id2));
04403         DEBUG_RET();
04404         return 0;
04405     }
04406     ret = pst_ff_getID2data(pf, ptr, &h);
04407     DEBUG_RET();
04408     return ret;
04409 }
04410 
04411 
04412 size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h) {
04413     size_t ret;
04414     char *b = NULL, *t;
04415     DEBUG_ENT("pst_ff_getID2data");
04416     if (!(ptr->id & 0x02)) {
04417         ret = pst_ff_getIDblock_dec(pf, ptr->id, &b);
04418         if (h->buf) {
04419             *(h->buf) = b;
04420         } else if ((h->base64 == 1) && h->fp) {
04421             t = base64_encode(b, ret);
04422             if (t) {
04423                 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
04424                 free(t);    // caught by valgrind
04425             }
04426             free(b);
04427         } else if (h->fp) {
04428             (void)pst_fwrite(b, (size_t)1, ret, h->fp);
04429             free(b);
04430         } else {
04431             // h-> does not specify any output
04432         }
04433 
04434     } else {
04435         // here we will assume it is a block that points to others
04436         DEBUG_READ(("Assuming it is a multi-block record because of it's id\n"));
04437         ret = pst_ff_compile_ID(pf, ptr->id, h, (size_t)0);
04438     }
04439     // bogus null termination off the end of the buffer!!
04440     //if (h->buf && *h->buf) (*(h->buf))[ret]='\0';
04441     DEBUG_RET();
04442     return ret;
04443 }
04444 
04445 
04446 size_t pst_ff_compile_ID(pst_file *pf, uint64_t id, pst_holder *h, size_t size) {
04447     size_t z, a, b;
04448     uint16_t count, y;
04449     char *buf3 = NULL, *buf2 = NULL, *t;
04450     char *b_ptr;
04451     pst_block_hdr  block_hdr;
04452     pst_table3_rec table3_rec;  //for type 3 (0x0101) blocks
04453 
04454     DEBUG_ENT("pst_ff_compile_ID");
04455     a = pst_ff_getIDblock(pf, id, &buf3);
04456     if (!a) {
04457         if (buf3) free(buf3);
04458         DEBUG_RET();
04459         return 0;
04460     }
04461     DEBUG_HEXDUMPC(buf3, a, 0x10);
04462     memcpy(&block_hdr, buf3, sizeof(block_hdr));
04463     LE16_CPU(block_hdr.index_offset);
04464     LE16_CPU(block_hdr.type);
04465     LE32_CPU(block_hdr.offset);
04466     DEBUG_EMAIL(("block header (index_offset=%#hx, type=%#hx, offset=%#x)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
04467 
04468     if (block_hdr.index_offset != (uint16_t)0x0101) { //type 3
04469         DEBUG_WARN(("WARNING: not a type 0x0101 buffer, Treating as normal buffer\n"));
04470         if (pf->encryption) (void)pst_decrypt(id, buf3, a, pf->encryption);
04471         if (h->buf)
04472             *(h->buf) = buf3;
04473         else if (h->base64 == 1 && h->fp) {
04474             t = base64_encode(buf3, a);
04475             if (t) {
04476                 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
04477                 free(t);    // caught by valgrind
04478             }
04479             free(buf3);
04480         } else if (h->fp) {
04481             (void)pst_fwrite(buf3, (size_t)1, a, h->fp);
04482             free(buf3);
04483         } else {
04484             // h-> does not specify any output
04485         }
04486         DEBUG_RET();
04487         return a;
04488     }
04489     count = block_hdr.type;
04490     b_ptr = buf3 + 8;
04491     for (y=0; y<count; y++) {
04492         b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
04493         z = pst_ff_getIDblock_dec(pf, table3_rec.id, &buf2);
04494         if (!z) {
04495             DEBUG_WARN(("call to getIDblock returned zero %i\n", z));
04496             if (buf2) free(buf2);
04497             free(buf3);
04498             DEBUG_RET();
04499             return z;
04500         }
04501         if (h->buf) {
04502             *(h->buf) = realloc(*(h->buf), size+z+1);
04503             DEBUG_READ(("appending read data of size %i onto main buffer from pos %i\n", z, size));
04504             memcpy(&((*(h->buf))[size]), buf2, z);
04505         } else if ((h->base64 == 1) && h->fp) {
04506             // include any byte left over from the last one encoding
04507             buf2 = (char*)realloc(buf2, z+h->base64_extra);
04508             memmove(buf2+h->base64_extra, buf2, z);
04509             memcpy(buf2, h->base64_extra_chars, h->base64_extra);
04510             z += h->base64_extra;
04511 
04512             b = z % 3; // find out how many bytes will be left over after the encoding.
04513             // and save them
04514             memcpy(h->base64_extra_chars, &(buf2[z-b]), b);
04515             h->base64_extra = b;
04516             t = base64_encode(buf2, z-b);
04517             if (t) {
04518                 DEBUG_READ(("writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size));
04519                 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
04520                 free(t);    // caught by valgrind
04521             }
04522         } else if (h->fp) {
04523             DEBUG_READ(("writing %i bytes to file. Currently %i\n", z, size));
04524             (void)pst_fwrite(buf2, (size_t)1, z, h->fp);
04525         } else {
04526             // h-> does not specify any output
04527         }
04528         size += z;
04529     }
04530     free(buf3);
04531     if (buf2) free(buf2);
04532     DEBUG_RET();
04533     return size;
04534 }
04535 
04536 
04537 #ifdef _MSC_VER
04538 char * fileTimeToAscii(const FILETIME* filetime) {
04539     time_t t;
04540     DEBUG_ENT("fileTimeToAscii");
04541     t = fileTimeToUnixTime(filetime, 0);
04542     if (t == -1)
04543         DEBUG_WARN(("ERROR time_t varible that was produced, is -1\n"));
04544     DEBUG_RET();
04545     return ctime(&t);
04546 }
04547 
04548 
04549 time_t fileTimeToUnixTime(const FILETIME* filetime, DWORD *x) {
04550     SYSTEMTIME s;
04551     struct tm t;
04552     DEBUG_ENT("fileTimeToUnixTime");
04553     memset (&t, 0, sizeof(struct tm));
04554     FileTimeToSystemTime(filetime, &s);
04555     t.tm_year = s.wYear-1900; // this is what is required
04556     t.tm_mon = s.wMonth-1; // also required! It made me a bit confused
04557     t.tm_mday = s.wDay;
04558     t.tm_hour = s.wHour;
04559     t.tm_min = s.wMinute;
04560     t.tm_sec = s.wSecond;
04561     DEBUG_RET();
04562     return mktime(&t);
04563 }
04564 
04565 
04566 struct tm * fileTimeToStructTM (const FILETIME *filetime) {
04567     time_t t1;
04568     t1 = fileTimeToUnixTime(filetime, 0);
04569     return gmtime(&t1);
04570 }
04571 
04572 
04573 #endif //_MSC_VER
04574 
04575 int pst_stricmp(char *a, char *b) {
04576     // compare strings case-insensitive.
04577     // returns -1 if a < b, 0 if a==b, 1 if a > b
04578     while(*a != '\0' && *b != '\0' && toupper(*a)==toupper(*b)) {
04579         a++; b++;
04580     }
04581     if (toupper(*a) == toupper(*b))
04582         return 0;
04583     else if (toupper(*a) < toupper(*b))
04584         return -1;
04585     else
04586         return 1;
04587 }
04588 
04589 
04590 int pst_strincmp(char *a, char *b, size_t x) {
04591     // compare upto x chars in string a and b case-insensitively
04592     // returns -1 if a < b, 0 if a==b, 1 if a > b
04593     size_t y = 0;
04594     while (*a != '\0' && *b != '\0' && y < x && toupper(*a)==toupper(*b)) {
04595         a++; b++; y++;
04596     }
04597     // if we have reached the end of either string, or a and b still match
04598     if (*a == '\0' || *b == '\0' || toupper(*a)==toupper(*b))
04599         return 0;
04600     else if (toupper(*a) < toupper(*b))
04601         return -1;
04602     else
04603         return 1;
04604 }
04605 
04606 
04607 size_t pst_fwrite(const void* ptr, size_t size, size_t nmemb, FILE *stream) {
04608     size_t r;
04609     DEBUG_ENT("pst_fwrite");
04610     if (ptr)
04611         r = fwrite(ptr, size, nmemb, stream);
04612     else {
04613         r = 0;
04614         DEBUG_WARN(("An attempt to write a NULL Pointer was made\n"));
04615     }
04616     DEBUG_RET();
04617     return r;
04618 }
04619 
04620 
04621 char * pst_wide_to_single(char *wt, size_t size) {
04622     // returns the first byte of each wide char. the size is the number of bytes in source
04623     char *x, *y;
04624     DEBUG_ENT("pst_wide_to_single");
04625     x = xmalloc((size/2)+1);
04626     y = x;
04627     while (size != 0 && *wt != '\0') {
04628         *y = *wt;
04629         wt+=2;
04630         size -= 2;
04631         y++;
04632     }
04633     *y = '\0';
04634     DEBUG_RET();
04635     return x;
04636 }
04637 
04638 
04639 char *pst_rfc2426_escape(char *str) {
04640     static char*  buf    = NULL;
04641     static size_t buflen = 0;
04642     char *ret, *a, *b;
04643     size_t x = 0;
04644     int y, z;
04645     DEBUG_ENT("rfc2426_escape");
04646     if (!str)
04647         ret = str;
04648     else {
04649 
04650         // calculate space required to escape all the following characters
04651         y = pst_chr_count(str, ',')
04652           + pst_chr_count(str, '\\')
04653           + pst_chr_count(str, ';')
04654           + pst_chr_count(str, '\n');
04655         z = pst_chr_count(str, '\r');
04656         if (y == 0 && z == 0)
04657             // there isn't any extra space required
04658             ret = str;
04659         else {
04660             x = strlen(str) + y - z + 1; // don't forget room for the NUL
04661             if (x > buflen) {
04662                 buf = (char*) realloc(buf, x);
04663                 buflen = x;
04664             }
04665             a = str;
04666             b = buf;
04667             while (*a != '\0') {
04668                 switch (*a) {
04669                 case ',' :
04670                 case '\\':
04671                 case ';' :
04672                     *(b++) = '\\';
04673                     *b = *a;
04674                     break;
04675                 case '\n':  // newlines are encoded as "\n"
04676                     *(b++) = '\\';
04677                     *b = 'n';
04678                     break;
04679                 case '\r':  // skip cr
04680                     b--;
04681                     break;
04682                 default:
04683                     *b=*a;
04684                 }
04685                 b++;
04686                 a++;
04687             }
04688             *b = '\0'; // NUL-terminate the string (buf)
04689             ret = buf;
04690         }
04691     }
04692     DEBUG_RET();
04693     return ret;
04694 }
04695 
04696 
04697 int pst_chr_count(char *str, char x) {
04698     int r = 0;
04699     while (*str) {
04700         if (*str == x) r++;
04701         str++;
04702     }
04703     return r;
04704 }
04705 
04706 
04707 char *pst_rfc2425_datetime_format(FILETIME *ft) {
04708     static char buffer[30];
04709     struct tm *stm = NULL;
04710     DEBUG_ENT("rfc2425_datetime_format");
04711     stm = fileTimeToStructTM(ft);
04712     if (strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", stm)==0) {
04713         DEBUG_INFO(("Problem occured formatting date\n"));
04714     }
04715     DEBUG_RET();
04716     return buffer;
04717 }
04718 
04719 
04720 char *pst_rfc2445_datetime_format(FILETIME *ft) {
04721     static char buffer[30];
04722     struct tm *stm = NULL;
04723     DEBUG_ENT("rfc2445_datetime_format");
04724     stm = fileTimeToStructTM(ft);
04725     if (strftime(buffer, sizeof(buffer), "%Y%m%dT%H%M%SZ", stm)==0) {
04726         DEBUG_INFO(("Problem occured formatting date\n"));
04727     }
04728     DEBUG_RET();
04729     return buffer;
04730 }
04731 
04732 

Generated on Tue Aug 5 12:06:14 2008 for 'LibPst' by  doxygen 1.3.9.1