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