@hiraokahypertools/pst-extractor 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BTHeap.d.ts +15 -0
- package/dist/BTHeap.js +76 -0
- package/dist/CollectionAsyncProvider.d.ts +15 -0
- package/dist/CollectionAsyncProvider.js +44 -0
- package/dist/KeyedDelay.d.ts +8 -0
- package/dist/KeyedDelay.js +37 -0
- package/dist/LZFu.class.d.ts +12 -0
- package/dist/LZFu.class.js +95 -0
- package/dist/NodeMap.class.d.ts +35 -0
- package/dist/NodeMap.class.js +86 -0
- package/dist/OutlookProperties.d.ts +278 -0
- package/dist/OutlookProperties.js +284 -0
- package/dist/PAUtil.d.ts +17 -0
- package/dist/PAUtil.js +145 -0
- package/dist/PHNodeHeap.d.ts +16 -0
- package/dist/PHNodeHeap.js +2 -0
- package/dist/PHNodeHeapReader.d.ts +6 -0
- package/dist/PHNodeHeapReader.js +5 -0
- package/dist/PHUtil.d.ts +6 -0
- package/dist/PHUtil.js +103 -0
- package/dist/PLMisc.d.ts +8 -0
- package/dist/PLMisc.js +16 -0
- package/dist/PLNode.d.ts +11 -0
- package/dist/PLNode.js +5 -0
- package/dist/PLStore.d.ts +9 -0
- package/dist/PLStore.js +5 -0
- package/dist/PLSubNode.d.ts +8 -0
- package/dist/PLSubNode.js +5 -0
- package/dist/PLUtil.d.ts +29 -0
- package/dist/PLUtil.js +683 -0
- package/dist/PSTActivity.class.d.ts +103 -0
- package/dist/PSTActivity.class.js +144 -0
- package/dist/PSTAppointment.class.d.ts +275 -0
- package/dist/PSTAppointment.class.js +381 -0
- package/dist/PSTAttachment.class.d.ts +168 -0
- package/dist/PSTAttachment.class.js +286 -0
- package/dist/PSTContact.class.d.ts +900 -0
- package/dist/PSTContact.class.js +1253 -0
- package/dist/PSTFile.class.d.ts +144 -0
- package/dist/PSTFile.class.js +221 -0
- package/dist/PSTFolder.class.d.ts +111 -0
- package/dist/PSTFolder.class.js +269 -0
- package/dist/PSTMessage.class.d.ts +773 -0
- package/dist/PSTMessage.class.js +1264 -0
- package/dist/PSTMessageStore.class.d.ts +16 -0
- package/dist/PSTMessageStore.class.js +18 -0
- package/dist/PSTObject.class.d.ts +107 -0
- package/dist/PSTObject.class.js +208 -0
- package/dist/PSTOpts.d.ts +24 -0
- package/dist/PSTOpts.js +2 -0
- package/dist/PSTRecipient.class.d.ts +68 -0
- package/dist/PSTRecipient.class.js +105 -0
- package/dist/PSTTask.class.d.ts +146 -0
- package/dist/PSTTask.class.js +206 -0
- package/dist/PSTUtil.class.d.ts +134 -0
- package/dist/PSTUtil.class.js +804 -0
- package/dist/Property.d.ts +38 -0
- package/dist/Property.js +2 -0
- package/dist/PropertyContext.d.ts +6 -0
- package/dist/PropertyContext.js +2 -0
- package/dist/PropertyContextUtil.d.ts +4 -0
- package/dist/PropertyContextUtil.js +77 -0
- package/dist/PropertyTypeObject.d.ts +12 -0
- package/dist/PropertyTypeObject.js +21 -0
- package/dist/PropertyValueResolver.d.ts +4 -0
- package/dist/PropertyValueResolver.js +2 -0
- package/dist/PropertyValueResolverV1.d.ts +7 -0
- package/dist/PropertyValueResolverV1.js +253 -0
- package/dist/RawProperty.d.ts +8 -0
- package/dist/RawProperty.js +2 -0
- package/dist/RecurrencePattern.class.d.ts +50 -0
- package/dist/RecurrencePattern.class.js +120 -0
- package/dist/RootProvider.d.ts +12 -0
- package/dist/RootProvider.js +2 -0
- package/dist/SingleAsyncProvider.d.ts +5 -0
- package/dist/SingleAsyncProvider.js +30 -0
- package/dist/TableContext.d.ts +4 -0
- package/dist/TableContext.js +2 -0
- package/dist/TableContextUtil.d.ts +4 -0
- package/dist/TableContextUtil.js +147 -0
- package/dist/TableRow.d.ts +6 -0
- package/dist/TableRow.js +2 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +28 -0
- package/dist/msftUuidStringify.d.ts +17 -0
- package/dist/msftUuidStringify.js +48 -0
- package/dist/openPstFile.d.ts +19 -0
- package/dist/openPstFile.js +67 -0
- package/package.json +105 -0
- package/readme.md +16 -0
package/dist/PAUtil.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PST adapter utilities
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.createPropertyFinder = exports.processNameToIDMap = void 0;
|
|
16
|
+
const msftUuidStringify_1 = require("./msftUuidStringify");
|
|
17
|
+
const NodeMap_class_1 = require("./NodeMap.class");
|
|
18
|
+
const PHUtil_1 = require("./PHUtil");
|
|
19
|
+
const PropertyContextUtil_1 = require("./PropertyContextUtil");
|
|
20
|
+
const PSTUtil_class_1 = require("./PSTUtil.class");
|
|
21
|
+
const guidMap = new Map([
|
|
22
|
+
['00020329-0000-0000-C000-000000000046', 0],
|
|
23
|
+
['00062008-0000-0000-C000-000000000046', 1],
|
|
24
|
+
['00062004-0000-0000-C000-000000000046', 2],
|
|
25
|
+
['00020386-0000-0000-C000-000000000046', 3],
|
|
26
|
+
['00062002-0000-0000-C000-000000000046', 4],
|
|
27
|
+
['6ED8DA90-450B-101B-98DA-00AA003F1305', 5],
|
|
28
|
+
['0006200A-0000-0000-C000-000000000046', 6],
|
|
29
|
+
['41F28F13-83F4-4114-A584-EEDB5A6B0BFF', 7],
|
|
30
|
+
['0006200E-0000-0000-C000-000000000046', 8],
|
|
31
|
+
['00062041-0000-0000-C000-000000000046', 9],
|
|
32
|
+
['00062003-0000-0000-C000-000000000046', 10],
|
|
33
|
+
['4442858E-A9E3-4E80-B900-317A210CC15B', 11],
|
|
34
|
+
['00020328-0000-0000-C000-000000000046', 12],
|
|
35
|
+
['71035549-0739-4DCB-9163-00F0580DBBDF', 13],
|
|
36
|
+
['00062040-0000-0000-C000-000000000046', 14],
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Process name to ID map.
|
|
40
|
+
*
|
|
41
|
+
* @param nameToIdMapDescriptorNode nodeId 97
|
|
42
|
+
*/
|
|
43
|
+
function processNameToIDMap(nameToIdMapDescriptorNode, resolver) {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
const subNode = nameToIdMapDescriptorNode.getSubNode();
|
|
46
|
+
const bcTable = (yield (yield (0, PropertyContextUtil_1.getPropertyContext)(yield (0, PHUtil_1.getHeapFrom)(subNode), resolver))
|
|
47
|
+
.list());
|
|
48
|
+
function getTableItem(key) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const found = bcTable.find(it => it.key === key);
|
|
51
|
+
if (found === undefined) {
|
|
52
|
+
throw new Error(`processNameToIDMap key:${key} is null`);
|
|
53
|
+
}
|
|
54
|
+
const { value } = found;
|
|
55
|
+
if (value instanceof ArrayBuffer) {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// process the map
|
|
62
|
+
// Get the guids
|
|
63
|
+
const guidEntry = yield getTableItem(2);
|
|
64
|
+
if (!guidEntry) {
|
|
65
|
+
throw new Error('PSTFile::processNameToIDMap guidEntry is null');
|
|
66
|
+
}
|
|
67
|
+
const guids = new Uint8Array(guidEntry);
|
|
68
|
+
const nGuids = Math.trunc(guids.byteLength / 16);
|
|
69
|
+
const guidIndexes = [];
|
|
70
|
+
let offset = 0;
|
|
71
|
+
for (let i = 0; i < nGuids; ++i) {
|
|
72
|
+
const strUID = (0, msftUuidStringify_1.msftUuidStringify)(guids, offset).toUpperCase();
|
|
73
|
+
const guid = guidMap.get(strUID);
|
|
74
|
+
if (guid) {
|
|
75
|
+
guidIndexes[i] = guid;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
guidIndexes[i] = -1; // We don't know this guid
|
|
79
|
+
}
|
|
80
|
+
// console.log('PSTFile:: processNameToIdMap idx: ' + i + ', ' + strUID + ', ' + guidIndexes[i]);
|
|
81
|
+
offset += 16;
|
|
82
|
+
}
|
|
83
|
+
// if we have a reference to an internal descriptor
|
|
84
|
+
const mapEntries = yield getTableItem(3);
|
|
85
|
+
if (!mapEntries) {
|
|
86
|
+
throw new Error('PSTFile::processNameToIDMap mapEntries is null');
|
|
87
|
+
}
|
|
88
|
+
const nameToIdByte = new Uint8Array(mapEntries);
|
|
89
|
+
const nameToIdByteView = new DataView(mapEntries);
|
|
90
|
+
const stringMapEntries = yield getTableItem(4);
|
|
91
|
+
if (!stringMapEntries) {
|
|
92
|
+
throw new Error('PSTFile::processNameToIDMap stringMapEntries is null');
|
|
93
|
+
}
|
|
94
|
+
const stringNameToIdByte = new Uint8Array(stringMapEntries);
|
|
95
|
+
const stringNameToIdByteView = new DataView(stringMapEntries);
|
|
96
|
+
const stringNameToIdByteBuffer = Buffer.from(stringMapEntries);
|
|
97
|
+
const nodeMap = new NodeMap_class_1.NodeMap();
|
|
98
|
+
// process the entries
|
|
99
|
+
for (let x = 0; x + 8 < nameToIdByte.length; x += 8) {
|
|
100
|
+
const key = nameToIdByteView.getUint32(x, true);
|
|
101
|
+
let guid = nameToIdByteView.getUint16(x + 4, true);
|
|
102
|
+
let propId = nameToIdByteView.getUint16(x + 6, true);
|
|
103
|
+
if (key == 0x55555555) {
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
const PS_PUBLIC_STRINGS = 0;
|
|
107
|
+
const PS_MAPI = 12;
|
|
108
|
+
if ((guid & 0x0001) == 0) {
|
|
109
|
+
// identifier is numeric
|
|
110
|
+
propId += 0x8000;
|
|
111
|
+
guid >>= 1;
|
|
112
|
+
let guidIndex;
|
|
113
|
+
if (guid == 1) {
|
|
114
|
+
guidIndex = PS_MAPI;
|
|
115
|
+
}
|
|
116
|
+
else if (guid == 2) {
|
|
117
|
+
guidIndex = PS_PUBLIC_STRINGS;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
guidIndex = guidIndexes[guid - 3];
|
|
121
|
+
}
|
|
122
|
+
nodeMap.setId(key, propId, guidIndex);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// identifier is a string
|
|
126
|
+
// key is byte offset into the String stream in which the string name of the property is stored.
|
|
127
|
+
const len = stringNameToIdByteView.getUint32(key, true);
|
|
128
|
+
const keyByteValue = Buffer.alloc(len);
|
|
129
|
+
PSTUtil_class_1.PSTUtil.arraycopy(stringNameToIdByteBuffer, key + 4, keyByteValue, 0, keyByteValue.length);
|
|
130
|
+
propId += 0x8000;
|
|
131
|
+
nodeMap.setId(keyByteValue.toString('utf16le').replace(/\0/g, ''), propId);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return nodeMap;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
exports.processNameToIDMap = processNameToIDMap;
|
|
138
|
+
function createPropertyFinder(props) {
|
|
139
|
+
return {
|
|
140
|
+
findByKey(key) {
|
|
141
|
+
return props.find(it => it.key === key);
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
exports.createPropertyFinder = createPropertyFinder;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PHNodeHeapReader } from "./PHNodeHeapReader";
|
|
2
|
+
export interface PHNodeHeap {
|
|
3
|
+
/**
|
|
4
|
+
* bType
|
|
5
|
+
*
|
|
6
|
+
* Set to `0` if heap structure doesn't exist, in case of loading absent subNode
|
|
7
|
+
*/
|
|
8
|
+
bClientSig: number;
|
|
9
|
+
/**
|
|
10
|
+
* hnid
|
|
11
|
+
*
|
|
12
|
+
* Set to `0` if heap structure doesn't exist, in case of loading absent subNode
|
|
13
|
+
*/
|
|
14
|
+
userRootHnid: number;
|
|
15
|
+
getReader(): PHNodeHeapReader;
|
|
16
|
+
}
|
package/dist/PHUtil.d.ts
ADDED
package/dist/PHUtil.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PST higher level utilities
|
|
4
|
+
*/
|
|
5
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
6
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
7
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
8
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
10
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
11
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getHeapFrom = void 0;
|
|
16
|
+
function getHeapFrom(node) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const data_array = yield node.getData();
|
|
19
|
+
const data_chunks = new Map();
|
|
20
|
+
let bClientSig = 0;
|
|
21
|
+
let userRootHnid = 0;
|
|
22
|
+
for (let x = 0; x < data_array.length; x++) {
|
|
23
|
+
if (x === 0) {
|
|
24
|
+
({ bClientSig, userRoot: userRootHnid } = load_root_header(data_chunks, data_array[x]));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
load_page_header(data_chunks, data_array[x], x);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
bClientSig,
|
|
32
|
+
userRootHnid,
|
|
33
|
+
toString() {
|
|
34
|
+
return `${node}`;
|
|
35
|
+
},
|
|
36
|
+
getReader() {
|
|
37
|
+
return {
|
|
38
|
+
getHeapBuffers(hnid) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
if (hnid === 0) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
else if (hnid & 0x1f) {
|
|
44
|
+
// this is NID (node)
|
|
45
|
+
const childNode = yield node.getChildBy(hnid);
|
|
46
|
+
if (childNode === undefined) {
|
|
47
|
+
throw new Error(`childNode=0x${hnid.toString(16)} of ${node} not found`);
|
|
48
|
+
}
|
|
49
|
+
const data_array = yield childNode.getData();
|
|
50
|
+
return data_array;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// this is HID (heap)
|
|
54
|
+
const data = data_chunks.get(hnid);
|
|
55
|
+
if (data === undefined) {
|
|
56
|
+
throw new Error(`heap=0x${hnid.toString(16)} of ${node} not found`);
|
|
57
|
+
}
|
|
58
|
+
return [data];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
toString() {
|
|
63
|
+
return `reader of ${node}`;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
exports.getHeapFrom = getHeapFrom;
|
|
71
|
+
/**
|
|
72
|
+
* Parse HNHDR
|
|
73
|
+
*
|
|
74
|
+
* @see https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-pst/8e4ae05c-3c24-4103-b7e5-ffef6f244834
|
|
75
|
+
*/
|
|
76
|
+
function load_root_header(data_chunks, data) {
|
|
77
|
+
const view = new DataView(data);
|
|
78
|
+
const page_map = view.getUint16(0, true);
|
|
79
|
+
const sig = view.getUint8(2);
|
|
80
|
+
const bClientSig = view.getUint8(3);
|
|
81
|
+
const userRoot = view.getUint32(4, true);
|
|
82
|
+
if (sig !== 0xec) {
|
|
83
|
+
throw new Error("invalid HNHDR signature found");
|
|
84
|
+
}
|
|
85
|
+
// read HNPAGEMAP
|
|
86
|
+
const offsets_count = view.getUint16(page_map, true) + 1;
|
|
87
|
+
for (let x = 0; x < offsets_count - 1; x++) {
|
|
88
|
+
const from = view.getUint16(page_map + 4 + 2 * (x), true);
|
|
89
|
+
const to = view.getUint16(page_map + 4 + 2 * (x + 1), true);
|
|
90
|
+
data_chunks.set(0x20 * (1 + x), data.slice(from, to));
|
|
91
|
+
}
|
|
92
|
+
return { bClientSig, userRoot };
|
|
93
|
+
}
|
|
94
|
+
function load_page_header(data_chunks, data, page_index) {
|
|
95
|
+
const view = new DataView(data);
|
|
96
|
+
const page_map = view.getUint16(0, true);
|
|
97
|
+
const offsets_count = view.getUint16(page_map, true) + 1;
|
|
98
|
+
for (let x = 0; x < offsets_count - 1; x++) {
|
|
99
|
+
const from = view.getUint16(page_map + 4 + 2 * (x), true);
|
|
100
|
+
const to = view.getUint16(page_map + 4 + 2 * (x + 1), true);
|
|
101
|
+
data_chunks.set(0x20 * (1 + x) + 65536 * page_index, data.slice(from, to));
|
|
102
|
+
}
|
|
103
|
+
}
|
package/dist/PLMisc.d.ts
ADDED
package/dist/PLMisc.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PST lower level misc utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.splitPer = void 0;
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
function* splitPer(array, per) {
|
|
12
|
+
for (let offset = 0; offset < array.byteLength; offset += per) {
|
|
13
|
+
yield array.slice(offset, offset + per);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.splitPer = splitPer;
|
package/dist/PLNode.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PST lower level node
|
|
3
|
+
*/
|
|
4
|
+
import { PLSubNode } from "./PLSubNode";
|
|
5
|
+
export interface PLNode {
|
|
6
|
+
nodeId: number;
|
|
7
|
+
getParent(): PLNode | undefined;
|
|
8
|
+
getChildren(): PLNode[];
|
|
9
|
+
getSubNode(): PLSubNode;
|
|
10
|
+
getSiblingNode(nidType: number): PLNode | undefined;
|
|
11
|
+
}
|
package/dist/PLNode.js
ADDED
package/dist/PLStore.js
ADDED
package/dist/PLUtil.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PST lower level utilities
|
|
3
|
+
*/
|
|
4
|
+
import Long from "long";
|
|
5
|
+
import { PLStore } from "./PLStore";
|
|
6
|
+
export declare type ReadFile = (buffer: ArrayBuffer, offset: number, length: number, position: number) => Promise<number>;
|
|
7
|
+
export declare type Close = () => Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Defines a callback based async file operation API.
|
|
10
|
+
*/
|
|
11
|
+
export interface ReadFileApi {
|
|
12
|
+
/**
|
|
13
|
+
* Defines read API like `fs.promises.readFile`.
|
|
14
|
+
*/
|
|
15
|
+
readFile: ReadFile;
|
|
16
|
+
/**
|
|
17
|
+
* Defines close API like `fs.promises.close`.
|
|
18
|
+
*/
|
|
19
|
+
close: Close;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare function readNumber64(view: DataView, offset: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export declare function readLong(view: DataView, offset: number): Long;
|
|
29
|
+
export declare function openLowPst(api: ReadFileApi): Promise<PLStore>;
|