file-type 22.0.1 → 22.0.2
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/package.json +1 -1
- package/readme.md +3 -0
- package/source/detectors/zip.js +6 -1
- package/source/index.d.ts +3 -0
- package/source/index.js +25 -13
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -306,6 +306,9 @@ They allow support for uncommon file types, non-binary formats, or customized de
|
|
|
306
306
|
Detectors can be added via the constructor options or by directly modifying `FileTypeParser#detectors`.
|
|
307
307
|
Detectors provided through the constructor are executed before the default ones.
|
|
308
308
|
|
|
309
|
+
> [!NOTE]
|
|
310
|
+
> Not safe for concurrent use. Create a new instance per call if you need concurrency.
|
|
311
|
+
|
|
309
312
|
### Example adding a detector
|
|
310
313
|
|
|
311
314
|
```js
|
package/source/detectors/zip.js
CHANGED
|
@@ -53,12 +53,17 @@ async function decompressDeflateRawWithLimit(data, {maximumLength = maximumZipEn
|
|
|
53
53
|
|
|
54
54
|
totalLength += value.length;
|
|
55
55
|
if (totalLength > maximumLength) {
|
|
56
|
-
await reader.cancel();
|
|
56
|
+
await reader.cancel().catch(() => {});
|
|
57
57
|
throw new Error(`ZIP entry decompressed data exceeds ${maximumLength} bytes`);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
chunks.push(value);
|
|
61
61
|
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
// A ZIP entry with a data descriptor has an unknown compressed size, so the buffered data can contain bytes that follow the deflate stream. Node.js 24 rejects those, unlike other versions. The data decompressed so far is still valid and enough for detection.
|
|
64
|
+
if (error.code !== 'ERR_TRAILING_JUNK_AFTER_STREAM_END') {
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
62
67
|
} finally {
|
|
63
68
|
reader.releaseLock();
|
|
64
69
|
}
|
package/source/index.d.ts
CHANGED
|
@@ -238,6 +238,9 @@ This method can be handy to put in a stream pipeline, but it comes with a price.
|
|
|
238
238
|
*/
|
|
239
239
|
export function fileTypeStream(webStream: AnyWebReadableStream<Uint8Array>, options?: StreamOptions & FileTypeOptions): Promise<AnyWebReadableByteStreamWithFileType>;
|
|
240
240
|
|
|
241
|
+
/**
|
|
242
|
+
Not safe for concurrent use. Create a new instance per call if you need concurrency.
|
|
243
|
+
*/
|
|
241
244
|
export declare class FileTypeParser {
|
|
242
245
|
/**
|
|
243
246
|
File type detectors.
|
package/source/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import {detectPng} from './detectors/png.js';
|
|
|
25
25
|
import {detectAsf} from './detectors/asf.js';
|
|
26
26
|
|
|
27
27
|
export const reasonableDetectionSizeInBytes = 4100; // A fair amount of file-types are detectable within this range.
|
|
28
|
-
const maximumMpegOffsetTolerance = reasonableDetectionSizeInBytes -
|
|
28
|
+
const maximumMpegOffsetTolerance = reasonableDetectionSizeInBytes - 4; // Keep room for the 4 bytes of the frame header at the deepest scanned offset.
|
|
29
29
|
const maximumNestedGzipDetectionSizeInBytes = maximumUntrustedSkipSizeInBytes;
|
|
30
30
|
const maximumNestedGzipProbeDepth = 1;
|
|
31
31
|
const unknownSizeGzipProbeTimeoutInMilliseconds = 100;
|
|
@@ -1729,11 +1729,11 @@ export class FileTypeParser {
|
|
|
1729
1729
|
};
|
|
1730
1730
|
}
|
|
1731
1731
|
|
|
1732
|
-
// Adjust buffer to `mpegOffsetTolerance
|
|
1733
|
-
await tokenizer.peekBuffer(this.buffer, {length: Math.min(
|
|
1732
|
+
// Adjust buffer to `mpegOffsetTolerance`, plus the 4 bytes of the frame header itself
|
|
1733
|
+
await tokenizer.peekBuffer(this.buffer, {length: Math.min(4 + this.options.mpegOffsetTolerance, fileSize), mayBeLess: true});
|
|
1734
1734
|
|
|
1735
1735
|
// Check MPEG 1 or 2 Layer 3 header, or 'layer 0' for ADTS (MPEG sync-word 0xFFE)
|
|
1736
|
-
if (this.buffer.length >= (
|
|
1736
|
+
if (this.buffer.length >= (4 + this.options.mpegOffsetTolerance)) {
|
|
1737
1737
|
for (let depth = 0; depth <= this.options.mpegOffsetTolerance; ++depth) {
|
|
1738
1738
|
const type = this.scanMpeg(depth);
|
|
1739
1739
|
if (type) {
|
|
@@ -1865,22 +1865,34 @@ export class FileTypeParser {
|
|
|
1865
1865
|
*/
|
|
1866
1866
|
scanMpeg(offset) {
|
|
1867
1867
|
if (this.check([0xFF, 0xE0], {offset, mask: [0xFF, 0xE0]})) {
|
|
1868
|
+
// Both (ADTS) MPEG-2 and MPEG-4 are AAC
|
|
1868
1869
|
if (this.check([0x10], {offset: offset + 1, mask: [0x16]})) {
|
|
1869
|
-
// Check for (ADTS) MPEG-2
|
|
1870
|
-
if (this.check([0x08], {offset: offset + 1, mask: [0x08]})) {
|
|
1871
|
-
return {
|
|
1872
|
-
ext: 'aac',
|
|
1873
|
-
mime: 'audio/aac',
|
|
1874
|
-
};
|
|
1875
|
-
}
|
|
1876
|
-
|
|
1877
|
-
// Must be (ADTS) MPEG-4
|
|
1878
1870
|
return {
|
|
1879
1871
|
ext: 'aac',
|
|
1880
1872
|
mime: 'audio/aac',
|
|
1881
1873
|
};
|
|
1882
1874
|
}
|
|
1883
1875
|
|
|
1876
|
+
// An MPEG-1 Layer I header with CRC protection enabled is byte-identical to a UTF-16 LE BOM, so text files cannot be told apart from audio. `file(1)` disables MPEG-1 Layer I detection completely for this reason; we only drop the colliding variant.
|
|
1877
|
+
if (this.check([0xFF, 0xFE], {offset})) {
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
// Reject the reserved MPEG version `01`
|
|
1882
|
+
if (this.check([0x08], {offset: offset + 1, mask: [0x18]})) {
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
// Reject the `bad` (`1111`) bitrate index
|
|
1887
|
+
if (this.check([0xF0], {offset: offset + 2, mask: [0xF0]})) {
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
// Reject the reserved sampling frequency `11`
|
|
1892
|
+
if (this.check([0x0C], {offset: offset + 2, mask: [0x0C]})) {
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1884
1896
|
// MPEG 1 or 2 Layer 3 header
|
|
1885
1897
|
// Check for MPEG layer 3
|
|
1886
1898
|
if (this.check([0x02], {offset: offset + 1, mask: [0x06]})) {
|