file-type 8.1.0 → 9.0.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.
Files changed (3) hide show
  1. package/index.js +59 -39
  2. package/package.json +1 -1
  3. package/readme.md +2 -1
package/index.js CHANGED
@@ -151,41 +151,54 @@ module.exports = input => {
151
151
  };
152
152
  }
153
153
 
154
- // https://github.com/file/file/blob/master/magic/Magdir/msooxml
155
- if (check(oxmlContentTypes, {offset: 30}) || check(oxmlRels, {offset: 30})) {
156
- const sliced = buf.subarray(4, 4 + 2000);
157
- const nextZipHeaderIndex = arr => arr.findIndex((el, i, arr) => arr[i] === 0x50 && arr[i + 1] === 0x4B && arr[i + 2] === 0x3 && arr[i + 3] === 0x4);
158
- const header2Pos = nextZipHeaderIndex(sliced);
159
-
160
- if (header2Pos !== -1) {
161
- const slicedAgain = buf.subarray(header2Pos + 8, header2Pos + 8 + 1000);
162
- const header3Pos = nextZipHeaderIndex(slicedAgain);
163
-
164
- if (header3Pos !== -1) {
165
- const offset = 8 + header2Pos + header3Pos + 30;
166
-
167
- if (checkString('word/', {offset})) {
168
- return {
169
- ext: 'docx',
170
- mime: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
171
- };
172
- }
173
-
174
- if (checkString('ppt/', {offset})) {
175
- return {
176
- ext: 'pptx',
177
- mime: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
178
- };
179
- }
180
-
181
- if (checkString('xl/', {offset})) {
182
- return {
183
- ext: 'xlsx',
184
- mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
185
- };
186
- }
154
+ // The docx, xlsx and pptx file types extend the Office Open XML file format:
155
+ // https://en.wikipedia.org/wiki/Office_Open_XML_file_formats
156
+ // We look for:
157
+ // - one entry named '[Content_Types].xml' or '_rels/.rels',
158
+ // - one entry indicating specific type of file.
159
+ // MS Office, OpenOffice and LibreOffice may put the parts in different order, so the check should not rely on it.
160
+ const findNextZipHeaderIndex = (arr, startAt = 0) => arr.findIndex((el, i, arr) => i >= startAt && arr[i] === 0x50 && arr[i + 1] === 0x4B && arr[i + 2] === 0x3 && arr[i + 3] === 0x4);
161
+
162
+ let zipHeaderIndex = 0; // The first zip header was already found at index 0
163
+ let oxmlFound = false;
164
+ let type = null;
165
+
166
+ do {
167
+ const offset = zipHeaderIndex + 30;
168
+
169
+ if (!oxmlFound) {
170
+ oxmlFound = (check(oxmlContentTypes, {offset}) || check(oxmlRels, {offset}));
171
+ }
172
+
173
+ if (!type) {
174
+ if (checkString('word/', {offset})) {
175
+ type = {
176
+ ext: 'docx',
177
+ mime: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
178
+ };
179
+ } else if (checkString('ppt/', {offset})) {
180
+ type = {
181
+ ext: 'pptx',
182
+ mime: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
183
+ };
184
+ } else if (checkString('xl/', {offset})) {
185
+ type = {
186
+ ext: 'xlsx',
187
+ mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
188
+ };
187
189
  }
188
190
  }
191
+
192
+ if (oxmlFound && type) {
193
+ return type;
194
+ }
195
+
196
+ zipHeaderIndex = findNextZipHeaderIndex(buf, offset);
197
+ } while (zipHeaderIndex >= 0);
198
+
199
+ // No more zip parts available in the buffer, but maybe we are almost certain about the type?
200
+ if (type) {
201
+ return type;
189
202
  }
190
203
  }
191
204
 
@@ -312,13 +325,13 @@ module.exports = input => {
312
325
  if (check([0x41, 0x56, 0x49], {offset: 8})) {
313
326
  return {
314
327
  ext: 'avi',
315
- mime: 'video/x-msvideo'
328
+ mime: 'video/vnd.avi'
316
329
  };
317
330
  }
318
331
  if (check([0x57, 0x41, 0x56, 0x45], {offset: 8})) {
319
332
  return {
320
333
  ext: 'wav',
321
- mime: 'audio/x-wav'
334
+ mime: 'audio/vnd.wave'
322
335
  };
323
336
  }
324
337
  // QLCM, QCP file
@@ -398,9 +411,9 @@ module.exports = input => {
398
411
  check([0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41], {offset: 4}) ||
399
412
  check([0x4D, 0x34, 0x41, 0x20])
400
413
  ) {
401
- return {
414
+ return { // MPEG-4 layer 3 (audio)
402
415
  ext: 'm4a',
403
- mime: 'audio/m4a'
416
+ mime: 'audio/mp4' // RFC 4337
404
417
  };
405
418
  }
406
419
 
@@ -468,13 +481,20 @@ module.exports = input => {
468
481
  };
469
482
  }
470
483
 
471
- if (check([0x4D, 0x41, 0x43, 0x20])) {
484
+ if (check([0x4D, 0x41, 0x43, 0x20])) { // 'MAC '
472
485
  return {
473
486
  ext: 'ape',
474
487
  mime: 'audio/ape'
475
488
  };
476
489
  }
477
490
 
491
+ if (check([0x77, 0x76, 0x70, 0x6B])) { // 'wvpk'
492
+ return {
493
+ ext: 'wv',
494
+ mime: 'audio/wavpack'
495
+ };
496
+ }
497
+
478
498
  if (check([0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A])) {
479
499
  return {
480
500
  ext: 'amr',
@@ -556,7 +576,7 @@ module.exports = input => {
556
576
  ) {
557
577
  return {
558
578
  ext: 'eot',
559
- mime: 'application/octet-stream'
579
+ mime: 'application/vnd.ms-fontobject'
560
580
  };
561
581
  }
562
582
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "file-type",
3
- "version": "8.1.0",
3
+ "version": "9.0.0",
4
4
  "description": "Detect the file type of a Buffer/Uint8Array",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/file-type",
package/readme.md CHANGED
@@ -76,7 +76,7 @@ Or `null` when no match.
76
76
 
77
77
  Type: `Buffer` `Uint8Array`
78
78
 
79
- It only needs the first 4100 bytes.
79
+ It only needs the first 4100 bytes. The exception is detection of `docx`, `pptx`, and `xlsx` which potentially requires reading the whole file.
80
80
 
81
81
 
82
82
  ## Supported file types
@@ -164,6 +164,7 @@ It only needs the first 4100 bytes.
164
164
  - [`cur`](https://en.wikipedia.org/wiki/ICO_(file_format))
165
165
  - [`ktx`](https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/)
166
166
  - [`ape`](https://en.wikipedia.org/wiki/Monkey%27s_Audio) - Monkey's Audio
167
+ - [`wv`](https://en.wikipedia.org/wiki/WavPack) - WavPack
167
168
 
168
169
  *SVG isn't included as it requires the whole file to be read, but you can get it [here](https://github.com/sindresorhus/is-svg).*
169
170