filetype.js 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168
  1. /*!
  2. * Library to detect file mime type of a Uint8Array.
  3. *
  4. * Modified from https://github.com/sindresorhus/file-type to be used standalone on browser based apps.
  5. *
  6. * This library requires Node "buffer" module as a pre-requisite. The "buffer" module is made available in this repo
  7. * for standalone use via the `buffer.js` script which needs to be loaded before this file on the page.
  8. *
  9. * Author: Kartik Visweswaran, Krajee.com
  10. */
  11. "use strict";
  12. // ES5 POLYFILL HELPERS FOR ES6
  13. function _typeof(obj) {
  14. "@babel/helpers - typeof";
  15. return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
  16. return typeof obj;
  17. } : function (obj) {
  18. return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  19. }, _typeof(obj);
  20. }
  21. function _toConsumableArray(arr) {
  22. return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  23. }
  24. function _nonIterableSpread() {
  25. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  26. }
  27. function _iterableToArray(iter) {
  28. if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
  29. }
  30. function _arrayWithoutHoles(arr) {
  31. if (Array.isArray(arr)) return _arrayLikeToArray(arr);
  32. }
  33. function _slicedToArray(arr, i) {
  34. return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  35. }
  36. function _nonIterableRest() {
  37. throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  38. }
  39. function _iterableToArrayLimit(arr, i) {
  40. var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
  41. if (_i == null) return;
  42. var _arr = [];
  43. var _n = true;
  44. var _d = false;
  45. var _s, _e;
  46. try {
  47. for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
  48. _arr.push(_s.value);
  49. if (i && _arr.length === i) break;
  50. }
  51. } catch (err) {
  52. _d = true;
  53. _e = err;
  54. } finally {
  55. try {
  56. if (!_n && _i["return"] != null) _i["return"]();
  57. } finally {
  58. if (_d) throw _e;
  59. }
  60. }
  61. return _arr;
  62. }
  63. function _arrayWithHoles(arr) {
  64. if (Array.isArray(arr)) return arr;
  65. }
  66. function _createForOfIteratorHelper(o, allowArrayLike) {
  67. var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
  68. if (!it) {
  69. if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
  70. if (it) o = it;
  71. var i = 0;
  72. var F = function F() {
  73. };
  74. return {
  75. s: F, n: function n() {
  76. if (i >= o.length) return {done: true};
  77. return {done: false, value: o[i++]};
  78. }, e: function e(_e2) {
  79. throw _e2;
  80. }, f: F
  81. };
  82. }
  83. throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  84. }
  85. var normalCompletion = true, didErr = false, err;
  86. return {
  87. s: function s() {
  88. it = it.call(o);
  89. }, n: function n() {
  90. var step = it.next();
  91. normalCompletion = step.done;
  92. return step;
  93. }, e: function e(_e3) {
  94. didErr = true;
  95. err = _e3;
  96. }, f: function f() {
  97. try {
  98. if (!normalCompletion && it.return != null) it.return();
  99. } finally {
  100. if (didErr) throw err;
  101. }
  102. }
  103. };
  104. }
  105. function _unsupportedIterableToArray(o, minLen) {
  106. if (!o) return;
  107. if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  108. var n = Object.prototype.toString.call(o).slice(8, -1);
  109. if (n === "Object" && o.constructor) n = o.constructor.name;
  110. if (n === "Map" || n === "Set") return Array.from(o);
  111. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  112. }
  113. function _arrayLikeToArray(arr, len) {
  114. if (len == null || len > arr.length) len = arr.length;
  115. for (var i = 0, arr2 = new Array(len); i < len; i++) {
  116. arr2[i] = arr[i];
  117. }
  118. return arr2;
  119. }
  120. function _instanceof(left, right) {
  121. if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
  122. return !!right[Symbol.hasInstance](left);
  123. } else {
  124. return left instanceof right;
  125. }
  126. }
  127. function _defineProperties(target, props) {
  128. for (var i = 0; i < props.length; i++) {
  129. var descriptor = props[i];
  130. descriptor.enumerable = descriptor.enumerable || false;
  131. descriptor.configurable = true;
  132. if ("value" in descriptor) descriptor.writable = true;
  133. Object.defineProperty(target, descriptor.key, descriptor);
  134. }
  135. }
  136. function _createClass(Constructor, protoProps, staticProps) {
  137. if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  138. if (staticProps) _defineProperties(Constructor, staticProps);
  139. Object.defineProperty(Constructor, "prototype", {writable: false});
  140. return Constructor;
  141. }
  142. function _classCallCheck(instance, Constructor) {
  143. if (!_instanceof(instance, Constructor)) {
  144. throw new TypeError("Cannot call a class as a function");
  145. }
  146. }
  147. function _inherits(subClass, superClass) {
  148. if (typeof superClass !== "function" && superClass !== null) {
  149. throw new TypeError("Super expression must either be null or a function");
  150. }
  151. subClass.prototype = Object.create(superClass && superClass.prototype, {
  152. constructor: {
  153. value: subClass,
  154. writable: true,
  155. configurable: true
  156. }
  157. });
  158. Object.defineProperty(subClass, "prototype", {writable: false});
  159. if (superClass) _setPrototypeOf(subClass, superClass);
  160. }
  161. function _createSuper(Derived) {
  162. var hasNativeReflectConstruct = _isNativeReflectConstruct();
  163. return function _createSuperInternal() {
  164. var Super = _getPrototypeOf(Derived), result;
  165. if (hasNativeReflectConstruct) {
  166. var NewTarget = _getPrototypeOf(this).constructor;
  167. result = Reflect.construct(Super, arguments, NewTarget);
  168. } else {
  169. result = Super.apply(this, arguments);
  170. }
  171. return _possibleConstructorReturn(this, result);
  172. };
  173. }
  174. function _possibleConstructorReturn(self, call) {
  175. if (call && (_typeof(call) === "object" || typeof call === "function")) {
  176. return call;
  177. } else if (call !== void 0) {
  178. throw new TypeError("Derived constructors may only return object or undefined");
  179. }
  180. return _assertThisInitialized(self);
  181. }
  182. function _assertThisInitialized(self) {
  183. if (self === void 0) {
  184. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  185. }
  186. return self;
  187. }
  188. function _wrapNativeSuper(Class) {
  189. var _cache = typeof Map === "function" ? new Map() : undefined;
  190. _wrapNativeSuper = function _wrapNativeSuper(Class) {
  191. if (Class === null || !_isNativeFunction(Class)) return Class;
  192. if (typeof Class !== "function") {
  193. throw new TypeError("Super expression must either be null or a function");
  194. }
  195. if (typeof _cache !== "undefined") {
  196. if (_cache.has(Class)) return _cache.get(Class);
  197. _cache.set(Class, Wrapper);
  198. }
  199. function Wrapper() {
  200. return _construct(Class, arguments, _getPrototypeOf(this).constructor);
  201. }
  202. Wrapper.prototype = Object.create(Class.prototype, {
  203. constructor: {
  204. value: Wrapper,
  205. enumerable: false,
  206. writable: true,
  207. configurable: true
  208. }
  209. });
  210. return _setPrototypeOf(Wrapper, Class);
  211. };
  212. return _wrapNativeSuper(Class);
  213. }
  214. function _construct(Parent, args, Class) {
  215. if (_isNativeReflectConstruct()) {
  216. _construct = Reflect.construct.bind();
  217. } else {
  218. _construct = function _construct(Parent, args, Class) {
  219. var a = [null];
  220. a.push.apply(a, args);
  221. var Constructor = Function.bind.apply(Parent, a);
  222. var instance = new Constructor();
  223. if (Class) _setPrototypeOf(instance, Class.prototype);
  224. return instance;
  225. };
  226. }
  227. return _construct.apply(null, arguments);
  228. }
  229. function _isNativeReflectConstruct() {
  230. if (typeof Reflect === "undefined" || !Reflect.construct) return false;
  231. if (Reflect.construct.sham) return false;
  232. if (typeof Proxy === "function") return true;
  233. try {
  234. Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {
  235. }));
  236. return true;
  237. } catch (e) {
  238. return false;
  239. }
  240. }
  241. function _isNativeFunction(fn) {
  242. return Function.toString.call(fn).indexOf("[native code]") !== -1;
  243. }
  244. function _setPrototypeOf(o, p) {
  245. _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
  246. o.__proto__ = p;
  247. return o;
  248. };
  249. return _setPrototypeOf(o, p);
  250. }
  251. function _getPrototypeOf(o) {
  252. _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
  253. return o.__proto__ || Object.getPrototypeOf(o);
  254. };
  255. return _getPrototypeOf(o);
  256. }
  257. // MAIN LIBRARY CODE
  258. var KrajeeFileTypeConfig = {
  259. minimumBytes: 4100,
  260. // A fair amount of file-types are detectable within this range,
  261. defaultMessages: 'End-Of-Stream',
  262. tarHeaderChecksumMatches: function tarHeaderChecksumMatches(buffer) {
  263. var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  264. var readSum = Number.parseInt(buffer.toString('utf8', 148, 154).replace(/\0.*$/, '').trim(), 8); // Read sum in header
  265. if (Number.isNaN(readSum)) {
  266. return false;
  267. }
  268. var sum = 8 * 0x20; // Initialize signed bit sum
  269. for (var i = offset; i < offset + 148; i++) {
  270. sum += buffer[i];
  271. }
  272. for (var _i = offset + 156; _i < offset + 512; _i++) {
  273. sum += buffer[_i];
  274. }
  275. return readSum === sum;
  276. },
  277. uint32SyncSafeToken: {
  278. get: function get(buffer, offset) {
  279. return buffer[offset + 3] & 0x7F | buffer[offset + 2] << 7 | buffer[offset + 1] << 14 | buffer[offset] << 21;
  280. },
  281. len: 4
  282. },
  283. dv: function dv(array) {
  284. return new DataView(array.buffer, array.byteOffset);
  285. },
  286. Token: {
  287. /**
  288. * 8-bit unsigned integer
  289. */
  290. UINT8: {
  291. len: 1,
  292. get: function get(array, offset) {
  293. return KrajeeFileTypeConfig.dv(array).getUint8(offset);
  294. },
  295. put: function put(array, offset, value) {
  296. KrajeeFileTypeConfig.dv(array).setUint8(offset, value);
  297. return offset + 1;
  298. }
  299. },
  300. /**
  301. * 16-bit unsigned integer, Little Endian byte order
  302. */
  303. UINT16_LE: {
  304. len: 2,
  305. get: function get(array, offset) {
  306. return KrajeeFileTypeConfig.dv(array).getUint16(offset, true);
  307. },
  308. put: function put(array, offset, value) {
  309. KrajeeFileTypeConfig.dv(array).setUint16(offset, value, true);
  310. return offset + 2;
  311. }
  312. },
  313. /**
  314. * 16-bit unsigned integer, Big Endian byte order
  315. */
  316. UINT16_BE: {
  317. len: 2,
  318. get: function get(array, offset) {
  319. return KrajeeFileTypeConfig.dv(array).getUint16(offset);
  320. },
  321. put: function put(array, offset, value) {
  322. KrajeeFileTypeConfig.dv(array).setUint16(offset, value);
  323. return offset + 2;
  324. }
  325. },
  326. /**
  327. * 32-bit unsigned integer, Big Endian byte order
  328. */
  329. INT32_BE: {
  330. len: 4,
  331. get: function get(array, offset) {
  332. return KrajeeFileTypeConfig.dv(array).getInt32(offset);
  333. },
  334. put: function put(array, offset, value) {
  335. KrajeeFileTypeConfig.dv(array).setInt32(offset, value);
  336. return offset + 4;
  337. }
  338. },
  339. /**
  340. * 32-bit unsigned integer, Little Endian byte order
  341. */
  342. UINT32_LE: {
  343. len: 4,
  344. get: function get(array, offset) {
  345. return KrajeeFileTypeConfig.dv(array).getUint32(offset, true);
  346. },
  347. put: function put(array, offset, value) {
  348. KrajeeFileTypeConfig.dv(array).setUint32(offset, value, true);
  349. return offset + 4;
  350. }
  351. },
  352. /**
  353. * 32-bit unsigned integer, Big Endian byte order
  354. */
  355. UINT32_BE: {
  356. len: 4,
  357. get: function get(array, offset) {
  358. return KrajeeFileTypeConfig.dv(array).getUint32(offset);
  359. },
  360. put: function put(array, offset, value) {
  361. KrajeeFileTypeConfig.dv(array).setUint32(offset, value);
  362. return offset + 4;
  363. }
  364. },
  365. /**
  366. * 64-bit unsigned integer, Little Endian byte order
  367. */
  368. UINT64_LE: {
  369. len: 8,
  370. get: function get(array, offset) {
  371. return KrajeeFileTypeConfig.dv(array).getBigUint64(offset, true);
  372. },
  373. put: function put(array, offset, value) {
  374. KrajeeFileTypeConfig.dv(array).setBigUint64(offset, value, true);
  375. return offset + 8;
  376. }
  377. },
  378. /**
  379. * 64-bit unsigned integer, Big Endian byte order
  380. */
  381. UINT64_BE: {
  382. len: 8,
  383. get: function get(array, offset) {
  384. return KrajeeFileTypeConfig.dv(array).getBigUint64(offset);
  385. },
  386. put: function put(array, offset, value) {
  387. KrajeeFileTypeConfig.dv(array).setBigUint64(offset, value);
  388. return offset + 8;
  389. }
  390. }
  391. }
  392. };
  393. var EndOfStreamError = /*#__PURE__*/function (_Error) {
  394. _inherits(EndOfStreamError, _Error);
  395. var _super = _createSuper(EndOfStreamError);
  396. function EndOfStreamError() {
  397. _classCallCheck(this, EndOfStreamError);
  398. return _super.call(this, KrajeeFileTypeConfig.defaultMessages);
  399. }
  400. return _createClass(EndOfStreamError);
  401. }( /*#__PURE__*/_wrapNativeSuper(Error));
  402. var StringType = /*#__PURE__*/function () {
  403. function StringType(len, encoding) {
  404. _classCallCheck(this, StringType);
  405. this.len = len;
  406. this.encoding = encoding;
  407. }
  408. _createClass(StringType, [{
  409. key: "get",
  410. value: function get(uint8Array, offset) {
  411. return Buffer.from(uint8Array).toString(this.encoding, offset, offset + this.len);
  412. }
  413. }]);
  414. return StringType;
  415. }();
  416. async function fileTypeFromTokenizer(tokenizer) {
  417. try {
  418. return new FileTypeParser().parse(tokenizer);
  419. } catch (error) {
  420. if (!_instanceof(error, EndOfStreamError)) {
  421. throw error;
  422. }
  423. }
  424. }
  425. var BufferTokenizer = /*#__PURE__*/function () {
  426. /**
  427. * Construct BufferTokenizer
  428. * @param uint8Array - Uint8Array to tokenize
  429. * @param fileInfo - Pass additional file information to the tokenizer
  430. */
  431. function BufferTokenizer(uint8Array, fileInfo) {
  432. _classCallCheck(this, BufferTokenizer);
  433. /**
  434. * Tokenizer-stream position
  435. */
  436. this.position = 0;
  437. this.numBuffer = new Uint8Array(8);
  438. this.fileInfo = fileInfo ? fileInfo : {};
  439. this.uint8Array = uint8Array;
  440. this.fileInfo.size = this.fileInfo.size ? this.fileInfo.size : uint8Array.length;
  441. }
  442. /**
  443. * Read a token from the tokenizer-stream
  444. * @param token - The token to read
  445. * @param position - If provided, the desired position in the tokenizer-stream
  446. * @returns Promise with token data
  447. */
  448. _createClass(BufferTokenizer, [{
  449. key: "readToken",
  450. value: async function readToken(token) {
  451. var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.position;
  452. var uint8Array = Buffer.alloc(token.len);
  453. var len = await this.readBuffer(uint8Array, {
  454. position: position
  455. });
  456. if (len < token.len) throw new EndOfStreamError();
  457. return token.get(uint8Array, 0);
  458. }
  459. /**
  460. * Peek a token from the tokenizer-stream.
  461. * @param token - Token to peek from the tokenizer-stream.
  462. * @param position - Offset where to begin reading within the file. If position is null, data will be read from the current file position.
  463. * @returns Promise with token data
  464. */
  465. }, {
  466. key: "peekToken",
  467. value: async function peekToken(token) {
  468. var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.position;
  469. var uint8Array = Buffer.alloc(token.len);
  470. var len = await this.peekBuffer(uint8Array, {
  471. position: position
  472. });
  473. if (len < token.len) throw new EndOfStreamError();
  474. return token.get(uint8Array, 0);
  475. }
  476. /**
  477. * Read buffer from tokenizer
  478. * @param uint8Array - Uint8Array to tokenize
  479. * @param options - Read behaviour options
  480. * @returns {Promise<number>}
  481. */
  482. }, {
  483. key: "readBuffer",
  484. value: async function readBuffer(uint8Array, options) {
  485. if (options && options.position) {
  486. if (options.position < this.position) {
  487. throw new Error('`options.position` must be equal or greater than `tokenizer.position`');
  488. }
  489. this.position = options.position;
  490. }
  491. var bytesRead = await this.peekBuffer(uint8Array, options);
  492. this.position += bytesRead;
  493. return bytesRead;
  494. }
  495. /**
  496. * Peek (read ahead) buffer from tokenizer
  497. * @param uint8Array
  498. * @param options - Read behaviour options
  499. * @returns {Promise<number>}
  500. */
  501. }, {
  502. key: "peekBuffer",
  503. value: async function peekBuffer(uint8Array, options) {
  504. var normOptions = this.normalizeOptions(uint8Array, options);
  505. var bytes2read = Math.min(this.uint8Array.length - normOptions.position, normOptions.length);
  506. if (!normOptions.mayBeLess && bytes2read < normOptions.length) {
  507. throw new EndOfStreamError();
  508. } else {
  509. uint8Array.set(this.uint8Array.subarray(normOptions.position, normOptions.position + bytes2read), normOptions.offset);
  510. return bytes2read;
  511. }
  512. }
  513. /**
  514. * Read a numeric token from the stream
  515. * @param token - Numeric token
  516. * @returns Promise with number
  517. */
  518. }, {
  519. key: "readNumber",
  520. value: async function readNumber(token) {
  521. var len = await this.readBuffer(this.numBuffer, {
  522. length: token.len
  523. });
  524. if (len < token.len) throw new EndOfStreamError();
  525. return token.get(this.numBuffer, 0);
  526. }
  527. /**
  528. * Read a numeric token from the stream
  529. * @param token - Numeric token
  530. * @returns Promise with number
  531. */
  532. }, {
  533. key: "peekNumber",
  534. value: async function peekNumber(token) {
  535. var len = await this.peekBuffer(this.numBuffer, {
  536. length: token.len
  537. });
  538. if (len < token.len) throw new EndOfStreamError();
  539. return token.get(this.numBuffer, 0);
  540. }
  541. }, {
  542. key: "close",
  543. value: async function close() {
  544. // empty
  545. }
  546. /**
  547. * Ignore number of bytes, advances the pointer in under tokenizer-stream.
  548. * @param length - Number of bytes to ignore
  549. * @return resolves the number of bytes ignored, equals length if this available, otherwise the number of bytes available
  550. */
  551. }, {
  552. key: "ignore",
  553. value: async function ignore(length) {
  554. if (this.fileInfo.size !== undefined) {
  555. var bytesLeft = this.fileInfo.size - this.position;
  556. if (length > bytesLeft) {
  557. this.position += bytesLeft;
  558. return bytesLeft;
  559. }
  560. }
  561. this.position += length;
  562. return length;
  563. }
  564. }, {
  565. key: "normalizeOptions",
  566. value: function normalizeOptions(uint8Array, options) {
  567. if (options && options.position !== undefined && options.position < this.position) {
  568. throw new Error('`options.position` must be equal or greater than `tokenizer.position`');
  569. }
  570. if (options) {
  571. return {
  572. mayBeLess: options.mayBeLess === true,
  573. offset: options.offset ? options.offset : 0,
  574. length: options.length ? options.length : uint8Array.length - (options.offset ? options.offset : 0),
  575. position: options.position ? options.position : this.position
  576. };
  577. }
  578. return {
  579. mayBeLess: false,
  580. offset: 0,
  581. length: uint8Array.length,
  582. position: this.position
  583. };
  584. }
  585. }]);
  586. return BufferTokenizer;
  587. }();
  588. var FileTypeParser = /*#__PURE__*/function () {
  589. function FileTypeParser() {
  590. _classCallCheck(this, FileTypeParser);
  591. }
  592. _createClass(FileTypeParser, [{
  593. key: "_check",
  594. value: function _check(buffer, headers, options) {
  595. options = {
  596. offset: 0,
  597. ...options
  598. };
  599. var _iterator = _createForOfIteratorHelper(headers.entries()),
  600. _step;
  601. try {
  602. for (_iterator.s(); !(_step = _iterator.n()).done;) {
  603. var _step$value = _slicedToArray(_step.value, 2),
  604. index = _step$value[0],
  605. header = _step$value[1];
  606. // If a bitmask is set
  607. if (options.mask) {
  608. // If header doesn't equal `buf` with bits masked off
  609. if (header !== (options.mask[index] & buffer[index + options.offset])) {
  610. return false;
  611. }
  612. } else if (header !== buffer[index + options.offset]) {
  613. return false;
  614. }
  615. }
  616. } catch (err) {
  617. _iterator.e(err);
  618. } finally {
  619. _iterator.f();
  620. }
  621. return true;
  622. }
  623. }, {
  624. key: "check",
  625. value: function check(header, options) {
  626. return this._check(this.buffer, header, options);
  627. }
  628. }, {
  629. key: "stringToBytes",
  630. value: function stringToBytes(string) {
  631. return _toConsumableArray(string).map(function (character) {
  632. return character.charCodeAt(0);
  633. });
  634. }
  635. }, {
  636. key: "checkString",
  637. value: function checkString(header, options) {
  638. return this.check(this.stringToBytes(header), options);
  639. }
  640. }, {
  641. key: "parse",
  642. value: async function parse(input) {
  643. if (!(_instanceof(input, Uint8Array) || _instanceof(input, ArrayBuffer) || _instanceof(input, BufferTokenizer))) {
  644. throw new TypeError("Expected the `input` argument to be of type `Uint8Array` or `Buffer` or `ArrayBuffer`, got `".concat(_typeof(input), "`"));
  645. }
  646. var tokenizer = input;
  647. if (!_instanceof(tokenizer, BufferTokenizer)) {
  648. var buffer = _instanceof(input, Uint8Array) ? input : new Uint8Array(input);
  649. if (!(buffer && buffer.length > 1)) {
  650. return;
  651. }
  652. tokenizer = new BufferTokenizer(buffer);
  653. }
  654. try {
  655. return this.parseTokenizer(tokenizer);
  656. } catch (error) {
  657. if (!_instanceof(error, EndOfStreamError)) {
  658. throw error;
  659. }
  660. }
  661. }
  662. }, {
  663. key: "parseTokenizer",
  664. value: async function parseTokenizer(tokenizer) {
  665. var Token = KrajeeFileTypeConfig.Token;
  666. this.buffer = Buffer.alloc(KrajeeFileTypeConfig.minimumBytes);
  667. // Keep reading until EOF if the file size is unknown.
  668. if (tokenizer.fileInfo.size === undefined) {
  669. tokenizer.fileInfo.size = Number.MAX_SAFE_INTEGER;
  670. }
  671. this.tokenizer = tokenizer;
  672. await tokenizer.peekBuffer(this.buffer, {
  673. length: 12,
  674. mayBeLess: true
  675. });
  676. // -- 2-byte signatures --
  677. if (this.check([0x42, 0x4D])) {
  678. return {
  679. ext: 'bmp',
  680. mime: 'image/bmp'
  681. };
  682. }
  683. if (this.check([0x0B, 0x77])) {
  684. return {
  685. ext: 'ac3',
  686. mime: 'audio/vnd.dolby.dd-raw'
  687. };
  688. }
  689. if (this.check([0x78, 0x01])) {
  690. return {
  691. ext: 'dmg',
  692. mime: 'application/x-apple-diskimage'
  693. };
  694. }
  695. if (this.check([0x4D, 0x5A])) {
  696. return {
  697. ext: 'exe',
  698. mime: 'application/x-msdownload'
  699. };
  700. }
  701. if (this.check([0x25, 0x21])) {
  702. await tokenizer.peekBuffer(this.buffer, {
  703. length: 24,
  704. mayBeLess: true
  705. });
  706. if (this.checkString('PS-Adobe-', {
  707. offset: 2
  708. }) && this.checkString(' EPSF-', {
  709. offset: 14
  710. })) {
  711. return {
  712. ext: 'eps',
  713. mime: 'application/eps'
  714. };
  715. }
  716. return {
  717. ext: 'ps',
  718. mime: 'application/postscript'
  719. };
  720. }
  721. if (this.check([0x1F, 0xA0]) || this.check([0x1F, 0x9D])) {
  722. return {
  723. ext: 'Z',
  724. mime: 'application/x-compress'
  725. };
  726. }
  727. // -- 3-byte signatures --
  728. if (this.check([0x47, 0x49, 0x46])) {
  729. return {
  730. ext: 'gif',
  731. mime: 'image/gif'
  732. };
  733. }
  734. if (this.check([0xFF, 0xD8, 0xFF])) {
  735. return {
  736. ext: 'jpg',
  737. mime: 'image/jpeg'
  738. };
  739. }
  740. if (this.check([0x49, 0x49, 0xBC])) {
  741. return {
  742. ext: 'jxr',
  743. mime: 'image/vnd.ms-photo'
  744. };
  745. }
  746. if (this.check([0x1F, 0x8B, 0x8])) {
  747. return {
  748. ext: 'gz',
  749. mime: 'application/gzip'
  750. };
  751. }
  752. if (this.check([0x42, 0x5A, 0x68])) {
  753. return {
  754. ext: 'bz2',
  755. mime: 'application/x-bzip2'
  756. };
  757. }
  758. if (this.checkString('ID3')) {
  759. await tokenizer.ignore(6); // Skip ID3 header until the header size
  760. var id3HeaderLength = await tokenizer.readToken(KrajeeFileTypeConfig.uint32SyncSafeToken);
  761. if (tokenizer.position + id3HeaderLength > tokenizer.fileInfo.size) {
  762. // Guess file type based on ID3 header for backward compatibility
  763. return {
  764. ext: 'mp3',
  765. mime: 'audio/mpeg'
  766. };
  767. }
  768. await tokenizer.ignore(id3HeaderLength);
  769. return fileTypeFromTokenizer(tokenizer); // Skip ID3 header, recursion
  770. }
  771. // Musepack, SV7
  772. if (this.checkString('MP+')) {
  773. return {
  774. ext: 'mpc',
  775. mime: 'audio/x-musepack'
  776. };
  777. }
  778. if ((this.buffer[0] === 0x43 || this.buffer[0] === 0x46) && this.check([0x57, 0x53], {
  779. offset: 1
  780. })) {
  781. return {
  782. ext: 'swf',
  783. mime: 'application/x-shockwave-flash'
  784. };
  785. }
  786. // -- 4-byte signatures --
  787. if (this.checkString('FLIF')) {
  788. return {
  789. ext: 'flif',
  790. mime: 'image/flif'
  791. };
  792. }
  793. if (this.checkString('8BPS')) {
  794. return {
  795. ext: 'psd',
  796. mime: 'image/vnd.adobe.photoshop'
  797. };
  798. }
  799. if (this.checkString('WEBP', {
  800. offset: 8
  801. })) {
  802. return {
  803. ext: 'webp',
  804. mime: 'image/webp'
  805. };
  806. }
  807. // Musepack, SV8
  808. if (this.checkString('MPCK')) {
  809. return {
  810. ext: 'mpc',
  811. mime: 'audio/x-musepack'
  812. };
  813. }
  814. if (this.checkString('FORM')) {
  815. return {
  816. ext: 'aif',
  817. mime: 'audio/aiff'
  818. };
  819. }
  820. if (this.checkString('icns', {
  821. offset: 0
  822. })) {
  823. return {
  824. ext: 'icns',
  825. mime: 'image/icns'
  826. };
  827. }
  828. // Zip-based file formats
  829. // Need to be before the `zip` check
  830. if (this.check([0x50, 0x4B, 0x3, 0x4])) {
  831. // Local file header signature
  832. try {
  833. while (tokenizer.position + 30 < tokenizer.fileInfo.size) {
  834. await tokenizer.readBuffer(this.buffer, {
  835. length: 30
  836. });
  837. // https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers
  838. var zipHeader = {
  839. compressedSize: this.buffer.readUInt32LE(18),
  840. uncompressedSize: this.buffer.readUInt32LE(22),
  841. filenameLength: this.buffer.readUInt16LE(26),
  842. extraFieldLength: this.buffer.readUInt16LE(28)
  843. };
  844. zipHeader.filename = await tokenizer.readToken(new StringType(zipHeader.filenameLength, 'utf-8'));
  845. await tokenizer.ignore(zipHeader.extraFieldLength);
  846. // Assumes signed `.xpi` from addons.mozilla.org
  847. if (zipHeader.filename === 'META-INF/mozilla.rsa') {
  848. return {
  849. ext: 'xpi',
  850. mime: 'application/x-xpinstall'
  851. };
  852. }
  853. if (zipHeader.filename.endsWith('.rels') || zipHeader.filename.endsWith('.xml')) {
  854. var type = zipHeader.filename.split('/')[0];
  855. switch (type) {
  856. case '_rels':
  857. break;
  858. case 'word':
  859. return {
  860. ext: 'docx',
  861. mime: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
  862. };
  863. case 'ppt':
  864. return {
  865. ext: 'pptx',
  866. mime: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
  867. };
  868. case 'xl':
  869. return {
  870. ext: 'xlsx',
  871. mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  872. };
  873. default:
  874. break;
  875. }
  876. }
  877. if (zipHeader.filename.startsWith('xl/')) {
  878. return {
  879. ext: 'xlsx',
  880. mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  881. };
  882. }
  883. if (zipHeader.filename.startsWith('3D/') && zipHeader.filename.endsWith('.model')) {
  884. return {
  885. ext: '3mf',
  886. mime: 'model/3mf'
  887. };
  888. }
  889. // The docx, xlsx and pptx file types extend the Office Open XML file format:
  890. // https://en.wikipedia.org/wiki/Office_Open_XML_file_formats
  891. // We look for:
  892. // - one entry named '[Content_Types].xml' or '_rels/.rels',
  893. // - one entry indicating specific type of file.
  894. // MS Office, OpenOffice and LibreOffice may put the parts in different order, so the check should not rely on it.
  895. if (zipHeader.filename === 'mimetype' && zipHeader.compressedSize === zipHeader.uncompressedSize) {
  896. var mimeType = (await tokenizer.readToken(new StringType(zipHeader.compressedSize, 'utf-8'))).trim();
  897. switch (mimeType) {
  898. case 'application/epub+zip':
  899. return {
  900. ext: 'epub',
  901. mime: 'application/epub+zip'
  902. };
  903. case 'application/vnd.oasis.opendocument.text':
  904. return {
  905. ext: 'odt',
  906. mime: 'application/vnd.oasis.opendocument.text'
  907. };
  908. case 'application/vnd.oasis.opendocument.spreadsheet':
  909. return {
  910. ext: 'ods',
  911. mime: 'application/vnd.oasis.opendocument.spreadsheet'
  912. };
  913. case 'application/vnd.oasis.opendocument.presentation':
  914. return {
  915. ext: 'odp',
  916. mime: 'application/vnd.oasis.opendocument.presentation'
  917. };
  918. default:
  919. }
  920. }
  921. // Try to find next header manually when current one is corrupted
  922. if (zipHeader.compressedSize === 0) {
  923. var nextHeaderIndex = -1;
  924. while (nextHeaderIndex < 0 && tokenizer.position < tokenizer.fileInfo.size) {
  925. await tokenizer.peekBuffer(this.buffer, {
  926. mayBeLess: true
  927. });
  928. nextHeaderIndex = this.buffer.indexOf('504B0304', 0, 'hex');
  929. // Move position to the next header if found, skip the whole buffer otherwise
  930. await tokenizer.ignore(nextHeaderIndex >= 0 ? nextHeaderIndex : this.buffer.length);
  931. }
  932. } else {
  933. await tokenizer.ignore(zipHeader.compressedSize);
  934. }
  935. }
  936. } catch (error) {
  937. if (!_instanceof(error, EndOfStreamError)) {
  938. throw error;
  939. }
  940. }
  941. return {
  942. ext: 'zip',
  943. mime: 'application/zip'
  944. };
  945. }
  946. if (this.checkString('OggS')) {
  947. // This is an OGG container
  948. await tokenizer.ignore(28);
  949. var _type = Buffer.alloc(8);
  950. await tokenizer.readBuffer(_type);
  951. // Needs to be before `ogg` check
  952. if (this._check(_type, [0x4F, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64])) {
  953. return {
  954. ext: 'opus',
  955. mime: 'audio/opus'
  956. };
  957. }
  958. // If ' theora' in header.
  959. if (this._check(_type, [0x80, 0x74, 0x68, 0x65, 0x6F, 0x72, 0x61])) {
  960. return {
  961. ext: 'ogv',
  962. mime: 'video/ogg'
  963. };
  964. }
  965. // If '\x01video' in header.
  966. if (this._check(_type, [0x01, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x00])) {
  967. return {
  968. ext: 'ogm',
  969. mime: 'video/ogg'
  970. };
  971. }
  972. // If ' FLAC' in header https://xiph.org/flac/faq.html
  973. if (this._check(_type, [0x7F, 0x46, 0x4C, 0x41, 0x43])) {
  974. return {
  975. ext: 'oga',
  976. mime: 'audio/ogg'
  977. };
  978. }
  979. // 'Speex ' in header https://en.wikipedia.org/wiki/Speex
  980. if (this._check(_type, [0x53, 0x70, 0x65, 0x65, 0x78, 0x20, 0x20])) {
  981. return {
  982. ext: 'spx',
  983. mime: 'audio/ogg'
  984. };
  985. }
  986. // If '\x01vorbis' in header
  987. if (this._check(_type, [0x01, 0x76, 0x6F, 0x72, 0x62, 0x69, 0x73])) {
  988. return {
  989. ext: 'ogg',
  990. mime: 'audio/ogg'
  991. };
  992. }
  993. // Default OGG container https://www.iana.org/assignments/media-types/application/ogg
  994. return {
  995. ext: 'ogx',
  996. mime: 'application/ogg'
  997. };
  998. }
  999. if (this.check([0x50, 0x4B]) && (this.buffer[2] === 0x3 || this.buffer[2] === 0x5 || this.buffer[2] === 0x7) && (this.buffer[3] === 0x4 || this.buffer[3] === 0x6 || this.buffer[3] === 0x8)) {
  1000. return {
  1001. ext: 'zip',
  1002. mime: 'application/zip'
  1003. };
  1004. }
  1005. //
  1006. // File Type Box (https://en.wikipedia.org/wiki/ISO_base_media_file_format)
  1007. // It's not required to be first, but it's recommended to be. Almost all ISO base media files start with `ftyp` box.
  1008. // `ftyp` box must contain a brand major identifier, which must consist of ISO 8859-1 printable characters.
  1009. // Here we check for 8859-1 printable characters (for simplicity, it's a mask which also catches one non-printable character).
  1010. if (this.checkString('ftyp', {
  1011. offset: 4
  1012. }) && (this.buffer[8] & 0x60) !== 0x00 // Brand major, first character ASCII?
  1013. ) {
  1014. // They all can have MIME `video/mp4` except `application/mp4` special-case which is hard to detect.
  1015. // For some cases, we're specific, everything else falls to `video/mp4` with `mp4` extension.
  1016. var brandMajor = this.buffer.toString('binary', 8, 12).replace('\0', ' ').trim();
  1017. switch (brandMajor) {
  1018. case 'avif':
  1019. case 'avis':
  1020. return {
  1021. ext: 'avif',
  1022. mime: 'image/avif'
  1023. };
  1024. case 'mif1':
  1025. return {
  1026. ext: 'heic',
  1027. mime: 'image/heif'
  1028. };
  1029. case 'msf1':
  1030. return {
  1031. ext: 'heic',
  1032. mime: 'image/heif-sequence'
  1033. };
  1034. case 'heic':
  1035. case 'heix':
  1036. return {
  1037. ext: 'heic',
  1038. mime: 'image/heic'
  1039. };
  1040. case 'hevc':
  1041. case 'hevx':
  1042. return {
  1043. ext: 'heic',
  1044. mime: 'image/heic-sequence'
  1045. };
  1046. case 'qt':
  1047. return {
  1048. ext: 'mov',
  1049. mime: 'video/quicktime'
  1050. };
  1051. case 'M4V':
  1052. case 'M4VH':
  1053. case 'M4VP':
  1054. return {
  1055. ext: 'm4v',
  1056. mime: 'video/x-m4v'
  1057. };
  1058. case 'M4P':
  1059. return {
  1060. ext: 'm4p',
  1061. mime: 'video/mp4'
  1062. };
  1063. case 'M4B':
  1064. return {
  1065. ext: 'm4b',
  1066. mime: 'audio/mp4'
  1067. };
  1068. case 'M4A':
  1069. return {
  1070. ext: 'm4a',
  1071. mime: 'audio/x-m4a'
  1072. };
  1073. case 'F4V':
  1074. return {
  1075. ext: 'f4v',
  1076. mime: 'video/mp4'
  1077. };
  1078. case 'F4P':
  1079. return {
  1080. ext: 'f4p',
  1081. mime: 'video/mp4'
  1082. };
  1083. case 'F4A':
  1084. return {
  1085. ext: 'f4a',
  1086. mime: 'audio/mp4'
  1087. };
  1088. case 'F4B':
  1089. return {
  1090. ext: 'f4b',
  1091. mime: 'audio/mp4'
  1092. };
  1093. case 'crx':
  1094. return {
  1095. ext: 'cr3',
  1096. mime: 'image/x-canon-cr3'
  1097. };
  1098. default:
  1099. if (brandMajor.startsWith('3g')) {
  1100. if (brandMajor.startsWith('3g2')) {
  1101. return {
  1102. ext: '3g2',
  1103. mime: 'video/3gpp2'
  1104. };
  1105. }
  1106. return {
  1107. ext: '3gp',
  1108. mime: 'video/3gpp'
  1109. };
  1110. }
  1111. return {
  1112. ext: 'mp4',
  1113. mime: 'video/mp4'
  1114. };
  1115. }
  1116. }
  1117. if (this.checkString('MThd')) {
  1118. return {
  1119. ext: 'mid',
  1120. mime: 'audio/midi'
  1121. };
  1122. }
  1123. if (this.checkString('wOFF') && (this.check([0x00, 0x01, 0x00, 0x00], {
  1124. offset: 4
  1125. }) || this.checkString('OTTO', {
  1126. offset: 4
  1127. }))) {
  1128. return {
  1129. ext: 'woff',
  1130. mime: 'font/woff'
  1131. };
  1132. }
  1133. if (this.checkString('wOF2') && (this.check([0x00, 0x01, 0x00, 0x00], {
  1134. offset: 4
  1135. }) || this.checkString('OTTO', {
  1136. offset: 4
  1137. }))) {
  1138. return {
  1139. ext: 'woff2',
  1140. mime: 'font/woff2'
  1141. };
  1142. }
  1143. if (this.check([0xD4, 0xC3, 0xB2, 0xA1]) || this.check([0xA1, 0xB2, 0xC3, 0xD4])) {
  1144. return {
  1145. ext: 'pcap',
  1146. mime: 'application/vnd.tcpdump.pcap'
  1147. };
  1148. }
  1149. // Sony DSD Stream File (DSF)
  1150. if (this.checkString('DSD ')) {
  1151. return {
  1152. ext: 'dsf',
  1153. mime: 'audio/x-dsf' // Non-standard
  1154. };
  1155. }
  1156. if (this.checkString('LZIP')) {
  1157. return {
  1158. ext: 'lz',
  1159. mime: 'application/x-lzip'
  1160. };
  1161. }
  1162. if (this.checkString('fLaC')) {
  1163. return {
  1164. ext: 'flac',
  1165. mime: 'audio/x-flac'
  1166. };
  1167. }
  1168. if (this.check([0x42, 0x50, 0x47, 0xFB])) {
  1169. return {
  1170. ext: 'bpg',
  1171. mime: 'image/bpg'
  1172. };
  1173. }
  1174. if (this.checkString('wvpk')) {
  1175. return {
  1176. ext: 'wv',
  1177. mime: 'audio/wavpack'
  1178. };
  1179. }
  1180. if (this.checkString('%PDF')) {
  1181. await tokenizer.ignore(1350);
  1182. var maxBufferSize = 10 * 1024 * 1024;
  1183. var buffer = Buffer.alloc(Math.min(maxBufferSize, tokenizer.fileInfo.size));
  1184. await tokenizer.readBuffer(buffer, {
  1185. mayBeLess: true
  1186. });
  1187. // Check if this is an Adobe Illustrator file
  1188. if (buffer.includes(Buffer.from('AIPrivateData'))) {
  1189. return {
  1190. ext: 'ai',
  1191. mime: 'application/postscript'
  1192. };
  1193. }
  1194. // Assume this is just a normal PDF
  1195. return {
  1196. ext: 'pdf',
  1197. mime: 'application/pdf'
  1198. };
  1199. }
  1200. if (this.check([0x00, 0x61, 0x73, 0x6D])) {
  1201. return {
  1202. ext: 'wasm',
  1203. mime: 'application/wasm'
  1204. };
  1205. }
  1206. // TIFF, little-endian type
  1207. if (this.check([0x49, 0x49])) {
  1208. var fileType = await this.readTiffHeader(false);
  1209. if (fileType) {
  1210. return fileType;
  1211. }
  1212. }
  1213. // TIFF, big-endian type
  1214. if (this.check([0x4D, 0x4D])) {
  1215. var _fileType = await this.readTiffHeader(true);
  1216. if (_fileType) {
  1217. return _fileType;
  1218. }
  1219. }
  1220. if (this.checkString('MAC ')) {
  1221. return {
  1222. ext: 'ape',
  1223. mime: 'audio/ape'
  1224. };
  1225. }
  1226. // https://github.com/threatstack/libmagic/blob/master/magic/Magdir/matroska
  1227. if (this.check([0x1A, 0x45, 0xDF, 0xA3])) {
  1228. // Root element: EBML
  1229. var readField = async function readField() {
  1230. var msb = await tokenizer.peekNumber(Token.UINT8);
  1231. var mask = 0x80;
  1232. var ic = 0; // 0 = A, 1 = B, 2 = C, 3
  1233. // = D
  1234. while ((msb & mask) === 0) {
  1235. ++ic;
  1236. mask >>= 1;
  1237. }
  1238. var id = Buffer.alloc(ic + 1);
  1239. await tokenizer.readBuffer(id);
  1240. return id;
  1241. };
  1242. var readElement = async function readElement() {
  1243. var id = await readField();
  1244. var lengthField = await readField();
  1245. lengthField[0] ^= 0x80 >> lengthField.length - 1;
  1246. var nrLength = Math.min(6, lengthField.length); // JavaScript can max read 6 bytes integer
  1247. return {
  1248. id: id.readUIntBE(0, id.length),
  1249. len: lengthField.readUIntBE(lengthField.length - nrLength, nrLength)
  1250. };
  1251. };
  1252. var readChildren = async function readChildren(level, children) {
  1253. while (children > 0) {
  1254. var element = await readElement();
  1255. if (element.id === 0x42_82) {
  1256. var rawValue = await tokenizer.readToken(new StringType(element.len, 'utf-8'));
  1257. return rawValue.replace(/\00.*$/g, ''); // Return DocType
  1258. }
  1259. await tokenizer.ignore(element.len); // ignore payload
  1260. --children;
  1261. }
  1262. };
  1263. var re = await readElement();
  1264. var docType = await readChildren(1, re.len);
  1265. switch (docType) {
  1266. case 'webm':
  1267. return {
  1268. ext: 'webm',
  1269. mime: 'video/webm'
  1270. };
  1271. case 'matroska':
  1272. return {
  1273. ext: 'mkv',
  1274. mime: 'video/x-matroska'
  1275. };
  1276. default:
  1277. return;
  1278. }
  1279. }
  1280. // RIFF file format which might be AVI, WAV, QCP, etc
  1281. if (this.check([0x52, 0x49, 0x46, 0x46])) {
  1282. if (this.check([0x41, 0x56, 0x49], {
  1283. offset: 8
  1284. })) {
  1285. return {
  1286. ext: 'avi',
  1287. mime: 'video/vnd.avi'
  1288. };
  1289. }
  1290. if (this.check([0x57, 0x41, 0x56, 0x45], {
  1291. offset: 8
  1292. })) {
  1293. return {
  1294. ext: 'wav',
  1295. mime: 'audio/vnd.wave'
  1296. };
  1297. }
  1298. // QLCM, QCP file
  1299. if (this.check([0x51, 0x4C, 0x43, 0x4D], {
  1300. offset: 8
  1301. })) {
  1302. return {
  1303. ext: 'qcp',
  1304. mime: 'audio/qcelp'
  1305. };
  1306. }
  1307. }
  1308. if (this.checkString('SQLi')) {
  1309. return {
  1310. ext: 'sqlite',
  1311. mime: 'application/x-sqlite3'
  1312. };
  1313. }
  1314. if (this.check([0x4E, 0x45, 0x53, 0x1A])) {
  1315. return {
  1316. ext: 'nes',
  1317. mime: 'application/x-nintendo-nes-rom'
  1318. };
  1319. }
  1320. if (this.checkString('Cr24')) {
  1321. return {
  1322. ext: 'crx',
  1323. mime: 'application/x-google-chrome-extension'
  1324. };
  1325. }
  1326. if (this.checkString('MSCF') || this.checkString('ISc(')) {
  1327. return {
  1328. ext: 'cab',
  1329. mime: 'application/vnd.ms-cab-compressed'
  1330. };
  1331. }
  1332. if (this.check([0xED, 0xAB, 0xEE, 0xDB])) {
  1333. return {
  1334. ext: 'rpm',
  1335. mime: 'application/x-rpm'
  1336. };
  1337. }
  1338. if (this.check([0xC5, 0xD0, 0xD3, 0xC6])) {
  1339. return {
  1340. ext: 'eps',
  1341. mime: 'application/eps'
  1342. };
  1343. }
  1344. if (this.check([0x28, 0xB5, 0x2F, 0xFD])) {
  1345. return {
  1346. ext: 'zst',
  1347. mime: 'application/zstd'
  1348. };
  1349. }
  1350. if (this.check([0x7F, 0x45, 0x4C, 0x46])) {
  1351. return {
  1352. ext: 'elf',
  1353. mime: 'application/x-elf'
  1354. };
  1355. }
  1356. // -- 5-byte signatures --
  1357. if (this.check([0x4F, 0x54, 0x54, 0x4F, 0x00])) {
  1358. return {
  1359. ext: 'otf',
  1360. mime: 'font/otf'
  1361. };
  1362. }
  1363. if (this.checkString('#!AMR')) {
  1364. return {
  1365. ext: 'amr',
  1366. mime: 'audio/amr'
  1367. };
  1368. }
  1369. if (this.checkString('{\\rtf')) {
  1370. return {
  1371. ext: 'rtf',
  1372. mime: 'application/rtf'
  1373. };
  1374. }
  1375. if (this.check([0x46, 0x4C, 0x56, 0x01])) {
  1376. return {
  1377. ext: 'flv',
  1378. mime: 'video/x-flv'
  1379. };
  1380. }
  1381. if (this.checkString('IMPM')) {
  1382. return {
  1383. ext: 'it',
  1384. mime: 'audio/x-it'
  1385. };
  1386. }
  1387. if (this.checkString('-lh0-', {
  1388. offset: 2
  1389. }) || this.checkString('-lh1-', {
  1390. offset: 2
  1391. }) || this.checkString('-lh2-', {
  1392. offset: 2
  1393. }) || this.checkString('-lh3-', {
  1394. offset: 2
  1395. }) || this.checkString('-lh4-', {
  1396. offset: 2
  1397. }) || this.checkString('-lh5-', {
  1398. offset: 2
  1399. }) || this.checkString('-lh6-', {
  1400. offset: 2
  1401. }) || this.checkString('-lh7-', {
  1402. offset: 2
  1403. }) || this.checkString('-lzs-', {
  1404. offset: 2
  1405. }) || this.checkString('-lz4-', {
  1406. offset: 2
  1407. }) || this.checkString('-lz5-', {
  1408. offset: 2
  1409. }) || this.checkString('-lhd-', {
  1410. offset: 2
  1411. })) {
  1412. return {
  1413. ext: 'lzh',
  1414. mime: 'application/x-lzh-compressed'
  1415. };
  1416. }
  1417. // MPEG program stream (PS or MPEG-PS)
  1418. if (this.check([0x00, 0x00, 0x01, 0xBA])) {
  1419. // MPEG-PS, MPEG-1 Part 1
  1420. if (this.check([0x21], {
  1421. offset: 4,
  1422. mask: [0xF1]
  1423. })) {
  1424. return {
  1425. ext: 'mpg',
  1426. // May also be .ps, .mpeg
  1427. mime: 'video/MP1S'
  1428. };
  1429. }
  1430. // MPEG-PS, MPEG-2 Part 1
  1431. if (this.check([0x44], {
  1432. offset: 4,
  1433. mask: [0xC4]
  1434. })) {
  1435. return {
  1436. ext: 'mpg',
  1437. // May also be .mpg, .m2p, .vob or .sub
  1438. mime: 'video/MP2P'
  1439. };
  1440. }
  1441. }
  1442. if (this.checkString('ITSF')) {
  1443. return {
  1444. ext: 'chm',
  1445. mime: 'application/vnd.ms-htmlhelp'
  1446. };
  1447. }
  1448. // -- 6-byte signatures --
  1449. if (this.check([0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00])) {
  1450. return {
  1451. ext: 'xz',
  1452. mime: 'application/x-xz'
  1453. };
  1454. }
  1455. if (this.checkString('<?xml ')) {
  1456. return {
  1457. ext: 'xml',
  1458. mime: 'application/xml'
  1459. };
  1460. }
  1461. if (this.check([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C])) {
  1462. return {
  1463. ext: '7z',
  1464. mime: 'application/x-7z-compressed'
  1465. };
  1466. }
  1467. if (this.check([0x52, 0x61, 0x72, 0x21, 0x1A, 0x7]) && (this.buffer[6] === 0x0 || this.buffer[6] === 0x1)) {
  1468. return {
  1469. ext: 'rar',
  1470. mime: 'application/x-rar-compressed'
  1471. };
  1472. }
  1473. if (this.checkString('solid ')) {
  1474. return {
  1475. ext: 'stl',
  1476. mime: 'model/stl'
  1477. };
  1478. }
  1479. // -- 7-byte signatures --
  1480. if (this.checkString('BLENDER')) {
  1481. return {
  1482. ext: 'blend',
  1483. mime: 'application/x-blender'
  1484. };
  1485. }
  1486. if (this.checkString('!<arch>')) {
  1487. await tokenizer.ignore(8);
  1488. var string = await tokenizer.readToken(new StringType(13, 'ascii'));
  1489. if (string === 'debian-binary') {
  1490. return {
  1491. ext: 'deb',
  1492. mime: 'application/x-deb'
  1493. };
  1494. }
  1495. return {
  1496. ext: 'ar',
  1497. mime: 'application/x-unix-archive'
  1498. };
  1499. }
  1500. // -- 8-byte signatures --
  1501. if (this.check([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) {
  1502. // ignore PNG signature
  1503. var readChunkHeader = async function readChunkHeader() {
  1504. return {
  1505. length: await tokenizer.readToken(Token.INT32_BE),
  1506. type: await tokenizer.readToken(new StringType(4, 'binary'))
  1507. };
  1508. };
  1509. // APNG format (https://wiki.mozilla.org/APNG_Specification)
  1510. // 1. Find the first IDAT (image data) chunk (49 44 41 54)
  1511. // 2. Check if there is an "acTL" chunk before the IDAT one (61 63 54 4C)
  1512. // Offset calculated as follows:
  1513. // - 8 bytes: PNG signature
  1514. // - 4 (length) + 4 (chunk type) + 13 (chunk data) + 4 (CRC): IHDR chunk
  1515. await tokenizer.ignore(8);
  1516. do {
  1517. var chunk = await readChunkHeader();
  1518. if (chunk.length < 0) {
  1519. return; // Invalid chunk length
  1520. }
  1521. switch (chunk.type) {
  1522. case 'IDAT':
  1523. return {
  1524. ext: 'png',
  1525. mime: 'image/png'
  1526. };
  1527. case 'acTL':
  1528. return {
  1529. ext: 'apng',
  1530. mime: 'image/apng'
  1531. };
  1532. default:
  1533. await tokenizer.ignore(chunk.length + 4);
  1534. // Ignore chunk-data + CRC
  1535. }
  1536. } while (tokenizer.position + 8 < tokenizer.fileInfo.size);
  1537. return {
  1538. ext: 'png',
  1539. mime: 'image/png'
  1540. };
  1541. }
  1542. if (this.check([0x41, 0x52, 0x52, 0x4F, 0x57, 0x31, 0x00, 0x00])) {
  1543. return {
  1544. ext: 'arrow',
  1545. mime: 'application/x-apache-arrow'
  1546. };
  1547. }
  1548. if (this.check([0x67, 0x6C, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00])) {
  1549. return {
  1550. ext: 'glb',
  1551. mime: 'model/gltf-binary'
  1552. };
  1553. }
  1554. // `mov` format variants
  1555. if (this.check([0x66, 0x72, 0x65, 0x65], {
  1556. offset: 4
  1557. }) // `free`
  1558. || this.check([0x6D, 0x64, 0x61, 0x74], {
  1559. offset: 4
  1560. }) // `mdat` MJPEG
  1561. || this.check([0x6D, 0x6F, 0x6F, 0x76], {
  1562. offset: 4
  1563. }) // `moov`
  1564. || this.check([0x77, 0x69, 0x64, 0x65], {
  1565. offset: 4
  1566. }) // `wide`
  1567. ) {
  1568. return {
  1569. ext: 'mov',
  1570. mime: 'video/quicktime'
  1571. };
  1572. }
  1573. if (this.check([0xEF, 0xBB, 0xBF]) && this.checkString('<?xml', {
  1574. offset: 3
  1575. })) {
  1576. // UTF-8-BOM
  1577. return {
  1578. ext: 'xml',
  1579. mime: 'application/xml'
  1580. };
  1581. }
  1582. // -- 9-byte signatures --
  1583. if (this.check([0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00, 0x18])) {
  1584. return {
  1585. ext: 'orf',
  1586. mime: 'image/x-olympus-orf'
  1587. };
  1588. }
  1589. if (this.checkString('gimp xcf ')) {
  1590. return {
  1591. ext: 'xcf',
  1592. mime: 'image/x-xcf'
  1593. };
  1594. }
  1595. // -- 12-byte signatures --
  1596. if (this.check([0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8])) {
  1597. return {
  1598. ext: 'rw2',
  1599. mime: 'image/x-panasonic-rw2'
  1600. };
  1601. }
  1602. // ASF_Header_Object first 80 bytes
  1603. if (this.check([0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9])) {
  1604. var readHeader = async function readHeader() {
  1605. var guid = Buffer.alloc(16);
  1606. await tokenizer.readBuffer(guid);
  1607. return {
  1608. id: guid,
  1609. size: Number(await tokenizer.readToken(Token.UINT64_LE))
  1610. };
  1611. };
  1612. await tokenizer.ignore(30);
  1613. // Search for header should be in first 1KB of file.
  1614. while (tokenizer.position + 24 < tokenizer.fileInfo.size) {
  1615. var header = await readHeader();
  1616. var payload = header.size - 24;
  1617. if (this._check(header.id, [0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65])) {
  1618. // Sync on Stream-Properties-Object (B7DC0791-A9B7-11CF-8EE6-00C00C205365)
  1619. var typeId = Buffer.alloc(16);
  1620. payload -= await tokenizer.readBuffer(typeId);
  1621. if (this._check(typeId, [0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B])) {
  1622. // Found audio:
  1623. return {
  1624. ext: 'asf',
  1625. mime: 'audio/x-ms-asf'
  1626. };
  1627. }
  1628. if (this._check(typeId, [0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B])) {
  1629. // Found video:
  1630. return {
  1631. ext: 'asf',
  1632. mime: 'video/x-ms-asf'
  1633. };
  1634. }
  1635. break;
  1636. }
  1637. await tokenizer.ignore(payload);
  1638. }
  1639. // Default to ASF generic extension
  1640. return {
  1641. ext: 'asf',
  1642. mime: 'application/vnd.ms-asf'
  1643. };
  1644. }
  1645. if (this.check([0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A])) {
  1646. return {
  1647. ext: 'ktx',
  1648. mime: 'image/ktx'
  1649. };
  1650. }
  1651. if ((this.check([0x7E, 0x10, 0x04]) || this.check([0x7E, 0x18, 0x04])) && this.check([0x30, 0x4D, 0x49, 0x45], {
  1652. offset: 4
  1653. })) {
  1654. return {
  1655. ext: 'mie',
  1656. mime: 'application/x-mie'
  1657. };
  1658. }
  1659. if (this.check([0x27, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], {
  1660. offset: 2
  1661. })) {
  1662. return {
  1663. ext: 'shp',
  1664. mime: 'application/x-esri-shape'
  1665. };
  1666. }
  1667. if (this.check([0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A])) {
  1668. // JPEG-2000 family
  1669. await tokenizer.ignore(20);
  1670. var _type2 = await tokenizer.readToken(new StringType(4, 'ascii'));
  1671. switch (_type2) {
  1672. case 'jp2 ':
  1673. return {
  1674. ext: 'jp2',
  1675. mime: 'image/jp2'
  1676. };
  1677. case 'jpx ':
  1678. return {
  1679. ext: 'jpx',
  1680. mime: 'image/jpx'
  1681. };
  1682. case 'jpm ':
  1683. return {
  1684. ext: 'jpm',
  1685. mime: 'image/jpm'
  1686. };
  1687. case 'mjp2':
  1688. return {
  1689. ext: 'mj2',
  1690. mime: 'image/mj2'
  1691. };
  1692. default:
  1693. return;
  1694. }
  1695. }
  1696. if (this.check([0xFF, 0x0A]) || this.check([0x00, 0x00, 0x00, 0x0C, 0x4A, 0x58, 0x4C, 0x20, 0x0D, 0x0A, 0x87, 0x0A])) {
  1697. return {
  1698. ext: 'jxl',
  1699. mime: 'image/jxl'
  1700. };
  1701. }
  1702. if (this.check([0xFE, 0xFF, 0, 60, 0, 63, 0, 120, 0, 109, 0, 108]) // UTF-16-BOM-LE
  1703. || this.check([0xFF, 0xFE, 60, 0, 63, 0, 120, 0, 109, 0, 108, 0]) // UTF-16-BOM-LE
  1704. ) {
  1705. return {
  1706. ext: 'xml',
  1707. mime: 'application/xml'
  1708. };
  1709. }
  1710. // -- Unsafe signatures --
  1711. if (this.check([0x0, 0x0, 0x1, 0xBA]) || this.check([0x0, 0x0, 0x1, 0xB3])) {
  1712. return {
  1713. ext: 'mpg',
  1714. mime: 'video/mpeg'
  1715. };
  1716. }
  1717. if (this.check([0x00, 0x01, 0x00, 0x00, 0x00])) {
  1718. return {
  1719. ext: 'ttf',
  1720. mime: 'font/ttf'
  1721. };
  1722. }
  1723. if (this.check([0x00, 0x00, 0x01, 0x00])) {
  1724. return {
  1725. ext: 'ico',
  1726. mime: 'image/x-icon'
  1727. };
  1728. }
  1729. if (this.check([0x00, 0x00, 0x02, 0x00])) {
  1730. return {
  1731. ext: 'cur',
  1732. mime: 'image/x-icon'
  1733. };
  1734. }
  1735. if (this.check([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1])) {
  1736. // Detected Microsoft Compound File Binary File (MS-CFB) Format.
  1737. return {
  1738. ext: 'cfb',
  1739. mime: 'application/x-cfb'
  1740. };
  1741. }
  1742. // Increase sample size from 12 to 256.
  1743. await tokenizer.peekBuffer(this.buffer, {
  1744. length: Math.min(256, tokenizer.fileInfo.size),
  1745. mayBeLess: true
  1746. });
  1747. // -- 15-byte signatures --
  1748. if (this.checkString('BEGIN:')) {
  1749. if (this.checkString('VCARD', {
  1750. offset: 6
  1751. })) {
  1752. return {
  1753. ext: 'vcf',
  1754. mime: 'text/vcard'
  1755. };
  1756. }
  1757. if (this.checkString('VCALENDAR', {
  1758. offset: 6
  1759. })) {
  1760. return {
  1761. ext: 'ics',
  1762. mime: 'text/calendar'
  1763. };
  1764. }
  1765. }
  1766. // `raf` is here just to keep all the raw image detectors together.
  1767. if (this.checkString('FUJIFILMCCD-RAW')) {
  1768. return {
  1769. ext: 'raf',
  1770. mime: 'image/x-fujifilm-raf'
  1771. };
  1772. }
  1773. if (this.checkString('Extended Module:')) {
  1774. return {
  1775. ext: 'xm',
  1776. mime: 'audio/x-xm'
  1777. };
  1778. }
  1779. if (this.checkString('Creative Voice File')) {
  1780. return {
  1781. ext: 'voc',
  1782. mime: 'audio/x-voc'
  1783. };
  1784. }
  1785. if (this.check([0x04, 0x00, 0x00, 0x00]) && this.buffer.length >= 16) {
  1786. // Rough & quick check Pickle/ASAR
  1787. var jsonSize = this.buffer.readUInt32LE(12);
  1788. if (jsonSize > 12 && this.buffer.length >= jsonSize + 16) {
  1789. try {
  1790. var _header = this.buffer.slice(16, jsonSize + 16).toString();
  1791. var json = JSON.parse(_header);
  1792. // Check if Pickle is ASAR
  1793. if (json.files) {
  1794. // Final check, assuring Pickle/ASAR format
  1795. return {
  1796. ext: 'asar',
  1797. mime: 'application/x-asar'
  1798. };
  1799. }
  1800. } catch (err) {
  1801. console.log(err);
  1802. }
  1803. }
  1804. }
  1805. if (this.check([0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02])) {
  1806. return {
  1807. ext: 'mxf',
  1808. mime: 'application/mxf'
  1809. };
  1810. }
  1811. if (this.checkString('SCRM', {
  1812. offset: 44
  1813. })) {
  1814. return {
  1815. ext: 's3m',
  1816. mime: 'audio/x-s3m'
  1817. };
  1818. }
  1819. // Raw MPEG-2 transport stream (188-byte packets)
  1820. if (this.check([0x47]) && this.check([0x47], {
  1821. offset: 188
  1822. })) {
  1823. return {
  1824. ext: 'mts',
  1825. mime: 'video/mp2t'
  1826. };
  1827. }
  1828. // Blu-ray Disc Audio-Video (BDAV) MPEG-2 transport stream has 4-byte TP_extra_header before each 188-byte packet
  1829. if (this.check([0x47], {
  1830. offset: 4
  1831. }) && this.check([0x47], {
  1832. offset: 196
  1833. })) {
  1834. return {
  1835. ext: 'mts',
  1836. mime: 'video/mp2t'
  1837. };
  1838. }
  1839. if (this.check([0x42, 0x4F, 0x4F, 0x4B, 0x4D, 0x4F, 0x42, 0x49], {
  1840. offset: 60
  1841. })) {
  1842. return {
  1843. ext: 'mobi',
  1844. mime: 'application/x-mobipocket-ebook'
  1845. };
  1846. }
  1847. if (this.check([0x44, 0x49, 0x43, 0x4D], {
  1848. offset: 128
  1849. })) {
  1850. return {
  1851. ext: 'dcm',
  1852. mime: 'application/dicom'
  1853. };
  1854. }
  1855. if (this.check([0x4C, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46])) {
  1856. return {
  1857. ext: 'lnk',
  1858. mime: 'application/x.ms.shortcut' // Invented by us
  1859. };
  1860. }
  1861. if (this.check([0x62, 0x6F, 0x6F, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x00])) {
  1862. return {
  1863. ext: 'alias',
  1864. mime: 'application/x.apple.alias' // Invented by us
  1865. };
  1866. }
  1867. if (this.check([0x4C, 0x50], {
  1868. offset: 34
  1869. }) && (this.check([0x00, 0x00, 0x01], {
  1870. offset: 8
  1871. }) || this.check([0x01, 0x00, 0x02], {
  1872. offset: 8
  1873. }) || this.check([0x02, 0x00, 0x02], {
  1874. offset: 8
  1875. }))) {
  1876. return {
  1877. ext: 'eot',
  1878. mime: 'application/vnd.ms-fontobject'
  1879. };
  1880. }
  1881. if (this.check([0x06, 0x06, 0xED, 0xF5, 0xD8, 0x1D, 0x46, 0xE5, 0xBD, 0x31, 0xEF, 0xE7, 0xFE, 0x74, 0xB7, 0x1D])) {
  1882. return {
  1883. ext: 'indd',
  1884. mime: 'application/x-indesign'
  1885. };
  1886. }
  1887. // Increase sample size from 256 to 512
  1888. await tokenizer.peekBuffer(this.buffer, {
  1889. length: Math.min(512, tokenizer.fileInfo.size),
  1890. mayBeLess: true
  1891. });
  1892. // Requires a buffer size of 512 bytes
  1893. if (KrajeeFileTypeConfig.tarHeaderChecksumMatches(this.buffer)) {
  1894. return {
  1895. ext: 'tar',
  1896. mime: 'application/x-tar'
  1897. };
  1898. }
  1899. if (this.check([0xFF, 0xFE, 0xFF, 0x0E, 0x53, 0x00, 0x6B, 0x00, 0x65, 0x00, 0x74, 0x00, 0x63, 0x00, 0x68, 0x00, 0x55, 0x00, 0x70, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6C, 0x00])) {
  1900. return {
  1901. ext: 'skp',
  1902. mime: 'application/vnd.sketchup.skp'
  1903. };
  1904. }
  1905. if (this.checkString('-----BEGIN PGP MESSAGE-----')) {
  1906. return {
  1907. ext: 'pgp',
  1908. mime: 'application/pgp-encrypted'
  1909. };
  1910. }
  1911. // Check MPEG 1 or 2 Layer 3 header, or 'layer 0' for ADTS (MPEG sync-word 0xFFE)
  1912. if (this.buffer.length >= 2 && this.check([0xFF, 0xE0], {
  1913. offset: 0,
  1914. mask: [0xFF, 0xE0]
  1915. })) {
  1916. if (this.check([0x10], {
  1917. offset: 1,
  1918. mask: [0x16]
  1919. })) {
  1920. // Check for (ADTS) MPEG-2
  1921. if (this.check([0x08], {
  1922. offset: 1,
  1923. mask: [0x08]
  1924. })) {
  1925. return {
  1926. ext: 'aac',
  1927. mime: 'audio/aac'
  1928. };
  1929. }
  1930. // Must be (ADTS) MPEG-4
  1931. return {
  1932. ext: 'aac',
  1933. mime: 'audio/aac'
  1934. };
  1935. }
  1936. // MPEG 1 or 2 Layer 3 header
  1937. // Check for MPEG layer 3
  1938. if (this.check([0x02], {
  1939. offset: 1,
  1940. mask: [0x06]
  1941. })) {
  1942. return {
  1943. ext: 'mp3',
  1944. mime: 'audio/mpeg'
  1945. };
  1946. }
  1947. // Check for MPEG layer 2
  1948. if (this.check([0x04], {
  1949. offset: 1,
  1950. mask: [0x06]
  1951. })) {
  1952. return {
  1953. ext: 'mp2',
  1954. mime: 'audio/mpeg'
  1955. };
  1956. }
  1957. // Check for MPEG layer 1
  1958. if (this.check([0x06], {
  1959. offset: 1,
  1960. mask: [0x06]
  1961. })) {
  1962. return {
  1963. ext: 'mp1',
  1964. mime: 'audio/mpeg'
  1965. };
  1966. }
  1967. }
  1968. return {};
  1969. }
  1970. }, {
  1971. key: "readTiffTag",
  1972. value: async function readTiffTag(bigEndian) {
  1973. var Token = KrajeeFileTypeConfig.Token;
  1974. var tagId = null;
  1975. try {
  1976. tagId = await this.tokenizer.readToken(bigEndian ? Token.UINT16_BE : Token.UINT16_LE);
  1977. } catch (error) {
  1978. if (_instanceof(error, EndOfStreamError)) {
  1979. return null;
  1980. }
  1981. throw error;
  1982. }
  1983. this.tokenizer.ignore(10);
  1984. switch (tagId) {
  1985. case 50_341:
  1986. return {
  1987. ext: 'arw',
  1988. mime: 'image/x-sony-arw'
  1989. };
  1990. case 50_706:
  1991. return {
  1992. ext: 'dng',
  1993. mime: 'image/x-adobe-dng'
  1994. };
  1995. default:
  1996. return null;
  1997. }
  1998. }
  1999. }, {
  2000. key: "readTiffIFD",
  2001. value: async function readTiffIFD(bigEndian) {
  2002. var Token = KrajeeFileTypeConfig.Token;
  2003. var numberOfTags = await this.tokenizer.readToken(bigEndian ? Token.UINT16_BE : Token.UINT16_LE);
  2004. for (var n = 0; n < numberOfTags; ++n) {
  2005. var fileType = await this.readTiffTag(bigEndian);
  2006. if (fileType) {
  2007. return fileType;
  2008. }
  2009. }
  2010. return null;
  2011. }
  2012. }, {
  2013. key: "readTiffHeader",
  2014. value: async function readTiffHeader(bigEndian) {
  2015. var Token = KrajeeFileTypeConfig.Token;
  2016. var version = (bigEndian ? Token.UINT16_BE : Token.UINT16_LE).get(this.buffer, 2);
  2017. var ifdOffset = (bigEndian ? Token.UINT32_BE : Token.UINT32_LE).get(this.buffer, 4);
  2018. var tiff = {
  2019. ext: 'tif',
  2020. mime: 'image/tiff'
  2021. };
  2022. if (version === 42) {
  2023. // TIFF file header
  2024. if (ifdOffset >= 6) {
  2025. if (this.checkString('CR', {
  2026. offset: 8
  2027. })) {
  2028. return {
  2029. ext: 'cr2',
  2030. mime: 'image/x-canon-cr2'
  2031. };
  2032. }
  2033. if (ifdOffset >= 8 && (this.check([0x1C, 0x00, 0xFE, 0x00], {
  2034. offset: 8
  2035. }) || this.check([0x1F, 0x00, 0x0B, 0x00], {
  2036. offset: 8
  2037. }))) {
  2038. return {
  2039. ext: 'nef',
  2040. mime: 'image/x-nikon-nef'
  2041. };
  2042. }
  2043. }
  2044. await this.tokenizer.ignore(ifdOffset);
  2045. var fileType = await this.readTiffIFD(false);
  2046. return fileType ? fileType : tiff;
  2047. }
  2048. if (version === 43) {
  2049. // Big TIFF file header
  2050. return tiff;
  2051. }
  2052. }
  2053. }]);
  2054. return FileTypeParser;
  2055. }();