Mercurial > libpst
comparison src/libpst.c @ 103:0af0bbe166e1
create dummy top-of-folder descriptor if needed for corrupt pst files
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 07 Oct 2008 10:45:50 -0700 |
parents | 8c4482be0b4c |
children | 39ba19372732 |
comparison
equal
deleted
inserted
replaced
102:8c4482be0b4c | 103:0af0bbe166e1 |
---|---|
245 DEBUG_RET(); | 245 DEBUG_RET(); |
246 return 0; | 246 return 0; |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 /** | |
251 * add a pst descriptor node to a linked list of such nodes. | |
252 * | |
253 * @param node pointer to the node to be added to the list | |
254 * @param head pointer to the list head pointer | |
255 * @param tail pointer to the list tail pointer | |
256 */ | |
257 static void add_descriptor_to_list(pst_desc_ll *node, pst_desc_ll **head, pst_desc_ll **tail); | |
258 static void add_descriptor_to_list(pst_desc_ll *node, pst_desc_ll **head, pst_desc_ll **tail) | |
259 { | |
260 DEBUG_ENT("add_descriptor_to_list"); | |
261 //DEBUG_INDEX(("Added node %#"PRIx64" parent %#"PRIx64" real parent %#"PRIx64" prev %#"PRIx64" next %#"PRIx64"\n", | |
262 // node->id, node->parent_id, | |
263 // (node->parent ? node->parent->id : (uint64_t)0), | |
264 // (node->prev ? node->prev->id : (uint64_t)0), | |
265 // (node->next ? node->next->id : (uint64_t)0))); | |
266 if (*tail) (*tail)->next = node; | |
267 if (!(*head)) *head = node; | |
268 node->prev = *tail; | |
269 node->next = NULL; | |
270 *tail = node; | |
271 DEBUG_RET(); | |
272 } | |
273 | |
274 | |
275 /** | |
276 * add a pst descriptor node into the global tree. | |
277 * | |
278 * @param pf global pst file pointer | |
279 * @param node pointer to the new node to be added to the tree | |
280 */ | |
281 static void record_descriptor(pst_file *pf, pst_desc_ll *node); | |
282 static void record_descriptor(pst_file *pf, pst_desc_ll *node) | |
283 { | |
284 // finish node initialization | |
285 node->parent = NULL; | |
286 node->child = NULL; | |
287 node->child_tail = NULL; | |
288 node->no_child = 0; | |
289 | |
290 // find any orphan children of this node, and collect them | |
291 pst_desc_ll *n = pf->d_head; | |
292 while (n) { | |
293 if (n->parent_id == node->id) { | |
294 // found a child of this node | |
295 DEBUG_INDEX(("Found orphan child %#"PRIx64" of parent %#"PRIx64"\n", n->id, node->id)); | |
296 pst_desc_ll *nn = n->next; | |
297 pst_desc_ll *pp = n->prev; | |
298 node->no_child++; | |
299 n->parent = node; | |
300 add_descriptor_to_list(n, &node->child, &node->child_tail); | |
301 if (pp) pp->next = nn; else pf->d_head = nn; | |
302 if (nn) nn->prev = pp; else pf->d_tail = pp; | |
303 n = nn; | |
304 } | |
305 else { | |
306 n = n->next; | |
307 } | |
308 } | |
309 | |
310 // now hook this node into the global tree | |
311 if (node->parent_id == 0) { | |
312 // add top level node to the descriptor tree | |
313 //DEBUG_INDEX(("Null parent\n")); | |
314 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); | |
315 } | |
316 else if (node->parent_id == node->id) { | |
317 // add top level node to the descriptor tree | |
318 DEBUG_INDEX(("%#"PRIx64" is its own parent. What is this world coming to?\n")); | |
319 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); | |
320 } else { | |
321 //DEBUG_INDEX(("Searching for parent %#"PRIx64" of %#"PRIx64"\n", node->parent_id, node->id)); | |
322 pst_desc_ll *parent = pst_getDptr(pf, node->parent_id); | |
323 if (parent) { | |
324 //DEBUG_INDEX(("Found parent %#"PRIx64"\n", node->parent_id)); | |
325 parent->no_child++; | |
326 node->parent = parent; | |
327 add_descriptor_to_list(node, &parent->child, &parent->child_tail); | |
328 } | |
329 else { | |
330 DEBUG_INDEX(("No parent %#"PRIx64", have an orphan child %#"PRIx64"\n", node->parent_id, node->id)); | |
331 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); | |
332 } | |
333 } | |
334 } | |
335 | |
336 | |
250 pst_desc_ll* pst_getTopOfFolders(pst_file *pf, pst_item *root) { | 337 pst_desc_ll* pst_getTopOfFolders(pst_file *pf, pst_item *root) { |
251 pst_desc_ll *ret; | 338 pst_desc_ll *topnode; |
339 uint32_t topid; | |
252 DEBUG_ENT("pst_getTopOfFolders"); | 340 DEBUG_ENT("pst_getTopOfFolders"); |
253 if (!root || !root->message_store) { | 341 if (!root || !root->message_store) { |
254 DEBUG_INDEX(("There isn't a top of folder record here.\n")); | 342 DEBUG_INDEX(("There isn't a top of folder record here.\n")); |
255 ret = NULL; | 343 DEBUG_RET(); |
256 } else if (!root->message_store->top_of_personal_folder) { | 344 return NULL; |
345 } | |
346 if (!root->message_store->top_of_personal_folder) { | |
257 // this is the OST way | 347 // this is the OST way |
258 // ASSUMPTION: Top Of Folders record in PST files is *always* descid 0x2142 | 348 // ASSUMPTION: Top Of Folders record in PST files is *always* descid 0x2142 |
259 ret = pst_getDptr(pf, (uint64_t)0x2142); | 349 topid = 0x2142; |
260 } else { | 350 } else { |
261 ret = pst_getDptr(pf, root->message_store->top_of_personal_folder->id); | 351 topid = root->message_store->top_of_personal_folder->id; |
352 } | |
353 DEBUG_INDEX(("looking for top of folder descriptor %#"PRIx32"\n", topid)); | |
354 topnode = pst_getDptr(pf, (uint64_t)topid); | |
355 if (!topnode) { | |
356 // add dummy top record to pickup orphan children | |
357 topnode = (pst_desc_ll*) xmalloc(sizeof(pst_desc_ll)); | |
358 topnode->id = topid; | |
359 topnode->parent_id = 0; | |
360 topnode->list_index = NULL; | |
361 topnode->desc = NULL; | |
362 record_descriptor(pf, topnode); // add to the global tree | |
262 } | 363 } |
263 DEBUG_RET(); | 364 DEBUG_RET(); |
264 return ret; | 365 return topnode; |
265 } | 366 } |
266 | 367 |
267 | 368 |
268 size_t pst_attach_to_mem(pst_file *pf, pst_item_attach *attach, char **b){ | 369 size_t pst_attach_to_mem(pst_file *pf, pst_item_attach *attach, char **b){ |
269 size_t size=0; | 370 size_t size=0; |
817 DEBUG_RET(); | 918 DEBUG_RET(); |
818 return 0; | 919 return 0; |
819 } | 920 } |
820 | 921 |
821 | 922 |
822 /** | |
823 * add a pst descriptor node to a linked list of such nodes. | |
824 * | |
825 * @param node pointer to the node to be added to the list | |
826 * @param head pointer to the list head pointer | |
827 * @param tail pointer to the list tail pointer | |
828 */ | |
829 static void add_descriptor_to_list(pst_desc_ll *node, pst_desc_ll **head, pst_desc_ll **tail); | |
830 static void add_descriptor_to_list(pst_desc_ll *node, pst_desc_ll **head, pst_desc_ll **tail) | |
831 { | |
832 DEBUG_ENT("add_descriptor_to_list"); | |
833 //DEBUG_INDEX(("Added node %#"PRIx64" parent %#"PRIx64" real parent %#"PRIx64" prev %#"PRIx64" next %#"PRIx64"\n", | |
834 // node->id, node->parent_id, | |
835 // (node->parent ? node->parent->id : (uint64_t)0), | |
836 // (node->prev ? node->prev->id : (uint64_t)0), | |
837 // (node->next ? node->next->id : (uint64_t)0))); | |
838 if (*tail) (*tail)->next = node; | |
839 if (!(*head)) *head = node; | |
840 node->prev = *tail; | |
841 *tail = node; | |
842 DEBUG_RET(); | |
843 } | |
844 | |
845 | |
846 /** | |
847 * add a pst descriptor node into the global tree. | |
848 * | |
849 * @param pf global pst file pointer | |
850 * @param node pointer to the node to be added to the tree | |
851 */ | |
852 static void record_descriptor(pst_file *pf, pst_desc_ll *node); | |
853 static void record_descriptor(pst_file *pf, pst_desc_ll *node) | |
854 { | |
855 // find any orphan children of this node, and collect them | |
856 pst_desc_ll *n = pf->d_head; | |
857 while (n) { | |
858 if (n->parent_id == node->id) { | |
859 // found a child of this node | |
860 DEBUG_INDEX(("Found orphan child %#"PRIx64" of parent %#"PRIx64"\n", n->id, node->id)); | |
861 pst_desc_ll *nn = n->next; | |
862 pst_desc_ll *pp = n->prev; | |
863 node->no_child++; | |
864 n->parent = node; | |
865 n->prev = NULL; | |
866 n->next = NULL; | |
867 add_descriptor_to_list(n, &node->child, &node->child_tail); | |
868 if (pp) pp->next = nn; else pf->d_head = nn; | |
869 if (nn) nn->prev = pp; else pf->d_tail = pp; | |
870 n = nn; | |
871 } | |
872 else { | |
873 n = n->next; | |
874 } | |
875 } | |
876 | |
877 // now hook this node into the global tree | |
878 if (node->parent_id == 0) { | |
879 // add top level node to the descriptor tree | |
880 //DEBUG_INDEX(("Null parent\n")); | |
881 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); | |
882 } | |
883 else if (node->parent_id == node->id) { | |
884 // add top level node to the descriptor tree | |
885 DEBUG_INDEX(("%#"PRIx64" is its own parent. What is this world coming to?\n")); | |
886 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); | |
887 } else { | |
888 //DEBUG_INDEX(("Searching for parent %#"PRIx64" of %#"PRIx64"\n", node->parent_id, node->id)); | |
889 pst_desc_ll *parent = pst_getDptr(pf, node->parent_id); | |
890 if (parent) { | |
891 //DEBUG_INDEX(("Found parent %#"PRIx64"\n", node->parent_id)); | |
892 parent->no_child++; | |
893 node->parent = parent; | |
894 add_descriptor_to_list(node, &parent->child, &parent->child_tail); | |
895 } | |
896 else { | |
897 DEBUG_INDEX(("No parent %#"PRIx64", have an orphan child %#"PRIx64"\n", node->parent_id, node->id)); | |
898 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); | |
899 } | |
900 } | |
901 } | |
902 | |
903 | |
904 int pst_build_desc_ptr (pst_file *pf, off_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val) { | 923 int pst_build_desc_ptr (pst_file *pf, off_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val) { |
905 struct pst_table_ptr_structn table, table2; | 924 struct pst_table_ptr_structn table, table2; |
906 pst_descn desc_rec; | 925 pst_descn desc_rec; |
907 pst_desc_ll *d_ptr=NULL, *parent=NULL; | 926 pst_desc_ll *d_ptr=NULL, *parent=NULL; |
908 int32_t item_count; | 927 int32_t item_count; |
967 d_ptr = (pst_desc_ll*) xmalloc(sizeof(pst_desc_ll)); | 986 d_ptr = (pst_desc_ll*) xmalloc(sizeof(pst_desc_ll)); |
968 d_ptr->id = desc_rec.d_id; | 987 d_ptr->id = desc_rec.d_id; |
969 d_ptr->parent_id = desc_rec.parent_id; | 988 d_ptr->parent_id = desc_rec.parent_id; |
970 d_ptr->list_index = pst_getID(pf, desc_rec.list_id); | 989 d_ptr->list_index = pst_getID(pf, desc_rec.list_id); |
971 d_ptr->desc = pst_getID(pf, desc_rec.desc_id); | 990 d_ptr->desc = pst_getID(pf, desc_rec.desc_id); |
972 d_ptr->prev = NULL; | |
973 d_ptr->next = NULL; | |
974 d_ptr->parent = NULL; | |
975 d_ptr->child = NULL; | |
976 d_ptr->child_tail = NULL; | |
977 d_ptr->no_child = 0; | |
978 record_descriptor(pf, d_ptr); // add to the global tree | 991 record_descriptor(pf, d_ptr); // add to the global tree |
979 //DEBUG_INDEX(("dump parent descriptor tree\n")); //!! | |
980 //d_ptr = pst_getDptr(pf, (uint64_t)-1); //!! | |
981 } | 992 } |
982 } else { | 993 } else { |
983 // this node contains node pointers | 994 // this node contains node pointers |
984 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, ITEM_SIZE32); | 995 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, ITEM_SIZE32); |
985 if (item_count > INDEX_COUNT_MAX) { | 996 if (item_count > INDEX_COUNT_MAX) { |
3409 DEBUG_EMAIL(("Unknown type %#x double floating [size = %#x]\n", list->items[x]->id, | 3420 DEBUG_EMAIL(("Unknown type %#x double floating [size = %#x]\n", list->items[x]->id, |
3410 list->items[x]->size)); | 3421 list->items[x]->size)); |
3411 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); | 3422 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); |
3412 | 3423 |
3413 } else if (list->items[x]->type == (uint32_t)0x0006) { | 3424 } else if (list->items[x]->type == (uint32_t)0x0006) { |
3414 DEBUG_EMAIL(("Unknown type %#x signed 64bit int = %lli\n", list->items[x]->id, | 3425 DEBUG_EMAIL(("Unknown type %#x signed 64bit int = %"PRIi64"\n", list->items[x]->id, |
3415 *(int64_t*)list->items[x]->data)); | 3426 *(int64_t*)list->items[x]->data)); |
3416 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); | 3427 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); |
3417 | 3428 |
3418 } else if (list->items[x]->type == (uint32_t)0x0007) { | 3429 } else if (list->items[x]->type == (uint32_t)0x0007) { |
3419 DEBUG_EMAIL(("Unknown type %#x application time [size = %#x]\n", list->items[x]->id, | 3430 DEBUG_EMAIL(("Unknown type %#x application time [size = %#x]\n", list->items[x]->id, |
3433 DEBUG_EMAIL(("Unknown type %#x Embedded object [size = %#x]\n", list->items[x]->id, | 3444 DEBUG_EMAIL(("Unknown type %#x Embedded object [size = %#x]\n", list->items[x]->id, |
3434 list->items[x]->size)); | 3445 list->items[x]->size)); |
3435 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); | 3446 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); |
3436 | 3447 |
3437 } else if (list->items[x]->type == (uint32_t)0x0014) { | 3448 } else if (list->items[x]->type == (uint32_t)0x0014) { |
3438 DEBUG_EMAIL(("Unknown type %#x signed 64bit int = %lli\n", list->items[x]->id, | 3449 DEBUG_EMAIL(("Unknown type %#x signed 64bit int = %"PRIi64"\n", list->items[x]->id, |
3439 *(int64_t*)list->items[x]->data)); | 3450 *(int64_t*)list->items[x]->data)); |
3440 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); | 3451 DEBUG_HEXDUMP(list->items[x]->data, list->items[x]->size); |
3441 | 3452 |
3442 } else if (list->items[x]->type == (uint32_t)0x001e) { | 3453 } else if (list->items[x]->type == (uint32_t)0x001e) { |
3443 DEBUG_EMAIL(("Unknown type %#x String Data = \"%s\"\n", list->items[x]->id, | 3454 DEBUG_EMAIL(("Unknown type %#x String Data = \"%s\"\n", list->items[x]->id, |
3635 b_ptr += pst_decode_assoc(pf, &id2_rec, b_ptr); | 3646 b_ptr += pst_decode_assoc(pf, &id2_rec, b_ptr); |
3636 DEBUG_INDEX(("\tid2 = %#x, id = %#"PRIx64", table2 = %#"PRIx64"\n", id2_rec.id2, id2_rec.id, id2_rec.table2)); | 3647 DEBUG_INDEX(("\tid2 = %#x, id = %#"PRIx64", table2 = %#"PRIx64"\n", id2_rec.id2, id2_rec.id, id2_rec.table2)); |
3637 if ((i_ptr = pst_getID(pf, id2_rec.id)) == NULL) { | 3648 if ((i_ptr = pst_getID(pf, id2_rec.id)) == NULL) { |
3638 DEBUG_WARN(("\t\t%#"PRIx64" - Not Found\n", id2_rec.id)); | 3649 DEBUG_WARN(("\t\t%#"PRIx64" - Not Found\n", id2_rec.id)); |
3639 } else { | 3650 } else { |
3640 DEBUG_INDEX(("\t\t%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %lli(%#"PRIx64")\n", i_ptr->id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size)); | 3651 DEBUG_INDEX(("\t\t%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %"PRIi64"(%#"PRIx64")\n", |
3652 i_ptr->id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size)); | |
3641 // add it to the linked list | 3653 // add it to the linked list |
3642 i2_ptr = (pst_index2_ll*) xmalloc(sizeof(pst_index2_ll)); | 3654 i2_ptr = (pst_index2_ll*) xmalloc(sizeof(pst_index2_ll)); |
3643 i2_ptr->id2 = id2_rec.id2; | 3655 i2_ptr->id2 = id2_rec.id2; |
3644 i2_ptr->id = i_ptr; | 3656 i2_ptr->id = i_ptr; |
3645 i2_ptr->next = NULL; | 3657 i2_ptr->next = NULL; |
4033 | 4045 |
4034 | 4046 |
4035 void pst_printDptr(pst_file *pf, pst_desc_ll *ptr) { | 4047 void pst_printDptr(pst_file *pf, pst_desc_ll *ptr) { |
4036 DEBUG_ENT("pst_printDptr"); | 4048 DEBUG_ENT("pst_printDptr"); |
4037 while (ptr) { | 4049 while (ptr) { |
4038 DEBUG_INDEX(("%#x [%i] desc=%#x, list=%#x\n", ptr->id, ptr->no_child, | 4050 DEBUG_INDEX(("%#"PRIx64" [%i] desc=%#"PRIx64", list=%#"PRIx64"\n", ptr->id, ptr->no_child, |
4039 (ptr->desc==NULL?0:ptr->desc->id), | 4051 (ptr->desc ? ptr->desc->id : (uint64_t)0), |
4040 (ptr->list_index==NULL?0:ptr->list_index->id))); | 4052 (ptr->list_index ? ptr->list_index->id : (uint64_t)0))); |
4041 if (ptr->child) { | 4053 if (ptr->child) { |
4042 pst_printDptr(pf, ptr->child); | 4054 pst_printDptr(pf, ptr->child); |
4043 } | 4055 } |
4044 ptr = ptr->next; | 4056 ptr = ptr->next; |
4045 } | 4057 } |
4049 | 4061 |
4050 void pst_printIDptr(pst_file* pf) { | 4062 void pst_printIDptr(pst_file* pf) { |
4051 pst_index_ll *ptr = pf->i_head; | 4063 pst_index_ll *ptr = pf->i_head; |
4052 DEBUG_ENT("pst_printIDptr"); | 4064 DEBUG_ENT("pst_printIDptr"); |
4053 while (ptr) { | 4065 while (ptr) { |
4054 DEBUG_INDEX(("%#x offset=%#x size=%#x\n", ptr->id, ptr->offset, ptr->size)); | 4066 DEBUG_INDEX(("%#"PRIx64" offset=%#"PRIx64" size=%#"PRIx64"\n", ptr->id, ptr->offset, ptr->size)); |
4055 ptr = ptr->next; | 4067 ptr = ptr->next; |
4056 } | 4068 } |
4057 DEBUG_RET(); | 4069 DEBUG_RET(); |
4058 } | 4070 } |
4059 | 4071 |
4060 | 4072 |
4061 void pst_printID2ptr(pst_index2_ll *ptr) { | 4073 void pst_printID2ptr(pst_index2_ll *ptr) { |
4062 DEBUG_ENT("pst_printID2ptr"); | 4074 DEBUG_ENT("pst_printID2ptr"); |
4063 while (ptr) { | 4075 while (ptr) { |
4064 DEBUG_INDEX(("%#x id=%#x\n", ptr->id2, (ptr->id!=NULL?ptr->id->id:0))); | 4076 DEBUG_INDEX(("%#"PRIx64" id=%#"PRIx64"\n", ptr->id2, (ptr->id ? ptr->id->id : (uint64_t)0))); |
4065 ptr = ptr->next; | 4077 ptr = ptr->next; |
4066 } | 4078 } |
4067 DEBUG_RET(); | 4079 DEBUG_RET(); |
4068 } | 4080 } |
4069 | 4081 |