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