rar-stream 3.2.0 → 3.3.0
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/README.md +33 -9
- package/dist/index.cjs +50 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -8
- package/dist/index.d.ts +12 -8
- package/dist/index.js +50 -25
- package/dist/index.js.map +1 -1
- package/package.json +6 -7
package/README.md
CHANGED
|
@@ -30,9 +30,8 @@ const rarFilesPackage = new RarFilesPackage(localRarFiles);
|
|
|
30
30
|
async function writeInnerRarFilesToDisk() {
|
|
31
31
|
const innerFiles = await rarFilesPackage.parse();
|
|
32
32
|
for (const innerFile of innerFiles) {
|
|
33
|
-
innerFile
|
|
34
|
-
|
|
35
|
-
.pipe(fs.createWriteStream(innerFile.name));
|
|
33
|
+
const stream = await innerFile.createReadStream({ start: 0, end: innerFile.length - 1 })
|
|
34
|
+
stream.pipe(fs.createWriteStream(innerFile.name));
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
|
|
@@ -60,6 +59,31 @@ npm i rar-stream
|
|
|
60
59
|
| _constructor_ | Takes an array of local file paths as strings or instances that satifies the [`FileMedia`](#filemedia-interface) interface mentioned below. |
|
|
61
60
|
| parse | Parses all rar files and returns a Promise with [`InnerFile`](#innerfile-api)s. |
|
|
62
61
|
|
|
62
|
+
#### Filtering:
|
|
63
|
+
|
|
64
|
+
The `RarFilesPackage.parse()` method accepts one optional parameter that should be an object of options.
|
|
65
|
+
|
|
66
|
+
As parsing is done sequencially, `opts.filter` and `opts.maxFiles` can be used to filter and limit results.
|
|
67
|
+
|
|
68
|
+
Here is an example:
|
|
69
|
+
```
|
|
70
|
+
{
|
|
71
|
+
filter: (fileName, fileIdx) => {
|
|
72
|
+
if (fileName.includes('Lorem Ipsum')) {
|
|
73
|
+
return true;
|
|
74
|
+
} else if (fileIdx === 9) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
},
|
|
79
|
+
maxFiles: 1
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The filter function will be called on each file entry from within the RAR archive and it will always include the name of the file and the file index. The filter function is expected to return a boolean value, if the returned value is `true` the file will be included in the parser's results.
|
|
84
|
+
|
|
85
|
+
The parser will stop processing the file list once it reaches the `maxFiles` limit of returned files.
|
|
86
|
+
|
|
63
87
|
#### Events:
|
|
64
88
|
|
|
65
89
|
| Event | Description |
|
|
@@ -84,10 +108,10 @@ Implements the [`FileMedia`](#filemedia-interface) interface.
|
|
|
84
108
|
|
|
85
109
|
#### Methods:
|
|
86
110
|
|
|
87
|
-
| Method | Description
|
|
88
|
-
| ---------------------------------------------- |
|
|
89
|
-
| createReadStream({start: number, end: number}) | Returns a `Readable` stream. The start and end interval is inclusive.
|
|
90
|
-
| readToEnd | Returns a Promise with a Buffer containing all the content of the file.
|
|
111
|
+
| Method | Description |
|
|
112
|
+
| ---------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
113
|
+
| createReadStream({start: number, end: number}) | Returns a Promise with a `Readable` stream. The start and end interval is inclusive. |
|
|
114
|
+
| readToEnd | Returns a Promise with a Buffer containing all the content of the file. |
|
|
91
115
|
|
|
92
116
|
#### Properties:
|
|
93
117
|
|
|
@@ -100,7 +124,7 @@ Implements the [`FileMedia`](#filemedia-interface) interface.
|
|
|
100
124
|
|
|
101
125
|
```
|
|
102
126
|
const innerFiles = await rarStreamPackage.parse();
|
|
103
|
-
const innerFileStream = innerFiles[0].createReadStream({ start: 0, end: 30});
|
|
127
|
+
const innerFileStream = await innerFiles[0].createReadStream({ start: 0, end: 30});
|
|
104
128
|
```
|
|
105
129
|
|
|
106
130
|
### _FileMedia Interface_
|
|
@@ -112,7 +136,7 @@ Should have the following shape:
|
|
|
112
136
|
```javascript
|
|
113
137
|
// FileMedia
|
|
114
138
|
{
|
|
115
|
-
createReadStream(interval: Interval): Readable
|
|
139
|
+
createReadStream(interval: Interval): Promise<Readable>,
|
|
116
140
|
name: string,
|
|
117
141
|
length: number // Length or size of the file in bytes
|
|
118
142
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ var _events = require('events');
|
|
|
4
4
|
// src/rar-file-bundle.ts
|
|
5
5
|
var RXX_EXTENSION = /\.R(\d\d)$|.RAR$/i;
|
|
6
6
|
var RAR_EXTENSION = /.RAR$/i;
|
|
7
|
-
var PARTXX_RAR_EXTENSION = /.PART(\d\d).RAR/i;
|
|
7
|
+
var PARTXX_RAR_EXTENSION = /.PART(\d\d?\d?).RAR/i;
|
|
8
8
|
var isPartXXExtension = (fileMedias = []) => {
|
|
9
9
|
let anyPartXXTypes = fileMedias.filter(
|
|
10
10
|
(file) => file.name && file.name.match(PARTXX_RAR_EXTENSION)
|
|
@@ -137,12 +137,12 @@ var InnerFileStream = class extends _stream.Readable {
|
|
|
137
137
|
get isStarted() {
|
|
138
138
|
return !!this.stream;
|
|
139
139
|
}
|
|
140
|
-
next() {
|
|
140
|
+
async next() {
|
|
141
141
|
const chunk = this.rarFileChunks.shift();
|
|
142
142
|
if (!chunk) {
|
|
143
143
|
this.push(null);
|
|
144
144
|
} else {
|
|
145
|
-
this.stream = chunk.getStream();
|
|
145
|
+
this.stream = await chunk.getStream();
|
|
146
146
|
_optionalChain([this, 'access', _4 => _4.stream, 'optionalAccess', _5 => _5.on, 'call', _6 => _6("data", (data) => this.pushData(data))]);
|
|
147
147
|
_optionalChain([this, 'access', _7 => _7.stream, 'optionalAccess', _8 => _8.on, 'call', _9 => _9("end", () => this.next())]);
|
|
148
148
|
}
|
|
@@ -193,10 +193,9 @@ var InnerFile = class {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
|
|
196
|
-
readToEnd() {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
);
|
|
196
|
+
async readToEnd() {
|
|
197
|
+
const stream = await this.createReadStream({ start: 0, end: this.length - 1 });
|
|
198
|
+
return streamToBuffer(stream);
|
|
200
199
|
}
|
|
201
200
|
getChunksToStream(fileStart, fileEnd) {
|
|
202
201
|
const { index: startIndex, start: startOffset } = this.findMappedChunk(fileStart);
|
|
@@ -224,7 +223,9 @@ var InnerFile = class {
|
|
|
224
223
|
if (start < 0 || end >= this.length) {
|
|
225
224
|
throw Error("Illegal start/end offset");
|
|
226
225
|
}
|
|
227
|
-
return
|
|
226
|
+
return Promise.resolve(
|
|
227
|
+
new InnerFileStream(this.getChunksToStream(start, end))
|
|
228
|
+
);
|
|
228
229
|
}
|
|
229
230
|
calculateChunkMap(rarFileChunks) {
|
|
230
231
|
const chunkMap = [];
|
|
@@ -404,7 +405,7 @@ var TerminatorHeaderParser = (_class4 = class {
|
|
|
404
405
|
|
|
405
406
|
// src/rar-files-package.ts
|
|
406
407
|
var parseHeader = async (Parser, fileMedia, offset = 0) => {
|
|
407
|
-
const stream = fileMedia.createReadStream({
|
|
408
|
+
const stream = await fileMedia.createReadStream({
|
|
408
409
|
start: offset,
|
|
409
410
|
end: offset + Parser.HEADER_SIZE
|
|
410
411
|
});
|
|
@@ -418,7 +419,7 @@ var RarFilesPackage = class extends _events.EventEmitter {
|
|
|
418
419
|
super();
|
|
419
420
|
this.rarFileBundle = makeRarFileBundle(fileMedias);
|
|
420
421
|
}
|
|
421
|
-
async parseFile(rarFile) {
|
|
422
|
+
async parseFile(rarFile, opts) {
|
|
422
423
|
const fileChunks = [];
|
|
423
424
|
let fileOffset = 0;
|
|
424
425
|
const markerHead = await parseHeader(MarkerHeaderParser, rarFile);
|
|
@@ -429,36 +430,58 @@ var RarFilesPackage = class extends _events.EventEmitter {
|
|
|
429
430
|
fileOffset
|
|
430
431
|
);
|
|
431
432
|
fileOffset += archiveHeader.size;
|
|
433
|
+
let countFiles = 0;
|
|
434
|
+
let retrievedFiles = 0;
|
|
432
435
|
while (fileOffset < rarFile.length - TerminatorHeaderParser.HEADER_SIZE) {
|
|
436
|
+
let getFileChunk2 = function() {
|
|
437
|
+
if (fileHead.method !== 48) {
|
|
438
|
+
throw new Error("Decompression is not implemented");
|
|
439
|
+
}
|
|
440
|
+
return {
|
|
441
|
+
name: fileHead.name,
|
|
442
|
+
fileHead,
|
|
443
|
+
chunk: new RarFileChunk(
|
|
444
|
+
rarFile,
|
|
445
|
+
fileOffset,
|
|
446
|
+
fileOffset + fileHead.size - 1
|
|
447
|
+
)
|
|
448
|
+
};
|
|
449
|
+
};
|
|
450
|
+
var getFileChunk = getFileChunk2;
|
|
433
451
|
const fileHead = await parseHeader(FileHeaderParser, rarFile, fileOffset);
|
|
434
452
|
if (fileHead.type !== 116) {
|
|
435
453
|
break;
|
|
436
454
|
}
|
|
437
|
-
if (fileHead.method !== 48) {
|
|
438
|
-
throw new Error("Decompression is not implemented");
|
|
439
|
-
}
|
|
440
455
|
fileOffset += fileHead.headSize;
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
456
|
+
if (opts.filter) {
|
|
457
|
+
if (opts.filter(fileHead.name, countFiles)) {
|
|
458
|
+
fileChunks.push(getFileChunk2());
|
|
459
|
+
retrievedFiles++;
|
|
460
|
+
if (opts.hasOwnProperty("maxFiles") && retrievedFiles === opts.maxFiles) {
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
} else {
|
|
465
|
+
fileChunks.push(getFileChunk2());
|
|
466
|
+
}
|
|
450
467
|
fileOffset += fileHead.size;
|
|
468
|
+
countFiles++;
|
|
451
469
|
}
|
|
452
470
|
this.emit("file-parsed", rarFile);
|
|
453
471
|
return fileChunks;
|
|
454
472
|
}
|
|
455
|
-
async parse() {
|
|
473
|
+
async parse(opts) {
|
|
474
|
+
opts = opts || {};
|
|
456
475
|
this.emit("parsing-start", this.rarFileBundle);
|
|
457
476
|
const parsedFileChunks = [];
|
|
458
477
|
const { files } = this.rarFileBundle;
|
|
459
478
|
for (let i = 0; i < files.length; ++i) {
|
|
460
479
|
const file = files[i];
|
|
461
|
-
const chunks = await this.parseFile(file);
|
|
480
|
+
const chunks = await this.parseFile(file, opts);
|
|
481
|
+
if (!chunks.length) {
|
|
482
|
+
this.emit("parsing-complete", []);
|
|
483
|
+
return [];
|
|
484
|
+
}
|
|
462
485
|
const { fileHead, chunk } = chunks[chunks.length - 1];
|
|
463
486
|
const chunkSize = Math.abs(chunk.endOffset - chunk.startOffset);
|
|
464
487
|
let innerFileSize = fileHead.unpackedSize;
|
|
@@ -506,7 +529,9 @@ var LocalFileMedia = class {
|
|
|
506
529
|
|
|
507
530
|
|
|
508
531
|
createReadStream(interval) {
|
|
509
|
-
return
|
|
532
|
+
return Promise.resolve(
|
|
533
|
+
_fs.createReadStream.call(void 0, this.path, interval)
|
|
534
|
+
);
|
|
510
535
|
}
|
|
511
536
|
};
|
|
512
537
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rar-files-package.ts","../src/rar-file-bundle.ts","../src/rar-file-chunk.ts","../src/inner-file-stream.ts","../src/stream-utils.ts","../src/utils.ts","../src/inner-file.ts","../src/parsing/marker-header-parser.ts","../src/parsing/archive-header-parser.ts","../src/parsing/file-header-parser.ts","../src/parsing/terminator-header-parser.ts","../src/local-file-media.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"events\";\nimport { makeRarFileBundle, RarFileBundle } from \"./rar-file-bundle.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { InnerFile } from \"./inner-file.js\";\n\nimport { MarkerHeaderParser } from \"./parsing/marker-header-parser.js\";\nimport { ArchiveHeaderParser } from \"./parsing/archive-header-parser.js\";\nimport { FileHeaderParser, IFileHeader } from \"./parsing/file-header-parser.js\";\nimport { TerminatorHeaderParser } from \"./parsing/terminator-header-parser.js\";\n\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { IFileMedia, IParser, IParsers } from \"./interfaces.js\";\nimport { groupBy, mapValues } from \"./utils.js\";\n\nconst parseHeader = async <T extends IParsers>(\n Parser: IParser<T>,\n fileMedia: IFileMedia,\n offset = 0\n) => {\n const stream = fileMedia.createReadStream({\n start: offset,\n end: offset + Parser.HEADER_SIZE,\n });\n const headerBuffer = await streamToBuffer(stream);\n const parser = new Parser(headerBuffer);\n return parser.parse() as ReturnType<T[\"parse\"]>;\n};\ninterface ParsedFileChunkMapping {\n name: string;\n chunk: RarFileChunk;\n}\ninterface FileChunkMapping extends ParsedFileChunkMapping {\n fileHead: IFileHeader;\n}\n\nexport class RarFilesPackage extends EventEmitter {\n rarFileBundle: RarFileBundle;\n constructor(fileMedias: IFileMedia[]) {\n super();\n this.rarFileBundle = makeRarFileBundle(fileMedias);\n }\n async parseFile(rarFile: IFileMedia) {\n const fileChunks: FileChunkMapping[] = [];\n let fileOffset = 0;\n const markerHead = await parseHeader(MarkerHeaderParser, rarFile);\n fileOffset += markerHead.size;\n\n const archiveHeader = await parseHeader(\n ArchiveHeaderParser,\n rarFile,\n fileOffset\n );\n fileOffset += archiveHeader.size;\n\n while (fileOffset < rarFile.length - TerminatorHeaderParser.HEADER_SIZE) {\n const fileHead = await parseHeader(FileHeaderParser, rarFile, fileOffset);\n if (fileHead.type !== 116) {\n break;\n }\n if (fileHead.method !== 0x30) {\n throw new Error(\"Decompression is not implemented\");\n }\n fileOffset += fileHead.headSize;\n\n fileChunks.push({\n name: fileHead.name,\n fileHead,\n chunk: new RarFileChunk(\n rarFile,\n fileOffset,\n fileOffset + fileHead.size - 1\n ),\n });\n fileOffset += fileHead.size;\n }\n this.emit(\"file-parsed\", rarFile);\n return fileChunks;\n }\n async parse(): Promise<InnerFile[]> {\n this.emit(\"parsing-start\", this.rarFileBundle);\n const parsedFileChunks: ParsedFileChunkMapping[][] = [];\n const { files } = this.rarFileBundle;\n for (let i = 0; i < files.length; ++i) {\n const file = files[i]!;\n\n const chunks = await this.parseFile(file);\n const { fileHead, chunk } = chunks[chunks.length - 1]!;\n const chunkSize = Math.abs(chunk.endOffset - chunk.startOffset);\n let innerFileSize = fileHead.unpackedSize;\n parsedFileChunks.push(chunks);\n\n if (fileHead.continuesInNext) {\n while (Math.abs(innerFileSize - chunkSize) >= chunkSize) {\n const nextFile = files[++i]!;\n\n parsedFileChunks.push([\n {\n name: fileHead.name,\n chunk: new RarFileChunk(\n nextFile,\n chunk.startOffset,\n chunk.endOffset\n ),\n },\n ]);\n this.emit(\"file-parsed\", nextFile);\n innerFileSize -= chunkSize;\n }\n }\n }\n\n const fileChunks = parsedFileChunks.flat();\n\n const grouped = mapValues(\n groupBy(fileChunks, (f) => f.name),\n (value) => value.map((v) => v.chunk)\n );\n\n const innerFiles = Object.entries(grouped).map(\n ([name, chunks]) => new InnerFile(name, chunks)\n );\n\n this.emit(\"parsing-complete\", innerFiles);\n return innerFiles;\n }\n}\n","const RXX_EXTENSION = /\\.R(\\d\\d)$|.RAR$/i;\nconst RAR_EXTENSION = /.RAR$/i;\nconst PARTXX_RAR_EXTENSION = /.PART(\\d\\d).RAR/i;\nimport { IFileMedia } from \"./interfaces.js\";\n\nconst isPartXXExtension = (fileMedias: IFileMedia[] = []) => {\n let anyPartXXTypes = fileMedias.filter(\n (file) => file.name && file.name.match(PARTXX_RAR_EXTENSION)\n );\n\n if (anyPartXXTypes.length > 0) {\n return true;\n } else {\n return false;\n }\n};\n\nclass NumericRarFileBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter(\n (file) => file.name && file.name.match(RXX_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n if (first.name.match(RAR_EXTENSION)) {\n return -1;\n } else if (second.name.match(RAR_EXTENSION)) {\n return 1;\n } else {\n const firstMatch = first.name.match(RXX_EXTENSION);\n const secondMatch = second.name.match(RXX_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n }\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nclass PartXXRarBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter((file) =>\n file.name.match(PARTXX_RAR_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n const firstMatch = first.name.match(PARTXX_RAR_EXTENSION);\n const secondMatch = second.name.match(PARTXX_RAR_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nexport type RarFileBundle = PartXXRarBundle | NumericRarFileBundle;\nexport const makeRarFileBundle = (\n fileMedias: IFileMedia[] = []\n): RarFileBundle => {\n return isPartXXExtension(fileMedias)\n ? new PartXXRarBundle(fileMedias)\n : new NumericRarFileBundle(fileMedias);\n};\n","import { IFileMedia } from \"./interfaces.js\";\n\nexport class RarFileChunk {\n constructor(\n private fileMedia: IFileMedia,\n public startOffset: number,\n public endOffset: number\n ) {}\n padEnd(endPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset,\n this.endOffset - endPadding\n );\n }\n padStart(startPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset + startPadding,\n this.endOffset\n );\n }\n get length() {\n return Math.max(0, this.endOffset - this.startOffset);\n }\n getStream() {\n return this.fileMedia.createReadStream({\n start: this.startOffset,\n end: this.endOffset,\n });\n }\n}\n","import { Readable, ReadableOptions } from \"stream\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\n\nexport class InnerFileStream extends Readable {\n stream?: NodeJS.ReadableStream;\n constructor(\n private rarFileChunks: RarFileChunk[],\n options?: ReadableOptions\n ) {\n super(options);\n }\n pushData(data: Uint16Array) {\n if (!this.push(data)) {\n this.stream?.pause();\n }\n }\n get isStarted() {\n return !!this.stream;\n }\n next() {\n const chunk = this.rarFileChunks.shift();\n\n if (!chunk) {\n this.push(null);\n } else {\n this.stream = chunk.getStream();\n this.stream?.on(\"data\", (data) => this.pushData(data));\n this.stream?.on(\"end\", () => this.next());\n }\n }\n override _read() {\n if (!this.isStarted) {\n this.next();\n } else {\n this.stream?.resume();\n }\n }\n}\n","import { Stream, Duplex } from \"stream\";\n\nexport const streamToBuffer = async (stream: Stream | NodeJS.ReadableStream): Promise<Buffer> =>\n new Promise((resolve, reject) => {\n const buffers: Uint8Array[] = [];\n stream.on(\"error\", reject);\n stream.on(\"data\", (data) => buffers.push(data));\n stream.on(\"end\", () => resolve(Buffer.concat(buffers)));\n });\n\nexport const bufferToStream = (buffer: Buffer): Stream => {\n const stream = new Duplex();\n stream.push(buffer);\n stream.push(null);\n return stream;\n};\n","export function groupBy<T>(arr: T[], fn: (item: T) => any) {\n return arr.reduce<Record<string, T[]>>((prev, curr) => {\n const groupKey = fn(curr);\n const group = prev[groupKey] || [];\n group.push(curr);\n return { ...prev, [groupKey]: group };\n }, {});\n}\n\nexport function sum(arr: number[]) {\n return arr.reduce((s, n) => s + n);\n}\nexport function mapValues<T extends Object, S>(\n object: T,\n mapper: (value: T[keyof T]) => S\n) {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [key, mapper(value)])\n ) as { [key in keyof T]: S };\n}\n","import { IFileMedia, IReadInterval } from \"./interfaces.js\";\nimport { InnerFileStream } from \"./inner-file-stream.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { sum } from \"./utils.js\";\ntype ChunkMapEntry = {\n index: number;\n start: number;\n end: number;\n chunk: RarFileChunk;\n};\n\nexport class InnerFile implements IFileMedia {\n length: number;\n\n chunkMap: ChunkMapEntry[];\n constructor(public name: string, private rarFileChunks: RarFileChunk[]) {\n this.length = sum(rarFileChunks.map((c) => c.length));\n this.chunkMap = this.calculateChunkMap(rarFileChunks);\n\n this.name = name;\n }\n readToEnd() {\n return streamToBuffer(\n this.createReadStream({ start: 0, end: this.length - 1 })\n );\n }\n getChunksToStream(fileStart: number, fileEnd: number) {\n const { index: startIndex, start: startOffset } =\n this.findMappedChunk(fileStart);\n let { index: endIndex, end: endOffset } = this.findMappedChunk(fileEnd);\n\n const chunksToStream = this.rarFileChunks.slice(startIndex, endIndex + 1);\n\n const last = chunksToStream.length - 1;\n const first = 0;\n chunksToStream[first] = chunksToStream[first]!.padStart(\n Math.abs(startOffset - fileStart)\n );\n\n let diff = Math.abs(endOffset - fileEnd);\n if (diff === this.rarFileChunks.length) {\n diff = 0;\n }\n if (diff !== 0) {\n chunksToStream[last] = chunksToStream[last]!.padEnd(diff);\n }\n\n return chunksToStream;\n }\n createReadStream(interval: IReadInterval) {\n if (!interval) {\n interval = { start: 0, end: this.length - 1 };\n }\n let { start, end } = interval;\n\n if (start < 0 || end >= this.length) {\n throw Error(\"Illegal start/end offset\");\n }\n\n return new InnerFileStream(this.getChunksToStream(start, end));\n }\n calculateChunkMap(rarFileChunks: RarFileChunk[]) {\n const chunkMap: ChunkMapEntry[] = [];\n let index = 0;\n let fileOffset = 0;\n for (const chunk of rarFileChunks) {\n const start = fileOffset;\n const end = fileOffset + chunk.length;\n fileOffset = end + 1;\n\n chunkMap.push({ index, start, end, chunk });\n index++;\n }\n\n return chunkMap;\n }\n findMappedChunk(offset: number) {\n let selectedMap = this.chunkMap[0]!;\n for (const chunkMapping of this.chunkMap) {\n if (offset >= chunkMapping.start && offset <= chunkMapping.end) {\n selectedMap = chunkMapping;\n break;\n }\n }\n return selectedMap;\n }\n}\n","export class MarkerHeaderParser {\n static HEADER_SIZE = 11;\n constructor(private headerBuffer: Buffer) {}\n\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n let size = this.headerBuffer.readUInt16LE(5);\n if ((flags & 0x8000) !== 0) {\n let addSize = this.headerBuffer.readUint32LE(7);\n size += addSize || 0;\n }\n return { crc, type, flags, size };\n }\n}\n","interface IArchiveHeader {\n crc: number;\n type: number;\n flags: number;\n size: number;\n reserved1: number;\n reserved2: number;\n}\n\nfunction parseFlags(parsedVars: IArchiveHeader) {\n return {\n hasVolumeAttributes: (parsedVars.flags & 0x0001) !== 0,\n hasComment: (parsedVars.flags & 0x0002) !== 0,\n isLocked: (parsedVars.flags & 0x0004) !== 0,\n hasSolidAttributes: (parsedVars.flags & 0x0008) !== 0,\n isNewNameScheme: (parsedVars.flags & 0x00010) !== 0,\n hasAuthInfo: (parsedVars.flags & 0x0020) !== 0,\n hasRecovery: (parsedVars.flags & 0x0040) !== 0,\n isBlockEncoded: (parsedVars.flags & 0x0080) !== 0,\n isFirstVolume: (parsedVars.flags & 0x0100) !== 0,\n };\n}\nexport class ArchiveHeaderParser {\n static HEADER_SIZE = 13;\n constructor(private buffer: Buffer) {}\n parse() {\n const crc = this.buffer.readUInt16LE(0);\n const type = this.buffer.readUInt8(2);\n const flags = this.buffer.readUInt16LE(3);\n let size = this.buffer.readUInt16LE(5);\n const reserved1 = this.buffer.readUInt16LE(7);\n const reserved2 = this.buffer.readUInt32LE(9);\n\n let vars = { crc, type, flags, size, reserved1, reserved2 };\n\n return { ...parseFlags(vars), ...vars };\n }\n}\n","interface IFileHeaderFlags {\n continuesFromPrevious: boolean;\n continuesInNext: boolean;\n isEncrypted: boolean;\n hasComment: boolean;\n hasInfoFromPrevious: boolean;\n hasHighSize: boolean;\n hasSpecialName: boolean;\n hasSalt: boolean;\n isOldVersion: boolean;\n hasExtendedTime: boolean;\n}\n\ninterface IFileHeaderRaw {\n crc: number;\n type: number;\n flags: number;\n headSize: number;\n size: number;\n unpackedSize: number;\n host: number;\n fileCrc: number;\n timestamp: number;\n version: number;\n method: number;\n nameSize: number;\n attributes: number;\n name: string;\n}\n\nexport type IFileHeader = IFileHeaderRaw & IFileHeaderFlags;\nexport class FileHeaderParser {\n static HEADER_SIZE = 280;\n offset = 0;\n constructor(private buffer: Buffer) {}\n private handleHighFileSize(parsedVars: IFileHeader) {\n if (parsedVars.hasHighSize) {\n const highPackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n const highUnpackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n parsedVars.size = highPackSize * 0x100000000 + parsedVars.size;\n parsedVars.unpackedSize =\n highUnpackSize * 0x100000000 + parsedVars.unpackedSize;\n }\n }\n private parseFileName(parsedVars: IFileHeaderRaw) {\n parsedVars.name = this.buffer\n .subarray(this.offset, this.offset + parsedVars.nameSize)\n .toString(\"utf-8\");\n }\n private parseFlags(parsedVars: IFileHeaderRaw): IFileHeaderFlags {\n return {\n continuesFromPrevious: (parsedVars.flags & 0x01) !== 0,\n continuesInNext: (parsedVars.flags & 0x02) !== 0,\n isEncrypted: (parsedVars.flags & 0x04) !== 0,\n hasComment: (parsedVars.flags & 0x08) !== 0,\n hasInfoFromPrevious: (parsedVars.flags & 0x10) !== 0,\n hasHighSize: (parsedVars.flags & 0x100) !== 0,\n hasSpecialName: (parsedVars.flags & 0x200) !== 0,\n hasSalt: (parsedVars.flags & 0x400) !== 0,\n isOldVersion: (parsedVars.flags & 0x800) !== 0,\n hasExtendedTime: (parsedVars.flags & 0x1000) !== 0,\n };\n }\n parse(): IFileHeader {\n const crc = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const type = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const flags = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const headSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const size = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const unpackedSize = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const host = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const fileCrc = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const timestamp = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const version = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const method = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const nameSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const attributes = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n let vars: IFileHeaderRaw = {\n crc,\n type,\n flags,\n headSize,\n size,\n unpackedSize,\n host,\n fileCrc,\n timestamp,\n version,\n method,\n nameSize,\n attributes,\n name: \"\",\n };\n\n const boolFlags = this.parseFlags(vars);\n const header = { ...vars, ...boolFlags };\n this.handleHighFileSize(header);\n this.parseFileName(header);\n this.offset = 0;\n return header;\n }\n}\n","export class TerminatorHeaderParser {\n static HEADER_SIZE = 27;\n constructor(private headerBuffer: Buffer) {}\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n const size = this.headerBuffer.readUInt16LE(5);\n return { crc, type, flags, size };\n }\n}\n","import { basename } from \"path\";\nimport { statSync, createReadStream } from \"fs\";\nimport { IFileMedia, IReadInterval } from \"./interfaces.js\";\n\nexport class LocalFileMedia implements IFileMedia {\n name: string;\n length: number;\n constructor(private path: string) {\n this.name = basename(path);\n this.length = statSync(path).size;\n }\n createReadStream(interval: IReadInterval) {\n return createReadStream(this.path, interval);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/Users/pejo/projects/rar-stream/dist/index.cjs","../src/rar-files-package.ts","../src/rar-file-bundle.ts","../src/rar-file-chunk.ts","../src/inner-file-stream.ts","../src/stream-utils.ts","../src/utils.ts","../src/inner-file.ts","../src/parsing/marker-header-parser.ts","../src/parsing/archive-header-parser.ts","../src/parsing/file-header-parser.ts","../src/parsing/terminator-header-parser.ts","../src/local-file-media.ts"],"names":["getFileChunk"],"mappings":"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","file":"/Users/pejo/projects/rar-stream/dist/index.cjs","sourcesContent":[null,"import { EventEmitter } from \"events\";\nimport { makeRarFileBundle, RarFileBundle } from \"./rar-file-bundle.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { InnerFile } from \"./inner-file.js\";\n\nimport { MarkerHeaderParser } from \"./parsing/marker-header-parser.js\";\nimport { ArchiveHeaderParser } from \"./parsing/archive-header-parser.js\";\nimport { FileHeaderParser, IFileHeader } from \"./parsing/file-header-parser.js\";\nimport { TerminatorHeaderParser } from \"./parsing/terminator-header-parser.js\";\n\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { IFileMedia, IParser, IParsers, FindOpts } from \"./interfaces.js\";\nimport { groupBy, mapValues } from \"./utils.js\";\n\nconst parseHeader = async <T extends IParsers>(\n Parser: IParser<T>,\n fileMedia: IFileMedia,\n offset = 0\n) => {\n const stream = await fileMedia.createReadStream({\n start: offset,\n end: offset + Parser.HEADER_SIZE,\n });\n const headerBuffer = await streamToBuffer(stream);\n const parser = new Parser(headerBuffer);\n return parser.parse() as ReturnType<T[\"parse\"]>;\n};\ninterface ParsedFileChunkMapping {\n name: string;\n chunk: RarFileChunk;\n}\ninterface FileChunkMapping extends ParsedFileChunkMapping {\n fileHead: IFileHeader;\n}\n\nexport class RarFilesPackage extends EventEmitter {\n rarFileBundle: RarFileBundle;\n constructor(fileMedias: IFileMedia[]) {\n super();\n this.rarFileBundle = makeRarFileBundle(fileMedias);\n }\n async parseFile(rarFile: IFileMedia, opts: FindOpts) {\n const fileChunks: FileChunkMapping[] = [];\n let fileOffset = 0;\n const markerHead = await parseHeader(MarkerHeaderParser, rarFile);\n fileOffset += markerHead.size;\n\n const archiveHeader = await parseHeader(\n ArchiveHeaderParser,\n rarFile,\n fileOffset\n );\n fileOffset += archiveHeader.size;\n\n let countFiles = 0;\n let retrievedFiles = 0;\n while (fileOffset < rarFile.length - TerminatorHeaderParser.HEADER_SIZE) {\n const fileHead = await parseHeader(FileHeaderParser, rarFile, fileOffset);\n if (fileHead.type !== 116) {\n break;\n }\n fileOffset += fileHead.headSize;\n function getFileChunk() {\n if (fileHead.method !== 0x30) {\n throw new Error(\"Decompression is not implemented\");\n }\n return {\n name: fileHead.name,\n fileHead,\n chunk: new RarFileChunk(\n rarFile,\n fileOffset,\n fileOffset + fileHead.size - 1\n ),\n };\n }\n if (opts.filter) {\n if (opts.filter(fileHead.name, countFiles)) {\n fileChunks.push(getFileChunk());\n retrievedFiles++;\n if (opts.hasOwnProperty('maxFiles') && retrievedFiles === opts.maxFiles) {\n break;\n }\n }\n } else {\n fileChunks.push(getFileChunk());\n }\n fileOffset += fileHead.size;\n countFiles++;\n }\n this.emit(\"file-parsed\", rarFile);\n return fileChunks;\n }\n async parse(opts: FindOpts): Promise<InnerFile[]> {\n opts = opts || {};\n this.emit(\"parsing-start\", this.rarFileBundle);\n const parsedFileChunks: ParsedFileChunkMapping[][] = [];\n const { files } = this.rarFileBundle;\n for (let i = 0; i < files.length; ++i) {\n const file = files[i]!;\n\n const chunks = await this.parseFile(file, opts);\n if (!chunks.length) {\n this.emit(\"parsing-complete\", []);\n return [];\n }\n const { fileHead, chunk } = chunks[chunks.length - 1]!;\n const chunkSize = Math.abs(chunk.endOffset - chunk.startOffset);\n let innerFileSize = fileHead.unpackedSize;\n parsedFileChunks.push(chunks);\n\n if (fileHead.continuesInNext) {\n while (Math.abs(innerFileSize - chunkSize) >= chunkSize) {\n const nextFile = files[++i]!;\n\n parsedFileChunks.push([\n {\n name: fileHead.name,\n chunk: new RarFileChunk(\n nextFile,\n chunk.startOffset,\n chunk.endOffset\n ),\n },\n ]);\n this.emit(\"file-parsed\", nextFile);\n innerFileSize -= chunkSize;\n }\n }\n }\n\n const fileChunks = parsedFileChunks.flat();\n\n const grouped = mapValues(\n groupBy(fileChunks, (f) => f.name),\n (value) => value.map((v) => v.chunk)\n );\n\n const innerFiles = Object.entries(grouped).map(\n ([name, chunks]) => new InnerFile(name, chunks)\n );\n\n this.emit(\"parsing-complete\", innerFiles);\n return innerFiles;\n }\n}\n","const RXX_EXTENSION = /\\.R(\\d\\d)$|.RAR$/i;\nconst RAR_EXTENSION = /.RAR$/i;\nconst PARTXX_RAR_EXTENSION = /.PART(\\d\\d?\\d?).RAR/i;\nimport { IFileMedia } from \"./interfaces.js\";\n\nconst isPartXXExtension = (fileMedias: IFileMedia[] = []) => {\n let anyPartXXTypes = fileMedias.filter(\n (file) => file.name && file.name.match(PARTXX_RAR_EXTENSION)\n );\n\n if (anyPartXXTypes.length > 0) {\n return true;\n } else {\n return false;\n }\n};\n\nclass NumericRarFileBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter(\n (file) => file.name && file.name.match(RXX_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n if (first.name.match(RAR_EXTENSION)) {\n return -1;\n } else if (second.name.match(RAR_EXTENSION)) {\n return 1;\n } else {\n const firstMatch = first.name.match(RXX_EXTENSION);\n const secondMatch = second.name.match(RXX_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n }\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nclass PartXXRarBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter((file) =>\n file.name.match(PARTXX_RAR_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n const firstMatch = first.name.match(PARTXX_RAR_EXTENSION);\n const secondMatch = second.name.match(PARTXX_RAR_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nexport type RarFileBundle = PartXXRarBundle | NumericRarFileBundle;\nexport const makeRarFileBundle = (\n fileMedias: IFileMedia[] = []\n): RarFileBundle => {\n return isPartXXExtension(fileMedias)\n ? new PartXXRarBundle(fileMedias)\n : new NumericRarFileBundle(fileMedias);\n};\n","import { IFileMedia } from \"./interfaces.js\";\n\nexport class RarFileChunk {\n constructor(\n private fileMedia: IFileMedia,\n public startOffset: number,\n public endOffset: number\n ) {}\n padEnd(endPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset,\n this.endOffset - endPadding\n );\n }\n padStart(startPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset + startPadding,\n this.endOffset\n );\n }\n get length() {\n return Math.max(0, this.endOffset - this.startOffset);\n }\n getStream() {\n return this.fileMedia.createReadStream({\n start: this.startOffset,\n end: this.endOffset,\n });\n }\n}\n","import { Readable, ReadableOptions } from \"stream\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\n\nexport class InnerFileStream extends Readable {\n stream?: NodeJS.ReadableStream;\n constructor(\n private rarFileChunks: RarFileChunk[],\n options?: ReadableOptions\n ) {\n super(options);\n }\n pushData(data: Uint16Array) {\n if (!this.push(data)) {\n this.stream?.pause();\n }\n }\n get isStarted() {\n return !!this.stream;\n }\n async next() {\n const chunk = this.rarFileChunks.shift();\n\n if (!chunk) {\n this.push(null);\n } else {\n this.stream = await chunk.getStream();\n this.stream?.on(\"data\", (data) => this.pushData(data));\n this.stream?.on(\"end\", () => this.next());\n }\n }\n override _read() {\n if (!this.isStarted) {\n this.next();\n } else {\n this.stream?.resume();\n }\n }\n}\n","import { Stream, Duplex } from \"stream\";\n\nexport const streamToBuffer = async (stream: Stream | NodeJS.ReadableStream): Promise<Buffer> =>\n new Promise((resolve, reject) => {\n const buffers: Uint8Array[] = [];\n stream.on(\"error\", reject);\n stream.on(\"data\", (data) => buffers.push(data));\n stream.on(\"end\", () => resolve(Buffer.concat(buffers)));\n });\n\nexport const bufferToStream = (buffer: Buffer): Stream => {\n const stream = new Duplex();\n stream.push(buffer);\n stream.push(null);\n return stream;\n};\n","export function groupBy<T>(arr: T[], fn: (item: T) => any) {\n return arr.reduce<Record<string, T[]>>((prev, curr) => {\n const groupKey = fn(curr);\n const group = prev[groupKey] || [];\n group.push(curr);\n return { ...prev, [groupKey]: group };\n }, {});\n}\n\nexport function sum(arr: number[]) {\n return arr.reduce((s, n) => s + n);\n}\nexport function mapValues<T extends Object, S>(\n object: T,\n mapper: (value: T[keyof T]) => S\n) {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [key, mapper(value)])\n ) as { [key in keyof T]: S };\n}\n","import { IFileMedia, IReadInterval } from \"./interfaces.js\";\nimport { InnerFileStream } from \"./inner-file-stream.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { sum } from \"./utils.js\";\ntype ChunkMapEntry = {\n index: number;\n start: number;\n end: number;\n chunk: RarFileChunk;\n};\n\nexport class InnerFile implements IFileMedia {\n length: number;\n\n chunkMap: ChunkMapEntry[];\n constructor(public name: string, private rarFileChunks: RarFileChunk[]) {\n this.length = sum(rarFileChunks.map((c) => c.length));\n this.chunkMap = this.calculateChunkMap(rarFileChunks);\n\n this.name = name;\n }\n async readToEnd() {\n const stream = await this.createReadStream({ start: 0, end: this.length - 1 });\n return streamToBuffer(stream);\n }\n getChunksToStream(fileStart: number, fileEnd: number) {\n const { index: startIndex, start: startOffset } =\n this.findMappedChunk(fileStart);\n let { index: endIndex, end: endOffset } = this.findMappedChunk(fileEnd);\n\n const chunksToStream = this.rarFileChunks.slice(startIndex, endIndex + 1);\n\n const last = chunksToStream.length - 1;\n const first = 0;\n chunksToStream[first] = chunksToStream[first]!.padStart(\n Math.abs(startOffset - fileStart)\n );\n\n let diff = Math.abs(endOffset - fileEnd);\n if (diff === this.rarFileChunks.length) {\n diff = 0;\n }\n if (diff !== 0) {\n chunksToStream[last] = chunksToStream[last]!.padEnd(diff);\n }\n\n return chunksToStream;\n }\n createReadStream(interval: IReadInterval) {\n if (!interval) {\n interval = { start: 0, end: this.length - 1 };\n }\n let { start, end } = interval;\n\n if (start < 0 || end >= this.length) {\n throw Error(\"Illegal start/end offset\");\n }\n\n return Promise.resolve(\n new InnerFileStream(this.getChunksToStream(start, end))\n );\n }\n calculateChunkMap(rarFileChunks: RarFileChunk[]) {\n const chunkMap: ChunkMapEntry[] = [];\n let index = 0;\n let fileOffset = 0;\n for (const chunk of rarFileChunks) {\n const start = fileOffset;\n const end = fileOffset + chunk.length;\n fileOffset = end + 1;\n\n chunkMap.push({ index, start, end, chunk });\n index++;\n }\n\n return chunkMap;\n }\n findMappedChunk(offset: number) {\n let selectedMap = this.chunkMap[0]!;\n for (const chunkMapping of this.chunkMap) {\n if (offset >= chunkMapping.start && offset <= chunkMapping.end) {\n selectedMap = chunkMapping;\n break;\n }\n }\n return selectedMap;\n }\n}\n","export class MarkerHeaderParser {\n static HEADER_SIZE = 11;\n constructor(private headerBuffer: Buffer) {}\n\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n let size = this.headerBuffer.readUInt16LE(5);\n if ((flags & 0x8000) !== 0) {\n let addSize = this.headerBuffer.readUint32LE(7);\n size += addSize || 0;\n }\n return { crc, type, flags, size };\n }\n}\n","interface IArchiveHeader {\n crc: number;\n type: number;\n flags: number;\n size: number;\n reserved1: number;\n reserved2: number;\n}\n\nfunction parseFlags(parsedVars: IArchiveHeader) {\n return {\n hasVolumeAttributes: (parsedVars.flags & 0x0001) !== 0,\n hasComment: (parsedVars.flags & 0x0002) !== 0,\n isLocked: (parsedVars.flags & 0x0004) !== 0,\n hasSolidAttributes: (parsedVars.flags & 0x0008) !== 0,\n isNewNameScheme: (parsedVars.flags & 0x00010) !== 0,\n hasAuthInfo: (parsedVars.flags & 0x0020) !== 0,\n hasRecovery: (parsedVars.flags & 0x0040) !== 0,\n isBlockEncoded: (parsedVars.flags & 0x0080) !== 0,\n isFirstVolume: (parsedVars.flags & 0x0100) !== 0,\n };\n}\nexport class ArchiveHeaderParser {\n static HEADER_SIZE = 13;\n constructor(private buffer: Buffer) {}\n parse() {\n const crc = this.buffer.readUInt16LE(0);\n const type = this.buffer.readUInt8(2);\n const flags = this.buffer.readUInt16LE(3);\n let size = this.buffer.readUInt16LE(5);\n const reserved1 = this.buffer.readUInt16LE(7);\n const reserved2 = this.buffer.readUInt32LE(9);\n\n let vars = { crc, type, flags, size, reserved1, reserved2 };\n\n return { ...parseFlags(vars), ...vars };\n }\n}\n","interface IFileHeaderFlags {\n continuesFromPrevious: boolean;\n continuesInNext: boolean;\n isEncrypted: boolean;\n hasComment: boolean;\n hasInfoFromPrevious: boolean;\n hasHighSize: boolean;\n hasSpecialName: boolean;\n hasSalt: boolean;\n isOldVersion: boolean;\n hasExtendedTime: boolean;\n}\n\ninterface IFileHeaderRaw {\n crc: number;\n type: number;\n flags: number;\n headSize: number;\n size: number;\n unpackedSize: number;\n host: number;\n fileCrc: number;\n timestamp: number;\n version: number;\n method: number;\n nameSize: number;\n attributes: number;\n name: string;\n}\n\nexport type IFileHeader = IFileHeaderRaw & IFileHeaderFlags;\nexport class FileHeaderParser {\n static HEADER_SIZE = 280;\n offset = 0;\n constructor(private buffer: Buffer) {}\n private handleHighFileSize(parsedVars: IFileHeader) {\n if (parsedVars.hasHighSize) {\n const highPackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n const highUnpackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n parsedVars.size = highPackSize * 0x100000000 + parsedVars.size;\n parsedVars.unpackedSize =\n highUnpackSize * 0x100000000 + parsedVars.unpackedSize;\n }\n }\n private parseFileName(parsedVars: IFileHeaderRaw) {\n parsedVars.name = this.buffer\n .subarray(this.offset, this.offset + parsedVars.nameSize)\n .toString(\"utf-8\");\n }\n private parseFlags(parsedVars: IFileHeaderRaw): IFileHeaderFlags {\n return {\n continuesFromPrevious: (parsedVars.flags & 0x01) !== 0,\n continuesInNext: (parsedVars.flags & 0x02) !== 0,\n isEncrypted: (parsedVars.flags & 0x04) !== 0,\n hasComment: (parsedVars.flags & 0x08) !== 0,\n hasInfoFromPrevious: (parsedVars.flags & 0x10) !== 0,\n hasHighSize: (parsedVars.flags & 0x100) !== 0,\n hasSpecialName: (parsedVars.flags & 0x200) !== 0,\n hasSalt: (parsedVars.flags & 0x400) !== 0,\n isOldVersion: (parsedVars.flags & 0x800) !== 0,\n hasExtendedTime: (parsedVars.flags & 0x1000) !== 0,\n };\n }\n parse(): IFileHeader {\n const crc = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const type = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const flags = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const headSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const size = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const unpackedSize = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const host = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const fileCrc = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const timestamp = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const version = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const method = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const nameSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const attributes = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n let vars: IFileHeaderRaw = {\n crc,\n type,\n flags,\n headSize,\n size,\n unpackedSize,\n host,\n fileCrc,\n timestamp,\n version,\n method,\n nameSize,\n attributes,\n name: \"\",\n };\n\n const boolFlags = this.parseFlags(vars);\n const header = { ...vars, ...boolFlags };\n this.handleHighFileSize(header);\n this.parseFileName(header);\n this.offset = 0;\n return header;\n }\n}\n","export class TerminatorHeaderParser {\n static HEADER_SIZE = 27;\n constructor(private headerBuffer: Buffer) {}\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n const size = this.headerBuffer.readUInt16LE(5);\n return { crc, type, flags, size };\n }\n}\n","import { basename } from \"path\";\nimport { statSync, createReadStream } from \"fs\";\nimport { IFileMedia, IReadInterval } from \"./interfaces.js\";\n\nexport class LocalFileMedia implements IFileMedia {\n name: string;\n length: number;\n constructor(private path: string) {\n this.name = basename(path);\n this.length = statSync(path).size;\n }\n createReadStream(interval: IReadInterval) {\n return Promise.resolve(\n createReadStream(this.path, interval)\n );\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -35,12 +35,16 @@ type IFileHeader = IFileHeaderRaw & IFileHeaderFlags;
|
|
|
35
35
|
interface IFileMedia {
|
|
36
36
|
length: number;
|
|
37
37
|
name: string;
|
|
38
|
-
createReadStream(opts?: IReadInterval): NodeJS.ReadableStream;
|
|
38
|
+
createReadStream(opts?: IReadInterval): Promise<NodeJS.ReadableStream> | NodeJS.ReadableStream;
|
|
39
39
|
}
|
|
40
40
|
interface IReadInterval {
|
|
41
41
|
start: number;
|
|
42
42
|
end: number;
|
|
43
43
|
}
|
|
44
|
+
interface FindOpts {
|
|
45
|
+
filter(filename: string, idx: number): boolean;
|
|
46
|
+
maxFiles: number;
|
|
47
|
+
}
|
|
44
48
|
|
|
45
49
|
declare class NumericRarFileBundle {
|
|
46
50
|
private fileMedias;
|
|
@@ -70,7 +74,7 @@ declare class RarFileChunk {
|
|
|
70
74
|
padEnd(endPadding: number): RarFileChunk;
|
|
71
75
|
padStart(startPadding: number): RarFileChunk;
|
|
72
76
|
get length(): number;
|
|
73
|
-
getStream(): NodeJS.ReadableStream
|
|
77
|
+
getStream(): NodeJS.ReadableStream | Promise<NodeJS.ReadableStream>;
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
declare class InnerFileStream extends Readable {
|
|
@@ -79,7 +83,7 @@ declare class InnerFileStream extends Readable {
|
|
|
79
83
|
constructor(rarFileChunks: RarFileChunk[], options?: ReadableOptions);
|
|
80
84
|
pushData(data: Uint16Array): void;
|
|
81
85
|
get isStarted(): boolean;
|
|
82
|
-
next(): void
|
|
86
|
+
next(): Promise<void>;
|
|
83
87
|
_read(): void;
|
|
84
88
|
}
|
|
85
89
|
|
|
@@ -95,9 +99,9 @@ declare class InnerFile implements IFileMedia {
|
|
|
95
99
|
length: number;
|
|
96
100
|
chunkMap: ChunkMapEntry[];
|
|
97
101
|
constructor(name: string, rarFileChunks: RarFileChunk[]);
|
|
98
|
-
readToEnd(): Promise<Buffer
|
|
102
|
+
readToEnd(): Promise<Buffer<ArrayBufferLike>>;
|
|
99
103
|
getChunksToStream(fileStart: number, fileEnd: number): RarFileChunk[];
|
|
100
|
-
createReadStream(interval: IReadInterval): InnerFileStream
|
|
104
|
+
createReadStream(interval: IReadInterval): Promise<InnerFileStream>;
|
|
101
105
|
calculateChunkMap(rarFileChunks: RarFileChunk[]): ChunkMapEntry[];
|
|
102
106
|
findMappedChunk(offset: number): ChunkMapEntry;
|
|
103
107
|
}
|
|
@@ -112,8 +116,8 @@ interface FileChunkMapping extends ParsedFileChunkMapping {
|
|
|
112
116
|
declare class RarFilesPackage extends EventEmitter {
|
|
113
117
|
rarFileBundle: RarFileBundle;
|
|
114
118
|
constructor(fileMedias: IFileMedia[]);
|
|
115
|
-
parseFile(rarFile: IFileMedia): Promise<FileChunkMapping[]>;
|
|
116
|
-
parse(): Promise<InnerFile[]>;
|
|
119
|
+
parseFile(rarFile: IFileMedia, opts: FindOpts): Promise<FileChunkMapping[]>;
|
|
120
|
+
parse(opts: FindOpts): Promise<InnerFile[]>;
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
declare class LocalFileMedia implements IFileMedia {
|
|
@@ -121,7 +125,7 @@ declare class LocalFileMedia implements IFileMedia {
|
|
|
121
125
|
name: string;
|
|
122
126
|
length: number;
|
|
123
127
|
constructor(path: string);
|
|
124
|
-
createReadStream(interval: IReadInterval): fs.ReadStream
|
|
128
|
+
createReadStream(interval: IReadInterval): Promise<fs.ReadStream>;
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
export { LocalFileMedia, RarFilesPackage };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,12 +35,16 @@ type IFileHeader = IFileHeaderRaw & IFileHeaderFlags;
|
|
|
35
35
|
interface IFileMedia {
|
|
36
36
|
length: number;
|
|
37
37
|
name: string;
|
|
38
|
-
createReadStream(opts?: IReadInterval): NodeJS.ReadableStream;
|
|
38
|
+
createReadStream(opts?: IReadInterval): Promise<NodeJS.ReadableStream> | NodeJS.ReadableStream;
|
|
39
39
|
}
|
|
40
40
|
interface IReadInterval {
|
|
41
41
|
start: number;
|
|
42
42
|
end: number;
|
|
43
43
|
}
|
|
44
|
+
interface FindOpts {
|
|
45
|
+
filter(filename: string, idx: number): boolean;
|
|
46
|
+
maxFiles: number;
|
|
47
|
+
}
|
|
44
48
|
|
|
45
49
|
declare class NumericRarFileBundle {
|
|
46
50
|
private fileMedias;
|
|
@@ -70,7 +74,7 @@ declare class RarFileChunk {
|
|
|
70
74
|
padEnd(endPadding: number): RarFileChunk;
|
|
71
75
|
padStart(startPadding: number): RarFileChunk;
|
|
72
76
|
get length(): number;
|
|
73
|
-
getStream(): NodeJS.ReadableStream
|
|
77
|
+
getStream(): NodeJS.ReadableStream | Promise<NodeJS.ReadableStream>;
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
declare class InnerFileStream extends Readable {
|
|
@@ -79,7 +83,7 @@ declare class InnerFileStream extends Readable {
|
|
|
79
83
|
constructor(rarFileChunks: RarFileChunk[], options?: ReadableOptions);
|
|
80
84
|
pushData(data: Uint16Array): void;
|
|
81
85
|
get isStarted(): boolean;
|
|
82
|
-
next(): void
|
|
86
|
+
next(): Promise<void>;
|
|
83
87
|
_read(): void;
|
|
84
88
|
}
|
|
85
89
|
|
|
@@ -95,9 +99,9 @@ declare class InnerFile implements IFileMedia {
|
|
|
95
99
|
length: number;
|
|
96
100
|
chunkMap: ChunkMapEntry[];
|
|
97
101
|
constructor(name: string, rarFileChunks: RarFileChunk[]);
|
|
98
|
-
readToEnd(): Promise<Buffer
|
|
102
|
+
readToEnd(): Promise<Buffer<ArrayBufferLike>>;
|
|
99
103
|
getChunksToStream(fileStart: number, fileEnd: number): RarFileChunk[];
|
|
100
|
-
createReadStream(interval: IReadInterval): InnerFileStream
|
|
104
|
+
createReadStream(interval: IReadInterval): Promise<InnerFileStream>;
|
|
101
105
|
calculateChunkMap(rarFileChunks: RarFileChunk[]): ChunkMapEntry[];
|
|
102
106
|
findMappedChunk(offset: number): ChunkMapEntry;
|
|
103
107
|
}
|
|
@@ -112,8 +116,8 @@ interface FileChunkMapping extends ParsedFileChunkMapping {
|
|
|
112
116
|
declare class RarFilesPackage extends EventEmitter {
|
|
113
117
|
rarFileBundle: RarFileBundle;
|
|
114
118
|
constructor(fileMedias: IFileMedia[]);
|
|
115
|
-
parseFile(rarFile: IFileMedia): Promise<FileChunkMapping[]>;
|
|
116
|
-
parse(): Promise<InnerFile[]>;
|
|
119
|
+
parseFile(rarFile: IFileMedia, opts: FindOpts): Promise<FileChunkMapping[]>;
|
|
120
|
+
parse(opts: FindOpts): Promise<InnerFile[]>;
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
declare class LocalFileMedia implements IFileMedia {
|
|
@@ -121,7 +125,7 @@ declare class LocalFileMedia implements IFileMedia {
|
|
|
121
125
|
name: string;
|
|
122
126
|
length: number;
|
|
123
127
|
constructor(path: string);
|
|
124
|
-
createReadStream(interval: IReadInterval): fs.ReadStream
|
|
128
|
+
createReadStream(interval: IReadInterval): Promise<fs.ReadStream>;
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
export { LocalFileMedia, RarFilesPackage };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { EventEmitter } from "events";
|
|
|
4
4
|
// src/rar-file-bundle.ts
|
|
5
5
|
var RXX_EXTENSION = /\.R(\d\d)$|.RAR$/i;
|
|
6
6
|
var RAR_EXTENSION = /.RAR$/i;
|
|
7
|
-
var PARTXX_RAR_EXTENSION = /.PART(\d\d).RAR/i;
|
|
7
|
+
var PARTXX_RAR_EXTENSION = /.PART(\d\d?\d?).RAR/i;
|
|
8
8
|
var isPartXXExtension = (fileMedias = []) => {
|
|
9
9
|
let anyPartXXTypes = fileMedias.filter(
|
|
10
10
|
(file) => file.name && file.name.match(PARTXX_RAR_EXTENSION)
|
|
@@ -137,12 +137,12 @@ var InnerFileStream = class extends Readable {
|
|
|
137
137
|
get isStarted() {
|
|
138
138
|
return !!this.stream;
|
|
139
139
|
}
|
|
140
|
-
next() {
|
|
140
|
+
async next() {
|
|
141
141
|
const chunk = this.rarFileChunks.shift();
|
|
142
142
|
if (!chunk) {
|
|
143
143
|
this.push(null);
|
|
144
144
|
} else {
|
|
145
|
-
this.stream = chunk.getStream();
|
|
145
|
+
this.stream = await chunk.getStream();
|
|
146
146
|
this.stream?.on("data", (data) => this.pushData(data));
|
|
147
147
|
this.stream?.on("end", () => this.next());
|
|
148
148
|
}
|
|
@@ -193,10 +193,9 @@ var InnerFile = class {
|
|
|
193
193
|
}
|
|
194
194
|
length;
|
|
195
195
|
chunkMap;
|
|
196
|
-
readToEnd() {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
);
|
|
196
|
+
async readToEnd() {
|
|
197
|
+
const stream = await this.createReadStream({ start: 0, end: this.length - 1 });
|
|
198
|
+
return streamToBuffer(stream);
|
|
200
199
|
}
|
|
201
200
|
getChunksToStream(fileStart, fileEnd) {
|
|
202
201
|
const { index: startIndex, start: startOffset } = this.findMappedChunk(fileStart);
|
|
@@ -224,7 +223,9 @@ var InnerFile = class {
|
|
|
224
223
|
if (start < 0 || end >= this.length) {
|
|
225
224
|
throw Error("Illegal start/end offset");
|
|
226
225
|
}
|
|
227
|
-
return
|
|
226
|
+
return Promise.resolve(
|
|
227
|
+
new InnerFileStream(this.getChunksToStream(start, end))
|
|
228
|
+
);
|
|
228
229
|
}
|
|
229
230
|
calculateChunkMap(rarFileChunks) {
|
|
230
231
|
const chunkMap = [];
|
|
@@ -404,7 +405,7 @@ var TerminatorHeaderParser = class {
|
|
|
404
405
|
|
|
405
406
|
// src/rar-files-package.ts
|
|
406
407
|
var parseHeader = async (Parser, fileMedia, offset = 0) => {
|
|
407
|
-
const stream = fileMedia.createReadStream({
|
|
408
|
+
const stream = await fileMedia.createReadStream({
|
|
408
409
|
start: offset,
|
|
409
410
|
end: offset + Parser.HEADER_SIZE
|
|
410
411
|
});
|
|
@@ -418,7 +419,7 @@ var RarFilesPackage = class extends EventEmitter {
|
|
|
418
419
|
super();
|
|
419
420
|
this.rarFileBundle = makeRarFileBundle(fileMedias);
|
|
420
421
|
}
|
|
421
|
-
async parseFile(rarFile) {
|
|
422
|
+
async parseFile(rarFile, opts) {
|
|
422
423
|
const fileChunks = [];
|
|
423
424
|
let fileOffset = 0;
|
|
424
425
|
const markerHead = await parseHeader(MarkerHeaderParser, rarFile);
|
|
@@ -429,36 +430,58 @@ var RarFilesPackage = class extends EventEmitter {
|
|
|
429
430
|
fileOffset
|
|
430
431
|
);
|
|
431
432
|
fileOffset += archiveHeader.size;
|
|
433
|
+
let countFiles = 0;
|
|
434
|
+
let retrievedFiles = 0;
|
|
432
435
|
while (fileOffset < rarFile.length - TerminatorHeaderParser.HEADER_SIZE) {
|
|
436
|
+
let getFileChunk2 = function() {
|
|
437
|
+
if (fileHead.method !== 48) {
|
|
438
|
+
throw new Error("Decompression is not implemented");
|
|
439
|
+
}
|
|
440
|
+
return {
|
|
441
|
+
name: fileHead.name,
|
|
442
|
+
fileHead,
|
|
443
|
+
chunk: new RarFileChunk(
|
|
444
|
+
rarFile,
|
|
445
|
+
fileOffset,
|
|
446
|
+
fileOffset + fileHead.size - 1
|
|
447
|
+
)
|
|
448
|
+
};
|
|
449
|
+
};
|
|
450
|
+
var getFileChunk = getFileChunk2;
|
|
433
451
|
const fileHead = await parseHeader(FileHeaderParser, rarFile, fileOffset);
|
|
434
452
|
if (fileHead.type !== 116) {
|
|
435
453
|
break;
|
|
436
454
|
}
|
|
437
|
-
if (fileHead.method !== 48) {
|
|
438
|
-
throw new Error("Decompression is not implemented");
|
|
439
|
-
}
|
|
440
455
|
fileOffset += fileHead.headSize;
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
456
|
+
if (opts.filter) {
|
|
457
|
+
if (opts.filter(fileHead.name, countFiles)) {
|
|
458
|
+
fileChunks.push(getFileChunk2());
|
|
459
|
+
retrievedFiles++;
|
|
460
|
+
if (opts.hasOwnProperty("maxFiles") && retrievedFiles === opts.maxFiles) {
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
} else {
|
|
465
|
+
fileChunks.push(getFileChunk2());
|
|
466
|
+
}
|
|
450
467
|
fileOffset += fileHead.size;
|
|
468
|
+
countFiles++;
|
|
451
469
|
}
|
|
452
470
|
this.emit("file-parsed", rarFile);
|
|
453
471
|
return fileChunks;
|
|
454
472
|
}
|
|
455
|
-
async parse() {
|
|
473
|
+
async parse(opts) {
|
|
474
|
+
opts = opts || {};
|
|
456
475
|
this.emit("parsing-start", this.rarFileBundle);
|
|
457
476
|
const parsedFileChunks = [];
|
|
458
477
|
const { files } = this.rarFileBundle;
|
|
459
478
|
for (let i = 0; i < files.length; ++i) {
|
|
460
479
|
const file = files[i];
|
|
461
|
-
const chunks = await this.parseFile(file);
|
|
480
|
+
const chunks = await this.parseFile(file, opts);
|
|
481
|
+
if (!chunks.length) {
|
|
482
|
+
this.emit("parsing-complete", []);
|
|
483
|
+
return [];
|
|
484
|
+
}
|
|
462
485
|
const { fileHead, chunk } = chunks[chunks.length - 1];
|
|
463
486
|
const chunkSize = Math.abs(chunk.endOffset - chunk.startOffset);
|
|
464
487
|
let innerFileSize = fileHead.unpackedSize;
|
|
@@ -506,7 +529,9 @@ var LocalFileMedia = class {
|
|
|
506
529
|
name;
|
|
507
530
|
length;
|
|
508
531
|
createReadStream(interval) {
|
|
509
|
-
return
|
|
532
|
+
return Promise.resolve(
|
|
533
|
+
createReadStream(this.path, interval)
|
|
534
|
+
);
|
|
510
535
|
}
|
|
511
536
|
};
|
|
512
537
|
export {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rar-files-package.ts","../src/rar-file-bundle.ts","../src/rar-file-chunk.ts","../src/inner-file-stream.ts","../src/stream-utils.ts","../src/utils.ts","../src/inner-file.ts","../src/parsing/marker-header-parser.ts","../src/parsing/archive-header-parser.ts","../src/parsing/file-header-parser.ts","../src/parsing/terminator-header-parser.ts","../src/local-file-media.ts"],"sourcesContent":["import { EventEmitter } from \"events\";\nimport { makeRarFileBundle, RarFileBundle } from \"./rar-file-bundle.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { InnerFile } from \"./inner-file.js\";\n\nimport { MarkerHeaderParser } from \"./parsing/marker-header-parser.js\";\nimport { ArchiveHeaderParser } from \"./parsing/archive-header-parser.js\";\nimport { FileHeaderParser, IFileHeader } from \"./parsing/file-header-parser.js\";\nimport { TerminatorHeaderParser } from \"./parsing/terminator-header-parser.js\";\n\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { IFileMedia, IParser, IParsers } from \"./interfaces.js\";\nimport { groupBy, mapValues } from \"./utils.js\";\n\nconst parseHeader = async <T extends IParsers>(\n Parser: IParser<T>,\n fileMedia: IFileMedia,\n offset = 0\n) => {\n const stream = fileMedia.createReadStream({\n start: offset,\n end: offset + Parser.HEADER_SIZE,\n });\n const headerBuffer = await streamToBuffer(stream);\n const parser = new Parser(headerBuffer);\n return parser.parse() as ReturnType<T[\"parse\"]>;\n};\ninterface ParsedFileChunkMapping {\n name: string;\n chunk: RarFileChunk;\n}\ninterface FileChunkMapping extends ParsedFileChunkMapping {\n fileHead: IFileHeader;\n}\n\nexport class RarFilesPackage extends EventEmitter {\n rarFileBundle: RarFileBundle;\n constructor(fileMedias: IFileMedia[]) {\n super();\n this.rarFileBundle = makeRarFileBundle(fileMedias);\n }\n async parseFile(rarFile: IFileMedia) {\n const fileChunks: FileChunkMapping[] = [];\n let fileOffset = 0;\n const markerHead = await parseHeader(MarkerHeaderParser, rarFile);\n fileOffset += markerHead.size;\n\n const archiveHeader = await parseHeader(\n ArchiveHeaderParser,\n rarFile,\n fileOffset\n );\n fileOffset += archiveHeader.size;\n\n while (fileOffset < rarFile.length - TerminatorHeaderParser.HEADER_SIZE) {\n const fileHead = await parseHeader(FileHeaderParser, rarFile, fileOffset);\n if (fileHead.type !== 116) {\n break;\n }\n if (fileHead.method !== 0x30) {\n throw new Error(\"Decompression is not implemented\");\n }\n fileOffset += fileHead.headSize;\n\n fileChunks.push({\n name: fileHead.name,\n fileHead,\n chunk: new RarFileChunk(\n rarFile,\n fileOffset,\n fileOffset + fileHead.size - 1\n ),\n });\n fileOffset += fileHead.size;\n }\n this.emit(\"file-parsed\", rarFile);\n return fileChunks;\n }\n async parse(): Promise<InnerFile[]> {\n this.emit(\"parsing-start\", this.rarFileBundle);\n const parsedFileChunks: ParsedFileChunkMapping[][] = [];\n const { files } = this.rarFileBundle;\n for (let i = 0; i < files.length; ++i) {\n const file = files[i]!;\n\n const chunks = await this.parseFile(file);\n const { fileHead, chunk } = chunks[chunks.length - 1]!;\n const chunkSize = Math.abs(chunk.endOffset - chunk.startOffset);\n let innerFileSize = fileHead.unpackedSize;\n parsedFileChunks.push(chunks);\n\n if (fileHead.continuesInNext) {\n while (Math.abs(innerFileSize - chunkSize) >= chunkSize) {\n const nextFile = files[++i]!;\n\n parsedFileChunks.push([\n {\n name: fileHead.name,\n chunk: new RarFileChunk(\n nextFile,\n chunk.startOffset,\n chunk.endOffset\n ),\n },\n ]);\n this.emit(\"file-parsed\", nextFile);\n innerFileSize -= chunkSize;\n }\n }\n }\n\n const fileChunks = parsedFileChunks.flat();\n\n const grouped = mapValues(\n groupBy(fileChunks, (f) => f.name),\n (value) => value.map((v) => v.chunk)\n );\n\n const innerFiles = Object.entries(grouped).map(\n ([name, chunks]) => new InnerFile(name, chunks)\n );\n\n this.emit(\"parsing-complete\", innerFiles);\n return innerFiles;\n }\n}\n","const RXX_EXTENSION = /\\.R(\\d\\d)$|.RAR$/i;\nconst RAR_EXTENSION = /.RAR$/i;\nconst PARTXX_RAR_EXTENSION = /.PART(\\d\\d).RAR/i;\nimport { IFileMedia } from \"./interfaces.js\";\n\nconst isPartXXExtension = (fileMedias: IFileMedia[] = []) => {\n let anyPartXXTypes = fileMedias.filter(\n (file) => file.name && file.name.match(PARTXX_RAR_EXTENSION)\n );\n\n if (anyPartXXTypes.length > 0) {\n return true;\n } else {\n return false;\n }\n};\n\nclass NumericRarFileBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter(\n (file) => file.name && file.name.match(RXX_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n if (first.name.match(RAR_EXTENSION)) {\n return -1;\n } else if (second.name.match(RAR_EXTENSION)) {\n return 1;\n } else {\n const firstMatch = first.name.match(RXX_EXTENSION);\n const secondMatch = second.name.match(RXX_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n }\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nclass PartXXRarBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter((file) =>\n file.name.match(PARTXX_RAR_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n const firstMatch = first.name.match(PARTXX_RAR_EXTENSION);\n const secondMatch = second.name.match(PARTXX_RAR_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nexport type RarFileBundle = PartXXRarBundle | NumericRarFileBundle;\nexport const makeRarFileBundle = (\n fileMedias: IFileMedia[] = []\n): RarFileBundle => {\n return isPartXXExtension(fileMedias)\n ? new PartXXRarBundle(fileMedias)\n : new NumericRarFileBundle(fileMedias);\n};\n","import { IFileMedia } from \"./interfaces.js\";\n\nexport class RarFileChunk {\n constructor(\n private fileMedia: IFileMedia,\n public startOffset: number,\n public endOffset: number\n ) {}\n padEnd(endPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset,\n this.endOffset - endPadding\n );\n }\n padStart(startPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset + startPadding,\n this.endOffset\n );\n }\n get length() {\n return Math.max(0, this.endOffset - this.startOffset);\n }\n getStream() {\n return this.fileMedia.createReadStream({\n start: this.startOffset,\n end: this.endOffset,\n });\n }\n}\n","import { Readable, ReadableOptions } from \"stream\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\n\nexport class InnerFileStream extends Readable {\n stream?: NodeJS.ReadableStream;\n constructor(\n private rarFileChunks: RarFileChunk[],\n options?: ReadableOptions\n ) {\n super(options);\n }\n pushData(data: Uint16Array) {\n if (!this.push(data)) {\n this.stream?.pause();\n }\n }\n get isStarted() {\n return !!this.stream;\n }\n next() {\n const chunk = this.rarFileChunks.shift();\n\n if (!chunk) {\n this.push(null);\n } else {\n this.stream = chunk.getStream();\n this.stream?.on(\"data\", (data) => this.pushData(data));\n this.stream?.on(\"end\", () => this.next());\n }\n }\n override _read() {\n if (!this.isStarted) {\n this.next();\n } else {\n this.stream?.resume();\n }\n }\n}\n","import { Stream, Duplex } from \"stream\";\n\nexport const streamToBuffer = async (stream: Stream | NodeJS.ReadableStream): Promise<Buffer> =>\n new Promise((resolve, reject) => {\n const buffers: Uint8Array[] = [];\n stream.on(\"error\", reject);\n stream.on(\"data\", (data) => buffers.push(data));\n stream.on(\"end\", () => resolve(Buffer.concat(buffers)));\n });\n\nexport const bufferToStream = (buffer: Buffer): Stream => {\n const stream = new Duplex();\n stream.push(buffer);\n stream.push(null);\n return stream;\n};\n","export function groupBy<T>(arr: T[], fn: (item: T) => any) {\n return arr.reduce<Record<string, T[]>>((prev, curr) => {\n const groupKey = fn(curr);\n const group = prev[groupKey] || [];\n group.push(curr);\n return { ...prev, [groupKey]: group };\n }, {});\n}\n\nexport function sum(arr: number[]) {\n return arr.reduce((s, n) => s + n);\n}\nexport function mapValues<T extends Object, S>(\n object: T,\n mapper: (value: T[keyof T]) => S\n) {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [key, mapper(value)])\n ) as { [key in keyof T]: S };\n}\n","import { IFileMedia, IReadInterval } from \"./interfaces.js\";\nimport { InnerFileStream } from \"./inner-file-stream.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { sum } from \"./utils.js\";\ntype ChunkMapEntry = {\n index: number;\n start: number;\n end: number;\n chunk: RarFileChunk;\n};\n\nexport class InnerFile implements IFileMedia {\n length: number;\n\n chunkMap: ChunkMapEntry[];\n constructor(public name: string, private rarFileChunks: RarFileChunk[]) {\n this.length = sum(rarFileChunks.map((c) => c.length));\n this.chunkMap = this.calculateChunkMap(rarFileChunks);\n\n this.name = name;\n }\n readToEnd() {\n return streamToBuffer(\n this.createReadStream({ start: 0, end: this.length - 1 })\n );\n }\n getChunksToStream(fileStart: number, fileEnd: number) {\n const { index: startIndex, start: startOffset } =\n this.findMappedChunk(fileStart);\n let { index: endIndex, end: endOffset } = this.findMappedChunk(fileEnd);\n\n const chunksToStream = this.rarFileChunks.slice(startIndex, endIndex + 1);\n\n const last = chunksToStream.length - 1;\n const first = 0;\n chunksToStream[first] = chunksToStream[first]!.padStart(\n Math.abs(startOffset - fileStart)\n );\n\n let diff = Math.abs(endOffset - fileEnd);\n if (diff === this.rarFileChunks.length) {\n diff = 0;\n }\n if (diff !== 0) {\n chunksToStream[last] = chunksToStream[last]!.padEnd(diff);\n }\n\n return chunksToStream;\n }\n createReadStream(interval: IReadInterval) {\n if (!interval) {\n interval = { start: 0, end: this.length - 1 };\n }\n let { start, end } = interval;\n\n if (start < 0 || end >= this.length) {\n throw Error(\"Illegal start/end offset\");\n }\n\n return new InnerFileStream(this.getChunksToStream(start, end));\n }\n calculateChunkMap(rarFileChunks: RarFileChunk[]) {\n const chunkMap: ChunkMapEntry[] = [];\n let index = 0;\n let fileOffset = 0;\n for (const chunk of rarFileChunks) {\n const start = fileOffset;\n const end = fileOffset + chunk.length;\n fileOffset = end + 1;\n\n chunkMap.push({ index, start, end, chunk });\n index++;\n }\n\n return chunkMap;\n }\n findMappedChunk(offset: number) {\n let selectedMap = this.chunkMap[0]!;\n for (const chunkMapping of this.chunkMap) {\n if (offset >= chunkMapping.start && offset <= chunkMapping.end) {\n selectedMap = chunkMapping;\n break;\n }\n }\n return selectedMap;\n }\n}\n","export class MarkerHeaderParser {\n static HEADER_SIZE = 11;\n constructor(private headerBuffer: Buffer) {}\n\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n let size = this.headerBuffer.readUInt16LE(5);\n if ((flags & 0x8000) !== 0) {\n let addSize = this.headerBuffer.readUint32LE(7);\n size += addSize || 0;\n }\n return { crc, type, flags, size };\n }\n}\n","interface IArchiveHeader {\n crc: number;\n type: number;\n flags: number;\n size: number;\n reserved1: number;\n reserved2: number;\n}\n\nfunction parseFlags(parsedVars: IArchiveHeader) {\n return {\n hasVolumeAttributes: (parsedVars.flags & 0x0001) !== 0,\n hasComment: (parsedVars.flags & 0x0002) !== 0,\n isLocked: (parsedVars.flags & 0x0004) !== 0,\n hasSolidAttributes: (parsedVars.flags & 0x0008) !== 0,\n isNewNameScheme: (parsedVars.flags & 0x00010) !== 0,\n hasAuthInfo: (parsedVars.flags & 0x0020) !== 0,\n hasRecovery: (parsedVars.flags & 0x0040) !== 0,\n isBlockEncoded: (parsedVars.flags & 0x0080) !== 0,\n isFirstVolume: (parsedVars.flags & 0x0100) !== 0,\n };\n}\nexport class ArchiveHeaderParser {\n static HEADER_SIZE = 13;\n constructor(private buffer: Buffer) {}\n parse() {\n const crc = this.buffer.readUInt16LE(0);\n const type = this.buffer.readUInt8(2);\n const flags = this.buffer.readUInt16LE(3);\n let size = this.buffer.readUInt16LE(5);\n const reserved1 = this.buffer.readUInt16LE(7);\n const reserved2 = this.buffer.readUInt32LE(9);\n\n let vars = { crc, type, flags, size, reserved1, reserved2 };\n\n return { ...parseFlags(vars), ...vars };\n }\n}\n","interface IFileHeaderFlags {\n continuesFromPrevious: boolean;\n continuesInNext: boolean;\n isEncrypted: boolean;\n hasComment: boolean;\n hasInfoFromPrevious: boolean;\n hasHighSize: boolean;\n hasSpecialName: boolean;\n hasSalt: boolean;\n isOldVersion: boolean;\n hasExtendedTime: boolean;\n}\n\ninterface IFileHeaderRaw {\n crc: number;\n type: number;\n flags: number;\n headSize: number;\n size: number;\n unpackedSize: number;\n host: number;\n fileCrc: number;\n timestamp: number;\n version: number;\n method: number;\n nameSize: number;\n attributes: number;\n name: string;\n}\n\nexport type IFileHeader = IFileHeaderRaw & IFileHeaderFlags;\nexport class FileHeaderParser {\n static HEADER_SIZE = 280;\n offset = 0;\n constructor(private buffer: Buffer) {}\n private handleHighFileSize(parsedVars: IFileHeader) {\n if (parsedVars.hasHighSize) {\n const highPackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n const highUnpackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n parsedVars.size = highPackSize * 0x100000000 + parsedVars.size;\n parsedVars.unpackedSize =\n highUnpackSize * 0x100000000 + parsedVars.unpackedSize;\n }\n }\n private parseFileName(parsedVars: IFileHeaderRaw) {\n parsedVars.name = this.buffer\n .subarray(this.offset, this.offset + parsedVars.nameSize)\n .toString(\"utf-8\");\n }\n private parseFlags(parsedVars: IFileHeaderRaw): IFileHeaderFlags {\n return {\n continuesFromPrevious: (parsedVars.flags & 0x01) !== 0,\n continuesInNext: (parsedVars.flags & 0x02) !== 0,\n isEncrypted: (parsedVars.flags & 0x04) !== 0,\n hasComment: (parsedVars.flags & 0x08) !== 0,\n hasInfoFromPrevious: (parsedVars.flags & 0x10) !== 0,\n hasHighSize: (parsedVars.flags & 0x100) !== 0,\n hasSpecialName: (parsedVars.flags & 0x200) !== 0,\n hasSalt: (parsedVars.flags & 0x400) !== 0,\n isOldVersion: (parsedVars.flags & 0x800) !== 0,\n hasExtendedTime: (parsedVars.flags & 0x1000) !== 0,\n };\n }\n parse(): IFileHeader {\n const crc = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const type = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const flags = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const headSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const size = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const unpackedSize = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const host = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const fileCrc = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const timestamp = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const version = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const method = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const nameSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const attributes = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n let vars: IFileHeaderRaw = {\n crc,\n type,\n flags,\n headSize,\n size,\n unpackedSize,\n host,\n fileCrc,\n timestamp,\n version,\n method,\n nameSize,\n attributes,\n name: \"\",\n };\n\n const boolFlags = this.parseFlags(vars);\n const header = { ...vars, ...boolFlags };\n this.handleHighFileSize(header);\n this.parseFileName(header);\n this.offset = 0;\n return header;\n }\n}\n","export class TerminatorHeaderParser {\n static HEADER_SIZE = 27;\n constructor(private headerBuffer: Buffer) {}\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n const size = this.headerBuffer.readUInt16LE(5);\n return { crc, type, flags, size };\n }\n}\n","import { basename } from \"path\";\nimport { statSync, createReadStream } from \"fs\";\nimport { IFileMedia, IReadInterval } from \"./interfaces.js\";\n\nexport class LocalFileMedia implements IFileMedia {\n name: string;\n length: number;\n constructor(private path: string) {\n this.name = basename(path);\n this.length = statSync(path).size;\n }\n createReadStream(interval: IReadInterval) {\n return createReadStream(this.path, interval);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/rar-files-package.ts","../src/rar-file-bundle.ts","../src/rar-file-chunk.ts","../src/inner-file-stream.ts","../src/stream-utils.ts","../src/utils.ts","../src/inner-file.ts","../src/parsing/marker-header-parser.ts","../src/parsing/archive-header-parser.ts","../src/parsing/file-header-parser.ts","../src/parsing/terminator-header-parser.ts","../src/local-file-media.ts"],"sourcesContent":["import { EventEmitter } from \"events\";\nimport { makeRarFileBundle, RarFileBundle } from \"./rar-file-bundle.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { InnerFile } from \"./inner-file.js\";\n\nimport { MarkerHeaderParser } from \"./parsing/marker-header-parser.js\";\nimport { ArchiveHeaderParser } from \"./parsing/archive-header-parser.js\";\nimport { FileHeaderParser, IFileHeader } from \"./parsing/file-header-parser.js\";\nimport { TerminatorHeaderParser } from \"./parsing/terminator-header-parser.js\";\n\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { IFileMedia, IParser, IParsers, FindOpts } from \"./interfaces.js\";\nimport { groupBy, mapValues } from \"./utils.js\";\n\nconst parseHeader = async <T extends IParsers>(\n Parser: IParser<T>,\n fileMedia: IFileMedia,\n offset = 0\n) => {\n const stream = await fileMedia.createReadStream({\n start: offset,\n end: offset + Parser.HEADER_SIZE,\n });\n const headerBuffer = await streamToBuffer(stream);\n const parser = new Parser(headerBuffer);\n return parser.parse() as ReturnType<T[\"parse\"]>;\n};\ninterface ParsedFileChunkMapping {\n name: string;\n chunk: RarFileChunk;\n}\ninterface FileChunkMapping extends ParsedFileChunkMapping {\n fileHead: IFileHeader;\n}\n\nexport class RarFilesPackage extends EventEmitter {\n rarFileBundle: RarFileBundle;\n constructor(fileMedias: IFileMedia[]) {\n super();\n this.rarFileBundle = makeRarFileBundle(fileMedias);\n }\n async parseFile(rarFile: IFileMedia, opts: FindOpts) {\n const fileChunks: FileChunkMapping[] = [];\n let fileOffset = 0;\n const markerHead = await parseHeader(MarkerHeaderParser, rarFile);\n fileOffset += markerHead.size;\n\n const archiveHeader = await parseHeader(\n ArchiveHeaderParser,\n rarFile,\n fileOffset\n );\n fileOffset += archiveHeader.size;\n\n let countFiles = 0;\n let retrievedFiles = 0;\n while (fileOffset < rarFile.length - TerminatorHeaderParser.HEADER_SIZE) {\n const fileHead = await parseHeader(FileHeaderParser, rarFile, fileOffset);\n if (fileHead.type !== 116) {\n break;\n }\n fileOffset += fileHead.headSize;\n function getFileChunk() {\n if (fileHead.method !== 0x30) {\n throw new Error(\"Decompression is not implemented\");\n }\n return {\n name: fileHead.name,\n fileHead,\n chunk: new RarFileChunk(\n rarFile,\n fileOffset,\n fileOffset + fileHead.size - 1\n ),\n };\n }\n if (opts.filter) {\n if (opts.filter(fileHead.name, countFiles)) {\n fileChunks.push(getFileChunk());\n retrievedFiles++;\n if (opts.hasOwnProperty('maxFiles') && retrievedFiles === opts.maxFiles) {\n break;\n }\n }\n } else {\n fileChunks.push(getFileChunk());\n }\n fileOffset += fileHead.size;\n countFiles++;\n }\n this.emit(\"file-parsed\", rarFile);\n return fileChunks;\n }\n async parse(opts: FindOpts): Promise<InnerFile[]> {\n opts = opts || {};\n this.emit(\"parsing-start\", this.rarFileBundle);\n const parsedFileChunks: ParsedFileChunkMapping[][] = [];\n const { files } = this.rarFileBundle;\n for (let i = 0; i < files.length; ++i) {\n const file = files[i]!;\n\n const chunks = await this.parseFile(file, opts);\n if (!chunks.length) {\n this.emit(\"parsing-complete\", []);\n return [];\n }\n const { fileHead, chunk } = chunks[chunks.length - 1]!;\n const chunkSize = Math.abs(chunk.endOffset - chunk.startOffset);\n let innerFileSize = fileHead.unpackedSize;\n parsedFileChunks.push(chunks);\n\n if (fileHead.continuesInNext) {\n while (Math.abs(innerFileSize - chunkSize) >= chunkSize) {\n const nextFile = files[++i]!;\n\n parsedFileChunks.push([\n {\n name: fileHead.name,\n chunk: new RarFileChunk(\n nextFile,\n chunk.startOffset,\n chunk.endOffset\n ),\n },\n ]);\n this.emit(\"file-parsed\", nextFile);\n innerFileSize -= chunkSize;\n }\n }\n }\n\n const fileChunks = parsedFileChunks.flat();\n\n const grouped = mapValues(\n groupBy(fileChunks, (f) => f.name),\n (value) => value.map((v) => v.chunk)\n );\n\n const innerFiles = Object.entries(grouped).map(\n ([name, chunks]) => new InnerFile(name, chunks)\n );\n\n this.emit(\"parsing-complete\", innerFiles);\n return innerFiles;\n }\n}\n","const RXX_EXTENSION = /\\.R(\\d\\d)$|.RAR$/i;\nconst RAR_EXTENSION = /.RAR$/i;\nconst PARTXX_RAR_EXTENSION = /.PART(\\d\\d?\\d?).RAR/i;\nimport { IFileMedia } from \"./interfaces.js\";\n\nconst isPartXXExtension = (fileMedias: IFileMedia[] = []) => {\n let anyPartXXTypes = fileMedias.filter(\n (file) => file.name && file.name.match(PARTXX_RAR_EXTENSION)\n );\n\n if (anyPartXXTypes.length > 0) {\n return true;\n } else {\n return false;\n }\n};\n\nclass NumericRarFileBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter(\n (file) => file.name && file.name.match(RXX_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n if (first.name.match(RAR_EXTENSION)) {\n return -1;\n } else if (second.name.match(RAR_EXTENSION)) {\n return 1;\n } else {\n const firstMatch = first.name.match(RXX_EXTENSION);\n const secondMatch = second.name.match(RXX_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n }\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nclass PartXXRarBundle {\n constructor(private fileMedias: IFileMedia[] = []) {\n if (this.fileMedias.length > 0) {\n this.filter();\n this.sort();\n }\n }\n filter() {\n this.fileMedias = this.fileMedias.filter((file) =>\n file.name.match(PARTXX_RAR_EXTENSION)\n );\n }\n sort() {\n this.fileMedias.sort((first, second) => {\n const firstMatch = first.name.match(PARTXX_RAR_EXTENSION);\n const secondMatch = second.name.match(PARTXX_RAR_EXTENSION);\n const firstNumber = +((firstMatch && firstMatch[1]) || 0);\n const secondNumber = +((secondMatch && secondMatch[1]) || 0);\n return firstNumber - secondNumber;\n });\n }\n\n get length() {\n return this.fileMedias.length;\n }\n get fileNames() {\n return this.fileMedias.map((file) => file.name);\n }\n get files() {\n return this.fileMedias;\n }\n}\n\nexport type RarFileBundle = PartXXRarBundle | NumericRarFileBundle;\nexport const makeRarFileBundle = (\n fileMedias: IFileMedia[] = []\n): RarFileBundle => {\n return isPartXXExtension(fileMedias)\n ? new PartXXRarBundle(fileMedias)\n : new NumericRarFileBundle(fileMedias);\n};\n","import { IFileMedia } from \"./interfaces.js\";\n\nexport class RarFileChunk {\n constructor(\n private fileMedia: IFileMedia,\n public startOffset: number,\n public endOffset: number\n ) {}\n padEnd(endPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset,\n this.endOffset - endPadding\n );\n }\n padStart(startPadding: number) {\n return new RarFileChunk(\n this.fileMedia,\n this.startOffset + startPadding,\n this.endOffset\n );\n }\n get length() {\n return Math.max(0, this.endOffset - this.startOffset);\n }\n getStream() {\n return this.fileMedia.createReadStream({\n start: this.startOffset,\n end: this.endOffset,\n });\n }\n}\n","import { Readable, ReadableOptions } from \"stream\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\n\nexport class InnerFileStream extends Readable {\n stream?: NodeJS.ReadableStream;\n constructor(\n private rarFileChunks: RarFileChunk[],\n options?: ReadableOptions\n ) {\n super(options);\n }\n pushData(data: Uint16Array) {\n if (!this.push(data)) {\n this.stream?.pause();\n }\n }\n get isStarted() {\n return !!this.stream;\n }\n async next() {\n const chunk = this.rarFileChunks.shift();\n\n if (!chunk) {\n this.push(null);\n } else {\n this.stream = await chunk.getStream();\n this.stream?.on(\"data\", (data) => this.pushData(data));\n this.stream?.on(\"end\", () => this.next());\n }\n }\n override _read() {\n if (!this.isStarted) {\n this.next();\n } else {\n this.stream?.resume();\n }\n }\n}\n","import { Stream, Duplex } from \"stream\";\n\nexport const streamToBuffer = async (stream: Stream | NodeJS.ReadableStream): Promise<Buffer> =>\n new Promise((resolve, reject) => {\n const buffers: Uint8Array[] = [];\n stream.on(\"error\", reject);\n stream.on(\"data\", (data) => buffers.push(data));\n stream.on(\"end\", () => resolve(Buffer.concat(buffers)));\n });\n\nexport const bufferToStream = (buffer: Buffer): Stream => {\n const stream = new Duplex();\n stream.push(buffer);\n stream.push(null);\n return stream;\n};\n","export function groupBy<T>(arr: T[], fn: (item: T) => any) {\n return arr.reduce<Record<string, T[]>>((prev, curr) => {\n const groupKey = fn(curr);\n const group = prev[groupKey] || [];\n group.push(curr);\n return { ...prev, [groupKey]: group };\n }, {});\n}\n\nexport function sum(arr: number[]) {\n return arr.reduce((s, n) => s + n);\n}\nexport function mapValues<T extends Object, S>(\n object: T,\n mapper: (value: T[keyof T]) => S\n) {\n return Object.fromEntries(\n Object.entries(object).map(([key, value]) => [key, mapper(value)])\n ) as { [key in keyof T]: S };\n}\n","import { IFileMedia, IReadInterval } from \"./interfaces.js\";\nimport { InnerFileStream } from \"./inner-file-stream.js\";\nimport { RarFileChunk } from \"./rar-file-chunk.js\";\nimport { streamToBuffer } from \"./stream-utils.js\";\nimport { sum } from \"./utils.js\";\ntype ChunkMapEntry = {\n index: number;\n start: number;\n end: number;\n chunk: RarFileChunk;\n};\n\nexport class InnerFile implements IFileMedia {\n length: number;\n\n chunkMap: ChunkMapEntry[];\n constructor(public name: string, private rarFileChunks: RarFileChunk[]) {\n this.length = sum(rarFileChunks.map((c) => c.length));\n this.chunkMap = this.calculateChunkMap(rarFileChunks);\n\n this.name = name;\n }\n async readToEnd() {\n const stream = await this.createReadStream({ start: 0, end: this.length - 1 });\n return streamToBuffer(stream);\n }\n getChunksToStream(fileStart: number, fileEnd: number) {\n const { index: startIndex, start: startOffset } =\n this.findMappedChunk(fileStart);\n let { index: endIndex, end: endOffset } = this.findMappedChunk(fileEnd);\n\n const chunksToStream = this.rarFileChunks.slice(startIndex, endIndex + 1);\n\n const last = chunksToStream.length - 1;\n const first = 0;\n chunksToStream[first] = chunksToStream[first]!.padStart(\n Math.abs(startOffset - fileStart)\n );\n\n let diff = Math.abs(endOffset - fileEnd);\n if (diff === this.rarFileChunks.length) {\n diff = 0;\n }\n if (diff !== 0) {\n chunksToStream[last] = chunksToStream[last]!.padEnd(diff);\n }\n\n return chunksToStream;\n }\n createReadStream(interval: IReadInterval) {\n if (!interval) {\n interval = { start: 0, end: this.length - 1 };\n }\n let { start, end } = interval;\n\n if (start < 0 || end >= this.length) {\n throw Error(\"Illegal start/end offset\");\n }\n\n return Promise.resolve(\n new InnerFileStream(this.getChunksToStream(start, end))\n );\n }\n calculateChunkMap(rarFileChunks: RarFileChunk[]) {\n const chunkMap: ChunkMapEntry[] = [];\n let index = 0;\n let fileOffset = 0;\n for (const chunk of rarFileChunks) {\n const start = fileOffset;\n const end = fileOffset + chunk.length;\n fileOffset = end + 1;\n\n chunkMap.push({ index, start, end, chunk });\n index++;\n }\n\n return chunkMap;\n }\n findMappedChunk(offset: number) {\n let selectedMap = this.chunkMap[0]!;\n for (const chunkMapping of this.chunkMap) {\n if (offset >= chunkMapping.start && offset <= chunkMapping.end) {\n selectedMap = chunkMapping;\n break;\n }\n }\n return selectedMap;\n }\n}\n","export class MarkerHeaderParser {\n static HEADER_SIZE = 11;\n constructor(private headerBuffer: Buffer) {}\n\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n let size = this.headerBuffer.readUInt16LE(5);\n if ((flags & 0x8000) !== 0) {\n let addSize = this.headerBuffer.readUint32LE(7);\n size += addSize || 0;\n }\n return { crc, type, flags, size };\n }\n}\n","interface IArchiveHeader {\n crc: number;\n type: number;\n flags: number;\n size: number;\n reserved1: number;\n reserved2: number;\n}\n\nfunction parseFlags(parsedVars: IArchiveHeader) {\n return {\n hasVolumeAttributes: (parsedVars.flags & 0x0001) !== 0,\n hasComment: (parsedVars.flags & 0x0002) !== 0,\n isLocked: (parsedVars.flags & 0x0004) !== 0,\n hasSolidAttributes: (parsedVars.flags & 0x0008) !== 0,\n isNewNameScheme: (parsedVars.flags & 0x00010) !== 0,\n hasAuthInfo: (parsedVars.flags & 0x0020) !== 0,\n hasRecovery: (parsedVars.flags & 0x0040) !== 0,\n isBlockEncoded: (parsedVars.flags & 0x0080) !== 0,\n isFirstVolume: (parsedVars.flags & 0x0100) !== 0,\n };\n}\nexport class ArchiveHeaderParser {\n static HEADER_SIZE = 13;\n constructor(private buffer: Buffer) {}\n parse() {\n const crc = this.buffer.readUInt16LE(0);\n const type = this.buffer.readUInt8(2);\n const flags = this.buffer.readUInt16LE(3);\n let size = this.buffer.readUInt16LE(5);\n const reserved1 = this.buffer.readUInt16LE(7);\n const reserved2 = this.buffer.readUInt32LE(9);\n\n let vars = { crc, type, flags, size, reserved1, reserved2 };\n\n return { ...parseFlags(vars), ...vars };\n }\n}\n","interface IFileHeaderFlags {\n continuesFromPrevious: boolean;\n continuesInNext: boolean;\n isEncrypted: boolean;\n hasComment: boolean;\n hasInfoFromPrevious: boolean;\n hasHighSize: boolean;\n hasSpecialName: boolean;\n hasSalt: boolean;\n isOldVersion: boolean;\n hasExtendedTime: boolean;\n}\n\ninterface IFileHeaderRaw {\n crc: number;\n type: number;\n flags: number;\n headSize: number;\n size: number;\n unpackedSize: number;\n host: number;\n fileCrc: number;\n timestamp: number;\n version: number;\n method: number;\n nameSize: number;\n attributes: number;\n name: string;\n}\n\nexport type IFileHeader = IFileHeaderRaw & IFileHeaderFlags;\nexport class FileHeaderParser {\n static HEADER_SIZE = 280;\n offset = 0;\n constructor(private buffer: Buffer) {}\n private handleHighFileSize(parsedVars: IFileHeader) {\n if (parsedVars.hasHighSize) {\n const highPackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n const highUnpackSize = this.buffer.readInt32LE(this.offset);\n this.offset += 4;\n parsedVars.size = highPackSize * 0x100000000 + parsedVars.size;\n parsedVars.unpackedSize =\n highUnpackSize * 0x100000000 + parsedVars.unpackedSize;\n }\n }\n private parseFileName(parsedVars: IFileHeaderRaw) {\n parsedVars.name = this.buffer\n .subarray(this.offset, this.offset + parsedVars.nameSize)\n .toString(\"utf-8\");\n }\n private parseFlags(parsedVars: IFileHeaderRaw): IFileHeaderFlags {\n return {\n continuesFromPrevious: (parsedVars.flags & 0x01) !== 0,\n continuesInNext: (parsedVars.flags & 0x02) !== 0,\n isEncrypted: (parsedVars.flags & 0x04) !== 0,\n hasComment: (parsedVars.flags & 0x08) !== 0,\n hasInfoFromPrevious: (parsedVars.flags & 0x10) !== 0,\n hasHighSize: (parsedVars.flags & 0x100) !== 0,\n hasSpecialName: (parsedVars.flags & 0x200) !== 0,\n hasSalt: (parsedVars.flags & 0x400) !== 0,\n isOldVersion: (parsedVars.flags & 0x800) !== 0,\n hasExtendedTime: (parsedVars.flags & 0x1000) !== 0,\n };\n }\n parse(): IFileHeader {\n const crc = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const type = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const flags = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const headSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const size = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const unpackedSize = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const host = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const fileCrc = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const timestamp = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n const version = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const method = this.buffer.readUInt8(this.offset);\n this.offset += 1;\n\n const nameSize = this.buffer.readUInt16LE(this.offset);\n this.offset += 2;\n\n const attributes = this.buffer.readUInt32LE(this.offset);\n this.offset += 4;\n\n let vars: IFileHeaderRaw = {\n crc,\n type,\n flags,\n headSize,\n size,\n unpackedSize,\n host,\n fileCrc,\n timestamp,\n version,\n method,\n nameSize,\n attributes,\n name: \"\",\n };\n\n const boolFlags = this.parseFlags(vars);\n const header = { ...vars, ...boolFlags };\n this.handleHighFileSize(header);\n this.parseFileName(header);\n this.offset = 0;\n return header;\n }\n}\n","export class TerminatorHeaderParser {\n static HEADER_SIZE = 27;\n constructor(private headerBuffer: Buffer) {}\n parse() {\n const crc = this.headerBuffer.readUInt16LE(0);\n const type = this.headerBuffer.readUInt8(2);\n const flags = this.headerBuffer.readUInt16LE(3);\n const size = this.headerBuffer.readUInt16LE(5);\n return { crc, type, flags, size };\n }\n}\n","import { basename } from \"path\";\nimport { statSync, createReadStream } from \"fs\";\nimport { IFileMedia, IReadInterval } from \"./interfaces.js\";\n\nexport class LocalFileMedia implements IFileMedia {\n name: string;\n length: number;\n constructor(private path: string) {\n this.name = basename(path);\n this.length = statSync(path).size;\n }\n createReadStream(interval: IReadInterval) {\n return Promise.resolve(\n createReadStream(this.path, interval)\n );\n }\n}\n"],"mappings":"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","names":["getFileChunk"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rar-stream",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Rar-Stream is a module for managing rar archives as node streams",
|
|
5
5
|
"author": "1313",
|
|
6
6
|
"repository": {
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
"url": "https://github.com/1313/rar-stream.git"
|
|
9
9
|
},
|
|
10
10
|
"type": "module",
|
|
11
|
-
"packageManager": "pnpm@7.18.2",
|
|
12
11
|
"engines": {
|
|
13
12
|
"node": ">=18"
|
|
14
13
|
},
|
|
@@ -20,11 +19,11 @@
|
|
|
20
19
|
],
|
|
21
20
|
"license": "MIT",
|
|
22
21
|
"devDependencies": {
|
|
23
|
-
"@types/node": "^
|
|
24
|
-
"@vitest/coverage-v8": "^1.
|
|
25
|
-
"tsup": "^8.
|
|
26
|
-
"typescript": "5.
|
|
27
|
-
"vitest": "1.
|
|
22
|
+
"@types/node": "^22.10.1",
|
|
23
|
+
"@vitest/coverage-v8": "^2.1.8",
|
|
24
|
+
"tsup": "^8.3.5",
|
|
25
|
+
"typescript": "5.7.2",
|
|
26
|
+
"vitest": "2.1.8"
|
|
28
27
|
},
|
|
29
28
|
"exports": {
|
|
30
29
|
"import": {
|