@rhyster/wow-casc-dbc 2.6.19 → 2.7.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/adb.d.ts +17 -0
- package/dist/adb.d.ts.map +1 -0
- package/dist/blte.d.ts +25 -0
- package/dist/blte.d.ts.map +1 -0
- package/dist/client.d.ts +84 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/dbd.d.ts +26 -0
- package/dist/dbd.d.ts.map +1 -0
- package/dist/fetcher.d.ts +21 -0
- package/dist/fetcher.d.ts.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +9 -261
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -0
- package/dist/jenkins96.d.ts +3 -0
- package/dist/jenkins96.d.ts.map +1 -0
- package/dist/parsers/archiveIndex.d.ts +9 -0
- package/dist/parsers/archiveIndex.d.ts.map +1 -0
- package/dist/parsers/config.d.ts +40 -0
- package/dist/parsers/config.d.ts.map +1 -0
- package/dist/parsers/encodingFile.d.ts +11 -0
- package/dist/parsers/encodingFile.d.ts.map +1 -0
- package/dist/parsers/productConfig.d.ts +21 -0
- package/dist/parsers/productConfig.d.ts.map +1 -0
- package/dist/parsers/rootFile.d.ts +45 -0
- package/dist/parsers/rootFile.d.ts.map +1 -0
- package/dist/salsa20.d.ts +14 -0
- package/dist/salsa20.d.ts.map +1 -0
- package/dist/store.d.ts +9 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/test/salsa20.test.d.ts +2 -0
- package/dist/test/salsa20.test.d.ts.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/wdc.d.ts +104 -0
- package/dist/wdc.d.ts.map +1 -0
- package/package.json +5 -4
- package/src/adb.ts +70 -0
- package/src/blte.ts +220 -0
- package/src/client.ts +411 -0
- package/src/dbd.ts +427 -0
- package/src/fetcher.ts +223 -0
- package/src/index.ts +44 -0
- package/src/jenkins96.ts +75 -0
- package/src/parsers/archiveIndex.ts +119 -0
- package/src/parsers/config.ts +75 -0
- package/src/parsers/encodingFile.ts +159 -0
- package/src/parsers/productConfig.ts +57 -0
- package/src/parsers/rootFile.ts +172 -0
- package/src/salsa20.ts +143 -0
- package/src/store.ts +37 -0
- package/src/test/salsa20.test.ts +522 -0
- package/src/utils.ts +77 -0
- package/src/wdc.ts +788 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
declare const ContentFlags: {
|
|
2
|
+
readonly Install: 4;
|
|
3
|
+
readonly LoadOnWindows: 8;
|
|
4
|
+
readonly LoadOnMacOS: 16;
|
|
5
|
+
readonly x86_32: 32;
|
|
6
|
+
readonly x86_64: 64;
|
|
7
|
+
readonly LowViolence: 128;
|
|
8
|
+
readonly DoNotLoad: 256;
|
|
9
|
+
readonly UpdatePlugin: 2048;
|
|
10
|
+
readonly ARM64: 32768;
|
|
11
|
+
readonly Encrypted: 134217728;
|
|
12
|
+
readonly NoNameHash: 268435456;
|
|
13
|
+
readonly UncommonResolution: 536870912;
|
|
14
|
+
readonly Bundle: 1073741824;
|
|
15
|
+
readonly NoCompression: 2147483648;
|
|
16
|
+
};
|
|
17
|
+
declare const LocaleFlags: {
|
|
18
|
+
readonly enUS: 2;
|
|
19
|
+
readonly koKR: 4;
|
|
20
|
+
readonly frFR: 16;
|
|
21
|
+
readonly deDE: 32;
|
|
22
|
+
readonly zhCN: 64;
|
|
23
|
+
readonly esES: 128;
|
|
24
|
+
readonly zhTW: 256;
|
|
25
|
+
readonly enGB: 512;
|
|
26
|
+
readonly esMX: 4096;
|
|
27
|
+
readonly ruRU: 8192;
|
|
28
|
+
readonly ptBR: 16384;
|
|
29
|
+
readonly itIT: 32768;
|
|
30
|
+
readonly ptPT: 65536;
|
|
31
|
+
};
|
|
32
|
+
interface FileInfo {
|
|
33
|
+
cKey: string;
|
|
34
|
+
contentFlags: number;
|
|
35
|
+
localeFlags: number;
|
|
36
|
+
}
|
|
37
|
+
interface RootData {
|
|
38
|
+
fileDataID2CKey: Map<number, FileInfo[]>;
|
|
39
|
+
nameHash2FileDataID: Map<string, number>;
|
|
40
|
+
}
|
|
41
|
+
declare const parseRootFile: (inputBuffer: Buffer, eKey: string, cKey: string) => RootData;
|
|
42
|
+
export default parseRootFile;
|
|
43
|
+
export { ContentFlags, LocaleFlags };
|
|
44
|
+
export type { FileInfo, RootData };
|
|
45
|
+
//# sourceMappingURL=rootFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rootFile.d.ts","sourceRoot":"","sources":["../../src/parsers/rootFile.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;CAeR,CAAC;AAEX,QAAA,MAAM,WAAW;;;;;;;;;;;;;;CAgBP,CAAC;AAEX,UAAU,QAAQ;IACd,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,QAAQ;IACd,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED,QAAA,MAAM,aAAa,gBAAiB,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAG,QA8GxE,CAAC;AAEF,eAAe,aAAa,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AAErC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default class Salsa20 {
|
|
2
|
+
private readonly fixed;
|
|
3
|
+
private readonly key;
|
|
4
|
+
private readonly nonce;
|
|
5
|
+
private counter;
|
|
6
|
+
private state;
|
|
7
|
+
private block;
|
|
8
|
+
private position;
|
|
9
|
+
constructor(key: Uint8Array, nonce: Uint8Array);
|
|
10
|
+
private QR;
|
|
11
|
+
private generateBlock;
|
|
12
|
+
process(input: Uint8Array): Uint8Array;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=salsa20.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salsa20.d.ts","sourceRoot":"","sources":["../src/salsa20.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,OAAO,OAAO,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IAEpC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAElC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IAEpC,OAAO,CAAC,OAAO,CAA2B;IAE1C,OAAO,CAAC,KAAK,CAAuB;IAEpC,OAAO,CAAC,KAAK,CAAsB;IAEnC,OAAO,CAAC,QAAQ,CAAK;gBAET,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;IAwC9C,OAAO,CAAC,EAAE;IAgBV,OAAO,CAAC,aAAa;IAmDrB,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU;CAgBzC"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export default class Store<K extends string | number | symbol, V> {
|
|
2
|
+
private data;
|
|
3
|
+
private dataFile;
|
|
4
|
+
private promise;
|
|
5
|
+
constructor(dataFile: string);
|
|
6
|
+
get(key: K): Promise<V | undefined>;
|
|
7
|
+
set(key: K, value: V): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5D,OAAO,CAAC,IAAI,CAA2B;IAEvC,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,OAAO,CAAgB;gBAEnB,QAAQ,EAAE,MAAM;IAiBf,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAKnC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAKpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salsa20.test.d.ts","sourceRoot":"","sources":["../../src/test/salsa20.test.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,cAAc,UAAW,MAAM,WAsC3C,CAAC;AAEF,eAAO,MAAM,cAAc,UAChB,MAAM,EAAE,QACT,MAAM,KACb,OAAO,CAAC,MAAM,EAAE,CAqBlB,CAAC"}
|
package/dist/wdc.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type ADBReader from './adb.ts';
|
|
2
|
+
import type { MissingKeyBlock } from './blte.ts';
|
|
3
|
+
interface FieldStructure {
|
|
4
|
+
size: number;
|
|
5
|
+
position: number;
|
|
6
|
+
}
|
|
7
|
+
interface FieldStorageInfoCompressionNone {
|
|
8
|
+
fieldOffsetBits: number;
|
|
9
|
+
fieldSizeBits: number;
|
|
10
|
+
additionalDataSize: number;
|
|
11
|
+
storageType: 'none';
|
|
12
|
+
}
|
|
13
|
+
interface FieldStorageInfoCompressionBitpacked {
|
|
14
|
+
fieldOffsetBits: number;
|
|
15
|
+
fieldSizeBits: number;
|
|
16
|
+
additionalDataSize: number;
|
|
17
|
+
storageType: 'bitpacked';
|
|
18
|
+
bitpackingOffsetBits: number;
|
|
19
|
+
bitpackingSizeBits: number;
|
|
20
|
+
flags: number;
|
|
21
|
+
}
|
|
22
|
+
interface FieldStorageInfoCompressionCommonData {
|
|
23
|
+
fieldOffsetBits: number;
|
|
24
|
+
fieldSizeBits: number;
|
|
25
|
+
additionalDataSize: number;
|
|
26
|
+
storageType: 'commonData';
|
|
27
|
+
defaultValue: number;
|
|
28
|
+
}
|
|
29
|
+
interface FieldStorageInfoCompressionBitpackedIndexed {
|
|
30
|
+
fieldOffsetBits: number;
|
|
31
|
+
fieldSizeBits: number;
|
|
32
|
+
additionalDataSize: number;
|
|
33
|
+
storageType: 'bitpackedIndexed';
|
|
34
|
+
bitpackingOffsetBits: number;
|
|
35
|
+
bitpackingSizeBits: number;
|
|
36
|
+
}
|
|
37
|
+
interface FieldStorageInfoCompressionBitpackedIndexedArray {
|
|
38
|
+
fieldOffsetBits: number;
|
|
39
|
+
fieldSizeBits: number;
|
|
40
|
+
additionalDataSize: number;
|
|
41
|
+
storageType: 'bitpackedIndexedArray';
|
|
42
|
+
bitpackingOffsetBits: number;
|
|
43
|
+
bitpackingSizeBits: number;
|
|
44
|
+
arrayCount: number;
|
|
45
|
+
}
|
|
46
|
+
interface FieldStorageInfoCompressionBitpackedSigned {
|
|
47
|
+
fieldOffsetBits: number;
|
|
48
|
+
fieldSizeBits: number;
|
|
49
|
+
additionalDataSize: number;
|
|
50
|
+
storageType: 'bitpackedSigned';
|
|
51
|
+
bitpackingOffsetBits: number;
|
|
52
|
+
bitpackingSizeBits: number;
|
|
53
|
+
flags: number;
|
|
54
|
+
}
|
|
55
|
+
type FieldStorageInfo = FieldStorageInfoCompressionNone | FieldStorageInfoCompressionBitpacked | FieldStorageInfoCompressionCommonData | FieldStorageInfoCompressionBitpackedIndexed | FieldStorageInfoCompressionBitpackedIndexedArray | FieldStorageInfoCompressionBitpackedSigned;
|
|
56
|
+
interface ParsedFieldNone {
|
|
57
|
+
type: 'none';
|
|
58
|
+
data: number | bigint;
|
|
59
|
+
string?: string;
|
|
60
|
+
}
|
|
61
|
+
interface ParsedFieldCommonData {
|
|
62
|
+
type: 'commonData';
|
|
63
|
+
data: number;
|
|
64
|
+
}
|
|
65
|
+
interface ParsedFieldBitpacked {
|
|
66
|
+
type: 'bitpacked';
|
|
67
|
+
data: number;
|
|
68
|
+
}
|
|
69
|
+
interface ParsedFieldBitpackedArray {
|
|
70
|
+
type: 'bitpackedArray';
|
|
71
|
+
data: number[];
|
|
72
|
+
}
|
|
73
|
+
type ParsedField = ParsedFieldNone | ParsedFieldCommonData | ParsedFieldBitpacked | ParsedFieldBitpackedArray;
|
|
74
|
+
interface SparseRow {
|
|
75
|
+
type: 'sparse';
|
|
76
|
+
data: Buffer;
|
|
77
|
+
}
|
|
78
|
+
interface HotfixModify {
|
|
79
|
+
type: 'modify';
|
|
80
|
+
data: Buffer;
|
|
81
|
+
}
|
|
82
|
+
interface HotfixDelete {
|
|
83
|
+
type: 'delete';
|
|
84
|
+
}
|
|
85
|
+
type Hotfix = HotfixModify | HotfixDelete;
|
|
86
|
+
export default class WDCReader {
|
|
87
|
+
readonly tableHash: number;
|
|
88
|
+
readonly layoutHash: number;
|
|
89
|
+
readonly locale: number;
|
|
90
|
+
readonly isNormal: boolean;
|
|
91
|
+
readonly hasRelationshipData: boolean;
|
|
92
|
+
readonly fields: FieldStructure[];
|
|
93
|
+
readonly fieldsInfo: FieldStorageInfo[];
|
|
94
|
+
readonly rows: Map<number, SparseRow | ParsedField[]>;
|
|
95
|
+
readonly relationships: Map<number, number>;
|
|
96
|
+
readonly copyTable: Map<number, number>;
|
|
97
|
+
readonly hotfixes: Map<number, Hotfix>;
|
|
98
|
+
constructor(buffer: Buffer, blocks?: MissingKeyBlock[], adb?: ADBReader);
|
|
99
|
+
getAllIDs(): number[];
|
|
100
|
+
getRowData(id: number): ParsedField[] | SparseRow | undefined;
|
|
101
|
+
getRowRelationship(id: number): number | undefined;
|
|
102
|
+
}
|
|
103
|
+
export type { FieldStructure, FieldStorageInfo, FieldStorageInfoCompressionNone, FieldStorageInfoCompressionBitpacked, FieldStorageInfoCompressionCommonData, FieldStorageInfoCompressionBitpackedIndexed, FieldStorageInfoCompressionBitpackedIndexedArray, FieldStorageInfoCompressionBitpackedSigned, ParsedField, ParsedFieldNone, ParsedFieldCommonData, ParsedFieldBitpacked, ParsedFieldBitpackedArray, SparseRow, Hotfix, HotfixModify, HotfixDelete, };
|
|
104
|
+
//# sourceMappingURL=wdc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wdc.d.ts","sourceRoot":"","sources":["../src/wdc.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhyster/wow-casc-dbc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "Fetch World of Warcraft data files from CASC and parse DBC/DB2 files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
"module": "./dist/index.mjs",
|
|
15
15
|
"types": "./dist/index.d.ts",
|
|
16
16
|
"files": [
|
|
17
|
-
"dist"
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
18
19
|
],
|
|
19
20
|
"scripts": {
|
|
20
|
-
"build": "unbuild",
|
|
21
|
+
"build": "unbuild && tsc --project .",
|
|
21
22
|
"lint": "eslint .",
|
|
22
23
|
"lint:fix": "eslint . --fix",
|
|
23
24
|
"test": "tsx --test"
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
"author": "Rhythm",
|
|
38
39
|
"license": "MIT",
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@rhyster/eslint-config": "^1.6.
|
|
41
|
+
"@rhyster/eslint-config": "^1.6.6",
|
|
41
42
|
"@types/async": "^3.2.24",
|
|
42
43
|
"@types/cli-progress": "^3.11.6",
|
|
43
44
|
"@types/node": "^22.10.2",
|
package/src/adb.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
|
|
3
|
+
const ADB_MAGIC = 0x58465448;
|
|
4
|
+
|
|
5
|
+
export interface HotfixEntry {
|
|
6
|
+
regionID: number,
|
|
7
|
+
pushID: number,
|
|
8
|
+
uniqueID: number,
|
|
9
|
+
tableHash: number,
|
|
10
|
+
recordID: number,
|
|
11
|
+
dataSize: number,
|
|
12
|
+
recordState: number,
|
|
13
|
+
data: Buffer,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default class ADBReader {
|
|
17
|
+
public build: number;
|
|
18
|
+
|
|
19
|
+
public entries: HotfixEntry[] = [];
|
|
20
|
+
|
|
21
|
+
public tableEntries = new Map<number, HotfixEntry[]>();
|
|
22
|
+
|
|
23
|
+
constructor(buffer: Buffer) {
|
|
24
|
+
const magic = buffer.readUInt32BE(0);
|
|
25
|
+
assert(magic === ADB_MAGIC, `[ADB]: Invalid magic: ${magic.toString(16).padStart(8, '0')}`);
|
|
26
|
+
|
|
27
|
+
const version = buffer.readUInt32LE(4);
|
|
28
|
+
assert(version === 9, `[ADB]: Invalid version: ${version.toString()}`);
|
|
29
|
+
|
|
30
|
+
const build = buffer.readUInt32LE(8);
|
|
31
|
+
this.build = build;
|
|
32
|
+
|
|
33
|
+
let pointer = 44;
|
|
34
|
+
while (pointer < buffer.byteLength) {
|
|
35
|
+
const offset = pointer;
|
|
36
|
+
|
|
37
|
+
const entryMagic = buffer.readUInt32BE(offset);
|
|
38
|
+
assert(entryMagic === ADB_MAGIC, `[ADB]: Invalid entry magic: ${magic.toString(16).padStart(8, '0')}`);
|
|
39
|
+
|
|
40
|
+
const regionID = buffer.readInt32LE(offset + 4);
|
|
41
|
+
const pushID = buffer.readInt32LE(offset + 8);
|
|
42
|
+
const uniqueID = buffer.readUInt32LE(offset + 12);
|
|
43
|
+
const tableHash = buffer.readUInt32LE(offset + 16);
|
|
44
|
+
const recordID = buffer.readUInt32LE(offset + 20);
|
|
45
|
+
const dataSize = buffer.readUInt32LE(offset + 24);
|
|
46
|
+
const recordState = buffer.readUInt32LE(offset + 28);
|
|
47
|
+
|
|
48
|
+
const data = buffer.subarray(offset + 32, offset + 32 + dataSize);
|
|
49
|
+
|
|
50
|
+
const entry: HotfixEntry = {
|
|
51
|
+
regionID,
|
|
52
|
+
pushID,
|
|
53
|
+
uniqueID,
|
|
54
|
+
tableHash,
|
|
55
|
+
recordID,
|
|
56
|
+
dataSize,
|
|
57
|
+
recordState,
|
|
58
|
+
data,
|
|
59
|
+
};
|
|
60
|
+
this.entries.push(entry);
|
|
61
|
+
|
|
62
|
+
if (!this.tableEntries.has(tableHash)) {
|
|
63
|
+
this.tableEntries.set(tableHash, []);
|
|
64
|
+
}
|
|
65
|
+
this.tableEntries.get(tableHash)?.push(entry);
|
|
66
|
+
|
|
67
|
+
pointer += 32 + dataSize;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/blte.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import zlib from 'node:zlib';
|
|
4
|
+
|
|
5
|
+
import Salsa20 from './salsa20.ts';
|
|
6
|
+
|
|
7
|
+
interface Block {
|
|
8
|
+
compressedSize: number,
|
|
9
|
+
decompressedSize: number,
|
|
10
|
+
hash: string,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface MissingKeyBlock {
|
|
14
|
+
offset: number,
|
|
15
|
+
size: number,
|
|
16
|
+
blockIndex: number,
|
|
17
|
+
keyName: string,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const BLTE_MAGIC = 0x424c5445;
|
|
21
|
+
const ENC_TYPE_SALSA20 = 0x53;
|
|
22
|
+
const EMPTY_HASH = '00000000000000000000000000000000';
|
|
23
|
+
|
|
24
|
+
export default class BLTEReader {
|
|
25
|
+
public buffer: Buffer;
|
|
26
|
+
|
|
27
|
+
public readonly blte: Buffer;
|
|
28
|
+
|
|
29
|
+
public readonly blocks: Block[] = [];
|
|
30
|
+
|
|
31
|
+
public readonly keys: Map<string, Uint8Array>;
|
|
32
|
+
|
|
33
|
+
private processedBlock = 0;
|
|
34
|
+
|
|
35
|
+
private processedOffset = 0;
|
|
36
|
+
|
|
37
|
+
constructor(buffer: Buffer, eKey: string, keys = new Map<string, Uint8Array>()) {
|
|
38
|
+
this.blte = buffer;
|
|
39
|
+
this.buffer = Buffer.alloc(0);
|
|
40
|
+
this.keys = keys;
|
|
41
|
+
|
|
42
|
+
const size = buffer.byteLength;
|
|
43
|
+
assert(size >= 8, `[BLTE]: Invalid size: ${size.toString()} < 8`);
|
|
44
|
+
|
|
45
|
+
const magic = buffer.readUInt32BE(0);
|
|
46
|
+
assert(magic === BLTE_MAGIC, `[BLTE]: Invalid magic: ${magic.toString(16).padStart(8, '0')}`);
|
|
47
|
+
|
|
48
|
+
const headerSize = buffer.readUInt32BE(4);
|
|
49
|
+
if (headerSize === 0) {
|
|
50
|
+
const blteHash = crypto.createHash('md5').update(buffer).digest('hex');
|
|
51
|
+
assert(blteHash === eKey, `[BLTE]: Invalid hash: expected ${eKey}, got ${blteHash}`);
|
|
52
|
+
|
|
53
|
+
this.blocks.push({
|
|
54
|
+
compressedSize: size - 8,
|
|
55
|
+
decompressedSize: size - 9,
|
|
56
|
+
hash: EMPTY_HASH,
|
|
57
|
+
});
|
|
58
|
+
this.processedOffset = 8;
|
|
59
|
+
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const blteHash = crypto.createHash('md5').update(buffer.subarray(0, headerSize)).digest('hex');
|
|
64
|
+
assert(blteHash === eKey, `[BLTE]: Invalid hash: expected ${eKey}, got ${blteHash}`);
|
|
65
|
+
|
|
66
|
+
assert(size >= 12, `[BLTE]: Invalid size: ${size.toString()} < 12`);
|
|
67
|
+
|
|
68
|
+
const flag = buffer.readUInt8(8);
|
|
69
|
+
const numBlocks = buffer.readIntBE(9, 3);
|
|
70
|
+
|
|
71
|
+
assert(numBlocks > 0, `[BLTE]: Invalid number of blocks: ${numBlocks.toString()}`);
|
|
72
|
+
assert(flag === 0x0f, `[BLTE]: Invalid flag: ${flag.toString(16).padStart(2, '0')}`);
|
|
73
|
+
|
|
74
|
+
const blockHeaderSize = numBlocks * 24;
|
|
75
|
+
assert(headerSize === blockHeaderSize + 12, `[BLTE]: Invalid header size: header size ${headerSize.toString()} != block header size ${blockHeaderSize.toString()} + 12`);
|
|
76
|
+
|
|
77
|
+
assert(size >= headerSize, `[BLTE]: Invalid size: ${size.toString()} < ${headerSize.toString()}`);
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < numBlocks; i += 1) {
|
|
80
|
+
const offset = 12 + i * 24;
|
|
81
|
+
const compressedSize = buffer.readUInt32BE(offset);
|
|
82
|
+
const decompressedSize = buffer.readUInt32BE(offset + 4);
|
|
83
|
+
const hash = buffer.toString('hex', offset + 8, offset + 24);
|
|
84
|
+
|
|
85
|
+
this.blocks.push({
|
|
86
|
+
compressedSize,
|
|
87
|
+
decompressedSize,
|
|
88
|
+
hash,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this.processedOffset = headerSize;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private processBlock(buffer: Buffer, index: number, allowMissingKey: false): Buffer;
|
|
96
|
+
private processBlock(buffer: Buffer, index: number, allowMissingKey: true): Buffer | string;
|
|
97
|
+
private processBlock(buffer: Buffer, index: number, allowMissingKey: boolean): Buffer | string {
|
|
98
|
+
const flag = buffer.readUInt8(0);
|
|
99
|
+
switch (flag) {
|
|
100
|
+
case 0x45: { // Encrypted
|
|
101
|
+
let offset = 1;
|
|
102
|
+
|
|
103
|
+
const keyNameLength = buffer.readUInt8(offset);
|
|
104
|
+
offset += 1;
|
|
105
|
+
|
|
106
|
+
const keyNameBE = buffer.toString('hex', offset, offset + keyNameLength);
|
|
107
|
+
offset += keyNameLength;
|
|
108
|
+
|
|
109
|
+
const ivLength = buffer.readUInt8(offset);
|
|
110
|
+
offset += 1;
|
|
111
|
+
|
|
112
|
+
const ivBuffer = buffer.subarray(offset, offset + ivLength);
|
|
113
|
+
offset += ivLength;
|
|
114
|
+
|
|
115
|
+
const encryptType = buffer.readUInt8(offset);
|
|
116
|
+
offset += 1;
|
|
117
|
+
|
|
118
|
+
assert(encryptType === ENC_TYPE_SALSA20, `[BLTE]: Invalid encrypt type: ${encryptType.toString(16).padStart(2, '0')} at block ${index.toString()}`);
|
|
119
|
+
|
|
120
|
+
const keyName = [...keyNameBE.matchAll(/.{2}/g)].map((v) => v[0]).reverse().join('').toLowerCase();
|
|
121
|
+
const key = this.keys.get(keyName);
|
|
122
|
+
if (!key) {
|
|
123
|
+
if (allowMissingKey) {
|
|
124
|
+
return keyName;
|
|
125
|
+
}
|
|
126
|
+
throw new Error(`[BLTE]: Missing key: ${keyName} at block ${index.toString()}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const iv = new Uint8Array(8);
|
|
130
|
+
for (let i = 0; i < 8; i += 1) {
|
|
131
|
+
if (i < ivLength) {
|
|
132
|
+
// eslint-disable-next-line no-bitwise
|
|
133
|
+
iv[i] = ivBuffer.readUInt8(i) ^ ((index >>> (8 * i)) & 0xff);
|
|
134
|
+
} else {
|
|
135
|
+
iv[i] = 0x00;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const handler = new Salsa20(key, iv);
|
|
140
|
+
const decrypted = handler.process(buffer.subarray(offset));
|
|
141
|
+
|
|
142
|
+
if (allowMissingKey) {
|
|
143
|
+
return this.processBlock(Buffer.from(decrypted.buffer), index, true);
|
|
144
|
+
}
|
|
145
|
+
return this.processBlock(Buffer.from(decrypted.buffer), index, false);
|
|
146
|
+
}
|
|
147
|
+
case 0x46: // Frame (Recursive)
|
|
148
|
+
throw new Error(`[BLTE]: Frame (Recursive) block not supported at block ${index.toString()}`);
|
|
149
|
+
case 0x4e: // Frame (Normal)
|
|
150
|
+
return buffer.subarray(1);
|
|
151
|
+
case 0x5a: // Compressed
|
|
152
|
+
return zlib.inflateSync(buffer.subarray(1));
|
|
153
|
+
default:
|
|
154
|
+
throw new Error(`[BLTE]: Invalid block flag: ${flag.toString(16).padStart(2, '0')} at block ${index.toString()}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
processBytes(allowMissingKey?: false, size?: number): undefined;
|
|
159
|
+
processBytes(allowMissingKey: true, size?: number): MissingKeyBlock[];
|
|
160
|
+
processBytes(allowMissingKey = false, size = Infinity): MissingKeyBlock[] | undefined {
|
|
161
|
+
const missingKeyBlocks: MissingKeyBlock[] = [];
|
|
162
|
+
|
|
163
|
+
while (
|
|
164
|
+
this.processedBlock < this.blocks.length
|
|
165
|
+
&& size > this.buffer.byteLength
|
|
166
|
+
) {
|
|
167
|
+
const blockIndex = this.processedBlock;
|
|
168
|
+
const block = this.blocks[blockIndex];
|
|
169
|
+
|
|
170
|
+
const blockBuffer = this.blte.subarray(
|
|
171
|
+
this.processedOffset,
|
|
172
|
+
this.processedOffset + block.compressedSize,
|
|
173
|
+
);
|
|
174
|
+
if (block.hash !== EMPTY_HASH) {
|
|
175
|
+
const blockHash = crypto.createHash('md5').update(blockBuffer).digest('hex');
|
|
176
|
+
assert(blockHash === block.hash, `[BLTE]: Invalid block hash: expected ${block.hash}, got ${blockHash}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (allowMissingKey) {
|
|
180
|
+
const buffer = this.processBlock(blockBuffer, blockIndex, allowMissingKey);
|
|
181
|
+
if (typeof buffer === 'string') {
|
|
182
|
+
missingKeyBlocks.push({
|
|
183
|
+
offset: this.buffer.byteLength,
|
|
184
|
+
size: block.decompressedSize,
|
|
185
|
+
blockIndex,
|
|
186
|
+
keyName: buffer,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
this.buffer = Buffer.concat([
|
|
190
|
+
this.buffer,
|
|
191
|
+
Buffer.alloc(block.decompressedSize),
|
|
192
|
+
]);
|
|
193
|
+
} else {
|
|
194
|
+
assert(
|
|
195
|
+
buffer.byteLength === block.decompressedSize,
|
|
196
|
+
`[BLTE]: Invalid decompressed size: expected ${block.decompressedSize.toString()}, got ${buffer.byteLength.toString()}`,
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
this.buffer = Buffer.concat([this.buffer, buffer]);
|
|
200
|
+
}
|
|
201
|
+
} else {
|
|
202
|
+
const buffer = this.processBlock(blockBuffer, blockIndex, allowMissingKey);
|
|
203
|
+
|
|
204
|
+
assert(
|
|
205
|
+
buffer.byteLength === block.decompressedSize,
|
|
206
|
+
`[BLTE]: Invalid decompressed size: expected ${block.decompressedSize.toString()}, got ${buffer.byteLength.toString()}`,
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
this.buffer = Buffer.concat([this.buffer, buffer]);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
this.processedBlock += 1;
|
|
213
|
+
this.processedOffset += block.compressedSize;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return allowMissingKey ? missingKeyBlocks : undefined;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export type { MissingKeyBlock };
|