file-type 14.6.2 → 15.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core.d.ts CHANGED
@@ -23,6 +23,7 @@ declare namespace core {
23
23
  | 'icns'
24
24
  | 'jxr'
25
25
  | 'psd'
26
+ | 'indd'
26
27
  | 'zip'
27
28
  | 'tar'
28
29
  | 'rar'
@@ -72,7 +73,7 @@ declare namespace core {
72
73
  | 'rpm'
73
74
  | 'Z'
74
75
  | 'lz'
75
- | 'msi'
76
+ | 'cfb'
76
77
  | 'mxf'
77
78
  | 'mts'
78
79
  | 'wasm'
@@ -134,7 +135,8 @@ declare namespace core {
134
135
  | 'avif'
135
136
  | 'eps'
136
137
  | 'lzh'
137
- | 'pgp';
138
+ | 'pgp'
139
+ | 'asar';
138
140
 
139
141
  type MimeType =
140
142
  | 'image/jpeg'
@@ -149,6 +151,7 @@ declare namespace core {
149
151
  | 'image/icns'
150
152
  | 'image/vnd.ms-photo'
151
153
  | 'image/vnd.adobe.photoshop'
154
+ | 'application/x-indesign'
152
155
  | 'application/epub+zip'
153
156
  | 'application/x-xpinstall'
154
157
  | 'application/vnd.oasis.opendocument.text'
@@ -211,7 +214,7 @@ declare namespace core {
211
214
  | 'application/x-rpm'
212
215
  | 'application/x-compress'
213
216
  | 'application/x-lzip'
214
- | 'application/x-msi'
217
+ | 'application/x-cfb'
215
218
  | 'application/x-mie'
216
219
  | 'application/x-apache-arrow'
217
220
  | 'application/mxf'
@@ -260,7 +263,8 @@ declare namespace core {
260
263
  | 'application/vnd.sketchup.skp'
261
264
  | 'image/avif'
262
265
  | 'application/x-lzh-compressed'
263
- | 'application/pgp-encrypted';
266
+ | 'application/pgp-encrypted'
267
+ | 'application/x-asar';
264
268
 
265
269
  interface FileTypeResult {
266
270
  /**
@@ -332,7 +336,7 @@ declare namespace core {
332
336
  /**
333
337
  Supported file extensions.
334
338
  */
335
- const extensions: readonly core.FileExtension[];
339
+ const extensions: Set<core.FileExtension>;
336
340
 
337
341
  /**
338
342
  Supported MIME types.
package/core.js CHANGED
@@ -4,8 +4,7 @@ const strtok3 = require('strtok3/lib/core');
4
4
  const {
5
5
  stringToBytes,
6
6
  tarHeaderChecksumMatches,
7
- uint32SyncSafeToken,
8
- uint8ArrayUtf8ByteString
7
+ uint32SyncSafeToken
9
8
  } = require('./util');
10
9
  const supported = require('./supported');
11
10
 
@@ -464,7 +463,7 @@ async function _fromTokenizer(tokenizer) {
464
463
  ) {
465
464
  // They all can have MIME `video/mp4` except `application/mp4` special-case which is hard to detect.
466
465
  // For some cases, we're specific, everything else falls to `video/mp4` with `mp4` extension.
467
- const brandMajor = uint8ArrayUtf8ByteString(buffer, 8, 12).replace('\0', ' ').trim();
466
+ const brandMajor = buffer.toString('binary', 8, 12).replace('\0', ' ').trim();
468
467
  switch (brandMajor) {
469
468
  case 'avif':
470
469
  return {ext: 'avif', mime: 'image/avif'};
@@ -968,6 +967,10 @@ async function _fromTokenizer(tokenizer) {
968
967
 
969
968
  do {
970
969
  const chunk = await readChunkHeader();
970
+ if (chunk.length < 0) {
971
+ return; // Invalid chunk length
972
+ }
973
+
971
974
  switch (chunk.type) {
972
975
  case 'IDAT':
973
976
  return {
@@ -982,7 +985,7 @@ async function _fromTokenizer(tokenizer) {
982
985
  default:
983
986
  await tokenizer.ignore(chunk.length + 4); // Ignore chunk-data + CRC
984
987
  }
985
- } while (tokenizer.position < tokenizer.fileInfo.size);
988
+ } while (tokenizer.position + 8 < tokenizer.fileInfo.size);
986
989
 
987
990
  return {
988
991
  ext: 'png',
@@ -1170,6 +1173,14 @@ async function _fromTokenizer(tokenizer) {
1170
1173
  };
1171
1174
  }
1172
1175
 
1176
+ if (check([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1])) {
1177
+ // Detected Microsoft Compound File Binary File (MS-CFB) Format.
1178
+ return {
1179
+ ext: 'cfb',
1180
+ mime: 'application/x-cfb'
1181
+ };
1182
+ }
1183
+
1173
1184
  // Increase sample size from 12 to 256.
1174
1185
  await tokenizer.peekBuffer(buffer, {length: Math.min(256, tokenizer.fileInfo.size), mayBeLess: true});
1175
1186
 
@@ -1195,21 +1206,22 @@ async function _fromTokenizer(tokenizer) {
1195
1206
  };
1196
1207
  }
1197
1208
 
1198
- if (
1199
- check([0x30, 0x30, 0x30, 0x30, 0x30, 0x30], {offset: 148, mask: [0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8]}) && // Valid tar checksum
1200
- tarHeaderChecksumMatches(buffer)
1201
- ) {
1202
- return {
1203
- ext: 'tar',
1204
- mime: 'application/x-tar'
1205
- };
1206
- }
1207
-
1208
- if (check([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E])) {
1209
- return {
1210
- ext: 'msi',
1211
- mime: 'application/x-msi'
1212
- };
1209
+ if (check([0x04, 0x00, 0x00, 0x00]) && buffer.length >= 16) { // Rough & quick check Pickle/ASAR
1210
+ const jsonSize = buffer.readUInt32LE(12);
1211
+ if (jsonSize > 12 && jsonSize < 240 && buffer.length >= jsonSize + 16) {
1212
+ try {
1213
+ const header = buffer.slice(16, jsonSize + 16).toString();
1214
+ const json = JSON.parse(header);
1215
+ // Check if Pickle is ASAR
1216
+ if (json.files) { // Final check, assuring Pickle/ASAR format
1217
+ return {
1218
+ ext: 'asar',
1219
+ mime: 'application/x-asar'
1220
+ };
1221
+ }
1222
+ } catch (_) {
1223
+ }
1224
+ }
1213
1225
  }
1214
1226
 
1215
1227
  if (check([0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02])) {
@@ -1275,13 +1287,18 @@ async function _fromTokenizer(tokenizer) {
1275
1287
  };
1276
1288
  }
1277
1289
 
1290
+ if (check([0x06, 0x06, 0xED, 0xF5, 0xD8, 0x1D, 0x46, 0xE5, 0xBD, 0x31, 0xEF, 0xE7, 0xFE, 0x74, 0xB7, 0x1D])) {
1291
+ return {
1292
+ ext: 'indd',
1293
+ mime: 'application/x-indesign'
1294
+ };
1295
+ }
1296
+
1278
1297
  // Increase sample size from 256 to 512
1279
1298
  await tokenizer.peekBuffer(buffer, {length: Math.min(512, tokenizer.fileInfo.size), mayBeLess: true});
1280
1299
 
1281
- if (
1282
- check([0x30, 0x30, 0x30, 0x30, 0x30, 0x30], {offset: 148, mask: [0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8]}) && // Valid tar checksum
1283
- tarHeaderChecksumMatches(buffer)
1284
- ) {
1300
+ // Requires a buffer size of 512 bytes
1301
+ if (tarHeaderChecksumMatches(buffer)) {
1285
1302
  return {
1286
1303
  ext: 'tar',
1287
1304
  mime: 'application/x-tar'
@@ -1360,7 +1377,8 @@ const stream = readableStream => new Promise((resolve, reject) => {
1360
1377
  const pass = new stream.PassThrough();
1361
1378
  let outputStream;
1362
1379
  if (stream.pipeline) {
1363
- outputStream = stream.pipeline(readableStream, pass, () => {});
1380
+ outputStream = stream.pipeline(readableStream, pass, () => {
1381
+ });
1364
1382
  } else {
1365
1383
  outputStream = readableStream.pipe(pass);
1366
1384
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "file-type",
3
- "version": "14.6.2",
3
+ "version": "15.0.1",
4
4
  "description": "Detect the file type of a Buffer/Uint8Array/ArrayBuffer",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/file-type",
@@ -31,6 +31,7 @@
31
31
  "mime",
32
32
  "file",
33
33
  "type",
34
+ "magic",
34
35
  "archive",
35
36
  "image",
36
37
  "img",
@@ -66,6 +67,7 @@
66
67
  "icns",
67
68
  "jxr",
68
69
  "psd",
70
+ "indd",
69
71
  "zip",
70
72
  "tar",
71
73
  "rar",
@@ -110,7 +112,7 @@
110
112
  "rpm",
111
113
  "Z",
112
114
  "lz",
113
- "msi",
115
+ "cfb",
114
116
  "mxf",
115
117
  "mts",
116
118
  "wasm",
@@ -177,7 +179,8 @@
177
179
  "avif",
178
180
  "eps",
179
181
  "lzh",
180
- "pgp"
182
+ "pgp",
183
+ "asar"
181
184
  ],
182
185
  "devDependencies": {
183
186
  "@types/node": "^13.1.4",
package/readme.md CHANGED
@@ -1,4 +1,4 @@
1
- # file-type [![Build Status](https://travis-ci.com/sindresorhus/file-type.svg?branch=master)](https://travis-ci.ocomrg/sindresorhus/file-type)
1
+ # file-type [![Build Status](https://travis-ci.com/sindresorhus/file-type.svg?branch=master)](https://travis-ci.com/github/sindresorhus/file-type)
2
2
 
3
3
  > Detect the file type of a Buffer/Uint8Array/ArrayBuffer
4
4
 
@@ -289,6 +289,7 @@ Returns a set of supported MIME types.
289
289
  - [`icns`](https://en.wikipedia.org/wiki/Apple_Icon_Image_format)
290
290
  - [`jxr`](https://en.wikipedia.org/wiki/JPEG_XR)
291
291
  - [`psd`](https://en.wikipedia.org/wiki/Adobe_Photoshop#File_format)
292
+ - [`indd`](https://en.wikipedia.org/wiki/Adobe_InDesign#File_format)
292
293
  - [`zip`](https://en.wikipedia.org/wiki/Zip_(file_format))
293
294
  - [`tar`](https://en.wikipedia.org/wiki/Tar_(computing)#File_format)
294
295
  - [`rar`](https://en.wikipedia.org/wiki/RAR_(file_format))
@@ -342,7 +343,7 @@ Returns a set of supported MIME types.
342
343
  - [`rpm`](https://fileinfo.com/extension/rpm)
343
344
  - [`Z`](https://fileinfo.com/extension/z)
344
345
  - [`lz`](https://en.wikipedia.org/wiki/Lzip)
345
- - [`msi`](https://en.wikipedia.org/wiki/Windows_Installer)
346
+ - [`cfb`](https://en.wikipedia.org/wiki/Compound_File_Binary_Format)
346
347
  - [`mxf`](https://en.wikipedia.org/wiki/Material_Exchange_Format)
347
348
  - [`mts`](https://en.wikipedia.org/wiki/.m2ts)
348
349
  - [`wasm`](https://en.wikipedia.org/wiki/WebAssembly)
@@ -401,13 +402,16 @@ Returns a set of supported MIME types.
401
402
  - [`eps`](https://en.wikipedia.org/wiki/Encapsulated_PostScript) - Encapsulated PostScript
402
403
  - [`lzh`](https://en.wikipedia.org/wiki/LHA_(file_format)) - LZH archive
403
404
  - [`pgp`](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) - Pretty Good Privacy
405
+ - [`asar`](https://github.com/electron/asar#format) - Archive format primarily used to enclose Electron applications
404
406
 
405
407
  *Pull requests are welcome for additional commonly used file types.*
406
408
 
407
409
  The following file types will not be accepted:
408
- - `.doc` - Too old and difficult to parse.
409
- - `.xls` - Too old and difficult to parse.
410
- - `.ppt` - Too old and difficult to parse.
410
+ - [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), too old and difficult to parse:
411
+ - `.doc` - Microsoft Word 97-2003 Document
412
+ - `.xls` - Microsoft Excel 97-2003 Document
413
+ - `.ppt` - Microsoft PowerPoint97-2003 Document
414
+ - `.msi` - Microsoft Windows Installer
411
415
  - `.csv` - [Reason.](https://github.com/sindresorhus/file-type/issues/264#issuecomment-568439196)
412
416
  - `.svg` - Detecting it requires a full-blown parser. Check out [`is-svg`](https://github.com/sindresorhus/is-svg) for something that mostly works.
413
417
 
package/supported.js CHANGED
@@ -21,6 +21,7 @@ module.exports = {
21
21
  'icns',
22
22
  'jxr',
23
23
  'psd',
24
+ 'indd',
24
25
  'zip',
25
26
  'tar',
26
27
  'rar',
@@ -71,7 +72,7 @@ module.exports = {
71
72
  'rpm',
72
73
  'Z',
73
74
  'lz',
74
- 'msi',
75
+ 'cfb',
75
76
  'mxf',
76
77
  'mts',
77
78
  'blend',
@@ -132,7 +133,8 @@ module.exports = {
132
133
  'avif',
133
134
  'eps',
134
135
  'lzh',
135
- 'pgp'
136
+ 'pgp',
137
+ 'asar'
136
138
  ],
137
139
  mimeTypes: [
138
140
  'image/jpeg',
@@ -146,6 +148,7 @@ module.exports = {
146
148
  'image/bmp',
147
149
  'image/vnd.ms-photo',
148
150
  'image/vnd.adobe.photoshop',
151
+ 'application/x-indesign',
149
152
  'application/epub+zip',
150
153
  'application/x-xpinstall',
151
154
  'application/vnd.oasis.opendocument.text',
@@ -209,7 +212,7 @@ module.exports = {
209
212
  'application/x-rpm',
210
213
  'application/x-compress',
211
214
  'application/x-lzip',
212
- 'application/x-msi',
215
+ 'application/x-cfb',
213
216
  'application/x-mie',
214
217
  'application/mxf',
215
218
  'video/mp2t',
@@ -258,6 +261,7 @@ module.exports = {
258
261
  'application/vnd.sketchup.skp',
259
262
  'image/avif',
260
263
  'application/x-lzh-compressed',
261
- 'application/pgp-encrypted'
264
+ 'application/pgp-encrypted',
265
+ 'application/x-asar'
262
266
  ]
263
267
  };
package/util.js CHANGED
@@ -2,48 +2,32 @@
2
2
 
3
3
  exports.stringToBytes = string => [...string].map(character => character.charCodeAt(0));
4
4
 
5
- const uint8ArrayUtf8ByteString = (array, start, end) => {
6
- return String.fromCharCode(...array.slice(start, end));
7
- };
5
+ /**
6
+ Checks whether the TAR checksum is valid.
8
7
 
9
- exports.tarHeaderChecksumMatches = buffer => { // Does not check if checksum field characters are valid
10
- if (buffer.length < 512) { // `tar` header size, cannot compute checksum without it
8
+ @param {Buffer} buffer - The TAR header `[offset ... offset + 512]`.
9
+ @param {number} offset - TAR header offset.
10
+ @returns {boolean} `true` if the TAR checksum is valid, otherwise `false`.
11
+ */
12
+ exports.tarHeaderChecksumMatches = (buffer, offset = 0) => {
13
+ const readSum = parseInt(buffer.toString('utf8', 148, 154).replace(/\0.*$/, '').trim(), 8); // Read sum in header
14
+ if (isNaN(readSum)) {
11
15
  return false;
12
16
  }
13
17
 
14
- const MASK_8TH_BIT = 0x80;
15
-
16
- let sum = 256; // Intitalize sum, with 256 as sum of 8 spaces in checksum field
17
- let signedBitSum = 0; // Initialize signed bit sum
18
+ let sum = 8 * 0x20; // Initialize signed bit sum
18
19
 
19
- for (let i = 0; i < 148; i++) {
20
- const byte = buffer[i];
21
- sum += byte;
22
- signedBitSum += byte & MASK_8TH_BIT; // Add signed bit to signed bit sum
20
+ for (let i = offset; i < offset + 148; i++) {
21
+ sum += buffer[i];
23
22
  }
24
23
 
25
- // Skip checksum field
26
-
27
- for (let i = 156; i < 512; i++) {
28
- const byte = buffer[i];
29
- sum += byte;
30
- signedBitSum += byte & MASK_8TH_BIT; // Add signed bit to signed bit sum
24
+ for (let i = offset + 156; i < offset + 512; i++) {
25
+ sum += buffer[i];
31
26
  }
32
27
 
33
- const readSum = parseInt(uint8ArrayUtf8ByteString(buffer, 148, 154), 8); // Read sum in header
34
-
35
- // Some implementations compute checksum incorrectly using signed bytes
36
- return (
37
- // Checksum in header equals the sum we calculated
38
- readSum === sum ||
39
-
40
- // Checksum in header equals sum we calculated plus signed-to-unsigned delta
41
- readSum === (sum - (signedBitSum << 1))
42
- );
28
+ return readSum === sum;
43
29
  };
44
30
 
45
- exports.uint8ArrayUtf8ByteString = uint8ArrayUtf8ByteString;
46
-
47
31
  /**
48
32
  ID3 UINT32 sync-safe tokenizer token.
49
33
  28 bits (representing up to 256MB) integer, the msb is 0 to avoid "false syncsignals".