comparison src/libpst.c @ 35:b2f247463b83 stable-0-5-6

better decoding of 7c blocks
author carl
date Sun, 15 Jul 2007 14:25:34 -0700
parents 07177825c91b
children 6fe121a971c9
comparison
equal deleted inserted replaced
34:07177825c91b 35:b2f247463b83
42 #define SECOND_POINTER_64 0xE0 42 #define SECOND_POINTER_64 0xE0
43 43
44 #define PST_SIGNATURE 0x4E444221 44 #define PST_SIGNATURE 0x4E444221
45 45
46 struct _pst_table_ptr_struct{ 46 struct _pst_table_ptr_struct{
47 u_int32_t start; 47 int32_t start;
48 int32_t u1; 48 int32_t u1;
49 int32_t offset; 49 int32_t offset;
50 }; 50 };
51 51
52 typedef struct _pst_block_header { 52 typedef struct _pst_block_header {
53 int16_t type; 53 int16_t type;
54 int16_t count; 54 int16_t count;
55 } pst_block_header; 55 } pst_block_header;
56 56
57 typedef struct _pst_id2_assoc { 57 typedef struct _pst_id2_assoc {
58 int32_t id2; 58 u_int32_t id2;
59 int32_t id; 59 u_int32_t id;
60 int32_t table2; 60 int32_t table2;
61 } pst_id2_assoc; 61 } pst_id2_assoc;
62 62
63 // this is an array of the un-encrypted values. the un-encrypyed value is in the position 63 // this is an array of the un-encrypted values. the un-encrypted value is in the position
64 // of the encrypted value. ie the encrypted value 0x13 represents 0x02 64 // of the encrypted value. ie the encrypted value 0x13 represents 0x02
65 // 0 1 2 3 4 5 6 7 65 // 0 1 2 3 4 5 6 7
66 // 8 9 a b c d e f 66 // 8 9 a b c d e f
67 unsigned char comp_enc [] = 67 unsigned char comp_enc [] =
68 { 0x47, 0xf1, 0xb4, 0xe6, 0x0b, 0x6a, 0x72, 0x48, 68 { 0x47, 0xf1, 0xb4, 0xe6, 0x0b, 0x6a, 0x72, 0x48,
190 } 190 }
191 191
192 192
193 pst_desc_ll* pst_getTopOfFolders(pst_file *pf, pst_item *root) { 193 pst_desc_ll* pst_getTopOfFolders(pst_file *pf, pst_item *root) {
194 pst_desc_ll *ret; 194 pst_desc_ll *ret;
195 // pst_item *i;
196 // char *a, *b;
197 // int x,z;
198 DEBUG_ENT("pst_getTopOfFolders"); 195 DEBUG_ENT("pst_getTopOfFolders");
199 if (!root || !root->message_store) { 196 if (!root || !root->message_store) {
200 DEBUG_INDEX(("There isn't a top of folder record here.\n")); 197 DEBUG_INDEX(("There isn't a top of folder record here.\n"));
201 ret = NULL; 198 ret = NULL;
202 } else if (!root->message_store->top_of_personal_folder) { 199 } else if (!root->message_store->top_of_personal_folder) {
519 bptr += sizeof(index); 516 bptr += sizeof(index);
520 x++; 517 x++;
521 if (index.id == 0) break; 518 if (index.id == 0) break;
522 DEBUG_INDEX(("[%i]%i Item [id = %#x, offset = %#x, u1 = %#x, size = %i(%#x)]\n", 519 DEBUG_INDEX(("[%i]%i Item [id = %#x, offset = %#x, u1 = %#x, size = %i(%#x)]\n",
523 depth, x, index.id, index.offset, index.u1, index.size, index.size)); 520 depth, x, index.id, index.offset, index.u1, index.size, index.size));
524 if (index.id & 0x02) DEBUG_INDEX(("two-bit set!!\n")); 521 // if (index.id & 0x02) DEBUG_INDEX(("two-bit set!!\n"));
525 if ((index.id >= end_val) || (index.id < old)) { 522 if ((index.id >= end_val) || (index.id < old)) {
526 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n")); 523 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n"));
527 if (buf) free(buf); 524 if (buf) free(buf);
528 DEBUG_RET(); 525 DEBUG_RET();
529 return -1; 526 return -1;
589 DEBUG_RET(); 586 DEBUG_RET();
590 return 0; 587 return 0;
591 } 588 }
592 589
593 590
594 int32_t _pst_build_desc_ptr (pst_file *pf, int32_t offset, int32_t depth, int32_t linku1, u_int32_t *high_id, int32_t start_val, int32_t end_val) { 591 /** this list node type is used for a quick cache
592 of the descriptor tree nodes (rooted at pf->d_head)
593 and for a "lost and found" list.
594 If the parent isn't found yet, put it on the lost and found
595 list and check it each time you read a new item.
596 */
597 struct cache_list_node {
598 pst_desc_ll *ptr;
599 /** only used for lost and found lists */
600 u_int32_t parent;
601 struct cache_list_node *next;
602 struct cache_list_node *prev;
603 };
604 struct cache_list_node *cache_head;
605 struct cache_list_node *cache_tail;
606 struct cache_list_node *lostfound_head;
607 int32_t cache_count;
608
609
610 /**
611 add the d_ptr descriptor into the global tree
612 */
613 void record_descriptor(pst_file *pf, pst_desc_ll *d_ptr, u_int32_t parent_id) {
614 struct cache_list_node *lostfound_ptr = NULL;
615 struct cache_list_node *cache_ptr = NULL;
616 pst_desc_ll *parent = NULL;
617
618 if (parent_id == 0 || parent_id == d_ptr->id) {
619 // add top level node to the descriptor tree
620 if (parent_id == 0) {
621 DEBUG_INDEX(("No Parent\n"));
622 } else {
623 DEBUG_INDEX(("Record is its own parent. What is this world coming to?\n"));
624 }
625 if (pf->d_tail) pf->d_tail->next = d_ptr;
626 if (!pf->d_head) pf->d_head = d_ptr;
627 d_ptr->prev = pf->d_tail;
628 pf->d_tail = d_ptr;
629 } else {
630 DEBUG_INDEX(("Searching for parent\n"));
631 // check in the cache for the parent
632 cache_ptr = cache_head;
633 while (cache_ptr && (cache_ptr->ptr->id != parent_id)) {
634 cache_ptr = cache_ptr->next;
635 }
636 if (!cache_ptr && (parent = _pst_getDptr(pf, parent_id)) == NULL) {
637 // check in the lost/found list
638 lostfound_ptr = lostfound_head;
639 while (lostfound_ptr && (lostfound_ptr->ptr->id != parent_id)) {
640 lostfound_ptr = lostfound_ptr->next;
641 }
642 if (!lostfound_ptr) {
643 DEBUG_WARN(("ERROR -- cannot find parent with id %#x. Adding to lost/found\n", parent_id));
644 lostfound_ptr = (struct cache_list_node*) xmalloc(sizeof(struct cache_list_node));
645 lostfound_ptr->prev = NULL;
646 lostfound_ptr->next = lostfound_head;
647 lostfound_ptr->parent = parent_id;
648 lostfound_ptr->ptr = d_ptr;
649 lostfound_head = lostfound_ptr;
650 } else {
651 parent = lostfound_ptr->ptr;
652 DEBUG_INDEX(("Found parent (%#x) in Lost and Found\n", parent->id));
653 }
654 }
655
656 if (cache_ptr || parent) {
657 if (cache_ptr)
658 // parent is already in the cache
659 parent = cache_ptr->ptr;
660 else {
661 //add the parent to the cache
662 DEBUG_INDEX(("Cache addition\n"));
663 cache_ptr = (struct cache_list_node*) xmalloc(sizeof(struct cache_list_node));
664 cache_ptr->prev = NULL;
665 cache_ptr->next = cache_head;
666 cache_ptr->ptr = parent;
667 cache_head = cache_ptr;
668 if (!cache_tail) cache_tail = cache_ptr;
669 cache_count++;
670 if (cache_count > 100) {
671 DEBUG_INDEX(("trimming quick cache\n"));
672 //remove one from the end
673 cache_ptr = cache_tail;
674 cache_tail = cache_ptr->prev;
675 free (cache_ptr);
676 cache_count--;
677 }
678 }
679 DEBUG_INDEX(("Found a parent\n"));
680 parent->no_child++;
681 d_ptr->parent = parent;
682 if (parent->child_tail) parent->child_tail->next = d_ptr;
683 if (!parent->child) parent->child = d_ptr;
684 d_ptr->prev = parent->child_tail;
685 parent->child_tail = d_ptr;
686 }
687 }
688 }
689
690 int32_t _pst_build_desc_ptr (pst_file *pf, int32_t offset, int32_t depth, int32_t linku1, u_int32_t *high_id, u_int32_t start_val, u_int32_t end_val) {
595 struct _pst_table_ptr_struct table, table2; 691 struct _pst_table_ptr_struct table, table2;
596 pst_desc desc_rec; 692 pst_desc desc_rec;
597 pst_desc_ll *d_ptr=NULL, *d_par=NULL; 693 pst_desc_ll *d_ptr=NULL, *parent=NULL;
598 int32_t d_ptr_count = 0;
599 int32_t x, item_count; 694 int32_t x, item_count;
600 int32_t old = start_val; 695 u_int32_t old = start_val;
601 char *buf = NULL, *bptr; 696 char *buf = NULL, *bptr;
602 697 struct cache_list_node *cache_ptr = NULL;
603 struct _pst_d_ptr_ll { 698 struct cache_list_node *lostfound_ptr = NULL;
604 pst_desc_ll * ptr; 699 struct cache_list_node *lostfound_shd = NULL;
605 int32_t parent; // used for lost and found lists 700 struct cache_list_node *lostfound_tmp = NULL;
606 struct _pst_d_ptr_ll * next; 701
607 struct _pst_d_ptr_ll * prev; 702 if (depth == 0) {
608 } *d_ptr_head=NULL, *d_ptr_tail=NULL, *d_ptr_ptr=NULL, *lf_ptr=NULL, *lf_head=NULL, *lf_shd=NULL, *lf_tmp; 703 // initialize the linked list and lost/found list.
609 // lf_ptr and lf_head are used for the lost/found list. If the parent isn't found yet, put it on this 704 cache_head = NULL;
610 // list and check it each time you read a new item 705 cache_tail = NULL;
706 lostfound_head = NULL;
707 cache_count = 0;
708 }
611 709
612 DEBUG_ENT("_pst_build_desc_ptr"); 710 DEBUG_ENT("_pst_build_desc_ptr");
613 DEBUG_INDEX(("offset %x depth %i linku1 %x start %x end %x\n", offset, depth, linku1, start_val, end_val)); 711 DEBUG_INDEX(("offset %x depth %i linku1 %x start %x end %x\n", offset, depth, linku1, start_val, end_val));
614 if (end_val <= start_val) { 712 if (end_val <= start_val) {
615 DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#x, end:%#x]\n", start_val, end_val)); 713 DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#x, end:%#x]\n", start_val, end_val));
661 DEBUG_RET(); 759 DEBUG_RET();
662 return -1; 760 return -1;
663 } 761 }
664 old = desc_rec.d_id; 762 old = desc_rec.d_id;
665 if (x == 1) { // first entry 763 if (x == 1) { // first entry
666 if (start_val != -1 && desc_rec.d_id != start_val) { 764 if (start_val && (desc_rec.d_id != start_val)) {
667 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n")); 765 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n"));
668 if (buf) free(buf); 766 if (buf) free(buf);
669 DEBUG_RET(); 767 DEBUG_RET();
670 return -1; 768 return -1;
671 } 769 }
672 } 770 }
673 // When duplicates found, just update the info.... perhaps this is correct functionality 771 // When duplicates found, just update the info.... perhaps this is correct functionality
674 DEBUG_INDEX(("Searching for existing record\n")); 772 DEBUG_INDEX(("Searching for existing record\n"));
675 if (desc_rec.d_id <= *high_id && (d_ptr = _pst_getDptr(pf, desc_rec.d_id)) != NULL) { 773 if (desc_rec.d_id <= *high_id && (d_ptr = _pst_getDptr(pf, desc_rec.d_id))) {
676 DEBUG_INDEX(("Updating Existing Values\n")); 774 DEBUG_INDEX(("Updating Existing Values\n"));
677 d_ptr->list_index = _pst_getID(pf, desc_rec.list_id); 775 d_ptr->list_index = _pst_getID(pf, desc_rec.list_id);
678 d_ptr->desc = _pst_getID(pf, desc_rec.desc_id); 776 d_ptr->desc = _pst_getID(pf, desc_rec.desc_id);
679 DEBUG_INDEX(("\tdesc = %#x\tlist_index=%#x\n", 777 DEBUG_INDEX(("\tdesc = %#x\tlist_index=%#x\n",
680 (d_ptr->desc==NULL?0:d_ptr->desc->id), 778 (d_ptr->desc==NULL?0:d_ptr->desc->id),
704 pf->d_tail = d_ptr->prev; 802 pf->d_tail = d_ptr->prev;
705 803
706 d_ptr->prev = NULL; 804 d_ptr->prev = NULL;
707 d_ptr->next = NULL; 805 d_ptr->next = NULL;
708 d_ptr->parent = NULL; 806 d_ptr->parent = NULL;
709 807 record_descriptor(pf, d_ptr, desc_rec.parent_id); // add to the global tree
710 // ok, now place in correct place
711 DEBUG_INDEX(("Searching for parent\n"));
712 if (desc_rec.parent_id == 0) {
713 DEBUG_INDEX(("No Parent\n"));
714 if (pf->d_tail) pf->d_tail->next = d_ptr;
715 if (!pf->d_head) pf->d_head = d_ptr;
716 d_ptr->prev = pf->d_tail;
717 pf->d_tail = d_ptr;
718 } else {
719 // check in the quick list
720 d_ptr_ptr = d_ptr_head;
721 while (d_ptr_ptr && (d_ptr_ptr->ptr->id != desc_rec.parent_id)) {
722 d_ptr_ptr = d_ptr_ptr->next;
723 }
724
725 if (!d_ptr_ptr && (d_par = _pst_getDptr(pf, desc_rec.parent_id)) == NULL) {
726 // check in the lost/found list
727 lf_ptr = lf_head;
728 while (lf_ptr && lf_ptr->ptr->id != desc_rec.parent_id) {
729 lf_ptr = lf_ptr->next;
730 }
731 if (!lf_ptr) {
732 DEBUG_WARN(("ERROR -- not found parent with id %#x. Adding to lost/found\n", desc_rec.parent_id));
733 lf_ptr = (struct _pst_d_ptr_ll*) xmalloc(sizeof(struct _pst_d_ptr_ll));
734 lf_ptr->prev = NULL;
735 lf_ptr->next = lf_head;
736 lf_ptr->parent = desc_rec.parent_id;
737 lf_ptr->ptr = d_ptr;
738 lf_head = lf_ptr;
739 } else {
740 d_par = lf_ptr->ptr;
741 DEBUG_INDEX(("Found parent (%#x) in Lost and Found\n", d_par->id));
742 }
743 }
744
745 if (d_ptr_ptr || d_par) {
746 if (d_ptr_ptr)
747 d_par = d_ptr_ptr->ptr;
748 else {
749 //add the d_par to the cache
750 DEBUG_INDEX(("Update - Cache addition\n"));
751 d_ptr_ptr = (struct _pst_d_ptr_ll*) xmalloc(sizeof(struct _pst_d_ptr_ll));
752 d_ptr_ptr->prev = NULL;
753 d_ptr_ptr->next = d_ptr_head;
754 d_ptr_ptr->ptr = d_par;
755 d_ptr_head = d_ptr_ptr;
756 if (!d_ptr_tail) d_ptr_tail = d_ptr_ptr;
757 d_ptr_count++;
758 if (d_ptr_count > 100) {
759 //remove on from the end
760 d_ptr_ptr = d_ptr_tail;
761 d_ptr_tail = d_ptr_ptr->prev;
762 free (d_ptr_ptr);
763 d_ptr_count--;
764 }
765 }
766 DEBUG_INDEX(("Found a parent\n"));
767 d_par->no_child++;
768 d_ptr->parent = d_par;
769 if (d_par->child_tail) d_par->child_tail->next = d_ptr;
770 if (!d_par->child) d_par->child = d_ptr;
771 d_ptr->prev = d_par->child_tail;
772 d_par->child_tail = d_ptr;
773 }
774 }
775 } 808 }
776 } else { 809 } else {
777 if (*high_id < desc_rec.d_id) { 810 if (*high_id < desc_rec.d_id) {
778 DEBUG_INDEX(("Updating New High\n")); 811 DEBUG_INDEX(("Updating New High\n"));
779 *high_id = desc_rec.d_id; 812 *high_id = desc_rec.d_id;
787 d_ptr->next = NULL; 820 d_ptr->next = NULL;
788 d_ptr->parent = NULL; 821 d_ptr->parent = NULL;
789 d_ptr->child = NULL; 822 d_ptr->child = NULL;
790 d_ptr->child_tail = NULL; 823 d_ptr->child_tail = NULL;
791 d_ptr->no_child = 0; 824 d_ptr->no_child = 0;
792 825 record_descriptor(pf, d_ptr, desc_rec.parent_id); // add to the global tree
793 DEBUG_INDEX(("Searching for parent\n")); 826
794 if (desc_rec.parent_id == 0 || desc_rec.parent_id == desc_rec.d_id) {
795 if (desc_rec.parent_id == 0) {
796 DEBUG_INDEX(("No Parent\n"));
797 } else {
798 DEBUG_INDEX(("Record is its own parent. What is this world coming to?\n"));
799 }
800 if (pf->d_tail) pf->d_tail->next = d_ptr;
801 if (!pf->d_head) pf->d_head = d_ptr;
802 d_ptr->prev = pf->d_tail;
803 pf->d_tail = d_ptr;
804 } else {
805 d_ptr_ptr = d_ptr_head;
806 while (d_ptr_ptr && (d_ptr_ptr->ptr->id != desc_rec.parent_id)) {
807 d_ptr_ptr = d_ptr_ptr->next;
808 }
809 if (!d_ptr_ptr && (d_par = _pst_getDptr(pf, desc_rec.parent_id)) == NULL) {
810 // check in the lost/found list
811 lf_ptr = lf_head;
812 while (lf_ptr && (lf_ptr->ptr->id != desc_rec.parent_id)) {
813 lf_ptr = lf_ptr->next;
814 }
815 if (!lf_ptr) {
816 DEBUG_WARN(("ERROR -- not found parent with id %#x. Adding to lost/found\n", desc_rec.parent_id));
817 lf_ptr = (struct _pst_d_ptr_ll*) xmalloc(sizeof(struct _pst_d_ptr_ll));
818 lf_ptr->prev = NULL;
819 lf_ptr->next = lf_head;
820 lf_ptr->parent = desc_rec.parent_id;
821 lf_ptr->ptr = d_ptr;
822 lf_head = lf_ptr;
823 } else {
824 d_par = lf_ptr->ptr;
825 DEBUG_INDEX(("Found parent (%#x) in Lost and Found\n", d_par->id));
826 }
827 }
828
829 if (d_ptr_ptr || d_par) {
830 if (d_ptr_ptr)
831 d_par = d_ptr_ptr->ptr;
832 else {
833 //add the d_par to the cache
834 DEBUG_INDEX(("Normal - Cache addition\n"));
835 d_ptr_ptr = (struct _pst_d_ptr_ll*) xmalloc(sizeof(struct _pst_d_ptr_ll));
836 d_ptr_ptr->prev = NULL;
837 d_ptr_ptr->next = d_ptr_head;
838 d_ptr_ptr->ptr = d_par;
839 d_ptr_head = d_ptr_ptr;
840 if (!d_ptr_tail) d_ptr_tail = d_ptr_ptr;
841 d_ptr_count++;
842 if (d_ptr_count > 100) {
843 //remove one from the end
844 d_ptr_ptr = d_ptr_tail;
845 d_ptr_tail = d_ptr_ptr->prev;
846 free (d_ptr_ptr);
847 d_ptr_count--;
848 }
849 }
850
851 DEBUG_INDEX(("Found a parent\n"));
852 d_par->no_child++;
853 d_ptr->parent = d_par;
854 if (d_par->child_tail) d_par->child_tail->next = d_ptr;
855 if (!d_par->child) d_par->child = d_ptr;
856 d_ptr->prev = d_par->child_tail;
857 d_par->child_tail = d_ptr;
858 }
859 }
860 } 827 }
861 // check here to see if d_ptr is the parent of any of the items in the lost / found list 828 // check here to see if d_ptr is the parent of any of the items in the lost / found list
862 lf_ptr = lf_head; 829 lostfound_ptr = lostfound_head;
863 lf_shd = NULL; 830 lostfound_shd = NULL;
864 while (lf_ptr) { 831 while (lostfound_ptr) {
865 if (lf_ptr->parent == d_ptr->id) { 832 if (lostfound_ptr->parent == d_ptr->id) {
866 DEBUG_INDEX(("Found a child (%#x) of the current record. Joining to main structure.\n", lf_ptr->ptr->id)); 833 DEBUG_INDEX(("Found a child (%#x) of the current record. Joining to main structure.\n", lostfound_ptr->ptr->id));
867 d_par = d_ptr; 834 parent = d_ptr;
868 d_ptr = lf_ptr->ptr; 835 d_ptr = lostfound_ptr->ptr;
869 d_par->no_child++; 836 parent->no_child++;
870 d_ptr->parent = d_par; 837 d_ptr->parent = parent;
871 if (d_par->child_tail) d_par->child_tail->next = d_ptr; 838 if (parent->child_tail) parent->child_tail->next = d_ptr;
872 if (!d_par->child) d_par->child = d_ptr; 839 if (!parent->child) parent->child = d_ptr;
873 d_ptr->prev = d_par->child_tail; 840 d_ptr->prev = parent->child_tail;
874 d_par->child_tail = d_ptr; 841 parent->child_tail = d_ptr;
875 if (!lf_shd) 842 if (!lostfound_shd) lostfound_head = lostfound_ptr->next;
876 lf_head = lf_ptr->next; 843 else lostfound_shd->next = lostfound_ptr->next;
877 else 844 lostfound_tmp = lostfound_ptr->next;
878 lf_shd->next = lf_ptr->next; 845 free(lostfound_ptr);
879 lf_tmp = lf_ptr->next; 846 lostfound_ptr = lostfound_tmp;
880 free(lf_ptr);
881 lf_ptr = lf_tmp;
882 } else { 847 } else {
883 lf_shd = lf_ptr; 848 lostfound_shd = lostfound_ptr;
884 lf_ptr = lf_ptr->next; 849 lostfound_ptr = lostfound_ptr->next;
885 } 850 }
886 } 851 }
887 } 852 }
888 } else { 853 } else {
889 // this node contains node pointers 854 // this node contains node pointers
928 } 893 }
929 } 894 }
930 _pst_build_desc_ptr(pf, table.offset, depth+1, table.u1, high_id, table.start, table2.start); 895 _pst_build_desc_ptr(pf, table.offset, depth+1, table.u1, high_id, table.start, table2.start);
931 } 896 }
932 } 897 }
933 // ok, lets try freeing the d_ptr_head cache here 898 if (depth == 0) {
934 while (d_ptr_head) { 899 // free the quick cache
935 d_ptr_ptr = d_ptr_head->next; 900 while (cache_head) {
936 free(d_ptr_head); 901 cache_ptr = cache_head->next;
937 d_ptr_head = d_ptr_ptr; 902 free(cache_head);
938 } 903 cache_head = cache_ptr;
939 // TODO - need to free lost and found list also!! 904 }
940 // TODO - and show error for any remaining lf items 905 // free the lost and found
906 while (lostfound_head) {
907 lostfound_ptr = lostfound_head->next;
908 WARN(("unused lost/found item with parent %d))", lostfound_head->parent));
909 free(lostfound_head);
910 lostfound_head = lostfound_ptr;
911 }
912 }
941 if (buf) free(buf); 913 if (buf) free(buf);
942 DEBUG_RET(); 914 DEBUG_RET();
943 return 0; 915 return 0;
944 } 916 }
945 917
1074 DEBUG_RET(); 1046 DEBUG_RET();
1075 return item; 1047 return item;
1076 } 1048 }
1077 1049
1078 1050
1051 void freeall(unsigned char *buf, pst_block_offset_pointer *p1,
1052 pst_block_offset_pointer *p2,
1053 pst_block_offset_pointer *p3,
1054 pst_block_offset_pointer *p4,
1055 pst_block_offset_pointer *p5,
1056 pst_block_offset_pointer *p6,
1057 pst_block_offset_pointer *p7) {
1058 if (buf) free(buf);
1059 if (p1->needfree) free(p1->from);
1060 if (p2->needfree) free(p2->from);
1061 if (p3->needfree) free(p3->from);
1062 if (p4->needfree) free(p4->from);
1063 if (p5->needfree) free(p5->from);
1064 if (p6->needfree) free(p6->from);
1065 if (p7->needfree) free(p7->from);
1066 }
1067
1068
1079 pst_num_array * _pst_parse_block(pst_file *pf, u_int32_t block_id, pst_index2_ll *i2_head) { 1069 pst_num_array * _pst_parse_block(pst_file *pf, u_int32_t block_id, pst_index2_ll *i2_head) {
1080 unsigned char *buf = NULL; 1070 unsigned char *buf = NULL;
1081 pst_num_array *na_ptr = NULL, *na_head = NULL; 1071 pst_num_array *na_ptr = NULL, *na_head = NULL;
1082 pst_block_offset block_offset; 1072 pst_block_offset_pointer block_offset1;
1083 // pst_index_ll *rec = NULL; 1073 pst_block_offset_pointer block_offset2;
1084 u_int32_t size = 0, t_ptr = 0, fr_ptr = 0, to_ptr = 0, ind_ptr = 0, x = 0; 1074 pst_block_offset_pointer block_offset3;
1085 u_int32_t num_recs = 0, count_rec = 0, ind2_ptr = 0, ind2_end = 0, list_start = 0, num_list = 0, cur_list = 0; 1075 pst_block_offset_pointer block_offset4;
1086 int32_t block_type, rec_size; 1076 pst_block_offset_pointer block_offset5;
1077 pst_block_offset_pointer block_offset6;
1078 pst_block_offset_pointer block_offset7;
1079 u_int32_t size;
1080 u_int32_t x;
1081 u_int32_t num_recs;
1082 u_int32_t count_rec;
1083 u_int32_t num_list;
1084 u_int32_t cur_list;
1085 u_int32_t block_type;
1086 u_int32_t rec_size;
1087 u_int32_t ind_ptr;
1088 unsigned char* list_start;
1089 unsigned char* t_ptr;
1090 unsigned char* fr_ptr;
1091 unsigned char* to_ptr;
1092 unsigned char* ind2_end;
1093 unsigned char* ind2_ptr;
1087 size_t read_size=0; 1094 size_t read_size=0;
1088 pst_x_attrib_ll *mapptr; 1095 pst_x_attrib_ll *mapptr;
1089 1096
1090 struct { 1097 struct {
1091 u_int16_t type; 1098 u_int16_t type;
1092 u_int16_t ref_type; 1099 u_int16_t ref_type;
1093 u_int32_t value; 1100 u_int32_t value;
1094 } table_rec; //for type 1 ("BC") blocks 1101 } table_rec; //for type 1 (0xBCEC) blocks
1095 struct { 1102 struct {
1096 u_int16_t ref_type; 1103 u_int16_t ref_type;
1097 u_int16_t type; 1104 u_int16_t type;
1098 u_int16_t ind2_off; 1105 u_int16_t ind2_off;
1099 u_int16_t u1; 1106 u_int8_t size;
1100 } table2_rec; //for type 2 ("7C") blocks 1107 u_int8_t slot;
1108 } table2_rec; //for type 2 (0x7CEC) blocks
1109 struct {
1110 u_int32_t id;
1111 } table3_rec; //for type 3 (0x0101) blocks
1101 struct { 1112 struct {
1102 u_int16_t index_offset; 1113 u_int16_t index_offset;
1103 u_int16_t type; 1114 u_int16_t type;
1104 u_int16_t offset; 1115 u_int32_t offset;
1105 } block_hdr; 1116 } block_hdr;
1106 struct { 1117 struct {
1107 unsigned char seven_c; 1118 unsigned char seven_c;
1108 unsigned char item_count; 1119 unsigned char item_count;
1109 u_int16_t u1; 1120 u_int16_t u1;
1110 u_int16_t u2; 1121 u_int16_t u2;
1111 u_int16_t u3; 1122 u_int16_t u3;
1112 u_int16_t rec_size; 1123 u_int16_t rec_size;
1113 u_int16_t b_five_offset; 1124 u_int32_t b_five_offset;
1114 u_int16_t u5; 1125 u_int32_t ind2_offset;
1115 u_int16_t ind2_offset;
1116 u_int16_t u6;
1117 u_int16_t u7; 1126 u_int16_t u7;
1118 u_int16_t u8; 1127 u_int16_t u8;
1119 } seven_c_blk; 1128 } seven_c_blk;
1120 struct _type_d_rec { 1129 struct _type_d_rec {
1121 u_int32_t id; 1130 u_int32_t id;
1128 if (buf) free (buf); 1137 if (buf) free (buf);
1129 DEBUG_RET(); 1138 DEBUG_RET();
1130 return NULL; 1139 return NULL;
1131 } 1140 }
1132 1141
1142 block_offset1.needfree = 0;
1143 block_offset2.needfree = 0;
1144 block_offset3.needfree = 0;
1145 block_offset4.needfree = 0;
1146 block_offset5.needfree = 0;
1147 block_offset6.needfree = 0;
1148 block_offset7.needfree = 0;
1149
1133 memcpy(&block_hdr, buf, sizeof(block_hdr)); 1150 memcpy(&block_hdr, buf, sizeof(block_hdr));
1134 LE16_CPU(block_hdr.index_offset); 1151 LE16_CPU(block_hdr.index_offset);
1135 LE16_CPU(block_hdr.type); 1152 LE16_CPU(block_hdr.type);
1136 LE16_CPU(block_hdr.offset); 1153 LE32_CPU(block_hdr.offset);
1137 DEBUG_EMAIL(("block header (index_offset=%#hx, type=%#hx, offset=%#hx\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset)); 1154 DEBUG_EMAIL(("block header (index_offset=%#hx, type=%#hx, offset=%#hx\n", block_hdr.index_offset, block_hdr.type, block_hdr.offset));
1138 1155
1139 ind_ptr = block_hdr.index_offset; 1156 ind_ptr = block_hdr.index_offset;
1140 1157
1141 if (block_hdr.type == 0xBCEC) { //type 1 1158 if (block_hdr.type == 0xBCEC) { //type 1
1142 block_type = 1; 1159 block_type = 1;
1143 1160
1144 _pst_getBlockOffset(buf, read_size, ind_ptr, block_hdr.offset, &block_offset); 1161 if (_pst_getBlockOffsetPointer(pf, i2_head, buf, read_size, ind_ptr, block_hdr.offset, &block_offset1)) {
1145 fr_ptr = block_offset.from; 1162 DEBUG_WARN(("internal error (bc.b5 offset %#x) in reading block id %#x\n", block_hdr.offset, block_id));
1146 1163 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1147 memcpy(&table_rec, &(buf[fr_ptr]), sizeof(table_rec)); 1164 DEBUG_RET();
1165 return NULL;
1166 }
1167 memcpy(&table_rec, block_offset1.from, sizeof(table_rec));
1148 LE16_CPU(table_rec.type); 1168 LE16_CPU(table_rec.type);
1149 LE16_CPU(table_rec.ref_type); 1169 LE16_CPU(table_rec.ref_type);
1150 LE32_CPU(table_rec.value); 1170 LE32_CPU(table_rec.value);
1151 DEBUG_EMAIL(("table_rec (type=%#hx, ref_type=%#hx, value=%#x\n", table_rec.type, table_rec.ref_type, table_rec.value)); 1171 DEBUG_EMAIL(("table_rec (type=%#hx, ref_type=%#hx, value=%#x)\n", table_rec.type, table_rec.ref_type, table_rec.value));
1152 1172
1153 if (table_rec.type != 0x02B5) { 1173 if (table_rec.type != 0x02B5) {
1154 WARN(("Unknown second block constant - %#X for id %#x\n", table_rec.type, block_id)); 1174 WARN(("Unknown second block constant - %#X for id %#x\n", table_rec.type, block_id));
1155 DEBUG_HEXDUMPC(buf, sizeof(table_rec), 0x10); 1175 DEBUG_HEXDUMPC(buf, sizeof(table_rec), 0x10);
1156 if (buf) free (buf); 1176 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1157 DEBUG_RET(); 1177 DEBUG_RET();
1158 return NULL; 1178 return NULL;
1159 } 1179 }
1160 1180
1161 _pst_getBlockOffset(buf, read_size, ind_ptr, table_rec.value, &block_offset); 1181 if (_pst_getBlockOffsetPointer(pf, i2_head, buf, read_size, ind_ptr, table_rec.value, &block_offset2)) {
1162 list_start = block_offset.from; 1182 DEBUG_WARN(("internal error (bc.b5.desc offset) in reading block id %#x\n", table_rec.value, block_id));
1163 to_ptr = block_offset.to; 1183 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1184 DEBUG_RET();
1185 return NULL;
1186 }
1187 list_start = block_offset2.from;
1188 to_ptr = block_offset2.to;
1164 num_list = (to_ptr - list_start)/sizeof(table_rec); 1189 num_list = (to_ptr - list_start)/sizeof(table_rec);
1165 num_recs = 1; // only going to be one object in these blocks 1190 num_recs = 1; // only going to be one object in these blocks
1166 rec_size = 0; // doesn't matter cause there is only one object 1191 rec_size = 0; // doesn't matter cause there is only one object
1167 } 1192 }
1168 else if (block_hdr.type == 0x7CEC) { //type 2 1193 else if (block_hdr.type == 0x7CEC) { //type 2
1169 block_type = 2; 1194 block_type = 2;
1170 1195
1171 _pst_getBlockOffset(buf, read_size, ind_ptr, block_hdr.offset, &block_offset); 1196 if (_pst_getBlockOffsetPointer(pf, i2_head, buf, read_size, ind_ptr, block_hdr.offset, &block_offset3)) {
1172 fr_ptr = block_offset.from; //now got pointer to "7C block" 1197 DEBUG_WARN(("internal error (7c.7c offset %#x) in reading block id %#x\n", block_hdr.offset, block_id));
1198 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1199 DEBUG_RET();
1200 return NULL;
1201 }
1202 fr_ptr = block_offset3.from; //now got pointer to "7C block"
1173 memset(&seven_c_blk, 0, sizeof(seven_c_blk)); 1203 memset(&seven_c_blk, 0, sizeof(seven_c_blk));
1174 memcpy(&seven_c_blk, &(buf[fr_ptr]), sizeof(seven_c_blk)); 1204 memcpy(&seven_c_blk, fr_ptr, sizeof(seven_c_blk));
1175 LE16_CPU(seven_c_blk.u1); 1205 LE16_CPU(seven_c_blk.u1);
1176 LE16_CPU(seven_c_blk.u2); 1206 LE16_CPU(seven_c_blk.u2);
1177 LE16_CPU(seven_c_blk.u3); 1207 LE16_CPU(seven_c_blk.u3);
1178 LE16_CPU(seven_c_blk.rec_size); 1208 LE16_CPU(seven_c_blk.rec_size);
1179 LE16_CPU(seven_c_blk.b_five_offset); 1209 LE32_CPU(seven_c_blk.b_five_offset);
1180 LE16_CPU(seven_c_blk.u5); 1210 LE32_CPU(seven_c_blk.ind2_offset);
1181 LE16_CPU(seven_c_blk.ind2_offset);
1182 LE16_CPU(seven_c_blk.u6);
1183 LE16_CPU(seven_c_blk.u7); 1211 LE16_CPU(seven_c_blk.u7);
1184 LE16_CPU(seven_c_blk.u8); 1212 LE16_CPU(seven_c_blk.u8);
1185 1213
1186 list_start = fr_ptr + sizeof(seven_c_blk); // the list of item numbers start after this record 1214 list_start = fr_ptr + sizeof(seven_c_blk); // the list of item numbers start after this record
1187 1215
1188 if (seven_c_blk.seven_c != 0x7C) { // this would mean it isn't a 7C block! 1216 if (seven_c_blk.seven_c != 0x7C) { // this would mean it isn't a 7C block!
1189 WARN(("Error. There isn't a 7C where I want to see 7C!\n")); 1217 WARN(("Error. There isn't a 7C where I want to see 7C!\n"));
1190 if (buf) free(buf); 1218 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1191 DEBUG_RET(); 1219 DEBUG_RET();
1192 return NULL; 1220 return NULL;
1193 } 1221 }
1194 1222
1195 rec_size = seven_c_blk.rec_size; 1223 rec_size = seven_c_blk.rec_size;
1196 num_list = seven_c_blk.item_count; 1224 num_list = seven_c_blk.item_count;
1197 DEBUG_EMAIL(("b5 offset = %#x\n", seven_c_blk.b_five_offset)); 1225
1198 1226 if (_pst_getBlockOffsetPointer(pf, i2_head, buf, read_size, ind_ptr, seven_c_blk.b_five_offset, &block_offset4)) {
1199 _pst_getBlockOffset(buf, read_size, ind_ptr, seven_c_blk.b_five_offset, &block_offset); 1227 DEBUG_WARN(("internal error (7c.b5 offset %#x) in reading block id %#x\n", seven_c_blk.b_five_offset, block_id));
1200 fr_ptr = block_offset.from; 1228 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1201 memcpy(&table_rec, &(buf[fr_ptr]), sizeof(table_rec)); 1229 DEBUG_RET();
1230 return NULL;
1231 }
1232 memcpy(&table_rec, block_offset4.from, sizeof(table_rec));
1202 LE16_CPU(table_rec.type); 1233 LE16_CPU(table_rec.type);
1203 LE16_CPU(table_rec.ref_type); 1234 LE16_CPU(table_rec.ref_type);
1204 LE32_CPU(table_rec.value); 1235 LE32_CPU(table_rec.value);
1205 DEBUG_EMAIL(("after convert %#x\n", table_rec.type));
1206 1236
1207 if (table_rec.type != 0x04B5) { // different constant than a type 1 record 1237 if (table_rec.type != 0x04B5) { // different constant than a type 1 record
1208 WARN(("Unknown second block constant - %#X for id %#x\n", table_rec.type, block_id)); 1238 WARN(("Unknown second block constant - %#X for id %#x\n", table_rec.type, block_id));
1209 if (buf) free(buf); 1239 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1210 DEBUG_RET(); 1240 DEBUG_RET();
1211 return NULL; 1241 return NULL;
1212 } 1242 }
1213 1243
1214 if (table_rec.value == 0) { // this is for the 2nd index offset 1244 if (_pst_getBlockOffsetPointer(pf, i2_head, buf, read_size, ind_ptr, table_rec.value, &block_offset5)) {
1215 DEBUG_INFO(("reference to second index block is zero. ERROR\n")); 1245 DEBUG_WARN(("internal error (7c.5b.desc offset %#x) in reading block id %#x\n", table_rec.value, block_id));
1216 if (buf) free(buf); 1246 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1217 DEBUG_RET(); 1247 DEBUG_RET();
1218 return NULL; 1248 return NULL;
1219 } 1249 }
1220 1250 num_recs = (block_offset5.to - block_offset5.from) / 6; // this will give the number of records in this block
1221 _pst_getBlockOffset(buf, read_size, ind_ptr, table_rec.value, &block_offset); 1251
1222 num_recs = (block_offset.to - block_offset.from) / 6; // this will give the number of records in this block 1252 if (_pst_getBlockOffsetPointer(pf, i2_head, buf, read_size, ind_ptr, seven_c_blk.ind2_offset, &block_offset6)) {
1223 1253 DEBUG_WARN(("internal error (7c.ind2 offset %#x) in reading block id %#x\n", seven_c_blk.ind2_offset, block_id));
1224 _pst_getBlockOffset(buf, read_size, ind_ptr, seven_c_blk.ind2_offset, &block_offset); 1254 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1225 ind2_ptr = block_offset.from; 1255 DEBUG_RET();
1226 ind2_end = block_offset.to; 1256 return NULL;
1257 }
1258 ind2_ptr = block_offset6.from;
1259 ind2_end = block_offset6.to;
1260 }
1261 else if (block_hdr.index_offset == 0x0101) { //type 2
1262 unsigned char *buf2 = NULL;
1263 int n = block_hdr.type; // count
1264 int m = sizeof(table3_rec);
1265 int i;
1266 block_type = 3;
1267 for (i=0; i<n; i++) {
1268 memcpy(&table3_rec, buf+8+i*m, m);
1269 LE32_CPU(table3_rec.id);
1270 _pst_ff_getIDblock_dec(pf, table3_rec.id, &buf2);
1271 if (buf2) free(buf2);
1272 buf2 = NULL;
1273 }
1274 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1275 DEBUG_RET();
1276 return NULL;
1227 } else { 1277 } else {
1228 WARN(("ERROR: Unknown block constant - %#X for id %#x\n", block_hdr.type, block_id)); 1278 WARN(("ERROR: Unknown block constant - %#X for id %#x\n", block_hdr.type, block_id));
1229 DEBUG_HEXDUMPC(buf, read_size,0x10); 1279 DEBUG_HEXDUMPC(buf, read_size,0x10);
1230 if (buf) free(buf); 1280 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1231 DEBUG_RET(); 1281 DEBUG_RET();
1232 return NULL; 1282 return NULL;
1233 } 1283 }
1234 1284
1235 DEBUG_EMAIL(("Mallocing number of items %i\n", num_recs)); 1285 DEBUG_EMAIL(("Mallocing number of records %i\n", num_recs));
1236 while (count_rec < num_recs) { 1286 for (count_rec=0; count_rec<num_recs; count_rec++) {
1237 na_ptr = (pst_num_array*) xmalloc(sizeof(pst_num_array)); 1287 na_ptr = (pst_num_array*) xmalloc(sizeof(pst_num_array));
1238 memset(na_ptr, 0, sizeof(pst_num_array)); 1288 memset(na_ptr, 0, sizeof(pst_num_array));
1239 na_ptr->next = na_head; 1289 na_ptr->next = na_head;
1240 na_head = na_ptr; 1290 na_head = na_ptr;
1241 // allocate an array of count num_recs to contain sizeof(struct_pst_num_item) 1291 // allocate an array of count num_recs to contain sizeof(struct_pst_num_item)
1244 na_ptr->count_array = num_recs; // each record will have a record of the total number of records 1294 na_ptr->count_array = num_recs; // each record will have a record of the total number of records
1245 x = 0; 1295 x = 0;
1246 1296
1247 DEBUG_EMAIL(("going to read %i (%#x) items\n", na_ptr->count_item, na_ptr->count_item)); 1297 DEBUG_EMAIL(("going to read %i (%#x) items\n", na_ptr->count_item, na_ptr->count_item));
1248 1298
1249 fr_ptr = list_start; // init fr_ptr to the start of the list. 1299 fr_ptr = list_start; // initialize fr_ptr to the start of the list.
1250 cur_list = 0; 1300 for (cur_list=0; cur_list<num_list; cur_list++) { //we will increase fr_ptr as we progress through index
1251 while (cur_list < num_list) { //we will increase fr_ptr as we progress through index 1301 unsigned char* value_pointer = NULL; // needed for block type 2 with values larger than 4 bytes
1302 int value_size = 0;
1252 if (block_type == 1) { 1303 if (block_type == 1) {
1253 memcpy(&table_rec, &(buf[fr_ptr]), sizeof(table_rec)); 1304 memcpy(&table_rec, fr_ptr, sizeof(table_rec));
1254 LE16_CPU(table_rec.type); 1305 LE16_CPU(table_rec.type);
1255 LE16_CPU(table_rec.ref_type); 1306 LE16_CPU(table_rec.ref_type);
1256 //LE32_CPU(table_rec.value); // done later, some may be order invariant 1307 //LE32_CPU(table_rec.value); // done later, some may be order invariant
1257 fr_ptr += sizeof(table_rec); 1308 fr_ptr += sizeof(table_rec);
1258 } else if (block_type == 2) { 1309 } else if (block_type == 2) {
1259 // we will copy the table2_rec values into a table_rec record so that we can keep the rest of the code 1310 // we will copy the table2_rec values into a table_rec record so that we can keep the rest of the code
1260 memcpy(&table2_rec, &(buf[fr_ptr]), sizeof(table2_rec)); 1311 memcpy(&table2_rec, fr_ptr, sizeof(table2_rec));
1261 LE16_CPU(table2_rec.ref_type); 1312 LE16_CPU(table2_rec.ref_type);
1262 LE16_CPU(table2_rec.type); 1313 LE16_CPU(table2_rec.type);
1263 LE16_CPU(table2_rec.ind2_off); 1314 LE16_CPU(table2_rec.ind2_off);
1264 LE16_CPU(table2_rec.u1);
1265 1315
1266 // table_rec and table2_rec are arranged differently, so assign the values across 1316 // table_rec and table2_rec are arranged differently, so assign the values across
1267 table_rec.type = table2_rec.type; 1317 table_rec.type = table2_rec.type;
1268 table_rec.ref_type = table2_rec.ref_type; 1318 table_rec.ref_type = table2_rec.ref_type;
1269 if (ind2_ptr+table2_rec.ind2_off <= ind2_end) { 1319 if ((ind2_end - ind2_ptr) <= (table2_rec.ind2_off + table2_rec.size)) {
1270 memcpy(&(table_rec.value), &(buf[ind2_ptr+table2_rec.ind2_off]), sizeof(table_rec.value)); 1320 int n = table2_rec.size;
1321 int m = sizeof(table_rec.value);
1322 table_rec.value = 0;
1323 if (n <= m) {
1324 memcpy(&table_rec.value, ind2_ptr + table2_rec.ind2_off, n);
1325 }
1326 else {
1327 value_pointer = ind2_ptr + table2_rec.ind2_off;
1328 value_size = n;
1329 }
1271 //LE32_CPU(table_rec.value); // done later, some may be order invariant 1330 //LE32_CPU(table_rec.value); // done later, some may be order invariant
1272 } 1331 }
1273 else { 1332 else {
1274 DEBUG_WARN (("trying to read more than blocks size. Size=%#x, Req.=%#x," 1333 DEBUG_WARN (("Trying to read outside buffer, buffer size %#x, offset %#x, data size %#x\n",
1275 " Req Size=%#x\n", read_size, ind2_ptr+table2_rec.ind2_off, 1334 read_size, ind2_end-ind2_ptr+table2_rec.ind2_off, table2_rec.size));
1276 sizeof(table_rec.value)));
1277 } 1335 }
1278
1279 fr_ptr += sizeof(table2_rec); 1336 fr_ptr += sizeof(table2_rec);
1280 } else { 1337 } else {
1281 WARN(("Missing code for block_type %i\n", block_type)); 1338 WARN(("Missing code for block_type %i\n", block_type));
1282 if (buf) free(buf); 1339 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1283 if (na_head) _pst_free_list(na_head); 1340 if (na_head) _pst_free_list(na_head);
1284 DEBUG_RET(); 1341 DEBUG_RET();
1285 return NULL; 1342 return NULL;
1286 } 1343 }
1287 cur_list++; // get ready to read next bit from list
1288 DEBUG_EMAIL(("reading block %i (type=%#x, ref_type=%#x, value=%#x)\n", 1344 DEBUG_EMAIL(("reading block %i (type=%#x, ref_type=%#x, value=%#x)\n",
1289 x, table_rec.type, table_rec.ref_type, table_rec.value)); 1345 x, table_rec.type, table_rec.ref_type, table_rec.value));
1290 1346
1291 na_ptr->items[x] = (struct _pst_num_item*) xmalloc(sizeof(struct _pst_num_item)); 1347 na_ptr->items[x] = (struct _pst_num_item*) xmalloc(sizeof(struct _pst_num_item));
1292 memset(na_ptr->items[x], 0, sizeof(struct _pst_num_item)); //init it 1348 memset(na_ptr->items[x], 0, sizeof(struct _pst_num_item)); //init it
1327 0x1014 - Array of 64bit values 1383 0x1014 - Array of 64bit values
1328 0x101E - Array of Strings 1384 0x101E - Array of Strings
1329 0x1102 - Array of Binary data 1385 0x1102 - Array of Binary data
1330 */ 1386 */
1331 1387
1332 if (table_rec.ref_type == 0x0002 || table_rec.ref_type == 0x0003 || table_rec.ref_type == 0x000b) { 1388 if (table_rec.ref_type == 0x0002 ||
1333 //contains data 1389 table_rec.ref_type == 0x0003 ||
1390 table_rec.ref_type == 0x000b) {
1391 //contains 32 bits of data
1392 na_ptr->items[x]->size = sizeof(int32_t);
1393 na_ptr->items[x]->type = table_rec.ref_type;
1334 na_ptr->items[x]->data = xmalloc(sizeof(int32_t)); 1394 na_ptr->items[x]->data = xmalloc(sizeof(int32_t));
1335 memcpy(na_ptr->items[x]->data, &(table_rec.value), sizeof(int32_t)); 1395 memcpy(na_ptr->items[x]->data, &(table_rec.value), sizeof(int32_t));
1336 na_ptr->items[x]->size = sizeof(int32_t); 1396
1337 na_ptr->items[x]->type = table_rec.ref_type; 1397 } else if (table_rec.ref_type == 0x0005 ||
1338 1398 table_rec.ref_type == 0x000d ||
1339 } else if (table_rec.ref_type == 0x0005 || table_rec.ref_type == 0x000D 1399 table_rec.ref_type == 0x0014 ||
1340 || table_rec.ref_type == 0x1003 || table_rec.ref_type == 0x0014 1400 table_rec.ref_type == 0x001e ||
1341 || table_rec.ref_type == 0x001E || table_rec.ref_type == 0x0102 1401 table_rec.ref_type == 0x0040 ||
1342 || table_rec.ref_type == 0x0040 || table_rec.ref_type == 0x101E 1402 table_rec.ref_type == 0x0048 ||
1343 || table_rec.ref_type == 0x0048 || table_rec.ref_type == 0x1102 1403 table_rec.ref_type == 0x0102 ||
1344 || table_rec.ref_type == 0x1014) { 1404 table_rec.ref_type == 0x1003 ||
1345 //contains index_ref to data 1405 table_rec.ref_type == 0x1014 ||
1406 table_rec.ref_type == 0x101e ||
1407 table_rec.ref_type == 0x1102) {
1408 //contains index reference to data
1346 LE32_CPU(table_rec.value); 1409 LE32_CPU(table_rec.value);
1347 if ((table_rec.value & 0x0000000F) == 0xF) { 1410 if (value_pointer) {
1348 // if value ends in 'F' then this should be an id2 value 1411 // in a type 2 block, with a value that is more than 4 bytes
1349 DEBUG_EMAIL(("Found id2 [%#x] value. Will follow it\n", table_rec.value)); 1412 // directly stored in this block.
1350 if ((na_ptr->items[x]->size = _pst_ff_getID2block(pf, table_rec.value, i2_head, 1413 na_ptr->items[x]->size = value_size;
1351 &(na_ptr->items[x]->data)))==0) { 1414 na_ptr->items[x]->type = table_rec.ref_type;
1352 DEBUG_WARN(("not able to read the ID2 data. Setting to be read later. %#x\n", table_rec.value)); 1415 na_ptr->items[x]->data = xmalloc(value_size);
1416 memcpy(na_ptr->items[x]->data, value_pointer, value_size);
1417 }
1418 else if (_pst_getBlockOffsetPointer(pf, i2_head, buf, read_size, ind_ptr, table_rec.value, &block_offset7)) {
1419 if (table_rec.value) {
1420 DEBUG_WARN(("failed to get block offset for table_rec.value of %#x\n", table_rec.value));
1421 }
1422 na_ptr->count_item --; //we will be skipping a row
1423 continue;
1424 }
1425 else {
1426 value_size = block_offset7.to - block_offset7.from;
1427 na_ptr->items[x]->size = value_size;
1428 na_ptr->items[x]->type = table_rec.ref_type;
1429 na_ptr->items[x]->data = xmalloc(value_size+1);
1430 memcpy(na_ptr->items[x]->data, block_offset7.from, value_size);
1431 na_ptr->items[x]->data[value_size] = '\0'; // it might be a string, null terminate it.
1432 }
1433 if (table_rec.ref_type == 0xd) {
1434 // there is still more to do for the type of 0xD
1435 type_d_rec = (struct _type_d_rec*) na_ptr->items[x]->data;
1436 LE32_CPU(type_d_rec->id);
1437 if ((na_ptr->items[x]->size = _pst_ff_getID2block(pf, type_d_rec->id, i2_head, &(na_ptr->items[x]->data)))==0){
1438 DEBUG_WARN(("not able to read the ID2 data. Setting to be read later. %#x\n",
1439 type_d_rec->id));
1440 free(na_ptr->items[x]->data);
1353 na_ptr->items[x]->size = 0; 1441 na_ptr->items[x]->size = 0;
1354 na_ptr->items[x]->data = NULL; 1442 na_ptr->items[x]->data = NULL;
1355 na_ptr->items[x]->type = table_rec.value; 1443 na_ptr->items[x]->type = type_d_rec->id;
1356 } 1444 }
1357 } else if (table_rec.value != 0) {
1358 if ((table_rec.value >> 4)+ind_ptr > read_size) {
1359 // check that we will not be outside the buffer we have read
1360 DEBUG_WARN(("table_rec.value [%#x] is outside of block [%#x]\n", table_rec.value, read_size));
1361 na_ptr->count_item --;
1362 continue;
1363 }
1364 if (_pst_getBlockOffset(buf, read_size, ind_ptr, table_rec.value, &block_offset)) {
1365 DEBUG_WARN(("failed to get block offset for table_rec.value of %#x\n", table_rec.value));
1366 na_ptr->count_item --; //we will be skipping a row
1367 continue;
1368 }
1369 t_ptr = block_offset.from;
1370 if (t_ptr <= block_offset.to) {
1371 na_ptr->items[x]->size = size = block_offset.to - t_ptr;
1372 } else {
1373 DEBUG_WARN(("I don't want to malloc less than zero sized block. from=%#x, to=%#x."
1374 "Will change to 1 byte\n", block_offset.from, block_offset.to));
1375 na_ptr->items[x]->size = size = 0; // the malloc statement will add one to this
1376 }
1377
1378 // plus one for good luck (and strings) we will null terminate all reads
1379 na_ptr->items[x]->data = (unsigned char*) xmalloc(size+1);
1380 memcpy(na_ptr->items[x]->data, &(buf[t_ptr]), size);
1381 na_ptr->items[x]->data[size] = '\0'; // null terminate buffer
1382
1383 if (table_rec.ref_type == 0xd) {
1384 // there is still more to do for the type of 0xD
1385 type_d_rec = (struct _type_d_rec*) na_ptr->items[x]->data;
1386 LE32_CPU(type_d_rec->id);
1387 if ((na_ptr->items[x]->size = _pst_ff_getID2block(pf, type_d_rec->id, i2_head, &(na_ptr->items[x]->data)))==0){
1388 DEBUG_WARN(("not able to read the ID2 data. Setting to be read later. %#x\n",
1389 type_d_rec->id));
1390 na_ptr->items[x]->size = 0;
1391 na_ptr->items[x]->data = NULL;
1392 na_ptr->items[x]->type = type_d_rec->id;
1393 }
1394 }
1395 } else {
1396 DEBUG_EMAIL(("Ignoring 0 value in offset\n"));
1397 if (na_ptr->items[x]->data) free (na_ptr->items[x]->data);
1398 na_ptr->items[x]->data = NULL;
1399 free(na_ptr->items[x]);
1400 na_ptr->count_item--; // remove this item from the destination list
1401 continue;
1402 } 1445 }
1403 if (na_ptr->items[x]->type == 0) 1446 if (na_ptr->items[x]->type == 0) na_ptr->items[x]->type = table_rec.ref_type;
1404 //it can be used to convey information
1405 // to later functions
1406 na_ptr->items[x]->type = table_rec.ref_type;
1407 } else { 1447 } else {
1408 WARN(("ERROR Unknown ref_type %#x\n", table_rec.ref_type)); 1448 WARN(("ERROR Unknown ref_type %#x\n", table_rec.ref_type));
1409 if (buf) free(buf); 1449 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1410 if (na_head) _pst_free_list(na_head); 1450 if (na_head) _pst_free_list(na_head);
1411 DEBUG_RET(); 1451 DEBUG_RET();
1412 return NULL; 1452 return NULL;
1413 } 1453 }
1414 x++; 1454 x++;
1415 } 1455 }
1416 DEBUG_EMAIL(("increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n", rec_size, rec_size, ind2_ptr, ind2_ptr+rec_size)); 1456 DEBUG_EMAIL(("increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n", rec_size, rec_size, ind2_ptr, ind2_ptr+rec_size));
1417 ind2_ptr += rec_size; 1457 ind2_ptr += rec_size;
1418 count_rec++; 1458 }
1419 } 1459 freeall(buf, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1420 if (buf) free(buf);
1421 DEBUG_RET(); 1460 DEBUG_RET();
1422 return na_head; 1461 return na_head;
1423 } 1462 }
1424 1463
1425 1464
2996 MALLOC_JOURNAL(item); 3035 MALLOC_JOURNAL(item);
2997 LIST_COPY(item->journal->type, (char*)); 3036 LIST_COPY(item->journal->type, (char*));
2998 DEBUG_EMAIL(("%s\n", item->journal->type)); 3037 DEBUG_EMAIL(("%s\n", item->journal->type));
2999 break; 3038 break;
3000 default: 3039 default:
3040 DEBUG_EMAIL(("unknown type %#x\n", list->items[x]->id));
3001 /* Reference Types 3041 /* Reference Types
3002 3042
3003 2 - 0x0002 - Signed 16bit value 3043 2 - 0x0002 - Signed 16bit value
3004 3 - 0x0003 - Signed 32bit value 3044 3 - 0x0003 - Signed 32bit value
3005 11 - 0x000B - Boolean (non-zero = true) 3045 11 - 0x000B - Boolean (non-zero = true)
3429 } 3469 }
3430 DEBUG_RET(); 3470 DEBUG_RET();
3431 } 3471 }
3432 3472
3433 3473
3474 /**
3475 * The offset might be zero, in which case we have no data, so return a pair of null pointers.
3476 * Or, the offset might end in 0xf, so it is an id2 pointer, in which case we read the id2 block.
3477 * Otherwise, the offset>>4 is an index into the table of offsets in the buffer.
3478 */
3479 int32_t _pst_getBlockOffsetPointer(pst_file *pf, pst_index2_ll *i2_head, unsigned char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset_pointer *p) {
3480 int32_t size;
3481 pst_block_offset block_offset;
3482 DEBUG_ENT("_pst_getBlockOffsetPointer");
3483 if (p->needfree) free(p->from);
3484 p->from = NULL;
3485 p->needfree = 0;
3486 if (!offset) {
3487 p->from = p->to = NULL;
3488 }
3489 else if ((offset & 0xf) == 0xf) {
3490 DEBUG_WARN(("Found id2 %#x value. Will follow it\n", offset));
3491 size = _pst_ff_getID2block(pf, offset, i2_head, &(p->from));
3492 if (size) {
3493 p->to = p->from + size;
3494 p->needfree = 1;
3495 }
3496 else {
3497 p->from = p->to = NULL;
3498 }
3499 }
3500 else if (_pst_getBlockOffset(buf, read_size, i_offset, offset, &block_offset)) {
3501 p->from = p->to = NULL;
3502 }
3503 else {
3504 p->from = buf + block_offset.from;
3505 p->to = buf + block_offset.to;
3506 }
3507 DEBUG_RET();
3508 return (p->from) ? 0 : 1;
3509 }
3510
3511
3434 int32_t _pst_getBlockOffset(unsigned char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset *p) { 3512 int32_t _pst_getBlockOffset(unsigned char *buf, int32_t read_size, int32_t i_offset, int32_t offset, pst_block_offset *p) {
3435 int32_t of1 = offset>>4; 3513 int32_t low = offset & 0xf;
3514 int32_t of1 = offset >> 4;
3436 DEBUG_ENT("_pst_getBlockOffset"); 3515 DEBUG_ENT("_pst_getBlockOffset");
3437 if (!p || !buf || (i_offset == 0) || (i_offset+2+of1+sizeof(*p) > read_size)) { 3516 if (!p || !buf || !i_offset || low || (i_offset+2+of1+sizeof(*p) > read_size)) {
3438 DEBUG_WARN(("p is NULL or buf is NULL or offset is 0 (%p, %p, %#x, %i, %i)\n", p, buf, offset, read_size, i_offset)); 3517 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));
3439 DEBUG_RET(); 3518 DEBUG_RET();
3440 return -1; 3519 return -1;
3441 } 3520 }
3442 memcpy(&(p->from), &(buf[(i_offset+2)+of1]), sizeof(p->from)); 3521 memcpy(&(p->from), &(buf[(i_offset+2)+of1]), sizeof(p->from));
3443 memcpy(&(p->to), &(buf[(i_offset+2)+of1+sizeof(p->from)]), sizeof(p->to)); 3522 memcpy(&(p->to), &(buf[(i_offset+2)+of1+sizeof(p->from)]), sizeof(p->to));
3444 LE16_CPU(p->from); 3523 LE16_CPU(p->from);
3445 LE16_CPU(p->to); 3524 LE16_CPU(p->to);
3446 DEBUG_WARN(("get block offset finds from=%i(%#x), to=%i(%#x)", p->from, p->from, p->to, p->to)); 3525 DEBUG_WARN(("get block offset finds from=%i(%#x), to=%i(%#x)\n", p->from, p->from, p->to, p->to));
3526 if (p->from > p->to) {
3527 DEBUG_WARN(("get block offset from > to"));
3528 return -1;
3529 }
3447 DEBUG_RET(); 3530 DEBUG_RET();
3448 return 0; 3531 return 0;
3449 } 3532 }
3450 3533
3451 3534
3452 pst_index_ll * _pst_getID(pst_file* pf, u_int32_t id) { 3535 pst_index_ll* _pst_getID(pst_file* pf, u_int32_t id) {
3453 pst_index_ll *ptr = NULL; 3536 pst_index_ll *ptr = NULL;
3454 DEBUG_ENT("_pst_getID"); 3537 DEBUG_ENT("_pst_getID");
3455 if (id == 0) { 3538 if (id == 0) {
3456 DEBUG_RET(); 3539 DEBUG_RET();
3457 return NULL; 3540 return NULL;
3458 } 3541 }
3459 3542
3460 /* if (id & 0x3) { // if either of the last two bits on the id are set 3543 //if (id & 1) DEBUG_INDEX(("have odd id bit %#x\n", id));
3461 DEBUG_INDEX(("ODD_INDEX (not even) is this a pointer to a table?\n")); 3544 //if (id & 2) DEBUG_INDEX(("have two id bit %#x\n", id));
3462 }*/ 3545 id &= 0xFFFFFFFE;
3463 // Dave: I don't think I should do this. next bit. I really think it doesn't work
3464 // it isn't based on sound principles either.
3465 // update: seems that the last two sig bits are flags. u tell me!
3466 id &= 0xFFFFFFFE; // remove least sig. bit. seems that it might work if I do this
3467 3546
3468 DEBUG_INDEX(("Trying to find %#x\n", id)); 3547 DEBUG_INDEX(("Trying to find %#x\n", id));
3469 if (!ptr) ptr = pf->i_head; 3548 if (!ptr) ptr = pf->i_head;
3470 while (ptr && (ptr->id != id)) { 3549 while (ptr && (ptr->id != id)) {
3471 ptr = ptr->next; 3550 ptr = ptr->next;
3472 } 3551 }
3473 if (ptr) {DEBUG_INDEX(("Found Value %#x\n", ptr->id));} 3552 if (ptr) {DEBUG_INDEX(("Found Value %#x\n", id)); }
3474 else {DEBUG_INDEX(("ERROR: Value not found\n")); } 3553 else {DEBUG_INDEX(("ERROR: Value %#x not found\n", id)); }
3475 DEBUG_RET(); 3554 DEBUG_RET();
3476 return ptr; 3555 return ptr;
3477 } 3556 }
3478 3557
3479 3558
3494 DEBUG_RET(); 3573 DEBUG_RET();
3495 return NULL; 3574 return NULL;
3496 } 3575 }
3497 3576
3498 3577
3499 pst_desc_ll * _pst_getDptr(pst_file *pf, u_int32_t id) { 3578 /**
3579 * find the id in the descriptor tree rooted at pf->d_head
3580 *
3581 * @param pf global pst file pointer
3582 * @param id the id we are looking for
3583 *
3584 * @return pointer to the pst_desc_ll node in the descriptor tree
3585 */
3586 pst_desc_ll* _pst_getDptr(pst_file *pf, u_int32_t id) {
3500 pst_desc_ll *ptr = pf->d_head; 3587 pst_desc_ll *ptr = pf->d_head;
3501 DEBUG_ENT("_pst_getDptr"); 3588 DEBUG_ENT("_pst_getDptr");
3502 while (ptr && (ptr->id != id)) { 3589 while (ptr && (ptr->id != id)) {
3503 if (ptr->child) { 3590 if (ptr->child) {
3504 ptr = ptr->child; 3591 ptr = ptr->child;
3740 3827
3741 3828
3742 size_t _pst_ff_getIDblock_dec(pst_file *pf, u_int32_t id, unsigned char **b) { 3829 size_t _pst_ff_getIDblock_dec(pst_file *pf, u_int32_t id, unsigned char **b) {
3743 size_t r; 3830 size_t r;
3744 DEBUG_ENT("_pst_ff_getIDblock_dec"); 3831 DEBUG_ENT("_pst_ff_getIDblock_dec");
3832 DEBUG_INDEX(("for id %#x\n", id));
3745 r = _pst_ff_getIDblock(pf, id, b); 3833 r = _pst_ff_getIDblock(pf, id, b);
3746 if (pf->encryption) _pst_decrypt(*b, r, pf->encryption);
3747 DEBUG_HEXDUMPC(*b, r, 16); 3834 DEBUG_HEXDUMPC(*b, r, 16);
3835 int noenc = (id & 2); // disable encryption
3836 if ((pf->encryption) & !(noenc)) {
3837 _pst_decrypt(*b, r, pf->encryption);
3838 DEBUG_HEXDUMPC(*b, r, 16);
3839 }
3748 DEBUG_RET(); 3840 DEBUG_RET();
3749 return r; 3841 return r;
3750 } 3842 }
3751 3843
3752 3844
3753 /** the get ID function for the default file format that I am working with
3754 ie the one in the PST files */
3755 size_t _pst_ff_getIDblock(pst_file *pf, u_int32_t id, unsigned char** b) { 3845 size_t _pst_ff_getIDblock(pst_file *pf, u_int32_t id, unsigned char** b) {
3756 pst_index_ll *rec; 3846 pst_index_ll *rec;
3757 size_t rsize = 0;//, re_size=0; 3847 size_t rsize = 0;//, re_size=0;
3758 DEBUG_ENT("_pst_ff_getIDblock"); 3848 DEBUG_ENT("_pst_ff_getIDblock");
3759 if ((rec = _pst_getID(pf, id)) == NULL) { 3849 if ((rec = _pst_getID(pf, id)) == NULL) {