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

Generated on Thu Dec 11 11:58:49 2008 for 'LibPst' by  doxygen 1.3.9.1