17 #if defined(__GNUC__) || defined (__SUNPRO_C) || defined(__SUNPRO_CC) 21 #define ASSERT(x) { if(!(x)) raise( SIGSEGV ); } 23 #define INDEX_TYPE32 0x0E 24 #define INDEX_TYPE32A 0x0F // unknown, but assumed to be similar for now 25 #define INDEX_TYPE64 0x17 26 #define INDEX_TYPE64A 0x15 // http://sourceforge.net/projects/libpff/ 27 #define INDEX_TYPE4K 0x24 28 #define INDEX_TYPE_OFFSET (int64_t)0x0A 30 #define FILE_SIZE_POINTER32 (int64_t)0xA8 31 #define INDEX_POINTER32 (int64_t)0xC4 32 #define INDEX_BACK32 (int64_t)0xC0 33 #define SECOND_POINTER32 (int64_t)0xBC 34 #define SECOND_BACK32 (int64_t)0xB8 35 #define ENC_TYPE32 (int64_t)0x1CD 37 #define FILE_SIZE_POINTER64 (int64_t)0xB8 38 #define INDEX_POINTER64 (int64_t)0xF0 39 #define INDEX_BACK64 (int64_t)0xE8 40 #define SECOND_POINTER64 (int64_t)0xE0 41 #define SECOND_BACK64 (int64_t)0xD8 42 #define ENC_TYPE64 (int64_t)0x201 44 #define FILE_SIZE_POINTER ((pf->do_read64) ? FILE_SIZE_POINTER64 : FILE_SIZE_POINTER32) 45 #define INDEX_POINTER ((pf->do_read64) ? INDEX_POINTER64 : INDEX_POINTER32) 46 #define INDEX_BACK ((pf->do_read64) ? INDEX_BACK64 : INDEX_BACK32) 47 #define SECOND_POINTER ((pf->do_read64) ? SECOND_POINTER64 : SECOND_POINTER32) 48 #define SECOND_BACK ((pf->do_read64) ? SECOND_BACK64 : SECOND_BACK32) 49 #define ENC_TYPE ((pf->do_read64) ? ENC_TYPE64 : ENC_TYPE32) 52 #define PST_SIGNATURE 0x4E444221 210 0x47, 0xf1, 0xb4, 0xe6, 0x0b, 0x6a, 0x72, 0x48, 0x85, 0x4e, 0x9e, 0xeb, 0xe2, 0xf8, 0x94, 0x53,
211 0xe0, 0xbb, 0xa0, 0x02, 0xe8, 0x5a, 0x09, 0xab, 0xdb, 0xe3, 0xba, 0xc6, 0x7c, 0xc3, 0x10, 0xdd,
212 0x39, 0x05, 0x96, 0x30, 0xf5, 0x37, 0x60, 0x82, 0x8c, 0xc9, 0x13, 0x4a, 0x6b, 0x1d, 0xf3, 0xfb,
213 0x8f, 0x26, 0x97, 0xca, 0x91, 0x17, 0x01, 0xc4, 0x32, 0x2d, 0x6e, 0x31, 0x95, 0xff, 0xd9, 0x23,
214 0xd1, 0x00, 0x5e, 0x79, 0xdc, 0x44, 0x3b, 0x1a, 0x28, 0xc5, 0x61, 0x57, 0x20, 0x90, 0x3d, 0x83,
215 0xb9, 0x43, 0xbe, 0x67, 0xd2, 0x46, 0x42, 0x76, 0xc0, 0x6d, 0x5b, 0x7e, 0xb2, 0x0f, 0x16, 0x29,
216 0x3c, 0xa9, 0x03, 0x54, 0x0d, 0xda, 0x5d, 0xdf, 0xf6, 0xb7, 0xc7, 0x62, 0xcd, 0x8d, 0x06, 0xd3,
217 0x69, 0x5c, 0x86, 0xd6, 0x14, 0xf7, 0xa5, 0x66, 0x75, 0xac, 0xb1, 0xe9, 0x45, 0x21, 0x70, 0x0c,
218 0x87, 0x9f, 0x74, 0xa4, 0x22, 0x4c, 0x6f, 0xbf, 0x1f, 0x56, 0xaa, 0x2e, 0xb3, 0x78, 0x33, 0x50,
219 0xb0, 0xa3, 0x92, 0xbc, 0xcf, 0x19, 0x1c, 0xa7, 0x63, 0xcb, 0x1e, 0x4d, 0x3e, 0x4b, 0x1b, 0x9b,
220 0x4f, 0xe7, 0xf0, 0xee, 0xad, 0x3a, 0xb5, 0x59, 0x04, 0xea, 0x40, 0x55, 0x25, 0x51, 0xe5, 0x7a,
221 0x89, 0x38, 0x68, 0x52, 0x7b, 0xfc, 0x27, 0xae, 0xd7, 0xbd, 0xfa, 0x07, 0xf4, 0xcc, 0x8e, 0x5f,
222 0xef, 0x35, 0x9c, 0x84, 0x2b, 0x15, 0xd5, 0x77, 0x34, 0x49, 0xb6, 0x12, 0x0a, 0x7f, 0x71, 0x88,
223 0xfd, 0x9d, 0x18, 0x41, 0x7d, 0x93, 0xd8, 0x58, 0x2c, 0xce, 0xfe, 0x24, 0xaf, 0xde, 0xb8, 0x36,
224 0xc8, 0xa1, 0x80, 0xa6, 0x99, 0x98, 0xa8, 0x2f, 0x0e, 0x81, 0x65, 0x73, 0xe4, 0xc2, 0xa2, 0x8a,
225 0xd4, 0xe1, 0x11, 0xd0, 0x08, 0x8b, 0x2a, 0xf2, 0xed, 0x9a, 0x64, 0x3f, 0xc1, 0x6c, 0xf9, 0xec
231 0x41, 0x36, 0x13, 0x62, 0xa8, 0x21, 0x6e, 0xbb, 0xf4, 0x16, 0xcc, 0x04, 0x7f, 0x64, 0xe8, 0x5d,
232 0x1e, 0xf2, 0xcb, 0x2a, 0x74, 0xc5, 0x5e, 0x35, 0xd2, 0x95, 0x47, 0x9e, 0x96, 0x2d, 0x9a, 0x88,
233 0x4c, 0x7d, 0x84, 0x3f, 0xdb, 0xac, 0x31, 0xb6, 0x48, 0x5f, 0xf6, 0xc4, 0xd8, 0x39, 0x8b, 0xe7,
234 0x23, 0x3b, 0x38, 0x8e, 0xc8, 0xc1, 0xdf, 0x25, 0xb1, 0x20, 0xa5, 0x46, 0x60, 0x4e, 0x9c, 0xfb,
235 0xaa, 0xd3, 0x56, 0x51, 0x45, 0x7c, 0x55, 0x00, 0x07, 0xc9, 0x2b, 0x9d, 0x85, 0x9b, 0x09, 0xa0,
236 0x8f, 0xad, 0xb3, 0x0f, 0x63, 0xab, 0x89, 0x4b, 0xd7, 0xa7, 0x15, 0x5a, 0x71, 0x66, 0x42, 0xbf,
237 0x26, 0x4a, 0x6b, 0x98, 0xfa, 0xea, 0x77, 0x53, 0xb2, 0x70, 0x05, 0x2c, 0xfd, 0x59, 0x3a, 0x86,
238 0x7e, 0xce, 0x06, 0xeb, 0x82, 0x78, 0x57, 0xc7, 0x8d, 0x43, 0xaf, 0xb4, 0x1c, 0xd4, 0x5b, 0xcd,
239 0xe2, 0xe9, 0x27, 0x4f, 0xc3, 0x08, 0x72, 0x80, 0xcf, 0xb0, 0xef, 0xf5, 0x28, 0x6d, 0xbe, 0x30,
240 0x4d, 0x34, 0x92, 0xd5, 0x0e, 0x3c, 0x22, 0x32, 0xe5, 0xe4, 0xf9, 0x9f, 0xc2, 0xd1, 0x0a, 0x81,
241 0x12, 0xe1, 0xee, 0x91, 0x83, 0x76, 0xe3, 0x97, 0xe6, 0x61, 0x8a, 0x17, 0x79, 0xa4, 0xb7, 0xdc,
242 0x90, 0x7a, 0x5c, 0x8c, 0x02, 0xa6, 0xca, 0x69, 0xde, 0x50, 0x1a, 0x11, 0x93, 0xb9, 0x52, 0x87,
243 0x58, 0xfc, 0xed, 0x1d, 0x37, 0x49, 0x1b, 0x6a, 0xe0, 0x29, 0x33, 0x99, 0xbd, 0x6c, 0xd9, 0x94,
244 0xf3, 0x40, 0x54, 0x6f, 0xf0, 0xc6, 0x73, 0xb8, 0xd6, 0x3e, 0x65, 0x18, 0x44, 0x1f, 0xdd, 0x67,
245 0x10, 0xf1, 0x0c, 0x19, 0xec, 0xae, 0x03, 0xa1, 0x14, 0x7b, 0xa9, 0x0b, 0xff, 0xf8, 0xa3, 0xc0,
246 0xa2, 0x01, 0xf7, 0x2e, 0xbc, 0x24, 0x68, 0x75, 0x0d, 0xfe, 0xba, 0x2f, 0xb5, 0xd0, 0xda, 0x3d
252 0x14, 0x53, 0x0f, 0x56, 0xb3, 0xc8, 0x7a, 0x9c, 0xeb, 0x65, 0x48, 0x17, 0x16, 0x15, 0x9f, 0x02,
253 0xcc, 0x54, 0x7c, 0x83, 0x00, 0x0d, 0x0c, 0x0b, 0xa2, 0x62, 0xa8, 0x76, 0xdb, 0xd9, 0xed, 0xc7,
254 0xc5, 0xa4, 0xdc, 0xac, 0x85, 0x74, 0xd6, 0xd0, 0xa7, 0x9b, 0xae, 0x9a, 0x96, 0x71, 0x66, 0xc3,
255 0x63, 0x99, 0xb8, 0xdd, 0x73, 0x92, 0x8e, 0x84, 0x7d, 0xa5, 0x5e, 0xd1, 0x5d, 0x93, 0xb1, 0x57,
256 0x51, 0x50, 0x80, 0x89, 0x52, 0x94, 0x4f, 0x4e, 0x0a, 0x6b, 0xbc, 0x8d, 0x7f, 0x6e, 0x47, 0x46,
257 0x41, 0x40, 0x44, 0x01, 0x11, 0xcb, 0x03, 0x3f, 0xf7, 0xf4, 0xe1, 0xa9, 0x8f, 0x3c, 0x3a, 0xf9,
258 0xfb, 0xf0, 0x19, 0x30, 0x82, 0x09, 0x2e, 0xc9, 0x9d, 0xa0, 0x86, 0x49, 0xee, 0x6f, 0x4d, 0x6d,
259 0xc4, 0x2d, 0x81, 0x34, 0x25, 0x87, 0x1b, 0x88, 0xaa, 0xfc, 0x06, 0xa1, 0x12, 0x38, 0xfd, 0x4c,
260 0x42, 0x72, 0x64, 0x13, 0x37, 0x24, 0x6a, 0x75, 0x77, 0x43, 0xff, 0xe6, 0xb4, 0x4b, 0x36, 0x5c,
261 0xe4, 0xd8, 0x35, 0x3d, 0x45, 0xb9, 0x2c, 0xec, 0xb7, 0x31, 0x2b, 0x29, 0x07, 0x68, 0xa3, 0x0e,
262 0x69, 0x7b, 0x18, 0x9e, 0x21, 0x39, 0xbe, 0x28, 0x1a, 0x5b, 0x78, 0xf5, 0x23, 0xca, 0x2a, 0xb0,
263 0xaf, 0x3e, 0xfe, 0x04, 0x8c, 0xe7, 0xe5, 0x98, 0x32, 0x95, 0xd3, 0xf6, 0x4a, 0xe8, 0xa6, 0xea,
264 0xe9, 0xf3, 0xd5, 0x2f, 0x70, 0x20, 0xf2, 0x1f, 0x05, 0x67, 0xad, 0x55, 0x10, 0xce, 0xcd, 0xe3,
265 0x27, 0x3b, 0xda, 0xba, 0xd7, 0xc2, 0x26, 0xd4, 0x91, 0x1d, 0xd2, 0x1c, 0x22, 0x33, 0xf8, 0xfa,
266 0xf1, 0x5a, 0xef, 0xcf, 0x90, 0xb6, 0x8b, 0xb5, 0xbd, 0xc0, 0xbf, 0x08, 0x97, 0x1e, 0x6c, 0xe2,
267 0x61, 0xe0, 0xc6, 0xc1, 0x59, 0xab, 0xbb, 0x58, 0xde, 0x5f, 0xdf, 0x60, 0x79, 0x7e, 0xb2, 0x8a
271 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);
273 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);
298 static int pst_decrypt(uint64_t i_id,
char *buf,
size_t size,
unsigned char type);
305 #ifdef HAVE_GET_CURRENT_DIR_NAME 306 cwd = get_current_dir_name();
309 getcwd(cwd, PATH_MAX+1);
323 WARN ((
"cannot be passed a NULL pst_file\n"));
327 memset(pf, 0,
sizeof(*pf));
330 if ((pf->
fp = fopen(name,
"rb")) == NULL) {
331 perror(
"Error opening PST file");
337 if (
pst_getAtPos(pf, 0, &sig,
sizeof(sig)) !=
sizeof(sig)) {
338 (void)fclose(pf->
fp);
339 DEBUG_WARN((
"cannot read signature from PST file. Closing with error\n"));
346 (void)fclose(pf->
fp);
347 DEBUG_WARN((
"not a PST file that I know. Closing with error\n"));
368 (void)fclose(pf->
fp);
369 DEBUG_WARN((
"unknown .pst format, possibly newer than Outlook 2003 PST file?\n"));
390 pf->
fname = strdup(name);
398 if (cwd == NULL)
return -1;
399 if (chdir(pf->
cwd))
goto err;
400 if (!freopen(pf->
fname,
"rb", pf->
fp))
goto err;
401 if (chdir(cwd))
goto err;
420 if (fclose(pf->
fp)) {
421 DEBUG_WARN((
"fclose returned non-zero value\n"));
451 if (*tail) (*tail)->next = node;
452 if (!(*head)) *head = node;
481 DEBUG_INFO((
"Found orphan child %#"PRIx64
" of parent %#"PRIx64
"\n", n->
d_id, node->
d_id));
504 DEBUG_INFO((
"%#"PRIx64
" is its own parent. What is this world coming to?\n", node->
d_id));
534 if (!head)
return NULL;
549 DEBUG_INFO((
"There isn't a top of folder record here.\n"));
560 DEBUG_INFO((
"looking for top of folder descriptor %#"PRIx32
"\n", topid));
565 topnode->
d_id = topid;
568 topnode->
desc = NULL;
583 if ((!attach->
data.
data) && (attach->
i_id != (uint64_t)-1)) {
588 DEBUG_WARN((
"Couldn't find ID pointer. Cannot handle attachment\n"));
605 if ((!attach->
data.
data) && (attach->
i_id != (uint64_t)-1)) {
610 DEBUG_WARN((
"Couldn't find ID pointer. Cannot save attachment to file\n"));
629 if ((!attach->
data.
data) && (attach->
i_id != (uint64_t)-1)) {
634 DEBUG_WARN((
"Couldn't find ID pointer. Cannot save attachment to Base64\n"));
642 (void)
pst_fwrite(c, (
size_t)1, strlen(c), fp);
656 DEBUG_WARN((
"Cannot load index for a NULL pst_file\n"));
665 DEBUG_INFO((
"build desc ptr returns %i\n", x));
678 if ((r = d->
child) == NULL) {
703 char *buffer=NULL, *headerbuffer=NULL;
704 size_t bsize=0, hsize=0, bptr=0;
712 DEBUG_WARN((
"Cannot find d_id 0x61 for loading the Extended Attributes\n"));
718 DEBUG_WARN((
"descriptor is NULL for d_id 0x61. Cannot load Extended Attributes\n"));
727 DEBUG_WARN((
"Have not been able to fetch any id2 values for d_id 0x61. Brace yourself!\n"));
732 DEBUG_WARN((
"Cannot process desc block for item 0x61. Not loading extended Attributes\n"));
738 DEBUG_INFO((
"look through d_id 0x61 list of mapi objects\n"));
757 DEBUG_WARN((
"No extended attributes buffer found. Not processing\n"));
762 while (bptr < bsize) {
768 memset(ptr, 0,
sizeof(*ptr));
769 ptr->
map = xattrib.
map+0x8000;
771 DEBUG_INFO((
"xattrib: ext = %#"PRIx32
", type = %#"PRIx16
", map = %#"PRIx16
"\n",
773 if (xattrib.
type & 0x0001) {
778 memcpy(&tint, &(headerbuffer[xattrib.
extended]),
sizeof(tint));
781 memset(wt, 0, (
size_t)(tint+2));
782 memcpy(wt, &(headerbuffer[xattrib.
extended+
sizeof(tint)]), (
size_t)tint);
794 memset(ptr->
data, 0,
sizeof(uint32_t));
797 DEBUG_INFO((
"Mapped attribute %#"PRIx32
" to %#"PRIx32
"\n", ptr->
map, *((uint32_t*)ptr->
data)));
804 while (p_sh && (ptr->
map > p_sh->
map)) {
829 #define ITEM_COUNT_OFFSET32 0x1f0 // count byte 830 #define MAX_COUNT_OFFSET32 0x1f1 831 #define ENTRY_SIZE_OFFSET32 0x1f2 832 #define LEVEL_INDICATOR_OFFSET32 0x1f3 // node or leaf 833 #define BACKLINK_OFFSET32 0x1f8 // backlink u1 value 835 #define ITEM_COUNT_OFFSET64 0x1e8 // count byte 836 #define MAX_COUNT_OFFSET64 0x1e9 837 #define ENTRY_SIZE_OFFSET64 0x1ea // node or leaf 838 #define LEVEL_INDICATOR_OFFSET64 0x1eb // node or leaf 839 #define BACKLINK_OFFSET64 0x1f8 // backlink u1 value 841 #define ITEM_COUNT_OFFSET4K 0xfd8 842 #define MAX_COUNT_OFFSET4K 0xfda 843 #define ENTRY_SIZE_OFFSET4K 0xfdc 844 #define LEVEL_INDICATOR_OFFSET4K 0xfdd 845 #define BACKLINK_OFFSET4K 0xff0 847 #define BLOCK_SIZE (size_t)((pf->do_read64 == 2) ? 4096 : 512) // index blocks 848 #define DESC_BLOCK_SIZE (size_t)((pf->do_read64 == 2) ? 4096 : 512) // descriptor blocks 849 #define ITEM_COUNT_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? ITEM_COUNT_OFFSET4K : ITEM_COUNT_OFFSET64) : ITEM_COUNT_OFFSET32) 850 #define LEVEL_INDICATOR_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? LEVEL_INDICATOR_OFFSET4K : LEVEL_INDICATOR_OFFSET64) : LEVEL_INDICATOR_OFFSET32) 851 #define BACKLINK_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? BACKLINK_OFFSET4K : BACKLINK_OFFSET64) : BACKLINK_OFFSET32) 852 #define ENTRY_SIZE_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? ENTRY_SIZE_OFFSET4K : ENTRY_SIZE_OFFSET64) : ENTRY_SIZE_OFFSET32) 853 #define MAX_COUNT_OFFSET (size_t)((pf->do_read64) ? (pf->do_read64 == 2 ? MAX_COUNT_OFFSET4K : MAX_COUNT_OFFSET64) : MAX_COUNT_OFFSET32) 855 #define read_twobyte(BUF, OFF) (int32_t) ((((unsigned)BUF[OFF + 1] & 0xFF)) << 8) | ((unsigned)BUF[OFF] & 0xFF); 863 memcpy(desc, buf,
sizeof(
pst_desc));
944 index->
id = index64.
id;
948 index->
u0 = index64.
u0;
949 index->
u1 = index64.
u1;
960 index->
id = index32.
id;
965 index->
u1 = index32.
u1;
992 assoc->
id = assoc32.
id;
1016 table3_rec->
id = table3_rec32.
id;
1033 int32_t x, item_count, count_max;
1034 uint64_t old = start_val;
1035 char *buf = NULL, *bptr;
1038 DEBUG_INFO((
"offset %#"PRIx64
" depth %i linku1 %#"PRIx64
" start %#"PRIx64
" end %#"PRIx64
"\n",
offset, depth, linku1, start_val, end_val));
1039 if (end_val <= start_val) {
1040 DEBUG_WARN((
"The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64
", end:%#"PRIx64
"]\n", start_val, end_val));
1060 if (item_count > count_max) {
1061 DEBUG_WARN((
"Item count %i too large, max is %i\n", item_count, count_max));
1067 if (index.
id != linku1) {
1068 DEBUG_WARN((
"Backlink %#"PRIx64
" in this node does not match required %#"PRIx64
"\n", index.
id, linku1));
1074 DEBUG_INFO((
"count %#"PRIx64
" max %#"PRIx64
" size %#"PRIx64
"\n", item_count, count_max, entry_size));
1078 while (x < item_count) {
1082 if (index.
id == 0)
break;
1083 DEBUG_INFO((
"[%i]%i Item [id = %#"PRIx64
", offset = %#"PRIx64
", u1 = %#x, size = %i(%#x)]\n",
1086 if ((index.
id >= end_val) || (index.
id < old)) {
1087 DEBUG_WARN((
"This item isn't right. Must be corruption, or I got it wrong!\n"));
1099 i_ptr->offset = index.
offset;
1100 i_ptr->u1 = index.
u1;
1101 i_ptr->size = index.
size;
1107 while (x < item_count) {
1111 if (table.
start == 0)
break;
1112 if (x < item_count) {
1116 table2.
start = end_val;
1118 DEBUG_INFO((
"[%i] %i Index Table [start id = %#"PRIx64
", u1 = %#"PRIx64
", offset = %#"PRIx64
", end id = %#"PRIx64
"]\n",
1120 if ((table.
start >= end_val) || (table.
start < old)) {
1121 DEBUG_WARN((
"This table isn't right. Must be corruption, or I got it wrong!\n"));
1130 if (buf) free (buf);
1143 int32_t item_count, count_max;
1144 uint64_t old = start_val;
1146 char *buf = NULL, *bptr;
1149 DEBUG_INFO((
"offset %#"PRIx64
" depth %i linku1 %#"PRIx64
" start %#"PRIx64
" end %#"PRIx64
"\n",
offset, depth, linku1, start_val, end_val));
1150 if (end_val <= start_val) {
1151 DEBUG_WARN((
"The end value is BEFORE the start value. This function will quit. Soz. [start:%#"PRIx64
", end:%#"PRIx64
"]\n", start_val, end_val));
1171 if (desc_rec.d_id != linku1) {
1172 DEBUG_WARN((
"Backlink %#"PRIx64
" in this node does not match required %#"PRIx64
"\n", desc_rec.d_id, linku1));
1181 if (item_count > count_max) {
1182 DEBUG_WARN((
"Item count %i too large, max is %i\n", item_count, count_max));
1187 for (x=0; x<item_count; x++) {
1190 DEBUG_INFO((
"[%i] Item(%#x) = [d_id = %#"PRIx64
", desc_id = %#"PRIx64
", tree_id = %#"PRIx64
", parent_d_id = %#x]\n",
1191 depth, x, desc_rec.d_id, desc_rec.desc_id, desc_rec.tree_id, desc_rec.parent_d_id));
1192 if ((desc_rec.d_id >= end_val) || (desc_rec.d_id < old)) {
1193 DEBUG_WARN((
"This item isn't right. Must be corruption, or I got it wrong!\n"));
1199 old = desc_rec.d_id;
1200 DEBUG_INFO((
"New Record %#"PRIx64
" with parent %#x\n", desc_rec.d_id, desc_rec.parent_d_id));
1203 d_ptr->
d_id = desc_rec.d_id;
1213 if (item_count > count_max) {
1214 DEBUG_WARN((
"Item count %i too large, max is %i\n", item_count, count_max));
1219 for (x=0; x<item_count; x++) {
1222 if (table.
start == 0)
break;
1223 if (x < (item_count-1)) {
1227 table2.
start = end_val;
1229 DEBUG_INFO((
"[%i] %i Descriptor Table [start id = %#"PRIx64
", u1 = %#"PRIx64
", offset = %#"PRIx64
", end id = %#"PRIx64
"]\n",
1231 if ((table.
start >= end_val) || (table.
start < old)) {
1232 DEBUG_WARN((
"This table isn't right. Must be corruption, or I got it wrong!\n"));
1258 DEBUG_WARN((
"you cannot pass me a NULL! I don't want it!\n"));
1264 DEBUG_WARN((
"why is d_ptr->desc == NULL? I don't want to do anything else with this record\n"));
1271 DEBUG_WARN((
"supplied master head, but have a list that is building a new id2_head\n"));
1280 DEBUG_WARN((
"pst_parse_block() returned an error for d_ptr->desc->i_id [%#"PRIx64
"]\n", d_ptr->
desc->
i_id));
1291 DEBUG_WARN((
"pst_process() returned non-zero value. That is an error\n"));
1300 if ((id2_ptr =
pst_getID2(id2_head, (uint64_t)0x692))) {
1312 DEBUG_WARN((
"ERROR pst_process() failed with DSN/MDN attachments\n"));
1321 DEBUG_WARN((
"ERROR error processing main DSN/MDN record\n"));
1328 if ((id2_ptr =
pst_getID2(id2_head, (uint64_t)0x671))) {
1329 DEBUG_INFO((
"ATTACHMENT processing attachment\n"));
1334 DEBUG_WARN((
"ERROR error processing main attachment record\n"));
1347 DEBUG_WARN((
"ERROR pst_process() failed with attachments\n"));
1359 for (attach = item->
attach; attach; attach = attach->
next) {
1362 DEBUG_WARN((
"initial attachment id2 found id %#"PRIx64
"\n", id2_ptr->
id->
i_id));
1368 DEBUG_WARN((
"ERROR error processing an attachment record\n"));
1372 DEBUG_WARN((
"ERROR probably fatal, list count array will overrun attach structure.\n"));
1377 DEBUG_WARN((
"ERROR pst_process() failed with an attachment\n"));
1386 DEBUG_WARN((
"second pass attachment updating id2 %#"PRIx64
" found i_id %#"PRIx64
"\n", attach->
id2_val, id2_ptr->
id->
i_id));
1391 DEBUG_WARN((
"have not located the correct value for the attachment [%#"PRIx64
"]\n", attach->
id2_val));
1443 size_t read_size = 0;
1454 int32_t num_mapi_objects;
1455 int32_t count_mapi_objects;
1456 int32_t num_mapi_elements;
1457 int32_t count_mapi_elements;
1459 uint32_t rec_size = 0;
1463 char* ind2_end = NULL;
1464 char* ind2_ptr = NULL;
1465 char* ind2_block_start = NULL;
1466 size_t ind2_max_block_size = pf->
do_read64 ? 0x1FF0 : 0x1FF4;
1472 unsigned char seven_c;
1473 unsigned char item_count;
1478 uint32_t b_five_offset;
1479 uint32_t ind2_offset;
1484 struct _type_d_rec {
1505 DEBUG_WARN((
"Error reading block id %#"PRIx64
"\n", block_id));
1506 if (buf) free (buf);
1519 memcpy(&block_hdr, buf,
sizeof(block_hdr));
1527 char *b_ptr = buf + 8;
1535 memcpy(&block_hdr, subblocks.
subs[i].
buf,
sizeof(block_hdr));
1545 memcpy(&block_hdr, subblocks.
subs[0].
buf,
sizeof(block_hdr));
1560 if (block_hdr.
type == (uint16_t)0xBCEC) {
1564 DEBUG_WARN((
"internal error (bc.b5 offset %#x) in reading block id %#"PRIx64
"\n", block_hdr.
offset, block_id));
1565 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1569 memcpy(&table_rec, block_offset1.
from,
sizeof(table_rec));
1573 DEBUG_INFO((
"table_rec (type=%#hx, ref_type=%#hx, value=%#x)\n", table_rec.type, table_rec.ref_type, table_rec.value));
1575 if ((table_rec.type != (uint16_t)0x02B5) || (table_rec.ref_type != 6)) {
1576 DEBUG_WARN((
"Unknown second block constant - %#hx %#hx for id %#"PRIx64
"\n", table_rec.type, table_rec.ref_type, block_id));
1577 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1583 DEBUG_WARN((
"internal error (bc.b5.desc offset #x) in reading block id %#"PRIx64
"\n", table_rec.value, block_id));
1584 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1588 list_start = block_offset2.
from;
1589 to_ptr = block_offset2.
to;
1590 num_mapi_elements = (to_ptr - list_start)/
sizeof(table_rec);
1591 num_mapi_objects = 1;
1593 else if (block_hdr.
type == (uint16_t)0x7CEC) {
1597 DEBUG_WARN((
"internal error (7c.7c offset %#x) in reading block id %#"PRIx64
"\n", block_hdr.
offset, block_id));
1598 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1602 fr_ptr = block_offset3.
from;
1603 memset(&seven_c_blk, 0,
sizeof(seven_c_blk));
1604 memcpy(&seven_c_blk, fr_ptr,
sizeof(seven_c_blk));
1609 LE32_CPU(seven_c_blk.b_five_offset);
1614 list_start = fr_ptr +
sizeof(seven_c_blk);
1616 if (seven_c_blk.seven_c != 0x7C) {
1617 DEBUG_WARN((
"Error. There isn't a 7C where I want to see 7C!\n"));
1618 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1623 rec_size = seven_c_blk.rec_size;
1624 num_mapi_elements = (int32_t)(
unsigned)seven_c_blk.item_count;
1627 DEBUG_WARN((
"internal error (7c.b5 offset %#x) in reading block id %#"PRIx64
"\n", seven_c_blk.b_five_offset, block_id));
1628 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1632 memcpy(&table_rec, block_offset4.
from,
sizeof(table_rec));
1636 DEBUG_INFO((
"table_rec (type=%#hx, ref_type=%#hx, value=%#x)\n", table_rec.type, table_rec.ref_type, table_rec.value));
1638 if (table_rec.type != (uint16_t)0x04B5) {
1639 DEBUG_WARN((
"Unknown second block constant - %#hx for id %#"PRIx64
"\n", table_rec.type, block_id));
1640 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1645 if (table_rec.value > 0) {
1647 DEBUG_WARN((
"internal error (7c.b5.desc offset %#x) in reading block id %#"PRIx64
"\n", table_rec.value, block_id));
1648 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1654 num_mapi_objects = (block_offset5.
to - block_offset5.
from) / (4 + table_rec.ref_type);
1657 DEBUG_WARN((
"internal error (7c.ind2 offset %#x) in reading block id %#"PRIx64
"\n", seven_c_blk.ind2_offset, block_id));
1658 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1662 ind2_ptr = block_offset6.
from;
1663 ind2_block_start = ind2_ptr;
1664 ind2_end = block_offset6.
to;
1667 num_mapi_objects = 0;
1669 DEBUG_INFO((
"7cec block index2 pointer %#x and end %#x\n", ind2_ptr, ind2_end));
1672 DEBUG_WARN((
"ERROR: Unknown block constant - %#hx for id %#"PRIx64
"\n", block_hdr.
type, block_id));
1673 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1678 DEBUG_INFO((
"found %i mapi objects each with %i mapi elements\n", num_mapi_objects, num_mapi_elements));
1679 for (count_mapi_objects=0; count_mapi_objects<num_mapi_objects; count_mapi_objects++) {
1683 mo_ptr->
next = mo_head;
1690 for (x=0; x<num_mapi_elements; x++) mo_ptr->
elements[x] = NULL;
1692 DEBUG_INFO((
"going to read %i mapi elements for mapi object %i\n", num_mapi_elements, count_mapi_objects));
1694 fr_ptr = list_start;
1696 for (count_mapi_elements=0; count_mapi_elements<num_mapi_elements; count_mapi_elements++) {
1697 char* value_pointer = NULL;
1698 size_t value_size = 0;
1699 if (block_type == 1) {
1700 memcpy(&table_rec, fr_ptr,
sizeof(table_rec));
1704 fr_ptr +=
sizeof(table_rec);
1705 }
else if (block_type == 2) {
1707 memcpy(&table2_rec, fr_ptr,
sizeof(table2_rec));
1711 DEBUG_INFO((
"reading element %i (type=%#x, ref_type=%#x, offset=%#x, size=%#x)\n",
1712 x, table2_rec.type, table2_rec.ref_type, table2_rec.ind2_off, table2_rec.size));
1715 table_rec.type = table2_rec.type;
1716 table_rec.ref_type = table2_rec.ref_type;
1717 table_rec.value = 0;
1718 if ((ind2_end - ind2_ptr) >= (
int)(table2_rec.ind2_off + table2_rec.size)) {
1719 size_t n = table2_rec.size;
1720 size_t m =
sizeof(table_rec.value);
1722 memcpy(&table_rec.value, ind2_ptr + table2_rec.ind2_off, n);
1725 value_pointer = ind2_ptr + table2_rec.ind2_off;
1731 DEBUG_WARN ((
"Trying to read outside buffer, buffer size %#x, offset %#x, data size %#x\n",
1732 read_size, ind2_end-ind2_ptr+table2_rec.ind2_off, table2_rec.size));
1734 fr_ptr +=
sizeof(table2_rec);
1736 DEBUG_WARN((
"Missing code for block_type %i\n", block_type));
1737 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1742 DEBUG_INFO((
"reading element %i (type=%#x, ref_type=%#x, value=%#x)\n",
1743 x, table_rec.type, table_rec.ref_type, table_rec.value));
1752 while (mapptr && (mapptr->
map < table_rec.type)) mapptr = mapptr->
next;
1753 if (mapptr && (mapptr->
map == table_rec.type)) {
1758 DEBUG_INFO((
"Internet Header mapping found %#"PRIx32
" to %s\n", table_rec.type, mapptr->
data));
1792 if (table_rec.ref_type == (uint16_t)0x0002 ||
1793 table_rec.ref_type == (uint16_t)0x0003 ||
1794 table_rec.ref_type == (uint16_t)0x000b) {
1799 memcpy(mo_ptr->
elements[x]->
data, &(table_rec.value),
sizeof(int32_t));
1803 }
else if (table_rec.ref_type == (uint16_t)0x0005 ||
1804 table_rec.ref_type == (uint16_t)0x000d ||
1805 table_rec.ref_type == (uint16_t)0x0014 ||
1806 table_rec.ref_type == (uint16_t)0x001e ||
1807 table_rec.ref_type == (uint16_t)0x001f ||
1808 table_rec.ref_type == (uint16_t)0x0040 ||
1809 table_rec.ref_type == (uint16_t)0x0048 ||
1810 table_rec.ref_type == (uint16_t)0x0102 ||
1811 table_rec.ref_type == (uint16_t)0x1003 ||
1812 table_rec.ref_type == (uint16_t)0x1014 ||
1813 table_rec.ref_type == (uint16_t)0x101e ||
1814 table_rec.ref_type == (uint16_t)0x101f ||
1815 table_rec.ref_type == (uint16_t)0x1102) {
1818 if (value_pointer) {
1824 memcpy(mo_ptr->
elements[x]->
data, value_pointer, value_size);
1827 if ((table_rec.value & 0xf) == (uint32_t)0xf) {
1828 DEBUG_WARN((
"failed to get block offset for table_rec.value of %#x to be read later.\n", table_rec.value));
1834 if (table_rec.value) {
1835 DEBUG_WARN((
"failed to get block offset for table_rec.value of %#x\n", table_rec.value));
1842 value_size = (size_t)(block_offset7.
to - block_offset7.
from);
1849 if (table_rec.ref_type == (uint16_t)0xd) {
1851 type_d_rec = (
struct _type_d_rec*) mo_ptr->
elements[x]->
data;
1855 DEBUG_WARN((
"not able to read the ID2 data. Setting to be read later. %#x\n", type_d_rec->id));
1861 if (table_rec.ref_type == (uint16_t)0x1f) {
1866 if (!utf16buf) utf16buf =
pst_vballoc((
size_t)1024);
1867 if (!utf8buf) utf8buf =
pst_vballoc((
size_t)1024);
1875 if (rc == (
size_t)-1) {
1876 DEBUG_WARN((
"Failed to convert utf-16 to utf-8\n"));
1889 DEBUG_WARN((
"ERROR Unknown ref_type %#hx\n", table_rec.ref_type));
1893 DEBUG_INFO((
"increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n", rec_size, rec_size, ind2_ptr, ind2_ptr+rec_size));
1894 ind2_ptr += rec_size;
1896 if (ind2_ptr + rec_size > ind2_block_start + ind2_max_block_size) {
1897 ind2_block_start += ind2_max_block_size;
1898 DEBUG_INFO((
"advancing ind2_ptr to next block. Was %#x, Now %#x\n", ind2_ptr, ind2_block_start));
1899 ind2_ptr = ind2_block_start;
1902 freeall(&subblocks, &block_offset1, &block_offset2, &block_offset3, &block_offset4, &block_offset5, &block_offset6, &block_offset7);
1909 #define SAFE_FREE(x) {if (x) free(x);} 1910 #define SAFE_FREE_STR(x) SAFE_FREE(x.str) 1911 #define SAFE_FREE_BIN(x) SAFE_FREE(x.data) 1914 #define MALLOC_EMAIL(x) { if (!x->email) { x->email = (pst_item_email*) pst_malloc(sizeof(pst_item_email)); memset(x->email, 0, sizeof(pst_item_email) );} } 1915 #define MALLOC_FOLDER(x) { if (!x->folder) { x->folder = (pst_item_folder*) pst_malloc(sizeof(pst_item_folder)); memset(x->folder, 0, sizeof(pst_item_folder) );} } 1916 #define MALLOC_CONTACT(x) { if (!x->contact) { x->contact = (pst_item_contact*) pst_malloc(sizeof(pst_item_contact)); memset(x->contact, 0, sizeof(pst_item_contact) );} } 1917 #define MALLOC_MESSAGESTORE(x) { if (!x->message_store) { x->message_store = (pst_item_message_store*) pst_malloc(sizeof(pst_item_message_store)); memset(x->message_store, 0, sizeof(pst_item_message_store));} } 1918 #define MALLOC_JOURNAL(x) { if (!x->journal) { x->journal = (pst_item_journal*) pst_malloc(sizeof(pst_item_journal)); memset(x->journal, 0, sizeof(pst_item_journal) );} } 1919 #define MALLOC_APPOINTMENT(x) { if (!x->appointment) { x->appointment = (pst_item_appointment*) pst_malloc(sizeof(pst_item_appointment)); memset(x->appointment, 0, sizeof(pst_item_appointment) );} } 1922 #define LIST_COPY(targ, type) { \ 1923 targ = type pst_realloc(targ, list->elements[x]->size+1); \ 1924 memcpy(targ, list->elements[x]->data, list->elements[x]->size);\ 1925 memset(((char*)targ)+list->elements[x]->size, 0, (size_t)1); \ 1928 #define LIST_COPY_CSTR(targ) { \ 1929 if ((list->elements[x]->type == 0x1f) || \ 1930 (list->elements[x]->type == 0x1e) || \ 1931 (list->elements[x]->type == 0x102)) { \ 1932 LIST_COPY(targ, (char*)) \ 1935 DEBUG_WARN(("src not 0x1e or 0x1f or 0x102 for string dst\n")); \ 1936 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ 1942 #define LIST_COPY_BOOL(label, targ) { \ 1943 if (list->elements[x]->type != 0x0b) { \ 1944 DEBUG_WARN(("src not 0x0b for boolean dst\n")); \ 1945 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ 1947 if (*(int16_t*)list->elements[x]->data) { \ 1948 DEBUG_INFO((label" - True\n")); \ 1951 DEBUG_INFO((label" - False\n")); \ 1956 #define LIST_COPY_EMAIL_BOOL(label, targ) { \ 1957 MALLOC_EMAIL(item); \ 1958 LIST_COPY_BOOL(label, targ) \ 1961 #define LIST_COPY_CONTACT_BOOL(label, targ) { \ 1962 MALLOC_CONTACT(item); \ 1963 LIST_COPY_BOOL(label, targ) \ 1966 #define LIST_COPY_APPT_BOOL(label, targ) { \ 1967 MALLOC_APPOINTMENT(item); \ 1968 LIST_COPY_BOOL(label, targ) \ 1971 #define LIST_COPY_INT16_N(targ) { \ 1972 if (list->elements[x]->type != 0x02) { \ 1973 DEBUG_WARN(("src not 0x02 for int16 dst\n")); \ 1974 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ 1976 memcpy(&(targ), list->elements[x]->data, sizeof(targ)); \ 1980 #define LIST_COPY_INT16(label, targ) { \ 1981 LIST_COPY_INT16_N(targ); \ 1982 DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \ 1985 #define LIST_COPY_INT32_N(targ) { \ 1986 if (list->elements[x]->type != 0x03) { \ 1987 DEBUG_WARN(("src not 0x03 for int32 dst\n")); \ 1988 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ 1990 memcpy(&(targ), list->elements[x]->data, sizeof(targ)); \ 1994 #define LIST_COPY_INT32(label, targ) { \ 1995 LIST_COPY_INT32_N(targ); \ 1996 DEBUG_INFO((label" - %i %#x\n", (int)targ, (int)targ)); \ 1999 #define LIST_COPY_EMAIL_INT32(label, targ) { \ 2000 MALLOC_EMAIL(item); \ 2001 LIST_COPY_INT32(label, targ); \ 2004 #define LIST_COPY_APPT_INT32(label, targ) { \ 2005 MALLOC_APPOINTMENT(item); \ 2006 LIST_COPY_INT32(label, targ); \ 2009 #define LIST_COPY_FOLDER_INT32(label, targ) { \ 2010 MALLOC_FOLDER(item); \ 2011 LIST_COPY_INT32(label, targ); \ 2014 #define LIST_COPY_STORE_INT32(label, targ) { \ 2015 MALLOC_MESSAGESTORE(item); \ 2016 LIST_COPY_INT32(label, targ); \ 2019 #define LIST_COPY_ENUM(label, targ, delta, count, ...) { \ 2020 char *tlabels[] = {__VA_ARGS__}; \ 2021 LIST_COPY_INT32_N(targ); \ 2023 DEBUG_INFO((label" - %s [%i]\n", \ 2024 (((int)targ < 0) || ((int)targ >= count)) \ 2026 : tlabels[(int)targ], (int)targ)); \ 2029 #define LIST_COPY_EMAIL_ENUM(label, targ, delta, count, ...) { \ 2030 MALLOC_EMAIL(item); \ 2031 LIST_COPY_ENUM(label, targ, delta, count, __VA_ARGS__); \ 2034 #define LIST_COPY_APPT_ENUM(label, targ, delta, count, ...) { \ 2035 MALLOC_APPOINTMENT(item); \ 2036 LIST_COPY_ENUM(label, targ, delta, count, __VA_ARGS__); \ 2039 #define LIST_COPY_ENUM16(label, targ, delta, count, ...) { \ 2040 char *tlabels[] = {__VA_ARGS__}; \ 2041 LIST_COPY_INT16_N(targ); \ 2043 DEBUG_INFO((label" - %s [%i]\n", \ 2044 (((int)targ < 0) || ((int)targ >= count)) \ 2046 : tlabels[(int)targ], (int)targ)); \ 2049 #define LIST_COPY_CONTACT_ENUM16(label, targ, delta, count, ...) { \ 2050 MALLOC_CONTACT(item); \ 2051 LIST_COPY_ENUM16(label, targ, delta, count, __VA_ARGS__); \ 2054 #define LIST_COPY_ENTRYID(label, targ) { \ 2055 LIST_COPY(targ, (pst_entryid*)); \ 2056 LE32_CPU(targ->u1); \ 2057 LE32_CPU(targ->id); \ 2058 DEBUG_INFO((label" u1=%#x, id=%#x\n", targ->u1, targ->id)); \ 2061 #define LIST_COPY_EMAIL_ENTRYID(label, targ) { \ 2062 MALLOC_EMAIL(item); \ 2063 LIST_COPY_ENTRYID(label, targ); \ 2066 #define LIST_COPY_STORE_ENTRYID(label, targ) { \ 2067 MALLOC_MESSAGESTORE(item); \ 2068 LIST_COPY_ENTRYID(label, targ); \ 2074 #define LIST_COPY_STR(label, targ) { \ 2075 LIST_COPY_CSTR(targ.str); \ 2076 targ.is_utf8 = (list->elements[x]->type == 0x1f) ? 1 : 0; \ 2077 DEBUG_INFO((label" - unicode %d - %s\n", targ.is_utf8, targ.str)); \ 2080 #define LIST_COPY_EMAIL_STR(label, targ) { \ 2081 MALLOC_EMAIL(item); \ 2082 LIST_COPY_STR(label, targ); \ 2085 #define LIST_COPY_CONTACT_STR(label, targ) { \ 2086 MALLOC_CONTACT(item); \ 2087 LIST_COPY_STR(label, targ); \ 2090 #define LIST_COPY_APPT_STR(label, targ) { \ 2091 MALLOC_APPOINTMENT(item); \ 2092 LIST_COPY_STR(label, targ); \ 2095 #define LIST_COPY_JOURNAL_STR(label, targ) { \ 2096 MALLOC_JOURNAL(item); \ 2097 LIST_COPY_STR(label, targ); \ 2101 #define LIST_COPY_TIME(label, targ) { \ 2102 if ((list->elements[x]->type != 0x40) || \ 2103 (list->elements[x]->size != sizeof(FILETIME))) { \ 2104 DEBUG_WARN(("src not 0x40 or wrong length for filetime dst\n")); \ 2105 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); \ 2108 targ = (FILETIME*) pst_realloc(targ, sizeof(FILETIME)); \ 2109 memcpy(targ, list->elements[x]->data, sizeof(FILETIME)); \ 2110 LE32_CPU(targ->dwLowDateTime); \ 2111 LE32_CPU(targ->dwHighDateTime); \ 2112 DEBUG_INFO((label" - %s", pst_fileTimeToAscii(targ, time_buffer))); \ 2116 #define LIST_COPY_EMAIL_TIME(label, targ) { \ 2117 MALLOC_EMAIL(item); \ 2118 LIST_COPY_TIME(label, targ); \ 2121 #define LIST_COPY_CONTACT_TIME(label, targ) { \ 2122 MALLOC_CONTACT(item); \ 2123 LIST_COPY_TIME(label, targ); \ 2126 #define LIST_COPY_APPT_TIME(label, targ) { \ 2127 MALLOC_APPOINTMENT(item); \ 2128 LIST_COPY_TIME(label, targ); \ 2131 #define LIST_COPY_JOURNAL_TIME(label, targ) { \ 2132 MALLOC_JOURNAL(item); \ 2133 LIST_COPY_TIME(label, targ); \ 2137 #define LIST_COPY_BIN(targ) { \ 2138 targ.size = list->elements[x]->size; \ 2140 targ.data = (char*)pst_realloc(targ.data, targ.size); \ 2141 memcpy(targ.data, list->elements[x]->data, targ.size); \ 2144 SAFE_FREE_BIN(targ); \ 2149 #define LIST_COPY_EMAIL_BIN(label, targ) { \ 2150 MALLOC_EMAIL(item); \ 2151 LIST_COPY_BIN(targ); \ 2152 DEBUG_INFO((label"\n")); \ 2154 #define LIST_COPY_APPT_BIN(label, targ) { \ 2155 MALLOC_APPOINTMENT(item); \ 2156 LIST_COPY_BIN(targ); \ 2157 DEBUG_INFO((label"\n")); \ 2158 DEBUG_HEXDUMP(targ.data, targ.size); \ 2161 #define NULL_CHECK(x) { if (!x) { DEBUG_WARN(("NULL_CHECK: Null Found\n")); break;} } 2190 char time_buffer[30];
2201 int32_t string_length, i, offset, next_offset;
2204 for (i = 1; i <= array_element_count; i++) {
2209 string_length = next_offset - offset;
2212 ef->
value[string_length] =
'\0';
2229 if (strcmp(ef->
field_name,
"content-type") == 0) {
2230 char *p = strstr(ef->
value,
"charset=\"");
2233 char *pp = strchr(p,
'"');
2236 char *
set = strdup(p);
2241 DEBUG_INFO((
"body charset %s from content-type extra field\n",
set));
2265 DEBUG_INFO((
"Extended Attributes Table - NOT PROCESSED\n"));
2323 "None",
"Personal",
"Private",
"Company Confidential");
2330 "None",
"Personal",
"Private",
"Company Confidential");
2352 DEBUG_INFO((
"Recipient Structure 1 -- NOT PROCESSED\n"));
2358 DEBUG_INFO((
"Sent on behalf of Structure 1 -- NOT PROCESSED\n"));
2364 DEBUG_INFO((
"Received on behalf of Structure -- NOT PROCESSED\n"));
2370 DEBUG_INFO((
"Reply-To Structure -- NOT PROCESSED\n"));
2439 DEBUG_INFO((
"Non-Receipt Notification Requested -- NOT PROCESSED\n"));
2445 DEBUG_INFO((
"Sender Structure 2 -- NOT PROCESSED\n"));
2641 DEBUG_INFO((
"Seen a Reference. The data hasn't been loaded yet. [%#"PRIx64
"]\n", attach->
id2_val));
2655 "Attach By Reference",
2656 "Attach by Reference Resolve",
2657 "Attach by Reference Only",
2688 DEBUG_INFO((
"Contact Alternate Recipient - NOT PROCESSED\n"));
2736 DEBUG_INFO((
"Original Entry ID - NOT PROCESSED\n"));
2739 DEBUG_INFO((
"Original Display Name - NOT PROCESSED\n"));
2742 DEBUG_INFO((
"Original Search Key - NOT PROCESSED\n"));
2784 DEBUG_INFO((
"User Certificate - NOT PROCESSED\n"));
2886 DEBUG_INFO((
"Children's Names - NOT PROCESSED\n"));
3023 "Free",
"Tentative",
"Busy",
"Out Of Office");
3043 "Needs Preparation",
3124 }
else if (list->
elements[x]->
type == (uint32_t)0x0003) {
3128 }
else if (list->
elements[x]->
type == (uint32_t)0x0004) {
3133 }
else if (list->
elements[x]->
type == (uint32_t)0x0005) {
3138 }
else if (list->
elements[x]->
type == (uint32_t)0x0006) {
3143 }
else if (list->
elements[x]->
type == (uint32_t)0x0007) {
3148 }
else if (list->
elements[x]->
type == (uint32_t)0x000a) {
3152 }
else if (list->
elements[x]->
type == (uint32_t)0x000b) {
3154 (*((int16_t*)list->
elements[x]->
data)!=0?
"True":
"False"),
3157 }
else if (list->
elements[x]->
type == (uint32_t)0x000d) {
3162 }
else if (list->
elements[x]->
type == (uint32_t)0x0014) {
3167 }
else if (list->
elements[x]->
type == (uint32_t)0x001e) {
3171 }
else if (list->
elements[x]->
type == (uint32_t)0x001f) {
3176 }
else if (list->
elements[x]->
type == (uint32_t)0x0040) {
3180 }
else if (list->
elements[x]->
type == (uint32_t)0x0048) {
3185 }
else if (list->
elements[x]->
type == (uint32_t)0x0102) {
3190 }
else if (list->
elements[x]->
type == (uint32_t)0x1003) {
3195 }
else if (list->
elements[x]->
type == (uint32_t)0x1014) {
3200 }
else if (list->
elements[x]->
type == (uint32_t)0x101e) {
3205 }
else if (list->
elements[x]->
type == (uint32_t)0x101f) {
3210 }
else if (list->
elements[x]->
type == (uint32_t)0x1102) {
3228 if (attach) attach = attach->
next;
3309 DEBUG_WARN((
"block read error occurred. offset = %#"PRIx64
", size = %#"PRIx64
"\n", list->
offset, list->
size));
3316 memcpy(&block_head, buf,
sizeof(block_head));
3320 if (block_head.
type != (uint16_t)0x0002) {
3321 DEBUG_WARN((
"Unknown constant [%#hx] at start of id2 values [offset %#"PRIx64
"].\n", block_head.
type, list->
offset));
3327 DEBUG_INFO((
"ID %#"PRIx64
" is likely to be a description record. Count is %i (offset %#"PRIx64
")\n",
3330 b_ptr = buf + ((pf->
do_read64) ? 0x08 : 0x04);
3331 while (x < block_head.
count) {
3333 DEBUG_INFO((
"id2 = %#x, id = %#"PRIx64
", child id = %#"PRIx64
"\n", id2_rec.
id2, id2_rec.
id, id2_rec.
child_id));
3334 if ((i_ptr =
pst_getID(pf, id2_rec.
id)) == NULL) {
3337 DEBUG_INFO((
"%#"PRIx64
" - Offset %#"PRIx64
", u1 %#"PRIx64
", Size %"PRIi64
"(%#"PRIx64
")\n",
3341 i2_ptr->
id2 = id2_rec.
id2;
3343 i2_ptr->
child = NULL;
3344 i2_ptr->
next = NULL;
3345 if (!head) head = i2_ptr;
3346 if (tail) tail->
next = i2_ptr;
3359 if (buf) free (buf);
3608 else if ((offset & 0xf) == (uint32_t)0xf) {
3610 DEBUG_WARN((
"Found id2 %#x value. Will follow it\n", offset));
3618 DEBUG_WARN((
"size zero but non-null pointer\n"));
3625 DEBUG_WARN((
"Found internal %#x value.\n", offset));
3627 size_t subindex = offset >> 16;
3630 subindex = subindex >> 3;
3632 size_t suboffset = offset & 0xffff;
3633 if (subindex < subblocks->subblock_count) {
3637 suboffset, &block_offset)) {
3639 p->
to = subblocks->
subs[subindex].
buf + block_offset.
to;
3644 return (p->
from) ? 0 : 1;
3650 uint32_t low = offset & 0xf;
3651 uint32_t of1 = offset >> 4;
3653 if (!p || !buf || !i_offset || low || (i_offset+2+of1+
sizeof(*p) > read_size)) {
3654 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));
3658 memcpy(&(p->
from), &(buf[(i_offset+2)+of1]),
sizeof(p->
from));
3659 memcpy(&(p->
to), &(buf[(i_offset+2)+of1+
sizeof(p->
from)]),
sizeof(p->
to));
3663 if (p->
from > p->
to || p->
to > read_size) {
3664 DEBUG_WARN((
"get block offset bad range\n"));
3674 uint64_t key_id = *(
const uint64_t*)key;
3675 uint64_t entry_id = ((
const pst_index_ll*)entry)->i_id;
3676 return (key_id > entry_id) - (key_id < entry_id);
3693 DEBUG_INFO((
"Trying to find %#"PRIx64
"\n", i_id));
3695 if (ptr) {
DEBUG_INFO((
"Found Value %#"PRIx64
"\n", i_id)); }
3696 else {
DEBUG_INFO((
"ERROR: Value %#"PRIx64
" not found\n", i_id)); }
3707 DEBUG_INFO((
"looking for id2 = %#"PRIx64
"\n", id2));
3710 if (ptr->
id2 == id2)
break;
3713 if (ptr && ptr->
id) {
3735 while (ptr && (ptr->
d_id != d_id)) {
3789 DEBUG_INFO((
"Reading raw block from %#"PRIx64
", %x bytes\n", offset, size));
3798 if (rsize != size) {
3799 DEBUG_WARN((
"Didn't read all the data. fread returned less [%i instead of %i]\n", rsize, size));
3801 DEBUG_WARN((
"We tried to read past the end of the file at [offset %#"PRIx64
", size %#x]\n", offset, size));
3802 }
else if (ferror(pf->
fp)) {
3803 DEBUG_WARN((
"Error is set on file stream.\n"));
3805 DEBUG_WARN((
"I can't tell why it failed\n"));
3815 DEBUG_INFO((
"Reading block from %#"PRIx64
", %x bytes, %x inflated\n", offset, size, inflated_size));
3816 if (inflated_size <= size) {
3825 DEBUG_WARN((
"Failed to read %i bytes\n", size));
3826 if (zbuf) free(zbuf);
3831 size_t result_size = inflated_size;
3832 if (uncompress((Bytef *) *buf, &result_size, (Bytef *) zbuf, size) != Z_OK || result_size != inflated_size) {
3833 DEBUG_WARN((
"Failed to uncompress %i bytes to %i bytes, got %i\n", size, inflated_size, result_size));
3834 if (zbuf) free(zbuf);
3839 return inflated_size;
3854 static int pst_decrypt(uint64_t i_id,
char *buf,
size_t size,
unsigned char type) {
3866 y = (
unsigned char)(buf[x]);
3874 uint16_t salt = (uint16_t) (((i_id & 0x00000000ffff0000) >> 16) ^ (i_id & 0x000000000000ffff));
3877 uint8_t losalt = (salt & 0x00ff);
3878 uint8_t hisalt = (salt & 0xff00) >> 8;
3879 y = (
unsigned char)buf[x];
3893 DEBUG_WARN((
"Unknown encryption: %i. Cannot decrypt\n", type));
3906 memcpy(&buf64, buf,
sizeof(buf64));
3911 memcpy(&buf32, buf,
sizeof(buf32));
3967 if (fseeko(pf->
fp, pos, SEEK_SET) == -1) {
3971 rc = fread(buf, (
size_t)1, size, pf->
fp);
3987 int noenc = (int)(i_id & 2);
4014 DEBUG_INFO((
"Cannot find ID %#"PRIx64
"\n", i_id));
4018 DEBUG_INFO((
"id = %#"PRIx64
", record size = %#x, offset = %#x\n", i_id, rec->
size, rec->
offset));
4033 DEBUG_WARN((
"Cannot find id2 value %#"PRIx64
"\n", id2));
4055 if (!(ptr->
i_id & 0x02)) {
4061 DEBUG_INFO((
"Assuming it is a multi-block record because of it's id %#"PRIx64
"\n", ptr->
i_id));
4091 if (buf3) free(buf3);
4096 memcpy(&block_hdr, buf3,
sizeof(block_hdr));
4102 count = block_hdr.
type;
4109 for (y=0; y<count; y++) {
4119 DEBUG_WARN((
"WARNING: not a type 0x0101 buffer, Treating as normal buffer\n"));
4127 for (y=0; y<count; y++) {
4131 DEBUG_WARN((
"call to getIDblock returned zero %i\n", z));
4132 if (buf2) free(buf2);
4141 if (buf2) free(buf2);
4162 DEBUG_INFO((
"appending read data of size %i onto main buffer from pos %i\n", z, size));
4163 memcpy(*(h->
buf)+size, *buf, z);
4166 }
else if ((h->
base64 == 1) && h->
fp) {
4186 DEBUG_INFO((
"writing %i bytes to file as base64 [%i]. Currently %i\n", z, strlen(t), size));
4193 DEBUG_INFO((
"writing %i bytes to file. Currently %i\n", z, size));
4232 while(*a !=
'\0' && *b !=
'\0' && toupper(*a)==toupper(*b)) {
4235 if (toupper(*a) == toupper(*b))
4237 else if (toupper(*a) < toupper(*b))
4248 while (*a !=
'\0' && *b !=
'\0' && y < x && toupper(*a)==toupper(*b)) {
4252 if (*a ==
'\0' || *b ==
'\0' || toupper(*a)==toupper(*b))
4254 else if (toupper(*a) < toupper(*b))
4261 size_t pst_fwrite(
const void* ptr,
size_t size,
size_t nmemb, FILE *stream) {
4264 r = fwrite(ptr, size, nmemb, stream);
4268 DEBUG_WARN((
"An attempt to write a NULL Pointer was made\n"));
4281 while (size != 0 && *wt !=
'\0') {
4299 if (!str)
return NULL;
4307 if (y == 0 && z == 0)
4311 x = strlen(str) + y - z + 1;
4318 while (*a !=
'\0') {
4361 if (strftime(result, buflen,
"%Y-%m-%dT%H:%M:%SZ", &stm)==0) {
4362 DEBUG_INFO((
"Problem occurred formatting date\n"));
4373 if (strftime(result, buflen,
"%Y%m%dT%H%M%SZ", &stm)==0) {
4374 DEBUG_INFO((
"Problem occurred formatting date\n"));
4383 time_t t = time(NULL);
4384 DEBUG_ENT(
"rfc2445_datetime_format_now");
4386 if (strftime(result, buflen,
"%Y%m%dT%H%M%SZ", &stm)==0) {
4387 DEBUG_INFO((
"Problem occurred formatting date\n"));
4402 static const char*
codepage(
int cp,
int buflen,
char* result);
4403 static const char*
codepage(
int cp,
int buflen,
char* result) {
4405 case 932 :
return "iso-2022-jp";
4406 case 936 :
return "gb2313";
4407 case 950 :
return "big5";
4408 case 1200 :
return "ucs-2le";
4409 case 1201 :
return "ucs-2be";
4410 case 20127 :
return "us-ascii";
4411 case 20269 :
return "iso-6937";
4412 case 20865 :
return "iso-8859-15";
4413 case 20866 :
return "koi8-r";
4414 case 21866 :
return "koi8-u";
4415 case 28591 :
return "iso-8859-1";
4416 case 28592 :
return "iso-8859-2";
4417 case 28595 :
return "iso-8859-5";
4418 case 28596 :
return "iso-8859-6";
4419 case 28597 :
return "iso-8859-7";
4420 case 28598 :
return "iso-8859-8";
4421 case 28599 :
return "iso-8859-9";
4422 case 28600 :
return "iso-8859-10";
4423 case 28601 :
return "iso-8859-11";
4424 case 28602 :
return "iso-8859-12";
4425 case 28603 :
return "iso-8859-13";
4426 case 28604 :
return "iso-8859-14";
4427 case 28605 :
return "iso-8859-15";
4428 case 28606 :
return "iso-8859-16";
4429 case 50220 :
return "iso-2022-jp";
4430 case 50221 :
return "csiso2022jp";
4431 case 51932 :
return "euc-jp";
4432 case 51949 :
return "euc-kr";
4433 case 65000 :
return "utf-7";
4434 case 65001 :
return "utf-8";
4436 snprintf(result, buflen,
"windows-%d", cp);
4466 const int8_t *x = (int8_t *)str->
str;
4468 if (*x <= 32) needs++;
4471 int n = strlen(str->
str) + 2*needs + 15;
4473 strcpy(buffer,
"utf-8''");
4474 x = (int8_t *)str->
str;
4475 const uint8_t *y = (uint8_t *)str->
str;
4476 uint8_t *z = (uint8_t *)buffer;
4477 z += strlen(buffer);
4480 *(z++) = (uint8_t)
'%';
4481 snprintf(z, 3,
"%2x", *y);
4504 int needs_coding = 0;
4506 const int8_t *x = (int8_t *)str->
str;
4508 if (*x == 32) has_space = 1;
4509 if (*x < 32) needs_coding = 1;
4515 int n = strlen(enc) + 20;
4517 snprintf(str->
str, n,
"=?utf-8?B?%s?=", enc);
4520 else if (has_space && needs_quote) {
4521 int n = strlen(str->
str) + 10;
4523 snprintf(buffer, n,
"\"%s\"", str->
str);
4536 if (!str->
str)
return;
4555 str->
str = strdup(
"");
4561 DEBUG_WARN((
"default charset is %s\n", charset));
4562 if (!strcasecmp(
"utf-8", charset)) {
4568 if (rc == (
size_t)-1) {
4570 DEBUG_WARN((
"Failed to convert %s to utf-8 - %s\n", charset, str->
str));
4574 str->
str = newer->
b;
4588 const int bias = 30 * 24 * 60;
4589 int m[4] = {3,4,4,5};
4602 for (j=0; j<n; j++) {
pst_string sender_address
mapi element 0x0065 PR_SENT_REPRESENTING_EMAIL_ADDRESS
#define INDEX_TYPE_OFFSET
#define PST_ATTRIB_HEADER
int32_t valid_mask
mapi element 0x35df, bit mask of folders in this message store
pst_string original_cc
mapi element 0x0073 PR_ORIGINAL_DISPLAY_CC
pst_entryid * sent_items_folder
mapi element 0x35e4
pst_string timezonestring
mapi element 0x8234
uint32_t bydaymask
bit mask of days of the week
pst_string outlook_received_name1
mapi element 0x0040 PR_RECEIVED_BY_NAME
#define LIST_COPY_BOOL(label, targ)
#define LIST_COPY_APPT_BIN(label, targ)
pst_binary pst_attach_to_mem(pst_file *pf, pst_item_attach *attach)
Assemble the binary attachment into a single buffer.
int32_t alarm_minutes
mapi element 0x8501 PR_OUTLOOK_COMMON_REMINDER_MINUTES_BEFORE
struct pst_mapi_element pst_mapi_element
pst_binary encrypted_htmlbody
mapi element 0x6f02
struct pst_id2_assoc32 pst_id2_assoc32
pst_item_appointment * appointment
calendar mapi elements
struct pst_holder pst_holder
FILETIME * modify_date
mapi element 0x3008 PR_LAST_MODIFICATION_TIME
pst_item_contact * contact
contact mapi elements
pst_string comment
mapi element 0x3004 PR_COMMENT
struct pst_id2_assoc pst_id2_assoc
int32_t importance
mapi element 0x0017 PR_IMPORTANCE
int32_t flags
mapi element 0x0e07 PR_MESSAGE_FLAGS
pst_string subject
mapi element 0x0037 PR_SUBJECT
pst_vbuf * pst_vballoc(size_t len)
int32_t recurrence_type
mapi element 0x8231
static int pst_chr_count(char *str, char x)
void pst_vbappend(pst_vbuf *vb, void *b, size_t len)
append len bytes of b to vb, resize if necessary
uint32_t position
occurrence of day for 2nd Tuesday of month, in which case position is 2
static size_t pst_ff_compile_ID(pst_file *pf, uint64_t i_id, pst_holder *h, size_t size)
find the actual data from an indirection i_id and send it to the destination specified by the pst_hol...
static void add_descriptor_to_list(pst_desc_tree *node, pst_desc_tree **head, pst_desc_tree **tail)
add a pst descriptor node to a linked list of such nodes.
pst_string alarm_filename
mapi element 0x851f
struct pst_table3_rec pst_table3_rec
pst_binary record_key
mapi element 0x0ff9 PR_RECORD_KEY
#define LIST_COPY_CSTR(targ)
int subfolder
mapi element 0x360a PR_SUBFOLDERS
pst_string header
mapi element 0x007d PR_TRANSPORT_MESSAGE_HEADERS
static unsigned char comp_high1[]
for "strong" encryption, this is the second rotor of an Enigma 3 rotor cipher.
static pst_mapi_object * pst_parse_block(pst_file *pf, uint64_t block_id, pst_id2_tree *i2_head)
Process a low level descriptor block (0x0101, 0xbcec, 0x7cec) into a list of MAPI objects...
#define LIST_COPY_TIME(label, targ)
struct pst_desc_tree * child_tail
#define LIST_COPY_EMAIL_BIN(label, targ)
int32_t original_sensitivity
mapi element 0x002e PR_ORIGINAL_SENSITIVITY
static size_t pst_read_raw_block_size(pst_file *pf, int64_t offset, size_t size, char **buf)
Read a block of data from file into memory.
FILETIME * create_date
mapi element 0x3007 PR_CREATION_TIME
int32_t rtf_ws_trailing_count
mapi element 0x1011 PR_RTF_SYNC_TRAILING_COUNT, a count of the ignored characters after the last sign...
static void pst_free_id2(pst_id2_tree *head)
#define LIST_COPY_APPT_ENUM(label, targ, delta, count,...)
uint32_t parm1
must be contiguous, not an array to make Python interface easier
uint64_t index2_back
back pointer value in the first b-tree node in the descriptor tree
pst_binary conversation_index
mapi element 0x0071 PR_CONVERSATION_INDEX
int delete_after_submit
mapi element 0x0e01 PR_DELETE_AFTER_SUBMIT
pst_entryid * default_outbox_folder
mapi element 0x35e2
pst_string processed_subject
mapi element 0x0070 PR_CONVERSATION_TOPIC
#define LIST_COPY_APPT_INT32(label, targ)
uint32_t termination
type of termination of the recurrence
uint64_t id2_val
only used if the attachment is by reference, in which case this is the id2 reference ...
struct pst_x_attrib pst_x_attrib
int32_t internet_cpid
mapi element 0x3fde PR_INTERNET_CPID
pst_recurrence * pst_convert_recurrence(pst_item_appointment *appt)
Decode raw recurrence data into a better structure.
size_t pst_vb_utf16to8(pst_vbuf *dest, const char *inbuf, int iblen)
struct pst_desc_tree * parent
void pst_rfc2047(pst_item *item, pst_string *str, int needs_quote)
Convert str to rfc2047 encoding of str, possibly enclosed in quotes if it contains spaces...
int alarm
mapi element 0x8503 PR_OUTLOOK_COMMON_REMINDER_SET
#define LIST_COPY_CONTACT_ENUM16(label, targ, delta, count,...)
char * ascii_type
mapi element 0x001a PR_MESSAGE_CLASS or 0x3613 PR_CONTAINER_CLASS
int rtf_in_sync
mapi element 0x0e1f PR_RTF_IN_SYNC, True means that the rtf version is same as text body...
void pst_freeItem(pst_item *item)
Free the item returned by pst_parse_item().
struct pst_x_attrib_ll * next
link to next item in the list
int pst_load_extended_attributes(pst_file *pf)
Try to load the extended attributes from the pst file.
pst_item_journal * journal
journal mapi elements
#define LIST_COPY_APPT_STR(label, targ)
static uint64_t pst_getIntAtPos(pst_file *pf, int64_t pos)
char * pst_rfc2426_escape(char *str, char **buf, size_t *buflen)
Add any necessary escape characters for rfc2426 vcard format.
#define LEVEL_INDICATOR_OFFSET
void * pst_malloc(size_t size)
uint64_t block_id
block id that can be used to generate uid
uint32_t map
key for the mapping
struct pst_index32 pst_index32
unsigned char ind_type
index type or file type
pst_entryid * user_views_folder
mapi element 0x35e5
#define LIST_COPY_JOURNAL_TIME(label, targ)
pst_binary encrypted_body
mapi element 0x6f04
#define LIST_COPY_STORE_INT32(label, targ)
char base64_extra_chars[2]
int pst_close(pst_file *pf)
Close a pst file.
int32_t unseen_item_count
mapi element 0x3603 PR_CONTENT_UNREAD
pst_string recurrence_description
mapi element 0x8232 recurrence description
#define LIST_COPY_EMAIL_ENTRYID(label, targ)
#define LIST_COPY_EMAIL_STR(label, targ)
FILETIME * end
mapi element 0x8708
static size_t pst_ff_getID2data(pst_file *pf, pst_index_ll *ptr, pst_holder *h)
find the actual data from an i_id and send it to the destination specified by the pst_holder h...
int conversion_prohibited
mapi element 0x3a03 PR_CONVERSION_PROHIBITED
#define PST_TYPE_SCHEDULE
pst_string outlook_sender
mapi element 0x003b PR_SENT_REPRESENTING_SEARCH_KEY
FILETIME * recurrence_start
mapi element 0x8235 PR_OUTLOOK_EVENT_RECURRENCE_START
pst_string sender2_access
mapi element 0x0c1e PR_SENDER_ADDRTYPE
int32_t showas
mapi element 0x8205 PR_OUTLOOK_EVENT_SHOW_TIME_AS
static void freeall(pst_subblocks *subs, pst_block_offset_pointer *p1, pst_block_offset_pointer *p2, pst_block_offset_pointer *p3, pst_block_offset_pointer *p4, pst_block_offset_pointer *p5, pst_block_offset_pointer *p6, pst_block_offset_pointer *p7)
static char * pst_wide_to_single(char *wt, size_t size)
FILETIME * reminder
mapi element 0x8560
size_t pst_vb_8bit2utf8(pst_vbuf *dest, const char *inbuf, int iblen, const char *charset)
This contains the common mapi elements, and pointers to structures for each major mapi item type...
static pst_id2_tree * pst_build_id2(pst_file *pf, pst_index_ll *list)
int32_t method
mapi element 0x3705 PR_ATTACH_METHOD
pst_entryid * top_of_personal_folder
mapi element 0x35e0
int private_member
mapi element 0x002b PR_RECIPIENT_REASSIGNMENT_PROHIBITED
This contains the attachment related mapi elements.
Linked list of extended attributes.
size_t pst_attach_to_file_base64(pst_file *pf, pst_item_attach *attach, FILE *fp)
Write a binary attachment base64 encoded to a file.
const char * pst_default_charset(pst_item *item, int buflen, char *result)
Get the default character set for this item.
pst_string reply_to
mapi element 0x0050 PR_REPLY_RECIPIENT_NAMES
uint32_t sub_type
implies number of recurrence parameters
char * cwd
original cwd when the file was opened
pst_string outlook_recipient_name
mapi element 0x0044 PR_RCVD_REPRESENTING_NAME
pst_binary data
mapi element 0x3701 PR_ATTACH_DATA_OBJ
a simple wrapper for binary blobs
pst_string report_text
mapi element 0x1001 PR_REPORT_TEXT, delivery report dsn body
pst_entryid * common_view_folder
mapi element 0x35e6
pst_string body_charset
derived from extra_fields["content-type"] if it contains a charset= subfield
pst_entryid * deleted_items_folder
mapi element 0x35e3
int message_cc_me
mapi element 0x0058 PR_MESSAGE_CC_ME, this user is listed explicitly in the CC address ...
#define DEBUG_HEXDUMP(x, s)
pst_string file_as
mapi element 0x3001 PR_DISPLAY_NAME
static size_t pst_decode_table(pst_file *pf, struct pst_table_ptr_struct *table, char *buf)
static void record_descriptor(pst_file *pf, pst_desc_tree *node)
add a pst descriptor node into the global tree.
static void pst_free_xattrib(pst_x_attrib_ll *x)
struct pst_block_offset_pointer pst_block_offset_pointer
pst_string messageid
mapi element 0x1035
int32_t rtf_body_char_count
mapi element 0x1007 PR_RTF_SYNC_BODY_COUNT, a count of the significant characters in the rtf body...
static size_t pst_read_block_size(pst_file *pf, int64_t offset, size_t size, size_t inflated_size, char **buf)
pst_string outlook_sender_name2
mapi element 0x0c1a PR_SENDER_NAME
void pst_fileTimeToStructTM(const FILETIME *filetime, struct tm *result)
Convert a FILETIME to unix struct tm.
pst_string outlook_search_key
mapi element 0x300b PR_SEARCH_KEY
uint32_t monthofyear
month of year for yearly recurrences
The string is either utf8 encoded, or it is in the code page specified by the containing mapi object...
static size_t pst_append_holder(pst_holder *h, size_t size, char **buf, size_t z)
append (buf,z) data to the output destination (h,size)
#define PST_LE_GET_INT32(p)
int32_t ndr_reason_code
mapi element 0x0c04 PR_NDR_REASON_CODE
pst_string recip2_address
mapi element 0x0078 PR_RCVD_REPRESENTING_EMAIL_ADDRESS
int autoforward
mapi element 0x0002 PR_ALTERNATE_RECIPIENT_ALLOWED
struct pst_desc_tree * next
int32_t priority
mapi element 0x0026 PR_PRIORITY
static size_t pst_finish_cleanup_holder(pst_holder *h, size_t size)
finish cleanup for base64 encoding to a file with extra bytes left over
pst_string recip_access
mapi element 0x0075 PR_RECEIVED_BY_ADDRTYPE
static int pst_decrypt(uint64_t i_id, char *buf, size_t size, unsigned char type)
Decrypt a block of data from the pst file.
pst_desc_tree * pst_getTopOfFolders(pst_file *pf, const pst_item *root)
Get the top of folders descriptor tree.
pst_string outlook_recipient2
mapi element 0x0052 PR_RCVD_REPRESENTING_SEARCH_KEY
struct pst_id2_tree * child
static void pst_free_desc(pst_desc_tree *head)
pst_string mimetype
mapi element 0x370e PR_ATTACH_MIME_TAG
int32_t label
mapi element 0x8214
#define LIST_COPY_APPT_BOOL(label, targ)
pst_binary predecessor_change
mapi element 0x65e3 PR_PREDECESSOR_CHANGE_LIST
struct pst_desc_tree * child
int pst_open(pst_file *pf, const char *name, const char *charset)
Open a pst file.
#define LIST_COPY_EMAIL_TIME(label, targ)
#define LIST_COPY_EMAIL_ENUM(label, targ, delta, count,...)
pst_index_ll * pst_getID(pst_file *pf, uint64_t i_id)
Lookup the i_id in the index linked list, and return a pointer to the element.
char * pst_rfc2445_datetime_format_now(int buflen, char *result)
Convert the current time rfc2445 date/time format 19531015T231000Z.
static pst_desc_tree * pst_getDptr(pst_file *pf, uint64_t d_id)
find the id in the descriptor tree rooted at pf->d_head
pst_string cc_address
mapi element 0x0e03 PR_DISPLAY_CC
void pst_rfc2231(pst_string *str)
Convert str to rfc2231 encoding of str.
static int pst_getBlockOffset(char *buf, size_t read_size, uint32_t i_offset, uint32_t offset, pst_block_offset *p)
#define PST_LE_GET_UINT8(p)
#define LIST_COPY_STORE_ENTRYID(label, targ)
#define PST_LE_GET_UINT16(p)
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)
Process the index2 b-tree from the pst file and create the pf->d_head tree from it.
static int pst_getID_compare(const void *key, const void *entry)
uint32_t signature
0x30043004
pst_string sentto_address
mapi element 0x0e04 PR_DISPLAY_TO
int32_t rtf_ws_prefix_count
mapi element 0x1010 PR_RTF_SYNC_PREFIX_COUNT, a count of the ignored characters before the first sign...
uint64_t index1
file offset of the first b-tree node in the index tree
FILETIME * sent_date
mapi element 0x0039 PR_CLIENT_SUBMIT_TIME
struct pst_mapi_object * next
int delivery_report
mapi element 0x0023 PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED
pst_string filename1
mapi element 0x3704 PR_ATTACH_FILENAME
uint32_t dayofmonth
day of month for monthly and yearly recurrences
int32_t assoc_count
mapi element 0x3617 PR_ASSOC_CONTENT_COUNT Associated content are items that are attached to this fol...
pst_string body
mapi element 0x1000 PR_BODY
size_t pst_ff_getIDblock_dec(pst_file *pf, uint64_t i_id, char **buf)
Get an ID block from file using pst_ff_getIDblock() and decrypt if necessary.
pst_item_message_store * message_store
message store mapi elements
int32_t message_size
mapi element 0x0e08 PR_MESSAGE_SIZE
static size_t pst_decode_index(pst_file *pf, pst_index *index, char *buf)
FILETIME * end
mapi element 0x820e PR_OUTLOOK_EVENT_START_END
#define PST_TYPE_STICKYNOTE
#define DEBUG_HEXDUMPC(x, s, c)
static pst_id2_tree * pst_getID2(pst_id2_tree *ptr, uint64_t id)
static void pst_printDptr(pst_file *pf, pst_desc_tree *ptr)
#define LIST_COPY_APPT_TIME(label, targ)
uint32_t interval
recurrence interval in terms of the recurrence type
void pst_free_recurrence(pst_recurrence *r)
Free a recurrence structure.
pst_entryid * top_of_folder
mapi element 0x7c07
pst_string type
mapi element 0x8700
char * pst_base64_encode(void *data, size_t size)
static size_t pst_decode_assoc(pst_file *pf, pst_id2_assoc *assoc, char *buf)
pst_string supplementary_info
mapi element 0x0c1b PR_SUPPLEMENTARY_INFO
FILETIME * arrival_date
mapi element 0x0e06 PR_MESSAGE_DELIVERY_TIME
pst_string sender_access
mapi element 0x0064 PR_SENT_REPRESENTING_ADDRTYPE
pst_string outlook_recipient
mapi element 0x0051 PR_RECEIVED_BY_SEARCH_KEY
struct pst_subblocks pst_subblocks
int32_t message_codepage
mapi element 0x3ffd PR_MESSAGE_CODEPAGE
int read_receipt
mapi element 0x0029 PR_READ_RECEIPT_REQUESTED
uint64_t i_id
calculated from id2_val during creation of record
pst_string bcc_address
mapi element 0x0e02 PR_DISPLAY_BCC
void * data
data target of the mapping, either uint32_t or string
void pst_vbset(pst_vbuf *vb, void *b, size_t len)
set vbuf b size=len, resize if necessary, relen = how much to over-allocate
pst_string outlook_version
mapi element 0x8554 PR_OUTLOOK_VERSION
uint64_t index2
file offset of the first b-tree node in the descriptor tree
#define LIST_COPY_JOURNAL_STR(label, targ)
#define read_twobyte(BUF, OFF)
pst_x_attrib_ll * x_head
the head of the extended attributes linked list
pst_index_ll * assoc_tree
static int pst_getBlockOffsetPointer(pst_file *pf, pst_id2_tree *i2_head, pst_subblocks *subblocks, uint32_t offset, pst_block_offset_pointer *p)
The offset might be zero, in which case we have no data, so return a pair of null pointers...
#define LIST_COPY_FOLDER_INT32(label, targ)
int is_recurring
mapi element 0x8223 PR_OUTLOOK_EVENT_IS_RECURRING
pst_string htmlbody
mapi element 0x1013
char * fname
original file name when the file was opened
int type
derived from mapi elements 0x001a PR_MESSAGE_CLASS or 0x3613 PR_CONTAINER_CLASS
int32_t pwd_chksum
mapi element 0x76ff
#define LIST_COPY_CONTACT_TIME(label, targ)
int32_t sequence
mapi element 0x3710 PR_ATTACH_MIME_SEQUENCE
static int pst_process(uint64_t block_id, pst_mapi_object *list, pst_item *item, pst_item_attach *attach)
process the list of MAPI objects produced from parse_block()
int pst_reopen(pst_file *pf)
Reopen the pst file after a fork.
int message_to_me
mapi element 0x0057 PR_MESSAGE_TO_ME, this user is listed explicitly in the TO address ...
char * pst_rfc2425_datetime_format(const FILETIME *ft, int buflen, char *result)
Convert a FILETIME into rfc2425 date/time format 1953-10-15T23:10:00Z which is the same as one of the...
#define PST_FLAG_HAS_ATTACHMENT
This contains the appointment related mapi elements.
pst_item_extra_field * extra_fields
linked list of extra headers and such
#define LIST_COPY_EMAIL_BOOL(label, targ)
int reply_requested
mapi element 0x0c17 PR_REPLY_REQUESTED
static size_t pst_decode_type3(pst_file *pf, pst_table3_rec *table3_rec, char *buf)
static char * pst_getcwd(void)
static unsigned char comp_high2[]
for "strong" encryption, this is the third rotor of an Enigma 3 rotor cipher.
char * pst_fileTimeToAscii(const FILETIME *filetime, char *result)
Convert a FILETIME to ascii printable local time.
static void pst_free_attach(pst_item_attach *attach)
static size_t pst_decode_desc(pst_file *pf, pst_desc *desc, char *buf)
pst_entryid * search_root_folder
mapi element 0x35e7
static void pst_free_list(pst_mapi_object *list)
pst_string in_reply_to
mapi element 0x1042
pst_string outlook_normalized_subject
mapi element 0x0e1d PR_NORMALIZED_SUBJECT
uint64_t index1_back
back pointer value in the first b-tree node in the index tree
pst_binary recurrence_data
mapi element 0x8216 recurrence data
pst_string outlook_sender_name
mapi element 0x0042 PR_SENT_REPRESENTING_NAME
uint64_t size
size of the pst file
#define LIST_COPY_STR(label, targ)
struct pst_block_hdr pst_block_hdr
pst_string sender2_address
mapi element 0x0c1f PR_SENDER_EMAIL_ADDRESS
pst_binary rtf_compressed
mapi element 0x1009 PR_RTF_COMPRESSED, the compressed rtf body data.
char * pst_base64_encode_single(void *data, size_t size)
pst_item * pst_parse_item(pst_file *pf, pst_desc_tree *d_ptr, pst_id2_tree *m_head)
Process a high level object from the pst file.
int32_t ndr_status_code
mapi element 0x0c20 PR_NDR_STATUS_CODE
#define LIST_COPY_EMAIL_INT32(label, targ)
pst_string return_path_address
mapi element 0x1046, this seems to be the message-id of the rfc822 mail that is being returned ...
pst_string filename2
mapi element 0x3707 PR_ATTACH_LONG_FILENAME
FILETIME * report_time
mapi element 0x0032 PR_REPORT_TIME, delivery report time
pst_string description
mapi element 0x8712
int pst_stricmp(char *a, char *b)
compare strings case-insensitive.
size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE *fp)
Write a binary attachment to a file.
FILETIME * recurrence_end
mapi element 0x8236 PR_OUTLOOK_EVENT_RECURRENCE_END
int message_recip_me
mapi element 0x0059 PR_MESSAGE_RECIP_ME, this user appears in TO, CC or BCC address list ...
void * pst_realloc(void *ptr, size_t size)
#define LIST_COPY_CONTACT_STR(label, targ)
#define FILE_SIZE_POINTER
static size_t pst_ff_getIDblock(pst_file *pf, uint64_t i_id, char **buf)
Read a block of data from file into memory.
struct pst_mapi_element ** elements
pst_desc_tree * pst_getNextDptr(pst_desc_tree *d)
Walk the descriptor tree.
char * pst_rfc2445_datetime_format(const FILETIME *ft, int buflen, char *result)
Convert a FILETIME into rfc2445 date/time format 19531015T231000Z.
const char * charset
default character set for items without one
pst_desc_tree * d_head
the head and tail of the top level of the descriptor tree
pst_string recip_address
mapi element 0x0076 PR_RECEIVED_BY_EMAIL_ADDRESS
struct pst_block_offset pst_block_offset
struct pst_table3_rec32 pst_table3_rec32
struct pst_desc32 pst_desc32
struct pst_id2_tree * next
static uint64_t pst_getIntAt(pst_file *pf, char *buf)
int32_t ndr_diag_code
mapi element 0x0c05 PR_NDR_DIAG_CODE
#define PST_LE_GET_UINT32(p)
struct pst_index pst_index
pst_item_email * email
email mapi elements
int response_requested
mapi element 0x0063 PR_RESPONSE_REQUESTED
pst_entryid * sentmail_folder
mapi element 0x0e0a PR_SENTMAIL_ENTRYID
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)
Process the index1 b-tree from the pst file and create the pf->i_head linked list from it...
int32_t sensitivity
mapi element 0x0036 PR_SENSITIVITY
#define PST_TYPE_APPOINTMENT
pst_item_attach * attach
linked list of attachments
#define LIST_COPY_BIN(targ)
pst_string recip2_access
mapi element 0x0077 PR_RCVD_REPRESENTING_ADDRTYPE
FILETIME * start
mapi element 0x820d PR_OUTLOOK_EVENT_START_DATE
pst_string original_to
mapi element 0x0074 PR_ORIGINAL_DISPLAY_TO
static unsigned char comp_enc[]
for "compressible" encryption, just a simple substitution cipher, plaintext = comp_enc[ciphertext]; f...
FILE * fp
file pointer to opened PST file
struct pst_item_attach * next
int32_t position
mapi element 0x370b PR_RENDERING_POSITION
struct pst_mapi_object pst_mapi_object
static size_t pst_getAtPos(pst_file *pf, int64_t pos, void *buf, size_t size)
Read part of the pst file.
uint32_t count
number of occurrences, even if recurrence terminates based on date
#define LIST_COPY_CONTACT_BOOL(label, targ)
char * pst_base64_encode_multiple(void *data, size_t size, int *line_count)
static int pst_strincmp(char *a, char *b, size_t x)
static const char * codepage(int cp, int buflen, char *result)
Convert a code page integer into a string suitable for iconv()
int pst_load_index(pst_file *pf)
Load the index entries from the pst file.
pst_string rtf_body_tag
mapi element 0x1008 PR_RTF_SYNC_BODY_TAG, the first couple of lines of RTF body so that after modific...
size_t pst_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
fwrite with checking for null pointer.
struct pst_index64 pst_index64
#define LIST_COPY_ENUM(label, targ, delta, count,...)
static void pst_printID2ptr(pst_id2_tree *ptr)
struct pst_desc_tree * prev
pst_item_folder * folder
folder mapi elements
void pst_convert_utf8_null(pst_item *item, pst_string *str)
Convert str to utf8 if possible; null strings are preserved.
int32_t rtf_body_crc
mapi element 0x1006 PR_RTF_SYNC_BODY_CRC
pst_string outlook_sender2
mapi element 0x0c1d PR_SENDER_SEARCH_KEY
#define LIST_COPY_INT32(label, targ)
pst_string original_bcc
mapi element 0x0072 PR_ORIGINAL_DISPLAY_BCC
static pst_id2_tree * deep_copy(pst_id2_tree *head)
make a deep copy of part of the id2 mapping tree, for use by an attachment containing an embedded rfc...
pst_id2_tree * id2_head
id2 tree needed to resolve attachments by reference
struct pst_block_header pst_block_header
struct pst_subblock pst_subblock
FILETIME * start
mapi element 0x8706
#define ITEM_COUNT_OFFSET
int32_t item_count
mapi element 0x3602 PR_CONTENT_COUNT
static size_t pst_ff_getID2block(pst_file *pf, uint64_t id2, pst_id2_tree *id2_head, char **buf)
#define ENTRY_SIZE_OFFSET
This contains the recurrence data separated into fields.
int all_day
mapi element 0x8215 PR_OUTLOOK_EVENT_ALL_DAY
pst_index_ll * i_table
the array of index structures
struct pst_file * pf
pointer to the pst_file
void pst_convert_utf8(pst_item *item, pst_string *str)
Convert str to utf8 if possible; null strings are converted into empty strings.
pst_string location
mapi element 0x8208 PR_OUTLOOK_EVENT_LOCATION
pst_string content_id
mapi element 0x3712 PR_ATTACH_CONTENT_ID