-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
88 lines (68 loc) · 2.59 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
type Property = { key: string, value: string | number | Property[] };
function getString(buffer: Buffer, offset: number): [ value: string, length: number ] {
const currentBuffer = buffer.subarray(offset);
const length = currentBuffer.findIndex((byte) => byte === 0x00);
return [ currentBuffer.toString('utf-8', 0, length), length ];
}
function getNumber(buffer: Buffer, offset: number): number {
return buffer.readUInt32LE(offset);
}
function getProperty(buffer: Buffer, offset: number): { offset: number, property: Property } {
switch (buffer[offset]) {
// Property containing object (of more properties)
case 0x00: {
offset++; // Skip newmap byte
// Read key name
const [ key, keyLength ] = getString(buffer, offset);
offset += keyLength + 1; // String length + null terminator
// Get properties in value
const property: any = { key, value: {} };
while (buffer[offset] !== 0x08) {
const propertyInfo = getProperty(buffer, offset);
property.value[propertyInfo.property.key] = propertyInfo.property.value;
offset = propertyInfo.offset;
}
offset++;
return { offset, property };
}
// Property containing string
case 0x01: {
offset++;
const [ key, keyLength ] = getString(buffer, offset);
offset += keyLength + 1;
const [ value, valueLength ] = getString(buffer, offset);
offset += valueLength + 1;
const property = { key, value };
return { offset, property };
}
// Property containing number
case 0x02: {
offset++;
const [ key, keyLength ] = getString(buffer, offset);
offset += keyLength + 1;
const value = getNumber(buffer, offset);
offset += 4;
const property = { key, value };
return { offset, property};
}
default: throw new Error(`Type not implemented (0x${buffer[offset].toString(16).padStart(2, '0')} at offset ${offset} (0x${offset.toString(16).padStart(2, '0')}))`);
}
}
function readVdf(buffer: Buffer) {
const infos: any[] = [];
let offset = 0;
const APPINFO_STRING = '00617070696E666F00';
while (offset < buffer.length) {
// Find next appinfo header
const nextAppinfoOffset = buffer.subarray(offset).indexOf(APPINFO_STRING, 0, 'hex');
if (nextAppinfoOffset === -1) break;
offset += nextAppinfoOffset;
const appInfo: any = {};
const propertyInfo = getProperty(buffer, offset);
offset = propertyInfo.offset;
appInfo[propertyInfo.property.key] = propertyInfo.property.value;
infos.push(appInfo);
}
return infos;
}
export { readVdf };