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