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