Mercurial > libpst
comparison src/libpst.c @ 373:0ccc746c8079
Zachary Travis - Add support for the OST 2013 format, and Content-Disposition filename key fix for outlook compatibility
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 21 Jul 2017 20:01:44 -0700 |
parents | 8700cc322c0c |
children | 2379a4d8d9c7 |
comparison
equal
deleted
inserted
replaced
372:5b52efe35bd8 | 373:0ccc746c8079 |
---|---|
4 * Written by David Smith | 4 * Written by David Smith |
5 * dave.s@earthcorp.com | 5 * dave.s@earthcorp.com |
6 */ | 6 */ |
7 | 7 |
8 #include "define.h" | 8 #include "define.h" |
9 #include "zlib.h" | |
9 | 10 |
10 | 11 |
11 // switch to maximal packing for our own internal structures | 12 // switch to maximal packing for our own internal structures |
12 // use the same code as in libpst.h | 13 // use the same code as in libpst.h |
13 #ifdef _MSC_VER | 14 #ifdef _MSC_VER |
21 | 22 |
22 #define INDEX_TYPE32 0x0E | 23 #define INDEX_TYPE32 0x0E |
23 #define INDEX_TYPE32A 0x0F // unknown, but assumed to be similar for now | 24 #define INDEX_TYPE32A 0x0F // unknown, but assumed to be similar for now |
24 #define INDEX_TYPE64 0x17 | 25 #define INDEX_TYPE64 0x17 |
25 #define INDEX_TYPE64A 0x15 // http://sourceforge.net/projects/libpff/ | 26 #define INDEX_TYPE64A 0x15 // http://sourceforge.net/projects/libpff/ |
27 #define INDEX_TYPE4K 0x24 | |
26 #define INDEX_TYPE_OFFSET (int64_t)0x0A | 28 #define INDEX_TYPE_OFFSET (int64_t)0x0A |
27 | 29 |
28 #define FILE_SIZE_POINTER32 (int64_t)0xA8 | 30 #define FILE_SIZE_POINTER32 (int64_t)0xA8 |
29 #define INDEX_POINTER32 (int64_t)0xC4 | 31 #define INDEX_POINTER32 (int64_t)0xC4 |
30 #define INDEX_BACK32 (int64_t)0xC0 | 32 #define INDEX_BACK32 (int64_t)0xC0 |
43 #define INDEX_POINTER ((pf->do_read64) ? INDEX_POINTER64 : INDEX_POINTER32) | 45 #define INDEX_POINTER ((pf->do_read64) ? INDEX_POINTER64 : INDEX_POINTER32) |
44 #define INDEX_BACK ((pf->do_read64) ? INDEX_BACK64 : INDEX_BACK32) | 46 #define INDEX_BACK ((pf->do_read64) ? INDEX_BACK64 : INDEX_BACK32) |
45 #define SECOND_POINTER ((pf->do_read64) ? SECOND_POINTER64 : SECOND_POINTER32) | 47 #define SECOND_POINTER ((pf->do_read64) ? SECOND_POINTER64 : SECOND_POINTER32) |
46 #define SECOND_BACK ((pf->do_read64) ? SECOND_BACK64 : SECOND_BACK32) | 48 #define SECOND_BACK ((pf->do_read64) ? SECOND_BACK64 : SECOND_BACK32) |
47 #define ENC_TYPE ((pf->do_read64) ? ENC_TYPE64 : ENC_TYPE32) | 49 #define ENC_TYPE ((pf->do_read64) ? ENC_TYPE64 : ENC_TYPE32) |
50 | |
48 | 51 |
49 #define PST_SIGNATURE 0x4E444221 | 52 #define PST_SIGNATURE 0x4E444221 |
50 | 53 |
51 | 54 |
52 typedef struct pst_block_offset { | 55 typedef struct pst_block_offset { |
133 uint32_t parent_d_id; // not 64 bit | 136 uint32_t parent_d_id; // not 64 bit |
134 uint32_t u1; // padding | 137 uint32_t u1; // padding |
135 } pst_desc; | 138 } pst_desc; |
136 | 139 |
137 | 140 |
141 typedef struct pst_index64 { | |
142 uint64_t id; | |
143 uint64_t offset; | |
144 uint16_t size; | |
145 int16_t u0; | |
146 int32_t u1; | |
147 } pst_index64; | |
148 | |
138 typedef struct pst_index { | 149 typedef struct pst_index { |
139 uint64_t id; | 150 uint64_t id; |
140 uint64_t offset; | 151 uint64_t offset; |
141 uint16_t size; | 152 uint16_t size; |
153 uint16_t inflated_size; | |
142 int16_t u0; | 154 int16_t u0; |
143 int32_t u1; | 155 int32_t u1; |
144 } pst_index; | 156 } pst_index; |
145 | 157 |
146 | 158 |
279 static uint64_t pst_getIntAtPos(pst_file *pf, int64_t pos); | 291 static uint64_t pst_getIntAtPos(pst_file *pf, int64_t pos); |
280 static pst_mapi_object* pst_parse_block(pst_file *pf, uint64_t block_id, pst_id2_tree *i2_head); | 292 static pst_mapi_object* pst_parse_block(pst_file *pf, uint64_t block_id, pst_id2_tree *i2_head); |
281 static void pst_printDptr(pst_file *pf, pst_desc_tree *ptr); | 293 static void pst_printDptr(pst_file *pf, pst_desc_tree *ptr); |
282 static void pst_printID2ptr(pst_id2_tree *ptr); | 294 static void pst_printID2ptr(pst_id2_tree *ptr); |
283 static int pst_process(uint64_t block_id, pst_mapi_object *list, pst_item *item, pst_item_attach *attach); | 295 static int pst_process(uint64_t block_id, pst_mapi_object *list, pst_item *item, pst_item_attach *attach); |
284 static size_t pst_read_block_size(pst_file *pf, int64_t offset, size_t size, char **buf); | 296 static size_t pst_read_block_size(pst_file *pf, int64_t offset, size_t size, size_t inflated_size, char **buf); |
297 static size_t pst_read_raw_block_size(pst_file *pf, int64_t offset, size_t size, char **buf); | |
285 static int pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type); | 298 static int pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type); |
286 static int pst_strincmp(char *a, char *b, size_t x); | 299 static int pst_strincmp(char *a, char *b, size_t x); |
287 static char* pst_wide_to_single(char *wt, size_t size); | 300 static char* pst_wide_to_single(char *wt, size_t size); |
288 | 301 |
289 | 302 |
345 pf->do_read64 = 0; | 358 pf->do_read64 = 0; |
346 break; | 359 break; |
347 case INDEX_TYPE64 : | 360 case INDEX_TYPE64 : |
348 case INDEX_TYPE64A : | 361 case INDEX_TYPE64A : |
349 pf->do_read64 = 1; | 362 pf->do_read64 = 1; |
363 break; | |
364 case INDEX_TYPE4K : | |
365 pf->do_read64 = 2; | |
350 break; | 366 break; |
351 default: | 367 default: |
352 (void)fclose(pf->fp); | 368 (void)fclose(pf->fp); |
353 DEBUG_WARN(("unknown .pst format, possibly newer than Outlook 2003 PST file?\n")); | 369 DEBUG_WARN(("unknown .pst format, possibly newer than Outlook 2003 PST file?\n")); |
354 DEBUG_RET(); | 370 DEBUG_RET(); |
805 return 1; | 821 return 1; |
806 } | 822 } |
807 | 823 |
808 | 824 |
809 #define ITEM_COUNT_OFFSET32 0x1f0 // count byte | 825 #define ITEM_COUNT_OFFSET32 0x1f0 // count byte |
826 #define MAX_COUNT_OFFSET32 0x1f1 | |
827 #define ENTRY_SIZE_OFFSET32 0x1f2 | |
810 #define LEVEL_INDICATOR_OFFSET32 0x1f3 // node or leaf | 828 #define LEVEL_INDICATOR_OFFSET32 0x1f3 // node or leaf |
811 #define BACKLINK_OFFSET32 0x1f8 // backlink u1 value | 829 #define BACKLINK_OFFSET32 0x1f8 // backlink u1 value |
812 #define ITEM_SIZE32 12 | |
813 #define DESC_SIZE32 16 | |
814 #define INDEX_COUNT_MAX32 41 // max active items | |
815 #define DESC_COUNT_MAX32 31 // max active items | |
816 | 830 |
817 #define ITEM_COUNT_OFFSET64 0x1e8 // count byte | 831 #define ITEM_COUNT_OFFSET64 0x1e8 // count byte |
832 #define MAX_COUNT_OFFSET64 0x1e9 | |
833 #define ENTRY_SIZE_OFFSET64 0x1ea // node or leaf | |
818 #define LEVEL_INDICATOR_OFFSET64 0x1eb // node or leaf | 834 #define LEVEL_INDICATOR_OFFSET64 0x1eb // node or leaf |
819 #define BACKLINK_OFFSET64 0x1f8 // backlink u1 value | 835 #define BACKLINK_OFFSET64 0x1f8 // backlink u1 value |
820 #define ITEM_SIZE64 24 | 836 |
821 #define DESC_SIZE64 32 | 837 #define ITEM_COUNT_OFFSET4K 0xfd8 |
822 #define INDEX_COUNT_MAX64 20 // max active items | 838 #define MAX_COUNT_OFFSET4K 0xfda |
823 #define DESC_COUNT_MAX64 15 // max active items | 839 #define ENTRY_SIZE_OFFSET4K 0xfdc |
824 | 840 #define LEVEL_INDICATOR_OFFSET4K 0xfdd |
825 #define BLOCK_SIZE 512 // index blocks | 841 #define BACKLINK_OFFSET4K 0xff0 |
826 #define DESC_BLOCK_SIZE 512 // descriptor blocks | 842 |
827 #define ITEM_COUNT_OFFSET (size_t)((pf->do_read64) ? ITEM_COUNT_OFFSET64 : ITEM_COUNT_OFFSET32) | 843 #define BLOCK_SIZE (size_t)((pf->do_read64 == 2) ? 4096 : 512) // index blocks |
828 #define LEVEL_INDICATOR_OFFSET (size_t)((pf->do_read64) ? LEVEL_INDICATOR_OFFSET64 : LEVEL_INDICATOR_OFFSET32) | 844 #define DESC_BLOCK_SIZE (size_t)((pf->do_read64 == 2) ? 4096 : 512) // descriptor blocks |
829 #define BACKLINK_OFFSET (size_t)((pf->do_read64) ? BACKLINK_OFFSET64 : BACKLINK_OFFSET32) | 845 #define ITEM_COUNT_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? ITEM_COUNT_OFFSET4K : ITEM_COUNT_OFFSET64) : ITEM_COUNT_OFFSET32) |
830 #define ITEM_SIZE (size_t)((pf->do_read64) ? ITEM_SIZE64 : ITEM_SIZE32) | 846 #define LEVEL_INDICATOR_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? LEVEL_INDICATOR_OFFSET4K : LEVEL_INDICATOR_OFFSET64) : LEVEL_INDICATOR_OFFSET32) |
831 #define DESC_SIZE (size_t)((pf->do_read64) ? DESC_SIZE64 : DESC_SIZE32) | 847 #define BACKLINK_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? BACKLINK_OFFSET4K : BACKLINK_OFFSET64) : BACKLINK_OFFSET32) |
832 #define INDEX_COUNT_MAX (int32_t)((pf->do_read64) ? INDEX_COUNT_MAX64 : INDEX_COUNT_MAX32) | 848 #define ENTRY_SIZE_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? ENTRY_SIZE_OFFSET4K : ENTRY_SIZE_OFFSET64) : ENTRY_SIZE_OFFSET32) |
833 #define DESC_COUNT_MAX (int32_t)((pf->do_read64) ? DESC_COUNT_MAX64 : DESC_COUNT_MAX32) | 849 #define MAX_COUNT_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? MAX_COUNT_OFFSET4K : MAX_COUNT_OFFSET64) : MAX_COUNT_OFFSET32) |
834 | 850 |
851 #define read_twobyte(BUF, OFF) (int32_t) ((((unsigned)BUF[OFF + 1] & 0xFF)) << 8) | ((unsigned)BUF[OFF] & 0xFF); | |
835 | 852 |
836 static size_t pst_decode_desc(pst_file *pf, pst_desc *desc, char *buf); | 853 static size_t pst_decode_desc(pst_file *pf, pst_desc *desc, char *buf); |
837 static size_t pst_decode_desc(pst_file *pf, pst_desc *desc, char *buf) { | 854 static size_t pst_decode_desc(pst_file *pf, pst_desc *desc, char *buf) { |
838 size_t r; | 855 size_t r; |
839 if (pf->do_read64) { | 856 if (pf->do_read64) { |
897 | 914 |
898 | 915 |
899 static size_t pst_decode_index(pst_file *pf, pst_index *index, char *buf); | 916 static size_t pst_decode_index(pst_file *pf, pst_index *index, char *buf); |
900 static size_t pst_decode_index(pst_file *pf, pst_index *index, char *buf) { | 917 static size_t pst_decode_index(pst_file *pf, pst_index *index, char *buf) { |
901 size_t r; | 918 size_t r; |
902 if (pf->do_read64) { | 919 if (pf->do_read64 == 2) { |
903 DEBUG_INFO(("Decoding index64\n")); | 920 DEBUG_INFO(("Decoding index4k\n")); |
904 DEBUG_HEXDUMPC(buf, sizeof(pst_index), 0x10); | 921 DEBUG_HEXDUMPC(buf, sizeof(pst_index), 0x10); |
905 memcpy(index, buf, sizeof(pst_index)); | 922 memcpy(index, buf, sizeof(pst_index)); |
906 LE64_CPU(index->id); | 923 LE64_CPU(index->id); |
907 LE64_CPU(index->offset); | 924 LE64_CPU(index->offset); |
908 LE16_CPU(index->size); | 925 LE16_CPU(index->size); |
926 LE16_CPU(index->inflated_size); | |
909 LE16_CPU(index->u0); | 927 LE16_CPU(index->u0); |
910 LE32_CPU(index->u1); | 928 LE32_CPU(index->u1); |
911 r = sizeof(pst_index); | 929 r = sizeof(pst_index); |
930 } else if (pf->do_read64 == 1) { | |
931 pst_index64 index64; | |
932 DEBUG_INFO(("Decoding index64\n")); | |
933 DEBUG_HEXDUMPC(buf, sizeof(pst_index64), 0x10); | |
934 memcpy(&index64, buf, sizeof(pst_index64)); | |
935 LE64_CPU(index64.id); | |
936 LE64_CPU(index64.offset); | |
937 LE16_CPU(index64.size); | |
938 LE16_CPU(index64.u0); | |
939 LE32_CPU(index64.u1); | |
940 index->id = index64.id; | |
941 index->offset = index64.offset; | |
942 index->size = index64.size; | |
943 index->inflated_size = index64.size; | |
944 index->u0 = index64.u0; | |
945 index->u1 = index64.u1; | |
946 r = sizeof(pst_index64); | |
912 } else { | 947 } else { |
913 pst_index32 index32; | 948 pst_index32 index32; |
914 DEBUG_INFO(("Decoding index32\n")); | 949 DEBUG_INFO(("Decoding index32\n")); |
915 DEBUG_HEXDUMPC(buf, sizeof(pst_index32), 0x10); | 950 DEBUG_HEXDUMPC(buf, sizeof(pst_index32), 0x10); |
916 memcpy(&index32, buf, sizeof(pst_index32)); | 951 memcpy(&index32, buf, sizeof(pst_index32)); |
919 LE16_CPU(index32.size); | 954 LE16_CPU(index32.size); |
920 LE16_CPU(index32.u1); | 955 LE16_CPU(index32.u1); |
921 index->id = index32.id; | 956 index->id = index32.id; |
922 index->offset = index32.offset; | 957 index->offset = index32.offset; |
923 index->size = index32.size; | 958 index->size = index32.size; |
959 index->inflated_size = index32.size; | |
924 index->u0 = 0; | 960 index->u0 = 0; |
925 index->u1 = index32.u1; | 961 index->u1 = index32.u1; |
926 r = sizeof(pst_index32); | 962 r = sizeof(pst_index32); |
927 } | 963 } |
928 return r; | 964 return r; |
988 */ | 1024 */ |
989 static int pst_build_id_ptr(pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val) { | 1025 static int pst_build_id_ptr(pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val) { |
990 struct pst_table_ptr_struct table, table2; | 1026 struct pst_table_ptr_struct table, table2; |
991 pst_index_ll *i_ptr=NULL; | 1027 pst_index_ll *i_ptr=NULL; |
992 pst_index index; | 1028 pst_index index; |
993 int32_t x, item_count; | 1029 int32_t x, item_count, count_max; |
994 uint64_t old = start_val; | 1030 uint64_t old = start_val; |
995 char *buf = NULL, *bptr; | 1031 char *buf = NULL, *bptr; |
996 | 1032 |
997 DEBUG_ENT("pst_build_id_ptr"); | 1033 DEBUG_ENT("pst_build_id_ptr"); |
998 DEBUG_INFO(("offset %#"PRIx64" depth %i linku1 %#"PRIx64" start %#"PRIx64" end %#"PRIx64"\n", offset, depth, linku1, start_val, end_val)); | 1034 DEBUG_INFO(("offset %#"PRIx64" depth %i linku1 %#"PRIx64" start %#"PRIx64" end %#"PRIx64"\n", offset, depth, linku1, start_val, end_val)); |
1000 DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64", end:%#"PRIx64"]\n", start_val, end_val)); | 1036 DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64", end:%#"PRIx64"]\n", start_val, end_val)); |
1001 DEBUG_RET(); | 1037 DEBUG_RET(); |
1002 return -1; | 1038 return -1; |
1003 } | 1039 } |
1004 DEBUG_INFO(("Reading index block\n")); | 1040 DEBUG_INFO(("Reading index block\n")); |
1005 if (pst_read_block_size(pf, offset, BLOCK_SIZE, &buf) < BLOCK_SIZE) { | 1041 if (pst_read_block_size(pf, offset, BLOCK_SIZE, BLOCK_SIZE, &buf) < BLOCK_SIZE) { |
1006 DEBUG_WARN(("Failed to read %i bytes\n", BLOCK_SIZE)); | 1042 DEBUG_WARN(("Failed to read %i bytes\n", BLOCK_SIZE)); |
1007 if (buf) free(buf); | 1043 if (buf) free(buf); |
1008 DEBUG_RET(); | 1044 DEBUG_RET(); |
1009 return -1; | 1045 return -1; |
1010 } | 1046 } |
1011 bptr = buf; | 1047 bptr = buf; |
1012 DEBUG_HEXDUMPC(buf, BLOCK_SIZE, ITEM_SIZE32); | 1048 DEBUG_HEXDUMPC(buf, BLOCK_SIZE, 0x10); |
1013 item_count = (int32_t)(unsigned)(buf[ITEM_COUNT_OFFSET]); | 1049 if (pf->do_read64 == 2) { |
1014 if (item_count > INDEX_COUNT_MAX) { | 1050 item_count = read_twobyte(buf, ITEM_COUNT_OFFSET); |
1015 DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, INDEX_COUNT_MAX)); | 1051 count_max = read_twobyte(buf, MAX_COUNT_OFFSET); |
1052 } else { | |
1053 item_count = (int32_t)(unsigned)(buf[ITEM_COUNT_OFFSET]); | |
1054 count_max = (int32_t)(unsigned)(buf[MAX_COUNT_OFFSET]); | |
1055 } | |
1056 if (item_count > count_max) { | |
1057 DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, count_max)); | |
1016 if (buf) free(buf); | 1058 if (buf) free(buf); |
1017 DEBUG_RET(); | 1059 DEBUG_RET(); |
1018 return -1; | 1060 return -1; |
1019 } | 1061 } |
1020 index.id = pst_getIntAt(pf, buf+BACKLINK_OFFSET); | 1062 index.id = pst_getIntAt(pf, buf+BACKLINK_OFFSET); |
1022 DEBUG_WARN(("Backlink %#"PRIx64" in this node does not match required %#"PRIx64"\n", index.id, linku1)); | 1064 DEBUG_WARN(("Backlink %#"PRIx64" in this node does not match required %#"PRIx64"\n", index.id, linku1)); |
1023 if (buf) free(buf); | 1065 if (buf) free(buf); |
1024 DEBUG_RET(); | 1066 DEBUG_RET(); |
1025 return -1; | 1067 return -1; |
1026 } | 1068 } |
1027 | 1069 int entry_size = (int32_t)(unsigned)(buf[ENTRY_SIZE_OFFSET]); |
1070 DEBUG_INFO(("count %#"PRIx64" max %#"PRIx64" size %#"PRIx64"\n", item_count, count_max, entry_size)); | |
1028 if (buf[LEVEL_INDICATOR_OFFSET] == '\0') { | 1071 if (buf[LEVEL_INDICATOR_OFFSET] == '\0') { |
1029 // this node contains leaf pointers | 1072 // this node contains leaf pointers |
1030 x = 0; | 1073 x = 0; |
1031 while (x < item_count) { | 1074 while (x < item_count) { |
1032 bptr += pst_decode_index(pf, &index, bptr); | 1075 pst_decode_index(pf, &index, bptr); |
1076 bptr += entry_size; | |
1033 x++; | 1077 x++; |
1034 if (index.id == 0) break; | 1078 if (index.id == 0) break; |
1035 DEBUG_INFO(("[%i]%i Item [id = %#"PRIx64", offset = %#"PRIx64", u1 = %#x, size = %i(%#x)]\n", | 1079 DEBUG_INFO(("[%i]%i Item [id = %#"PRIx64", offset = %#"PRIx64", u1 = %#x, size = %i(%#x)]\n", |
1036 depth, x, index.id, index.offset, index.u1, index.size, index.size)); | 1080 depth, x, index.id, index.offset, index.u1, index.size, index.size)); |
1037 // if (index.id & 0x02) DEBUG_INFO(("two-bit set!!\n")); | 1081 // if (index.id & 0x02) DEBUG_INFO(("two-bit set!!\n")); |
1049 i_ptr = &pf->i_table[pf->i_count++]; | 1093 i_ptr = &pf->i_table[pf->i_count++]; |
1050 i_ptr->i_id = index.id; | 1094 i_ptr->i_id = index.id; |
1051 i_ptr->offset = index.offset; | 1095 i_ptr->offset = index.offset; |
1052 i_ptr->u1 = index.u1; | 1096 i_ptr->u1 = index.u1; |
1053 i_ptr->size = index.size; | 1097 i_ptr->size = index.size; |
1098 i_ptr->inflated_size = index.inflated_size; | |
1054 } | 1099 } |
1055 } else { | 1100 } else { |
1056 // this node contains node pointers | 1101 // this node contains node pointers |
1057 x = 0; | 1102 x = 0; |
1058 while (x < item_count) { | 1103 while (x < item_count) { |
1059 bptr += pst_decode_table(pf, &table, bptr); | 1104 pst_decode_table(pf, &table, bptr); |
1105 bptr += entry_size; | |
1060 x++; | 1106 x++; |
1061 if (table.start == 0) break; | 1107 if (table.start == 0) break; |
1062 if (x < item_count) { | 1108 if (x < item_count) { |
1063 (void)pst_decode_table(pf, &table2, bptr); | 1109 (void)pst_decode_table(pf, &table2, bptr); |
1064 } | 1110 } |
1088 * higher level objects (email, contact, etc) in the pst file. | 1134 * higher level objects (email, contact, etc) in the pst file. |
1089 */ | 1135 */ |
1090 static int pst_build_desc_ptr (pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val) { | 1136 static int pst_build_desc_ptr (pst_file *pf, int64_t offset, int32_t depth, uint64_t linku1, uint64_t start_val, uint64_t end_val) { |
1091 struct pst_table_ptr_struct table, table2; | 1137 struct pst_table_ptr_struct table, table2; |
1092 pst_desc desc_rec; | 1138 pst_desc desc_rec; |
1093 int32_t item_count; | 1139 int32_t item_count, count_max; |
1094 uint64_t old = start_val; | 1140 uint64_t old = start_val; |
1095 int x; | 1141 int x; |
1096 char *buf = NULL, *bptr; | 1142 char *buf = NULL, *bptr; |
1097 | 1143 |
1098 DEBUG_ENT("pst_build_desc_ptr"); | 1144 DEBUG_ENT("pst_build_desc_ptr"); |
1101 DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64", end:%#"PRIx64"]\n", start_val, end_val)); | 1147 DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64", end:%#"PRIx64"]\n", start_val, end_val)); |
1102 DEBUG_RET(); | 1148 DEBUG_RET(); |
1103 return -1; | 1149 return -1; |
1104 } | 1150 } |
1105 DEBUG_INFO(("Reading desc block\n")); | 1151 DEBUG_INFO(("Reading desc block\n")); |
1106 if (pst_read_block_size(pf, offset, DESC_BLOCK_SIZE, &buf) < DESC_BLOCK_SIZE) { | 1152 if (pst_read_block_size(pf, offset, DESC_BLOCK_SIZE, DESC_BLOCK_SIZE, &buf) < DESC_BLOCK_SIZE) { |
1107 DEBUG_WARN(("Failed to read %i bytes\n", DESC_BLOCK_SIZE)); | 1153 DEBUG_WARN(("Failed to read %i bytes\n", DESC_BLOCK_SIZE)); |
1108 if (buf) free(buf); | 1154 if (buf) free(buf); |
1109 DEBUG_RET(); | 1155 DEBUG_RET(); |
1110 return -1; | 1156 return -1; |
1111 } | 1157 } |
1112 bptr = buf; | 1158 bptr = buf; |
1113 item_count = (int32_t)(unsigned)(buf[ITEM_COUNT_OFFSET]); | 1159 if (pf->do_read64 == 2) { |
1114 | 1160 item_count = read_twobyte(buf, ITEM_COUNT_OFFSET); |
1161 count_max = read_twobyte(buf, MAX_COUNT_OFFSET); | |
1162 } else { | |
1163 item_count = (int32_t)(unsigned)(buf[ITEM_COUNT_OFFSET]); | |
1164 count_max = (int32_t)(unsigned)(buf[MAX_COUNT_OFFSET]); | |
1165 } | |
1115 desc_rec.d_id = pst_getIntAt(pf, buf+BACKLINK_OFFSET); | 1166 desc_rec.d_id = pst_getIntAt(pf, buf+BACKLINK_OFFSET); |
1116 if (desc_rec.d_id != linku1) { | 1167 if (desc_rec.d_id != linku1) { |
1117 DEBUG_WARN(("Backlink %#"PRIx64" in this node does not match required %#"PRIx64"\n", desc_rec.d_id, linku1)); | 1168 DEBUG_WARN(("Backlink %#"PRIx64" in this node does not match required %#"PRIx64"\n", desc_rec.d_id, linku1)); |
1118 if (buf) free(buf); | 1169 if (buf) free(buf); |
1119 DEBUG_RET(); | 1170 DEBUG_RET(); |
1120 return -1; | 1171 return -1; |
1121 } | 1172 } |
1173 int32_t entry_size = (int32_t)(unsigned)(buf[ENTRY_SIZE_OFFSET]); | |
1122 if (buf[LEVEL_INDICATOR_OFFSET] == '\0') { | 1174 if (buf[LEVEL_INDICATOR_OFFSET] == '\0') { |
1123 // this node contains leaf pointers | 1175 // this node contains leaf pointers |
1124 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, DESC_SIZE32); | 1176 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, entry_size); |
1125 if (item_count > DESC_COUNT_MAX) { | 1177 if (item_count > count_max) { |
1126 DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, DESC_COUNT_MAX)); | 1178 DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, count_max)); |
1127 if (buf) free(buf); | 1179 if (buf) free(buf); |
1128 DEBUG_RET(); | 1180 DEBUG_RET(); |
1129 return -1; | 1181 return -1; |
1130 } | 1182 } |
1131 for (x=0; x<item_count; x++) { | 1183 for (x=0; x<item_count; x++) { |
1132 bptr += pst_decode_desc(pf, &desc_rec, bptr); | 1184 pst_decode_desc(pf, &desc_rec, bptr); |
1185 bptr += entry_size; | |
1133 DEBUG_INFO(("[%i] Item(%#x) = [d_id = %#"PRIx64", desc_id = %#"PRIx64", tree_id = %#"PRIx64", parent_d_id = %#x]\n", | 1186 DEBUG_INFO(("[%i] Item(%#x) = [d_id = %#"PRIx64", desc_id = %#"PRIx64", tree_id = %#"PRIx64", parent_d_id = %#x]\n", |
1134 depth, x, desc_rec.d_id, desc_rec.desc_id, desc_rec.tree_id, desc_rec.parent_d_id)); | 1187 depth, x, desc_rec.d_id, desc_rec.desc_id, desc_rec.tree_id, desc_rec.parent_d_id)); |
1135 if ((desc_rec.d_id >= end_val) || (desc_rec.d_id < old)) { | 1188 if ((desc_rec.d_id >= end_val) || (desc_rec.d_id < old)) { |
1136 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n")); | 1189 DEBUG_WARN(("This item isn't right. Must be corruption, or I got it wrong!\n")); |
1137 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, 16); | 1190 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, 16); |
1150 record_descriptor(pf, d_ptr); // add to the global tree | 1203 record_descriptor(pf, d_ptr); // add to the global tree |
1151 } | 1204 } |
1152 } | 1205 } |
1153 } else { | 1206 } else { |
1154 // this node contains node pointers | 1207 // this node contains node pointers |
1155 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, ITEM_SIZE32); | 1208 DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, entry_size); |
1156 if (item_count > INDEX_COUNT_MAX) { | 1209 if (item_count > count_max) { |
1157 DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, INDEX_COUNT_MAX)); | 1210 DEBUG_WARN(("Item count %i too large, max is %i\n", item_count, count_max)); |
1158 if (buf) free(buf); | 1211 if (buf) free(buf); |
1159 DEBUG_RET(); | 1212 DEBUG_RET(); |
1160 return -1; | 1213 return -1; |
1161 } | 1214 } |
1162 for (x=0; x<item_count; x++) { | 1215 for (x=0; x<item_count; x++) { |
1163 bptr += pst_decode_table(pf, &table, bptr); | 1216 pst_decode_table(pf, &table, bptr); |
1217 bptr += entry_size; | |
1164 if (table.start == 0) break; | 1218 if (table.start == 0) break; |
1165 if (x < (item_count-1)) { | 1219 if (x < (item_count-1)) { |
1166 (void)pst_decode_table(pf, &table2, bptr); | 1220 (void)pst_decode_table(pf, &table2, bptr); |
1167 } | 1221 } |
1168 else { | 1222 else { |
3244 pst_id2_assoc id2_rec; | 3298 pst_id2_assoc id2_rec; |
3245 pst_index_ll *i_ptr = NULL; | 3299 pst_index_ll *i_ptr = NULL; |
3246 pst_id2_tree *i2_ptr = NULL; | 3300 pst_id2_tree *i2_ptr = NULL; |
3247 DEBUG_ENT("pst_build_id2"); | 3301 DEBUG_ENT("pst_build_id2"); |
3248 | 3302 |
3249 if (pst_read_block_size(pf, list->offset, list->size, &buf) < list->size) { | 3303 if (pst_read_block_size(pf, list->offset, list->size, list->inflated_size, &buf) < list->size) { |
3250 //an error occured in block read | 3304 //an error occured in block read |
3251 DEBUG_WARN(("block read error occured. offset = %#"PRIx64", size = %#"PRIx64"\n", list->offset, list->size)); | 3305 DEBUG_WARN(("block read error occured. offset = %#"PRIx64", size = %#"PRIx64"\n", list->offset, list->size)); |
3252 if (buf) free(buf); | 3306 if (buf) free(buf); |
3253 DEBUG_RET(); | 3307 DEBUG_RET(); |
3254 return NULL; | 3308 return NULL; |
3275 DEBUG_INFO(("id2 = %#x, id = %#"PRIx64", child id = %#"PRIx64"\n", id2_rec.id2, id2_rec.id, id2_rec.child_id)); | 3329 DEBUG_INFO(("id2 = %#x, id = %#"PRIx64", child id = %#"PRIx64"\n", id2_rec.id2, id2_rec.id, id2_rec.child_id)); |
3276 if ((i_ptr = pst_getID(pf, id2_rec.id)) == NULL) { | 3330 if ((i_ptr = pst_getID(pf, id2_rec.id)) == NULL) { |
3277 DEBUG_WARN(("%#"PRIx64" - Not Found\n", id2_rec.id)); | 3331 DEBUG_WARN(("%#"PRIx64" - Not Found\n", id2_rec.id)); |
3278 } else { | 3332 } else { |
3279 DEBUG_INFO(("%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %"PRIi64"(%#"PRIx64")\n", | 3333 DEBUG_INFO(("%#"PRIx64" - Offset %#"PRIx64", u1 %#"PRIx64", Size %"PRIi64"(%#"PRIx64")\n", |
3280 i_ptr->i_id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->size)); | 3334 i_ptr->i_id, i_ptr->offset, i_ptr->u1, i_ptr->size, i_ptr->inflated_size)); |
3281 // add it to the tree | 3335 // add it to the tree |
3282 i2_ptr = (pst_id2_tree*) pst_malloc(sizeof(pst_id2_tree)); | 3336 i2_ptr = (pst_id2_tree*) pst_malloc(sizeof(pst_id2_tree)); |
3283 i2_ptr->id2 = id2_rec.id2; | 3337 i2_ptr->id2 = id2_rec.id2; |
3284 i2_ptr->id = i_ptr; | 3338 i2_ptr->id = i_ptr; |
3285 i2_ptr->child = NULL; | 3339 i2_ptr->child = NULL; |
3562 } | 3616 } |
3563 p->from = p->to = NULL; | 3617 p->from = p->to = NULL; |
3564 } | 3618 } |
3565 } | 3619 } |
3566 else { | 3620 else { |
3621 DEBUG_WARN(("Found internal %#x value.\n", offset)); | |
3567 // internal index reference | 3622 // internal index reference |
3568 size_t subindex = offset >> 16; | 3623 size_t subindex = offset >> 16; |
3624 if (pf->do_read64 == 2) { | |
3625 // Shift over 3 more bits for new flags. | |
3626 subindex = subindex >> 3; | |
3627 } | |
3569 size_t suboffset = offset & 0xffff; | 3628 size_t suboffset = offset & 0xffff; |
3570 if (subindex < subblocks->subblock_count) { | 3629 if (subindex < subblocks->subblock_count) { |
3571 if (pst_getBlockOffset(subblocks->subs[subindex].buf, | 3630 if (pst_getBlockOffset(subblocks->subs[subindex].buf, |
3572 subblocks->subs[subindex].read_size, | 3631 subblocks->subs[subindex].read_size, |
3573 subblocks->subs[subindex].i_offset, | 3632 subblocks->subs[subindex].i_offset, |
3718 * @param size size of the block to be read | 3777 * @param size size of the block to be read |
3719 * @param buf reference to pointer to buffer. If this pointer | 3778 * @param buf reference to pointer to buffer. If this pointer |
3720 is non-NULL, it will first be free()d | 3779 is non-NULL, it will first be free()d |
3721 * @return size of block read into memory | 3780 * @return size of block read into memory |
3722 */ | 3781 */ |
3723 static size_t pst_read_block_size(pst_file *pf, int64_t offset, size_t size, char **buf) { | 3782 static size_t pst_read_raw_block_size(pst_file *pf, int64_t offset, size_t size, char **buf) { |
3724 size_t rsize; | 3783 size_t rsize; |
3725 DEBUG_ENT("pst_read_block_size"); | 3784 DEBUG_ENT("pst_read_raw_block_size"); |
3726 DEBUG_INFO(("Reading block from %#"PRIx64", %x bytes\n", offset, size)); | 3785 DEBUG_INFO(("Reading raw block from %#"PRIx64", %x bytes\n", offset, size)); |
3727 | 3786 |
3728 if (*buf) { | 3787 if (*buf) { |
3729 DEBUG_INFO(("Freeing old memory\n")); | 3788 DEBUG_INFO(("Freeing old memory\n")); |
3730 free(*buf); | 3789 free(*buf); |
3731 } | 3790 } |
3744 } | 3803 } |
3745 | 3804 |
3746 DEBUG_RET(); | 3805 DEBUG_RET(); |
3747 return rsize; | 3806 return rsize; |
3748 } | 3807 } |
3808 | |
3809 static size_t pst_read_block_size(pst_file *pf, int64_t offset, size_t size, size_t inflated_size, char **buf) { | |
3810 DEBUG_ENT("pst_read_block_size"); | |
3811 DEBUG_INFO(("Reading block from %#"PRIx64", %x bytes, %x inflated\n", offset, size, inflated_size)); | |
3812 if (inflated_size <= size) { | |
3813 // Not deflated. | |
3814 size_t ret = pst_read_raw_block_size(pf, offset, size, buf); | |
3815 DEBUG_RET(); | |
3816 return ret; | |
3817 } | |
3818 // We need to read the raw block and inflate it. | |
3819 char *zbuf = NULL; | |
3820 if (pst_read_raw_block_size(pf, offset, size, &zbuf) != size) { | |
3821 DEBUG_WARN(("Failed to read %i bytes\n", size)); | |
3822 if (zbuf) free(zbuf); | |
3823 DEBUG_RET(); | |
3824 return -1; | |
3825 } | |
3826 *buf = (char *) pst_malloc(inflated_size); | |
3827 size_t result_size = inflated_size; | |
3828 if (uncompress((Bytef *) *buf, &result_size, (Bytef *) zbuf, size) != Z_OK || result_size != inflated_size) { | |
3829 DEBUG_WARN(("Failed to uncompress %i bytes to %i bytes, got %i\n", size, inflated_size, result_size)); | |
3830 if (zbuf) free(zbuf); | |
3831 DEBUG_RET(); | |
3832 return -1; | |
3833 } | |
3834 DEBUG_RET(); | |
3835 return inflated_size; | |
3836 } | |
3837 | |
3749 | 3838 |
3750 | 3839 |
3751 /** Decrypt a block of data from the pst file. | 3840 /** Decrypt a block of data from the pst file. |
3752 * @param i_id identifier of this block, needed as part of the key for the enigma cipher | 3841 * @param i_id identifier of this block, needed as part of the key for the enigma cipher |
3753 * @param buf pointer to the buffer to be decrypted in place | 3842 * @param buf pointer to the buffer to be decrypted in place |
3921 DEBUG_INFO(("Cannot find ID %#"PRIx64"\n", i_id)); | 4010 DEBUG_INFO(("Cannot find ID %#"PRIx64"\n", i_id)); |
3922 DEBUG_RET(); | 4011 DEBUG_RET(); |
3923 return 0; | 4012 return 0; |
3924 } | 4013 } |
3925 DEBUG_INFO(("id = %#"PRIx64", record size = %#x, offset = %#x\n", i_id, rec->size, rec->offset)); | 4014 DEBUG_INFO(("id = %#"PRIx64", record size = %#x, offset = %#x\n", i_id, rec->size, rec->offset)); |
3926 rsize = pst_read_block_size(pf, rec->offset, rec->size, buf); | 4015 rsize = pst_read_block_size(pf, rec->offset, rec->size, rec->inflated_size, buf); |
3927 DEBUG_RET(); | 4016 DEBUG_RET(); |
3928 return rsize; | 4017 return rsize; |
3929 } | 4018 } |
3930 | 4019 |
3931 | 4020 |