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