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