llonebot-dist 7.11.0 → 7.11.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/llbot.js +38149 -71365
- package/llbot.js.map +1 -1
- package/node_modules/file-type/package.json +36 -53
- package/node_modules/file-type/readme.md +35 -102
- package/node_modules/file-type/source/detectors/asf.js +127 -0
- package/node_modules/file-type/source/detectors/ebml.js +120 -0
- package/node_modules/file-type/source/detectors/png.js +123 -0
- package/node_modules/file-type/source/detectors/zip.js +643 -0
- package/node_modules/file-type/{core.d.ts → source/index.d.ts} +49 -22
- package/node_modules/file-type/{core.js → source/index.js} +253 -1056
- package/node_modules/file-type/source/index.test-d.ts +53 -0
- package/node_modules/file-type/source/parser.js +65 -0
- package/node_modules/file-type/{supported.js → source/supported.js} +14 -6
- package/node_modules/file-type/{util.js → source/tokens.js} +2 -2
- package/node_modules/strtok3/LICENSE.txt +1 -1
- package/node_modules/strtok3/README.md +2 -2
- package/node_modules/strtok3/lib/AbstractTokenizer.d.ts +1 -1
- package/node_modules/strtok3/lib/AbstractTokenizer.js +4 -1
- package/node_modules/strtok3/lib/ReadStreamTokenizer.d.ts +3 -0
- package/node_modules/strtok3/lib/ReadStreamTokenizer.js +6 -1
- package/node_modules/strtok3/lib/stream/WebStreamByobReader.js +1 -1
- package/node_modules/strtok3/package.json +8 -8
- package/node_modules/ws/index.js +15 -6
- package/node_modules/ws/lib/permessage-deflate.js +6 -6
- package/node_modules/ws/lib/websocket-server.js +5 -5
- package/node_modules/ws/lib/websocket.js +6 -6
- package/node_modules/ws/package.json +4 -3
- package/node_modules/ws/wrapper.mjs +14 -1
- package/package.json +1 -1
- package/webui/assets/index-BkP41fNe.js +37 -0
- package/webui/assets/{index-B6wi2XZx.css → index-DsGxgscs.css} +1 -1
- package/webui/index.html +2 -2
- package//346/233/264/346/226/260/346/227/245/345/277/227.txt +42 -2
- package/node_modules/file-type/index.d.ts +0 -98
- package/node_modules/file-type/index.js +0 -110
- package/webui/assets/index-DwQjH3d6.js +0 -37
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-type",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "22.0.0",
|
|
4
4
|
"description": "Detect the file type of a file, stream, or data",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/file-type",
|
|
@@ -12,41 +12,18 @@
|
|
|
12
12
|
},
|
|
13
13
|
"type": "module",
|
|
14
14
|
"exports": {
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
"types": "./index.d.ts",
|
|
18
|
-
"import": "./index.js",
|
|
19
|
-
"module-sync": "./index.js"
|
|
20
|
-
},
|
|
21
|
-
"default": {
|
|
22
|
-
"types": "./core.d.ts",
|
|
23
|
-
"import": "./core.js",
|
|
24
|
-
"module-sync": "./core.js"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"./core": {
|
|
28
|
-
"types": "./core.d.ts",
|
|
29
|
-
"default": "./core.js"
|
|
30
|
-
},
|
|
31
|
-
"./node": {
|
|
32
|
-
"types": "./index.d.ts",
|
|
33
|
-
"default": "./index.js"
|
|
34
|
-
}
|
|
15
|
+
"types": "./source/index.d.ts",
|
|
16
|
+
"default": "./source/index.js"
|
|
35
17
|
},
|
|
36
18
|
"sideEffects": false,
|
|
37
19
|
"engines": {
|
|
38
|
-
"node": ">=
|
|
20
|
+
"node": ">=22"
|
|
39
21
|
},
|
|
40
22
|
"scripts": {
|
|
41
|
-
"test": "xo && ava && tsd"
|
|
23
|
+
"test": "xo && ava && tsd --typings source/index.d.ts --files source/index.test-d.ts"
|
|
42
24
|
},
|
|
43
25
|
"files": [
|
|
44
|
-
"
|
|
45
|
-
"index.d.ts",
|
|
46
|
-
"core.js",
|
|
47
|
-
"core.d.ts",
|
|
48
|
-
"supported.js",
|
|
49
|
-
"util.js"
|
|
26
|
+
"source"
|
|
50
27
|
],
|
|
51
28
|
"keywords": [
|
|
52
29
|
"mime",
|
|
@@ -248,42 +225,48 @@
|
|
|
248
225
|
"ppsx",
|
|
249
226
|
"tar.gz",
|
|
250
227
|
"reg",
|
|
251
|
-
"dat"
|
|
228
|
+
"dat",
|
|
229
|
+
"key",
|
|
230
|
+
"numbers",
|
|
231
|
+
"pages"
|
|
252
232
|
],
|
|
253
233
|
"dependencies": {
|
|
254
234
|
"@tokenizer/inflate": "^0.4.1",
|
|
255
|
-
"strtok3": "^10.3.
|
|
256
|
-
"token-types": "^6.1.
|
|
257
|
-
"uint8array-extras": "^1.
|
|
235
|
+
"strtok3": "^10.3.5",
|
|
236
|
+
"token-types": "^6.1.2",
|
|
237
|
+
"uint8array-extras": "^1.5.0"
|
|
258
238
|
},
|
|
259
239
|
"devDependencies": {
|
|
260
240
|
"@tokenizer/token": "^0.3.0",
|
|
261
|
-
"@types/node": "^25.
|
|
241
|
+
"@types/node": "^25.5.0",
|
|
262
242
|
"ava": "^7.0.0",
|
|
263
243
|
"commonmark": "^0.31.2",
|
|
264
244
|
"get-stream": "^9.0.1",
|
|
265
|
-
"noop-stream": "^1.0.0",
|
|
266
245
|
"tsd": "^0.33.0",
|
|
267
|
-
"xo": "^0.
|
|
246
|
+
"xo": "^2.0.2"
|
|
268
247
|
},
|
|
269
|
-
"xo":
|
|
270
|
-
|
|
271
|
-
"
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
248
|
+
"xo": [
|
|
249
|
+
{
|
|
250
|
+
"ignores": [
|
|
251
|
+
"fixture/**"
|
|
252
|
+
]
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"rules": {
|
|
256
|
+
"no-inner-declarations": "warn",
|
|
257
|
+
"no-await-in-loop": "warn",
|
|
258
|
+
"no-bitwise": "off",
|
|
259
|
+
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
260
|
+
"unicorn/text-encoding-identifier-case": "off",
|
|
261
|
+
"unicorn/switch-case-braces": "off",
|
|
262
|
+
"unicorn/prefer-top-level-await": "off",
|
|
263
|
+
"n/prefer-global/buffer": "off",
|
|
264
|
+
"@stylistic/curly-newline": "off",
|
|
265
|
+
"ava/no-useless-t-pass": "off",
|
|
266
|
+
"ava/no-conditional-assertion": "off"
|
|
267
|
+
}
|
|
285
268
|
}
|
|
286
|
-
|
|
269
|
+
],
|
|
287
270
|
"ava": {
|
|
288
271
|
"serial": true
|
|
289
272
|
}
|
|
@@ -50,52 +50,6 @@ console.log(await fileTypeFromBuffer(buffer));
|
|
|
50
50
|
|
|
51
51
|
Determine file type from a stream:
|
|
52
52
|
|
|
53
|
-
```js
|
|
54
|
-
import fs from 'node:fs';
|
|
55
|
-
import {fileTypeFromStream} from 'file-type';
|
|
56
|
-
|
|
57
|
-
const stream = fs.createReadStream('Unicorn.mp4');
|
|
58
|
-
|
|
59
|
-
console.log(await fileTypeFromStream(stream));
|
|
60
|
-
//=> {ext: 'mp4', mime: 'video/mp4'}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
The stream method can also be used to read from a remote location:
|
|
64
|
-
|
|
65
|
-
```js
|
|
66
|
-
import got from 'got';
|
|
67
|
-
import {fileTypeFromStream} from 'file-type';
|
|
68
|
-
|
|
69
|
-
const url = 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg';
|
|
70
|
-
|
|
71
|
-
const stream = got.stream(url);
|
|
72
|
-
|
|
73
|
-
console.log(await fileTypeFromStream(stream));
|
|
74
|
-
//=> {ext: 'jpg', mime: 'image/jpeg'}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Another stream example:
|
|
78
|
-
|
|
79
|
-
```js
|
|
80
|
-
import stream from 'node:stream';
|
|
81
|
-
import fs from 'node:fs';
|
|
82
|
-
import crypto from 'node:crypto';
|
|
83
|
-
import {fileTypeStream} from 'file-type';
|
|
84
|
-
|
|
85
|
-
const read = fs.createReadStream('encrypted.enc');
|
|
86
|
-
const decipher = crypto.createDecipheriv(alg, key, iv);
|
|
87
|
-
|
|
88
|
-
const streamWithFileType = await fileTypeStream(stream.pipeline(read, decipher));
|
|
89
|
-
|
|
90
|
-
console.log(streamWithFileType.fileType);
|
|
91
|
-
//=> {ext: 'mov', mime: 'video/quicktime'}
|
|
92
|
-
|
|
93
|
-
const write = fs.createWriteStream(`decrypted.${streamWithFileType.fileType.ext}`);
|
|
94
|
-
streamWithFileType.pipe(write);
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Browser
|
|
98
|
-
|
|
99
53
|
```js
|
|
100
54
|
import {fileTypeFromStream} from 'file-type';
|
|
101
55
|
|
|
@@ -112,7 +66,7 @@ console.log(fileType);
|
|
|
112
66
|
|
|
113
67
|
### fileTypeFromBuffer(buffer, options)
|
|
114
68
|
|
|
115
|
-
Detect the file type of a `Uint8Array
|
|
69
|
+
Detect the file type of a `Uint8Array` or `ArrayBuffer`.
|
|
116
70
|
|
|
117
71
|
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
118
72
|
|
|
@@ -135,11 +89,9 @@ A buffer representing file data. It works best if the buffer contains the entire
|
|
|
135
89
|
|
|
136
90
|
Detect the file type of a file path.
|
|
137
91
|
|
|
138
|
-
|
|
92
|
+
Only available in environments where `node:fs` is available, such as Node.js. To read from a [`File`](https://developer.mozilla.org/docs/Web/API/File), see [`fileTypeFromBlob()`](#filetypefromblobblob-options).
|
|
139
93
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
94
|
+
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the file.
|
|
143
95
|
|
|
144
96
|
Returns a `Promise` for an object with the detected file type:
|
|
145
97
|
|
|
@@ -154,14 +106,10 @@ Type: `string`
|
|
|
154
106
|
|
|
155
107
|
The file path to parse.
|
|
156
108
|
|
|
157
|
-
### fileTypeFromStream(stream)
|
|
109
|
+
### fileTypeFromStream(stream, options)
|
|
158
110
|
|
|
159
111
|
Detect the file type of a [web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
|
160
112
|
|
|
161
|
-
If the engine is Node.js, this may also be a [Node.js `stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable).
|
|
162
|
-
|
|
163
|
-
Direct support for Node.js streams will be dropped in the future, when Node.js streams can be converted to Web streams (see [`toWeb()`](https://nodejs.org/api/stream.html#streamreadabletowebstreamreadable-options)).
|
|
164
|
-
|
|
165
113
|
The file type is detected by checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of the buffer.
|
|
166
114
|
|
|
167
115
|
Returns a `Promise` for an object with the detected file type:
|
|
@@ -173,13 +121,16 @@ Or `undefined` when there is no match.
|
|
|
173
121
|
|
|
174
122
|
#### stream
|
|
175
123
|
|
|
176
|
-
Type: [Web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
|
124
|
+
Type: [Web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
|
177
125
|
|
|
178
126
|
A readable stream representing file data.
|
|
179
127
|
|
|
128
|
+
> [!TIP]
|
|
129
|
+
> If you have a Node.js `stream.Readable`, convert it with [`Readable.toWeb()`](https://nodejs.org/api/stream.html#streamreadabletowebstreamreadable-options).
|
|
130
|
+
|
|
180
131
|
### fileTypeFromBlob(blob, options)
|
|
181
132
|
|
|
182
|
-
Detect the file type of a [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob)
|
|
133
|
+
Detect the file type of a [`Blob`](https://developer.mozilla.org/docs/Web/API/Blob).
|
|
183
134
|
|
|
184
135
|
> [!TIP]
|
|
185
136
|
> A [`File` object](https://developer.mozilla.org/docs/Web/API/File) is a `Blob` and can be passed in here.
|
|
@@ -248,7 +199,6 @@ import {S3Client} from '@aws-sdk/client-s3';
|
|
|
248
199
|
import {makeChunkedTokenizerFromS3} from '@tokenizer/s3';
|
|
249
200
|
import {fileTypeFromTokenizer} from 'file-type';
|
|
250
201
|
|
|
251
|
-
// Initialize the S3 client
|
|
252
202
|
// Initialize S3 client
|
|
253
203
|
const s3 = new S3Client();
|
|
254
204
|
|
|
@@ -275,16 +225,16 @@ A file source implementing the [tokenizer interface](https://github.com/Borewit/
|
|
|
275
225
|
|
|
276
226
|
Returns a `Promise` which resolves to the original readable stream argument, but with an added `fileType` property, which is an object like the one returned from `fileTypeFromFile()`.
|
|
277
227
|
|
|
278
|
-
This method can be handy to put in
|
|
228
|
+
This method can be handy to put in a stream pipeline, but it comes with a price.
|
|
279
229
|
Internally `stream()` builds up a buffer of `sampleSize` bytes, used as a sample, to determine the file type.
|
|
280
230
|
The sample size impacts the file detection resolution.
|
|
281
231
|
A smaller sample size will result in lower probability of the best file type detection.
|
|
282
232
|
|
|
283
|
-
|
|
233
|
+
#### webStream
|
|
284
234
|
|
|
285
|
-
|
|
235
|
+
Type: [Web `ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
|
|
286
236
|
|
|
287
|
-
|
|
237
|
+
The input stream.
|
|
288
238
|
|
|
289
239
|
#### options
|
|
290
240
|
|
|
@@ -302,25 +252,18 @@ The sample size in bytes.
|
|
|
302
252
|
#### Example
|
|
303
253
|
|
|
304
254
|
```js
|
|
305
|
-
import got from 'got';
|
|
306
255
|
import {fileTypeStream} from 'file-type';
|
|
307
256
|
|
|
308
257
|
const url = 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg';
|
|
309
258
|
|
|
310
|
-
const
|
|
311
|
-
const
|
|
259
|
+
const response = await fetch(url);
|
|
260
|
+
const stream = await fileTypeStream(response.body, {sampleSize: 1024});
|
|
312
261
|
|
|
313
|
-
if (
|
|
314
|
-
//
|
|
262
|
+
if (stream.fileType?.mime === 'image/jpeg') {
|
|
263
|
+
// stream can be used to stream the JPEG image (from the very beginning of the stream)
|
|
315
264
|
}
|
|
316
265
|
```
|
|
317
266
|
|
|
318
|
-
#### readableStream
|
|
319
|
-
|
|
320
|
-
Type: [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable)
|
|
321
|
-
|
|
322
|
-
The input stream.
|
|
323
|
-
|
|
324
267
|
### supportedExtensions
|
|
325
268
|
|
|
326
269
|
Returns a `Set<string>` of supported file extensions.
|
|
@@ -360,15 +303,11 @@ A tolerance of 10 bytes covers most cases.
|
|
|
360
303
|
Custom file type detectors are plugins designed to extend the default detection capabilities.
|
|
361
304
|
They allow support for uncommon file types, non-binary formats, or customized detection behavior.
|
|
362
305
|
|
|
363
|
-
Detectors can be added via the constructor options or by modifying `FileTypeParser#detectors` directly.
|
|
364
|
-
Detectors provided through the constructor are executed before the default ones.
|
|
365
|
-
|
|
366
306
|
Detectors can be added via the constructor options or by directly modifying `FileTypeParser#detectors`.
|
|
307
|
+
Detectors provided through the constructor are executed before the default ones.
|
|
367
308
|
|
|
368
309
|
### Example adding a detector
|
|
369
310
|
|
|
370
|
-
For example:
|
|
371
|
-
|
|
372
311
|
```js
|
|
373
312
|
import {FileTypeParser} from 'file-type';
|
|
374
313
|
import {detectXml} from '@file-type/xml';
|
|
@@ -394,14 +333,14 @@ If a detector returns `undefined`, the following rules apply:
|
|
|
394
333
|
|
|
395
334
|
### Writing your own custom detector
|
|
396
335
|
|
|
397
|
-
Below is an example of a custom detector
|
|
336
|
+
Below is an example of a custom detector. This can be passed to the `FileTypeParser` via the `customDetectors` option.
|
|
398
337
|
|
|
399
338
|
```js
|
|
400
339
|
import {FileTypeParser} from 'file-type';
|
|
401
340
|
|
|
402
341
|
const unicornDetector = {
|
|
403
342
|
id: 'unicorn', // May be used to recognize the detector in the detector list
|
|
404
|
-
|
|
343
|
+
async detect(tokenizer) {
|
|
405
344
|
const unicornHeader = [85, 78, 73, 67, 79, 82, 78]; // "UNICORN" in ASCII decimal
|
|
406
345
|
|
|
407
346
|
const buffer = new Uint8Array(unicornHeader.length);
|
|
@@ -426,7 +365,10 @@ console.log(fileType); // {ext: 'unicorn', mime: 'application/unicorn'}
|
|
|
426
365
|
@param fileType - The file type detected by standard or previous custom detectors, or `undefined` if no match is found.
|
|
427
366
|
@returns The detected file type, or `undefined` if no match is found.
|
|
428
367
|
*/
|
|
429
|
-
export type Detector =
|
|
368
|
+
export type Detector = {
|
|
369
|
+
id: string;
|
|
370
|
+
detect: (tokenizer: ITokenizer, fileType?: FileTypeResult) => Promise<FileTypeResult | undefined>;
|
|
371
|
+
};
|
|
430
372
|
```
|
|
431
373
|
|
|
432
374
|
## Abort signal
|
|
@@ -436,9 +378,9 @@ Some async operations can be aborted by passing an [`AbortSignal`](https://devel
|
|
|
436
378
|
```js
|
|
437
379
|
import {FileTypeParser} from 'file-type';
|
|
438
380
|
|
|
439
|
-
const abortController = new AbortController()
|
|
381
|
+
const abortController = new AbortController();
|
|
440
382
|
|
|
441
|
-
const parser = new FileTypeParser({
|
|
383
|
+
const parser = new FileTypeParser({signal: abortController.signal});
|
|
442
384
|
|
|
443
385
|
const promise = parser.fromStream(blob.stream());
|
|
444
386
|
|
|
@@ -447,6 +389,8 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
|
|
|
447
389
|
|
|
448
390
|
## Supported file types
|
|
449
391
|
|
|
392
|
+
MIME media subtypes prefixed with `x-ft-` are custom and defined by us. They are neither formally registered with IANA nor based on any informal conventions.
|
|
393
|
+
|
|
450
394
|
- [`3g2`](https://en.wikipedia.org/wiki/3GP_and_3G2#3G2) - Multimedia container format defined by the 3GPP2 for 3G CDMA2000 multimedia services
|
|
451
395
|
- [`3gp`](https://en.wikipedia.org/wiki/3GP_and_3G2#3GP) - Multimedia container format defined by the Third Generation Partnership Project (3GPP) for 3G UMTS multimedia services
|
|
452
396
|
- [`3mf`](https://en.wikipedia.org/wiki/3D_Manufacturing_Format) - 3D Manufacturing Format
|
|
@@ -528,6 +472,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
|
|
|
528
472
|
- [`jpx`](https://en.wikipedia.org/wiki/JPEG_2000) - JPEG 2000
|
|
529
473
|
- [`jxl`](https://en.wikipedia.org/wiki/JPEG_XL) - JPEG XL image format
|
|
530
474
|
- [`jxr`](https://en.wikipedia.org/wiki/JPEG_XR) - Joint Photographic Experts Group extended range
|
|
475
|
+
- [`key`](https://en.wikipedia.org/wiki/Keynote_(presentation_software)) - Apple Keynote presentation
|
|
531
476
|
- [`ktx`](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/) - OpenGL and OpenGL ES textures
|
|
532
477
|
- [`lnk`](https://en.wikipedia.org/wiki/Shortcut_%28computing%29#Microsoft_Windows) - Microsoft Windows file shortcut
|
|
533
478
|
- [`lz`](https://en.wikipedia.org/wiki/Lzip) - Archive file
|
|
@@ -554,6 +499,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
|
|
|
554
499
|
- [`mxf`](https://en.wikipedia.org/wiki/Material_Exchange_Format) - Material Exchange Format
|
|
555
500
|
- [`nef`](https://www.nikonusa.com/en/learn-and-explore/a/products-and-innovation/nikon-electronic-format-nef.html) - Nikon Electronic Format image file
|
|
556
501
|
- [`nes`](https://fileinfo.com/extension/nes) - Nintendo NES ROM
|
|
502
|
+
- [`numbers`](https://en.wikipedia.org/wiki/Numbers_(spreadsheet)) - Apple Numbers spreadsheet
|
|
557
503
|
- [`odg`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for drawing
|
|
558
504
|
- [`odp`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for presentations
|
|
559
505
|
- [`ods`](https://en.wikipedia.org/wiki/OpenDocument) - OpenDocument for spreadsheets
|
|
@@ -570,6 +516,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
|
|
|
570
516
|
- [`otp`](https://en.wikipedia.org/wiki/OpenDocument_technical_specification#Templates) - OpenDocument template for presentations
|
|
571
517
|
- [`ots`](https://en.wikipedia.org/wiki/OpenDocument_technical_specification#Templates) - OpenDocument template for spreadsheets
|
|
572
518
|
- [`ott`](https://en.wikipedia.org/wiki/OpenDocument_technical_specification#Templates) - OpenDocument template for word processing
|
|
519
|
+
- [`pages`](https://en.wikipedia.org/wiki/Pages_(word_processor)) - Apple Pages document
|
|
573
520
|
- [`parquet`](https://en.wikipedia.org/wiki/Apache_Parquet) - Apache Parquet
|
|
574
521
|
- [`pcap`](https://wiki.wireshark.org/Development/LibpcapFileFormat) - Libpcap File Format
|
|
575
522
|
- [`pdf`](https://en.wikipedia.org/wiki/Portable_Document_Format) - Portable Document Format
|
|
@@ -581,7 +528,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
|
|
|
581
528
|
- [`ppsx`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions#PowerPoint) - Office PowerPoint 2007 slide show
|
|
582
529
|
- [`pptm`](https://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions) - Microsoft PowerPoint macro-enabled document
|
|
583
530
|
- [`pptx`](https://en.wikipedia.org/wiki/Office_Open_XML) - Microsoft PowerPoint document
|
|
584
|
-
- [`ps`](https://en.wikipedia.org/wiki/Postscript) -
|
|
531
|
+
- [`ps`](https://en.wikipedia.org/wiki/Postscript) - PostScript
|
|
585
532
|
- [`psd`](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format) - Adobe Photoshop document
|
|
586
533
|
- [`pst`](https://en.wikipedia.org/wiki/Personal_Storage_Table) - Personal Storage Table file
|
|
587
534
|
- [`qcp`](https://en.wikipedia.org/wiki/QCP) - Tagged and chunked data
|
|
@@ -598,7 +545,7 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
|
|
|
598
545
|
- [`skp`](https://en.wikipedia.org/wiki/SketchUp) - SketchUp
|
|
599
546
|
- [`spx`](https://en.wikipedia.org/wiki/Ogg) - Audio file
|
|
600
547
|
- [`sqlite`](https://www.sqlite.org/fileformat2.html) - SQLite file
|
|
601
|
-
- [`stl`](https://en.wikipedia.org/wiki/STL_(file_format)) - Standard
|
|
548
|
+
- [`stl`](https://en.wikipedia.org/wiki/STL_(file_format)) - Standard Tessellated Geometry File Format (ASCII only)
|
|
602
549
|
- [`swf`](https://en.wikipedia.org/wiki/SWF) - Adobe Flash Player file
|
|
603
550
|
- [`tar`](https://en.wikipedia.org/wiki/Tar_(computing)#File_format) - Tape archive or tarball
|
|
604
551
|
- [`tar.gz`](https://en.wikipedia.org/wiki/Gzip) - Gzipped tape archive (tarball)
|
|
@@ -630,29 +577,15 @@ abortController.abort(); // Abort file-type reading from the Blob stream.
|
|
|
630
577
|
|
|
631
578
|
*[Pull requests](.github/pull_request_template.md) are welcome for additional commonly used file types.*
|
|
632
579
|
|
|
633
|
-
The following file types will not be accepted, but most of them are supported by [third-party
|
|
580
|
+
The following file types will not be accepted, but most of them are supported by [third-party detectors](#available-third-party-file-type-detectors).
|
|
634
581
|
- [MS-CFB: Microsoft Compound File Binary File Format based formats](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-cfb/53989ce4-7b05-4f8d-829b-d08d6148375b)
|
|
635
582
|
- `.doc` - Microsoft Word 97-2003 Document
|
|
636
583
|
- `.xls` - Microsoft Excel 97-2003 Document
|
|
637
|
-
- `.ppt` - Microsoft
|
|
584
|
+
- `.ppt` - Microsoft PowerPoint 97-2003 Document
|
|
638
585
|
- `.msi` - Microsoft Windows Installer
|
|
639
586
|
- `.csv` - [Reason.](https://github.com/sindresorhus/file-type/issues/264#issuecomment-568439196)
|
|
640
587
|
- `.svg`
|
|
641
588
|
|
|
642
|
-
#### tokenizer
|
|
643
|
-
|
|
644
|
-
Type: [`ITokenizer`](https://github.com/Borewit/strtok3#tokenizer)
|
|
645
|
-
|
|
646
|
-
Usable as source of the examined file.
|
|
647
|
-
|
|
648
|
-
#### fileType
|
|
649
|
-
|
|
650
|
-
Type: `FileTypeResult`
|
|
651
|
-
|
|
652
|
-
An object having an `ext` (extension) and `mime` (mime type) property.
|
|
653
|
-
|
|
654
|
-
Detected by the standard detections or a previous custom detection. Undefined if no matching fileTypeResult could be found.
|
|
655
|
-
|
|
656
589
|
## Related
|
|
657
590
|
|
|
658
591
|
- [file-type-cli](https://github.com/sindresorhus/file-type-cli) - CLI for this module
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as Token from 'token-types';
|
|
2
|
+
import * as strtok3 from 'strtok3/core';
|
|
3
|
+
import {
|
|
4
|
+
maximumUntrustedSkipSizeInBytes,
|
|
5
|
+
ParserHardLimitError,
|
|
6
|
+
checkBytes,
|
|
7
|
+
safeReadBuffer,
|
|
8
|
+
safeIgnore,
|
|
9
|
+
hasUnknownFileSize,
|
|
10
|
+
hasExceededUnknownSizeScanBudget,
|
|
11
|
+
} from '../parser.js';
|
|
12
|
+
|
|
13
|
+
const maximumAsfHeaderObjectCount = 512;
|
|
14
|
+
const maximumAsfHeaderPayloadSizeInBytes = 1024 * 1024;
|
|
15
|
+
|
|
16
|
+
export async function detectAsf(tokenizer) {
|
|
17
|
+
let isMalformedAsf = false;
|
|
18
|
+
try {
|
|
19
|
+
async function readHeader() {
|
|
20
|
+
const guid = new Uint8Array(16);
|
|
21
|
+
await safeReadBuffer(tokenizer, guid, undefined, {
|
|
22
|
+
maximumLength: guid.length,
|
|
23
|
+
reason: 'ASF header GUID',
|
|
24
|
+
});
|
|
25
|
+
return {
|
|
26
|
+
id: guid,
|
|
27
|
+
size: Number(await tokenizer.readToken(Token.UINT64_LE)),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
await safeIgnore(tokenizer, 30, {
|
|
32
|
+
maximumLength: 30,
|
|
33
|
+
reason: 'ASF header prelude',
|
|
34
|
+
});
|
|
35
|
+
const isUnknownFileSize = hasUnknownFileSize(tokenizer);
|
|
36
|
+
const asfHeaderScanStart = tokenizer.position;
|
|
37
|
+
let asfHeaderObjectCount = 0;
|
|
38
|
+
while (tokenizer.position + 24 < tokenizer.fileInfo.size) {
|
|
39
|
+
asfHeaderObjectCount++;
|
|
40
|
+
if (asfHeaderObjectCount > maximumAsfHeaderObjectCount) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (hasExceededUnknownSizeScanBudget(tokenizer, asfHeaderScanStart, maximumUntrustedSkipSizeInBytes)) {
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const previousPosition = tokenizer.position;
|
|
49
|
+
const header = await readHeader();
|
|
50
|
+
let payload = header.size - 24;
|
|
51
|
+
if (
|
|
52
|
+
!Number.isFinite(payload)
|
|
53
|
+
|| payload < 0
|
|
54
|
+
) {
|
|
55
|
+
isMalformedAsf = true;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (checkBytes(header.id, [0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65])) {
|
|
60
|
+
// Sync on Stream-Properties-Object (B7DC0791-A9B7-11CF-8EE6-00C00C205365)
|
|
61
|
+
const typeId = new Uint8Array(16);
|
|
62
|
+
payload -= await safeReadBuffer(tokenizer, typeId, undefined, {
|
|
63
|
+
maximumLength: typeId.length,
|
|
64
|
+
reason: 'ASF stream type GUID',
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (checkBytes(typeId, [0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B])) {
|
|
68
|
+
// Found audio:
|
|
69
|
+
return {
|
|
70
|
+
ext: 'asf',
|
|
71
|
+
mime: 'audio/x-ms-asf',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (checkBytes(typeId, [0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B])) {
|
|
76
|
+
// Found video:
|
|
77
|
+
return {
|
|
78
|
+
ext: 'asf',
|
|
79
|
+
mime: 'video/x-ms-asf',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
isUnknownFileSize
|
|
88
|
+
&& payload > maximumAsfHeaderPayloadSizeInBytes
|
|
89
|
+
) {
|
|
90
|
+
isMalformedAsf = true;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
await safeIgnore(tokenizer, payload, {
|
|
95
|
+
maximumLength: isUnknownFileSize ? maximumAsfHeaderPayloadSizeInBytes : tokenizer.fileInfo.size,
|
|
96
|
+
reason: 'ASF header payload',
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Safeguard against malformed files: break if the position did not advance.
|
|
100
|
+
if (tokenizer.position <= previousPosition) {
|
|
101
|
+
isMalformedAsf = true;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
if (
|
|
107
|
+
error instanceof strtok3.EndOfStreamError
|
|
108
|
+
|| error instanceof ParserHardLimitError
|
|
109
|
+
) {
|
|
110
|
+
if (hasUnknownFileSize(tokenizer)) {
|
|
111
|
+
isMalformedAsf = true;
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (isMalformedAsf) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Default to ASF generic extension
|
|
123
|
+
return {
|
|
124
|
+
ext: 'asf',
|
|
125
|
+
mime: 'application/vnd.ms-asf',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as Token from 'token-types';
|
|
2
|
+
import {getUintBE} from 'uint8array-extras';
|
|
3
|
+
import {
|
|
4
|
+
maximumUntrustedSkipSizeInBytes,
|
|
5
|
+
getSafeBound,
|
|
6
|
+
safeReadBuffer,
|
|
7
|
+
safeIgnore,
|
|
8
|
+
hasUnknownFileSize,
|
|
9
|
+
hasExceededUnknownSizeScanBudget,
|
|
10
|
+
} from '../parser.js';
|
|
11
|
+
|
|
12
|
+
const maximumEbmlDocumentTypeSizeInBytes = 64;
|
|
13
|
+
const maximumEbmlElementPayloadSizeInBytes = 1024 * 1024;
|
|
14
|
+
const maximumEbmlElementCount = 256;
|
|
15
|
+
|
|
16
|
+
export async function detectEbml(tokenizer) {
|
|
17
|
+
async function readField() {
|
|
18
|
+
const msb = await tokenizer.peekNumber(Token.UINT8);
|
|
19
|
+
let mask = 0x80;
|
|
20
|
+
let ic = 0; // 0 = A, 1 = B, 2 = C, 3 = D
|
|
21
|
+
|
|
22
|
+
while ((msb & mask) === 0 && mask !== 0) {
|
|
23
|
+
++ic;
|
|
24
|
+
mask >>= 1;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const id = new Uint8Array(ic + 1);
|
|
28
|
+
await safeReadBuffer(tokenizer, id, undefined, {
|
|
29
|
+
maximumLength: id.length,
|
|
30
|
+
reason: 'EBML field',
|
|
31
|
+
});
|
|
32
|
+
return id;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function readElement() {
|
|
36
|
+
const idField = await readField();
|
|
37
|
+
const lengthField = await readField();
|
|
38
|
+
|
|
39
|
+
lengthField[0] ^= 0x80 >> (lengthField.length - 1);
|
|
40
|
+
const nrLength = Math.min(6, lengthField.length); // JavaScript can max read 6 bytes integer
|
|
41
|
+
|
|
42
|
+
const idView = new DataView(idField.buffer);
|
|
43
|
+
const lengthView = new DataView(lengthField.buffer, lengthField.length - nrLength, nrLength);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
id: getUintBE(idView),
|
|
47
|
+
len: getUintBE(lengthView),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function readChildren(children) {
|
|
52
|
+
let ebmlElementCount = 0;
|
|
53
|
+
while (children > 0) {
|
|
54
|
+
ebmlElementCount++;
|
|
55
|
+
if (ebmlElementCount > maximumEbmlElementCount) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (hasExceededUnknownSizeScanBudget(tokenizer, ebmlScanStart, maximumUntrustedSkipSizeInBytes)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const previousPosition = tokenizer.position;
|
|
64
|
+
const element = await readElement();
|
|
65
|
+
|
|
66
|
+
if (element.id === 0x42_82) {
|
|
67
|
+
// `DocType` is a short string ("webm", "matroska", ...), reject implausible lengths to avoid large allocations.
|
|
68
|
+
if (element.len > maximumEbmlDocumentTypeSizeInBytes) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const documentTypeLength = getSafeBound(element.len, maximumEbmlDocumentTypeSizeInBytes, 'EBML DocType');
|
|
73
|
+
const rawValue = await tokenizer.readToken(new Token.StringType(documentTypeLength));
|
|
74
|
+
return rawValue.replaceAll(/\0.*$/gv, ''); // Return DocType
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
hasUnknownFileSize(tokenizer)
|
|
79
|
+
&& (
|
|
80
|
+
!Number.isFinite(element.len)
|
|
81
|
+
|| element.len < 0
|
|
82
|
+
|| element.len > maximumEbmlElementPayloadSizeInBytes
|
|
83
|
+
)
|
|
84
|
+
) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await safeIgnore(tokenizer, element.len, {
|
|
89
|
+
maximumLength: hasUnknownFileSize(tokenizer) ? maximumEbmlElementPayloadSizeInBytes : tokenizer.fileInfo.size,
|
|
90
|
+
reason: 'EBML payload',
|
|
91
|
+
}); // ignore payload
|
|
92
|
+
--children;
|
|
93
|
+
|
|
94
|
+
// Safeguard against malformed files: bail if the position did not advance.
|
|
95
|
+
if (tokenizer.position <= previousPosition) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const rootElement = await readElement();
|
|
102
|
+
const ebmlScanStart = tokenizer.position;
|
|
103
|
+
const documentType = await readChildren(rootElement.len);
|
|
104
|
+
|
|
105
|
+
switch (documentType) {
|
|
106
|
+
case 'webm':
|
|
107
|
+
return {
|
|
108
|
+
ext: 'webm',
|
|
109
|
+
mime: 'video/webm',
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
case 'matroska':
|
|
113
|
+
return {
|
|
114
|
+
ext: 'mkv',
|
|
115
|
+
mime: 'video/matroska',
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
default:
|
|
119
|
+
}
|
|
120
|
+
}
|