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