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