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
02126 static int pst_process(uint64_t block_id, pst_mapi_object *list, pst_item *item, pst_item_attach *attach) {
02127 DEBUG_ENT("pst_process");
02128 if (!item) {
02129 DEBUG_WARN(("item cannot be NULL.\n"));
02130 DEBUG_RET();
02131 return -1;
02132 }
02133
02134 item->block_id = block_id;
02135 while (list) {
02136 int32_t x;
02137 char time_buffer[30];
02138 for (x=0; x<list->count_elements; x++) {
02139 int32_t t;
02140 uint32_t ut;
02141 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));
02142
02143 switch (list->elements[x]->mapi_id) {
02144 case PST_ATTRIB_HEADER:
02145 if (list->elements[x]->extra) {
02146 if (list->elements[x]->type == 0x0101e) {
02147
02148 int32_t string_length, i, offset, next_offset;
02149 int32_t p = 0;
02150 int32_t array_element_count = PST_LE_GET_INT32(list->elements[x]->data); p+=4;
02151 for (i = 1; i <= array_element_count; i++) {
02152 pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field));
02153 memset(ef, 0, sizeof(pst_item_extra_field));
02154 offset = PST_LE_GET_INT32(list->elements[x]->data + p); p+=4;
02155 next_offset = (i == array_element_count) ? list->elements[x]->size : PST_LE_GET_INT32(list->elements[x]->data + p);;
02156 string_length = next_offset - offset;
02157 ef->value = pst_malloc(string_length + 1);
02158 memcpy(ef->value, list->elements[x]->data + offset, string_length);
02159 ef->value[string_length] = '\0';
02160 ef->field_name = strdup(list->elements[x]->extra);
02161 ef->next = item->extra_fields;
02162 item->extra_fields = ef;
02163 DEBUG_INFO(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value));
02164 }
02165 }
02166 else {
02167
02168 pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field));
02169 memset(ef, 0, sizeof(pst_item_extra_field));
02170 LIST_COPY_CSTR(ef->value);
02171 if (ef->value) {
02172 ef->field_name = strdup(list->elements[x]->extra);
02173 ef->next = item->extra_fields;
02174 item->extra_fields = ef;
02175 DEBUG_INFO(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value));
02176 if (strcmp(ef->field_name, "content-type") == 0) {
02177 char *p = strstr(ef->value, "charset=\"");
02178 if (p) {
02179 p += 9;
02180 char *pp = strchr(p, '"');
02181 if (pp) {
02182 *pp = '\0';
02183 char *set = strdup(p);
02184 *pp = '"';
02185 if (item->body_charset.str) free(item->body_charset.str);
02186 item->body_charset.str = set;
02187 item->body_charset.is_utf8 = 1;
02188 DEBUG_INFO(("body charset %s from content-type extra field\n", set));
02189 }
02190 }
02191 }
02192 }
02193 else {
02194 DEBUG_WARN(("What does this mean? Internet header %s value\n", list->elements[x]->extra));
02195 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02196 free(ef);
02197 }
02198 }
02199 }
02200 break;
02201 case 0x0002:
02202 if (list->elements[x]->type == 0x0b) {
02203
02204 LIST_COPY_EMAIL_BOOL("AutoForward allowed", item->email->autoforward);
02205 if (!item->email->autoforward) item->email->autoforward = -1;
02206 } else {
02207 DEBUG_WARN(("What does this mean?\n"));
02208 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02209 }
02210 break;
02211 case 0x0003:
02212 DEBUG_INFO(("Extended Attributes Table - NOT PROCESSED\n"));
02213 break;
02214 case 0x0017:
02215 LIST_COPY_EMAIL_ENUM("Importance Level", item->email->importance, 0, 3, "Low", "Normal", "High");
02216 break;
02217 case 0x001A:
02218 if ((list->elements[x]->type == 0x1e) ||
02219 (list->elements[x]->type == 0x1f)) {
02220 LIST_COPY_CSTR(item->ascii_type);
02221 if (!item->ascii_type) item->ascii_type = strdup("unknown");
02222 if (pst_strincmp("IPM.Note", item->ascii_type, 8) == 0)
02223 item->type = PST_TYPE_NOTE;
02224 else if (pst_stricmp("IPM", item->ascii_type) == 0)
02225 item->type = PST_TYPE_NOTE;
02226 else if (pst_strincmp("IPM.Contact", item->ascii_type, 11) == 0)
02227 item->type = PST_TYPE_CONTACT;
02228 else if (pst_strincmp("REPORT.IPM.Note", item->ascii_type, 15) == 0)
02229 item->type = PST_TYPE_REPORT;
02230 else if (pst_strincmp("IPM.Activity", item->ascii_type, 12) == 0)
02231 item->type = PST_TYPE_JOURNAL;
02232 else if (pst_strincmp("IPM.Appointment", item->ascii_type, 15) == 0)
02233 item->type = PST_TYPE_APPOINTMENT;
02234 else if (pst_strincmp("IPM.Schedule.Meeting", item->ascii_type, 20) == 0)
02235 item->type = PST_TYPE_SCHEDULE;
02236 else if (pst_strincmp("IPM.StickyNote", item->ascii_type, 14) == 0)
02237 item->type = PST_TYPE_STICKYNOTE;
02238 else if (pst_strincmp("IPM.Task", item->ascii_type, 8) == 0)
02239 item->type = PST_TYPE_TASK;
02240 else
02241 item->type = PST_TYPE_OTHER;
02242 DEBUG_INFO(("Message class %s [%"PRIi32"] \n", item->ascii_type, item->type));
02243 }
02244 else {
02245 DEBUG_WARN(("What does this mean?\n"));
02246 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02247 }
02248 break;
02249 case 0x0023:
02250 if (list->elements[x]->type == 0x0b) {
02251
02252 LIST_COPY_EMAIL_BOOL("Global Delivery Report", item->email->delivery_report);
02253 }
02254 else {
02255 DEBUG_WARN(("What does this mean?\n"));
02256 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02257 }
02258 break;
02259 case 0x0026:
02260 LIST_COPY_EMAIL_ENUM("Priority", item->email->priority, 1, 3, "NonUrgent", "Normal", "Urgent");
02261 break;
02262 case 0x0029:
02263 LIST_COPY_EMAIL_BOOL("Read Receipt", item->email->read_receipt);
02264 break;
02265 case 0x002B:
02266 LIST_COPY_BOOL("Reassignment Prohibited (Private)", item->private_member);
02267 break;
02268 case 0x002E:
02269 LIST_COPY_EMAIL_ENUM("Original Sensitivity", item->email->original_sensitivity, 0, 4,
02270 "None", "Personal", "Private", "Company Confidential");
02271 break;
02272 case 0x0032:
02273 LIST_COPY_EMAIL_TIME("Report time", item->email->report_time);
02274 break;
02275 case 0x0036:
02276 LIST_COPY_EMAIL_ENUM("Sensitivity", item->email->sensitivity, 0, 4,
02277 "None", "Personal", "Private", "Company Confidential");
02278 break;
02279 case 0x0037:
02280 {
02281 int off = 0;
02282 if ((list->elements[x]->size > 2) && (((uint8_t)list->elements[x]->data[0]) < 0x20)) {
02283 off = 2;
02284 }
02285 list->elements[x]->data += off;
02286 list->elements[x]->size -= off;
02287 LIST_COPY_STR("Raw Subject", item->subject);
02288 list->elements[x]->size += off;
02289 list->elements[x]->data -= off;
02290 }
02291 break;
02292 case 0x0039:
02293 LIST_COPY_EMAIL_TIME("Date sent", item->email->sent_date);
02294 break;
02295 case 0x003B:
02296 LIST_COPY_EMAIL_STR("Sent on behalf of address 1", item->email->outlook_sender);
02297 break;
02298 case 0x003F:
02299 DEBUG_INFO(("Recipient Structure 1 -- NOT PROCESSED\n"));
02300 break;
02301 case 0x0040:
02302 DEBUG_INFO(("Received By Name 1 -- NOT PROCESSED\n"));
02303 break;
02304 case 0x0041:
02305 DEBUG_INFO(("Sent on behalf of Structure 1 -- NOT PROCESSED\n"));
02306 break;
02307 case 0x0042:
02308 LIST_COPY_EMAIL_STR("Sent on behalf of", item->email->outlook_sender_name);
02309 break;
02310 case 0x0043:
02311 DEBUG_INFO(("Received on behalf of Structure -- NOT PROCESSED\n"));
02312 break;
02313 case 0x0044:
02314 LIST_COPY_EMAIL_STR("Received on behalf of", item->email->outlook_recipient_name);
02315 break;
02316 case 0x004F:
02317 DEBUG_INFO(("Reply-To Structure -- NOT PROCESSED\n"));
02318 break;
02319 case 0x0050:
02320 LIST_COPY_EMAIL_STR("Reply-To", item->email->reply_to);
02321 break;
02322 case 0x0051:
02323 LIST_COPY_EMAIL_STR("Recipient's Address 1", item->email->outlook_recipient);
02324 break;
02325 case 0x0052:
02326 LIST_COPY_EMAIL_STR("Recipient's Address 2", item->email->outlook_recipient2);
02327 break;
02328 case 0x0057:
02329
02330 LIST_COPY_EMAIL_BOOL("My address in TO field", item->email->message_to_me);
02331 break;
02332 case 0x0058:
02333
02334 LIST_COPY_EMAIL_BOOL("My address in CC field", item->email->message_cc_me);
02335 break;
02336 case 0x0059:
02337
02338 LIST_COPY_EMAIL_BOOL("Message addressed to me", item->email->message_recip_me);
02339 break;
02340 case 0x0063:
02341 LIST_COPY_BOOL("Response requested", item->response_requested);
02342 break;
02343 case 0x0064:
02344 LIST_COPY_EMAIL_STR("Sent on behalf of address type", item->email->sender_access);
02345 break;
02346 case 0x0065:
02347 LIST_COPY_EMAIL_STR("Sent on behalf of address", item->email->sender_address);
02348 break;
02349 case 0x0070:
02350 LIST_COPY_EMAIL_STR("Processed Subject (Conversation Topic)", item->email->processed_subject);
02351 break;
02352 case 0x0071:
02353 LIST_COPY_EMAIL_BIN("Conversation Index", item->email->conversation_index);
02354 break;
02355 case 0x0072:
02356 LIST_COPY_EMAIL_STR("Original display bcc", item->email->original_bcc);
02357 break;
02358 case 0x0073:
02359 LIST_COPY_EMAIL_STR("Original display cc", item->email->original_cc);
02360 break;
02361 case 0x0074:
02362 LIST_COPY_EMAIL_STR("Original display to", item->email->original_to);
02363 break;
02364 case 0x0075:
02365 LIST_COPY_EMAIL_STR("Received by Address type", item->email->recip_access);
02366 break;
02367 case 0x0076:
02368 LIST_COPY_EMAIL_STR("Received by Address", item->email->recip_address);
02369 break;
02370 case 0x0077:
02371 LIST_COPY_EMAIL_STR("Received on behalf of Address type", item->email->recip2_access);
02372 break;
02373 case 0x0078:
02374 LIST_COPY_EMAIL_STR("Received on behalf of Address", item->email->recip2_address);
02375 break;
02376 case 0x007D:
02377 LIST_COPY_EMAIL_STR("Internet Header", item->email->header);
02378 break;
02379 case 0x0C04:
02380 LIST_COPY_EMAIL_INT32("NDR reason code", item->email->ndr_reason_code);
02381 break;
02382 case 0x0C05:
02383 LIST_COPY_EMAIL_INT32("NDR diag code", item->email->ndr_diag_code);
02384 break;
02385 case 0x0C06:
02386 DEBUG_INFO(("Non-Receipt Notification Requested -- NOT PROCESSED\n"));
02387 break;
02388 case 0x0C17:
02389 LIST_COPY_EMAIL_BOOL("Reply Requested", item->email->reply_requested);
02390 break;
02391 case 0x0C19:
02392 DEBUG_INFO(("Sender Structure 2 -- NOT PROCESSED\n"));
02393 break;
02394 case 0x0C1A:
02395 DEBUG_INFO(("Name of Sender Structure 2 -- NOT PROCESSED\n"));
02396 break;
02397 case 0x0C1B:
02398 LIST_COPY_EMAIL_STR("Supplementary info", item->email->supplementary_info);
02399 break;
02400 case 0x0C1D:
02401 LIST_COPY_EMAIL_STR("Name of Sender Address 2 (Sender search key)", item->email->outlook_sender2);
02402 break;
02403 case 0x0C1E:
02404 LIST_COPY_EMAIL_STR("Sender Address type", item->email->sender2_access);
02405 break;
02406 case 0x0C1F:
02407 LIST_COPY_EMAIL_STR("Sender Address", item->email->sender2_address);
02408 break;
02409 case 0x0C20:
02410 LIST_COPY_EMAIL_INT32("NDR status code", item->email->ndr_status_code);
02411 break;
02412 case 0x0E01:
02413 LIST_COPY_EMAIL_BOOL("Delete after submit", item->email->delete_after_submit);
02414 break;
02415 case 0x0E02:
02416 LIST_COPY_EMAIL_STR("Display BCC Addresses", item->email->bcc_address);
02417 break;
02418 case 0x0E03:
02419 LIST_COPY_EMAIL_STR("Display CC Addresses", item->email->cc_address);
02420 break;
02421 case 0x0E04:
02422 LIST_COPY_EMAIL_STR("Display Sent-To Address", item->email->sentto_address);
02423 break;
02424 case 0x0E06:
02425 LIST_COPY_EMAIL_TIME("Date 3 (Delivery Time)", item->email->arrival_date);
02426 break;
02427 case 0x0E07:
02428 LIST_COPY_EMAIL_INT32("Message Flags", item->flags);
02429 break;
02430 case 0x0E08:
02431 LIST_COPY_INT32("Message Size", item->message_size);
02432 break;
02433 case 0x0E0A:
02434
02435 LIST_COPY_EMAIL_ENTRYID("Sentmail EntryID", item->email->sentmail_folder);
02436 break;
02437 case 0x0E1F:
02438
02439
02440
02441
02442 LIST_COPY_EMAIL_BOOL("Compressed RTF in Sync", item->email->rtf_in_sync);
02443 break;
02444 case 0x0E20:
02445 NULL_CHECK(attach);
02446 LIST_COPY_INT32("Attachment Size", t);
02447
02448
02449 break;
02450 case 0x0FF9:
02451 LIST_COPY_BIN(item->record_key);
02452 DEBUG_INFO(("Record Key\n"));
02453 DEBUG_HEXDUMP(item->record_key.data, item->record_key.size);
02454 break;
02455 case 0x1000:
02456 LIST_COPY_STR("Plain Text body", item->body);
02457 break;
02458 case 0x1001:
02459 LIST_COPY_EMAIL_STR("Report Text", item->email->report_text);
02460 break;
02461 case 0x1006:
02462 LIST_COPY_EMAIL_INT32("RTF Sync Body CRC", item->email->rtf_body_crc);
02463 break;
02464 case 0x1007:
02465
02466
02467 LIST_COPY_EMAIL_INT32("RTF Sync Body character count", item->email->rtf_body_char_count);
02468 break;
02469 case 0x1008:
02470
02471
02472 LIST_COPY_EMAIL_STR("RTF Sync body tag", item->email->rtf_body_tag);
02473 break;
02474 case 0x1009:
02475 LIST_COPY_EMAIL_BIN("RTF Compressed body", item->email->rtf_compressed);
02476 break;
02477 case 0x1010:
02478
02479 LIST_COPY_EMAIL_INT32("RTF whitespace prefix count", item->email->rtf_ws_prefix_count);
02480 break;
02481 case 0x1011:
02482
02483 LIST_COPY_EMAIL_INT32("RTF whitespace tailing count", item->email->rtf_ws_trailing_count);
02484 break;
02485 case 0x1013:
02486 LIST_COPY_EMAIL_STR("HTML body", item->email->htmlbody);
02487 break;
02488 case 0x1035:
02489 LIST_COPY_EMAIL_STR("Message ID", item->email->messageid);
02490 break;
02491 case 0x1042:
02492 LIST_COPY_EMAIL_STR("In-Reply-To", item->email->in_reply_to);
02493 break;
02494 case 0x1046:
02495 LIST_COPY_EMAIL_STR("Return Path", item->email->return_path_address);
02496 break;
02497 case 0x3001:
02498 LIST_COPY_STR("Display Name", item->file_as);
02499 break;
02500 case 0x3002:
02501 LIST_COPY_CONTACT_STR("Address Type", item->contact->address1_transport);
02502 break;
02503 case 0x3003:
02504 LIST_COPY_CONTACT_STR("Contact email Address", item->contact->address1);
02505 break;
02506 case 0x3004:
02507 LIST_COPY_STR("Comment", item->comment);
02508 break;
02509 case 0x3007:
02510 LIST_COPY_TIME("Date 4 (Item Creation Date)", item->create_date);
02511 break;
02512 case 0x3008:
02513 LIST_COPY_TIME("Date 5 (Modify Date)", item->modify_date);
02514 break;
02515 case 0x300B:
02516 DEBUG_INFO(("Record Search 2 -- NOT PROCESSED\n"));
02517 break;
02518 case 0x35DF:
02519 LIST_COPY_STORE_INT32("Valid Folder Mask", item->message_store->valid_mask);
02520 break;
02521 case 0x35E0:
02522 LIST_COPY_STORE_ENTRYID("Top of Personal Folder Record", item->message_store->top_of_personal_folder);
02523 break;
02524 case 0x35E2:
02525 LIST_COPY_STORE_ENTRYID("Default Outbox Folder record", item->message_store->default_outbox_folder);
02526 break;
02527 case 0x35E3:
02528 LIST_COPY_STORE_ENTRYID("Deleted Items Folder record", item->message_store->deleted_items_folder);
02529 break;
02530 case 0x35E4:
02531 LIST_COPY_STORE_ENTRYID("Sent Items Folder record", item->message_store->sent_items_folder);
02532 break;
02533 case 0x35E5:
02534 LIST_COPY_STORE_ENTRYID("User Views Folder record", item->message_store->user_views_folder);
02535 break;
02536 case 0x35E6:
02537 LIST_COPY_STORE_ENTRYID("Common View Folder record", item->message_store->common_view_folder);
02538 break;
02539 case 0x35E7:
02540 LIST_COPY_STORE_ENTRYID("Search Root Folder record", item->message_store->search_root_folder);
02541 break;
02542 case 0x3602:
02543 LIST_COPY_FOLDER_INT32("Folder Email Count", item->folder->item_count);
02544 break;
02545 case 0x3603:
02546 LIST_COPY_FOLDER_INT32("Unread Email Count", item->folder->unseen_item_count);
02547 break;
02548 case 0x360A:
02549 MALLOC_FOLDER(item);
02550 LIST_COPY_BOOL("Has Subfolders", item->folder->subfolder);
02551 break;
02552 case 0x3613:
02553 LIST_COPY_CSTR(item->ascii_type);
02554 if (pst_strincmp("IPF.Note", item->ascii_type, 8) == 0)
02555 item->type = PST_TYPE_NOTE;
02556 else if (pst_strincmp("IPF.Imap", item->ascii_type, 8) == 0)
02557 item->type = PST_TYPE_NOTE;
02558 else if (pst_stricmp("IPF", item->ascii_type) == 0)
02559 item->type = PST_TYPE_NOTE;
02560 else if (pst_strincmp("IPF.Contact", item->ascii_type, 11) == 0)
02561 item->type = PST_TYPE_CONTACT;
02562 else if (pst_strincmp("IPF.Journal", item->ascii_type, 11) == 0)
02563 item->type = PST_TYPE_JOURNAL;
02564 else if (pst_strincmp("IPF.Appointment", item->ascii_type, 15) == 0)
02565 item->type = PST_TYPE_APPOINTMENT;
02566 else if (pst_strincmp("IPF.StickyNote", item->ascii_type, 14) == 0)
02567 item->type = PST_TYPE_STICKYNOTE;
02568 else if (pst_strincmp("IPF.Task", item->ascii_type, 8) == 0)
02569 item->type = PST_TYPE_TASK;
02570 else
02571 item->type = PST_TYPE_OTHER;
02572
02573 DEBUG_INFO(("Container class %s [%"PRIi32"]\n", item->ascii_type, item->type));
02574 break;
02575 case 0x3617:
02576
02577
02578 LIST_COPY_FOLDER_INT32("Associated Content count", item->folder->assoc_count);
02579 break;
02580 case 0x3701:
02581 DEBUG_INFO(("Binary Data [Size %i]\n", list->elements[x]->size));
02582 NULL_CHECK(attach);
02583 if (!list->elements[x]->data) {
02584 attach->id2_val = list->elements[x]->type;
02585 DEBUG_INFO(("Seen a Reference. The data hasn't been loaded yet. [%#"PRIx64"]\n", attach->id2_val));
02586 } else {
02587 LIST_COPY_BIN(attach->data);
02588 }
02589 break;
02590 case 0x3704:
02591 NULL_CHECK(attach);
02592 LIST_COPY_STR("Attachment Filename", attach->filename1);
02593 break;
02594 case 0x3705:
02595 NULL_CHECK(attach);
02596 LIST_COPY_ENUM("Attachment method", attach->method, 0, 7,
02597 "No Attachment",
02598 "Attach By Value",
02599 "Attach By Reference",
02600 "Attach by Reference Resolve",
02601 "Attach by Reference Only",
02602 "Embedded Message",
02603 "OLE");
02604 break;
02605 case 0x3707:
02606 NULL_CHECK(attach);
02607 LIST_COPY_STR("Attachment Filename long", attach->filename2);
02608 break;
02609 case 0x370B:
02610
02611 NULL_CHECK(attach);
02612 LIST_COPY_INT32("Attachment Position", attach->position);
02613 break;
02614 case 0x370E:
02615 NULL_CHECK(attach);
02616 LIST_COPY_STR("Attachment mime encoding", attach->mimetype);
02617 break;
02618 case 0x3710:
02619
02620 NULL_CHECK(attach);
02621 LIST_COPY_INT32("Attachment Mime Sequence", attach->sequence);
02622 break;
02623 case 0x3A00:
02624 LIST_COPY_CONTACT_STR("Contact's Account name", item->contact->account_name);
02625 break;
02626 case 0x3A01:
02627 DEBUG_INFO(("Contact Alternate Recipient - NOT PROCESSED\n"));
02628 break;
02629 case 0x3A02:
02630 LIST_COPY_CONTACT_STR("Callback telephone number", item->contact->callback_phone);
02631 break;
02632 case 0x3A03:
02633 LIST_COPY_EMAIL_BOOL("Message Conversion Prohibited", item->email->conversion_prohibited);
02634 break;
02635 case 0x3A05:
02636 LIST_COPY_CONTACT_STR("Contacts Suffix", item->contact->suffix);
02637 break;
02638 case 0x3A06:
02639 LIST_COPY_CONTACT_STR("Contacts First Name", item->contact->first_name);
02640 break;
02641 case 0x3A07:
02642 LIST_COPY_CONTACT_STR("Contacts Government ID Number", item->contact->gov_id);
02643 break;
02644 case 0x3A08:
02645 LIST_COPY_CONTACT_STR("Business Telephone Number", item->contact->business_phone);
02646 break;
02647 case 0x3A09:
02648 LIST_COPY_CONTACT_STR("Home Telephone Number", item->contact->home_phone);
02649 break;
02650 case 0x3A0A:
02651 LIST_COPY_CONTACT_STR("Contacts Initials", item->contact->initials);
02652 break;
02653 case 0x3A0B:
02654 LIST_COPY_CONTACT_STR("Keyword", item->contact->keyword);
02655 break;
02656 case 0x3A0C:
02657 LIST_COPY_CONTACT_STR("Contact's Language", item->contact->language);
02658 break;
02659 case 0x3A0D:
02660 LIST_COPY_CONTACT_STR("Contact's Location", item->contact->location);
02661 break;
02662 case 0x3A0E:
02663 LIST_COPY_CONTACT_BOOL("Mail Permission", item->contact->mail_permission);
02664 break;
02665 case 0x3A0F:
02666 LIST_COPY_CONTACT_STR("MHS Common Name", item->contact->common_name);
02667 break;
02668 case 0x3A10:
02669 LIST_COPY_CONTACT_STR("Organizational ID #", item->contact->org_id);
02670 break;
02671 case 0x3A11:
02672 LIST_COPY_CONTACT_STR("Contacts Surname", item->contact->surname);
02673 break;
02674 case 0x3A12:
02675 DEBUG_INFO(("Original Entry ID - NOT PROCESSED\n"));
02676 break;
02677 case 0x3A13:
02678 DEBUG_INFO(("Original Display Name - NOT PROCESSED\n"));
02679 break;
02680 case 0x3A14:
02681 DEBUG_INFO(("Original Search Key - NOT PROCESSED\n"));
02682 break;
02683 case 0x3A15:
02684 LIST_COPY_CONTACT_STR("Default Postal Address", item->contact->def_postal_address);
02685 break;
02686 case 0x3A16:
02687 LIST_COPY_CONTACT_STR("Company Name", item->contact->company_name);
02688 break;
02689 case 0x3A17:
02690 LIST_COPY_CONTACT_STR("Job Title", item->contact->job_title);
02691 break;
02692 case 0x3A18:
02693 LIST_COPY_CONTACT_STR("Department Name", item->contact->department);
02694 break;
02695 case 0x3A19:
02696 LIST_COPY_CONTACT_STR("Office Location", item->contact->office_loc);
02697 break;
02698 case 0x3A1A:
02699 LIST_COPY_CONTACT_STR("Primary Telephone", item->contact->primary_phone);
02700 break;
02701 case 0x3A1B:
02702 LIST_COPY_CONTACT_STR("Business Phone Number 2", item->contact->business_phone2);
02703 break;
02704 case 0x3A1C:
02705 LIST_COPY_CONTACT_STR("Mobile Phone Number", item->contact->mobile_phone);
02706 break;
02707 case 0x3A1D:
02708 LIST_COPY_CONTACT_STR("Radio Phone Number", item->contact->radio_phone);
02709 break;
02710 case 0x3A1E:
02711 LIST_COPY_CONTACT_STR("Car Phone Number", item->contact->car_phone);
02712 break;
02713 case 0x3A1F:
02714 LIST_COPY_CONTACT_STR("Other Phone Number", item->contact->other_phone);
02715 break;
02716 case 0x3A20:
02717 LIST_COPY_CONTACT_STR("Transmittable Display Name", item->contact->transmittable_display_name);
02718 break;
02719 case 0x3A21:
02720 LIST_COPY_CONTACT_STR("Pager Phone Number", item->contact->pager_phone);
02721 break;
02722 case 0x3A22:
02723 DEBUG_INFO(("User Certificate - NOT PROCESSED\n"));
02724 break;
02725 case 0x3A23:
02726 LIST_COPY_CONTACT_STR("Primary Fax Number", item->contact->primary_fax);
02727 break;
02728 case 0x3A24:
02729 LIST_COPY_CONTACT_STR("Business Fax Number", item->contact->business_fax);
02730 break;
02731 case 0x3A25:
02732 LIST_COPY_CONTACT_STR("Home Fax Number", item->contact->home_fax);
02733 break;
02734 case 0x3A26:
02735 LIST_COPY_CONTACT_STR("Business Address Country", item->contact->business_country);
02736 break;
02737 case 0x3A27:
02738 LIST_COPY_CONTACT_STR("Business Address City", item->contact->business_city);
02739 break;
02740 case 0x3A28:
02741 LIST_COPY_CONTACT_STR("Business Address State", item->contact->business_state);
02742 break;
02743 case 0x3A29:
02744 LIST_COPY_CONTACT_STR("Business Address Street", item->contact->business_street);
02745 break;
02746 case 0x3A2A:
02747 LIST_COPY_CONTACT_STR("Business Postal Code", item->contact->business_postal_code);
02748 break;
02749 case 0x3A2B:
02750 LIST_COPY_CONTACT_STR("Business PO Box", item->contact->business_po_box);
02751 break;
02752 case 0x3A2C:
02753 LIST_COPY_CONTACT_STR("Telex Number", item->contact->telex);
02754 break;
02755 case 0x3A2D:
02756 LIST_COPY_CONTACT_STR("ISDN Number", item->contact->isdn_phone);
02757 break;
02758 case 0x3A2E:
02759 LIST_COPY_CONTACT_STR("Assistant Phone Number", item->contact->assistant_phone);
02760 break;
02761 case 0x3A2F:
02762 LIST_COPY_CONTACT_STR("Home Phone 2", item->contact->home_phone2);
02763 break;
02764 case 0x3A30:
02765 LIST_COPY_CONTACT_STR("Assistant's Name", item->contact->assistant_name);
02766 break;
02767 case 0x3A40:
02768 LIST_COPY_CONTACT_BOOL("Can receive Rich Text", item->contact->rich_text);
02769 break;
02770 case 0x3A41:
02771 LIST_COPY_CONTACT_TIME("Wedding Anniversary", item->contact->wedding_anniversary);
02772 break;
02773 case 0x3A42:
02774 LIST_COPY_CONTACT_TIME("Birthday", item->contact->birthday);
02775 break;
02776 case 0x3A43:
02777 LIST_COPY_CONTACT_STR("Hobbies", item->contact->hobbies);
02778 break;
02779 case 0x3A44:
02780 LIST_COPY_CONTACT_STR("Middle Name", item->contact->middle_name);
02781 break;
02782 case 0x3A45:
02783 LIST_COPY_CONTACT_STR("Display Name Prefix (Title)", item->contact->display_name_prefix);
02784 break;
02785 case 0x3A46:
02786 LIST_COPY_CONTACT_STR("Profession", item->contact->profession);
02787 break;
02788 case 0x3A47:
02789 LIST_COPY_CONTACT_STR("Preferred By Name", item->contact->pref_name);
02790 break;
02791 case 0x3A48:
02792 LIST_COPY_CONTACT_STR("Spouse's Name", item->contact->spouse_name);
02793 break;
02794 case 0x3A49:
02795 LIST_COPY_CONTACT_STR("Computer Network Name", item->contact->computer_name);
02796 break;
02797 case 0x3A4A:
02798 LIST_COPY_CONTACT_STR("Customer ID", item->contact->customer_id);
02799 break;
02800 case 0x3A4B:
02801 LIST_COPY_CONTACT_STR("TTY/TDD Phone", item->contact->ttytdd_phone);
02802 break;
02803 case 0x3A4C:
02804 LIST_COPY_CONTACT_STR("Ftp Site", item->contact->ftp_site);
02805 break;
02806 case 0x3A4D:
02807 LIST_COPY_CONTACT_ENUM16("Gender", item->contact->gender, 0, 3, "Unspecified", "Female", "Male");
02808 break;
02809 case 0x3A4E:
02810 LIST_COPY_CONTACT_STR("Manager's Name", item->contact->manager_name);
02811 break;
02812 case 0x3A4F:
02813 LIST_COPY_CONTACT_STR("Nickname", item->contact->nickname);
02814 break;
02815 case 0x3A50:
02816 LIST_COPY_CONTACT_STR("Personal Home Page", item->contact->personal_homepage);
02817 break;
02818 case 0x3A51:
02819 LIST_COPY_CONTACT_STR("Business Home Page", item->contact->business_homepage);
02820 break;
02821 case 0x3A57:
02822 LIST_COPY_CONTACT_STR("Company Main Phone", item->contact->company_main_phone);
02823 break;
02824 case 0x3A58:
02825 DEBUG_INFO(("Children's Names - NOT PROCESSED\n"));
02826 break;
02827 case 0x3A59:
02828 LIST_COPY_CONTACT_STR("Home Address City", item->contact->home_city);
02829 break;
02830 case 0x3A5A:
02831 LIST_COPY_CONTACT_STR("Home Address Country", item->contact->home_country);
02832 break;
02833 case 0x3A5B:
02834 LIST_COPY_CONTACT_STR("Home Address Postal Code", item->contact->home_postal_code);
02835 break;
02836 case 0x3A5C:
02837 LIST_COPY_CONTACT_STR("Home Address State or Province", item->contact->home_state);
02838 break;
02839 case 0x3A5D:
02840 LIST_COPY_CONTACT_STR("Home Address Street", item->contact->home_street);
02841 break;
02842 case 0x3A5E:
02843 LIST_COPY_CONTACT_STR("Home Address Post Office Box", item->contact->home_po_box);
02844 break;
02845 case 0x3A5F:
02846 LIST_COPY_CONTACT_STR("Other Address City", item->contact->other_city);
02847 break;
02848 case 0x3A60:
02849 LIST_COPY_CONTACT_STR("Other Address Country", item->contact->other_country);
02850 break;
02851 case 0x3A61:
02852 LIST_COPY_CONTACT_STR("Other Address Postal Code", item->contact->other_postal_code);
02853 break;
02854 case 0x3A62:
02855 LIST_COPY_CONTACT_STR("Other Address State", item->contact->other_state);
02856 break;
02857 case 0x3A63:
02858 LIST_COPY_CONTACT_STR("Other Address Street", item->contact->other_street);
02859 break;
02860 case 0x3A64:
02861 LIST_COPY_CONTACT_STR("Other Address Post Office box", item->contact->other_po_box);
02862 break;
02863 case 0x3FDE:
02864 LIST_COPY_INT32("Internet code page", item->internet_cpid);
02865 break;
02866 case 0x3FFD:
02867 LIST_COPY_INT32("Message code page", item->message_codepage);
02868 break;
02869 case 0x65E3:
02870 LIST_COPY_BIN(item->predecessor_change);
02871 DEBUG_INFO(("Predecessor Change\n"));
02872 DEBUG_HEXDUMP(item->predecessor_change.data, item->predecessor_change.size);
02873 break;
02874 case 0x67F2:
02875 NULL_CHECK(attach);
02876 LIST_COPY_INT32("Attachment ID2 value", ut);
02877 attach->id2_val = ut;
02878 break;
02879 case 0x67FF:
02880 LIST_COPY_STORE_INT32("Password checksum", item->message_store->pwd_chksum);
02881 break;
02882 case 0x6F02:
02883 LIST_COPY_EMAIL_BIN("Secure HTML Body", item->email->encrypted_htmlbody);
02884 break;
02885 case 0x6F04:
02886 LIST_COPY_EMAIL_BIN("Secure Text Body", item->email->encrypted_body);
02887 break;
02888 case 0x7C07:
02889 LIST_COPY_STORE_ENTRYID("Top of folders RecID", item->message_store->top_of_folder);
02890 break;
02891 case 0x8005:
02892 LIST_COPY_CONTACT_STR("Contact Fullname", item->contact->fullname);
02893 break;
02894 case 0x801A:
02895 LIST_COPY_CONTACT_STR("Home Address", item->contact->home_address);
02896 break;
02897 case 0x801B:
02898 LIST_COPY_CONTACT_STR("Business Address", item->contact->business_address);
02899 break;
02900 case 0x801C:
02901 LIST_COPY_CONTACT_STR("Other Address", item->contact->other_address);
02902 break;
02903 case 0x8045:
02904 LIST_COPY_CONTACT_STR("Work address street", item->contact->work_address_street);
02905 break;
02906 case 0x8046:
02907 LIST_COPY_CONTACT_STR("Work address city", item->contact->work_address_city);
02908 break;
02909 case 0x8047:
02910 LIST_COPY_CONTACT_STR("Work address state", item->contact->work_address_state);
02911 break;
02912 case 0x8048:
02913 LIST_COPY_CONTACT_STR("Work address postalcode", item->contact->work_address_postalcode);
02914 break;
02915 case 0x8049:
02916 LIST_COPY_CONTACT_STR("Work address country", item->contact->work_address_country);
02917 break;
02918 case 0x804A:
02919 LIST_COPY_CONTACT_STR("Work address postofficebox", item->contact->work_address_postofficebox);
02920 break;
02921 case 0x8082:
02922 LIST_COPY_CONTACT_STR("Email Address 1 Transport", item->contact->address1_transport);
02923 break;
02924 case 0x8083:
02925 LIST_COPY_CONTACT_STR("Email Address 1 Address", item->contact->address1);
02926 break;
02927 case 0x8084:
02928 LIST_COPY_CONTACT_STR("Email Address 1 Description", item->contact->address1_desc);
02929 break;
02930 case 0x8085:
02931 LIST_COPY_CONTACT_STR("Email Address 1 Record", item->contact->address1a);
02932 break;
02933 case 0x8092:
02934 LIST_COPY_CONTACT_STR("Email Address 2 Transport", item->contact->address2_transport);
02935 break;
02936 case 0x8093:
02937 LIST_COPY_CONTACT_STR("Email Address 2 Address", item->contact->address2);
02938 break;
02939 case 0x8094:
02940 LIST_COPY_CONTACT_STR("Email Address 2 Description", item->contact->address2_desc);
02941 break;
02942 case 0x8095:
02943 LIST_COPY_CONTACT_STR("Email Address 2 Record", item->contact->address2a);
02944 break;
02945 case 0x80A2:
02946 LIST_COPY_CONTACT_STR("Email Address 3 Transport", item->contact->address3_transport);
02947 break;
02948 case 0x80A3:
02949 LIST_COPY_CONTACT_STR("Email Address 3 Address", item->contact->address3);
02950 break;
02951 case 0x80A4:
02952 LIST_COPY_CONTACT_STR("Email Address 3 Description", item->contact->address3_desc);
02953 break;
02954 case 0x80A5:
02955 LIST_COPY_CONTACT_STR("Email Address 3 Record", item->contact->address3a);
02956 break;
02957 case 0x80D8:
02958 LIST_COPY_CONTACT_STR("Internet Free/Busy", item->contact->free_busy_address);
02959 break;
02960 case 0x8205:
02961 LIST_COPY_APPT_ENUM("Appointment shows as", item->appointment->showas, 0, 4,
02962 "Free", "Tentative", "Busy", "Out Of Office");
02963 break;
02964 case 0x8208:
02965 LIST_COPY_APPT_STR("Appointment Location", item->appointment->location);
02966 break;
02967 case 0x820d:
02968 LIST_COPY_APPT_TIME("Appointment Date Start", item->appointment->start);
02969 break;
02970 case 0x820e:
02971 LIST_COPY_APPT_TIME("Appointment Date End", item->appointment->end);
02972 break;
02973 case 0x8214:
02974 LIST_COPY_APPT_ENUM("Label for appointment", item->appointment->label, 0, 11,
02975 "None",
02976 "Important",
02977 "Business",
02978 "Personal",
02979 "Vacation",
02980 "Must Attend",
02981 "Travel Required",
02982 "Needs Preparation",
02983 "Birthday",
02984 "Anniversary",
02985 "Phone Call");
02986 break;
02987 case 0x8215:
02988 LIST_COPY_APPT_BOOL("All day flag", item->appointment->all_day);
02989 break;
02990 case 0x8216:
02991 LIST_COPY_APPT_BIN("Appointment recurrence data", item->appointment->recurrence_data);
02992 break;
02993 case 0x8223:
02994 LIST_COPY_APPT_BOOL("Is recurring", item->appointment->is_recurring);
02995 break;
02996 case 0x8231:
02997 LIST_COPY_APPT_ENUM("Appointment recurrence type ", item->appointment->recurrence_type, 0, 5,
02998 "None",
02999 "Daily",
03000 "Weekly",
03001 "Monthly",
03002 "Yearly");
03003 break;
03004 case 0x8232:
03005 LIST_COPY_APPT_STR("Appointment recurrence description", item->appointment->recurrence_description);
03006 break;
03007 case 0x8234:
03008 LIST_COPY_APPT_STR("TimeZone of times", item->appointment->timezonestring);
03009 break;
03010 case 0x8235:
03011 LIST_COPY_APPT_TIME("Recurrence Start Date", item->appointment->recurrence_start);
03012 break;
03013 case 0x8236:
03014 LIST_COPY_APPT_TIME("Recurrence End Date", item->appointment->recurrence_end);
03015 break;
03016 case 0x8501:
03017 LIST_COPY_APPT_INT32("Alarm minutes", item->appointment->alarm_minutes);
03018 break;
03019 case 0x8503:
03020 LIST_COPY_APPT_BOOL("Reminder alarm", item->appointment->alarm);
03021 break;
03022 case 0x8516:
03023 DEBUG_INFO(("Common Start Date - %s\n", pst_fileTimeToAscii((FILETIME*)list->elements[x]->data, time_buffer)));
03024 break;
03025 case 0x8517:
03026 DEBUG_INFO(("Common End Date - %s\n", pst_fileTimeToAscii((FILETIME*)list->elements[x]->data, time_buffer)));
03027 break;
03028 case 0x851f:
03029 LIST_COPY_APPT_STR("Appointment reminder sound filename", item->appointment->alarm_filename);
03030 break;
03031 case 0x8530:
03032 LIST_COPY_CONTACT_STR("Followup String", item->contact->followup);
03033 break;
03034 case 0x8534:
03035 LIST_COPY_CONTACT_STR("Mileage", item->contact->mileage);
03036 break;
03037 case 0x8535:
03038 LIST_COPY_CONTACT_STR("Billing Information", item->contact->billing_information);
03039 break;
03040 case 0x8554:
03041 LIST_COPY_STR("Outlook Version", item->outlook_version);
03042 break;
03043 case 0x8560:
03044 LIST_COPY_APPT_TIME("Appointment Reminder Time", item->appointment->reminder);
03045 break;
03046 case 0x8700:
03047 LIST_COPY_JOURNAL_STR("Journal Entry Type", item->journal->type);
03048 break;
03049 case 0x8706:
03050 LIST_COPY_JOURNAL_TIME("Start Timestamp", item->journal->start);
03051 break;
03052 case 0x8708:
03053 LIST_COPY_JOURNAL_TIME("End Timestamp", item->journal->end);
03054 break;
03055 case 0x8712:
03056 LIST_COPY_JOURNAL_STR("Journal description", item->journal->description);
03057 break;
03058 default:
03059 if (list->elements[x]->type == (uint32_t)0x0002) {
03060 DEBUG_WARN(("Unknown type %#x 16bit int = %hi\n", list->elements[x]->mapi_id,
03061 *(int16_t*)list->elements[x]->data));
03062
03063 } else if (list->elements[x]->type == (uint32_t)0x0003) {
03064 DEBUG_WARN(("Unknown type %#x 32bit int = %i\n", list->elements[x]->mapi_id,
03065 *(int32_t*)list->elements[x]->data));
03066
03067 } else if (list->elements[x]->type == (uint32_t)0x0004) {
03068 DEBUG_WARN(("Unknown type %#x 4-byte floating [size = %#x]\n", list->elements[x]->mapi_id,
03069 list->elements[x]->size));
03070 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03071
03072 } else if (list->elements[x]->type == (uint32_t)0x0005) {
03073 DEBUG_WARN(("Unknown type %#x double floating [size = %#x]\n", list->elements[x]->mapi_id,
03074 list->elements[x]->size));
03075 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03076
03077 } else if (list->elements[x]->type == (uint32_t)0x0006) {
03078 DEBUG_WARN(("Unknown type %#x signed 64bit int = %"PRIi64"\n", list->elements[x]->mapi_id,
03079 *(int64_t*)list->elements[x]->data));
03080 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03081
03082 } else if (list->elements[x]->type == (uint32_t)0x0007) {
03083 DEBUG_WARN(("Unknown type %#x application time [size = %#x]\n", list->elements[x]->mapi_id,
03084 list->elements[x]->size));
03085 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03086
03087 } else if (list->elements[x]->type == (uint32_t)0x000a) {
03088 DEBUG_WARN(("Unknown type %#x 32bit error value = %i\n", list->elements[x]->mapi_id,
03089 *(int32_t*)list->elements[x]->data));
03090
03091 } else if (list->elements[x]->type == (uint32_t)0x000b) {
03092 DEBUG_WARN(("Unknown type %#x 16bit boolean = %s [%hi]\n", list->elements[x]->mapi_id,
03093 (*((int16_t*)list->elements[x]->data)!=0?"True":"False"),
03094 *((int16_t*)list->elements[x]->data)));
03095
03096 } else if (list->elements[x]->type == (uint32_t)0x000d) {
03097 DEBUG_WARN(("Unknown type %#x Embedded object [size = %#x]\n", list->elements[x]->mapi_id,
03098 list->elements[x]->size));
03099 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03100
03101 } else if (list->elements[x]->type == (uint32_t)0x0014) {
03102 DEBUG_WARN(("Unknown type %#x signed 64bit int = %"PRIi64"\n", list->elements[x]->mapi_id,
03103 *(int64_t*)list->elements[x]->data));
03104 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03105
03106 } else if (list->elements[x]->type == (uint32_t)0x001e) {
03107 DEBUG_WARN(("Unknown type %#x String Data = \"%s\"\n", list->elements[x]->mapi_id,
03108 list->elements[x]->data));
03109
03110 } else if (list->elements[x]->type == (uint32_t)0x001f) {
03111 DEBUG_WARN(("Unknown type %#x Unicode String Data [size = %#x]\n", list->elements[x]->mapi_id,
03112 list->elements[x]->size));
03113 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03114
03115 } else if (list->elements[x]->type == (uint32_t)0x0040) {
03116 DEBUG_WARN(("Unknown type %#x Date = \"%s\"\n", list->elements[x]->mapi_id,
03117 pst_fileTimeToAscii((FILETIME*)list->elements[x]->data, time_buffer)));
03118
03119 } else if (list->elements[x]->type == (uint32_t)0x0048) {
03120 DEBUG_WARN(("Unknown type %#x OLE GUID [size = %#x]\n", list->elements[x]->mapi_id,
03121 list->elements[x]->size));
03122 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03123
03124 } else if (list->elements[x]->type == (uint32_t)0x0102) {
03125 DEBUG_WARN(("Unknown type %#x Binary Data [size = %#x]\n", list->elements[x]->mapi_id,
03126 list->elements[x]->size));
03127 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03128
03129 } else if (list->elements[x]->type == (uint32_t)0x1003) {
03130 DEBUG_WARN(("Unknown type %#x Array of 32 bit values [size = %#x]\n", list->elements[x]->mapi_id,
03131 list->elements[x]->size));
03132 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03133
03134 } else if (list->elements[x]->type == (uint32_t)0x1014) {
03135 DEBUG_WARN(("Unknown type %#x Array of 64 bit values [siize = %#x]\n", list->elements[x]->mapi_id,
03136 list->elements[x]->size));
03137 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03138
03139 } else if (list->elements[x]->type == (uint32_t)0x101e) {
03140 DEBUG_WARN(("Unknown type %#x Array of Strings [size = %#x]\n", list->elements[x]->mapi_id,
03141 list->elements[x]->size));
03142 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03143
03144 } else if (list->elements[x]->type == (uint32_t)0x101f) {
03145 DEBUG_WARN(("Unknown type %#x Array of Unicode Strings [size = %#x]\n", list->elements[x]->mapi_id,
03146 list->elements[x]->size));
03147 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03148
03149 } else if (list->elements[x]->type == (uint32_t)0x1102) {
03150 DEBUG_WARN(("Unknown type %#x Array of binary data blobs [size = %#x]\n", list->elements[x]->mapi_id,
03151 list->elements[x]->size));
03152 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03153
03154 } else {
03155 DEBUG_WARN(("Unknown type %#x Not Printable [%#x]\n", list->elements[x]->mapi_id,
03156 list->elements[x]->type));
03157 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03158 }
03159
03160 if (list->elements[x]->data) {
03161 free(list->elements[x]->data);
03162 list->elements[x]->data = NULL;
03163 }
03164 }
03165 }
03166 list = list->next;
03167 if (attach) attach = attach->next;
03168 }
03169 DEBUG_RET();
03170 return 0;
03171 }
03172
03173
03174 static void pst_free_list(pst_mapi_object *list) {
03175 pst_mapi_object *l;
03176 DEBUG_ENT("pst_free_list");
03177 while (list) {
03178 if (list->elements) {
03179 int32_t x;
03180 for (x=0; x < list->orig_count; x++) {
03181 if (list->elements[x]) {
03182 if (list->elements[x]->data) free(list->elements[x]->data);
03183 free(list->elements[x]);
03184 }
03185 }
03186 free(list->elements);
03187 }
03188 l = list->next;
03189 free (list);
03190 list = l;
03191 }
03192 DEBUG_RET();
03193 }
03194
03195
03196 static void pst_free_id2(pst_id2_tree * head) {
03197 pst_id2_tree *t;
03198 DEBUG_ENT("pst_free_id2");
03199 while (head) {
03200 pst_free_id2(head->child);
03201 t = head->next;
03202 free(head);
03203 head = t;
03204 }
03205 DEBUG_RET();
03206 }
03207
03208
03209 static void pst_free_id (pst_index_ll *head) {
03210 pst_index_ll *t;
03211 DEBUG_ENT("pst_free_id");
03212 while (head) {
03213 t = head->next;
03214 free(head);
03215 head = t;
03216 }
03217 DEBUG_RET();
03218 }
03219
03220
03221 static void pst_free_desc (pst_desc_tree *head) {
03222 pst_desc_tree *t;
03223 DEBUG_ENT("pst_free_desc");
03224 while (head) {
03225 pst_free_desc(head->child);
03226 t = head->next;
03227 free(head);
03228 head = t;
03229 }
03230 DEBUG_RET();
03231 }
03232
03233
03234 static void pst_free_xattrib(pst_x_attrib_ll *x) {
03235 pst_x_attrib_ll *t;
03236 DEBUG_ENT("pst_free_xattrib");
03237 while (x) {
03238 if (x->data) free(x->data);
03239 t = x->next;
03240 free(x);
03241 x = t;
03242 }
03243 DEBUG_RET();
03244 }
03245
03246
03247 static pst_id2_tree * pst_build_id2(pst_file *pf, pst_index_ll* list) {
03248 pst_block_header block_head;
03249 pst_id2_tree *head = NULL, *tail = NULL;
03250 uint16_t x = 0;
03251 char *b_ptr = NULL;
03252 char *buf = NULL;
03253 pst_id2_assoc id2_rec;
03254 pst_index_ll *i_ptr = NULL;
03255 pst_id2_tree *i2_ptr = NULL;
03256 DEBUG_ENT("pst_build_id2");
03257
03258 if (pst_read_block_size(pf, list->offset, list->size, &buf) < list->size) {
03259
03260 DEBUG_WARN(("block read error occured. offset = %#"PRIx64", size = %#"PRIx64"\n", list->offset, list->size));
03261 if (buf) free(buf);
03262 DEBUG_RET();
03263 return NULL;
03264 }
03265 DEBUG_HEXDUMPC(buf, list->size, 16);
03266
03267 memcpy(&block_head, buf, sizeof(block_head));
03268 LE16_CPU(block_head.type);
03269 LE16_CPU(block_head.count);
03270
03271 if (block_head.type != (uint16_t)0x0002) {
03272 DEBUG_WARN(("Unknown constant [%#hx] at start of id2 values [offset %#"PRIx64"].\n", block_head.type, list->offset));
03273 if (buf) free(buf);
03274 DEBUG_RET();
03275 return NULL;
03276 }
03277
03278 DEBUG_INFO(("ID %#"PRIx64" is likely to be a description record. Count is %i (offset %#"PRIx64")\n",
03279 list->i_id, block_head.count, list->offset));
03280 x = 0;
03281 b_ptr = buf + ((pf->do_read64) ? 0x08 : 0x04);
03282 while (x < block_head.count) {
03283 b_ptr += pst_decode_assoc(pf, &id2_rec, b_ptr);
03284 DEBUG_INFO(("id2 = %#x, id = %#"PRIx64", child id = %#"PRIx64"\n", id2_rec.id2, id2_rec.id, id2_rec.child_id));
03285 if ((i_ptr = pst_getID(pf, id2_rec.id)) == NULL) {
03286 DEBUG_WARN(("%#"PRIx64" - Not Found\n", id2_rec.id));
03287 } else {
03288 DEBUG_INFO(("%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %"PRIi64"(%#"PRIx64")\n",
03289 i_ptr->i_id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size));
03290
03291 i2_ptr = (pst_id2_tree*) pst_malloc(sizeof(pst_id2_tree));
03292 i2_ptr->id2 = id2_rec.id2;
03293 i2_ptr->id = i_ptr;
03294 i2_ptr->child = NULL;
03295 i2_ptr->next = NULL;
03296 if (!head) head = i2_ptr;
03297 if (tail) tail->next = i2_ptr;
03298 tail = i2_ptr;
03299 if (id2_rec.child_id) {
03300 if ((i_ptr = pst_getID(pf, id2_rec.child_id)) == NULL) {
03301 DEBUG_WARN(("child id [%#"PRIx64"] not found\n", id2_rec.child_id));
03302 }
03303 else {
03304 i2_ptr->child = pst_build_id2(pf, i_ptr);
03305 }
03306 }
03307 }
03308 x++;
03309 }
03310 if (buf) free (buf);
03311 DEBUG_RET();
03312 return head;
03313 }
03314
03315
03316 static void pst_free_attach(pst_item_attach *attach) {
03317 while (attach) {
03318 pst_item_attach *t;
03319 SAFE_FREE_STR(attach->filename1);
03320 SAFE_FREE_STR(attach->filename2);
03321 SAFE_FREE_STR(attach->mimetype);
03322 SAFE_FREE_BIN(attach->data);
03323 pst_free_id2(attach->id2_head);
03324 t = attach->next;
03325 free(attach);
03326 attach = t;
03327 }
03328 }
03329
03330
03331 void pst_freeItem(pst_item *item) {
03332 pst_item_extra_field *et;
03333
03334 DEBUG_ENT("pst_freeItem");
03335 if (item) {
03336 if (item->email) {
03337 SAFE_FREE(item->email->arrival_date);
03338 SAFE_FREE_STR(item->email->cc_address);
03339 SAFE_FREE_STR(item->email->bcc_address);
03340 SAFE_FREE_BIN(item->email->conversation_index);
03341 SAFE_FREE_BIN(item->email->encrypted_body);
03342 SAFE_FREE_BIN(item->email->encrypted_htmlbody);
03343 SAFE_FREE_STR(item->email->header);
03344 SAFE_FREE_STR(item->email->htmlbody);
03345 SAFE_FREE_STR(item->email->in_reply_to);
03346 SAFE_FREE_STR(item->email->messageid);
03347 SAFE_FREE_STR(item->email->original_bcc);
03348 SAFE_FREE_STR(item->email->original_cc);
03349 SAFE_FREE_STR(item->email->original_to);
03350 SAFE_FREE_STR(item->email->outlook_recipient);
03351 SAFE_FREE_STR(item->email->outlook_recipient_name);
03352 SAFE_FREE_STR(item->email->outlook_recipient2);
03353 SAFE_FREE_STR(item->email->outlook_sender);
03354 SAFE_FREE_STR(item->email->outlook_sender_name);
03355 SAFE_FREE_STR(item->email->outlook_sender2);
03356 SAFE_FREE_STR(item->email->processed_subject);
03357 SAFE_FREE_STR(item->email->recip_access);
03358 SAFE_FREE_STR(item->email->recip_address);
03359 SAFE_FREE_STR(item->email->recip2_access);
03360 SAFE_FREE_STR(item->email->recip2_address);
03361 SAFE_FREE_STR(item->email->reply_to);
03362 SAFE_FREE_STR(item->email->rtf_body_tag);
03363 SAFE_FREE_BIN(item->email->rtf_compressed);
03364 SAFE_FREE_STR(item->email->return_path_address);
03365 SAFE_FREE_STR(item->email->sender_access);
03366 SAFE_FREE_STR(item->email->sender_address);
03367 SAFE_FREE_STR(item->email->sender2_access);
03368 SAFE_FREE_STR(item->email->sender2_address);
03369 SAFE_FREE(item->email->sent_date);
03370 SAFE_FREE(item->email->sentmail_folder);
03371 SAFE_FREE_STR(item->email->sentto_address);
03372 SAFE_FREE_STR(item->email->report_text);
03373 SAFE_FREE(item->email->report_time);
03374 SAFE_FREE_STR(item->email->supplementary_info);
03375 free(item->email);
03376 }
03377 if (item->folder) {
03378 free(item->folder);
03379 }
03380 if (item->message_store) {
03381 SAFE_FREE(item->message_store->top_of_personal_folder);
03382 SAFE_FREE(item->message_store->default_outbox_folder);
03383 SAFE_FREE(item->message_store->deleted_items_folder);
03384 SAFE_FREE(item->message_store->sent_items_folder);
03385 SAFE_FREE(item->message_store->user_views_folder);
03386 SAFE_FREE(item->message_store->common_view_folder);
03387 SAFE_FREE(item->message_store->search_root_folder);
03388 SAFE_FREE(item->message_store->top_of_folder);
03389 free(item->message_store);
03390 }
03391 if (item->contact) {
03392 SAFE_FREE_STR(item->contact->account_name);
03393 SAFE_FREE_STR(item->contact->address1);
03394 SAFE_FREE_STR(item->contact->address1a);
03395 SAFE_FREE_STR(item->contact->address1_desc);
03396 SAFE_FREE_STR(item->contact->address1_transport);
03397 SAFE_FREE_STR(item->contact->address2);
03398 SAFE_FREE_STR(item->contact->address2a);
03399 SAFE_FREE_STR(item->contact->address2_desc);
03400 SAFE_FREE_STR(item->contact->address2_transport);
03401 SAFE_FREE_STR(item->contact->address3);
03402 SAFE_FREE_STR(item->contact->address3a);
03403 SAFE_FREE_STR(item->contact->address3_desc);
03404 SAFE_FREE_STR(item->contact->address3_transport);
03405 SAFE_FREE_STR(item->contact->assistant_name);
03406 SAFE_FREE_STR(item->contact->assistant_phone);
03407 SAFE_FREE_STR(item->contact->billing_information);
03408 SAFE_FREE(item->contact->birthday);
03409 SAFE_FREE_STR(item->contact->business_address);
03410 SAFE_FREE_STR(item->contact->business_city);
03411 SAFE_FREE_STR(item->contact->business_country);
03412 SAFE_FREE_STR(item->contact->business_fax);
03413 SAFE_FREE_STR(item->contact->business_homepage);
03414 SAFE_FREE_STR(item->contact->business_phone);
03415 SAFE_FREE_STR(item->contact->business_phone2);
03416 SAFE_FREE_STR(item->contact->business_po_box);
03417 SAFE_FREE_STR(item->contact->business_postal_code);
03418 SAFE_FREE_STR(item->contact->business_state);
03419 SAFE_FREE_STR(item->contact->business_street);
03420 SAFE_FREE_STR(item->contact->callback_phone);
03421 SAFE_FREE_STR(item->contact->car_phone);
03422 SAFE_FREE_STR(item->contact->company_main_phone);
03423 SAFE_FREE_STR(item->contact->company_name);
03424 SAFE_FREE_STR(item->contact->computer_name);
03425 SAFE_FREE_STR(item->contact->customer_id);
03426 SAFE_FREE_STR(item->contact->def_postal_address);
03427 SAFE_FREE_STR(item->contact->department);
03428 SAFE_FREE_STR(item->contact->display_name_prefix);
03429 SAFE_FREE_STR(item->contact->first_name);
03430 SAFE_FREE_STR(item->contact->followup);
03431 SAFE_FREE_STR(item->contact->free_busy_address);
03432 SAFE_FREE_STR(item->contact->ftp_site);
03433 SAFE_FREE_STR(item->contact->fullname);
03434 SAFE_FREE_STR(item->contact->gov_id);
03435 SAFE_FREE_STR(item->contact->hobbies);
03436 SAFE_FREE_STR(item->contact->home_address);
03437 SAFE_FREE_STR(item->contact->home_city);
03438 SAFE_FREE_STR(item->contact->home_country);
03439 SAFE_FREE_STR(item->contact->home_fax);
03440 SAFE_FREE_STR(item->contact->home_po_box);
03441 SAFE_FREE_STR(item->contact->home_phone);
03442 SAFE_FREE_STR(item->contact->home_phone2);
03443 SAFE_FREE_STR(item->contact->home_postal_code);
03444 SAFE_FREE_STR(item->contact->home_state);
03445 SAFE_FREE_STR(item->contact->home_street);
03446 SAFE_FREE_STR(item->contact->initials);
03447 SAFE_FREE_STR(item->contact->isdn_phone);
03448 SAFE_FREE_STR(item->contact->job_title);
03449 SAFE_FREE_STR(item->contact->keyword);
03450 SAFE_FREE_STR(item->contact->language);
03451 SAFE_FREE_STR(item->contact->location);
03452 SAFE_FREE_STR(item->contact->manager_name);
03453 SAFE_FREE_STR(item->contact->middle_name);
03454 SAFE_FREE_STR(item->contact->mileage);
03455 SAFE_FREE_STR(item->contact->mobile_phone);
03456 SAFE_FREE_STR(item->contact->nickname);
03457 SAFE_FREE_STR(item->contact->office_loc);
03458 SAFE_FREE_STR(item->contact->common_name);
03459 SAFE_FREE_STR(item->contact->org_id);
03460 SAFE_FREE_STR(item->contact->other_address);
03461 SAFE_FREE_STR(item->contact->other_city);
03462 SAFE_FREE_STR(item->contact->other_country);
03463 SAFE_FREE_STR(item->contact->other_phone);
03464 SAFE_FREE_STR(item->contact->other_po_box);
03465 SAFE_FREE_STR(item->contact->other_postal_code);
03466 SAFE_FREE_STR(item->contact->other_state);
03467 SAFE_FREE_STR(item->contact->other_street);
03468 SAFE_FREE_STR(item->contact->pager_phone);
03469 SAFE_FREE_STR(item->contact->personal_homepage);
03470 SAFE_FREE_STR(item->contact->pref_name);
03471 SAFE_FREE_STR(item->contact->primary_fax);
03472 SAFE_FREE_STR(item->contact->primary_phone);
03473 SAFE_FREE_STR(item->contact->profession);
03474 SAFE_FREE_STR(item->contact->radio_phone);
03475 SAFE_FREE_STR(item->contact->spouse_name);
03476 SAFE_FREE_STR(item->contact->suffix);
03477 SAFE_FREE_STR(item->contact->surname);
03478 SAFE_FREE_STR(item->contact->telex);
03479 SAFE_FREE_STR(item->contact->transmittable_display_name);
03480 SAFE_FREE_STR(item->contact->ttytdd_phone);
03481 SAFE_FREE(item->contact->wedding_anniversary);
03482 SAFE_FREE_STR(item->contact->work_address_street);
03483 SAFE_FREE_STR(item->contact->work_address_city);
03484 SAFE_FREE_STR(item->contact->work_address_state);
03485 SAFE_FREE_STR(item->contact->work_address_postalcode);
03486 SAFE_FREE_STR(item->contact->work_address_country);
03487 SAFE_FREE_STR(item->contact->work_address_postofficebox);
03488 free(item->contact);
03489 }
03490
03491 pst_free_attach(item->attach);
03492
03493 while (item->extra_fields) {
03494 SAFE_FREE(item->extra_fields->field_name);
03495 SAFE_FREE(item->extra_fields->value);
03496 et = item->extra_fields->next;
03497 free(item->extra_fields);
03498 item->extra_fields = et;
03499 }
03500 if (item->journal) {
03501 SAFE_FREE(item->journal->start);
03502 SAFE_FREE(item->journal->end);
03503 SAFE_FREE_STR(item->journal->type);
03504 free(item->journal);
03505 }
03506 if (item->appointment) {
03507 SAFE_FREE(item->appointment->start);
03508 SAFE_FREE(item->appointment->end);
03509 SAFE_FREE_STR(item->appointment->location);
03510 SAFE_FREE(item->appointment->reminder);
03511 SAFE_FREE_STR(item->appointment->alarm_filename);
03512 SAFE_FREE_STR(item->appointment->timezonestring);
03513 SAFE_FREE_STR(item->appointment->recurrence_description);
03514 SAFE_FREE_BIN(item->appointment->recurrence_data);
03515 SAFE_FREE(item->appointment->recurrence_start);
03516 SAFE_FREE(item->appointment->recurrence_end);
03517 free(item->appointment);
03518 }
03519 SAFE_FREE(item->ascii_type);
03520 SAFE_FREE_STR(item->body_charset);
03521 SAFE_FREE_STR(item->body);
03522 SAFE_FREE_STR(item->subject);
03523 SAFE_FREE_STR(item->comment);
03524 SAFE_FREE(item->create_date);
03525 SAFE_FREE_STR(item->file_as);
03526 SAFE_FREE(item->modify_date);
03527 SAFE_FREE_STR(item->outlook_version);
03528 SAFE_FREE_BIN(item->record_key);
03529 SAFE_FREE_BIN(item->predecessor_change);
03530 free(item);
03531 }
03532 DEBUG_RET();
03533 }
03534
03535
03542 static int pst_getBlockOffsetPointer(pst_file *pf, pst_id2_tree *i2_head, pst_subblocks *subblocks, uint32_t offset, pst_block_offset_pointer *p) {
03543 size_t size;
03544 pst_block_offset block_offset;
03545 DEBUG_ENT("pst_getBlockOffsetPointer");
03546 if (p->needfree) free(p->from);
03547 p->from = NULL;
03548 p->to = NULL;
03549 p->needfree = 0;
03550 if (!offset) {
03551
03552 p->from = p->to = NULL;
03553 }
03554 else if ((offset & 0xf) == (uint32_t)0xf) {
03555
03556 DEBUG_WARN(("Found id2 %#x value. Will follow it\n", offset));
03557 size = pst_ff_getID2block(pf, offset, i2_head, &(p->from));
03558 if (size) {
03559 p->to = p->from + size;
03560 p->needfree = 1;
03561 }
03562 else {
03563 if (p->from) {
03564 DEBUG_WARN(("size zero but non-null pointer\n"));
03565 free(p->from);
03566 }
03567 p->from = p->to = NULL;
03568 }
03569 }
03570 else {
03571
03572 size_t subindex = offset >> 16;
03573 size_t suboffset = offset & 0xffff;
03574 if (subindex < subblocks->subblock_count) {
03575 if (pst_getBlockOffset(subblocks->subs[subindex].buf,
03576 subblocks->subs[subindex].read_size,
03577 subblocks->subs[subindex].i_offset,
03578 suboffset, &block_offset)) {
03579 p->from = subblocks->subs[subindex].buf + block_offset.from;
03580 p->to = subblocks->subs[subindex].buf + block_offset.to;
03581 }
03582 }
03583 }
03584 DEBUG_RET();
03585 return (p->from) ? 0 : 1;
03586 }
03587
03588
03590 static int pst_getBlockOffset(char *buf, size_t read_size, uint32_t i_offset, uint32_t offset, pst_block_offset *p) {
03591 uint32_t low = offset & 0xf;
03592 uint32_t of1 = offset >> 4;
03593 DEBUG_ENT("pst_getBlockOffset");
03594 if (!p || !buf || !i_offset || low || (i_offset+2+of1+sizeof(*p) > read_size)) {
03595 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));
03596 DEBUG_RET();
03597 return 0;
03598 }
03599 memcpy(&(p->from), &(buf[(i_offset+2)+of1]), sizeof(p->from));
03600 memcpy(&(p->to), &(buf[(i_offset+2)+of1+sizeof(p->from)]), sizeof(p->to));
03601 LE16_CPU(p->from);
03602 LE16_CPU(p->to);
03603 DEBUG_WARN(("get block offset finds from=%i(%#x), to=%i(%#x)\n", p->from, p->from, p->to, p->to));
03604 if (p->from > p->to) {
03605 DEBUG_WARN(("get block offset from > to\n"));
03606 DEBUG_RET();
03607 return 0;
03608 }
03609 DEBUG_RET();
03610 return 1;
03611 }
03612
03613
03615 pst_index_ll* pst_getID(pst_file* pf, uint64_t i_id) {
03616 pst_index_ll *ptr;
03617 DEBUG_ENT("pst_getID");
03618 if (i_id == 0) {
03619 DEBUG_RET();
03620 return NULL;
03621 }
03622
03623
03624
03625 i_id -= (i_id & 1);
03626
03627 DEBUG_INFO(("Trying to find %#"PRIx64"\n", i_id));
03628 ptr = pf->i_head;
03629 while (ptr && (ptr->i_id != i_id)) {
03630 ptr = ptr->next;
03631 }
03632 if (ptr) {DEBUG_INFO(("Found Value %#"PRIx64"\n", i_id)); }
03633 else {DEBUG_INFO(("ERROR: Value %#"PRIx64" not found\n", i_id)); }
03634 DEBUG_RET();
03635 return ptr;
03636 }
03637
03638
03639 static pst_id2_tree *pst_getID2(pst_id2_tree *head, uint64_t id2) {
03640 DEBUG_ENT("pst_getID2");
03641 DEBUG_INFO(("looking for id2 = %#"PRIx64"\n", id2));
03642 pst_id2_tree *ptr = head;
03643 while (ptr) {
03644 if (ptr->id2 == id2) break;
03645 if (ptr->child) {
03646 pst_id2_tree *rc = pst_getID2(ptr->child, id2);
03647 if (rc) {
03648 DEBUG_RET();
03649 return rc;
03650 }
03651 }
03652 ptr = ptr->next;
03653 }
03654 if (ptr && ptr->id) {
03655 DEBUG_INFO(("Found value %#"PRIx64"\n", ptr->id->i_id));
03656 DEBUG_RET();
03657 return ptr;
03658 }
03659 DEBUG_INFO(("ERROR Not Found\n"));
03660 DEBUG_RET();
03661 return NULL;
03662 }
03663
03664
03673 static pst_desc_tree* pst_getDptr(pst_file *pf, uint64_t d_id) {
03674 pst_desc_tree *ptr = pf->d_head;
03675 DEBUG_ENT("pst_getDptr");
03676 while (ptr && (ptr->d_id != d_id)) {
03677
03678 if (ptr->child) {
03679 ptr = ptr->child;
03680 continue;
03681 }
03682 while (!ptr->next && ptr->parent) {
03683 ptr = ptr->parent;
03684 }
03685 ptr = ptr->next;
03686 }
03687 DEBUG_RET();
03688 return ptr;
03689 }
03690
03691
03692 static void pst_printDptr(pst_file *pf, pst_desc_tree *ptr) {
03693 DEBUG_ENT("pst_printDptr");
03694 while (ptr) {
03695 DEBUG_INFO(("%#"PRIx64" [%i] desc=%#"PRIx64", assoc tree=%#"PRIx64"\n", ptr->d_id, ptr->no_child,
03696 (ptr->desc ? ptr->desc->i_id : (uint64_t)0),
03697 (ptr->assoc_tree ? ptr->assoc_tree->i_id : (uint64_t)0)));
03698 if (ptr->child) {
03699 pst_printDptr(pf, ptr->child);
03700 }
03701 ptr = ptr->next;
03702 }
03703 DEBUG_RET();
03704 }
03705
03706
03707 static void pst_printID2ptr(pst_id2_tree *ptr) {
03708 DEBUG_ENT("pst_printID2ptr");
03709 while (ptr) {
03710 DEBUG_INFO(("%#"PRIx64" id=%#"PRIx64"\n", ptr->id2, (ptr->id ? ptr->id->i_id : (uint64_t)0)));
03711 if (ptr->child) pst_printID2ptr(ptr->child);
03712 ptr = ptr->next;
03713 }
03714 DEBUG_RET();
03715 }
03716
03717
03727 static size_t pst_read_block_size(pst_file *pf, int64_t offset, size_t size, char **buf) {
03728 size_t rsize;
03729 DEBUG_ENT("pst_read_block_size");
03730 DEBUG_INFO(("Reading block from %#"PRIx64", %x bytes\n", offset, size));
03731
03732 if (*buf) {
03733 DEBUG_INFO(("Freeing old memory\n"));
03734 free(*buf);
03735 }
03736 *buf = (char*) pst_malloc(size);
03737
03738 rsize = pst_getAtPos(pf, offset, *buf, size);
03739 if (rsize != size) {
03740 DEBUG_WARN(("Didn't read all the data. fread returned less [%i instead of %i]\n", rsize, size));
03741 if (feof(pf->fp)) {
03742 DEBUG_WARN(("We tried to read past the end of the file at [offset %#"PRIx64", size %#x]\n", offset, size));
03743 } else if (ferror(pf->fp)) {
03744 DEBUG_WARN(("Error is set on file stream.\n"));
03745 } else {
03746 DEBUG_WARN(("I can't tell why it failed\n"));
03747 }
03748 }
03749
03750 DEBUG_RET();
03751 return rsize;
03752 }
03753
03754
03765 static int pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type) {
03766 size_t x = 0;
03767 unsigned char y;
03768 DEBUG_ENT("pst_decrypt");
03769 if (!buf) {
03770 DEBUG_RET();
03771 return -1;
03772 }
03773
03774 if (type == PST_COMP_ENCRYPT) {
03775 x = 0;
03776 while (x < size) {
03777 y = (unsigned char)(buf[x]);
03778 buf[x] = (char)comp_enc[y];
03779 x++;
03780 }
03781
03782 } else if (type == PST_ENCRYPT) {
03783
03784
03785 uint16_t salt = (uint16_t) (((i_id & 0x00000000ffff0000) >> 16) ^ (i_id & 0x000000000000ffff));
03786 x = 0;
03787 while (x < size) {
03788 uint8_t losalt = (salt & 0x00ff);
03789 uint8_t hisalt = (salt & 0xff00) >> 8;
03790 y = (unsigned char)buf[x];
03791 y += losalt;
03792 y = comp_high1[y];
03793 y += hisalt;
03794 y = comp_high2[y];
03795 y -= hisalt;
03796 y = comp_enc[y];
03797 y -= losalt;
03798 buf[x] = (char)y;
03799 x++;
03800 salt++;
03801 }
03802
03803 } else {
03804 DEBUG_WARN(("Unknown encryption: %i. Cannot decrypt\n", type));
03805 DEBUG_RET();
03806 return -1;
03807 }
03808 DEBUG_RET();
03809 return 0;
03810 }
03811
03812
03813 static uint64_t pst_getIntAt(pst_file *pf, char *buf) {
03814 uint64_t buf64;
03815 uint32_t buf32;
03816 if (pf->do_read64) {
03817 memcpy(&buf64, buf, sizeof(buf64));
03818 LE64_CPU(buf64);
03819 return buf64;
03820 }
03821 else {
03822 memcpy(&buf32, buf, sizeof(buf32));
03823 LE32_CPU(buf32);
03824 return buf32;
03825 }
03826 }
03827
03828
03829 static uint64_t pst_getIntAtPos(pst_file *pf, int64_t pos ) {
03830 uint64_t buf64;
03831 uint32_t buf32;
03832 if (pf->do_read64) {
03833 (void)pst_getAtPos(pf, pos, &buf64, sizeof(buf64));
03834 LE64_CPU(buf64);
03835 return buf64;
03836 }
03837 else {
03838 (void)pst_getAtPos(pf, pos, &buf32, sizeof(buf32));
03839 LE32_CPU(buf32);
03840 return buf32;
03841 }
03842 }
03843
03853 static size_t pst_getAtPos(pst_file *pf, int64_t pos, void* buf, size_t size) {
03854 size_t rc;
03855 DEBUG_ENT("pst_getAtPos");
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878 if (fseeko(pf->fp, pos, SEEK_SET) == -1) {
03879 DEBUG_RET();
03880 return 0;
03881 }
03882 rc = fread(buf, (size_t)1, size, pf->fp);
03883 DEBUG_RET();
03884 return rc;
03885 }
03886
03887
03896 size_t pst_ff_getIDblock_dec(pst_file *pf, uint64_t i_id, char **buf) {
03897 size_t r;
03898 int noenc = (int)(i_id & 2);
03899 DEBUG_ENT("pst_ff_getIDblock_dec");
03900 DEBUG_INFO(("for id %#"PRIx64"\n", i_id));
03901 r = pst_ff_getIDblock(pf, i_id, buf);
03902 if ((pf->encryption) && !(noenc)) {
03903 (void)pst_decrypt(i_id, *buf, r, pf->encryption);
03904 }
03905 DEBUG_HEXDUMPC(*buf, r, 16);
03906 DEBUG_RET();
03907 return r;
03908 }
03909
03910
03919 static size_t pst_ff_getIDblock(pst_file *pf, uint64_t i_id, char** buf) {
03920 pst_index_ll *rec;
03921 size_t rsize;
03922 DEBUG_ENT("pst_ff_getIDblock");
03923 rec = pst_getID(pf, i_id);
03924 if (!rec) {
03925 DEBUG_INFO(("Cannot find ID %#"PRIx64"\n", i_id));
03926 DEBUG_RET();
03927 return 0;
03928 }
03929 DEBUG_INFO(("id = %#"PRIx64", record size = %#x, offset = %#x\n", i_id, rec->size, rec->offset));
03930 rsize = pst_read_block_size(pf, rec->offset, rec->size, buf);
03931 DEBUG_RET();
03932 return rsize;
03933 }
03934
03935
03936 static size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_id2_tree *id2_head, char** buf) {
03937 size_t ret;
03938 pst_id2_tree* ptr;
03939 pst_holder h = {buf, NULL, 0, 0, 0};
03940 DEBUG_ENT("pst_ff_getID2block");
03941 ptr = pst_getID2(id2_head, id2);
03942
03943 if (!ptr) {
03944 DEBUG_WARN(("Cannot find id2 value %#"PRIx64"\n", id2));
03945 DEBUG_RET();
03946 return 0;
03947 }
03948 ret = pst_ff_getID2data(pf, ptr->id, &h);
03949 DEBUG_RET();
03950 return ret;
03951 }
03952
03953
03962 static size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h) {
03963 size_t ret;
03964 char *b = NULL;
03965 DEBUG_ENT("pst_ff_getID2data");
03966 if (!(ptr->i_id & 0x02)) {
03967 ret = pst_ff_getIDblock_dec(pf, ptr->i_id, &b);
03968 ret = pst_append_holder(h, (size_t)0, &b, ret);
03969 free(b);
03970 } else {
03971
03972 DEBUG_INFO(("Assuming it is a multi-block record because of it's id %#"PRIx64"\n", ptr->i_id));
03973 ret = pst_ff_compile_ID(pf, ptr->i_id, h, (size_t)0);
03974 }
03975 ret = pst_finish_cleanup_holder(h, ret);
03976 DEBUG_RET();
03977 return ret;
03978 }
03979
03980
03990 static size_t pst_ff_compile_ID(pst_file *pf, uint64_t i_id, pst_holder *h, size_t size) {
03991 size_t z, a;
03992 uint16_t count, y;
03993 char *buf3 = NULL;
03994 char *buf2 = NULL;
03995 char *b_ptr;
03996 pst_block_hdr block_hdr;
03997 pst_table3_rec table3_rec;
03998
03999 DEBUG_ENT("pst_ff_compile_ID");
04000 a = pst_ff_getIDblock(pf, i_id, &buf3);
04001 if (!a) {
04002 if (buf3) free(buf3);
04003 DEBUG_RET();
04004 return 0;
04005 }
04006 DEBUG_HEXDUMPC(buf3, a, 16);
04007 memcpy(&block_hdr, buf3, sizeof(block_hdr));
04008 LE16_CPU(block_hdr.index_offset);
04009 LE16_CPU(block_hdr.type);
04010 LE32_CPU(block_hdr.offset);
04011 DEBUG_INFO(("block header (index_offset=%#hx, type=%#hx, offset=%#x)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
04012
04013 count = block_hdr.type;
04014 b_ptr = buf3 + 8;
04015
04016
04017
04018
04019 if (block_hdr.index_offset == (uint16_t)0x0201) {
04020 for (y=0; y<count; y++) {
04021 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
04022 size = pst_ff_compile_ID(pf, table3_rec.id, h, size);
04023 }
04024 free(buf3);
04025 DEBUG_RET();
04026 return size;
04027 }
04028
04029 if (block_hdr.index_offset != (uint16_t)0x0101) {
04030 DEBUG_WARN(("WARNING: not a type 0x0101 buffer, Treating as normal buffer\n"));
04031 if (pf->encryption) (void)pst_decrypt(i_id, buf3, a, pf->encryption);
04032 size = pst_append_holder(h, size, &buf3, a);
04033 free(buf3);
04034 DEBUG_RET();
04035 return size;
04036 }
04037
04038 for (y=0; y<count; y++) {
04039 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
04040 z = pst_ff_getIDblock_dec(pf, table3_rec.id, &buf2);
04041 if (!z) {
04042 DEBUG_WARN(("call to getIDblock returned zero %i\n", z));
04043 if (buf2) free(buf2);
04044 free(buf3);
04045 DEBUG_RET();
04046 return z;
04047 }
04048 size = pst_append_holder(h, size, &buf2, z);
04049 }
04050
04051 free(buf3);
04052 if (buf2) free(buf2);
04053 DEBUG_RET();
04054 return size;
04055 }
04056
04057
04066 static size_t pst_append_holder(pst_holder *h, size_t size, char **buf, size_t z) {
04067 char *t;
04068 DEBUG_ENT("pst_append_holder");
04069
04070
04071 if (h->buf) {
04072 *(h->buf) = pst_realloc(*(h->buf), size+z+1);
04073 DEBUG_INFO(("appending read data of size %i onto main buffer from pos %i\n", z, size));
04074 memcpy(*(h->buf)+size, *buf, z);
04075
04076
04077 } else if ((h->base64 == 1) && h->fp) {
04078
04079 if (h->base64_extra) {
04080
04081 *buf = (char*)pst_realloc(*buf, z+h->base64_extra);
04082 memmove(*buf+h->base64_extra, *buf, z);
04083 memcpy(*buf, h->base64_extra_chars, h->base64_extra);
04084 z += h->base64_extra;
04085 }
04086
04087
04088 h->base64_extra = z % 3;
04089 if (h->base64_extra) {
04090 z -= h->base64_extra;
04091 memcpy(h->base64_extra_chars, *buf+z, h->base64_extra);
04092 }
04093
04094
04095 t = pst_base64_encode_multiple(*buf, z, &h->base64_line_count);
04096 if (t) {
04097 DEBUG_INFO(("writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size));
04098 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
04099 free(t);
04100 }
04101
04102
04103 } else if (h->fp) {
04104 DEBUG_INFO(("writing %i bytes to file. Currently %i\n", z, size));
04105 (void)pst_fwrite(*buf, (size_t)1, z, h->fp);
04106
04107
04108 } else {
04109
04110 }
04111 DEBUG_RET();
04112 return size+z;
04113 }
04114
04115
04122 static size_t pst_finish_cleanup_holder(pst_holder *h, size_t size) {
04123 char *t;
04124 DEBUG_ENT("pst_finish_cleanup_holder");
04125 if ((h->base64 == 1) && h->fp && h->base64_extra) {
04126
04127 t = pst_base64_encode_multiple(h->base64_extra_chars, h->base64_extra, &h->base64_line_count);
04128 if (t) {
04129 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
04130 free(t);
04131 }
04132 size += h->base64_extra;
04133 }
04134 DEBUG_RET();
04135 return size;
04136 }
04137
04138
04139 static int pst_stricmp(char *a, char *b) {
04140
04141
04142 while(*a != '\0' && *b != '\0' && toupper(*a)==toupper(*b)) {
04143 a++; b++;
04144 }
04145 if (toupper(*a) == toupper(*b))
04146 return 0;
04147 else if (toupper(*a) < toupper(*b))
04148 return -1;
04149 else
04150 return 1;
04151 }
04152
04153
04154 static int pst_strincmp(char *a, char *b, size_t x) {
04155
04156
04157 size_t y = 0;
04158 while (*a != '\0' && *b != '\0' && y < x && toupper(*a)==toupper(*b)) {
04159 a++; b++; y++;
04160 }
04161
04162 if (*a == '\0' || *b == '\0' || toupper(*a)==toupper(*b))
04163 return 0;
04164 else if (toupper(*a) < toupper(*b))
04165 return -1;
04166 else
04167 return 1;
04168 }
04169
04170
04171 size_t pst_fwrite(const void* ptr, size_t size, size_t nmemb, FILE *stream) {
04172 size_t r;
04173 if (ptr)
04174 r = fwrite(ptr, size, nmemb, stream);
04175 else {
04176 r = 0;
04177 DEBUG_ENT("pst_fwrite");
04178 DEBUG_WARN(("An attempt to write a NULL Pointer was made\n"));
04179 DEBUG_RET();
04180 }
04181 return r;
04182 }
04183
04184
04185 static char* pst_wide_to_single(char *wt, size_t size) {
04186
04187 char *x, *y;
04188 DEBUG_ENT("pst_wide_to_single");
04189 x = pst_malloc((size/2)+1);
04190 y = x;
04191 while (size != 0 && *wt != '\0') {
04192 *y = *wt;
04193 wt+=2;
04194 size -= 2;
04195 y++;
04196 }
04197 *y = '\0';
04198 DEBUG_RET();
04199 return x;
04200 }
04201
04202
04203 char* pst_rfc2426_escape(char* str, char **buf, size_t* buflen) {
04204
04205
04206 char *ret, *a, *b;
04207 size_t x = 0;
04208 int y, z;
04209 if (!str) return NULL;
04210 DEBUG_ENT("rfc2426_escape");
04211
04212 y = pst_chr_count(str, ',')
04213 + pst_chr_count(str, '\\')
04214 + pst_chr_count(str, ';')
04215 + pst_chr_count(str, '\n');
04216 z = pst_chr_count(str, '\r');
04217 if (y == 0 && z == 0)
04218
04219 ret = str;
04220 else {
04221 x = strlen(str) + y - z + 1;
04222 if (x > *buflen) {
04223 *buf = (char*)pst_realloc(*buf, x);
04224 *buflen = x;
04225 }
04226 a = str;
04227 b = *buf;
04228 while (*a != '\0') {
04229 switch (*a) {
04230 case ',' :
04231 case '\\':
04232 case ';' :
04233 *(b++) = '\\';
04234 *b = *a;
04235 break;
04236 case '\n':
04237 *(b++) = '\\';
04238 *b = 'n';
04239 break;
04240 case '\r':
04241 b--;
04242 break;
04243 default:
04244 *b=*a;
04245 }
04246 b++;
04247 a++;
04248 }
04249 *b = '\0';
04250 ret = *buf;
04251 }
04252 DEBUG_RET();
04253 return ret;
04254 }
04255
04256
04257 static int pst_chr_count(char *str, char x) {
04258 int r = 0;
04259 while (*str) {
04260 if (*str == x) r++;
04261 str++;
04262 }
04263 return r;
04264 }
04265
04266
04267 char* pst_rfc2425_datetime_format(const FILETIME* ft, int buflen, char* result) {
04268 struct tm stm;
04269 DEBUG_ENT("rfc2425_datetime_format");
04270 pst_fileTimeToStructTM(ft, &stm);
04271 if (strftime(result, buflen, "%Y-%m-%dT%H:%M:%SZ", &stm)==0) {
04272 DEBUG_INFO(("Problem occured formatting date\n"));
04273 }
04274 DEBUG_RET();
04275 return result;
04276 }
04277
04278
04279 char* pst_rfc2445_datetime_format(const FILETIME* ft, int buflen, char* result) {
04280 struct tm stm;
04281 DEBUG_ENT("rfc2445_datetime_format");
04282 pst_fileTimeToStructTM(ft, &stm);
04283 if (strftime(result, buflen, "%Y%m%dT%H%M%SZ", &stm)==0) {
04284 DEBUG_INFO(("Problem occured formatting date\n"));
04285 }
04286 DEBUG_RET();
04287 return result;
04288 }
04289
04290
04291 char* pst_rfc2445_datetime_format_now(int buflen, char* result) {
04292 struct tm stm;
04293 time_t t = time(NULL);
04294 DEBUG_ENT("rfc2445_datetime_format_now");
04295 gmtime_r(&t, &stm);
04296 if (strftime(result, buflen, "%Y%m%dT%H%M%SZ", &stm)==0) {
04297 DEBUG_INFO(("Problem occured formatting date\n"));
04298 }
04299 DEBUG_RET();
04300 return result;
04301 }
04302
04303
04312 static const char* codepage(int cp, int buflen, char* result);
04313 static const char* codepage(int cp, int buflen, char* result) {
04314 switch (cp) {
04315 case 932 : return "iso-2022-jp";
04316 case 936 : return "gb2313";
04317 case 950 : return "big5";
04318 case 1200 : return "ucs-2le";
04319 case 1201 : return "ucs-2be";
04320 case 20127 : return "us-ascii";
04321 case 20269 : return "iso-6937";
04322 case 20865 : return "iso-8859-15";
04323 case 20866 : return "koi8-r";
04324 case 21866 : return "koi8-u";
04325 case 28591 : return "iso-8859-1";
04326 case 28592 : return "iso-8859-2";
04327 case 28595 : return "iso-8859-5";
04328 case 28596 : return "iso-8859-6";
04329 case 28597 : return "iso-8859-7";
04330 case 28598 : return "iso-8859-8";
04331 case 28599 : return "iso-8859-9";
04332 case 28600 : return "iso-8859-10";
04333 case 28601 : return "iso-8859-11";
04334 case 28602 : return "iso-8859-12";
04335 case 28603 : return "iso-8859-13";
04336 case 28604 : return "iso-8859-14";
04337 case 28605 : return "iso-8859-15";
04338 case 28606 : return "iso-8859-16";
04339 case 50220 : return "iso-2022-jp";
04340 case 50221 : return "csiso2022jp";
04341 case 51932 : return "euc-jp";
04342 case 51949 : return "euc-kr";
04343 case 65000 : return "utf-7";
04344 case 65001 : return "utf-8";
04345 default :
04346 snprintf(result, buflen, "windows-%d", cp);
04347 return result;
04348 }
04349 return NULL;
04350 }
04351
04352
04361 const char* pst_default_charset(pst_item *item, int buflen, char* result) {
04362 return (item->body_charset.str) ? item->body_charset.str :
04363 (item->message_codepage) ? codepage(item->message_codepage, buflen, result) :
04364 (item->internet_cpid) ? codepage(item->internet_cpid, buflen, result) :
04365 (item->pf && item->pf->charset) ? item->pf->charset :
04366 "iso-8859-1";
04367 }
04368
04369
04374 void pst_rfc2231(pst_string *str) {
04375 int needs = 0;
04376 const int8_t *x = (int8_t *)str->str;
04377 while (*x) {
04378 if (*x <= 32) needs++;
04379 x++;
04380 }
04381 int n = strlen(str->str) + 2*needs + 15;
04382 char *buffer = pst_malloc(n);
04383 strcpy(buffer, "utf-8''");
04384 x = (int8_t *)str->str;
04385 const uint8_t *y = (uint8_t *)str->str;
04386 uint8_t *z = (uint8_t *)buffer;
04387 z += strlen(buffer);
04388 while (*y) {
04389 if (*x <= 32) {
04390 *(z++) = (uint8_t)'%';
04391 snprintf(z, 3, "%2x", *y);
04392 z += 2;
04393 }
04394 else {
04395 *(z++) = *y;
04396 }
04397 x++;
04398 y++;
04399 }
04400 *z = '\0';
04401 free(str->str);
04402 str->str = buffer;
04403 }
04404
04405
04412 void pst_rfc2047(pst_item *item, pst_string *str, int needs_quote) {
04413 int has_space = 0;
04414 int needs_coding = 0;
04415 pst_convert_utf8(item, str);
04416 const int8_t *x = (int8_t *)str->str;
04417 while (*x) {
04418 if (*x == 32) has_space = 1;
04419 if (*x < 32) needs_coding = 1;
04420 x++;
04421 }
04422 if (needs_coding) {
04423 char *enc = pst_base64_encode_single(str->str, strlen(str->str));
04424 free(str->str);
04425 int n = strlen(enc) + 20;
04426 str->str = pst_malloc(n);
04427 snprintf(str->str, n, "=?utf-8?B?%s?=", enc);
04428 free(enc);
04429 }
04430 else if (has_space && needs_quote) {
04431 int n = strlen(str->str) + 10;
04432 char *buffer = pst_malloc(n);
04433 snprintf(buffer, n, "\"%s\"", str->str);
04434 free(str->str);
04435 str->str = buffer;
04436 }
04437 }
04438
04439
04445 void pst_convert_utf8_null(pst_item *item, pst_string *str) {
04446 if (!str->str) return;
04447 pst_convert_utf8(item, str);
04448 }
04449
04450
04456 void pst_convert_utf8(pst_item *item, pst_string *str) {
04457 DEBUG_ENT("pst_convert_utf8");
04458 char buffer[30];
04459 if (str->is_utf8) {
04460 DEBUG_WARN(("Already utf8\n"));
04461 DEBUG_RET();
04462 return;
04463 }
04464 if (!str->str) {
04465 str->str = strdup("");
04466 DEBUG_WARN(("null to empty string\n"));
04467 DEBUG_RET();
04468 return;
04469 }
04470 const char *charset = pst_default_charset(item, sizeof(buffer), buffer);
04471 DEBUG_WARN(("default charset is %s\n", charset));
04472 if (!strcasecmp("utf-8", charset)) {
04473 DEBUG_RET();
04474 return;
04475 }
04476 pst_vbuf *newer = pst_vballoc(2);
04477 size_t rc = pst_vb_8bit2utf8(newer, str->str, strlen(str->str) + 1, charset);
04478 if (rc == (size_t)-1) {
04479 free(newer->b);
04480 DEBUG_WARN(("Failed to convert %s to utf-8 - %s\n", charset, str->str));
04481 }
04482 else {
04483 free(str->str);
04484 str->str = newer->b;
04485 str->is_utf8 = 1;
04486 }
04487 free(newer);
04488 DEBUG_RET();
04489 }
04490
04491
04496 pst_recurrence* pst_convert_recurrence(pst_item_appointment* appt)
04497 {
04498 const int bias = 30 * 24 * 60;
04499 int m[4] = {3,4,4,5};
04500 pst_recurrence *r = pst_malloc(sizeof(pst_recurrence));
04501 memset(r, 0, sizeof(pst_recurrence));
04502 size_t s = appt->recurrence_data.size;
04503 size_t i = 0;
04504 char* p = appt->recurrence_data.data;
04505 if (p) {
04506 if (i+4 <= s) { r->signature = PST_LE_GET_UINT32(p+i); i += 4; }
04507 if (i <= s) { r->type = PST_LE_GET_UINT8(p+i) - 0x0a; i += 2; }
04508 if (i+4 <= s) { r->sub_type = PST_LE_GET_UINT32(p+i); i += 4; }
04509 if (r->sub_type <= 3) {
04510 int n = m[r->sub_type];
04511 int j = 0;
04512 for (j=0; j<n; j++) {
04513 if (i+4 <= s) { *(&r->parm1 + j) = PST_LE_GET_UINT32(p+i); i += 4; }
04514 }
04515 }
04516 if (i <= s) { r->termination = PST_LE_GET_UINT8(p+i) - 0x21; i += 4; }
04517 if (i+4 <= s) { r->count = PST_LE_GET_UINT32(p+i); i += 4; }
04518 if (r->termination == 2) r->count = 0;
04519 switch (r->type) {
04520 case 0:
04521 if (r->sub_type == 0) {
04522
04523 r->interval = r->parm2 / (24 * 60);
04524 }
04525 else {
04526
04527 r->interval = 1;
04528 r->bydaymask = r->parm4;
04529 }
04530 break;
04531 case 1:
04532 r->interval = r->parm2;
04533 r->bydaymask = r->parm4;
04534 break;
04535 case 2:
04536 r->interval = r->parm2;
04537 if (r->sub_type == 2) {
04538
04539 r->dayofmonth = r->parm4;
04540 }
04541 else {
04542
04543 r->bydaymask = r->parm4;
04544 r->position = r->parm5;
04545 }
04546 break;
04547 case 3:
04548 r->interval = 1;
04549 r->monthofyear = ((r->parm1 + bias/2) / bias) + 1;
04550 if (r->sub_type == 2) {
04551
04552 r->dayofmonth = r->parm4;
04553 }
04554 else {
04555
04556 r->bydaymask = r->parm4;
04557 r->position = r->parm5;
04558 }
04559 break;
04560 default:
04561 break;
04562 }
04563 }
04564 return r;
04565 }
04566
04567
04571 void pst_free_recurrence(pst_recurrence* r)
04572 {
04573 if (r) free(r);
04574 }