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