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