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