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