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