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

Generated on Thu Feb 26 13:40:07 2009 for 'LibPst' by  doxygen 1.3.9.1