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