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

Generated on Sat Feb 7 10:22:05 2009 for 'LibPst' by  doxygen 1.3.9.1