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 if (pst_process(list, item, attach)) {
01331 DEBUG_WARN(("ERROR pst_process() failed with an attachment\n"));
01332 pst_free_list(list);
01333 continue;
01334 }
01335 pst_free_list(list);
01336 id2_ptr = pst_getID2(id2_head, attach->id2_val);
01337 if (id2_ptr) {
01338 DEBUG_WARN(("second pass attachment updating id2 found i_id %#"PRIx64"\n", id2_ptr->id->i_id));
01339
01340
01341 attach->i_id = id2_ptr->id->i_id;
01342 attach->id2_head = deep_copy(id2_ptr->child);
01343 } else {
01344 DEBUG_WARN(("have not located the correct value for the attachment [%#"PRIx64"]\n", attach->id2_val));
01345 }
01346 } else {
01347 DEBUG_WARN(("ERROR cannot locate id2 value %#"PRIx64"\n", attach->id2_val));
01348 attach->id2_val = 0;
01349 }
01350 }
01351 }
01352
01353 if (!m_head) pst_free_id2(id2_head);
01354 DEBUG_RET();
01355 return item;
01356 }
01357
01358
01359 static void freeall(pst_subblocks *subs, pst_block_offset_pointer *p1,
01360 pst_block_offset_pointer *p2,
01361 pst_block_offset_pointer *p3,
01362 pst_block_offset_pointer *p4,
01363 pst_block_offset_pointer *p5,
01364 pst_block_offset_pointer *p6,
01365 pst_block_offset_pointer *p7);
01366 static void freeall(pst_subblocks *subs, pst_block_offset_pointer *p1,
01367 pst_block_offset_pointer *p2,
01368 pst_block_offset_pointer *p3,
01369 pst_block_offset_pointer *p4,
01370 pst_block_offset_pointer *p5,
01371 pst_block_offset_pointer *p6,
01372 pst_block_offset_pointer *p7) {
01373 size_t i;
01374 for (i=0; i<subs->subblock_count; i++) {
01375 if (subs->subs[i].buf) free(subs->subs[i].buf);
01376 }
01377 free(subs->subs);
01378 if (p1->needfree) free(p1->from);
01379 if (p2->needfree) free(p2->from);
01380 if (p3->needfree) free(p3->from);
01381 if (p4->needfree) free(p4->from);
01382 if (p5->needfree) free(p5->from);
01383 if (p6->needfree) free(p6->from);
01384 if (p7->needfree) free(p7->from);
01385 }
01386
01387
01393 static pst_mapi_object* pst_parse_block(pst_file *pf, uint64_t block_id, pst_id2_tree *i2_head) {
01394 pst_mapi_object *mo_head = NULL;
01395 char *buf = NULL;
01396 size_t read_size = 0;
01397 pst_subblocks subblocks;
01398 pst_mapi_object *mo_ptr = NULL;
01399 pst_block_offset_pointer block_offset1;
01400 pst_block_offset_pointer block_offset2;
01401 pst_block_offset_pointer block_offset3;
01402 pst_block_offset_pointer block_offset4;
01403 pst_block_offset_pointer block_offset5;
01404 pst_block_offset_pointer block_offset6;
01405 pst_block_offset_pointer block_offset7;
01406 int32_t x;
01407 int32_t num_mapi_objects;
01408 int32_t count_mapi_objects;
01409 int32_t num_mapi_elements;
01410 int32_t count_mapi_elements;
01411 int block_type;
01412 uint32_t rec_size = 0;
01413 char* list_start;
01414 char* fr_ptr;
01415 char* to_ptr;
01416 char* ind2_end = NULL;
01417 char* ind2_ptr = NULL;
01418 pst_x_attrib_ll *mapptr;
01419 pst_block_hdr block_hdr;
01420 pst_table3_rec table3_rec;
01421
01422 struct {
01423 unsigned char seven_c;
01424 unsigned char item_count;
01425 uint16_t u1;
01426 uint16_t u2;
01427 uint16_t u3;
01428 uint16_t rec_size;
01429 uint32_t b_five_offset;
01430 uint32_t ind2_offset;
01431 uint16_t u7;
01432 uint16_t u8;
01433 } seven_c_blk;
01434
01435 struct _type_d_rec {
01436 uint32_t id;
01437 uint32_t u1;
01438 } * type_d_rec;
01439
01440 struct {
01441 uint16_t type;
01442 uint16_t ref_type;
01443 uint32_t value;
01444 } table_rec;
01445
01446 struct {
01447 uint16_t ref_type;
01448 uint16_t type;
01449 uint16_t ind2_off;
01450 uint8_t size;
01451 uint8_t slot;
01452 } table2_rec;
01453
01454 DEBUG_ENT("pst_parse_block");
01455 if ((read_size = pst_ff_getIDblock_dec(pf, block_id, &buf)) == 0) {
01456 DEBUG_WARN(("Error reading block id %#"PRIx64"\n", block_id));
01457 if (buf) free (buf);
01458 DEBUG_RET();
01459 return NULL;
01460 }
01461
01462 block_offset1.needfree = 0;
01463 block_offset2.needfree = 0;
01464 block_offset3.needfree = 0;
01465 block_offset4.needfree = 0;
01466 block_offset5.needfree = 0;
01467 block_offset6.needfree = 0;
01468 block_offset7.needfree = 0;
01469
01470 memcpy(&block_hdr, buf, sizeof(block_hdr));
01471 LE16_CPU(block_hdr.index_offset);
01472 LE16_CPU(block_hdr.type);
01473 LE32_CPU(block_hdr.offset);
01474 DEBUG_INFO(("block header (index_offset=%#hx, type=%#hx, offset=%#hx)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
01475
01476 if (block_hdr.index_offset == (uint16_t)0x0101) {
01477 size_t i;
01478 char *b_ptr = buf + 8;
01479 subblocks.subblock_count = block_hdr.type;
01480 subblocks.subs = malloc(sizeof(pst_subblock) * subblocks.subblock_count);
01481 for (i=0; i<subblocks.subblock_count; i++) {
01482 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
01483 subblocks.subs[i].buf = NULL;
01484 subblocks.subs[i].read_size = pst_ff_getIDblock_dec(pf, table3_rec.id, &subblocks.subs[i].buf);
01485 if (subblocks.subs[i].buf) {
01486 memcpy(&block_hdr, subblocks.subs[i].buf, sizeof(block_hdr));
01487 LE16_CPU(block_hdr.index_offset);
01488 subblocks.subs[i].i_offset = block_hdr.index_offset;
01489 }
01490 else {
01491 subblocks.subs[i].read_size = 0;
01492 subblocks.subs[i].i_offset = 0;
01493 }
01494 }
01495 free(buf);
01496 memcpy(&block_hdr, subblocks.subs[0].buf, sizeof(block_hdr));
01497 LE16_CPU(block_hdr.index_offset);
01498 LE16_CPU(block_hdr.type);
01499 LE32_CPU(block_hdr.offset);
01500 DEBUG_INFO(("block header (index_offset=%#hx, type=%#hx, offset=%#hx)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
01501 }
01502 else {
01503
01504 subblocks.subblock_count = (size_t)1;
01505 subblocks.subs = malloc(sizeof(pst_subblock));
01506 subblocks.subs[0].buf = buf;
01507 subblocks.subs[0].read_size = read_size;
01508 subblocks.subs[0].i_offset = block_hdr.index_offset;
01509 }
01510
01511 if (block_hdr.type == (uint16_t)0xBCEC) {
01512 block_type = 1;
01513
01514 if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, block_hdr.offset, &block_offset1)) {
01515 DEBUG_WARN(("internal error (bc.b5 offset %#x) in reading block id %#"PRIx64"\n", block_hdr.offset, block_id));
01516 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01517 DEBUG_RET();
01518 return NULL;
01519 }
01520 memcpy(&table_rec, block_offset1.from, sizeof(table_rec));
01521 LE16_CPU(table_rec.type);
01522 LE16_CPU(table_rec.ref_type);
01523 LE32_CPU(table_rec.value);
01524 DEBUG_INFO(("table_rec (type=%#hx, ref_type=%#hx, value=%#x)\n", table_rec.type, table_rec.ref_type, table_rec.value));
01525
01526 if ((table_rec.type != (uint16_t)0x02B5) || (table_rec.ref_type != 6)) {
01527 DEBUG_WARN(("Unknown second block constant - %#hx %#hx for id %#"PRIx64"\n", table_rec.type, table_rec.ref_type, block_id));
01528 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01529 DEBUG_RET();
01530 return NULL;
01531 }
01532
01533 if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset2)) {
01534 DEBUG_WARN(("internal error (bc.b5.desc offset #x) in reading block id %#"PRIx64"\n", table_rec.value, block_id));
01535 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01536 DEBUG_RET();
01537 return NULL;
01538 }
01539 list_start = block_offset2.from;
01540 to_ptr = block_offset2.to;
01541 num_mapi_elements = (to_ptr - list_start)/sizeof(table_rec);
01542 num_mapi_objects = 1;
01543 }
01544 else if (block_hdr.type == (uint16_t)0x7CEC) {
01545 block_type = 2;
01546
01547 if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, block_hdr.offset, &block_offset3)) {
01548 DEBUG_WARN(("internal error (7c.7c offset %#x) in reading block id %#"PRIx64"\n", block_hdr.offset, block_id));
01549 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01550 DEBUG_RET();
01551 return NULL;
01552 }
01553 fr_ptr = block_offset3.from;
01554 memset(&seven_c_blk, 0, sizeof(seven_c_blk));
01555 memcpy(&seven_c_blk, fr_ptr, sizeof(seven_c_blk));
01556 LE16_CPU(seven_c_blk.u1);
01557 LE16_CPU(seven_c_blk.u2);
01558 LE16_CPU(seven_c_blk.u3);
01559 LE16_CPU(seven_c_blk.rec_size);
01560 LE32_CPU(seven_c_blk.b_five_offset);
01561 LE32_CPU(seven_c_blk.ind2_offset);
01562 LE16_CPU(seven_c_blk.u7);
01563 LE16_CPU(seven_c_blk.u8);
01564
01565 list_start = fr_ptr + sizeof(seven_c_blk);
01566
01567 if (seven_c_blk.seven_c != 0x7C) {
01568 DEBUG_WARN(("Error. There isn't a 7C where I want to see 7C!\n"));
01569 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01570 DEBUG_RET();
01571 return NULL;
01572 }
01573
01574 rec_size = seven_c_blk.rec_size;
01575 num_mapi_elements = (int32_t)(unsigned)seven_c_blk.item_count;
01576
01577 if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, seven_c_blk.b_five_offset, &block_offset4)) {
01578 DEBUG_WARN(("internal error (7c.b5 offset %#x) in reading block id %#"PRIx64"\n", seven_c_blk.b_five_offset, block_id));
01579 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01580 DEBUG_RET();
01581 return NULL;
01582 }
01583 memcpy(&table_rec, block_offset4.from, sizeof(table_rec));
01584 LE16_CPU(table_rec.type);
01585 LE16_CPU(table_rec.ref_type);
01586 LE32_CPU(table_rec.value);
01587 DEBUG_INFO(("table_rec (type=%#hx, ref_type=%#hx, value=%#x)\n", table_rec.type, table_rec.ref_type, table_rec.value));
01588
01589 if (table_rec.type != (uint16_t)0x04B5) {
01590 DEBUG_WARN(("Unknown second block constant - %#hx for id %#"PRIx64"\n", table_rec.type, block_id));
01591 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01592 DEBUG_RET();
01593 return NULL;
01594 }
01595
01596 if (table_rec.value > 0) {
01597 if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset5)) {
01598 DEBUG_WARN(("internal error (7c.b5.desc offset %#x) in reading block id %#"PRIx64"\n", table_rec.value, block_id));
01599 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01600 DEBUG_RET();
01601 return NULL;
01602 }
01603
01604
01605 num_mapi_objects = (block_offset5.to - block_offset5.from) / (4 + table_rec.ref_type);
01606
01607 if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, seven_c_blk.ind2_offset, &block_offset6)) {
01608 DEBUG_WARN(("internal error (7c.ind2 offset %#x) in reading block id %#"PRIx64"\n", seven_c_blk.ind2_offset, block_id));
01609 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01610 DEBUG_RET();
01611 return NULL;
01612 }
01613 ind2_ptr = block_offset6.from;
01614 ind2_end = block_offset6.to;
01615 }
01616 else {
01617 num_mapi_objects = 0;
01618 }
01619 DEBUG_INFO(("7cec block index2 pointer %#x and end %#x\n", ind2_ptr, ind2_end));
01620 }
01621 else {
01622 DEBUG_WARN(("ERROR: Unknown block constant - %#hx for id %#"PRIx64"\n", block_hdr.type, block_id));
01623 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01624 DEBUG_RET();
01625 return NULL;
01626 }
01627
01628 DEBUG_INFO(("found %i mapi objects each with %i mapi elements\n", num_mapi_objects, num_mapi_elements));
01629 for (count_mapi_objects=0; count_mapi_objects<num_mapi_objects; count_mapi_objects++) {
01630
01631 mo_ptr = (pst_mapi_object*) pst_malloc(sizeof(pst_mapi_object));
01632 memset(mo_ptr, 0, sizeof(pst_mapi_object));
01633 mo_ptr->next = mo_head;
01634 mo_head = mo_ptr;
01635
01636 mo_ptr->elements = (pst_mapi_element**) pst_malloc(sizeof(pst_mapi_element)*num_mapi_elements);
01637 mo_ptr->count_elements = num_mapi_elements;
01638 mo_ptr->orig_count = num_mapi_elements;
01639 mo_ptr->count_objects = (int32_t)num_mapi_objects;
01640 for (x=0; x<num_mapi_elements; x++) mo_ptr->elements[x] = NULL;
01641
01642 DEBUG_INFO(("going to read %i mapi elements for mapi object %i\n", num_mapi_elements, count_mapi_objects));
01643
01644 fr_ptr = list_start;
01645 x = 0;
01646 for (count_mapi_elements=0; count_mapi_elements<num_mapi_elements; count_mapi_elements++) {
01647 char* value_pointer = NULL;
01648 size_t value_size = 0;
01649 if (block_type == 1) {
01650 memcpy(&table_rec, fr_ptr, sizeof(table_rec));
01651 LE16_CPU(table_rec.type);
01652 LE16_CPU(table_rec.ref_type);
01653
01654 fr_ptr += sizeof(table_rec);
01655 } else if (block_type == 2) {
01656
01657 memcpy(&table2_rec, fr_ptr, sizeof(table2_rec));
01658 LE16_CPU(table2_rec.ref_type);
01659 LE16_CPU(table2_rec.type);
01660 LE16_CPU(table2_rec.ind2_off);
01661 DEBUG_INFO(("reading element %i (type=%#x, ref_type=%#x, offset=%#x, size=%#x)\n",
01662 x, table2_rec.type, table2_rec.ref_type, table2_rec.ind2_off, table2_rec.size));
01663
01664
01665 table_rec.type = table2_rec.type;
01666 table_rec.ref_type = table2_rec.ref_type;
01667 table_rec.value = 0;
01668 if ((ind2_end - ind2_ptr) >= (int)(table2_rec.ind2_off + table2_rec.size)) {
01669 size_t n = table2_rec.size;
01670 size_t m = sizeof(table_rec.value);
01671 if (n <= m) {
01672 memcpy(&table_rec.value, ind2_ptr + table2_rec.ind2_off, n);
01673 }
01674 else {
01675 value_pointer = ind2_ptr + table2_rec.ind2_off;
01676 value_size = n;
01677 }
01678
01679 }
01680 else {
01681 DEBUG_WARN (("Trying to read outside buffer, buffer size %#x, offset %#x, data size %#x\n",
01682 read_size, ind2_end-ind2_ptr+table2_rec.ind2_off, table2_rec.size));
01683 }
01684 fr_ptr += sizeof(table2_rec);
01685 } else {
01686 DEBUG_WARN(("Missing code for block_type %i\n", block_type));
01687 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01688 pst_free_list(mo_head);
01689 DEBUG_RET();
01690 return NULL;
01691 }
01692 DEBUG_INFO(("reading element %i (type=%#x, ref_type=%#x, value=%#x)\n",
01693 x, table_rec.type, table_rec.ref_type, table_rec.value));
01694
01695 if (!mo_ptr->elements[x]) {
01696 mo_ptr->elements[x] = (pst_mapi_element*) pst_malloc(sizeof(pst_mapi_element));
01697 }
01698 memset(mo_ptr->elements[x], 0, sizeof(pst_mapi_element));
01699
01700
01701 mapptr = pf->x_head;
01702 while (mapptr && (mapptr->map < table_rec.type)) mapptr = mapptr->next;
01703 if (mapptr && (mapptr->map == table_rec.type)) {
01704 if (mapptr->mytype == PST_MAP_ATTRIB) {
01705 mo_ptr->elements[x]->mapi_id = *((uint32_t*)mapptr->data);
01706 DEBUG_INFO(("Mapped attrib %#x to %#x\n", table_rec.type, mo_ptr->elements[x]->mapi_id));
01707 } else if (mapptr->mytype == PST_MAP_HEADER) {
01708 DEBUG_INFO(("Internet Header mapping found %#"PRIx32" to %s\n", table_rec.type, mapptr->data));
01709 mo_ptr->elements[x]->mapi_id = (uint32_t)PST_ATTRIB_HEADER;
01710 mo_ptr->elements[x]->extra = mapptr->data;
01711 }
01712 else {
01713 DEBUG_WARN(("Missing assertion failure\n"));
01714
01715 }
01716 } else {
01717 mo_ptr->elements[x]->mapi_id = table_rec.type;
01718 }
01719 mo_ptr->elements[x]->type = 0;
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742 if (table_rec.ref_type == (uint16_t)0x0002 ||
01743 table_rec.ref_type == (uint16_t)0x0003 ||
01744 table_rec.ref_type == (uint16_t)0x000b) {
01745
01746 mo_ptr->elements[x]->size = sizeof(int32_t);
01747 mo_ptr->elements[x]->type = table_rec.ref_type;
01748 mo_ptr->elements[x]->data = pst_malloc(sizeof(int32_t));
01749 memcpy(mo_ptr->elements[x]->data, &(table_rec.value), sizeof(int32_t));
01750
01751
01752
01753 } else if (table_rec.ref_type == (uint16_t)0x0005 ||
01754 table_rec.ref_type == (uint16_t)0x000d ||
01755 table_rec.ref_type == (uint16_t)0x0014 ||
01756 table_rec.ref_type == (uint16_t)0x001e ||
01757 table_rec.ref_type == (uint16_t)0x001f ||
01758 table_rec.ref_type == (uint16_t)0x0040 ||
01759 table_rec.ref_type == (uint16_t)0x0048 ||
01760 table_rec.ref_type == (uint16_t)0x0102 ||
01761 table_rec.ref_type == (uint16_t)0x1003 ||
01762 table_rec.ref_type == (uint16_t)0x1014 ||
01763 table_rec.ref_type == (uint16_t)0x101e ||
01764 table_rec.ref_type == (uint16_t)0x101f ||
01765 table_rec.ref_type == (uint16_t)0x1102) {
01766
01767 LE32_CPU(table_rec.value);
01768 if (value_pointer) {
01769
01770
01771 mo_ptr->elements[x]->size = value_size;
01772 mo_ptr->elements[x]->type = table_rec.ref_type;
01773 mo_ptr->elements[x]->data = pst_malloc(value_size);
01774 memcpy(mo_ptr->elements[x]->data, value_pointer, value_size);
01775 }
01776 else if (pst_getBlockOffsetPointer(pf, i2_head, &subblocks, table_rec.value, &block_offset7)) {
01777 if ((table_rec.value & 0xf) == (uint32_t)0xf) {
01778 DEBUG_WARN(("failed to get block offset for table_rec.value of %#x to be read later.\n", table_rec.value));
01779 mo_ptr->elements[x]->size = 0;
01780 mo_ptr->elements[x]->data = NULL;
01781 mo_ptr->elements[x]->type = table_rec.value;
01782 }
01783 else {
01784 if (table_rec.value) {
01785 DEBUG_WARN(("failed to get block offset for table_rec.value of %#x\n", table_rec.value));
01786 }
01787 mo_ptr->count_elements --;
01788 continue;
01789 }
01790 }
01791 else {
01792 value_size = (size_t)(block_offset7.to - block_offset7.from);
01793 mo_ptr->elements[x]->size = value_size;
01794 mo_ptr->elements[x]->type = table_rec.ref_type;
01795 mo_ptr->elements[x]->data = pst_malloc(value_size+1);
01796 memcpy(mo_ptr->elements[x]->data, block_offset7.from, value_size);
01797 mo_ptr->elements[x]->data[value_size] = '\0';
01798 }
01799 if (table_rec.ref_type == (uint16_t)0xd) {
01800
01801 type_d_rec = (struct _type_d_rec*) mo_ptr->elements[x]->data;
01802 LE32_CPU(type_d_rec->id);
01803 mo_ptr->elements[x]->size = pst_ff_getID2block(pf, type_d_rec->id, i2_head, &(mo_ptr->elements[x]->data));
01804 if (!mo_ptr->elements[x]->size){
01805 DEBUG_WARN(("not able to read the ID2 data. Setting to be read later. %#x\n", type_d_rec->id));
01806 mo_ptr->elements[x]->type = type_d_rec->id;
01807 free(mo_ptr->elements[x]->data);
01808 mo_ptr->elements[x]->data = NULL;
01809 }
01810 }
01811 if (table_rec.ref_type == (uint16_t)0x1f) {
01812
01813 size_t rc;
01814 static pst_vbuf *utf16buf = NULL;
01815 static pst_vbuf *utf8buf = NULL;
01816 if (!utf16buf) utf16buf = pst_vballoc((size_t)1024);
01817 if (!utf8buf) utf8buf = pst_vballoc((size_t)1024);
01818
01819
01820 pst_vbset(utf16buf, mo_ptr->elements[x]->data, mo_ptr->elements[x]->size);
01821 pst_vbappend(utf16buf, "\0\0", (size_t)2);
01822 DEBUG_INFO(("Iconv in:\n"));
01823 DEBUG_HEXDUMPC(utf16buf->b, utf16buf->dlen, 0x10);
01824 rc = pst_vb_utf16to8(utf8buf, utf16buf->b, utf16buf->dlen);
01825 if (rc == (size_t)-1) {
01826 DEBUG_WARN(("Failed to convert utf-16 to utf-8\n"));
01827 }
01828 else {
01829 free(mo_ptr->elements[x]->data);
01830 mo_ptr->elements[x]->size = utf8buf->dlen;
01831 mo_ptr->elements[x]->data = pst_malloc(utf8buf->dlen);
01832 memcpy(mo_ptr->elements[x]->data, utf8buf->b, utf8buf->dlen);
01833 }
01834 DEBUG_INFO(("Iconv out:\n"));
01835 DEBUG_HEXDUMPC(mo_ptr->elements[x]->data, mo_ptr->elements[x]->size, 0x10);
01836 }
01837 if (mo_ptr->elements[x]->type == 0) mo_ptr->elements[x]->type = table_rec.ref_type;
01838 } else {
01839 DEBUG_WARN(("ERROR Unknown ref_type %#hx\n", table_rec.ref_type));
01840 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01841 pst_free_list(mo_head);
01842 DEBUG_RET();
01843 return NULL;
01844 }
01845 x++;
01846 }
01847 DEBUG_INFO(("increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n", rec_size, rec_size, ind2_ptr, ind2_ptr+rec_size));
01848 ind2_ptr += rec_size;
01849 }
01850 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
01851 DEBUG_RET();
01852 return mo_head;
01853 }
01854
01855
01856
01857 #define SAFE_FREE(x) {if (x) free(x);}
01858 #define SAFE_FREE_STR(x) SAFE_FREE(x.str)
01859 #define SAFE_FREE_BIN(x) SAFE_FREE(x.data)
01860
01861
01862 #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) );} }
01863 #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) );} }
01864 #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) );} }
01865 #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));} }
01866 #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) );} }
01867 #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) );} }
01868
01869
01870 #define LIST_COPY(targ, type) { \
01871 targ = type realloc(targ, list->elements[x]->size+1); \
01872 memcpy(targ, list->elements[x]->data, list->elements[x]->size);\
01873 memset(((char*)targ)+list->elements[x]->size, 0, (size_t)1); \
01874 }
01875
01876 #define LIST_COPY_CSTR(targ) { \
01877 if ((list->elements[x]->type == 0x1f) || \
01878 (list->elements[x]->type == 0x1e) || \
01879 (list->elements[x]->type == 0x102)) { \
01880 LIST_COPY(targ, (char*)) \
01881 } \
01882 else { \
01883 DEBUG_WARN(("src not 0x1e or 0x1f or 0x102 for string dst\n")); \
01884 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \
01885 SAFE_FREE(targ); \
01886 targ = NULL; \
01887 } \
01888 }
01889
01890 #define LIST_COPY_BOOL(label, targ) { \
01891 if (list->elements[x]->type != 0x0b) { \
01892 DEBUG_WARN(("src not 0x0b for boolean dst\n")); \
01893 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \
01894 } \
01895 if (*(int16_t*)list->elements[x]->data) { \
01896 DEBUG_INFO((label" - True\n")); \
01897 targ = 1; \
01898 } else { \
01899 DEBUG_INFO((label" - False\n")); \
01900 targ = 0; \
01901 } \
01902 }
01903
01904 #define LIST_COPY_EMAIL_BOOL(label, targ) { \
01905 MALLOC_EMAIL(item); \
01906 LIST_COPY_BOOL(label, targ) \
01907 }
01908
01909 #define LIST_COPY_CONTACT_BOOL(label, targ) { \
01910 MALLOC_CONTACT(item); \
01911 LIST_COPY_BOOL(label, targ) \
01912 }
01913
01914 #define LIST_COPY_APPT_BOOL(label, targ) { \
01915 MALLOC_APPOINTMENT(item); \
01916 LIST_COPY_BOOL(label, targ) \
01917 }
01918
01919 #define LIST_COPY_INT16_N(targ) { \
01920 if (list->elements[x]->type != 0x02) { \
01921 DEBUG_WARN(("src not 0x02 for int16 dst\n")); \
01922 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \
01923 } \
01924 memcpy(&(targ), list->elements[x]->data, sizeof(targ)); \
01925 LE16_CPU(targ); \
01926 }
01927
01928 #define LIST_COPY_INT16(label, targ) { \
01929 LIST_COPY_INT16_N(targ); \
01930 DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \
01931 }
01932
01933 #define LIST_COPY_INT32_N(targ) { \
01934 if (list->elements[x]->type != 0x03) { \
01935 DEBUG_WARN(("src not 0x03 for int32 dst\n")); \
01936 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \
01937 } \
01938 memcpy(&(targ), list->elements[x]->data, sizeof(targ)); \
01939 LE32_CPU(targ); \
01940 }
01941
01942 #define LIST_COPY_INT32(label, targ) { \
01943 LIST_COPY_INT32_N(targ); \
01944 DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \
01945 }
01946
01947 #define LIST_COPY_EMAIL_INT32(label, targ) { \
01948 MALLOC_EMAIL(item); \
01949 LIST_COPY_INT32(label, targ); \
01950 }
01951
01952 #define LIST_COPY_APPT_INT32(label, targ) { \
01953 MALLOC_APPOINTMENT(item); \
01954 LIST_COPY_INT32(label, targ); \
01955 }
01956
01957 #define LIST_COPY_FOLDER_INT32(label, targ) { \
01958 MALLOC_FOLDER(item); \
01959 LIST_COPY_INT32(label, targ); \
01960 }
01961
01962 #define LIST_COPY_STORE_INT32(label, targ) { \
01963 MALLOC_MESSAGESTORE(item); \
01964 LIST_COPY_INT32(label, targ); \
01965 }
01966
01967 #define LIST_COPY_ENUM(label, targ, delta, count, ...) { \
01968 char *tlabels[] = {__VA_ARGS__}; \
01969 LIST_COPY_INT32_N(targ); \
01970 targ += delta; \
01971 DEBUG_INFO((label" - %s [%i]\n", \
01972 (((int)targ < 0) || ((int)targ >= count)) \
01973 ? "**invalid" \
01974 : tlabels[(int)targ], (int)targ)); \
01975 }
01976
01977 #define LIST_COPY_EMAIL_ENUM(label, targ, delta, count, ...) { \
01978 MALLOC_EMAIL(item); \
01979 LIST_COPY_ENUM(label, targ, delta, count, __VA_ARGS__); \
01980 }
01981
01982 #define LIST_COPY_APPT_ENUM(label, targ, delta, count, ...) { \
01983 MALLOC_APPOINTMENT(item); \
01984 LIST_COPY_ENUM(label, targ, delta, count, __VA_ARGS__); \
01985 }
01986
01987 #define LIST_COPY_ENUM16(label, targ, delta, count, ...) { \
01988 char *tlabels[] = {__VA_ARGS__}; \
01989 LIST_COPY_INT16_N(targ); \
01990 targ += delta; \
01991 DEBUG_INFO((label" - %s [%i]\n", \
01992 (((int)targ < 0) || ((int)targ >= count)) \
01993 ? "**invalid" \
01994 : tlabels[(int)targ], (int)targ)); \
01995 }
01996
01997 #define LIST_COPY_CONTACT_ENUM16(label, targ, delta, count, ...) { \
01998 MALLOC_CONTACT(item); \
01999 LIST_COPY_ENUM16(label, targ, delta, count, __VA_ARGS__); \
02000 }
02001
02002 #define LIST_COPY_ENTRYID(label, targ) { \
02003 LIST_COPY(targ, (pst_entryid*)); \
02004 LE32_CPU(targ->u1); \
02005 LE32_CPU(targ->id); \
02006 DEBUG_INFO((label" u1=%#x, id=%#x\n", targ->u1, targ->id));\
02007 }
02008
02009 #define LIST_COPY_EMAIL_ENTRYID(label, targ) { \
02010 MALLOC_EMAIL(item); \
02011 LIST_COPY_ENTRYID(label, targ); \
02012 }
02013
02014 #define LIST_COPY_STORE_ENTRYID(label, targ) { \
02015 MALLOC_MESSAGESTORE(item); \
02016 LIST_COPY_ENTRYID(label, targ); \
02017 }
02018
02019
02020
02021
02022 #define LIST_COPY_STR(label, targ) { \
02023 LIST_COPY_CSTR(targ.str); \
02024 targ.is_utf8 = (list->elements[x]->type == 0x1f) ? 1 : 0; \
02025 DEBUG_INFO((label" - unicode %d - %s\n", targ.is_utf8, targ.str)); \
02026 }
02027
02028 #define LIST_COPY_EMAIL_STR(label, targ) { \
02029 MALLOC_EMAIL(item); \
02030 LIST_COPY_STR(label, targ); \
02031 }
02032
02033 #define LIST_COPY_CONTACT_STR(label, targ) { \
02034 MALLOC_CONTACT(item); \
02035 LIST_COPY_STR(label, targ); \
02036 }
02037
02038 #define LIST_COPY_APPT_STR(label, targ) { \
02039 MALLOC_APPOINTMENT(item); \
02040 LIST_COPY_STR(label, targ); \
02041 }
02042
02043 #define LIST_COPY_JOURNAL_STR(label, targ) { \
02044 MALLOC_JOURNAL(item); \
02045 LIST_COPY_STR(label, targ); \
02046 }
02047
02048
02049 #define LIST_COPY_TIME(label, targ) { \
02050 if (list->elements[x]->type != 0x40) { \
02051 DEBUG_WARN(("src not 0x40 for filetime dst\n")); \
02052 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \
02053 } \
02054 targ = (FILETIME*) realloc(targ, sizeof(FILETIME)); \
02055 memcpy(targ, list->elements[x]->data, list->elements[x]->size); \
02056 LE32_CPU(targ->dwLowDateTime); \
02057 LE32_CPU(targ->dwHighDateTime); \
02058 DEBUG_INFO((label" - %s", pst_fileTimeToAscii(targ, time_buffer))); \
02059 }
02060
02061 #define LIST_COPY_EMAIL_TIME(label, targ) { \
02062 MALLOC_EMAIL(item); \
02063 LIST_COPY_TIME(label, targ); \
02064 }
02065
02066 #define LIST_COPY_CONTACT_TIME(label, targ) { \
02067 MALLOC_CONTACT(item); \
02068 LIST_COPY_TIME(label, targ); \
02069 }
02070
02071 #define LIST_COPY_APPT_TIME(label, targ) { \
02072 MALLOC_APPOINTMENT(item); \
02073 LIST_COPY_TIME(label, targ); \
02074 }
02075
02076 #define LIST_COPY_JOURNAL_TIME(label, targ) { \
02077 MALLOC_JOURNAL(item); \
02078 LIST_COPY_TIME(label, targ); \
02079 }
02080
02081
02082 #define LIST_COPY_BIN(targ) { \
02083 targ.size = list->elements[x]->size; \
02084 if (targ.size) { \
02085 targ.data = (char*)realloc(targ.data, targ.size); \
02086 memcpy(targ.data, list->elements[x]->data, targ.size); \
02087 } \
02088 else { \
02089 SAFE_FREE_BIN(targ); \
02090 targ.data = NULL; \
02091 } \
02092 }
02093
02094 #define LIST_COPY_EMAIL_BIN(label, targ) { \
02095 MALLOC_EMAIL(item); \
02096 LIST_COPY_BIN(targ); \
02097 DEBUG_INFO((label"\n")); \
02098 }
02099 #define LIST_COPY_APPT_BIN(label, targ) { \
02100 MALLOC_APPOINTMENT(item); \
02101 LIST_COPY_BIN(targ); \
02102 DEBUG_INFO((label"\n")); \
02103 DEBUG_HEXDUMP(targ.data, targ.size); \
02104 }
02105
02106 #define NULL_CHECK(x) { if (!x) { DEBUG_WARN(("NULL_CHECK: Null Found\n")); break;} }
02107
02108
02123 static int pst_process(pst_mapi_object *list, pst_item *item, pst_item_attach *attach) {
02124 DEBUG_ENT("pst_process");
02125 if (!item) {
02126 DEBUG_WARN(("item cannot be NULL.\n"));
02127 DEBUG_RET();
02128 return -1;
02129 }
02130
02131 while (list) {
02132 int32_t x;
02133 char time_buffer[30];
02134 for (x=0; x<list->count_elements; x++) {
02135 int32_t t;
02136 DEBUG_INFO(("#%d - mapi-id: %#x type: %#x length: %#x\n", x, list->elements[x]->mapi_id, list->elements[x]->type, list->elements[x]->size));
02137
02138 switch (list->elements[x]->mapi_id) {
02139 case PST_ATTRIB_HEADER:
02140 if (list->elements[x]->extra) {
02141 pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field));
02142 memset(ef, 0, sizeof(pst_item_extra_field));
02143 LIST_COPY_CSTR(ef->value);
02144 if (ef->value) {
02145 ef->field_name = strdup(list->elements[x]->extra);
02146 ef->next = item->extra_fields;
02147 item->extra_fields = ef;
02148 DEBUG_INFO(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value));
02149 if (strcmp(ef->field_name, "content-type") == 0) {
02150 char *p = strstr(ef->value, "charset=\"");
02151 if (p) {
02152 p += 9;
02153 char *pp = strchr(p, '"');
02154 if (pp) {
02155 *pp = '\0';
02156 char *set = strdup(p);
02157 *pp = '"';
02158 if (item->body_charset.str) free(item->body_charset.str);
02159 item->body_charset.str = set;
02160 item->body_charset.is_utf8 = 1;
02161 DEBUG_INFO(("body charset %s from content-type extra field\n", set));
02162 }
02163 }
02164 }
02165 }
02166 else {
02167 DEBUG_WARN(("What does this mean? Internet header %s value\n", list->elements[x]->extra));
02168 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02169 free(ef);
02170 }
02171 }
02172 break;
02173 case 0x0002:
02174 if (list->elements[x]->type == 0x0b) {
02175
02176 LIST_COPY_EMAIL_BOOL("AutoForward allowed", item->email->autoforward);
02177 if (!item->email->autoforward) item->email->autoforward = -1;
02178 } else {
02179 DEBUG_WARN(("What does this mean?\n"));
02180 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02181 }
02182 break;
02183 case 0x0003:
02184 DEBUG_INFO(("Extended Attributes Table - NOT PROCESSED\n"));
02185 break;
02186 case 0x0017:
02187 LIST_COPY_EMAIL_ENUM("Importance Level", item->email->importance, 0, 3, "Low", "Normal", "High");
02188 break;
02189 case 0x001A:
02190 if ((list->elements[x]->type == 0x1e) ||
02191 (list->elements[x]->type == 0x1f)) {
02192 LIST_COPY_CSTR(item->ascii_type);
02193 if (!item->ascii_type) item->ascii_type = strdup("unknown");
02194 if (pst_strincmp("IPM.Note", item->ascii_type, 8) == 0)
02195 item->type = PST_TYPE_NOTE;
02196 else if (pst_stricmp("IPM", item->ascii_type) == 0)
02197 item->type = PST_TYPE_NOTE;
02198 else if (pst_strincmp("IPM.Contact", item->ascii_type, 11) == 0)
02199 item->type = PST_TYPE_CONTACT;
02200 else if (pst_strincmp("REPORT.IPM.Note", item->ascii_type, 15) == 0)
02201 item->type = PST_TYPE_REPORT;
02202 else if (pst_strincmp("IPM.Activity", item->ascii_type, 12) == 0)
02203 item->type = PST_TYPE_JOURNAL;
02204 else if (pst_strincmp("IPM.Appointment", item->ascii_type, 15) == 0)
02205 item->type = PST_TYPE_APPOINTMENT;
02206 else if (pst_strincmp("IPM.Schedule.Meeting", item->ascii_type, 20) == 0)
02207 item->type = PST_TYPE_SCHEDULE;
02208 else if (pst_strincmp("IPM.StickyNote", item->ascii_type, 14) == 0)
02209 item->type = PST_TYPE_STICKYNOTE;
02210 else if (pst_strincmp("IPM.Task", item->ascii_type, 8) == 0)
02211 item->type = PST_TYPE_TASK;
02212 else
02213 item->type = PST_TYPE_OTHER;
02214 DEBUG_INFO(("Message class %s [%"PRIi32"] \n", item->ascii_type, item->type));
02215 }
02216 else {
02217 DEBUG_WARN(("What does this mean?\n"));
02218 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02219 }
02220 break;
02221 case 0x0023:
02222 if (list->elements[x]->type == 0x0b) {
02223
02224 LIST_COPY_EMAIL_BOOL("Global Delivery Report", item->email->delivery_report);
02225 }
02226 else {
02227 DEBUG_WARN(("What does this mean?\n"));
02228 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
02229 }
02230 break;
02231 case 0x0026:
02232 LIST_COPY_EMAIL_ENUM("Priority", item->email->priority, 1, 3, "NonUrgent", "Normal", "Urgent");
02233 break;
02234 case 0x0029:
02235 LIST_COPY_EMAIL_BOOL("Read Receipt", item->email->read_receipt);
02236 break;
02237 case 0x002B:
02238 LIST_COPY_BOOL("Reassignment Prohibited (Private)", item->private_member);
02239 break;
02240 case 0x002E:
02241 LIST_COPY_EMAIL_ENUM("Original Sensitivity", item->email->original_sensitivity, 0, 4,
02242 "None", "Personal", "Private", "Company Confidential");
02243 break;
02244 case 0x0032:
02245 LIST_COPY_EMAIL_TIME("Report time", item->email->report_time);
02246 break;
02247 case 0x0036:
02248 LIST_COPY_EMAIL_ENUM("Sensitivity", item->email->sensitivity, 0, 4,
02249 "None", "Personal", "Private", "Company Confidential");
02250 break;
02251 case 0x0037:
02252 {
02253 int off = 0;
02254 if ((list->elements[x]->size > 2) && (((uint8_t)list->elements[x]->data[0]) < 0x20)) {
02255 off = 2;
02256 }
02257 list->elements[x]->data += off;
02258 list->elements[x]->size -= off;
02259 LIST_COPY_STR("Raw Subject", item->subject);
02260 list->elements[x]->size += off;
02261 list->elements[x]->data -= off;
02262 }
02263 break;
02264 case 0x0039:
02265 LIST_COPY_EMAIL_TIME("Date sent", item->email->sent_date);
02266 break;
02267 case 0x003B:
02268 LIST_COPY_EMAIL_STR("Sent on behalf of address 1", item->email->outlook_sender);
02269 break;
02270 case 0x003F:
02271 DEBUG_INFO(("Recipient Structure 1 -- NOT PROCESSED\n"));
02272 break;
02273 case 0x0040:
02274 DEBUG_INFO(("Received By Name 1 -- NOT PROCESSED\n"));
02275 break;
02276 case 0x0041:
02277 DEBUG_INFO(("Sent on behalf of Structure 1 -- NOT PROCESSED\n"));
02278 break;
02279 case 0x0042:
02280 LIST_COPY_EMAIL_STR("Sent on behalf of", item->email->outlook_sender_name);
02281 break;
02282 case 0x0043:
02283 DEBUG_INFO(("Received on behalf of Structure -- NOT PROCESSED\n"));
02284 break;
02285 case 0x0044:
02286 LIST_COPY_EMAIL_STR("Received on behalf of", item->email->outlook_recipient_name);
02287 break;
02288 case 0x004F:
02289 DEBUG_INFO(("Reply-To Structure -- NOT PROCESSED\n"));
02290 break;
02291 case 0x0050:
02292 LIST_COPY_EMAIL_STR("Reply-To", item->email->reply_to);
02293 break;
02294 case 0x0051:
02295 LIST_COPY_EMAIL_STR("Recipient's Address 1", item->email->outlook_recipient);
02296 break;
02297 case 0x0052:
02298 LIST_COPY_EMAIL_STR("Recipient's Address 2", item->email->outlook_recipient2);
02299 break;
02300 case 0x0057:
02301
02302 LIST_COPY_EMAIL_BOOL("My address in TO field", item->email->message_to_me);
02303 break;
02304 case 0x0058:
02305
02306 LIST_COPY_EMAIL_BOOL("My address in CC field", item->email->message_cc_me);
02307 break;
02308 case 0x0059:
02309
02310 LIST_COPY_EMAIL_BOOL("Message addressed to me", item->email->message_recip_me);
02311 break;
02312 case 0x0063:
02313 LIST_COPY_BOOL("Response requested", item->response_requested);
02314 break;
02315 case 0x0064:
02316 LIST_COPY_EMAIL_STR("Sent on behalf of address type", item->email->sender_access);
02317 break;
02318 case 0x0065:
02319 LIST_COPY_EMAIL_STR("Sent on behalf of address", item->email->sender_address);
02320 break;
02321 case 0x0070:
02322 LIST_COPY_EMAIL_STR("Processed Subject (Conversation Topic)", item->email->processed_subject);
02323 break;
02324 case 0x0071:
02325 LIST_COPY_EMAIL_BIN("Conversation Index", item->email->conversation_index);
02326 break;
02327 case 0x0072:
02328 LIST_COPY_EMAIL_STR("Original display bcc", item->email->original_bcc);
02329 break;
02330 case 0x0073:
02331 LIST_COPY_EMAIL_STR("Original display cc", item->email->original_cc);
02332 break;
02333 case 0x0074:
02334 LIST_COPY_EMAIL_STR("Original display to", item->email->original_to);
02335 break;
02336 case 0x0075:
02337 LIST_COPY_EMAIL_STR("Received by Address type", item->email->recip_access);
02338 break;
02339 case 0x0076:
02340 LIST_COPY_EMAIL_STR("Received by Address", item->email->recip_address);
02341 break;
02342 case 0x0077:
02343 LIST_COPY_EMAIL_STR("Received on behalf of Address type", item->email->recip2_access);
02344 break;
02345 case 0x0078:
02346 LIST_COPY_EMAIL_STR("Received on behalf of Address", item->email->recip2_address);
02347 break;
02348 case 0x007D:
02349 LIST_COPY_EMAIL_STR("Internet Header", item->email->header);
02350 break;
02351 case 0x0C04:
02352 LIST_COPY_EMAIL_INT32("NDR reason code", item->email->ndr_reason_code);
02353 break;
02354 case 0x0C05:
02355 LIST_COPY_EMAIL_INT32("NDR diag code", item->email->ndr_diag_code);
02356 break;
02357 case 0x0C06:
02358 DEBUG_INFO(("Non-Receipt Notification Requested -- NOT PROCESSED\n"));
02359 break;
02360 case 0x0C17:
02361 LIST_COPY_EMAIL_BOOL("Reply Requested", item->email->reply_requested);
02362 break;
02363 case 0x0C19:
02364 DEBUG_INFO(("Sender Structure 2 -- NOT PROCESSED\n"));
02365 break;
02366 case 0x0C1A:
02367 DEBUG_INFO(("Name of Sender Structure 2 -- NOT PROCESSED\n"));
02368 break;
02369 case 0x0C1B:
02370 LIST_COPY_EMAIL_STR("Supplementary info", item->email->supplementary_info);
02371 break;
02372 case 0x0C1D:
02373 LIST_COPY_EMAIL_STR("Name of Sender Address 2 (Sender search key)", item->email->outlook_sender2);
02374 break;
02375 case 0x0C1E:
02376 LIST_COPY_EMAIL_STR("Sender Address type", item->email->sender2_access);
02377 break;
02378 case 0x0C1F:
02379 LIST_COPY_EMAIL_STR("Sender Address", item->email->sender2_address);
02380 break;
02381 case 0x0C20:
02382 LIST_COPY_EMAIL_INT32("NDR status code", item->email->ndr_status_code);
02383 break;
02384 case 0x0E01:
02385 LIST_COPY_EMAIL_BOOL("Delete after submit", item->email->delete_after_submit);
02386 break;
02387 case 0x0E02:
02388 LIST_COPY_EMAIL_STR("Display BCC Addresses", item->email->bcc_address);
02389 break;
02390 case 0x0E03:
02391 LIST_COPY_EMAIL_STR("Display CC Addresses", item->email->cc_address);
02392 break;
02393 case 0x0E04:
02394 LIST_COPY_EMAIL_STR("Display Sent-To Address", item->email->sentto_address);
02395 break;
02396 case 0x0E06:
02397 LIST_COPY_EMAIL_TIME("Date 3 (Delivery Time)", item->email->arrival_date);
02398 break;
02399 case 0x0E07:
02400 LIST_COPY_EMAIL_INT32("Message Flags", item->flags);
02401 break;
02402 case 0x0E08:
02403 LIST_COPY_INT32("Message Size", item->message_size);
02404 break;
02405 case 0x0E0A:
02406
02407 LIST_COPY_EMAIL_ENTRYID("Sentmail EntryID", item->email->sentmail_folder);
02408 break;
02409 case 0x0E1F:
02410
02411
02412
02413
02414 LIST_COPY_EMAIL_BOOL("Compressed RTF in Sync", item->email->rtf_in_sync);
02415 break;
02416 case 0x0E20:
02417 NULL_CHECK(attach);
02418 LIST_COPY_INT32("Attachment Size", t);
02419 attach->data.size = (size_t)t;
02420 break;
02421 case 0x0FF9:
02422 LIST_COPY_BIN(item->record_key);
02423 DEBUG_INFO(("Record Key\n"));
02424 DEBUG_HEXDUMP(item->record_key.data, item->record_key.size);
02425 break;
02426 case 0x1000:
02427 LIST_COPY_STR("Plain Text body", item->body);
02428 break;
02429 case 0x1001:
02430 LIST_COPY_EMAIL_STR("Report Text", item->email->report_text);
02431 break;
02432 case 0x1006:
02433 LIST_COPY_EMAIL_INT32("RTF Sync Body CRC", item->email->rtf_body_crc);
02434 break;
02435 case 0x1007:
02436
02437
02438 LIST_COPY_EMAIL_INT32("RTF Sync Body character count", item->email->rtf_body_char_count);
02439 break;
02440 case 0x1008:
02441
02442
02443 LIST_COPY_EMAIL_STR("RTF Sync body tag", item->email->rtf_body_tag);
02444 break;
02445 case 0x1009:
02446 LIST_COPY_EMAIL_BIN("RTF Compressed body", item->email->rtf_compressed);
02447 break;
02448 case 0x1010:
02449
02450 LIST_COPY_EMAIL_INT32("RTF whitespace prefix count", item->email->rtf_ws_prefix_count);
02451 break;
02452 case 0x1011:
02453
02454 LIST_COPY_EMAIL_INT32("RTF whitespace tailing count", item->email->rtf_ws_trailing_count);
02455 break;
02456 case 0x1013:
02457 LIST_COPY_EMAIL_STR("HTML body", item->email->htmlbody);
02458 break;
02459 case 0x1035:
02460 LIST_COPY_EMAIL_STR("Message ID", item->email->messageid);
02461 break;
02462 case 0x1042:
02463 LIST_COPY_EMAIL_STR("In-Reply-To", item->email->in_reply_to);
02464 break;
02465 case 0x1046:
02466 LIST_COPY_EMAIL_STR("Return Path", item->email->return_path_address);
02467 break;
02468 case 0x3001:
02469 LIST_COPY_STR("Display Name", item->file_as);
02470 break;
02471 case 0x3002:
02472 LIST_COPY_CONTACT_STR("Address Type", item->contact->address1_transport);
02473 break;
02474 case 0x3003:
02475 LIST_COPY_CONTACT_STR("Contact email Address", item->contact->address1);
02476 break;
02477 case 0x3004:
02478 LIST_COPY_STR("Comment", item->comment);
02479 break;
02480 case 0x3007:
02481 LIST_COPY_TIME("Date 4 (Item Creation Date)", item->create_date);
02482 break;
02483 case 0x3008:
02484 LIST_COPY_TIME("Date 5 (Modify Date)", item->modify_date);
02485 break;
02486 case 0x300B:
02487 DEBUG_INFO(("Record Search 2 -- NOT PROCESSED\n"));
02488 break;
02489 case 0x35DF:
02490 LIST_COPY_STORE_INT32("Valid Folder Mask", item->message_store->valid_mask);
02491 break;
02492 case 0x35E0:
02493 LIST_COPY_STORE_ENTRYID("Top of Personal Folder Record", item->message_store->top_of_personal_folder);
02494 break;
02495 case 0x35E2:
02496 LIST_COPY_STORE_ENTRYID("Default Outbox Folder record", item->message_store->default_outbox_folder);
02497 break;
02498 case 0x35E3:
02499 LIST_COPY_STORE_ENTRYID("Deleted Items Folder record", item->message_store->deleted_items_folder);
02500 break;
02501 case 0x35E4:
02502 LIST_COPY_STORE_ENTRYID("Sent Items Folder record", item->message_store->sent_items_folder);
02503 break;
02504 case 0x35E5:
02505 LIST_COPY_STORE_ENTRYID("User Views Folder record", item->message_store->user_views_folder);
02506 break;
02507 case 0x35E6:
02508 LIST_COPY_STORE_ENTRYID("Common View Folder record", item->message_store->common_view_folder);
02509 break;
02510 case 0x35E7:
02511 LIST_COPY_STORE_ENTRYID("Search Root Folder record", item->message_store->search_root_folder);
02512 break;
02513 case 0x3602:
02514 LIST_COPY_FOLDER_INT32("Folder Email Count", item->folder->item_count);
02515 break;
02516 case 0x3603:
02517 LIST_COPY_FOLDER_INT32("Unread Email Count", item->folder->unseen_item_count);
02518 break;
02519 case 0x360A:
02520 MALLOC_FOLDER(item);
02521 LIST_COPY_BOOL("Has Subfolders", item->folder->subfolder);
02522 break;
02523 case 0x3613:
02524 LIST_COPY_CSTR(item->ascii_type);
02525 if (pst_strincmp("IPF.Note", item->ascii_type, 8) == 0)
02526 item->type = PST_TYPE_NOTE;
02527 else if (pst_strincmp("IPF.Imap", item->ascii_type, 8) == 0)
02528 item->type = PST_TYPE_NOTE;
02529 else if (pst_stricmp("IPF", item->ascii_type) == 0)
02530 item->type = PST_TYPE_NOTE;
02531 else if (pst_strincmp("IPF.Contact", item->ascii_type, 11) == 0)
02532 item->type = PST_TYPE_CONTACT;
02533 else if (pst_strincmp("IPF.Journal", item->ascii_type, 11) == 0)
02534 item->type = PST_TYPE_JOURNAL;
02535 else if (pst_strincmp("IPF.Appointment", item->ascii_type, 15) == 0)
02536 item->type = PST_TYPE_APPOINTMENT;
02537 else if (pst_strincmp("IPF.StickyNote", item->ascii_type, 14) == 0)
02538 item->type = PST_TYPE_STICKYNOTE;
02539 else if (pst_strincmp("IPF.Task", item->ascii_type, 8) == 0)
02540 item->type = PST_TYPE_TASK;
02541 else
02542 item->type = PST_TYPE_OTHER;
02543
02544 DEBUG_INFO(("Container class %s [%"PRIi32"]\n", item->ascii_type, item->type));
02545 break;
02546 case 0x3617:
02547
02548
02549 LIST_COPY_FOLDER_INT32("Associated Content count", item->folder->assoc_count);
02550 break;
02551 case 0x3701:
02552 DEBUG_INFO(("Binary Data [Size %i]\n", list->elements[x]->size));
02553 NULL_CHECK(attach);
02554 if (!list->elements[x]->data) {
02555 attach->id2_val = list->elements[x]->type;
02556 DEBUG_INFO(("Seen a Reference. The data hasn't been loaded yet. [%#"PRIx64"]\n", attach->id2_val));
02557 } else {
02558 LIST_COPY_BIN(attach->data);
02559 }
02560 break;
02561 case 0x3704:
02562 NULL_CHECK(attach);
02563 LIST_COPY_STR("Attachment Filename", attach->filename1);
02564 break;
02565 case 0x3705:
02566 NULL_CHECK(attach);
02567 LIST_COPY_ENUM("Attachment method", attach->method, 0, 7,
02568 "No Attachment",
02569 "Attach By Value",
02570 "Attach By Reference",
02571 "Attach by Reference Resolve",
02572 "Attach by Reference Only",
02573 "Embedded Message",
02574 "OLE");
02575 break;
02576 case 0x3707:
02577 NULL_CHECK(attach);
02578 LIST_COPY_STR("Attachment Filename long", attach->filename2);
02579 break;
02580 case 0x370B:
02581
02582 NULL_CHECK(attach);
02583 LIST_COPY_INT32("Attachment Position", attach->position);
02584 break;
02585 case 0x370E:
02586 NULL_CHECK(attach);
02587 LIST_COPY_STR("Attachment mime encoding", attach->mimetype);
02588 break;
02589 case 0x3710:
02590
02591 NULL_CHECK(attach);
02592 LIST_COPY_INT32("Attachment Mime Sequence", attach->sequence);
02593 break;
02594 case 0x3A00:
02595 LIST_COPY_CONTACT_STR("Contact's Account name", item->contact->account_name);
02596 break;
02597 case 0x3A01:
02598 DEBUG_INFO(("Contact Alternate Recipient - NOT PROCESSED\n"));
02599 break;
02600 case 0x3A02:
02601 LIST_COPY_CONTACT_STR("Callback telephone number", item->contact->callback_phone);
02602 break;
02603 case 0x3A03:
02604 LIST_COPY_EMAIL_BOOL("Message Conversion Prohibited", item->email->conversion_prohibited);
02605 break;
02606 case 0x3A05:
02607 LIST_COPY_CONTACT_STR("Contacts Suffix", item->contact->suffix);
02608 break;
02609 case 0x3A06:
02610 LIST_COPY_CONTACT_STR("Contacts First Name", item->contact->first_name);
02611 break;
02612 case 0x3A07:
02613 LIST_COPY_CONTACT_STR("Contacts Government ID Number", item->contact->gov_id);
02614 break;
02615 case 0x3A08:
02616 LIST_COPY_CONTACT_STR("Business Telephone Number", item->contact->business_phone);
02617 break;
02618 case 0x3A09:
02619 LIST_COPY_CONTACT_STR("Home Telephone Number", item->contact->home_phone);
02620 break;
02621 case 0x3A0A:
02622 LIST_COPY_CONTACT_STR("Contacts Initials", item->contact->initials);
02623 break;
02624 case 0x3A0B:
02625 LIST_COPY_CONTACT_STR("Keyword", item->contact->keyword);
02626 break;
02627 case 0x3A0C:
02628 LIST_COPY_CONTACT_STR("Contact's Language", item->contact->language);
02629 break;
02630 case 0x3A0D:
02631 LIST_COPY_CONTACT_STR("Contact's Location", item->contact->location);
02632 break;
02633 case 0x3A0E:
02634 LIST_COPY_CONTACT_BOOL("Mail Permission", item->contact->mail_permission);
02635 break;
02636 case 0x3A0F:
02637 LIST_COPY_CONTACT_STR("MHS Common Name", item->contact->common_name);
02638 break;
02639 case 0x3A10:
02640 LIST_COPY_CONTACT_STR("Organizational ID #", item->contact->org_id);
02641 break;
02642 case 0x3A11:
02643 LIST_COPY_CONTACT_STR("Contacts Surname", item->contact->surname);
02644 break;
02645 case 0x3A12:
02646 DEBUG_INFO(("Original Entry ID - NOT PROCESSED\n"));
02647 break;
02648 case 0x3A13:
02649 DEBUG_INFO(("Original Display Name - NOT PROCESSED\n"));
02650 break;
02651 case 0x3A14:
02652 DEBUG_INFO(("Original Search Key - NOT PROCESSED\n"));
02653 break;
02654 case 0x3A15:
02655 LIST_COPY_CONTACT_STR("Default Postal Address", item->contact->def_postal_address);
02656 break;
02657 case 0x3A16:
02658 LIST_COPY_CONTACT_STR("Company Name", item->contact->company_name);
02659 break;
02660 case 0x3A17:
02661 LIST_COPY_CONTACT_STR("Job Title", item->contact->job_title);
02662 break;
02663 case 0x3A18:
02664 LIST_COPY_CONTACT_STR("Department Name", item->contact->department);
02665 break;
02666 case 0x3A19:
02667 LIST_COPY_CONTACT_STR("Office Location", item->contact->office_loc);
02668 break;
02669 case 0x3A1A:
02670 LIST_COPY_CONTACT_STR("Primary Telephone", item->contact->primary_phone);
02671 break;
02672 case 0x3A1B:
02673 LIST_COPY_CONTACT_STR("Business Phone Number 2", item->contact->business_phone2);
02674 break;
02675 case 0x3A1C:
02676 LIST_COPY_CONTACT_STR("Mobile Phone Number", item->contact->mobile_phone);
02677 break;
02678 case 0x3A1D:
02679 LIST_COPY_CONTACT_STR("Radio Phone Number", item->contact->radio_phone);
02680 break;
02681 case 0x3A1E:
02682 LIST_COPY_CONTACT_STR("Car Phone Number", item->contact->car_phone);
02683 break;
02684 case 0x3A1F:
02685 LIST_COPY_CONTACT_STR("Other Phone Number", item->contact->other_phone);
02686 break;
02687 case 0x3A20:
02688 LIST_COPY_CONTACT_STR("Transmittable Display Name", item->contact->transmittable_display_name);
02689 break;
02690 case 0x3A21:
02691 LIST_COPY_CONTACT_STR("Pager Phone Number", item->contact->pager_phone);
02692 break;
02693 case 0x3A22:
02694 DEBUG_INFO(("User Certificate - NOT PROCESSED\n"));
02695 break;
02696 case 0x3A23:
02697 LIST_COPY_CONTACT_STR("Primary Fax Number", item->contact->primary_fax);
02698 break;
02699 case 0x3A24:
02700 LIST_COPY_CONTACT_STR("Business Fax Number", item->contact->business_fax);
02701 break;
02702 case 0x3A25:
02703 LIST_COPY_CONTACT_STR("Home Fax Number", item->contact->home_fax);
02704 break;
02705 case 0x3A26:
02706 LIST_COPY_CONTACT_STR("Business Address Country", item->contact->business_country);
02707 break;
02708 case 0x3A27:
02709 LIST_COPY_CONTACT_STR("Business Address City", item->contact->business_city);
02710 break;
02711 case 0x3A28:
02712 LIST_COPY_CONTACT_STR("Business Address State", item->contact->business_state);
02713 break;
02714 case 0x3A29:
02715 LIST_COPY_CONTACT_STR("Business Address Street", item->contact->business_street);
02716 break;
02717 case 0x3A2A:
02718 LIST_COPY_CONTACT_STR("Business Postal Code", item->contact->business_postal_code);
02719 break;
02720 case 0x3A2B:
02721 LIST_COPY_CONTACT_STR("Business PO Box", item->contact->business_po_box);
02722 break;
02723 case 0x3A2C:
02724 LIST_COPY_CONTACT_STR("Telex Number", item->contact->telex);
02725 break;
02726 case 0x3A2D:
02727 LIST_COPY_CONTACT_STR("ISDN Number", item->contact->isdn_phone);
02728 break;
02729 case 0x3A2E:
02730 LIST_COPY_CONTACT_STR("Assistant Phone Number", item->contact->assistant_phone);
02731 break;
02732 case 0x3A2F:
02733 LIST_COPY_CONTACT_STR("Home Phone 2", item->contact->home_phone2);
02734 break;
02735 case 0x3A30:
02736 LIST_COPY_CONTACT_STR("Assistant's Name", item->contact->assistant_name);
02737 break;
02738 case 0x3A40:
02739 LIST_COPY_CONTACT_BOOL("Can receive Rich Text", item->contact->rich_text);
02740 break;
02741 case 0x3A41:
02742 LIST_COPY_CONTACT_TIME("Wedding Anniversary", item->contact->wedding_anniversary);
02743 break;
02744 case 0x3A42:
02745 LIST_COPY_CONTACT_TIME("Birthday", item->contact->birthday);
02746 break;
02747 case 0x3A43:
02748 LIST_COPY_CONTACT_STR("Hobbies", item->contact->hobbies);
02749 break;
02750 case 0x3A44:
02751 LIST_COPY_CONTACT_STR("Middle Name", item->contact->middle_name);
02752 break;
02753 case 0x3A45:
02754 LIST_COPY_CONTACT_STR("Display Name Prefix (Title)", item->contact->display_name_prefix);
02755 break;
02756 case 0x3A46:
02757 LIST_COPY_CONTACT_STR("Profession", item->contact->profession);
02758 break;
02759 case 0x3A47:
02760 LIST_COPY_CONTACT_STR("Preferred By Name", item->contact->pref_name);
02761 break;
02762 case 0x3A48:
02763 LIST_COPY_CONTACT_STR("Spouse's Name", item->contact->spouse_name);
02764 break;
02765 case 0x3A49:
02766 LIST_COPY_CONTACT_STR("Computer Network Name", item->contact->computer_name);
02767 break;
02768 case 0x3A4A:
02769 LIST_COPY_CONTACT_STR("Customer ID", item->contact->customer_id);
02770 break;
02771 case 0x3A4B:
02772 LIST_COPY_CONTACT_STR("TTY/TDD Phone", item->contact->ttytdd_phone);
02773 break;
02774 case 0x3A4C:
02775 LIST_COPY_CONTACT_STR("Ftp Site", item->contact->ftp_site);
02776 break;
02777 case 0x3A4D:
02778 LIST_COPY_CONTACT_ENUM16("Gender", item->contact->gender, 0, 3, "Unspecified", "Female", "Male");
02779 break;
02780 case 0x3A4E:
02781 LIST_COPY_CONTACT_STR("Manager's Name", item->contact->manager_name);
02782 break;
02783 case 0x3A4F:
02784 LIST_COPY_CONTACT_STR("Nickname", item->contact->nickname);
02785 break;
02786 case 0x3A50:
02787 LIST_COPY_CONTACT_STR("Personal Home Page", item->contact->personal_homepage);
02788 break;
02789 case 0x3A51:
02790 LIST_COPY_CONTACT_STR("Business Home Page", item->contact->business_homepage);
02791 break;
02792 case 0x3A57:
02793 LIST_COPY_CONTACT_STR("Company Main Phone", item->contact->company_main_phone);
02794 break;
02795 case 0x3A58:
02796 DEBUG_INFO(("Children's Names - NOT PROCESSED\n"));
02797 break;
02798 case 0x3A59:
02799 LIST_COPY_CONTACT_STR("Home Address City", item->contact->home_city);
02800 break;
02801 case 0x3A5A:
02802 LIST_COPY_CONTACT_STR("Home Address Country", item->contact->home_country);
02803 break;
02804 case 0x3A5B:
02805 LIST_COPY_CONTACT_STR("Home Address Postal Code", item->contact->home_postal_code);
02806 break;
02807 case 0x3A5C:
02808 LIST_COPY_CONTACT_STR("Home Address State or Province", item->contact->home_state);
02809 break;
02810 case 0x3A5D:
02811 LIST_COPY_CONTACT_STR("Home Address Street", item->contact->home_street);
02812 break;
02813 case 0x3A5E:
02814 LIST_COPY_CONTACT_STR("Home Address Post Office Box", item->contact->home_po_box);
02815 break;
02816 case 0x3A5F:
02817 LIST_COPY_CONTACT_STR("Other Address City", item->contact->other_city);
02818 break;
02819 case 0x3A60:
02820 LIST_COPY_CONTACT_STR("Other Address Country", item->contact->other_country);
02821 break;
02822 case 0x3A61:
02823 LIST_COPY_CONTACT_STR("Other Address Postal Code", item->contact->other_postal_code);
02824 break;
02825 case 0x3A62:
02826 LIST_COPY_CONTACT_STR("Other Address State", item->contact->other_state);
02827 break;
02828 case 0x3A63:
02829 LIST_COPY_CONTACT_STR("Other Address Street", item->contact->other_street);
02830 break;
02831 case 0x3A64:
02832 LIST_COPY_CONTACT_STR("Other Address Post Office box", item->contact->other_po_box);
02833 break;
02834 case 0x3FDE:
02835 LIST_COPY_INT32("Internet code page", item->internet_cpid);
02836 break;
02837 case 0x3FFD:
02838 LIST_COPY_INT32("Message code page", item->message_codepage);
02839 break;
02840 case 0x65E3:
02841 LIST_COPY_BIN(item->predecessor_change);
02842 DEBUG_INFO(("Predecessor Change\n"));
02843 DEBUG_HEXDUMP(item->predecessor_change.data, item->predecessor_change.size);
02844 break;
02845 case 0x67F2:
02846 if (attach) {
02847 uint32_t tempid;
02848 memcpy(&(tempid), list->elements[x]->data, sizeof(tempid));
02849 LE32_CPU(tempid);
02850 attach->id2_val = tempid;
02851 DEBUG_INFO(("Attachment ID2 value - %#"PRIx64"\n", attach->id2_val));
02852 } else {
02853 DEBUG_WARN(("NOT AN ATTACHMENT: %#x\n", list->elements[x]->mapi_id));
02854 }
02855 break;
02856 case 0x67FF:
02857 LIST_COPY_STORE_INT32("Password checksum", item->message_store->pwd_chksum);
02858 break;
02859 case 0x6F02:
02860 LIST_COPY_EMAIL_BIN("Secure HTML Body", item->email->encrypted_htmlbody);
02861 break;
02862 case 0x6F04:
02863 LIST_COPY_EMAIL_BIN("Secure Text Body", item->email->encrypted_body);
02864 break;
02865 case 0x7C07:
02866 LIST_COPY_STORE_ENTRYID("Top of folders RecID", item->message_store->top_of_folder);
02867 break;
02868 case 0x8005:
02869 LIST_COPY_CONTACT_STR("Contact Fullname", item->contact->fullname);
02870 break;
02871 case 0x801A:
02872 LIST_COPY_CONTACT_STR("Home Address", item->contact->home_address);
02873 break;
02874 case 0x801B:
02875 LIST_COPY_CONTACT_STR("Business Address", item->contact->business_address);
02876 break;
02877 case 0x801C:
02878 LIST_COPY_CONTACT_STR("Other Address", item->contact->other_address);
02879 break;
02880 case 0x8045:
02881 LIST_COPY_CONTACT_STR("Work address street", item->contact->work_address_street);
02882 break;
02883 case 0x8046:
02884 LIST_COPY_CONTACT_STR("Work address city", item->contact->work_address_city);
02885 break;
02886 case 0x8047:
02887 LIST_COPY_CONTACT_STR("Work address state", item->contact->work_address_state);
02888 break;
02889 case 0x8048:
02890 LIST_COPY_CONTACT_STR("Work address postalcode", item->contact->work_address_postalcode);
02891 break;
02892 case 0x8049:
02893 LIST_COPY_CONTACT_STR("Work address country", item->contact->work_address_country);
02894 break;
02895 case 0x804A:
02896 LIST_COPY_CONTACT_STR("Work address postofficebox", item->contact->work_address_postofficebox);
02897 break;
02898 case 0x8082:
02899 LIST_COPY_CONTACT_STR("Email Address 1 Transport", item->contact->address1_transport);
02900 break;
02901 case 0x8083:
02902 LIST_COPY_CONTACT_STR("Email Address 1 Address", item->contact->address1);
02903 break;
02904 case 0x8084:
02905 LIST_COPY_CONTACT_STR("Email Address 1 Description", item->contact->address1_desc);
02906 break;
02907 case 0x8085:
02908 LIST_COPY_CONTACT_STR("Email Address 1 Record", item->contact->address1a);
02909 break;
02910 case 0x8092:
02911 LIST_COPY_CONTACT_STR("Email Address 2 Transport", item->contact->address2_transport);
02912 break;
02913 case 0x8093:
02914 LIST_COPY_CONTACT_STR("Email Address 2 Address", item->contact->address2);
02915 break;
02916 case 0x8094:
02917 LIST_COPY_CONTACT_STR("Email Address 2 Description", item->contact->address2_desc);
02918 break;
02919 case 0x8095:
02920 LIST_COPY_CONTACT_STR("Email Address 2 Record", item->contact->address2a);
02921 break;
02922 case 0x80A2:
02923 LIST_COPY_CONTACT_STR("Email Address 3 Transport", item->contact->address3_transport);
02924 break;
02925 case 0x80A3:
02926 LIST_COPY_CONTACT_STR("Email Address 3 Address", item->contact->address3);
02927 break;
02928 case 0x80A4:
02929 LIST_COPY_CONTACT_STR("Email Address 3 Description", item->contact->address3_desc);
02930 break;
02931 case 0x80A5:
02932 LIST_COPY_CONTACT_STR("Email Address 3 Record", item->contact->address3a);
02933 break;
02934 case 0x80D8:
02935 LIST_COPY_CONTACT_STR("Internet Free/Busy", item->contact->free_busy_address);
02936 break;
02937 case 0x8205:
02938 LIST_COPY_APPT_ENUM("Appointment shows as", item->appointment->showas, 0, 4,
02939 "Free", "Tentative", "Busy", "Out Of Office");
02940 break;
02941 case 0x8208:
02942 LIST_COPY_APPT_STR("Appointment Location", item->appointment->location);
02943 break;
02944 case 0x820d:
02945 LIST_COPY_APPT_TIME("Appointment Date Start", item->appointment->start);
02946 break;
02947 case 0x820e:
02948 LIST_COPY_APPT_TIME("Appointment Date End", item->appointment->end);
02949 break;
02950 case 0x8214:
02951 LIST_COPY_APPT_ENUM("Label for appointment", item->appointment->label, 0, 11,
02952 "None",
02953 "Important",
02954 "Business",
02955 "Personal",
02956 "Vacation",
02957 "Must Attend",
02958 "Travel Required",
02959 "Needs Preparation",
02960 "Birthday",
02961 "Anniversary",
02962 "Phone Call");
02963 break;
02964 case 0x8215:
02965 LIST_COPY_APPT_BOOL("All day flag", item->appointment->all_day);
02966 break;
02967 case 0x8216:
02968 LIST_COPY_APPT_BIN("Appointment recurrence data", item->appointment->recurrence_data);
02969 break;
02970 case 0x8223:
02971 LIST_COPY_APPT_BOOL("Is recurring", item->appointment->is_recurring);
02972 break;
02973 case 0x8231:
02974 LIST_COPY_APPT_ENUM("Appointment recurrence type ", item->appointment->recurrence_type, 0, 5,
02975 "None",
02976 "Daily",
02977 "Weekly",
02978 "Monthly",
02979 "Yearly");
02980 break;
02981 case 0x8232:
02982 LIST_COPY_APPT_STR("Appointment recurrence description", item->appointment->recurrence_description);
02983 break;
02984 case 0x8234:
02985 LIST_COPY_APPT_STR("TimeZone of times", item->appointment->timezonestring);
02986 break;
02987 case 0x8235:
02988 LIST_COPY_APPT_TIME("Recurrence Start Date", item->appointment->recurrence_start);
02989 break;
02990 case 0x8236:
02991 LIST_COPY_APPT_TIME("Recurrence End Date", item->appointment->recurrence_end);
02992 break;
02993 case 0x8501:
02994 LIST_COPY_APPT_INT32("Alarm minutes", item->appointment->alarm_minutes);
02995 break;
02996 case 0x8503:
02997 LIST_COPY_APPT_BOOL("Reminder alarm", item->appointment->alarm);
02998 break;
02999 case 0x8516:
03000 DEBUG_INFO(("Common Start Date - %s\n", pst_fileTimeToAscii((FILETIME*)list->elements[x]->data, time_buffer)));
03001 break;
03002 case 0x8517:
03003 DEBUG_INFO(("Common End Date - %s\n", pst_fileTimeToAscii((FILETIME*)list->elements[x]->data, time_buffer)));
03004 break;
03005 case 0x851f:
03006 LIST_COPY_APPT_STR("Appointment reminder sound filename", item->appointment->alarm_filename);
03007 break;
03008 case 0x8530:
03009 LIST_COPY_CONTACT_STR("Followup String", item->contact->followup);
03010 break;
03011 case 0x8534:
03012 LIST_COPY_CONTACT_STR("Mileage", item->contact->mileage);
03013 break;
03014 case 0x8535:
03015 LIST_COPY_CONTACT_STR("Billing Information", item->contact->billing_information);
03016 break;
03017 case 0x8554:
03018 LIST_COPY_STR("Outlook Version", item->outlook_version);
03019 break;
03020 case 0x8560:
03021 LIST_COPY_APPT_TIME("Appointment Reminder Time", item->appointment->reminder);
03022 break;
03023 case 0x8700:
03024 LIST_COPY_JOURNAL_STR("Journal Entry Type", item->journal->type);
03025 break;
03026 case 0x8706:
03027 LIST_COPY_JOURNAL_TIME("Start Timestamp", item->journal->start);
03028 break;
03029 case 0x8708:
03030 LIST_COPY_JOURNAL_TIME("End Timestamp", item->journal->end);
03031 break;
03032 case 0x8712:
03033 LIST_COPY_JOURNAL_STR("Journal description", item->journal->description);
03034 break;
03035 default:
03036 if (list->elements[x]->type == (uint32_t)0x0002) {
03037 DEBUG_WARN(("Unknown type %#x 16bit int = %hi\n", list->elements[x]->mapi_id,
03038 *(int16_t*)list->elements[x]->data));
03039
03040 } else if (list->elements[x]->type == (uint32_t)0x0003) {
03041 DEBUG_WARN(("Unknown type %#x 32bit int = %i\n", list->elements[x]->mapi_id,
03042 *(int32_t*)list->elements[x]->data));
03043
03044 } else if (list->elements[x]->type == (uint32_t)0x0004) {
03045 DEBUG_WARN(("Unknown type %#x 4-byte floating [size = %#x]\n", list->elements[x]->mapi_id,
03046 list->elements[x]->size));
03047 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03048
03049 } else if (list->elements[x]->type == (uint32_t)0x0005) {
03050 DEBUG_WARN(("Unknown type %#x double floating [size = %#x]\n", list->elements[x]->mapi_id,
03051 list->elements[x]->size));
03052 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03053
03054 } else if (list->elements[x]->type == (uint32_t)0x0006) {
03055 DEBUG_WARN(("Unknown type %#x signed 64bit int = %"PRIi64"\n", list->elements[x]->mapi_id,
03056 *(int64_t*)list->elements[x]->data));
03057 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03058
03059 } else if (list->elements[x]->type == (uint32_t)0x0007) {
03060 DEBUG_WARN(("Unknown type %#x application time [size = %#x]\n", list->elements[x]->mapi_id,
03061 list->elements[x]->size));
03062 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03063
03064 } else if (list->elements[x]->type == (uint32_t)0x000a) {
03065 DEBUG_WARN(("Unknown type %#x 32bit error value = %i\n", list->elements[x]->mapi_id,
03066 *(int32_t*)list->elements[x]->data));
03067
03068 } else if (list->elements[x]->type == (uint32_t)0x000b) {
03069 DEBUG_WARN(("Unknown type %#x 16bit boolean = %s [%hi]\n", list->elements[x]->mapi_id,
03070 (*((int16_t*)list->elements[x]->data)!=0?"True":"False"),
03071 *((int16_t*)list->elements[x]->data)));
03072
03073 } else if (list->elements[x]->type == (uint32_t)0x000d) {
03074 DEBUG_WARN(("Unknown type %#x Embedded object [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)0x0014) {
03079 DEBUG_WARN(("Unknown type %#x signed 64bit int = %"PRIi64"\n", list->elements[x]->mapi_id,
03080 *(int64_t*)list->elements[x]->data));
03081 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03082
03083 } else if (list->elements[x]->type == (uint32_t)0x001e) {
03084 DEBUG_WARN(("Unknown type %#x String Data = \"%s\"\n", list->elements[x]->mapi_id,
03085 list->elements[x]->data));
03086
03087 } else if (list->elements[x]->type == (uint32_t)0x001f) {
03088 DEBUG_WARN(("Unknown type %#x Unicode String Data [size = %#x]\n", list->elements[x]->mapi_id,
03089 list->elements[x]->size));
03090 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03091
03092 } else if (list->elements[x]->type == (uint32_t)0x0040) {
03093 DEBUG_WARN(("Unknown type %#x Date = \"%s\"\n", list->elements[x]->mapi_id,
03094 pst_fileTimeToAscii((FILETIME*)list->elements[x]->data, time_buffer)));
03095
03096 } else if (list->elements[x]->type == (uint32_t)0x0048) {
03097 DEBUG_WARN(("Unknown type %#x OLE GUID [size = %#x]\n", list->elements[x]->mapi_id,
03098 list->elements[x]->size));
03099 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03100
03101 } else if (list->elements[x]->type == (uint32_t)0x0102) {
03102 DEBUG_WARN(("Unknown type %#x Binary Data [size = %#x]\n", list->elements[x]->mapi_id,
03103 list->elements[x]->size));
03104 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03105
03106 } else if (list->elements[x]->type == (uint32_t)0x1003) {
03107 DEBUG_WARN(("Unknown type %#x Array of 32 bit values [size = %#x]\n", list->elements[x]->mapi_id,
03108 list->elements[x]->size));
03109 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03110
03111 } else if (list->elements[x]->type == (uint32_t)0x1014) {
03112 DEBUG_WARN(("Unknown type %#x Array of 64 bit values [siize = %#x]\n", list->elements[x]->mapi_id,
03113 list->elements[x]->size));
03114 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03115
03116 } else if (list->elements[x]->type == (uint32_t)0x101e) {
03117 DEBUG_WARN(("Unknown type %#x Array of Strings [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)0x101f) {
03122 DEBUG_WARN(("Unknown type %#x Array of Unicode Strings [size = %#x]\n", list->elements[x]->mapi_id,
03123 list->elements[x]->size));
03124 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03125
03126 } else if (list->elements[x]->type == (uint32_t)0x1102) {
03127 DEBUG_WARN(("Unknown type %#x Array of binary data blobs [size = %#x]\n", list->elements[x]->mapi_id,
03128 list->elements[x]->size));
03129 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03130
03131 } else {
03132 DEBUG_WARN(("Unknown type %#x Not Printable [%#x]\n", list->elements[x]->mapi_id,
03133 list->elements[x]->type));
03134 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
03135 }
03136
03137 if (list->elements[x]->data) {
03138 free(list->elements[x]->data);
03139 list->elements[x]->data = NULL;
03140 }
03141 }
03142 }
03143 list = list->next;
03144 if (attach) attach = attach->next;
03145 }
03146 DEBUG_RET();
03147 return 0;
03148 }
03149
03150
03151 static void pst_free_list(pst_mapi_object *list) {
03152 pst_mapi_object *l;
03153 DEBUG_ENT("pst_free_list");
03154 while (list) {
03155 if (list->elements) {
03156 int32_t x;
03157 for (x=0; x < list->orig_count; x++) {
03158 if (list->elements[x]) {
03159 if (list->elements[x]->data) free(list->elements[x]->data);
03160 free(list->elements[x]);
03161 }
03162 }
03163 free(list->elements);
03164 }
03165 l = list->next;
03166 free (list);
03167 list = l;
03168 }
03169 DEBUG_RET();
03170 }
03171
03172
03173 static void pst_free_id2(pst_id2_tree * head) {
03174 pst_id2_tree *t;
03175 DEBUG_ENT("pst_free_id2");
03176 while (head) {
03177 if (head->child) pst_free_id2(head->child);
03178 t = head->next;
03179 free(head);
03180 head = t;
03181 }
03182 DEBUG_RET();
03183 }
03184
03185
03186 static void pst_free_id (pst_index_ll *head) {
03187 pst_index_ll *t;
03188 DEBUG_ENT("pst_free_id");
03189 while (head) {
03190 t = head->next;
03191 free(head);
03192 head = t;
03193 }
03194 DEBUG_RET();
03195 }
03196
03197
03198 static void pst_free_desc (pst_desc_tree *head) {
03199 pst_desc_tree *t;
03200 DEBUG_ENT("pst_free_desc");
03201 while (head) {
03202 while (head->child) {
03203 head = head->child;
03204 }
03205
03206
03207 t = head->next;
03208 if (!t && head->parent) {
03209 t = head->parent;
03210 t->child = NULL;
03211 }
03212
03213 if (head) free(head);
03214 else DIE(("head is NULL"));
03215
03216 head = t;
03217 }
03218 DEBUG_RET();
03219 }
03220
03221
03222 static void pst_free_xattrib(pst_x_attrib_ll *x) {
03223 pst_x_attrib_ll *t;
03224 DEBUG_ENT("pst_free_xattrib");
03225 while (x) {
03226 if (x->data) free(x->data);
03227 t = x->next;
03228 free(x);
03229 x = t;
03230 }
03231 DEBUG_RET();
03232 }
03233
03234
03235 static pst_id2_tree * pst_build_id2(pst_file *pf, pst_index_ll* list) {
03236 pst_block_header block_head;
03237 pst_id2_tree *head = NULL, *tail = NULL;
03238 uint16_t x = 0;
03239 char *b_ptr = NULL;
03240 char *buf = NULL;
03241 pst_id2_assoc id2_rec;
03242 pst_index_ll *i_ptr = NULL;
03243 pst_id2_tree *i2_ptr = NULL;
03244 DEBUG_ENT("pst_build_id2");
03245
03246 if (pst_read_block_size(pf, list->offset, list->size, &buf) < list->size) {
03247
03248 DEBUG_WARN(("block read error occured. offset = %#"PRIx64", size = %#"PRIx64"\n", list->offset, list->size));
03249 if (buf) free(buf);
03250 DEBUG_RET();
03251 return NULL;
03252 }
03253 DEBUG_HEXDUMPC(buf, list->size, 16);
03254
03255 memcpy(&block_head, buf, sizeof(block_head));
03256 LE16_CPU(block_head.type);
03257 LE16_CPU(block_head.count);
03258
03259 if (block_head.type != (uint16_t)0x0002) {
03260 DEBUG_WARN(("Unknown constant [%#hx] at start of id2 values [offset %#"PRIx64"].\n", block_head.type, list->offset));
03261 if (buf) free(buf);
03262 DEBUG_RET();
03263 return NULL;
03264 }
03265
03266 DEBUG_INFO(("ID %#"PRIx64" is likely to be a description record. Count is %i (offset %#"PRIx64")\n",
03267 list->i_id, block_head.count, list->offset));
03268 x = 0;
03269 b_ptr = buf + ((pf->do_read64) ? 0x08 : 0x04);
03270 while (x < block_head.count) {
03271 b_ptr += pst_decode_assoc(pf, &id2_rec, b_ptr);
03272 DEBUG_INFO(("id2 = %#x, id = %#"PRIx64", child id = %#"PRIx64"\n", id2_rec.id2, id2_rec.id, id2_rec.child_id));
03273 if ((i_ptr = pst_getID(pf, id2_rec.id)) == NULL) {
03274 DEBUG_WARN(("%#"PRIx64" - Not Found\n", id2_rec.id));
03275 } else {
03276 DEBUG_INFO(("%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %"PRIi64"(%#"PRIx64")\n",
03277 i_ptr->i_id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size));
03278
03279 i2_ptr = (pst_id2_tree*) pst_malloc(sizeof(pst_id2_tree));
03280 i2_ptr->id2 = id2_rec.id2;
03281 i2_ptr->id = i_ptr;
03282 i2_ptr->child = NULL;
03283 i2_ptr->next = NULL;
03284 if (!head) head = i2_ptr;
03285 if (tail) tail->next = i2_ptr;
03286 tail = i2_ptr;
03287 if (id2_rec.child_id) {
03288 if ((i_ptr = pst_getID(pf, id2_rec.child_id)) == NULL) {
03289 DEBUG_WARN(("child id [%#"PRIx64"] not found\n", id2_rec.child_id));
03290 }
03291 else {
03292 i2_ptr->child = pst_build_id2(pf, i_ptr);
03293 }
03294 }
03295 }
03296 x++;
03297 }
03298 if (buf) free (buf);
03299 DEBUG_RET();
03300 return head;
03301 }
03302
03303
03304 static void pst_free_attach(pst_item_attach *attach) {
03305 while (attach) {
03306 pst_item_attach *t;
03307 SAFE_FREE_STR(attach->filename1);
03308 SAFE_FREE_STR(attach->filename2);
03309 SAFE_FREE_STR(attach->mimetype);
03310 SAFE_FREE_BIN(attach->data);
03311 pst_free_id2(attach->id2_head);
03312 t = attach->next;
03313 free(attach);
03314 attach = t;
03315 }
03316 }
03317
03318
03319 void pst_freeItem(pst_item *item) {
03320 pst_item_extra_field *et;
03321
03322 DEBUG_ENT("pst_freeItem");
03323 if (item) {
03324 if (item->email) {
03325 SAFE_FREE(item->email->arrival_date);
03326 SAFE_FREE_STR(item->email->cc_address);
03327 SAFE_FREE_STR(item->email->bcc_address);
03328 SAFE_FREE_BIN(item->email->conversation_index);
03329 SAFE_FREE_BIN(item->email->encrypted_body);
03330 SAFE_FREE_BIN(item->email->encrypted_htmlbody);
03331 SAFE_FREE_STR(item->email->header);
03332 SAFE_FREE_STR(item->email->htmlbody);
03333 SAFE_FREE_STR(item->email->in_reply_to);
03334 SAFE_FREE_STR(item->email->messageid);
03335 SAFE_FREE_STR(item->email->original_bcc);
03336 SAFE_FREE_STR(item->email->original_cc);
03337 SAFE_FREE_STR(item->email->original_to);
03338 SAFE_FREE_STR(item->email->outlook_recipient);
03339 SAFE_FREE_STR(item->email->outlook_recipient_name);
03340 SAFE_FREE_STR(item->email->outlook_recipient2);
03341 SAFE_FREE_STR(item->email->outlook_sender);
03342 SAFE_FREE_STR(item->email->outlook_sender_name);
03343 SAFE_FREE_STR(item->email->outlook_sender2);
03344 SAFE_FREE_STR(item->email->processed_subject);
03345 SAFE_FREE_STR(item->email->recip_access);
03346 SAFE_FREE_STR(item->email->recip_address);
03347 SAFE_FREE_STR(item->email->recip2_access);
03348 SAFE_FREE_STR(item->email->recip2_address);
03349 SAFE_FREE_STR(item->email->reply_to);
03350 SAFE_FREE_STR(item->email->rtf_body_tag);
03351 SAFE_FREE_BIN(item->email->rtf_compressed);
03352 SAFE_FREE_STR(item->email->return_path_address);
03353 SAFE_FREE_STR(item->email->sender_access);
03354 SAFE_FREE_STR(item->email->sender_address);
03355 SAFE_FREE_STR(item->email->sender2_access);
03356 SAFE_FREE_STR(item->email->sender2_address);
03357 SAFE_FREE(item->email->sent_date);
03358 SAFE_FREE(item->email->sentmail_folder);
03359 SAFE_FREE_STR(item->email->sentto_address);
03360 SAFE_FREE_STR(item->email->report_text);
03361 SAFE_FREE(item->email->report_time);
03362 SAFE_FREE_STR(item->email->supplementary_info);
03363 free(item->email);
03364 }
03365 if (item->folder) {
03366 free(item->folder);
03367 }
03368 if (item->message_store) {
03369 SAFE_FREE(item->message_store->top_of_personal_folder);
03370 SAFE_FREE(item->message_store->default_outbox_folder);
03371 SAFE_FREE(item->message_store->deleted_items_folder);
03372 SAFE_FREE(item->message_store->sent_items_folder);
03373 SAFE_FREE(item->message_store->user_views_folder);
03374 SAFE_FREE(item->message_store->common_view_folder);
03375 SAFE_FREE(item->message_store->search_root_folder);
03376 SAFE_FREE(item->message_store->top_of_folder);
03377 free(item->message_store);
03378 }
03379 if (item->contact) {
03380 SAFE_FREE_STR(item->contact->account_name);
03381 SAFE_FREE_STR(item->contact->address1);
03382 SAFE_FREE_STR(item->contact->address1a);
03383 SAFE_FREE_STR(item->contact->address1_desc);
03384 SAFE_FREE_STR(item->contact->address1_transport);
03385 SAFE_FREE_STR(item->contact->address2);
03386 SAFE_FREE_STR(item->contact->address2a);
03387 SAFE_FREE_STR(item->contact->address2_desc);
03388 SAFE_FREE_STR(item->contact->address2_transport);
03389 SAFE_FREE_STR(item->contact->address3);
03390 SAFE_FREE_STR(item->contact->address3a);
03391 SAFE_FREE_STR(item->contact->address3_desc);
03392 SAFE_FREE_STR(item->contact->address3_transport);
03393 SAFE_FREE_STR(item->contact->assistant_name);
03394 SAFE_FREE_STR(item->contact->assistant_phone);
03395 SAFE_FREE_STR(item->contact->billing_information);
03396 SAFE_FREE(item->contact->birthday);
03397 SAFE_FREE_STR(item->contact->business_address);
03398 SAFE_FREE_STR(item->contact->business_city);
03399 SAFE_FREE_STR(item->contact->business_country);
03400 SAFE_FREE_STR(item->contact->business_fax);
03401 SAFE_FREE_STR(item->contact->business_homepage);
03402 SAFE_FREE_STR(item->contact->business_phone);
03403 SAFE_FREE_STR(item->contact->business_phone2);
03404 SAFE_FREE_STR(item->contact->business_po_box);
03405 SAFE_FREE_STR(item->contact->business_postal_code);
03406 SAFE_FREE_STR(item->contact->business_state);
03407 SAFE_FREE_STR(item->contact->business_street);
03408 SAFE_FREE_STR(item->contact->callback_phone);
03409 SAFE_FREE_STR(item->contact->car_phone);
03410 SAFE_FREE_STR(item->contact->company_main_phone);
03411 SAFE_FREE_STR(item->contact->company_name);
03412 SAFE_FREE_STR(item->contact->computer_name);
03413 SAFE_FREE_STR(item->contact->customer_id);
03414 SAFE_FREE_STR(item->contact->def_postal_address);
03415 SAFE_FREE_STR(item->contact->department);
03416 SAFE_FREE_STR(item->contact->display_name_prefix);
03417 SAFE_FREE_STR(item->contact->first_name);
03418 SAFE_FREE_STR(item->contact->followup);
03419 SAFE_FREE_STR(item->contact->free_busy_address);
03420 SAFE_FREE_STR(item->contact->ftp_site);
03421 SAFE_FREE_STR(item->contact->fullname);
03422 SAFE_FREE_STR(item->contact->gov_id);
03423 SAFE_FREE_STR(item->contact->hobbies);
03424 SAFE_FREE_STR(item->contact->home_address);
03425 SAFE_FREE_STR(item->contact->home_city);
03426 SAFE_FREE_STR(item->contact->home_country);
03427 SAFE_FREE_STR(item->contact->home_fax);
03428 SAFE_FREE_STR(item->contact->home_po_box);
03429 SAFE_FREE_STR(item->contact->home_phone);
03430 SAFE_FREE_STR(item->contact->home_phone2);
03431 SAFE_FREE_STR(item->contact->home_postal_code);
03432 SAFE_FREE_STR(item->contact->home_state);
03433 SAFE_FREE_STR(item->contact->home_street);
03434 SAFE_FREE_STR(item->contact->initials);
03435 SAFE_FREE_STR(item->contact->isdn_phone);
03436 SAFE_FREE_STR(item->contact->job_title);
03437 SAFE_FREE_STR(item->contact->keyword);
03438 SAFE_FREE_STR(item->contact->language);
03439 SAFE_FREE_STR(item->contact->location);
03440 SAFE_FREE_STR(item->contact->manager_name);
03441 SAFE_FREE_STR(item->contact->middle_name);
03442 SAFE_FREE_STR(item->contact->mileage);
03443 SAFE_FREE_STR(item->contact->mobile_phone);
03444 SAFE_FREE_STR(item->contact->nickname);
03445 SAFE_FREE_STR(item->contact->office_loc);
03446 SAFE_FREE_STR(item->contact->common_name);
03447 SAFE_FREE_STR(item->contact->org_id);
03448 SAFE_FREE_STR(item->contact->other_address);
03449 SAFE_FREE_STR(item->contact->other_city);
03450 SAFE_FREE_STR(item->contact->other_country);
03451 SAFE_FREE_STR(item->contact->other_phone);
03452 SAFE_FREE_STR(item->contact->other_po_box);
03453 SAFE_FREE_STR(item->contact->other_postal_code);
03454 SAFE_FREE_STR(item->contact->other_state);
03455 SAFE_FREE_STR(item->contact->other_street);
03456 SAFE_FREE_STR(item->contact->pager_phone);
03457 SAFE_FREE_STR(item->contact->personal_homepage);
03458 SAFE_FREE_STR(item->contact->pref_name);
03459 SAFE_FREE_STR(item->contact->primary_fax);
03460 SAFE_FREE_STR(item->contact->primary_phone);
03461 SAFE_FREE_STR(item->contact->profession);
03462 SAFE_FREE_STR(item->contact->radio_phone);
03463 SAFE_FREE_STR(item->contact->spouse_name);
03464 SAFE_FREE_STR(item->contact->suffix);
03465 SAFE_FREE_STR(item->contact->surname);
03466 SAFE_FREE_STR(item->contact->telex);
03467 SAFE_FREE_STR(item->contact->transmittable_display_name);
03468 SAFE_FREE_STR(item->contact->ttytdd_phone);
03469 SAFE_FREE(item->contact->wedding_anniversary);
03470 SAFE_FREE_STR(item->contact->work_address_street);
03471 SAFE_FREE_STR(item->contact->work_address_city);
03472 SAFE_FREE_STR(item->contact->work_address_state);
03473 SAFE_FREE_STR(item->contact->work_address_postalcode);
03474 SAFE_FREE_STR(item->contact->work_address_country);
03475 SAFE_FREE_STR(item->contact->work_address_postofficebox);
03476 free(item->contact);
03477 }
03478
03479 pst_free_attach(item->attach);
03480
03481 while (item->extra_fields) {
03482 SAFE_FREE(item->extra_fields->field_name);
03483 SAFE_FREE(item->extra_fields->value);
03484 et = item->extra_fields->next;
03485 free(item->extra_fields);
03486 item->extra_fields = et;
03487 }
03488 if (item->journal) {
03489 SAFE_FREE(item->journal->start);
03490 SAFE_FREE(item->journal->end);
03491 SAFE_FREE_STR(item->journal->type);
03492 free(item->journal);
03493 }
03494 if (item->appointment) {
03495 SAFE_FREE(item->appointment->start);
03496 SAFE_FREE(item->appointment->end);
03497 SAFE_FREE_STR(item->appointment->location);
03498 SAFE_FREE(item->appointment->reminder);
03499 SAFE_FREE_STR(item->appointment->alarm_filename);
03500 SAFE_FREE_STR(item->appointment->timezonestring);
03501 SAFE_FREE_STR(item->appointment->recurrence_description);
03502 SAFE_FREE_BIN(item->appointment->recurrence_data);
03503 SAFE_FREE(item->appointment->recurrence_start);
03504 SAFE_FREE(item->appointment->recurrence_end);
03505 free(item->appointment);
03506 }
03507 SAFE_FREE(item->ascii_type);
03508 SAFE_FREE_STR(item->body_charset);
03509 SAFE_FREE_STR(item->body);
03510 SAFE_FREE_STR(item->subject);
03511 SAFE_FREE_STR(item->comment);
03512 SAFE_FREE(item->create_date);
03513 SAFE_FREE_STR(item->file_as);
03514 SAFE_FREE(item->modify_date);
03515 SAFE_FREE_STR(item->outlook_version);
03516 SAFE_FREE_BIN(item->record_key);
03517 SAFE_FREE_BIN(item->predecessor_change);
03518 free(item);
03519 }
03520 DEBUG_RET();
03521 }
03522
03523
03530 static int pst_getBlockOffsetPointer(pst_file *pf, pst_id2_tree *i2_head, pst_subblocks *subblocks, uint32_t offset, pst_block_offset_pointer *p) {
03531 size_t size;
03532 pst_block_offset block_offset;
03533 DEBUG_ENT("pst_getBlockOffsetPointer");
03534 if (p->needfree) free(p->from);
03535 p->from = NULL;
03536 p->to = NULL;
03537 p->needfree = 0;
03538 if (!offset) {
03539
03540 p->from = p->to = NULL;
03541 }
03542 else if ((offset & 0xf) == (uint32_t)0xf) {
03543
03544 DEBUG_WARN(("Found id2 %#x value. Will follow it\n", offset));
03545 size = pst_ff_getID2block(pf, offset, i2_head, &(p->from));
03546 if (size) {
03547 p->to = p->from + size;
03548 p->needfree = 1;
03549 }
03550 else {
03551 if (p->from) {
03552 DEBUG_WARN(("size zero but non-null pointer\n"));
03553 free(p->from);
03554 }
03555 p->from = p->to = NULL;
03556 }
03557 }
03558 else {
03559
03560 size_t subindex = offset >> 16;
03561 size_t suboffset = offset & 0xffff;
03562 if (subindex < subblocks->subblock_count) {
03563 if (pst_getBlockOffset(subblocks->subs[subindex].buf,
03564 subblocks->subs[subindex].read_size,
03565 subblocks->subs[subindex].i_offset,
03566 suboffset, &block_offset)) {
03567 p->from = subblocks->subs[subindex].buf + block_offset.from;
03568 p->to = subblocks->subs[subindex].buf + block_offset.to;
03569 }
03570 }
03571 }
03572 DEBUG_RET();
03573 return (p->from) ? 0 : 1;
03574 }
03575
03576
03578 static int pst_getBlockOffset(char *buf, size_t read_size, uint32_t i_offset, uint32_t offset, pst_block_offset *p) {
03579 uint32_t low = offset & 0xf;
03580 uint32_t of1 = offset >> 4;
03581 DEBUG_ENT("pst_getBlockOffset");
03582 if (!p || !buf || !i_offset || low || (i_offset+2+of1+sizeof(*p) > read_size)) {
03583 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));
03584 DEBUG_RET();
03585 return 0;
03586 }
03587 memcpy(&(p->from), &(buf[(i_offset+2)+of1]), sizeof(p->from));
03588 memcpy(&(p->to), &(buf[(i_offset+2)+of1+sizeof(p->from)]), sizeof(p->to));
03589 LE16_CPU(p->from);
03590 LE16_CPU(p->to);
03591 DEBUG_WARN(("get block offset finds from=%i(%#x), to=%i(%#x)\n", p->from, p->from, p->to, p->to));
03592 if (p->from > p->to) {
03593 DEBUG_WARN(("get block offset from > to\n"));
03594 DEBUG_RET();
03595 return 0;
03596 }
03597 DEBUG_RET();
03598 return 1;
03599 }
03600
03601
03603 pst_index_ll* pst_getID(pst_file* pf, uint64_t i_id) {
03604 pst_index_ll *ptr;
03605 DEBUG_ENT("pst_getID");
03606 if (i_id == 0) {
03607 DEBUG_RET();
03608 return NULL;
03609 }
03610
03611
03612
03613 i_id -= (i_id & 1);
03614
03615 DEBUG_INFO(("Trying to find %#"PRIx64"\n", i_id));
03616 ptr = pf->i_head;
03617 while (ptr && (ptr->i_id != i_id)) {
03618 ptr = ptr->next;
03619 }
03620 if (ptr) {DEBUG_INFO(("Found Value %#"PRIx64"\n", i_id)); }
03621 else {DEBUG_INFO(("ERROR: Value %#"PRIx64" not found\n", i_id)); }
03622 DEBUG_RET();
03623 return ptr;
03624 }
03625
03626
03627 static pst_id2_tree *pst_getID2(pst_id2_tree *head, uint64_t id2) {
03628 DEBUG_ENT("pst_getID2");
03629 DEBUG_INFO(("looking for id2 = %#"PRIx64"\n", id2));
03630 pst_id2_tree *ptr = head;
03631 while (ptr) {
03632 if (ptr->id2 == id2) break;
03633 if (ptr->child) {
03634 pst_id2_tree *rc = pst_getID2(ptr->child, id2);
03635 if (rc) {
03636 DEBUG_RET();
03637 return rc;
03638 }
03639 }
03640 ptr = ptr->next;
03641 }
03642 if (ptr && ptr->id) {
03643 DEBUG_INFO(("Found value %#"PRIx64"\n", ptr->id->i_id));
03644 DEBUG_RET();
03645 return ptr;
03646 }
03647 DEBUG_INFO(("ERROR Not Found\n"));
03648 DEBUG_RET();
03649 return NULL;
03650 }
03651
03652
03661 static pst_desc_tree* pst_getDptr(pst_file *pf, uint64_t d_id) {
03662 pst_desc_tree *ptr = pf->d_head;
03663 DEBUG_ENT("pst_getDptr");
03664 while (ptr && (ptr->d_id != d_id)) {
03665
03666 if (ptr->child) {
03667 ptr = ptr->child;
03668 continue;
03669 }
03670 while (!ptr->next && ptr->parent) {
03671 ptr = ptr->parent;
03672 }
03673 ptr = ptr->next;
03674 }
03675 DEBUG_RET();
03676 return ptr;
03677 }
03678
03679
03680 static void pst_printDptr(pst_file *pf, pst_desc_tree *ptr) {
03681 DEBUG_ENT("pst_printDptr");
03682 while (ptr) {
03683 DEBUG_INFO(("%#"PRIx64" [%i] desc=%#"PRIx64", assoc tree=%#"PRIx64"\n", ptr->d_id, ptr->no_child,
03684 (ptr->desc ? ptr->desc->i_id : (uint64_t)0),
03685 (ptr->assoc_tree ? ptr->assoc_tree->i_id : (uint64_t)0)));
03686 if (ptr->child) {
03687 pst_printDptr(pf, ptr->child);
03688 }
03689 ptr = ptr->next;
03690 }
03691 DEBUG_RET();
03692 }
03693
03694
03695 static void pst_printID2ptr(pst_id2_tree *ptr) {
03696 DEBUG_ENT("pst_printID2ptr");
03697 while (ptr) {
03698 DEBUG_INFO(("%#"PRIx64" id=%#"PRIx64"\n", ptr->id2, (ptr->id ? ptr->id->i_id : (uint64_t)0)));
03699 if (ptr->child) pst_printID2ptr(ptr->child);
03700 ptr = ptr->next;
03701 }
03702 DEBUG_RET();
03703 }
03704
03705
03715 static size_t pst_read_block_size(pst_file *pf, int64_t offset, size_t size, char **buf) {
03716 size_t rsize;
03717 DEBUG_ENT("pst_read_block_size");
03718 DEBUG_INFO(("Reading block from %#"PRIx64", %x bytes\n", offset, size));
03719
03720 if (*buf) {
03721 DEBUG_INFO(("Freeing old memory\n"));
03722 free(*buf);
03723 }
03724 *buf = (char*) pst_malloc(size);
03725
03726 rsize = pst_getAtPos(pf, offset, *buf, size);
03727 if (rsize != size) {
03728 DEBUG_WARN(("Didn't read all the data. fread returned less [%i instead of %i]\n", rsize, size));
03729 if (feof(pf->fp)) {
03730 DEBUG_WARN(("We tried to read past the end of the file at [offset %#"PRIx64", size %#x]\n", offset, size));
03731 } else if (ferror(pf->fp)) {
03732 DEBUG_WARN(("Error is set on file stream.\n"));
03733 } else {
03734 DEBUG_WARN(("I can't tell why it failed\n"));
03735 }
03736 }
03737
03738 DEBUG_RET();
03739 return rsize;
03740 }
03741
03742
03753 static int pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type) {
03754 size_t x = 0;
03755 unsigned char y;
03756 DEBUG_ENT("pst_decrypt");
03757 if (!buf) {
03758 DEBUG_RET();
03759 return -1;
03760 }
03761
03762 if (type == PST_COMP_ENCRYPT) {
03763 x = 0;
03764 while (x < size) {
03765 y = (unsigned char)(buf[x]);
03766 buf[x] = (char)comp_enc[y];
03767 x++;
03768 }
03769
03770 } else if (type == PST_ENCRYPT) {
03771
03772
03773 uint16_t salt = (uint16_t) (((i_id & 0x00000000ffff0000) >> 16) ^ (i_id & 0x000000000000ffff));
03774 x = 0;
03775 while (x < size) {
03776 uint8_t losalt = (salt & 0x00ff);
03777 uint8_t hisalt = (salt & 0xff00) >> 8;
03778 y = (unsigned char)buf[x];
03779 y += losalt;
03780 y = comp_high1[y];
03781 y += hisalt;
03782 y = comp_high2[y];
03783 y -= hisalt;
03784 y = comp_enc[y];
03785 y -= losalt;
03786 buf[x] = (char)y;
03787 x++;
03788 salt++;
03789 }
03790
03791 } else {
03792 DEBUG_WARN(("Unknown encryption: %i. Cannot decrypt\n", type));
03793 DEBUG_RET();
03794 return -1;
03795 }
03796 DEBUG_RET();
03797 return 0;
03798 }
03799
03800
03801 static uint64_t pst_getIntAt(pst_file *pf, char *buf) {
03802 uint64_t buf64;
03803 uint32_t buf32;
03804 if (pf->do_read64) {
03805 memcpy(&buf64, buf, sizeof(buf64));
03806 LE64_CPU(buf64);
03807 return buf64;
03808 }
03809 else {
03810 memcpy(&buf32, buf, sizeof(buf32));
03811 LE32_CPU(buf32);
03812 return buf32;
03813 }
03814 }
03815
03816
03817 static uint64_t pst_getIntAtPos(pst_file *pf, int64_t pos ) {
03818 uint64_t buf64;
03819 uint32_t buf32;
03820 if (pf->do_read64) {
03821 (void)pst_getAtPos(pf, pos, &buf64, sizeof(buf64));
03822 LE64_CPU(buf64);
03823 return buf64;
03824 }
03825 else {
03826 (void)pst_getAtPos(pf, pos, &buf32, sizeof(buf32));
03827 LE32_CPU(buf32);
03828 return buf32;
03829 }
03830 }
03831
03841 static size_t pst_getAtPos(pst_file *pf, int64_t pos, void* buf, size_t size) {
03842 size_t rc;
03843 DEBUG_ENT("pst_getAtPos");
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866 if (fseeko(pf->fp, pos, SEEK_SET) == -1) {
03867 DEBUG_RET();
03868 return 0;
03869 }
03870 rc = fread(buf, (size_t)1, size, pf->fp);
03871 DEBUG_RET();
03872 return rc;
03873 }
03874
03875
03884 size_t pst_ff_getIDblock_dec(pst_file *pf, uint64_t i_id, char **buf) {
03885 size_t r;
03886 int noenc = (int)(i_id & 2);
03887 DEBUG_ENT("pst_ff_getIDblock_dec");
03888 DEBUG_INFO(("for id %#"PRIx64"\n", i_id));
03889 r = pst_ff_getIDblock(pf, i_id, buf);
03890 if ((pf->encryption) && !(noenc)) {
03891 (void)pst_decrypt(i_id, *buf, r, pf->encryption);
03892 }
03893 DEBUG_HEXDUMPC(*buf, r, 16);
03894 DEBUG_RET();
03895 return r;
03896 }
03897
03898
03907 static size_t pst_ff_getIDblock(pst_file *pf, uint64_t i_id, char** buf) {
03908 pst_index_ll *rec;
03909 size_t rsize;
03910 DEBUG_ENT("pst_ff_getIDblock");
03911 rec = pst_getID(pf, i_id);
03912 if (!rec) {
03913 DEBUG_INFO(("Cannot find ID %#"PRIx64"\n", i_id));
03914 DEBUG_RET();
03915 return 0;
03916 }
03917 DEBUG_INFO(("id = %#"PRIx64", record size = %#x, offset = %#x\n", i_id, rec->size, rec->offset));
03918 rsize = pst_read_block_size(pf, rec->offset, rec->size, buf);
03919 DEBUG_RET();
03920 return rsize;
03921 }
03922
03923
03924 static size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_id2_tree *id2_head, char** buf) {
03925 size_t ret;
03926 pst_id2_tree* ptr;
03927 pst_holder h = {buf, NULL, 0, 0, 0};
03928 DEBUG_ENT("pst_ff_getID2block");
03929 ptr = pst_getID2(id2_head, id2);
03930
03931 if (!ptr) {
03932 DEBUG_WARN(("Cannot find id2 value %#"PRIx64"\n", id2));
03933 DEBUG_RET();
03934 return 0;
03935 }
03936 ret = pst_ff_getID2data(pf, ptr->id, &h);
03937 DEBUG_RET();
03938 return ret;
03939 }
03940
03941
03950 static size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h) {
03951 size_t ret;
03952 char *b = NULL;
03953 DEBUG_ENT("pst_ff_getID2data");
03954 if (!(ptr->i_id & 0x02)) {
03955 ret = pst_ff_getIDblock_dec(pf, ptr->i_id, &b);
03956 ret = pst_append_holder(h, (size_t)0, &b, ret);
03957 free(b);
03958 } else {
03959
03960 DEBUG_INFO(("Assuming it is a multi-block record because of it's id\n"));
03961 ret = pst_ff_compile_ID(pf, ptr->i_id, h, (size_t)0);
03962 }
03963 ret = pst_finish_cleanup_holder(h, ret);
03964 DEBUG_RET();
03965 return ret;
03966 }
03967
03968
03978 static size_t pst_ff_compile_ID(pst_file *pf, uint64_t i_id, pst_holder *h, size_t size) {
03979 size_t z, a;
03980 uint16_t count, y;
03981 char *buf3 = NULL;
03982 char *buf2 = NULL;
03983 char *b_ptr;
03984 int line_count = 0;
03985 pst_block_hdr block_hdr;
03986 pst_table3_rec table3_rec;
03987
03988 DEBUG_ENT("pst_ff_compile_ID");
03989 a = pst_ff_getIDblock(pf, i_id, &buf3);
03990 if (!a) {
03991 if (buf3) free(buf3);
03992 DEBUG_RET();
03993 return 0;
03994 }
03995 DEBUG_HEXDUMPC(buf3, a, 16);
03996 memcpy(&block_hdr, buf3, sizeof(block_hdr));
03997 LE16_CPU(block_hdr.index_offset);
03998 LE16_CPU(block_hdr.type);
03999 LE32_CPU(block_hdr.offset);
04000 DEBUG_INFO(("block header (index_offset=%#hx, type=%#hx, offset=%#x)\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
04001
04002 count = block_hdr.type;
04003 b_ptr = buf3 + 8;
04004
04005
04006
04007
04008 if (block_hdr.index_offset == (uint16_t)0x0201) {
04009 for (y=0; y<count; y++) {
04010 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
04011 size = pst_ff_compile_ID(pf, table3_rec.id, h, size);
04012 }
04013 free(buf3);
04014 DEBUG_RET();
04015 return size;
04016 }
04017
04018 if (block_hdr.index_offset != (uint16_t)0x0101) {
04019 DEBUG_WARN(("WARNING: not a type 0x0101 buffer, Treating as normal buffer\n"));
04020 if (pf->encryption) (void)pst_decrypt(i_id, buf3, a, pf->encryption);
04021 size = pst_append_holder(h, size, &buf3, a);
04022 free(buf3);
04023 DEBUG_RET();
04024 return size;
04025 }
04026
04027 for (y=0; y<count; y++) {
04028 b_ptr += pst_decode_type3(pf, &table3_rec, b_ptr);
04029 z = pst_ff_getIDblock_dec(pf, table3_rec.id, &buf2);
04030 if (!z) {
04031 DEBUG_WARN(("call to getIDblock returned zero %i\n", z));
04032 if (buf2) free(buf2);
04033 free(buf3);
04034 DEBUG_RET();
04035 return z;
04036 }
04037 size = pst_append_holder(h, size, &buf2, z);
04038 }
04039
04040 free(buf3);
04041 if (buf2) free(buf2);
04042 DEBUG_RET();
04043 return size;
04044 }
04045
04046
04055 static size_t pst_append_holder(pst_holder *h, size_t size, char **buf, size_t z) {
04056 char *t;
04057 DEBUG_ENT("pst_append_holder");
04058
04059
04060 if (h->buf) {
04061 *(h->buf) = realloc(*(h->buf), size+z+1);
04062 DEBUG_INFO(("appending read data of size %i onto main buffer from pos %i\n", z, size));
04063 memcpy(*(h->buf)+size, *buf, z);
04064
04065
04066 } else if ((h->base64 == 1) && h->fp) {
04067
04068 if (h->base64_extra) {
04069
04070 *buf = (char*)realloc(*buf, z+h->base64_extra);
04071 memmove(*buf+h->base64_extra, *buf, z);
04072 memcpy(*buf, h->base64_extra_chars, h->base64_extra);
04073 z += h->base64_extra;
04074 }
04075
04076
04077 h->base64_extra = z % 3;
04078 if (h->base64_extra) {
04079 z -= h->base64_extra;
04080 memcpy(h->base64_extra_chars, *buf+z, h->base64_extra);
04081 }
04082
04083
04084 t = pst_base64_encode_multiple(*buf, z, &h->base64_line_count);
04085 if (t) {
04086 DEBUG_INFO(("writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size));
04087 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
04088 free(t);
04089 }
04090
04091
04092 } else if (h->fp) {
04093 DEBUG_INFO(("writing %i bytes to file. Currently %i\n", z, size));
04094 (void)pst_fwrite(*buf, (size_t)1, z, h->fp);
04095
04096
04097 } else {
04098
04099 }
04100 DEBUG_RET();
04101 return size+z;
04102 }
04103
04104
04111 static size_t pst_finish_cleanup_holder(pst_holder *h, size_t size) {
04112 char *t;
04113 DEBUG_ENT("pst_finish_cleanup_holder");
04114 if ((h->base64 == 1) && h->fp && h->base64_extra) {
04115
04116 t = pst_base64_encode_multiple(h->base64_extra_chars, h->base64_extra, &h->base64_line_count);
04117 if (t) {
04118 (void)pst_fwrite(t, (size_t)1, strlen(t), h->fp);
04119 free(t);
04120 }
04121 size += h->base64_extra;
04122 }
04123 DEBUG_RET();
04124 return size;
04125 }
04126
04127
04128 static int pst_stricmp(char *a, char *b) {
04129
04130
04131 while(*a != '\0' && *b != '\0' && toupper(*a)==toupper(*b)) {
04132 a++; b++;
04133 }
04134 if (toupper(*a) == toupper(*b))
04135 return 0;
04136 else if (toupper(*a) < toupper(*b))
04137 return -1;
04138 else
04139 return 1;
04140 }
04141
04142
04143 static int pst_strincmp(char *a, char *b, size_t x) {
04144
04145
04146 size_t y = 0;
04147 while (*a != '\0' && *b != '\0' && y < x && toupper(*a)==toupper(*b)) {
04148 a++; b++; y++;
04149 }
04150
04151 if (*a == '\0' || *b == '\0' || toupper(*a)==toupper(*b))
04152 return 0;
04153 else if (toupper(*a) < toupper(*b))
04154 return -1;
04155 else
04156 return 1;
04157 }
04158
04159
04160 size_t pst_fwrite(const void* ptr, size_t size, size_t nmemb, FILE *stream) {
04161 size_t r;
04162 if (ptr)
04163 r = fwrite(ptr, size, nmemb, stream);
04164 else {
04165 r = 0;
04166 DEBUG_ENT("pst_fwrite");
04167 DEBUG_WARN(("An attempt to write a NULL Pointer was made\n"));
04168 DEBUG_RET();
04169 }
04170 return r;
04171 }
04172
04173
04174 static char* pst_wide_to_single(char *wt, size_t size) {
04175
04176 char *x, *y;
04177 DEBUG_ENT("pst_wide_to_single");
04178 x = pst_malloc((size/2)+1);
04179 y = x;
04180 while (size != 0 && *wt != '\0') {
04181 *y = *wt;
04182 wt+=2;
04183 size -= 2;
04184 y++;
04185 }
04186 *y = '\0';
04187 DEBUG_RET();
04188 return x;
04189 }
04190
04191
04192 char* pst_rfc2426_escape(char* str, char **buf, size_t* buflen) {
04193
04194
04195 char *ret, *a, *b;
04196 size_t x = 0;
04197 int y, z;
04198 if (!str) return NULL;
04199 DEBUG_ENT("rfc2426_escape");
04200
04201 y = pst_chr_count(str, ',')
04202 + pst_chr_count(str, '\\')
04203 + pst_chr_count(str, ';')
04204 + pst_chr_count(str, '\n');
04205 z = pst_chr_count(str, '\r');
04206 if (y == 0 && z == 0)
04207
04208 ret = str;
04209 else {
04210 x = strlen(str) + y - z + 1;
04211 if (x > *buflen) {
04212 *buf = (char*) realloc(*buf, x);
04213 *buflen = x;
04214 }
04215 a = str;
04216 b = *buf;
04217 while (*a != '\0') {
04218 switch (*a) {
04219 case ',' :
04220 case '\\':
04221 case ';' :
04222 *(b++) = '\\';
04223 *b = *a;
04224 break;
04225 case '\n':
04226 *(b++) = '\\';
04227 *b = 'n';
04228 break;
04229 case '\r':
04230 b--;
04231 break;
04232 default:
04233 *b=*a;
04234 }
04235 b++;
04236 a++;
04237 }
04238 *b = '\0';
04239 ret = *buf;
04240 }
04241 DEBUG_RET();
04242 return ret;
04243 }
04244
04245
04246 static int pst_chr_count(char *str, char x) {
04247 int r = 0;
04248 while (*str) {
04249 if (*str == x) r++;
04250 str++;
04251 }
04252 return r;
04253 }
04254
04255
04256 char* pst_rfc2425_datetime_format(const FILETIME* ft, int buflen, char* result) {
04257 struct tm stm;
04258 DEBUG_ENT("rfc2425_datetime_format");
04259 pst_fileTimeToStructTM(ft, &stm);
04260 if (strftime(result, buflen, "%Y-%m-%dT%H:%M:%SZ", &stm)==0) {
04261 DEBUG_INFO(("Problem occured formatting date\n"));
04262 }
04263 DEBUG_RET();
04264 return result;
04265 }
04266
04267
04268 char* pst_rfc2445_datetime_format(const FILETIME* ft, int buflen, char* result) {
04269 struct tm stm;
04270 DEBUG_ENT("rfc2445_datetime_format");
04271 pst_fileTimeToStructTM(ft, &stm);
04272 if (strftime(result, buflen, "%Y%m%dT%H%M%SZ", &stm)==0) {
04273 DEBUG_INFO(("Problem occured formatting date\n"));
04274 }
04275 DEBUG_RET();
04276 return result;
04277 }
04278
04279
04280 char* pst_rfc2445_datetime_format_now(int buflen, char* result) {
04281 struct tm stm;
04282 time_t t = time(NULL);
04283 DEBUG_ENT("rfc2445_datetime_format_now");
04284 gmtime_r(&t, &stm);
04285 if (strftime(result, buflen, "%Y%m%dT%H%M%SZ", &stm)==0) {
04286 DEBUG_INFO(("Problem occured formatting date\n"));
04287 }
04288 DEBUG_RET();
04289 return result;
04290 }
04291
04292
04301 static const char* codepage(int cp, int buflen, char* result);
04302 static const char* codepage(int cp, int buflen, char* result) {
04303 switch (cp) {
04304 case 932 : return "iso-2022-jp";
04305 case 936 : return "gb2313";
04306 case 950 : return "big5";
04307 case 1200 : return "ucs-2le";
04308 case 1201 : return "ucs-2be";
04309 case 20127 : return "us-ascii";
04310 case 20269 : return "iso-6937";
04311 case 20865 : return "iso-8859-15";
04312 case 20866 : return "koi8-r";
04313 case 21866 : return "koi8-u";
04314 case 28591 : return "iso-8859-1";
04315 case 28592 : return "iso-8859-2";
04316 case 28595 : return "iso-8859-5";
04317 case 28596 : return "iso-8859-6";
04318 case 28597 : return "iso-8859-7";
04319 case 28598 : return "iso-8859-8";
04320 case 28599 : return "iso-8859-9";
04321 case 28600 : return "iso-8859-10";
04322 case 28601 : return "iso-8859-11";
04323 case 28602 : return "iso-8859-12";
04324 case 28603 : return "iso-8859-13";
04325 case 28604 : return "iso-8859-14";
04326 case 28605 : return "iso-8859-15";
04327 case 28606 : return "iso-8859-16";
04328 case 50220 : return "iso-2022-jp";
04329 case 50221 : return "csiso2022jp";
04330 case 51932 : return "euc-jp";
04331 case 51949 : return "euc-kr";
04332 case 65000 : return "utf-7";
04333 case 65001 : return "utf-8";
04334 default :
04335 snprintf(result, buflen, "windows-%d", cp);
04336 return result;
04337 }
04338 return NULL;
04339 }
04340
04341
04349 const char* pst_default_charset(pst_item *item, int buflen, char* result) {
04350 return (item->body_charset.str) ? item->body_charset.str :
04351 (item->message_codepage) ? codepage(item->message_codepage, buflen, result) :
04352 (item->internet_cpid) ? codepage(item->internet_cpid, buflen, result) :
04353 "utf-8";
04354 }
04355
04356
04362 void pst_convert_utf8_null(pst_item *item, pst_string *str) {
04363 if (!str->str) return;
04364 pst_convert_utf8(item, str);
04365 }
04366
04367
04373 void pst_convert_utf8(pst_item *item, pst_string *str) {
04374 char buffer[30];
04375 if (str->is_utf8) return;
04376 if (!str->str) {
04377 str->str = strdup("");
04378 return;
04379 }
04380 const char *charset = pst_default_charset(item, sizeof(buffer), buffer);
04381 if (!strcasecmp("utf-8", charset)) return;
04382 DEBUG_ENT("pst_convert_utf8");
04383 pst_vbuf *newer = pst_vballoc(2);
04384 size_t rc = pst_vb_8bit2utf8(newer, str->str, strlen(str->str) + 1, charset);
04385 if (rc == (size_t)-1) {
04386 free(newer->b);
04387 DEBUG_WARN(("Failed to convert %s to utf-8 - %s\n", charset, str->str));
04388 }
04389 else {
04390 free(str->str);
04391 str->str = newer->b;
04392 str->is_utf8 = 1;
04393 }
04394 free(newer);
04395 DEBUG_RET();
04396 }
04397
04398
04403 pst_recurrence* pst_convert_recurrence(pst_item_appointment* appt)
04404 {
04405 const int bias = 30 * 24 * 60;
04406 int m[4] = {3,4,4,5};
04407 pst_recurrence *r = pst_malloc(sizeof(pst_recurrence));
04408 memset(r, 0, sizeof(pst_recurrence));
04409 size_t s = appt->recurrence_data.size;
04410 size_t i = 0;
04411 char* p = appt->recurrence_data.data;
04412 if (p) {
04413 if (i+4 <= s) { r->signature = PST_LE_GET_UINT32(p+i); i += 4; }
04414 if (i <= s) { r->type = PST_LE_GET_UINT8(p+i) - 0x0a; i += 2; }
04415 if (i+4 <= s) { r->sub_type = PST_LE_GET_UINT32(p+i); i += 4; }
04416 if (r->sub_type <= 3) {
04417 int n = m[r->sub_type];
04418 int j = 0;
04419 for (j=0; j<n; j++) {
04420 if (i+4 <= s) { *(&r->parm1 + j) = PST_LE_GET_UINT32(p+i); i += 4; }
04421 }
04422 }
04423 if (i <= s) { r->termination = PST_LE_GET_UINT8(p+i) - 0x21; i += 4; }
04424 if (i+4 <= s) { r->count = PST_LE_GET_UINT32(p+i); i += 4; }
04425 if (r->termination == 2) r->count = 0;
04426 switch (r->type) {
04427 case 0:
04428 if (r->sub_type == 0) {
04429
04430 r->interval = r->parm2 / (24 * 60);
04431 }
04432 else {
04433
04434 r->interval = 1;
04435 r->bydaymask = r->parm4;
04436 }
04437 break;
04438 case 1:
04439 r->interval = r->parm2;
04440 r->bydaymask = r->parm4;
04441 break;
04442 case 2:
04443 r->interval = r->parm2;
04444 if (r->sub_type == 2) {
04445
04446 r->dayofmonth = r->parm4;
04447 }
04448 else {
04449
04450 r->bydaymask = r->parm4;
04451 r->position = r->parm5;
04452 }
04453 break;
04454 case 3:
04455 r->interval = 1;
04456 r->monthofyear = ((r->parm1 + bias/2) / bias) + 1;
04457 if (r->sub_type == 2) {
04458
04459 r->dayofmonth = r->parm4;
04460 }
04461 else {
04462
04463 r->bydaymask = r->parm4;
04464 r->position = r->parm5;
04465 }
04466 break;
04467 default:
04468 break;
04469 }
04470 }
04471 return r;
04472 }
04473
04474
04478 void pst_free_recurrence(pst_recurrence* r)
04479 {
04480 if (r) free(r);
04481 }