From 660f42befd63398acf556bcaf2d8621f0cf56e2e Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Wed, 4 Jun 2025 20:41:44 +0200 Subject: [PATCH] Audio: Fix cover retrieval (#5967) --- package-lock.json | 156 +- package.json | 1 + src/lib/music-metadata-browser/index.d.ts | 33 - src/lib/music-metadata-browser/index.js | 19378 -------------------- src/util/audio.ts | 7 +- 5 files changed, 155 insertions(+), 19420 deletions(-) delete mode 100644 src/lib/music-metadata-browser/index.d.ts delete mode 100644 src/lib/music-metadata-browser/index.js diff --git a/package-lock.json b/package-lock.json index 259698fac..bbc6b55e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "idb-keyval": "^6.2.2", "lowlight": "^3.3.0", "mp4box": "^0.5.4", + "music-metadata": "^11.2.3", "opus-recorder": "github:Ajaxy/opus-recorder", "os-browserify": "^0.3.0", "pako": "^2.1.0", @@ -5668,6 +5669,30 @@ "node": ">=8" } }, + "node_modules/@tokenizer/inflate": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", + "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "fflate": "^0.8.2", + "token-types": "^6.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -9182,7 +9207,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -9624,10 +9648,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -11973,6 +11996,12 @@ } } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -12012,6 +12041,24 @@ "node": ">=16.0.0" } }, + "node_modules/file-type": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz", + "integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==", + "license": "MIT", + "dependencies": { + "@tokenizer/inflate": "^0.2.6", + "strtok3": "^10.2.0", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -13498,7 +13545,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "devOptional": true, "funding": [ { "type": "github", @@ -16037,6 +16083,15 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/memfs": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.17.1.tgz", @@ -16383,7 +16438,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/multicast-dns": { @@ -16400,6 +16454,35 @@ "multicast-dns": "cli.js" } }, + "node_modules/music-metadata": { + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/music-metadata/-/music-metadata-11.2.3.tgz", + "integrity": "sha512-ReVxFoO12kaRiaNmqxkAdytul1Ntl2ersdIyw/CqWPysvOFpUrr19s8uOHEA4xjK69ETmpP71KezXWEE7r5Myg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + }, + { + "type": "buymeacoffee", + "url": "https://buymeacoffee.com/borewit" + } + ], + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "content-type": "^1.0.5", + "debug": "^4.4.1", + "file-type": "^20.5.0", + "media-typer": "^1.1.0", + "strtok3": "^10.2.2", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/nan": { "version": "2.22.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", @@ -17168,6 +17251,19 @@ "url": "https://github.com/sponsors/jet2jet" } }, + "node_modules/peek-readable": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-7.0.0.tgz", + "integrity": "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -19970,6 +20066,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strtok3": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.2.2.tgz", + "integrity": "sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -21084,6 +21197,23 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.0.0.tgz", + "integrity": "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -21879,6 +22009,18 @@ "node": ">=0.8.0" } }, + "node_modules/uint8array-extras": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", + "integrity": "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", diff --git a/package.json b/package.json index defa474e6..0e097f6ac 100644 --- a/package.json +++ b/package.json @@ -140,6 +140,7 @@ "idb-keyval": "^6.2.2", "lowlight": "^3.3.0", "mp4box": "^0.5.4", + "music-metadata": "^11.2.3", "opus-recorder": "github:Ajaxy/opus-recorder", "os-browserify": "^0.3.0", "pako": "^2.1.0", diff --git a/src/lib/music-metadata-browser/index.d.ts b/src/lib/music-metadata-browser/index.d.ts deleted file mode 100644 index c38f1278e..000000000 --- a/src/lib/music-metadata-browser/index.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -interface ICommonTagsResult { - title?: string; - artist?: string; - picture?: IPicture[]; -} - -interface IFormat { - duration?: number; -} - -interface IAudioMetadata extends INativeAudioMetadata { - common: ICommonTagsResult; - format: IFormat; -} - -interface IPicture { - format: string; - data: Buffer; - description?: string; - type?: string; - name?: string; -} - -interface IOptions { - duration?: boolean; - skipCovers?: boolean; - skipPostHeaders?: boolean; - includeChapters?: boolean; -} - -export declare function selectCover(pictures?: IPicture[]): IPicture | null; - -export declare function fetchFromUrl(audioTrackUrl: string, options?: IOptions): Promise; diff --git a/src/lib/music-metadata-browser/index.js b/src/lib/music-metadata-browser/index.js deleted file mode 100644 index bd491ba48..000000000 --- a/src/lib/music-metadata-browser/index.js +++ /dev/null @@ -1,19378 +0,0 @@ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -/*! - * content-type - * Copyright(c) 2015 Douglas Christopher Wilson - * MIT Licensed - */ - -/*! - * media-typer - * Copyright(c) 2014-2017 Douglas Christopher Wilson - * MIT Licensed - */ - -/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ - -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["music_metadata_browser"] = factory(); - else - root["music_metadata_browser"] = factory(); -})(self, () => { -return /******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ 9742: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - - -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray - -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array - -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] - revLookup[code.charCodeAt(i)] = i -} - -// Support decoding URL-safe base64 strings, as Node.js does. -// See: https://en.wikipedia.org/wiki/Base64#URL_applications -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 - -function getLens (b64) { - var len = b64.length - - if (len % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // Trim off extra bytes after placeholder bytes are found - // See: https://github.com/beatgammit/base64-js/issues/42 - var validLen = b64.indexOf('=') - if (validLen === -1) validLen = len - - var placeHoldersLen = validLen === len - ? 0 - : 4 - (validLen % 4) - - return [validLen, placeHoldersLen] -} - -// base64 is 4/3 + up to two characters of the original data -function byteLength (b64) { - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function _byteLength (b64, validLen, placeHoldersLen) { - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} - -function toByteArray (b64) { - var tmp - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - - var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) - - var curByte = 0 - - // if there are placeholders, only get up to the last complete 4 chars - var len = placeHoldersLen > 0 - ? validLen - 4 - : validLen - - var i - for (i = 0; i < len; i += 4) { - tmp = - (revLookup[b64.charCodeAt(i)] << 18) | - (revLookup[b64.charCodeAt(i + 1)] << 12) | - (revLookup[b64.charCodeAt(i + 2)] << 6) | - revLookup[b64.charCodeAt(i + 3)] - arr[curByte++] = (tmp >> 16) & 0xFF - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 2) { - tmp = - (revLookup[b64.charCodeAt(i)] << 2) | - (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[curByte++] = tmp & 0xFF - } - - if (placeHoldersLen === 1) { - tmp = - (revLookup[b64.charCodeAt(i)] << 10) | - (revLookup[b64.charCodeAt(i + 1)] << 4) | - (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } - - return arr -} - -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + - lookup[num >> 12 & 0x3F] + - lookup[num >> 6 & 0x3F] + - lookup[num & 0x3F] -} - -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = - ((uint8[i] << 16) & 0xFF0000) + - ((uint8[i + 1] << 8) & 0xFF00) + - (uint8[i + 2] & 0xFF) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} - -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk( - uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) - )) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - parts.push( - lookup[tmp >> 2] + - lookup[(tmp << 4) & 0x3F] + - '==' - ) - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + uint8[len - 1] - parts.push( - lookup[tmp >> 10] + - lookup[(tmp >> 4) & 0x3F] + - lookup[(tmp << 2) & 0x3F] + - '=' - ) - } - - return parts.join('') -} - - -/***/ }), - -/***/ 8764: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -/* eslint-disable no-proto */ - - - -const base64 = __webpack_require__(9742) -const ieee754 = __webpack_require__(645) -const customInspectSymbol = - (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation - ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation - : null - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 - -const K_MAX_LENGTH = 0x7fffffff -exports.kMaxLength = K_MAX_LENGTH - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Print warning and recommend using `buffer` v4.x which has an Object - * implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * We report that the browser does not support typed arrays if the are not subclassable - * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` - * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support - * for __proto__ and has a buggy typed array implementation. - */ -Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() - -if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && - typeof console.error === 'function') { - console.error( - 'This browser lacks typed array (Uint8Array) support which is required by ' + - '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' - ) -} - -function typedArraySupport () { - // Can typed array instances can be augmented? - try { - const arr = new Uint8Array(1) - const proto = { foo: function () { return 42 } } - Object.setPrototypeOf(proto, Uint8Array.prototype) - Object.setPrototypeOf(arr, proto) - return arr.foo() === 42 - } catch (e) { - return false - } -} - -Object.defineProperty(Buffer.prototype, 'parent', { - enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.buffer - } -}) - -Object.defineProperty(Buffer.prototype, 'offset', { - enumerable: true, - get: function () { - if (!Buffer.isBuffer(this)) return undefined - return this.byteOffset - } -}) - -function createBuffer (length) { - if (length > K_MAX_LENGTH) { - throw new RangeError('The value "' + length + '" is invalid for option "size"') - } - // Return an augmented `Uint8Array` instance - const buf = new Uint8Array(length) - Object.setPrototypeOf(buf, Buffer.prototype) - return buf -} - -/** - * The Buffer constructor returns instances of `Uint8Array` that have their - * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of - * `Uint8Array`, so the returned instances will have all the node `Buffer` methods - * and the `Uint8Array` methods. Square bracket notation works as expected -- it - * returns a single octet. - * - * The `Uint8Array` prototype remains unmodified. - */ - -function Buffer (arg, encodingOrOffset, length) { - // Common case. - if (typeof arg === 'number') { - if (typeof encodingOrOffset === 'string') { - throw new TypeError( - 'The "string" argument must be of type string. Received type number' - ) - } - return allocUnsafe(arg) - } - return from(arg, encodingOrOffset, length) -} - -Buffer.poolSize = 8192 // not used by this implementation - -function from (value, encodingOrOffset, length) { - if (typeof value === 'string') { - return fromString(value, encodingOrOffset) - } - - if (ArrayBuffer.isView(value)) { - return fromArrayView(value) - } - - if (value == null) { - throw new TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) - } - - if (isInstance(value, ArrayBuffer) || - (value && isInstance(value.buffer, ArrayBuffer))) { - return fromArrayBuffer(value, encodingOrOffset, length) - } - - if (typeof SharedArrayBuffer !== 'undefined' && - (isInstance(value, SharedArrayBuffer) || - (value && isInstance(value.buffer, SharedArrayBuffer)))) { - return fromArrayBuffer(value, encodingOrOffset, length) - } - - if (typeof value === 'number') { - throw new TypeError( - 'The "value" argument must not be of type number. Received type number' - ) - } - - const valueOf = value.valueOf && value.valueOf() - if (valueOf != null && valueOf !== value) { - return Buffer.from(valueOf, encodingOrOffset, length) - } - - const b = fromObject(value) - if (b) return b - - if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && - typeof value[Symbol.toPrimitive] === 'function') { - return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length) - } - - throw new TypeError( - 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + - 'or Array-like Object. Received type ' + (typeof value) - ) -} - -/** - * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError - * if value is a number. - * Buffer.from(str[, encoding]) - * Buffer.from(array) - * Buffer.from(buffer) - * Buffer.from(arrayBuffer[, byteOffset[, length]]) - **/ -Buffer.from = function (value, encodingOrOffset, length) { - return from(value, encodingOrOffset, length) -} - -// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: -// https://github.com/feross/buffer/pull/148 -Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype) -Object.setPrototypeOf(Buffer, Uint8Array) - -function assertSize (size) { - if (typeof size !== 'number') { - throw new TypeError('"size" argument must be of type number') - } else if (size < 0) { - throw new RangeError('The value "' + size + '" is invalid for option "size"') - } -} - -function alloc (size, fill, encoding) { - assertSize(size) - if (size <= 0) { - return createBuffer(size) - } - if (fill !== undefined) { - // Only pay attention to encoding if it's a string. This - // prevents accidentally sending in a number that would - // be interpreted as a start offset. - return typeof encoding === 'string' - ? createBuffer(size).fill(fill, encoding) - : createBuffer(size).fill(fill) - } - return createBuffer(size) -} - -/** - * Creates a new filled Buffer instance. - * alloc(size[, fill[, encoding]]) - **/ -Buffer.alloc = function (size, fill, encoding) { - return alloc(size, fill, encoding) -} - -function allocUnsafe (size) { - assertSize(size) - return createBuffer(size < 0 ? 0 : checked(size) | 0) -} - -/** - * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. - * */ -Buffer.allocUnsafe = function (size) { - return allocUnsafe(size) -} -/** - * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. - */ -Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(size) -} - -function fromString (string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8' - } - - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } - - const length = byteLength(string, encoding) | 0 - let buf = createBuffer(length) - - const actual = buf.write(string, encoding) - - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - buf = buf.slice(0, actual) - } - - return buf -} - -function fromArrayLike (array) { - const length = array.length < 0 ? 0 : checked(array.length) | 0 - const buf = createBuffer(length) - for (let i = 0; i < length; i += 1) { - buf[i] = array[i] & 255 - } - return buf -} - -function fromArrayView (arrayView) { - if (isInstance(arrayView, Uint8Array)) { - const copy = new Uint8Array(arrayView) - return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength) - } - return fromArrayLike(arrayView) -} - -function fromArrayBuffer (array, byteOffset, length) { - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('"offset" is outside of buffer bounds') - } - - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('"length" is outside of buffer bounds') - } - - let buf - if (byteOffset === undefined && length === undefined) { - buf = new Uint8Array(array) - } else if (length === undefined) { - buf = new Uint8Array(array, byteOffset) - } else { - buf = new Uint8Array(array, byteOffset, length) - } - - // Return an augmented `Uint8Array` instance - Object.setPrototypeOf(buf, Buffer.prototype) - - return buf -} - -function fromObject (obj) { - if (Buffer.isBuffer(obj)) { - const len = checked(obj.length) | 0 - const buf = createBuffer(len) - - if (buf.length === 0) { - return buf - } - - obj.copy(buf, 0, 0, len) - return buf - } - - if (obj.length !== undefined) { - if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { - return createBuffer(0) - } - return fromArrayLike(obj) - } - - if (obj.type === 'Buffer' && Array.isArray(obj.data)) { - return fromArrayLike(obj.data) - } -} - -function checked (length) { - // Note: cannot use `length < K_MAX_LENGTH` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= K_MAX_LENGTH) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') - } - return length | 0 -} - -function SlowBuffer (length) { - if (+length != length) { // eslint-disable-line eqeqeq - length = 0 - } - return Buffer.alloc(+length) -} - -Buffer.isBuffer = function isBuffer (b) { - return b != null && b._isBuffer === true && - b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false -} - -Buffer.compare = function compare (a, b) { - if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) - if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { - throw new TypeError( - 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' - ) - } - - if (a === b) return 0 - - let x = a.length - let y = b.length - - for (let i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i] - y = b[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -Buffer.isEncoding = function isEncoding (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'latin1': - case 'binary': - case 'base64': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} - -Buffer.concat = function concat (list, length) { - if (!Array.isArray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - - if (list.length === 0) { - return Buffer.alloc(0) - } - - let i - if (length === undefined) { - length = 0 - for (i = 0; i < list.length; ++i) { - length += list[i].length - } - } - - const buffer = Buffer.allocUnsafe(length) - let pos = 0 - for (i = 0; i < list.length; ++i) { - let buf = list[i] - if (isInstance(buf, Uint8Array)) { - if (pos + buf.length > buffer.length) { - if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf) - buf.copy(buffer, pos) - } else { - Uint8Array.prototype.set.call( - buffer, - buf, - pos - ) - } - } else if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } else { - buf.copy(buffer, pos) - } - pos += buf.length - } - return buffer -} - -function byteLength (string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - throw new TypeError( - 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + - 'Received type ' + typeof string - ) - } - - const len = string.length - const mustMatch = (arguments.length > 2 && arguments[2] === true) - if (!mustMatch && len === 0) return 0 - - // Use a for loop to avoid recursion - let loweredCase = false - for (;;) { - switch (encoding) { - case 'ascii': - case 'latin1': - case 'binary': - return len - case 'utf8': - case 'utf-8': - return utf8ToBytes(string).length - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return len * 2 - case 'hex': - return len >>> 1 - case 'base64': - return base64ToBytes(string).length - default: - if (loweredCase) { - return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 - } - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} -Buffer.byteLength = byteLength - -function slowToString (encoding, start, end) { - let loweredCase = false - - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only - // property of a typed array. - - // This behaves neither like String nor Uint8Array in that we set start/end - // to their upper/lower bounds if the value passed is out of range. - // undefined is handled specially as per ECMA-262 6th Edition, - // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. - if (start === undefined || start < 0) { - start = 0 - } - // Return early if start > this.length. Done here to prevent potential uint32 - // coercion fail below. - if (start > this.length) { - return '' - } - - if (end === undefined || end > this.length) { - end = this.length - } - - if (end <= 0) { - return '' - } - - // Force coercion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 - - if (end <= start) { - return '' - } - - if (!encoding) encoding = 'utf8' - - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) - - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) - - case 'ascii': - return asciiSlice(this, start, end) - - case 'latin1': - case 'binary': - return latin1Slice(this, start, end) - - case 'base64': - return base64Slice(this, start, end) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} - -// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) -// to detect a Buffer instance. It's not possible to use `instanceof Buffer` -// reliably in a browserify context because there could be multiple different -// copies of the 'buffer' package in use. This method works even for Buffer -// instances that were created from another copy of the `buffer` package. -// See: https://github.com/feross/buffer/issues/154 -Buffer.prototype._isBuffer = true - -function swap (b, n, m) { - const i = b[n] - b[n] = b[m] - b[m] = i -} - -Buffer.prototype.swap16 = function swap16 () { - const len = this.length - if (len % 2 !== 0) { - throw new RangeError('Buffer size must be a multiple of 16-bits') - } - for (let i = 0; i < len; i += 2) { - swap(this, i, i + 1) - } - return this -} - -Buffer.prototype.swap32 = function swap32 () { - const len = this.length - if (len % 4 !== 0) { - throw new RangeError('Buffer size must be a multiple of 32-bits') - } - for (let i = 0; i < len; i += 4) { - swap(this, i, i + 3) - swap(this, i + 1, i + 2) - } - return this -} - -Buffer.prototype.swap64 = function swap64 () { - const len = this.length - if (len % 8 !== 0) { - throw new RangeError('Buffer size must be a multiple of 64-bits') - } - for (let i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) - swap(this, i + 3, i + 4) - } - return this -} - -Buffer.prototype.toString = function toString () { - const length = this.length - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) - return slowToString.apply(this, arguments) -} - -Buffer.prototype.toLocaleString = Buffer.prototype.toString - -Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.inspect = function inspect () { - let str = '' - const max = exports.INSPECT_MAX_BYTES - str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() - if (this.length > max) str += ' ... ' - return '' -} -if (customInspectSymbol) { - Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect -} - -Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { - if (isInstance(target, Uint8Array)) { - target = Buffer.from(target, target.offset, target.byteLength) - } - if (!Buffer.isBuffer(target)) { - throw new TypeError( - 'The "target" argument must be one of type Buffer or Uint8Array. ' + - 'Received type ' + (typeof target) - ) - } - - if (start === undefined) { - start = 0 - } - if (end === undefined) { - end = target ? target.length : 0 - } - if (thisStart === undefined) { - thisStart = 0 - } - if (thisEnd === undefined) { - thisEnd = this.length - } - - if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { - throw new RangeError('out of range index') - } - - if (thisStart >= thisEnd && start >= end) { - return 0 - } - if (thisStart >= thisEnd) { - return -1 - } - if (start >= end) { - return 1 - } - - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 - - if (this === target) return 0 - - let x = thisEnd - thisStart - let y = end - start - const len = Math.min(x, y) - - const thisCopy = this.slice(thisStart, thisEnd) - const targetCopy = target.slice(start, end) - - for (let i = 0; i < len; ++i) { - if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, -// OR the last index of `val` in `buffer` at offset <= `byteOffset`. -// -// Arguments: -// - buffer - a Buffer to search -// - val - a string, Buffer, or number -// - byteOffset - an index into `buffer`; will be clamped to an int32 -// - encoding - an optional encoding, relevant is val is a string -// - dir - true for indexOf, false for lastIndexOf -function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1 - - // Normalize byteOffset - if (typeof byteOffset === 'string') { - encoding = byteOffset - byteOffset = 0 - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000 - } - byteOffset = +byteOffset // Coerce to Number. - if (numberIsNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : (buffer.length - 1) - } - - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset - if (byteOffset >= buffer.length) { - if (dir) return -1 - else byteOffset = buffer.length - 1 - } else if (byteOffset < 0) { - if (dir) byteOffset = 0 - else return -1 - } - - // Normalize val - if (typeof val === 'string') { - val = Buffer.from(val, encoding) - } - - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1 - } - return arrayIndexOf(buffer, val, byteOffset, encoding, dir) - } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] - if (typeof Uint8Array.prototype.indexOf === 'function') { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) - } - } - return arrayIndexOf(buffer, [val], byteOffset, encoding, dir) - } - - throw new TypeError('val must be string, number or Buffer') -} - -function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - let indexSize = 1 - let arrLength = arr.length - let valLength = val.length - - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() - if (encoding === 'ucs2' || encoding === 'ucs-2' || - encoding === 'utf16le' || encoding === 'utf-16le') { - if (arr.length < 2 || val.length < 2) { - return -1 - } - indexSize = 2 - arrLength /= 2 - valLength /= 2 - byteOffset /= 2 - } - } - - function read (buf, i) { - if (indexSize === 1) { - return buf[i] - } else { - return buf.readUInt16BE(i * indexSize) - } - } - - let i - if (dir) { - let foundIndex = -1 - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize - } else { - if (foundIndex !== -1) i -= i - foundIndex - foundIndex = -1 - } - } - } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength - for (i = byteOffset; i >= 0; i--) { - let found = true - for (let j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false - break - } - } - if (found) return i - } - } - - return -1 -} - -Buffer.prototype.includes = function includes (val, byteOffset, encoding) { - return this.indexOf(val, byteOffset, encoding) !== -1 -} - -Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} - -Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} - -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - const remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - - const strLen = string.length - - if (length > strLen / 2) { - length = strLen / 2 - } - let i - for (i = 0; i < length; ++i) { - const parsed = parseInt(string.substr(i * 2, 2), 16) - if (numberIsNaN(parsed)) return i - buf[offset + i] = parsed - } - return i -} - -function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) -} - -function asciiWrite (buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length) -} - -function base64Write (buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length) -} - -function ucs2Write (buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) -} - -Buffer.prototype.write = function write (string, offset, length, encoding) { - // Buffer#write(string) - if (offset === undefined) { - encoding = 'utf8' - length = this.length - offset = 0 - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length - offset = 0 - // Buffer#write(string, offset[, length][, encoding]) - } else if (isFinite(offset)) { - offset = offset >>> 0 - if (isFinite(length)) { - length = length >>> 0 - if (encoding === undefined) encoding = 'utf8' - } else { - encoding = length - length = undefined - } - } else { - throw new Error( - 'Buffer.write(string, encoding, offset[, length]) is no longer supported' - ) - } - - const remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining - - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } - - if (!encoding) encoding = 'utf8' - - let loweredCase = false - for (;;) { - switch (encoding) { - case 'hex': - return hexWrite(this, string, offset, length) - - case 'utf8': - case 'utf-8': - return utf8Write(this, string, offset, length) - - case 'ascii': - case 'latin1': - case 'binary': - return asciiWrite(this, string, offset, length) - - case 'base64': - // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return ucs2Write(this, string, offset, length) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} - -Buffer.prototype.toJSON = function toJSON () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} - -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} - -function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - const res = [] - - let i = start - while (i < end) { - const firstByte = buf[i] - let codePoint = null - let bytesPerSequence = (firstByte > 0xEF) - ? 4 - : (firstByte > 0xDF) - ? 3 - : (firstByte > 0xBF) - ? 2 - : 1 - - if (i + bytesPerSequence <= end) { - let secondByte, thirdByte, fourthByte, tempCodePoint - - switch (bytesPerSequence) { - case 1: - if (firstByte < 0x80) { - codePoint = firstByte - } - break - case 2: - secondByte = buf[i + 1] - if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) - if (tempCodePoint > 0x7F) { - codePoint = tempCodePoint - } - } - break - case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) - if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { - codePoint = tempCodePoint - } - } - break - case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) - if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { - codePoint = tempCodePoint - } - } - } - } - - if (codePoint === null) { - // we did not generate a valid codePoint so insert a - // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD - bytesPerSequence = 1 - } else if (codePoint > 0xFFFF) { - // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) - codePoint = 0xDC00 | codePoint & 0x3FF - } - - res.push(codePoint) - i += bytesPerSequence - } - - return decodeCodePointsArray(res) -} - -// Based on http://stackoverflow.com/a/22747272/680742, the browser with -// the lowest limit is Chrome, with 0x10000 args. -// We go 1 magnitude less, for safety -const MAX_ARGUMENTS_LENGTH = 0x1000 - -function decodeCodePointsArray (codePoints) { - const len = codePoints.length - if (len <= MAX_ARGUMENTS_LENGTH) { - return String.fromCharCode.apply(String, codePoints) // avoid extra slice() - } - - // Decode in chunks to avoid "call stack size exceeded". - let res = '' - let i = 0 - while (i < len) { - res += String.fromCharCode.apply( - String, - codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) - ) - } - return res -} - -function asciiSlice (buf, start, end) { - let ret = '' - end = Math.min(buf.length, end) - - for (let i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i] & 0x7F) - } - return ret -} - -function latin1Slice (buf, start, end) { - let ret = '' - end = Math.min(buf.length, end) - - for (let i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]) - } - return ret -} - -function hexSlice (buf, start, end) { - const len = buf.length - - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len - - let out = '' - for (let i = start; i < end; ++i) { - out += hexSliceLookupTable[buf[i]] - } - return out -} - -function utf16leSlice (buf, start, end) { - const bytes = buf.slice(start, end) - let res = '' - // If bytes.length is odd, the last 8 bits must be ignored (same as node.js) - for (let i = 0; i < bytes.length - 1; i += 2) { - res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) - } - return res -} - -Buffer.prototype.slice = function slice (start, end) { - const len = this.length - start = ~~start - end = end === undefined ? len : ~~end - - if (start < 0) { - start += len - if (start < 0) start = 0 - } else if (start > len) { - start = len - } - - if (end < 0) { - end += len - if (end < 0) end = 0 - } else if (end > len) { - end = len - } - - if (end < start) end = start - - const newBuf = this.subarray(start, end) - // Return an augmented `Uint8Array` instance - Object.setPrototypeOf(newBuf, Buffer.prototype) - - return newBuf -} - -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') - if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') -} - -Buffer.prototype.readUintLE = -Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - let val = this[offset] - let mul = 1 - let i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - - return val -} - -Buffer.prototype.readUintBE = -Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - checkOffset(offset, byteLength, this.length) - } - - let val = this[offset + --byteLength] - let mul = 1 - while (byteLength > 0 && (mul *= 0x100)) { - val += this[offset + --byteLength] * mul - } - - return val -} - -Buffer.prototype.readUint8 = -Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - return this[offset] -} - -Buffer.prototype.readUint16LE = -Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} - -Buffer.prototype.readUint16BE = -Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} - -Buffer.prototype.readUint32LE = -Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} - -Buffer.prototype.readUint32BE = -Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} - -Buffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE (offset) { - offset = offset >>> 0 - validateNumber(offset, 'offset') - const first = this[offset] - const last = this[offset + 7] - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 8) - } - - const lo = first + - this[++offset] * 2 ** 8 + - this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 24 - - const hi = this[++offset] + - this[++offset] * 2 ** 8 + - this[++offset] * 2 ** 16 + - last * 2 ** 24 - - return BigInt(lo) + (BigInt(hi) << BigInt(32)) -}) - -Buffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE (offset) { - offset = offset >>> 0 - validateNumber(offset, 'offset') - const first = this[offset] - const last = this[offset + 7] - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 8) - } - - const hi = first * 2 ** 24 + - this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + - this[++offset] - - const lo = this[++offset] * 2 ** 24 + - this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + - last - - return (BigInt(hi) << BigInt(32)) + BigInt(lo) -}) - -Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - let val = this[offset] - let mul = 1 - let i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - let i = byteLength - let mul = 1 - let val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) { - val += this[offset + --i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - const val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 2, this.length) - const val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} - -Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} - -Buffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE (offset) { - offset = offset >>> 0 - validateNumber(offset, 'offset') - const first = this[offset] - const last = this[offset + 7] - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 8) - } - - const val = this[offset + 4] + - this[offset + 5] * 2 ** 8 + - this[offset + 6] * 2 ** 16 + - (last << 24) // Overflow - - return (BigInt(val) << BigInt(32)) + - BigInt(first + - this[++offset] * 2 ** 8 + - this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 24) -}) - -Buffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE (offset) { - offset = offset >>> 0 - validateNumber(offset, 'offset') - const first = this[offset] - const last = this[offset + 7] - if (first === undefined || last === undefined) { - boundsError(offset, this.length - 8) - } - - const val = (first << 24) + // Overflow - this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + - this[++offset] - - return (BigInt(val) << BigInt(32)) + - BigInt(this[++offset] * 2 ** 24 + - this[++offset] * 2 ** 16 + - this[++offset] * 2 ** 8 + - last) -}) - -Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} - -Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} - -Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} - -Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - offset = offset >>> 0 - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} - -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') - if (offset + ext > buf.length) throw new RangeError('Index out of range') -} - -Buffer.prototype.writeUintLE = -Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - const maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - let mul = 1 - let i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUintBE = -Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - byteLength = byteLength >>> 0 - if (!noAssert) { - const maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - let i = byteLength - 1 - let mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUint8 = -Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - this[offset] = (value & 0xff) - return offset + 1 -} - -Buffer.prototype.writeUint16LE = -Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} - -Buffer.prototype.writeUint16BE = -Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} - -Buffer.prototype.writeUint32LE = -Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - return offset + 4 -} - -Buffer.prototype.writeUint32BE = -Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 -} - -function wrtBigUInt64LE (buf, value, offset, min, max) { - checkIntBI(value, min, max, buf, offset, 7) - - let lo = Number(value & BigInt(0xffffffff)) - buf[offset++] = lo - lo = lo >> 8 - buf[offset++] = lo - lo = lo >> 8 - buf[offset++] = lo - lo = lo >> 8 - buf[offset++] = lo - let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)) - buf[offset++] = hi - hi = hi >> 8 - buf[offset++] = hi - hi = hi >> 8 - buf[offset++] = hi - hi = hi >> 8 - buf[offset++] = hi - return offset -} - -function wrtBigUInt64BE (buf, value, offset, min, max) { - checkIntBI(value, min, max, buf, offset, 7) - - let lo = Number(value & BigInt(0xffffffff)) - buf[offset + 7] = lo - lo = lo >> 8 - buf[offset + 6] = lo - lo = lo >> 8 - buf[offset + 5] = lo - lo = lo >> 8 - buf[offset + 4] = lo - let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)) - buf[offset + 3] = hi - hi = hi >> 8 - buf[offset + 2] = hi - hi = hi >> 8 - buf[offset + 1] = hi - hi = hi >> 8 - buf[offset] = hi - return offset + 8 -} - -Buffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE (value, offset = 0) { - return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) -}) - -Buffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE (value, offset = 0) { - return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) -}) - -Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - const limit = Math.pow(2, (8 * byteLength) - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - let i = 0 - let mul = 1 - let sub = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - const limit = Math.pow(2, (8 * byteLength) - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - let i = byteLength - 1 - let mul = 1 - let sub = 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) - return offset + 1 -} - -Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - return offset + 2 -} - -Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - return offset + 2 -} - -Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - return offset + 4 -} - -Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - return offset + 4 -} - -Buffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE (value, offset = 0) { - return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) -}) - -Buffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE (value, offset = 0) { - return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) -}) - -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') - if (offset < 0) throw new RangeError('Index out of range') -} - -function writeFloat (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} - -Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} - -function writeDouble (buf, value, offset, littleEndian, noAssert) { - value = +value - offset = offset >>> 0 - if (!noAssert) { - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} - -Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start - - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 - - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('Index out of range') - if (end < 0) throw new RangeError('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) end = this.length - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start - } - - const len = end - start - - if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { - // Use built-in when available, missing from IE11 - this.copyWithin(targetStart, start, end) - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, end), - targetStart - ) - } - - return len -} - -// Usage: -// buffer.fill(number[, offset[, end]]) -// buffer.fill(buffer[, offset[, end]]) -// buffer.fill(string[, offset[, end]][, encoding]) -Buffer.prototype.fill = function fill (val, start, end, encoding) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - encoding = start - start = 0 - end = this.length - } else if (typeof end === 'string') { - encoding = end - end = this.length - } - if (encoding !== undefined && typeof encoding !== 'string') { - throw new TypeError('encoding must be a string') - } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } - if (val.length === 1) { - const code = val.charCodeAt(0) - if ((encoding === 'utf8' && code < 128) || - encoding === 'latin1') { - // Fast path: If `val` fits into a single byte, use that numeric value. - val = code - } - } - } else if (typeof val === 'number') { - val = val & 255 - } else if (typeof val === 'boolean') { - val = Number(val) - } - - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } - - if (end <= start) { - return this - } - - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 - - if (!val) val = 0 - - let i - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val - } - } else { - const bytes = Buffer.isBuffer(val) - ? val - : Buffer.from(val, encoding) - const len = bytes.length - if (len === 0) { - throw new TypeError('The value "' + val + - '" is invalid for argument "value"') - } - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len] - } - } - - return this -} - -// CUSTOM ERRORS -// ============= - -// Simplified versions from Node, changed for Buffer-only usage -const errors = {} -function E (sym, getMessage, Base) { - errors[sym] = class NodeError extends Base { - constructor () { - super() - - Object.defineProperty(this, 'message', { - value: getMessage.apply(this, arguments), - writable: true, - configurable: true - }) - - // Add the error code to the name to include it in the stack trace. - this.name = `${this.name} [${sym}]` - // Access the stack to generate the error message including the error code - // from the name. - this.stack // eslint-disable-line no-unused-expressions - // Reset the name to the actual name. - delete this.name - } - - get code () { - return sym - } - - set code (value) { - Object.defineProperty(this, 'code', { - configurable: true, - enumerable: true, - value, - writable: true - }) - } - - toString () { - return `${this.name} [${sym}]: ${this.message}` - } - } -} - -E('ERR_BUFFER_OUT_OF_BOUNDS', - function (name) { - if (name) { - return `${name} is outside of buffer bounds` - } - - return 'Attempt to access memory outside buffer bounds' - }, RangeError) -E('ERR_INVALID_ARG_TYPE', - function (name, actual) { - return `The "${name}" argument must be of type number. Received type ${typeof actual}` - }, TypeError) -E('ERR_OUT_OF_RANGE', - function (str, range, input) { - let msg = `The value of "${str}" is out of range.` - let received = input - if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) { - received = addNumericalSeparator(String(input)) - } else if (typeof input === 'bigint') { - received = String(input) - if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) { - received = addNumericalSeparator(received) - } - received += 'n' - } - msg += ` It must be ${range}. Received ${received}` - return msg - }, RangeError) - -function addNumericalSeparator (val) { - let res = '' - let i = val.length - const start = val[0] === '-' ? 1 : 0 - for (; i >= start + 4; i -= 3) { - res = `_${val.slice(i - 3, i)}${res}` - } - return `${val.slice(0, i)}${res}` -} - -// CHECK FUNCTIONS -// =============== - -function checkBounds (buf, offset, byteLength) { - validateNumber(offset, 'offset') - if (buf[offset] === undefined || buf[offset + byteLength] === undefined) { - boundsError(offset, buf.length - (byteLength + 1)) - } -} - -function checkIntBI (value, min, max, buf, offset, byteLength) { - if (value > max || value < min) { - const n = typeof min === 'bigint' ? 'n' : '' - let range - if (byteLength > 3) { - if (min === 0 || min === BigInt(0)) { - range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}` - } else { - range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` + - `${(byteLength + 1) * 8 - 1}${n}` - } - } else { - range = `>= ${min}${n} and <= ${max}${n}` - } - throw new errors.ERR_OUT_OF_RANGE('value', range, value) - } - checkBounds(buf, offset, byteLength) -} - -function validateNumber (value, name) { - if (typeof value !== 'number') { - throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value) - } -} - -function boundsError (value, length, type) { - if (Math.floor(value) !== value) { - validateNumber(value, type) - throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value) - } - - if (length < 0) { - throw new errors.ERR_BUFFER_OUT_OF_BOUNDS() - } - - throw new errors.ERR_OUT_OF_RANGE(type || 'offset', - `>= ${type ? 1 : 0} and <= ${length}`, - value) -} - -// HELPER FUNCTIONS -// ================ - -const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g - -function base64clean (str) { - // Node takes equal signs as end of the Base64 encoding - str = str.split('=')[0] - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = str.trim().replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} - -function utf8ToBytes (string, units) { - units = units || Infinity - let codePoint - const length = string.length - let leadSurrogate = null - const bytes = [] - - for (let i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) - - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } - - // valid lead - leadSurrogate = codePoint - - continue - } - - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue - } - - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - } - - leadSurrogate = null - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else { - throw new Error('Invalid code point') - } - } - - return bytes -} - -function asciiToBytes (str) { - const byteArray = [] - for (let i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} - -function utf16leToBytes (str, units) { - let c, hi, lo - const byteArray = [] - for (let i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break - - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } - - return byteArray -} - -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} - -function blitBuffer (src, dst, offset, length) { - let i - for (i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i] - } - return i -} - -// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass -// the `instanceof` check but they should be treated as of that type. -// See: https://github.com/feross/buffer/issues/166 -function isInstance (obj, type) { - return obj instanceof type || - (obj != null && obj.constructor != null && obj.constructor.name != null && - obj.constructor.name === type.name) -} -function numberIsNaN (obj) { - // For IE11 support - return obj !== obj // eslint-disable-line no-self-compare -} - -// Create lookup table for `toString('hex')` -// See: https://github.com/feross/buffer/issues/219 -const hexSliceLookupTable = (function () { - const alphabet = '0123456789abcdef' - const table = new Array(256) - for (let i = 0; i < 16; ++i) { - const i16 = i * 16 - for (let j = 0; j < 16; ++j) { - table[i16 + j] = alphabet[i] + alphabet[j] - } - } - return table -})() - -// Return not function with Error if BigInt not supported -function defineBigIntMethod (fn) { - return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn -} - -function BufferBigIntNotDefined () { - throw new Error('BigInt not supported') -} - - -/***/ }), - -/***/ 7811: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; -/*! - * content-type - * Copyright(c) 2015 Douglas Christopher Wilson - * MIT Licensed - */ - - - -/** - * RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1 - * - * parameter = token "=" ( token / quoted-string ) - * token = 1*tchar - * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" - * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" - * / DIGIT / ALPHA - * ; any VCHAR, except delimiters - * quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE - * qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text - * obs-text = %x80-FF - * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) - */ -var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g -var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/ -var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ - -/** - * RegExp to match quoted-pair in RFC 7230 sec 3.2.6 - * - * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) - * obs-text = %x80-FF - */ -var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g - -/** - * RegExp to match chars that must be quoted-pair in RFC 7230 sec 3.2.6 - */ -var QUOTE_REGEXP = /([\\"])/g - -/** - * RegExp to match type in RFC 7231 sec 3.1.1.1 - * - * media-type = type "/" subtype - * type = token - * subtype = token - */ -var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ - -/** - * Module exports. - * @public - */ - -exports.format = format -exports.parse = parse - -/** - * Format object to media type. - * - * @param {object} obj - * @return {string} - * @public - */ - -function format (obj) { - if (!obj || typeof obj !== 'object') { - throw new TypeError('argument obj is required') - } - - var parameters = obj.parameters - var type = obj.type - - if (!type || !TYPE_REGEXP.test(type)) { - throw new TypeError('invalid type') - } - - var string = type - - // append parameters - if (parameters && typeof parameters === 'object') { - var param - var params = Object.keys(parameters).sort() - - for (var i = 0; i < params.length; i++) { - param = params[i] - - if (!TOKEN_REGEXP.test(param)) { - throw new TypeError('invalid parameter name') - } - - string += '; ' + param + '=' + qstring(parameters[param]) - } - } - - return string -} - -/** - * Parse media type to object. - * - * @param {string|object} string - * @return {Object} - * @public - */ - -function parse (string) { - if (!string) { - throw new TypeError('argument string is required') - } - - // support req/res-like objects as argument - var header = typeof string === 'object' - ? getcontenttype(string) - : string - - if (typeof header !== 'string') { - throw new TypeError('argument string is required to be a string') - } - - var index = header.indexOf(';') - var type = index !== -1 - ? header.substr(0, index).trim() - : header.trim() - - if (!TYPE_REGEXP.test(type)) { - throw new TypeError('invalid media type') - } - - var obj = new ContentType(type.toLowerCase()) - - // parse parameters - if (index !== -1) { - var key - var match - var value - - PARAM_REGEXP.lastIndex = index - - while ((match = PARAM_REGEXP.exec(header))) { - if (match.index !== index) { - throw new TypeError('invalid parameter format') - } - - index += match[0].length - key = match[1].toLowerCase() - value = match[2] - - if (value[0] === '"') { - // remove quotes and escapes - value = value - .substr(1, value.length - 2) - .replace(QESC_REGEXP, '$1') - } - - obj.parameters[key] = value - } - - if (index !== header.length) { - throw new TypeError('invalid parameter format') - } - } - - return obj -} - -/** - * Get content-type from req/res objects. - * - * @param {object} - * @return {Object} - * @private - */ - -function getcontenttype (obj) { - var header - - if (typeof obj.getHeader === 'function') { - // res-like - header = obj.getHeader('content-type') - } else if (typeof obj.headers === 'object') { - // req-like - header = obj.headers && obj.headers['content-type'] - } - - if (typeof header !== 'string') { - throw new TypeError('content-type header is missing from object') - } - - return header -} - -/** - * Quote a string if necessary. - * - * @param {string} val - * @return {string} - * @private - */ - -function qstring (val) { - var str = String(val) - - // no need to quote tokens - if (TOKEN_REGEXP.test(str)) { - return str - } - - if (str.length > 0 && !TEXT_REGEXP.test(str)) { - throw new TypeError('invalid parameter value') - } - - return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' -} - -/** - * Class to represent a content type. - * @private - */ -function ContentType (type) { - this.parameters = Object.create(null) - this.type = type -} - - -/***/ }), - -/***/ 1227: -/***/ ((module, exports, __webpack_require__) => { - -/* provided dependency */ var process = __webpack_require__(4155); -/* eslint-env browser */ - -/** - * This is the web browser implementation of `debug()`. - */ - -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = localstorage(); -exports.destroy = (() => { - let warned = false; - - return () => { - if (!warned) { - warned = true; - console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); - } - }; -})(); - -/** - * Colors. - */ - -exports.colors = [ - '#0000CC', - '#0000FF', - '#0033CC', - '#0033FF', - '#0066CC', - '#0066FF', - '#0099CC', - '#0099FF', - '#00CC00', - '#00CC33', - '#00CC66', - '#00CC99', - '#00CCCC', - '#00CCFF', - '#3300CC', - '#3300FF', - '#3333CC', - '#3333FF', - '#3366CC', - '#3366FF', - '#3399CC', - '#3399FF', - '#33CC00', - '#33CC33', - '#33CC66', - '#33CC99', - '#33CCCC', - '#33CCFF', - '#6600CC', - '#6600FF', - '#6633CC', - '#6633FF', - '#66CC00', - '#66CC33', - '#9900CC', - '#9900FF', - '#9933CC', - '#9933FF', - '#99CC00', - '#99CC33', - '#CC0000', - '#CC0033', - '#CC0066', - '#CC0099', - '#CC00CC', - '#CC00FF', - '#CC3300', - '#CC3333', - '#CC3366', - '#CC3399', - '#CC33CC', - '#CC33FF', - '#CC6600', - '#CC6633', - '#CC9900', - '#CC9933', - '#CCCC00', - '#CCCC33', - '#FF0000', - '#FF0033', - '#FF0066', - '#FF0099', - '#FF00CC', - '#FF00FF', - '#FF3300', - '#FF3333', - '#FF3366', - '#FF3399', - '#FF33CC', - '#FF33FF', - '#FF6600', - '#FF6633', - '#FF9900', - '#FF9933', - '#FFCC00', - '#FFCC33' -]; - -/** - * Currently only WebKit-based Web Inspectors, Firefox >= v31, - * and the Firebug extension (any Firefox version) are known - * to support "%c" CSS customizations. - * - * TODO: add a `localStorage` variable to explicitly enable/disable colors - */ - -// eslint-disable-next-line complexity -function useColors() { - // NB: In an Electron preload script, document will be defined but not fully - // initialized. Since we know we're in Chrome, we'll just detect this case - // explicitly - if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { - return true; - } - - // Internet Explorer and Edge do not support colors. - if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { - return false; - } - - // Is webkit? http://stackoverflow.com/a/16459606/376773 - // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 - return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || - // Is firebug? http://stackoverflow.com/a/398120/376773 - (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || - // Is firefox >= v31? - // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || - // Double check webkit in userAgent just in case we are in a worker - (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); -} - -/** - * Colorize log arguments if enabled. - * - * @api public - */ - -function formatArgs(args) { - args[0] = (this.useColors ? '%c' : '') + - this.namespace + - (this.useColors ? ' %c' : ' ') + - args[0] + - (this.useColors ? '%c ' : ' ') + - '+' + module.exports.humanize(this.diff); - - if (!this.useColors) { - return; - } - - const c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit'); - - // The final "%c" is somewhat tricky, because there could be other - // arguments passed either before or after the %c, so we need to - // figure out the correct index to insert the CSS into - let index = 0; - let lastC = 0; - args[0].replace(/%[a-zA-Z%]/g, match => { - if (match === '%%') { - return; - } - index++; - if (match === '%c') { - // We only are interested in the *last* %c - // (the user may have provided their own) - lastC = index; - } - }); - - args.splice(lastC, 0, c); -} - -/** - * Invokes `console.debug()` when available. - * No-op when `console.debug` is not a "function". - * If `console.debug` is not available, falls back - * to `console.log`. - * - * @api public - */ -exports.log = console.debug || console.log || (() => {}); - -/** - * Save `namespaces`. - * - * @param {String} namespaces - * @api private - */ -function save(namespaces) { - try { - if (namespaces) { - exports.storage.setItem('debug', namespaces); - } else { - exports.storage.removeItem('debug'); - } - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } -} - -/** - * Load `namespaces`. - * - * @return {String} returns the previously persisted debug modes - * @api private - */ -function load() { - let r; - try { - r = exports.storage.getItem('debug'); - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } - - // If debug isn't set in LS, and we're in Electron, try to load $DEBUG - if (!r && typeof process !== 'undefined' && 'env' in process) { - r = process.env.DEBUG; - } - - return r; -} - -/** - * Localstorage attempts to return the localstorage. - * - * This is necessary because safari throws - * when a user disables cookies/localstorage - * and you attempt to access it. - * - * @return {LocalStorage} - * @api private - */ - -function localstorage() { - try { - // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context - // The Browser also has localStorage in the global context. - return localStorage; - } catch (error) { - // Swallow - // XXX (@Qix-) should we be logging these? - } -} - -module.exports = __webpack_require__(2447)(exports); - -const {formatters} = module.exports; - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -formatters.j = function (v) { - try { - return JSON.stringify(v); - } catch (error) { - return '[UnexpectedJSONParseError]: ' + error.message; - } -}; - - -/***/ }), - -/***/ 2447: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - - -/** - * This is the common logic for both the Node.js and web browser - * implementations of `debug()`. - */ - -function setup(env) { - createDebug.debug = createDebug; - createDebug.default = createDebug; - createDebug.coerce = coerce; - createDebug.disable = disable; - createDebug.enable = enable; - createDebug.enabled = enabled; - createDebug.humanize = __webpack_require__(7824); - createDebug.destroy = destroy; - - Object.keys(env).forEach(key => { - createDebug[key] = env[key]; - }); - - /** - * The currently active debug mode names, and names to skip. - */ - - createDebug.names = []; - createDebug.skips = []; - - /** - * Map of special "%n" handling functions, for the debug "format" argument. - * - * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". - */ - createDebug.formatters = {}; - - /** - * Selects a color for a debug namespace - * @param {String} namespace The namespace string for the debug instance to be colored - * @return {Number|String} An ANSI color code for the given namespace - * @api private - */ - function selectColor(namespace) { - let hash = 0; - - for (let i = 0; i < namespace.length; i++) { - hash = ((hash << 5) - hash) + namespace.charCodeAt(i); - hash |= 0; // Convert to 32bit integer - } - - return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; - } - createDebug.selectColor = selectColor; - - /** - * Create a debugger with the given `namespace`. - * - * @param {String} namespace - * @return {Function} - * @api public - */ - function createDebug(namespace) { - let prevTime; - let enableOverride = null; - let namespacesCache; - let enabledCache; - - function debug(...args) { - // Disabled? - if (!debug.enabled) { - return; - } - - const self = debug; - - // Set `diff` timestamp - const curr = Number(new Date()); - const ms = curr - (prevTime || curr); - self.diff = ms; - self.prev = prevTime; - self.curr = curr; - prevTime = curr; - - args[0] = createDebug.coerce(args[0]); - - if (typeof args[0] !== 'string') { - // Anything else let's inspect with %O - args.unshift('%O'); - } - - // Apply any `formatters` transformations - let index = 0; - args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { - // If we encounter an escaped % then don't increase the array index - if (match === '%%') { - return '%'; - } - index++; - const formatter = createDebug.formatters[format]; - if (typeof formatter === 'function') { - const val = args[index]; - match = formatter.call(self, val); - - // Now we need to remove `args[index]` since it's inlined in the `format` - args.splice(index, 1); - index--; - } - return match; - }); - - // Apply env-specific formatting (colors, etc.) - createDebug.formatArgs.call(self, args); - - const logFn = self.log || createDebug.log; - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.useColors = createDebug.useColors(); - debug.color = createDebug.selectColor(namespace); - debug.extend = extend; - debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. - - Object.defineProperty(debug, 'enabled', { - enumerable: true, - configurable: false, - get: () => { - if (enableOverride !== null) { - return enableOverride; - } - if (namespacesCache !== createDebug.namespaces) { - namespacesCache = createDebug.namespaces; - enabledCache = createDebug.enabled(namespace); - } - - return enabledCache; - }, - set: v => { - enableOverride = v; - } - }); - - // Env-specific initialization logic for debug instances - if (typeof createDebug.init === 'function') { - createDebug.init(debug); - } - - return debug; - } - - function extend(namespace, delimiter) { - const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); - newDebug.log = this.log; - return newDebug; - } - - /** - * Enables a debug mode by namespaces. This can include modes - * separated by a colon and wildcards. - * - * @param {String} namespaces - * @api public - */ - function enable(namespaces) { - createDebug.save(namespaces); - createDebug.namespaces = namespaces; - - createDebug.names = []; - createDebug.skips = []; - - let i; - const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - const len = split.length; - - for (i = 0; i < len; i++) { - if (!split[i]) { - // ignore empty strings - continue; - } - - namespaces = split[i].replace(/\*/g, '.*?'); - - if (namespaces[0] === '-') { - createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$')); - } else { - createDebug.names.push(new RegExp('^' + namespaces + '$')); - } - } - } - - /** - * Disable debug output. - * - * @return {String} namespaces - * @api public - */ - function disable() { - const namespaces = [ - ...createDebug.names.map(toNamespace), - ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) - ].join(','); - createDebug.enable(''); - return namespaces; - } - - /** - * Returns true if the given mode name is enabled, false otherwise. - * - * @param {String} name - * @return {Boolean} - * @api public - */ - function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } - - let i; - let len; - - for (i = 0, len = createDebug.skips.length; i < len; i++) { - if (createDebug.skips[i].test(name)) { - return false; - } - } - - for (i = 0, len = createDebug.names.length; i < len; i++) { - if (createDebug.names[i].test(name)) { - return true; - } - } - - return false; - } - - /** - * Convert regexp to namespace - * - * @param {RegExp} regxep - * @return {String} namespace - * @api private - */ - function toNamespace(regexp) { - return regexp.toString() - .substring(2, regexp.toString().length - 2) - .replace(/\.\*\?$/, '*'); - } - - /** - * Coerce `val`. - * - * @param {Mixed} val - * @return {Mixed} - * @api private - */ - function coerce(val) { - if (val instanceof Error) { - return val.stack || val.message; - } - return val; - } - - /** - * XXX DO NOT USE. This is a temporary stub function. - * XXX It WILL be removed in the next major release. - */ - function destroy() { - console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); - } - - createDebug.enable(createDebug.load()); - - return createDebug; -} - -module.exports = setup; - - -/***/ }), - -/***/ 7187: -/***/ ((module) => { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -var R = typeof Reflect === 'object' ? Reflect : null -var ReflectApply = R && typeof R.apply === 'function' - ? R.apply - : function ReflectApply(target, receiver, args) { - return Function.prototype.apply.call(target, receiver, args); - } - -var ReflectOwnKeys -if (R && typeof R.ownKeys === 'function') { - ReflectOwnKeys = R.ownKeys -} else if (Object.getOwnPropertySymbols) { - ReflectOwnKeys = function ReflectOwnKeys(target) { - return Object.getOwnPropertyNames(target) - .concat(Object.getOwnPropertySymbols(target)); - }; -} else { - ReflectOwnKeys = function ReflectOwnKeys(target) { - return Object.getOwnPropertyNames(target); - }; -} - -function ProcessEmitWarning(warning) { - if (console && console.warn) console.warn(warning); -} - -var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { - return value !== value; -} - -function EventEmitter() { - EventEmitter.init.call(this); -} -module.exports = EventEmitter; -module.exports.once = once; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._eventsCount = 0; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -var defaultMaxListeners = 10; - -function checkListener(listener) { - if (typeof listener !== 'function') { - throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); - } -} - -Object.defineProperty(EventEmitter, 'defaultMaxListeners', { - enumerable: true, - get: function() { - return defaultMaxListeners; - }, - set: function(arg) { - if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { - throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); - } - defaultMaxListeners = arg; - } -}); - -EventEmitter.init = function() { - - if (this._events === undefined || - this._events === Object.getPrototypeOf(this)._events) { - this._events = Object.create(null); - this._eventsCount = 0; - } - - this._maxListeners = this._maxListeners || undefined; -}; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { - if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { - throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); - } - this._maxListeners = n; - return this; -}; - -function _getMaxListeners(that) { - if (that._maxListeners === undefined) - return EventEmitter.defaultMaxListeners; - return that._maxListeners; -} - -EventEmitter.prototype.getMaxListeners = function getMaxListeners() { - return _getMaxListeners(this); -}; - -EventEmitter.prototype.emit = function emit(type) { - var args = []; - for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); - var doError = (type === 'error'); - - var events = this._events; - if (events !== undefined) - doError = (doError && events.error === undefined); - else if (!doError) - return false; - - // If there is no 'error' event listener then throw. - if (doError) { - var er; - if (args.length > 0) - er = args[0]; - if (er instanceof Error) { - // Note: The comments on the `throw` lines are intentional, they show - // up in Node's output if this results in an unhandled exception. - throw er; // Unhandled 'error' event - } - // At least give some kind of context to the user - var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); - err.context = er; - throw err; // Unhandled 'error' event - } - - var handler = events[type]; - - if (handler === undefined) - return false; - - if (typeof handler === 'function') { - ReflectApply(handler, this, args); - } else { - var len = handler.length; - var listeners = arrayClone(handler, len); - for (var i = 0; i < len; ++i) - ReflectApply(listeners[i], this, args); - } - - return true; -}; - -function _addListener(target, type, listener, prepend) { - var m; - var events; - var existing; - - checkListener(listener); - - events = target._events; - if (events === undefined) { - events = target._events = Object.create(null); - target._eventsCount = 0; - } else { - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (events.newListener !== undefined) { - target.emit('newListener', type, - listener.listener ? listener.listener : listener); - - // Re-assign `events` because a newListener handler could have caused the - // this._events to be assigned to a new object - events = target._events; - } - existing = events[type]; - } - - if (existing === undefined) { - // Optimize the case of one listener. Don't need the extra array object. - existing = events[type] = listener; - ++target._eventsCount; - } else { - if (typeof existing === 'function') { - // Adding the second element, need to change to array. - existing = events[type] = - prepend ? [listener, existing] : [existing, listener]; - // If we've already got an array, just append. - } else if (prepend) { - existing.unshift(listener); - } else { - existing.push(listener); - } - - // Check for listener leak - m = _getMaxListeners(target); - if (m > 0 && existing.length > m && !existing.warned) { - existing.warned = true; - // No error code for this since it is a Warning - // eslint-disable-next-line no-restricted-syntax - var w = new Error('Possible EventEmitter memory leak detected. ' + - existing.length + ' ' + String(type) + ' listeners ' + - 'added. Use emitter.setMaxListeners() to ' + - 'increase limit'); - w.name = 'MaxListenersExceededWarning'; - w.emitter = target; - w.type = type; - w.count = existing.length; - ProcessEmitWarning(w); - } - } - - return target; -} - -EventEmitter.prototype.addListener = function addListener(type, listener) { - return _addListener(this, type, listener, false); -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.prependListener = - function prependListener(type, listener) { - return _addListener(this, type, listener, true); - }; - -function onceWrapper() { - if (!this.fired) { - this.target.removeListener(this.type, this.wrapFn); - this.fired = true; - if (arguments.length === 0) - return this.listener.call(this.target); - return this.listener.apply(this.target, arguments); - } -} - -function _onceWrap(target, type, listener) { - var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; - var wrapped = onceWrapper.bind(state); - wrapped.listener = listener; - state.wrapFn = wrapped; - return wrapped; -} - -EventEmitter.prototype.once = function once(type, listener) { - checkListener(listener); - this.on(type, _onceWrap(this, type, listener)); - return this; -}; - -EventEmitter.prototype.prependOnceListener = - function prependOnceListener(type, listener) { - checkListener(listener); - this.prependListener(type, _onceWrap(this, type, listener)); - return this; - }; - -// Emits a 'removeListener' event if and only if the listener was removed. -EventEmitter.prototype.removeListener = - function removeListener(type, listener) { - var list, events, position, i, originalListener; - - checkListener(listener); - - events = this._events; - if (events === undefined) - return this; - - list = events[type]; - if (list === undefined) - return this; - - if (list === listener || list.listener === listener) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else { - delete events[type]; - if (events.removeListener) - this.emit('removeListener', type, list.listener || listener); - } - } else if (typeof list !== 'function') { - position = -1; - - for (i = list.length - 1; i >= 0; i--) { - if (list[i] === listener || list[i].listener === listener) { - originalListener = list[i].listener; - position = i; - break; - } - } - - if (position < 0) - return this; - - if (position === 0) - list.shift(); - else { - spliceOne(list, position); - } - - if (list.length === 1) - events[type] = list[0]; - - if (events.removeListener !== undefined) - this.emit('removeListener', type, originalListener || listener); - } - - return this; - }; - -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; - -EventEmitter.prototype.removeAllListeners = - function removeAllListeners(type) { - var listeners, events, i; - - events = this._events; - if (events === undefined) - return this; - - // not listening for removeListener, no need to emit - if (events.removeListener === undefined) { - if (arguments.length === 0) { - this._events = Object.create(null); - this._eventsCount = 0; - } else if (events[type] !== undefined) { - if (--this._eventsCount === 0) - this._events = Object.create(null); - else - delete events[type]; - } - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - var keys = Object.keys(events); - var key; - for (i = 0; i < keys.length; ++i) { - key = keys[i]; - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = Object.create(null); - this._eventsCount = 0; - return this; - } - - listeners = events[type]; - - if (typeof listeners === 'function') { - this.removeListener(type, listeners); - } else if (listeners !== undefined) { - // LIFO order - for (i = listeners.length - 1; i >= 0; i--) { - this.removeListener(type, listeners[i]); - } - } - - return this; - }; - -function _listeners(target, type, unwrap) { - var events = target._events; - - if (events === undefined) - return []; - - var evlistener = events[type]; - if (evlistener === undefined) - return []; - - if (typeof evlistener === 'function') - return unwrap ? [evlistener.listener || evlistener] : [evlistener]; - - return unwrap ? - unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); -} - -EventEmitter.prototype.listeners = function listeners(type) { - return _listeners(this, type, true); -}; - -EventEmitter.prototype.rawListeners = function rawListeners(type) { - return _listeners(this, type, false); -}; - -EventEmitter.listenerCount = function(emitter, type) { - if (typeof emitter.listenerCount === 'function') { - return emitter.listenerCount(type); - } else { - return listenerCount.call(emitter, type); - } -}; - -EventEmitter.prototype.listenerCount = listenerCount; -function listenerCount(type) { - var events = this._events; - - if (events !== undefined) { - var evlistener = events[type]; - - if (typeof evlistener === 'function') { - return 1; - } else if (evlistener !== undefined) { - return evlistener.length; - } - } - - return 0; -} - -EventEmitter.prototype.eventNames = function eventNames() { - return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; -}; - -function arrayClone(arr, n) { - var copy = new Array(n); - for (var i = 0; i < n; ++i) - copy[i] = arr[i]; - return copy; -} - -function spliceOne(list, index) { - for (; index + 1 < list.length; index++) - list[index] = list[index + 1]; - list.pop(); -} - -function unwrapListeners(arr) { - var ret = new Array(arr.length); - for (var i = 0; i < ret.length; ++i) { - ret[i] = arr[i].listener || arr[i]; - } - return ret; -} - -function once(emitter, name) { - return new Promise(function (resolve, reject) { - function errorListener(err) { - emitter.removeListener(name, resolver); - reject(err); - } - - function resolver() { - if (typeof emitter.removeListener === 'function') { - emitter.removeListener('error', errorListener); - } - resolve([].slice.call(arguments)); - }; - - eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); - if (name !== 'error') { - addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); - } - }); -} - -function addErrorHandlerIfEventEmitter(emitter, handler, flags) { - if (typeof emitter.on === 'function') { - eventTargetAgnosticAddListener(emitter, 'error', handler, flags); - } -} - -function eventTargetAgnosticAddListener(emitter, name, listener, flags) { - if (typeof emitter.on === 'function') { - if (flags.once) { - emitter.once(name, listener); - } else { - emitter.on(name, listener); - } - } else if (typeof emitter.addEventListener === 'function') { - // EventTarget does not have `error` event semantics like Node - // EventEmitters, we do not listen for `error` events here. - emitter.addEventListener(name, function wrapListener(arg) { - // IE does not have builtin `{ once: true }` support so we - // have to do it manually. - if (flags.once) { - emitter.removeEventListener(name, wrapListener); - } - listener(arg); - }); - } else { - throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); - } -} - - -/***/ }), - -/***/ 1: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -const Token = __webpack_require__(3416); -const strtok3 = __webpack_require__(5849); -const { - stringToBytes, - tarHeaderChecksumMatches, - uint32SyncSafeToken -} = __webpack_require__(6188); -const supported = __webpack_require__(9898); - -const minimumBytes = 4100; // A fair amount of file-types are detectable within this range - -async function fromStream(stream) { - const tokenizer = await strtok3.fromStream(stream); - try { - return await fromTokenizer(tokenizer); - } finally { - await tokenizer.close(); - } -} - -async function fromBuffer(input) { - if (!(input instanceof Uint8Array || input instanceof ArrayBuffer || Buffer.isBuffer(input))) { - throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`Buffer\` or \`ArrayBuffer\`, got \`${typeof input}\``); - } - - const buffer = input instanceof Buffer ? input : Buffer.from(input); - - if (!(buffer && buffer.length > 1)) { - return; - } - - const tokenizer = strtok3.fromBuffer(buffer); - return fromTokenizer(tokenizer); -} - -function _check(buffer, headers, options) { - options = { - offset: 0, - ...options - }; - - for (const [index, header] of headers.entries()) { - // If a bitmask is set - if (options.mask) { - // If header doesn't equal `buf` with bits masked off - if (header !== (options.mask[index] & buffer[index + options.offset])) { - return false; - } - } else if (header !== buffer[index + options.offset]) { - return false; - } - } - - return true; -} - -async function fromTokenizer(tokenizer) { - try { - return _fromTokenizer(tokenizer); - } catch (error) { - if (!(error instanceof strtok3.EndOfStreamError)) { - throw error; - } - } -} - -async function _fromTokenizer(tokenizer) { - let buffer = Buffer.alloc(minimumBytes); - const bytesRead = 12; - const check = (header, options) => _check(buffer, header, options); - const checkString = (header, options) => check(stringToBytes(header), options); - - // Keep reading until EOF if the file size is unknown. - if (!tokenizer.fileInfo.size) { - tokenizer.fileInfo.size = Number.MAX_SAFE_INTEGER; - } - - await tokenizer.peekBuffer(buffer, {length: bytesRead, mayBeLess: true}); - - // -- 2-byte signatures -- - - if (check([0x42, 0x4D])) { - return { - ext: 'bmp', - mime: 'image/bmp' - }; - } - - if (check([0x0B, 0x77])) { - return { - ext: 'ac3', - mime: 'audio/vnd.dolby.dd-raw' - }; - } - - if (check([0x78, 0x01])) { - return { - ext: 'dmg', - mime: 'application/x-apple-diskimage' - }; - } - - if (check([0x4D, 0x5A])) { - return { - ext: 'exe', - mime: 'application/x-msdownload' - }; - } - - if (check([0x25, 0x21])) { - await tokenizer.peekBuffer(buffer, {length: 24, mayBeLess: true}); - - if (checkString('PS-Adobe-', {offset: 2}) && - checkString(' EPSF-', {offset: 14})) { - return { - ext: 'eps', - mime: 'application/eps' - }; - } - - return { - ext: 'ps', - mime: 'application/postscript' - }; - } - - if ( - check([0x1F, 0xA0]) || - check([0x1F, 0x9D]) - ) { - return { - ext: 'Z', - mime: 'application/x-compress' - }; - } - - // -- 3-byte signatures -- - - if (check([0xFF, 0xD8, 0xFF])) { - return { - ext: 'jpg', - mime: 'image/jpeg' - }; - } - - if (check([0x49, 0x49, 0xBC])) { - return { - ext: 'jxr', - mime: 'image/vnd.ms-photo' - }; - } - - if (check([0x1F, 0x8B, 0x8])) { - return { - ext: 'gz', - mime: 'application/gzip' - }; - } - - if (check([0x42, 0x5A, 0x68])) { - return { - ext: 'bz2', - mime: 'application/x-bzip2' - }; - } - - if (checkString('ID3')) { - await tokenizer.ignore(6); // Skip ID3 header until the header size - const id3HeaderLen = await tokenizer.readToken(uint32SyncSafeToken); - if (tokenizer.position + id3HeaderLen > tokenizer.fileInfo.size) { - // Guess file type based on ID3 header for backward compatibility - return { - ext: 'mp3', - mime: 'audio/mpeg' - }; - } - - await tokenizer.ignore(id3HeaderLen); - return fromTokenizer(tokenizer); // Skip ID3 header, recursion - } - - // Musepack, SV7 - if (checkString('MP+')) { - return { - ext: 'mpc', - mime: 'audio/x-musepack' - }; - } - - if ( - (buffer[0] === 0x43 || buffer[0] === 0x46) && - check([0x57, 0x53], {offset: 1}) - ) { - return { - ext: 'swf', - mime: 'application/x-shockwave-flash' - }; - } - - // -- 4-byte signatures -- - - if (check([0x47, 0x49, 0x46])) { - return { - ext: 'gif', - mime: 'image/gif' - }; - } - - if (checkString('FLIF')) { - return { - ext: 'flif', - mime: 'image/flif' - }; - } - - if (checkString('8BPS')) { - return { - ext: 'psd', - mime: 'image/vnd.adobe.photoshop' - }; - } - - if (checkString('WEBP', {offset: 8})) { - return { - ext: 'webp', - mime: 'image/webp' - }; - } - - // Musepack, SV8 - if (checkString('MPCK')) { - return { - ext: 'mpc', - mime: 'audio/x-musepack' - }; - } - - if (checkString('FORM')) { - return { - ext: 'aif', - mime: 'audio/aiff' - }; - } - - if (checkString('icns', {offset: 0})) { - return { - ext: 'icns', - mime: 'image/icns' - }; - } - - // Zip-based file formats - // Need to be before the `zip` check - if (check([0x50, 0x4B, 0x3, 0x4])) { // Local file header signature - try { - while (tokenizer.position + 30 < tokenizer.fileInfo.size) { - await tokenizer.readBuffer(buffer, {length: 30}); - - // https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers - const zipHeader = { - compressedSize: buffer.readUInt32LE(18), - uncompressedSize: buffer.readUInt32LE(22), - filenameLength: buffer.readUInt16LE(26), - extraFieldLength: buffer.readUInt16LE(28) - }; - - zipHeader.filename = await tokenizer.readToken(new Token.StringType(zipHeader.filenameLength, 'utf-8')); - await tokenizer.ignore(zipHeader.extraFieldLength); - - // Assumes signed `.xpi` from addons.mozilla.org - if (zipHeader.filename === 'META-INF/mozilla.rsa') { - return { - ext: 'xpi', - mime: 'application/x-xpinstall' - }; - } - - if (zipHeader.filename.endsWith('.rels') || zipHeader.filename.endsWith('.xml')) { - const type = zipHeader.filename.split('/')[0]; - switch (type) { - case '_rels': - break; - case 'word': - return { - ext: 'docx', - mime: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - }; - case 'ppt': - return { - ext: 'pptx', - mime: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' - }; - case 'xl': - return { - ext: 'xlsx', - mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - }; - default: - break; - } - } - - if (zipHeader.filename.startsWith('xl/')) { - return { - ext: 'xlsx', - mime: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - }; - } - - if (zipHeader.filename.startsWith('3D/') && zipHeader.filename.endsWith('.model')) { - return { - ext: '3mf', - mime: 'model/3mf' - }; - } - - // The docx, xlsx and pptx file types extend the Office Open XML file format: - // https://en.wikipedia.org/wiki/Office_Open_XML_file_formats - // We look for: - // - one entry named '[Content_Types].xml' or '_rels/.rels', - // - one entry indicating specific type of file. - // MS Office, OpenOffice and LibreOffice may put the parts in different order, so the check should not rely on it. - if (zipHeader.filename === 'mimetype' && zipHeader.compressedSize === zipHeader.uncompressedSize) { - const mimeType = await tokenizer.readToken(new Token.StringType(zipHeader.compressedSize, 'utf-8')); - - switch (mimeType) { - case 'application/epub+zip': - return { - ext: 'epub', - mime: 'application/epub+zip' - }; - case 'application/vnd.oasis.opendocument.text': - return { - ext: 'odt', - mime: 'application/vnd.oasis.opendocument.text' - }; - case 'application/vnd.oasis.opendocument.spreadsheet': - return { - ext: 'ods', - mime: 'application/vnd.oasis.opendocument.spreadsheet' - }; - case 'application/vnd.oasis.opendocument.presentation': - return { - ext: 'odp', - mime: 'application/vnd.oasis.opendocument.presentation' - }; - default: - } - } - - // Try to find next header manually when current one is corrupted - if (zipHeader.compressedSize === 0) { - let nextHeaderIndex = -1; - - while (nextHeaderIndex < 0 && (tokenizer.position < tokenizer.fileInfo.size)) { - await tokenizer.peekBuffer(buffer, {mayBeLess: true}); - - nextHeaderIndex = buffer.indexOf('504B0304', 0, 'hex'); - // Move position to the next header if found, skip the whole buffer otherwise - await tokenizer.ignore(nextHeaderIndex >= 0 ? nextHeaderIndex : buffer.length); - } - } else { - await tokenizer.ignore(zipHeader.compressedSize); - } - } - } catch (error) { - if (!(error instanceof strtok3.EndOfStreamError)) { - throw error; - } - } - - return { - ext: 'zip', - mime: 'application/zip' - }; - } - - if (checkString('OggS')) { - // This is an OGG container - await tokenizer.ignore(28); - const type = Buffer.alloc(8); - await tokenizer.readBuffer(type); - - // Needs to be before `ogg` check - if (_check(type, [0x4F, 0x70, 0x75, 0x73, 0x48, 0x65, 0x61, 0x64])) { - return { - ext: 'opus', - mime: 'audio/opus' - }; - } - - // If ' theora' in header. - if (_check(type, [0x80, 0x74, 0x68, 0x65, 0x6F, 0x72, 0x61])) { - return { - ext: 'ogv', - mime: 'video/ogg' - }; - } - - // If '\x01video' in header. - if (_check(type, [0x01, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x00])) { - return { - ext: 'ogm', - mime: 'video/ogg' - }; - } - - // If ' FLAC' in header https://xiph.org/flac/faq.html - if (_check(type, [0x7F, 0x46, 0x4C, 0x41, 0x43])) { - return { - ext: 'oga', - mime: 'audio/ogg' - }; - } - - // 'Speex ' in header https://en.wikipedia.org/wiki/Speex - if (_check(type, [0x53, 0x70, 0x65, 0x65, 0x78, 0x20, 0x20])) { - return { - ext: 'spx', - mime: 'audio/ogg' - }; - } - - // If '\x01vorbis' in header - if (_check(type, [0x01, 0x76, 0x6F, 0x72, 0x62, 0x69, 0x73])) { - return { - ext: 'ogg', - mime: 'audio/ogg' - }; - } - - // Default OGG container https://www.iana.org/assignments/media-types/application/ogg - return { - ext: 'ogx', - mime: 'application/ogg' - }; - } - - if ( - check([0x50, 0x4B]) && - (buffer[2] === 0x3 || buffer[2] === 0x5 || buffer[2] === 0x7) && - (buffer[3] === 0x4 || buffer[3] === 0x6 || buffer[3] === 0x8) - ) { - return { - ext: 'zip', - mime: 'application/zip' - }; - } - - // - - // File Type Box (https://en.wikipedia.org/wiki/ISO_base_media_file_format) - // It's not required to be first, but it's recommended to be. Almost all ISO base media files start with `ftyp` box. - // `ftyp` box must contain a brand major identifier, which must consist of ISO 8859-1 printable characters. - // Here we check for 8859-1 printable characters (for simplicity, it's a mask which also catches one non-printable character). - if ( - checkString('ftyp', {offset: 4}) && - (buffer[8] & 0x60) !== 0x00 // Brand major, first character ASCII? - ) { - // They all can have MIME `video/mp4` except `application/mp4` special-case which is hard to detect. - // For some cases, we're specific, everything else falls to `video/mp4` with `mp4` extension. - const brandMajor = buffer.toString('binary', 8, 12).replace('\0', ' ').trim(); - switch (brandMajor) { - case 'avif': - return {ext: 'avif', mime: 'image/avif'}; - case 'mif1': - return {ext: 'heic', mime: 'image/heif'}; - case 'msf1': - return {ext: 'heic', mime: 'image/heif-sequence'}; - case 'heic': - case 'heix': - return {ext: 'heic', mime: 'image/heic'}; - case 'hevc': - case 'hevx': - return {ext: 'heic', mime: 'image/heic-sequence'}; - case 'qt': - return {ext: 'mov', mime: 'video/quicktime'}; - case 'M4V': - case 'M4VH': - case 'M4VP': - return {ext: 'm4v', mime: 'video/x-m4v'}; - case 'M4P': - return {ext: 'm4p', mime: 'video/mp4'}; - case 'M4B': - return {ext: 'm4b', mime: 'audio/mp4'}; - case 'M4A': - return {ext: 'm4a', mime: 'audio/x-m4a'}; - case 'F4V': - return {ext: 'f4v', mime: 'video/mp4'}; - case 'F4P': - return {ext: 'f4p', mime: 'video/mp4'}; - case 'F4A': - return {ext: 'f4a', mime: 'audio/mp4'}; - case 'F4B': - return {ext: 'f4b', mime: 'audio/mp4'}; - case 'crx': - return {ext: 'cr3', mime: 'image/x-canon-cr3'}; - default: - if (brandMajor.startsWith('3g')) { - if (brandMajor.startsWith('3g2')) { - return {ext: '3g2', mime: 'video/3gpp2'}; - } - - return {ext: '3gp', mime: 'video/3gpp'}; - } - - return {ext: 'mp4', mime: 'video/mp4'}; - } - } - - if (checkString('MThd')) { - return { - ext: 'mid', - mime: 'audio/midi' - }; - } - - if ( - checkString('wOFF') && - ( - check([0x00, 0x01, 0x00, 0x00], {offset: 4}) || - checkString('OTTO', {offset: 4}) - ) - ) { - return { - ext: 'woff', - mime: 'font/woff' - }; - } - - if ( - checkString('wOF2') && - ( - check([0x00, 0x01, 0x00, 0x00], {offset: 4}) || - checkString('OTTO', {offset: 4}) - ) - ) { - return { - ext: 'woff2', - mime: 'font/woff2' - }; - } - - if (check([0xD4, 0xC3, 0xB2, 0xA1]) || check([0xA1, 0xB2, 0xC3, 0xD4])) { - return { - ext: 'pcap', - mime: 'application/vnd.tcpdump.pcap' - }; - } - - // Sony DSD Stream File (DSF) - if (checkString('DSD ')) { - return { - ext: 'dsf', - mime: 'audio/x-dsf' // Non-standard - }; - } - - if (checkString('LZIP')) { - return { - ext: 'lz', - mime: 'application/x-lzip' - }; - } - - if (checkString('fLaC')) { - return { - ext: 'flac', - mime: 'audio/x-flac' - }; - } - - if (check([0x42, 0x50, 0x47, 0xFB])) { - return { - ext: 'bpg', - mime: 'image/bpg' - }; - } - - if (checkString('wvpk')) { - return { - ext: 'wv', - mime: 'audio/wavpack' - }; - } - - if (checkString('%PDF')) { - await tokenizer.ignore(1350); - const maxBufferSize = 10 * 1024 * 1024; - const buffer = Buffer.alloc(Math.min(maxBufferSize, tokenizer.fileInfo.size)); - await tokenizer.readBuffer(buffer, {mayBeLess: true}); - - // Check if this is an Adobe Illustrator file - if (buffer.includes(Buffer.from('AIPrivateData'))) { - return { - ext: 'ai', - mime: 'application/postscript' - }; - } - - // Assume this is just a normal PDF - return { - ext: 'pdf', - mime: 'application/pdf' - }; - } - - if (check([0x00, 0x61, 0x73, 0x6D])) { - return { - ext: 'wasm', - mime: 'application/wasm' - }; - } - - // TIFF, little-endian type - if (check([0x49, 0x49, 0x2A, 0x0])) { - if (checkString('CR', {offset: 8})) { - return { - ext: 'cr2', - mime: 'image/x-canon-cr2' - }; - } - - if (check([0x1C, 0x00, 0xFE, 0x00], {offset: 8}) || check([0x1F, 0x00, 0x0B, 0x00], {offset: 8})) { - return { - ext: 'nef', - mime: 'image/x-nikon-nef' - }; - } - - if ( - check([0x08, 0x00, 0x00, 0x00], {offset: 4}) && - (check([0x2D, 0x00, 0xFE, 0x00], {offset: 8}) || - check([0x27, 0x00, 0xFE, 0x00], {offset: 8})) - ) { - return { - ext: 'dng', - mime: 'image/x-adobe-dng' - }; - } - - buffer = Buffer.alloc(24); - await tokenizer.peekBuffer(buffer); - if ( - (check([0x10, 0xFB, 0x86, 0x01], {offset: 4}) || check([0x08, 0x00, 0x00, 0x00], {offset: 4})) && - // This pattern differentiates ARW from other TIFF-ish file types: - check([0x00, 0xFE, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x01], {offset: 9}) - ) { - return { - ext: 'arw', - mime: 'image/x-sony-arw' - }; - } - - return { - ext: 'tif', - mime: 'image/tiff' - }; - } - - // TIFF, big-endian type - if (check([0x4D, 0x4D, 0x0, 0x2A])) { - return { - ext: 'tif', - mime: 'image/tiff' - }; - } - - if (checkString('MAC ')) { - return { - ext: 'ape', - mime: 'audio/ape' - }; - } - - // https://github.com/threatstack/libmagic/blob/master/magic/Magdir/matroska - if (check([0x1A, 0x45, 0xDF, 0xA3])) { // Root element: EBML - async function readField() { - const msb = await tokenizer.peekNumber(Token.UINT8); - let mask = 0x80; - let ic = 0; // 0 = A, 1 = B, 2 = C, 3 = D - - while ((msb & mask) === 0) { - ++ic; - mask >>= 1; - } - - const id = Buffer.alloc(ic + 1); - await tokenizer.readBuffer(id); - return id; - } - - async function readElement() { - const id = await readField(); - const lenField = await readField(); - lenField[0] ^= 0x80 >> (lenField.length - 1); - const nrLen = Math.min(6, lenField.length); // JavaScript can max read 6 bytes integer - return { - id: id.readUIntBE(0, id.length), - len: lenField.readUIntBE(lenField.length - nrLen, nrLen) - }; - } - - async function readChildren(level, children) { - while (children > 0) { - const e = await readElement(); - if (e.id === 0x4282) { - return tokenizer.readToken(new Token.StringType(e.len, 'utf-8')); // Return DocType - } - - await tokenizer.ignore(e.len); // ignore payload - --children; - } - } - - const re = await readElement(); - const docType = await readChildren(1, re.len); - - switch (docType) { - case 'webm': - return { - ext: 'webm', - mime: 'video/webm' - }; - - case 'matroska': - return { - ext: 'mkv', - mime: 'video/x-matroska' - }; - - default: - return; - } - } - - // RIFF file format which might be AVI, WAV, QCP, etc - if (check([0x52, 0x49, 0x46, 0x46])) { - if (check([0x41, 0x56, 0x49], {offset: 8})) { - return { - ext: 'avi', - mime: 'video/vnd.avi' - }; - } - - if (check([0x57, 0x41, 0x56, 0x45], {offset: 8})) { - return { - ext: 'wav', - mime: 'audio/vnd.wave' - }; - } - - // QLCM, QCP file - if (check([0x51, 0x4C, 0x43, 0x4D], {offset: 8})) { - return { - ext: 'qcp', - mime: 'audio/qcelp' - }; - } - } - - if (checkString('SQLi')) { - return { - ext: 'sqlite', - mime: 'application/x-sqlite3' - }; - } - - if (check([0x4E, 0x45, 0x53, 0x1A])) { - return { - ext: 'nes', - mime: 'application/x-nintendo-nes-rom' - }; - } - - if (checkString('Cr24')) { - return { - ext: 'crx', - mime: 'application/x-google-chrome-extension' - }; - } - - if ( - checkString('MSCF') || - checkString('ISc(') - ) { - return { - ext: 'cab', - mime: 'application/vnd.ms-cab-compressed' - }; - } - - if (check([0xED, 0xAB, 0xEE, 0xDB])) { - return { - ext: 'rpm', - mime: 'application/x-rpm' - }; - } - - if (check([0xC5, 0xD0, 0xD3, 0xC6])) { - return { - ext: 'eps', - mime: 'application/eps' - }; - } - - if (check([0x28, 0xB5, 0x2F, 0xFD])) { - return { - ext: 'zst', - mime: 'application/zstd' - }; - } - - // -- 5-byte signatures -- - - if (check([0x4F, 0x54, 0x54, 0x4F, 0x00])) { - return { - ext: 'otf', - mime: 'font/otf' - }; - } - - if (checkString('#!AMR')) { - return { - ext: 'amr', - mime: 'audio/amr' - }; - } - - if (checkString('{\\rtf')) { - return { - ext: 'rtf', - mime: 'application/rtf' - }; - } - - if (check([0x46, 0x4C, 0x56, 0x01])) { - return { - ext: 'flv', - mime: 'video/x-flv' - }; - } - - if (checkString('IMPM')) { - return { - ext: 'it', - mime: 'audio/x-it' - }; - } - - if ( - checkString('-lh0-', {offset: 2}) || - checkString('-lh1-', {offset: 2}) || - checkString('-lh2-', {offset: 2}) || - checkString('-lh3-', {offset: 2}) || - checkString('-lh4-', {offset: 2}) || - checkString('-lh5-', {offset: 2}) || - checkString('-lh6-', {offset: 2}) || - checkString('-lh7-', {offset: 2}) || - checkString('-lzs-', {offset: 2}) || - checkString('-lz4-', {offset: 2}) || - checkString('-lz5-', {offset: 2}) || - checkString('-lhd-', {offset: 2}) - ) { - return { - ext: 'lzh', - mime: 'application/x-lzh-compressed' - }; - } - - // MPEG program stream (PS or MPEG-PS) - if (check([0x00, 0x00, 0x01, 0xBA])) { - // MPEG-PS, MPEG-1 Part 1 - if (check([0x21], {offset: 4, mask: [0xF1]})) { - return { - ext: 'mpg', // May also be .ps, .mpeg - mime: 'video/MP1S' - }; - } - - // MPEG-PS, MPEG-2 Part 1 - if (check([0x44], {offset: 4, mask: [0xC4]})) { - return { - ext: 'mpg', // May also be .mpg, .m2p, .vob or .sub - mime: 'video/MP2P' - }; - } - } - - if (checkString('ITSF')) { - return { - ext: 'chm', - mime: 'application/vnd.ms-htmlhelp' - }; - } - - // -- 6-byte signatures -- - - if (check([0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00])) { - return { - ext: 'xz', - mime: 'application/x-xz' - }; - } - - if (checkString('')) { - await tokenizer.ignore(8); - const str = await tokenizer.readToken(new Token.StringType(13, 'ascii')); - if (str === 'debian-binary') { - return { - ext: 'deb', - mime: 'application/x-deb' - }; - } - - return { - ext: 'ar', - mime: 'application/x-unix-archive' - }; - } - - // -- 8-byte signatures -- - - if (check([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])) { - // APNG format (https://wiki.mozilla.org/APNG_Specification) - // 1. Find the first IDAT (image data) chunk (49 44 41 54) - // 2. Check if there is an "acTL" chunk before the IDAT one (61 63 54 4C) - - // Offset calculated as follows: - // - 8 bytes: PNG signature - // - 4 (length) + 4 (chunk type) + 13 (chunk data) + 4 (CRC): IHDR chunk - - await tokenizer.ignore(8); // ignore PNG signature - - async function readChunkHeader() { - return { - length: await tokenizer.readToken(Token.INT32_BE), - type: await tokenizer.readToken(new Token.StringType(4, 'binary')) - }; - } - - do { - const chunk = await readChunkHeader(); - if (chunk.length < 0) { - return; // Invalid chunk length - } - - switch (chunk.type) { - case 'IDAT': - return { - ext: 'png', - mime: 'image/png' - }; - case 'acTL': - return { - ext: 'apng', - mime: 'image/apng' - }; - default: - await tokenizer.ignore(chunk.length + 4); // Ignore chunk-data + CRC - } - } while (tokenizer.position + 8 < tokenizer.fileInfo.size); - - return { - ext: 'png', - mime: 'image/png' - }; - } - - if (check([0x41, 0x52, 0x52, 0x4F, 0x57, 0x31, 0x00, 0x00])) { - return { - ext: 'arrow', - mime: 'application/x-apache-arrow' - }; - } - - if (check([0x67, 0x6C, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00])) { - return { - ext: 'glb', - mime: 'model/gltf-binary' - }; - } - - // `mov` format variants - if ( - check([0x66, 0x72, 0x65, 0x65], {offset: 4}) || // `free` - check([0x6D, 0x64, 0x61, 0x74], {offset: 4}) || // `mdat` MJPEG - check([0x6D, 0x6F, 0x6F, 0x76], {offset: 4}) || // `moov` - check([0x77, 0x69, 0x64, 0x65], {offset: 4}) // `wide` - ) { - return { - ext: 'mov', - mime: 'video/quicktime' - }; - } - - // -- 9-byte signatures -- - - if (check([0x49, 0x49, 0x52, 0x4F, 0x08, 0x00, 0x00, 0x00, 0x18])) { - return { - ext: 'orf', - mime: 'image/x-olympus-orf' - }; - } - - if (checkString('gimp xcf ')) { - return { - ext: 'xcf', - mime: 'image/x-xcf' - }; - } - - // -- 12-byte signatures -- - - if (check([0x49, 0x49, 0x55, 0x00, 0x18, 0x00, 0x00, 0x00, 0x88, 0xE7, 0x74, 0xD8])) { - return { - ext: 'rw2', - mime: 'image/x-panasonic-rw2' - }; - } - - // ASF_Header_Object first 80 bytes - if (check([0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9])) { - async function readHeader() { - const guid = Buffer.alloc(16); - await tokenizer.readBuffer(guid); - return { - id: guid, - size: Number(await tokenizer.readToken(Token.UINT64_LE)) - }; - } - - await tokenizer.ignore(30); - // Search for header should be in first 1KB of file. - while (tokenizer.position + 24 < tokenizer.fileInfo.size) { - const header = await readHeader(); - let payload = header.size - 24; - if (_check(header.id, [0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65])) { - // Sync on Stream-Properties-Object (B7DC0791-A9B7-11CF-8EE6-00C00C205365) - const typeId = Buffer.alloc(16); - payload -= await tokenizer.readBuffer(typeId); - - if (_check(typeId, [0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B])) { - // Found audio: - return { - ext: 'asf', - mime: 'audio/x-ms-asf' - }; - } - - if (_check(typeId, [0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B])) { - // Found video: - return { - ext: 'asf', - mime: 'video/x-ms-asf' - }; - } - - break; - } - - await tokenizer.ignore(payload); - } - - // Default to ASF generic extension - return { - ext: 'asf', - mime: 'application/vnd.ms-asf' - }; - } - - if (check([0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A])) { - return { - ext: 'ktx', - mime: 'image/ktx' - }; - } - - if ((check([0x7E, 0x10, 0x04]) || check([0x7E, 0x18, 0x04])) && check([0x30, 0x4D, 0x49, 0x45], {offset: 4})) { - return { - ext: 'mie', - mime: 'application/x-mie' - }; - } - - if (check([0x27, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], {offset: 2})) { - return { - ext: 'shp', - mime: 'application/x-esri-shape' - }; - } - - if (check([0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A])) { - // JPEG-2000 family - - await tokenizer.ignore(20); - const type = await tokenizer.readToken(new Token.StringType(4, 'ascii')); - switch (type) { - case 'jp2 ': - return { - ext: 'jp2', - mime: 'image/jp2' - }; - case 'jpx ': - return { - ext: 'jpx', - mime: 'image/jpx' - }; - case 'jpm ': - return { - ext: 'jpm', - mime: 'image/jpm' - }; - case 'mjp2': - return { - ext: 'mj2', - mime: 'image/mj2' - }; - default: - return; - } - } - - if ( - check([0xFF, 0x0A]) || - check([0x00, 0x00, 0x00, 0x0C, 0x4A, 0x58, 0x4C, 0x20, 0x0D, 0x0A, 0x87, 0x0A]) - ) { - return { - ext: 'jxl', - mime: 'image/jxl' - }; - } - - // -- Unsafe signatures -- - - if ( - check([0x0, 0x0, 0x1, 0xBA]) || - check([0x0, 0x0, 0x1, 0xB3]) - ) { - return { - ext: 'mpg', - mime: 'video/mpeg' - }; - } - - if (check([0x00, 0x01, 0x00, 0x00, 0x00])) { - return { - ext: 'ttf', - mime: 'font/ttf' - }; - } - - if (check([0x00, 0x00, 0x01, 0x00])) { - return { - ext: 'ico', - mime: 'image/x-icon' - }; - } - - if (check([0x00, 0x00, 0x02, 0x00])) { - return { - ext: 'cur', - mime: 'image/x-icon' - }; - } - - if (check([0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1])) { - // Detected Microsoft Compound File Binary File (MS-CFB) Format. - return { - ext: 'cfb', - mime: 'application/x-cfb' - }; - } - - // Increase sample size from 12 to 256. - await tokenizer.peekBuffer(buffer, {length: Math.min(256, tokenizer.fileInfo.size), mayBeLess: true}); - - // -- 15-byte signatures -- - - if (checkString('BEGIN:')) { - if (checkString('VCARD', {offset: 6})) { - return { - ext: 'vcf', - mime: 'text/vcard' - }; - } - - if (checkString('VCALENDAR', {offset: 6})) { - return { - ext: 'ics', - mime: 'text/calendar' - }; - } - } - - // `raf` is here just to keep all the raw image detectors together. - if (checkString('FUJIFILMCCD-RAW')) { - return { - ext: 'raf', - mime: 'image/x-fujifilm-raf' - }; - } - - if (checkString('Extended Module:')) { - return { - ext: 'xm', - mime: 'audio/x-xm' - }; - } - - if (checkString('Creative Voice File')) { - return { - ext: 'voc', - mime: 'audio/x-voc' - }; - } - - if (check([0x04, 0x00, 0x00, 0x00]) && buffer.length >= 16) { // Rough & quick check Pickle/ASAR - const jsonSize = buffer.readUInt32LE(12); - if (jsonSize > 12 && buffer.length >= jsonSize + 16) { - try { - const header = buffer.slice(16, jsonSize + 16).toString(); - const json = JSON.parse(header); - // Check if Pickle is ASAR - if (json.files) { // Final check, assuring Pickle/ASAR format - return { - ext: 'asar', - mime: 'application/x-asar' - }; - } - } catch (_) { - } - } - } - - if (check([0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02])) { - return { - ext: 'mxf', - mime: 'application/mxf' - }; - } - - if (checkString('SCRM', {offset: 44})) { - return { - ext: 's3m', - mime: 'audio/x-s3m' - }; - } - - if (check([0x47], {offset: 4}) && (check([0x47], {offset: 192}) || check([0x47], {offset: 196}))) { - return { - ext: 'mts', - mime: 'video/mp2t' - }; - } - - if (check([0x42, 0x4F, 0x4F, 0x4B, 0x4D, 0x4F, 0x42, 0x49], {offset: 60})) { - return { - ext: 'mobi', - mime: 'application/x-mobipocket-ebook' - }; - } - - if (check([0x44, 0x49, 0x43, 0x4D], {offset: 128})) { - return { - ext: 'dcm', - mime: 'application/dicom' - }; - } - - if (check([0x4C, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46])) { - return { - ext: 'lnk', - mime: 'application/x.ms.shortcut' // Invented by us - }; - } - - if (check([0x62, 0x6F, 0x6F, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x72, 0x6B, 0x00, 0x00, 0x00, 0x00])) { - return { - ext: 'alias', - mime: 'application/x.apple.alias' // Invented by us - }; - } - - if ( - check([0x4C, 0x50], {offset: 34}) && - ( - check([0x00, 0x00, 0x01], {offset: 8}) || - check([0x01, 0x00, 0x02], {offset: 8}) || - check([0x02, 0x00, 0x02], {offset: 8}) - ) - ) { - return { - ext: 'eot', - mime: 'application/vnd.ms-fontobject' - }; - } - - if (check([0x06, 0x06, 0xED, 0xF5, 0xD8, 0x1D, 0x46, 0xE5, 0xBD, 0x31, 0xEF, 0xE7, 0xFE, 0x74, 0xB7, 0x1D])) { - return { - ext: 'indd', - mime: 'application/x-indesign' - }; - } - - // Increase sample size from 256 to 512 - await tokenizer.peekBuffer(buffer, {length: Math.min(512, tokenizer.fileInfo.size), mayBeLess: true}); - - // Requires a buffer size of 512 bytes - if (tarHeaderChecksumMatches(buffer)) { - return { - ext: 'tar', - mime: 'application/x-tar' - }; - } - - if (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])) { - return { - ext: 'skp', - mime: 'application/vnd.sketchup.skp' - }; - } - - if (checkString('-----BEGIN PGP MESSAGE-----')) { - return { - ext: 'pgp', - mime: 'application/pgp-encrypted' - }; - } - - // Check MPEG 1 or 2 Layer 3 header, or 'layer 0' for ADTS (MPEG sync-word 0xFFE) - if (buffer.length >= 2 && check([0xFF, 0xE0], {offset: 0, mask: [0xFF, 0xE0]})) { - if (check([0x10], {offset: 1, mask: [0x16]})) { - // Check for (ADTS) MPEG-2 - if (check([0x08], {offset: 1, mask: [0x08]})) { - return { - ext: 'aac', - mime: 'audio/aac' - }; - } - - // Must be (ADTS) MPEG-4 - return { - ext: 'aac', - mime: 'audio/aac' - }; - } - - // MPEG 1 or 2 Layer 3 header - // Check for MPEG layer 3 - if (check([0x02], {offset: 1, mask: [0x06]})) { - return { - ext: 'mp3', - mime: 'audio/mpeg' - }; - } - - // Check for MPEG layer 2 - if (check([0x04], {offset: 1, mask: [0x06]})) { - return { - ext: 'mp2', - mime: 'audio/mpeg' - }; - } - - // Check for MPEG layer 1 - if (check([0x06], {offset: 1, mask: [0x06]})) { - return { - ext: 'mp1', - mime: 'audio/mpeg' - }; - } - } -} - -const stream = readableStream => new Promise((resolve, reject) => { - // Using `eval` to work around issues when bundling with Webpack - const stream = eval('require')('stream'); // eslint-disable-line no-eval - - readableStream.on('error', reject); - readableStream.once('readable', async () => { - // Set up output stream - const pass = new stream.PassThrough(); - let outputStream; - if (stream.pipeline) { - outputStream = stream.pipeline(readableStream, pass, () => { - }); - } else { - outputStream = readableStream.pipe(pass); - } - - // Read the input stream and detect the filetype - const chunk = readableStream.read(minimumBytes) || readableStream.read() || Buffer.alloc(0); - try { - const fileType = await fromBuffer(chunk); - pass.fileType = fileType; - } catch (error) { - reject(error); - } - - resolve(outputStream); - }); -}); - -const fileType = { - fromStream, - fromTokenizer, - fromBuffer, - stream -}; - -Object.defineProperty(fileType, 'extensions', { - get() { - return new Set(supported.extensions); - } -}); - -Object.defineProperty(fileType, 'mimeTypes', { - get() { - return new Set(supported.mimeTypes); - } -}); - -module.exports = fileType; - - -/***/ }), - -/***/ 9898: -/***/ ((module) => { - -"use strict"; - - -module.exports = { - extensions: [ - 'jpg', - 'png', - 'apng', - 'gif', - 'webp', - 'flif', - 'xcf', - 'cr2', - 'cr3', - 'orf', - 'arw', - 'dng', - 'nef', - 'rw2', - 'raf', - 'tif', - 'bmp', - 'icns', - 'jxr', - 'psd', - 'indd', - 'zip', - 'tar', - 'rar', - 'gz', - 'bz2', - '7z', - 'dmg', - 'mp4', - 'mid', - 'mkv', - 'webm', - 'mov', - 'avi', - 'mpg', - 'mp2', - 'mp3', - 'm4a', - 'oga', - 'ogg', - 'ogv', - 'opus', - 'flac', - 'wav', - 'spx', - 'amr', - 'pdf', - 'epub', - 'exe', - 'swf', - 'rtf', - 'wasm', - 'woff', - 'woff2', - 'eot', - 'ttf', - 'otf', - 'ico', - 'flv', - 'ps', - 'xz', - 'sqlite', - 'nes', - 'crx', - 'xpi', - 'cab', - 'deb', - 'ar', - 'rpm', - 'Z', - 'lz', - 'cfb', - 'mxf', - 'mts', - 'blend', - 'bpg', - 'docx', - 'pptx', - 'xlsx', - '3gp', - '3g2', - 'jp2', - 'jpm', - 'jpx', - 'mj2', - 'aif', - 'qcp', - 'odt', - 'ods', - 'odp', - 'xml', - 'mobi', - 'heic', - 'cur', - 'ktx', - 'ape', - 'wv', - 'dcm', - 'ics', - 'glb', - 'pcap', - 'dsf', - 'lnk', - 'alias', - 'voc', - 'ac3', - 'm4v', - 'm4p', - 'm4b', - 'f4v', - 'f4p', - 'f4b', - 'f4a', - 'mie', - 'asf', - 'ogm', - 'ogx', - 'mpc', - 'arrow', - 'shp', - 'aac', - 'mp1', - 'it', - 's3m', - 'xm', - 'ai', - 'skp', - 'avif', - 'eps', - 'lzh', - 'pgp', - 'asar', - 'stl', - 'chm', - '3mf', - 'zst', - 'jxl', - 'vcf' - ], - mimeTypes: [ - 'image/jpeg', - 'image/png', - 'image/gif', - 'image/webp', - 'image/flif', - 'image/x-xcf', - 'image/x-canon-cr2', - 'image/x-canon-cr3', - 'image/tiff', - 'image/bmp', - 'image/vnd.ms-photo', - 'image/vnd.adobe.photoshop', - 'application/x-indesign', - 'application/epub+zip', - 'application/x-xpinstall', - 'application/vnd.oasis.opendocument.text', - 'application/vnd.oasis.opendocument.spreadsheet', - 'application/vnd.oasis.opendocument.presentation', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'application/zip', - 'application/x-tar', - 'application/x-rar-compressed', - 'application/gzip', - 'application/x-bzip2', - 'application/x-7z-compressed', - 'application/x-apple-diskimage', - 'application/x-apache-arrow', - 'video/mp4', - 'audio/midi', - 'video/x-matroska', - 'video/webm', - 'video/quicktime', - 'video/vnd.avi', - 'audio/vnd.wave', - 'audio/qcelp', - 'audio/x-ms-asf', - 'video/x-ms-asf', - 'application/vnd.ms-asf', - 'video/mpeg', - 'video/3gpp', - 'audio/mpeg', - 'audio/mp4', // RFC 4337 - 'audio/opus', - 'video/ogg', - 'audio/ogg', - 'application/ogg', - 'audio/x-flac', - 'audio/ape', - 'audio/wavpack', - 'audio/amr', - 'application/pdf', - 'application/x-msdownload', - 'application/x-shockwave-flash', - 'application/rtf', - 'application/wasm', - 'font/woff', - 'font/woff2', - 'application/vnd.ms-fontobject', - 'font/ttf', - 'font/otf', - 'image/x-icon', - 'video/x-flv', - 'application/postscript', - 'application/eps', - 'application/x-xz', - 'application/x-sqlite3', - 'application/x-nintendo-nes-rom', - 'application/x-google-chrome-extension', - 'application/vnd.ms-cab-compressed', - 'application/x-deb', - 'application/x-unix-archive', - 'application/x-rpm', - 'application/x-compress', - 'application/x-lzip', - 'application/x-cfb', - 'application/x-mie', - 'application/mxf', - 'video/mp2t', - 'application/x-blender', - 'image/bpg', - 'image/jp2', - 'image/jpx', - 'image/jpm', - 'image/mj2', - 'audio/aiff', - 'application/xml', - 'application/x-mobipocket-ebook', - 'image/heif', - 'image/heif-sequence', - 'image/heic', - 'image/heic-sequence', - 'image/icns', - 'image/ktx', - 'application/dicom', - 'audio/x-musepack', - 'text/calendar', - 'text/vcard', - 'model/gltf-binary', - 'application/vnd.tcpdump.pcap', - 'audio/x-dsf', // Non-standard - 'application/x.ms.shortcut', // Invented by us - 'application/x.apple.alias', // Invented by us - 'audio/x-voc', - 'audio/vnd.dolby.dd-raw', - 'audio/x-m4a', - 'image/apng', - 'image/x-olympus-orf', - 'image/x-sony-arw', - 'image/x-adobe-dng', - 'image/x-nikon-nef', - 'image/x-panasonic-rw2', - 'image/x-fujifilm-raf', - 'video/x-m4v', - 'video/3gpp2', - 'application/x-esri-shape', - 'audio/aac', - 'audio/x-it', - 'audio/x-s3m', - 'audio/x-xm', - 'video/MP1S', - 'video/MP2P', - 'application/vnd.sketchup.skp', - 'image/avif', - 'application/x-lzh-compressed', - 'application/pgp-encrypted', - 'application/x-asar', - 'model/stl', - 'application/vnd.ms-htmlhelp', - 'model/3mf', - 'image/jxl', - 'application/zstd' - ] -}; - - -/***/ }), - -/***/ 6188: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - - -exports.stringToBytes = string => [...string].map(character => character.charCodeAt(0)); - -/** -Checks whether the TAR checksum is valid. - -@param {Buffer} buffer - The TAR header `[offset ... offset + 512]`. -@param {number} offset - TAR header offset. -@returns {boolean} `true` if the TAR checksum is valid, otherwise `false`. -*/ -exports.tarHeaderChecksumMatches = (buffer, offset = 0) => { - const readSum = parseInt(buffer.toString('utf8', 148, 154).replace(/\0.*$/, '').trim(), 8); // Read sum in header - if (isNaN(readSum)) { - return false; - } - - let sum = 8 * 0x20; // Initialize signed bit sum - - for (let i = offset; i < offset + 148; i++) { - sum += buffer[i]; - } - - for (let i = offset + 156; i < offset + 512; i++) { - sum += buffer[i]; - } - - return readSum === sum; -}; - -/** -ID3 UINT32 sync-safe tokenizer token. -28 bits (representing up to 256MB) integer, the msb is 0 to avoid "false syncsignals". -*/ -exports.uint32SyncSafeToken = { - get: (buffer, offset) => { - return (buffer[offset + 3] & 0x7F) | ((buffer[offset + 2]) << 7) | ((buffer[offset + 1]) << 14) | ((buffer[offset]) << 21); - }, - len: 4 -}; - - -/***/ }), - -/***/ 645: -/***/ ((__unused_webpack_module, exports) => { - -/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ -exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = (nBytes * 8) - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] - - i += d - - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen - for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} - - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen - for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} - - if (e === 0) { - e = 1 - eBias - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity) - } else { - m = m + Math.pow(2, mLen) - e = e - eBias - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen) -} - -exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = (nBytes * 8) - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 - - value = Math.abs(value) - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 - e = eMax - } else { - e = Math.floor(Math.log(value) / Math.LN2) - if (value * (c = Math.pow(2, -e)) < 1) { - e-- - c *= 2 - } - if (e + eBias >= 1) { - value += rt / c - } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } - - if (e + eBias >= eMax) { - m = 0 - e = eMax - } else if (e + eBias >= 1) { - m = ((value * c) - 1) * Math.pow(2, mLen) - e = e + eBias - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) - e = 0 - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} - - buffer[offset + i - d] |= s * 128 -} - - -/***/ }), - -/***/ 5717: -/***/ ((module) => { - -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }) - } - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - if (superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } - } -} - - -/***/ }), - -/***/ 2577: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; -/*! - * media-typer - * Copyright(c) 2014-2017 Douglas Christopher Wilson - * MIT Licensed - */ - - - -/** - * RegExp to match type in RFC 6838 - * - * type-name = restricted-name - * subtype-name = restricted-name - * restricted-name = restricted-name-first *126restricted-name-chars - * restricted-name-first = ALPHA / DIGIT - * restricted-name-chars = ALPHA / DIGIT / "!" / "#" / - * "$" / "&" / "-" / "^" / "_" - * restricted-name-chars =/ "." ; Characters before first dot always - * ; specify a facet name - * restricted-name-chars =/ "+" ; Characters after last plus always - * ; specify a structured syntax suffix - * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z - * DIGIT = %x30-39 ; 0-9 - */ -var SUBTYPE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.-]{0,126}$/ -var TYPE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/ -var TYPE_REGEXP = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/ - -/** - * Module exports. - */ - -exports.format = format -exports.parse = parse -exports.test = test - -/** - * Format object to media type. - * - * @param {object} obj - * @return {string} - * @public - */ - -function format (obj) { - if (!obj || typeof obj !== 'object') { - throw new TypeError('argument obj is required') - } - - var subtype = obj.subtype - var suffix = obj.suffix - var type = obj.type - - if (!type || !TYPE_NAME_REGEXP.test(type)) { - throw new TypeError('invalid type') - } - - if (!subtype || !SUBTYPE_NAME_REGEXP.test(subtype)) { - throw new TypeError('invalid subtype') - } - - // format as type/subtype - var string = type + '/' + subtype - - // append +suffix - if (suffix) { - if (!TYPE_NAME_REGEXP.test(suffix)) { - throw new TypeError('invalid suffix') - } - - string += '+' + suffix - } - - return string -} - -/** - * Test media type. - * - * @param {string} string - * @return {object} - * @public - */ - -function test (string) { - if (!string) { - throw new TypeError('argument string is required') - } - - if (typeof string !== 'string') { - throw new TypeError('argument string is required to be a string') - } - - return TYPE_REGEXP.test(string.toLowerCase()) -} - -/** - * Parse media type to object. - * - * @param {string} string - * @return {object} - * @public - */ - -function parse (string) { - if (!string) { - throw new TypeError('argument string is required') - } - - if (typeof string !== 'string') { - throw new TypeError('argument string is required to be a string') - } - - var match = TYPE_REGEXP.exec(string.toLowerCase()) - - if (!match) { - throw new TypeError('invalid media type') - } - - var type = match[1] - var subtype = match[2] - var suffix - - // suffix after last + - var index = subtype.lastIndexOf('+') - if (index !== -1) { - suffix = subtype.substr(index + 1) - subtype = subtype.substr(0, index) - } - - return new MediaType(type, subtype, suffix) -} - -/** - * Class for MediaType object. - * @public - */ - -function MediaType (type, subtype, suffix) { - this.type = type - this.subtype = subtype - this.suffix = suffix -} - - -/***/ }), - -/***/ 7824: -/***/ ((module) => { - -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; -var w = d * 7; -var y = d * 365.25; - -/** - * Parse or format the given `val`. - * - * Options: - * - * - `long` verbose formatting [false] - * - * @param {String|Number} val - * @param {Object} [options] - * @throws {Error} throw an error if val is not a non-empty string or a number - * @return {String|Number} - * @api public - */ - -module.exports = function(val, options) { - options = options || {}; - var type = typeof val; - if (type === 'string' && val.length > 0) { - return parse(val); - } else if (type === 'number' && isFinite(val)) { - return options.long ? fmtLong(val) : fmtShort(val); - } - throw new Error( - 'val is not a non-empty string or a valid number. val=' + - JSON.stringify(val) - ); -}; - -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function parse(str) { - str = String(str); - if (str.length > 100) { - return; - } - var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( - str - ); - if (!match) { - return; - } - var n = parseFloat(match[1]); - var type = (match[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'yrs': - case 'yr': - case 'y': - return n * y; - case 'weeks': - case 'week': - case 'w': - return n * w; - case 'days': - case 'day': - case 'd': - return n * d; - case 'hours': - case 'hour': - case 'hrs': - case 'hr': - case 'h': - return n * h; - case 'minutes': - case 'minute': - case 'mins': - case 'min': - case 'm': - return n * m; - case 'seconds': - case 'second': - case 'secs': - case 'sec': - case 's': - return n * s; - case 'milliseconds': - case 'millisecond': - case 'msecs': - case 'msec': - case 'ms': - return n; - default: - return undefined; - } -} - -/** - * Short format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtShort(ms) { - var msAbs = Math.abs(ms); - if (msAbs >= d) { - return Math.round(ms / d) + 'd'; - } - if (msAbs >= h) { - return Math.round(ms / h) + 'h'; - } - if (msAbs >= m) { - return Math.round(ms / m) + 'm'; - } - if (msAbs >= s) { - return Math.round(ms / s) + 's'; - } - return ms + 'ms'; -} - -/** - * Long format for `ms`. - * - * @param {Number} ms - * @return {String} - * @api private - */ - -function fmtLong(ms) { - var msAbs = Math.abs(ms); - if (msAbs >= d) { - return plural(ms, msAbs, d, 'day'); - } - if (msAbs >= h) { - return plural(ms, msAbs, h, 'hour'); - } - if (msAbs >= m) { - return plural(ms, msAbs, m, 'minute'); - } - if (msAbs >= s) { - return plural(ms, msAbs, s, 'second'); - } - return ms + ' ms'; -} - -/** - * Pluralization helper. - */ - -function plural(ms, msAbs, n, name) { - var isPlural = msAbs >= n * 1.5; - return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); -} - - -/***/ }), - -/***/ 3275: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ParserFactory = exports.parseHttpContentType = void 0; -const FileType = __webpack_require__(1); -const ContentType = __webpack_require__(7811); -const MimeType = __webpack_require__(2577); -const debug_1 = __webpack_require__(1227); -const MetadataCollector_1 = __webpack_require__(7584); -const AiffParser_1 = __webpack_require__(5410); -const APEv2Parser_1 = __webpack_require__(6742); -const AsfParser_1 = __webpack_require__(1004); -const FlacParser_1 = __webpack_require__(498); -const MP4Parser_1 = __webpack_require__(8841); -const MpegParser_1 = __webpack_require__(60); -const musepack_1 = __webpack_require__(9606); -const OggParser_1 = __webpack_require__(1915); -const WaveParser_1 = __webpack_require__(2682); -const WavPackParser_1 = __webpack_require__(5870); -const DsfParser_1 = __webpack_require__(1533); -const DsdiffParser_1 = __webpack_require__(6789); -const MatroskaParser_1 = __webpack_require__(78); -const debug = (0, debug_1.default)('music-metadata:parser:factory'); -function parseHttpContentType(contentType) { - const type = ContentType.parse(contentType); - const mime = MimeType.parse(type.type); - return { - type: mime.type, - subtype: mime.subtype, - suffix: mime.suffix, - parameters: type.parameters - }; -} -exports.parseHttpContentType = parseHttpContentType; -async function parse(tokenizer, parserId, opts = {}) { - // Parser found, execute parser - const parser = await ParserFactory.loadParser(parserId); - const metadata = new MetadataCollector_1.MetadataCollector(opts); - await parser.init(metadata, tokenizer, opts).parse(); - return metadata.toCommonMetadata(); -} -class ParserFactory { - /** - * Parse metadata from tokenizer - * @param tokenizer - Tokenizer - * @param opts - Options - * @returns Native metadata - */ - static async parseOnContentType(tokenizer, opts) { - const { mimeType, path, url } = await tokenizer.fileInfo; - // Resolve parser based on MIME-type or file extension - const parserId = ParserFactory.getParserIdForMimeType(mimeType) || ParserFactory.getParserIdForExtension(path) || ParserFactory.getParserIdForExtension(url); - if (!parserId) { - debug('No parser found for MIME-type / extension: ' + mimeType); - } - return this.parse(tokenizer, parserId, opts); - } - static async parse(tokenizer, parserId, opts) { - if (!parserId) { - // Parser could not be determined on MIME-type or extension - debug('Guess parser on content...'); - const buf = Buffer.alloc(4100); - await tokenizer.peekBuffer(buf, { mayBeLess: true }); - if (tokenizer.fileInfo.path) { - parserId = this.getParserIdForExtension(tokenizer.fileInfo.path); - } - if (!parserId) { - const guessedType = await FileType.fromBuffer(buf); - if (!guessedType) { - throw new Error('Failed to determine audio format'); - } - debug(`Guessed file type is mime=${guessedType.mime}, extension=${guessedType.ext}`); - parserId = ParserFactory.getParserIdForMimeType(guessedType.mime); - if (!parserId) { - throw new Error('Guessed MIME-type not supported: ' + guessedType.mime); - } - } - } - // Parser found, execute parser - return parse(tokenizer, parserId, opts); - } - /** - * @param filePath - Path, filename or extension to audio file - * @return Parser sub-module name - */ - static getParserIdForExtension(filePath) { - if (!filePath) - return; - const extension = this.getExtension(filePath).toLocaleLowerCase() || filePath; - switch (extension) { - case '.mp2': - case '.mp3': - case '.m2a': - case '.aac': // Assume it is ADTS-container - return 'mpeg'; - case '.ape': - return 'apev2'; - case '.mp4': - case '.m4a': - case '.m4b': - case '.m4pa': - case '.m4v': - case '.m4r': - case '.3gp': - return 'mp4'; - case '.wma': - case '.wmv': - case '.asf': - return 'asf'; - case '.flac': - return 'flac'; - case '.ogg': - case '.ogv': - case '.oga': - case '.ogm': - case '.ogx': - case '.opus': // recommended filename extension for Ogg Opus - case '.spx': // recommended filename extension for Ogg Speex - return 'ogg'; - case '.aif': - case '.aiff': - case '.aifc': - return 'aiff'; - case '.wav': - case '.bwf': // Broadcast Wave Format - return 'riff'; - case '.wv': - case '.wvp': - return 'wavpack'; - case '.mpc': - return 'musepack'; - case '.dsf': - return 'dsf'; - case '.dff': - return 'dsdiff'; - case '.mka': - case '.mkv': - case '.mk3d': - case '.mks': - case '.webm': - return 'matroska'; - } - } - static async loadParser(moduleName) { - switch (moduleName) { - case 'aiff': return new AiffParser_1.AIFFParser(); - case 'adts': - case 'mpeg': - return new MpegParser_1.MpegParser(); - case 'apev2': return new APEv2Parser_1.APEv2Parser(); - case 'asf': return new AsfParser_1.AsfParser(); - case 'dsf': return new DsfParser_1.DsfParser(); - case 'dsdiff': return new DsdiffParser_1.DsdiffParser(); - case 'flac': return new FlacParser_1.FlacParser(); - case 'mp4': return new MP4Parser_1.MP4Parser(); - case 'musepack': return new musepack_1.default(); - case 'ogg': return new OggParser_1.OggParser(); - case 'riff': return new WaveParser_1.WaveParser(); - case 'wavpack': return new WavPackParser_1.WavPackParser(); - case 'matroska': return new MatroskaParser_1.MatroskaParser(); - default: - throw new Error(`Unknown parser type: ${moduleName}`); - } - } - static getExtension(fname) { - const i = fname.lastIndexOf('.'); - return i === -1 ? '' : fname.slice(i); - } - /** - * @param httpContentType - HTTP Content-Type, extension, path or filename - * @returns Parser sub-module name - */ - static getParserIdForMimeType(httpContentType) { - let mime; - try { - mime = parseHttpContentType(httpContentType); - } - catch (err) { - debug(`Invalid HTTP Content-Type header value: ${httpContentType}`); - return; - } - const subType = mime.subtype.indexOf('x-') === 0 ? mime.subtype.substring(2) : mime.subtype; - switch (mime.type) { - case 'audio': - switch (subType) { - case 'mp3': // Incorrect MIME-type, Chrome, in Web API File object - case 'mpeg': - return 'mpeg'; - case 'aac': - case 'aacp': - return 'adts'; - case 'flac': - return 'flac'; - case 'ape': - case 'monkeys-audio': - return 'apev2'; - case 'mp4': - case 'm4a': - return 'mp4'; - case 'ogg': // RFC 7845 - case 'opus': // RFC 6716 - case 'speex': // RFC 5574 - return 'ogg'; - case 'ms-wma': - case 'ms-wmv': - case 'ms-asf': - return 'asf'; - case 'aiff': - case 'aif': - case 'aifc': - return 'aiff'; - case 'vnd.wave': - case 'wav': - case 'wave': - return 'riff'; - case 'wavpack': - return 'wavpack'; - case 'musepack': - return 'musepack'; - case 'matroska': - case 'webm': - return 'matroska'; - case 'dsf': - return 'dsf'; - } - break; - case 'video': - switch (subType) { - case 'ms-asf': - case 'ms-wmv': - return 'asf'; - case 'm4v': - case 'mp4': - return 'mp4'; - case 'ogg': - return 'ogg'; - case 'matroska': - case 'webm': - return 'matroska'; - } - break; - case 'application': - switch (subType) { - case 'vnd.ms-asf': - return 'asf'; - case 'ogg': - return 'ogg'; - } - break; - } - } -} -exports.ParserFactory = ParserFactory; - - -/***/ }), - -/***/ 5410: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.AIFFParser = void 0; -const Token = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const strtok3 = __webpack_require__(5849); -const ID3v2Parser_1 = __webpack_require__(8928); -const FourCC_1 = __webpack_require__(8049); -const BasicParser_1 = __webpack_require__(7805); -const AiffToken = __webpack_require__(1162); -const iff = __webpack_require__(4633); -const debug = (0, debug_1.default)('music-metadata:parser:aiff'); -/** - * AIFF - Audio Interchange File Format - * - * Ref: - * - http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/AIFF.html - * - http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf - */ -class AIFFParser extends BasicParser_1.BasicParser { - async parse() { - const header = await this.tokenizer.readToken(iff.Header); - if (header.chunkID !== 'FORM') - throw new Error('Invalid Chunk-ID, expected \'FORM\''); // Not AIFF format - const type = await this.tokenizer.readToken(FourCC_1.FourCcToken); - switch (type) { - case 'AIFF': - this.metadata.setFormat('container', type); - this.isCompressed = false; - break; - case 'AIFC': - this.metadata.setFormat('container', 'AIFF-C'); - this.isCompressed = true; - break; - default: - throw Error('Unsupported AIFF type: ' + type); - } - this.metadata.setFormat('lossless', !this.isCompressed); - try { - while (!this.tokenizer.fileInfo.size || this.tokenizer.fileInfo.size - this.tokenizer.position >= iff.Header.len) { - debug('Reading AIFF chunk at offset=' + this.tokenizer.position); - const chunkHeader = await this.tokenizer.readToken(iff.Header); - debug(`Chunk id=${chunkHeader.chunkID}`); - const nextChunk = 2 * Math.round(chunkHeader.chunkSize / 2); - const bytesRead = await this.readData(chunkHeader); - await this.tokenizer.ignore(nextChunk - bytesRead); - } - } - catch (err) { - if (err instanceof strtok3.EndOfStreamError) { - debug(`End-of-stream`); - } - else { - throw err; - } - } - } - async readData(header) { - switch (header.chunkID) { - case 'COMM': // The Common Chunk - const common = await this.tokenizer.readToken(new AiffToken.Common(header, this.isCompressed)); - this.metadata.setFormat('bitsPerSample', common.sampleSize); - this.metadata.setFormat('sampleRate', common.sampleRate); - this.metadata.setFormat('numberOfChannels', common.numChannels); - this.metadata.setFormat('numberOfSamples', common.numSampleFrames); - this.metadata.setFormat('duration', common.numSampleFrames / common.sampleRate); - this.metadata.setFormat('codec', common.compressionName); - return header.chunkSize; - case 'ID3 ': // ID3-meta-data - const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(header.chunkSize)); - const rst = strtok3.fromBuffer(id3_data); - await new ID3v2Parser_1.ID3v2Parser().parse(this.metadata, rst, this.options); - return header.chunkSize; - case 'SSND': // Sound Data Chunk - if (this.metadata.format.duration) { - this.metadata.setFormat('bitrate', 8 * header.chunkSize / this.metadata.format.duration); - } - return 0; - default: - return 0; - } - } -} -exports.AIFFParser = AIFFParser; - - -/***/ }), - -/***/ 1162: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Common = void 0; -const Token = __webpack_require__(3416); -const FourCC_1 = __webpack_require__(8049); -class Common { - constructor(header, isAifc) { - this.isAifc = isAifc; - const minimumChunkSize = isAifc ? 22 : 18; - if (header.chunkSize < minimumChunkSize) - throw new Error(`COMMON CHUNK size should always be at least ${minimumChunkSize}`); - this.len = header.chunkSize; - } - get(buf, off) { - // see: https://cycling74.com/forums/aiffs-80-bit-sample-rate-value - const shift = buf.readUInt16BE(off + 8) - 16398; - const baseSampleRate = buf.readUInt16BE(off + 8 + 2); - const res = { - numChannels: buf.readUInt16BE(off), - numSampleFrames: buf.readUInt32BE(off + 2), - sampleSize: buf.readUInt16BE(off + 6), - sampleRate: shift < 0 ? baseSampleRate >> Math.abs(shift) : baseSampleRate << shift - }; - if (this.isAifc) { - res.compressionType = FourCC_1.FourCcToken.get(buf, off + 18); - if (this.len > 22) { - const strLen = buf.readInt8(off + 22); - const padding = (strLen + 1) % 2; - if (23 + strLen + padding === this.len) { - res.compressionName = new Token.StringType(strLen, 'binary').get(buf, off + 23); - } - else { - throw new Error('Illegal pstring length'); - } - } - } - else { - res.compressionName = 'PCM'; - } - return res; - } -} -exports.Common = Common; - - -/***/ }), - -/***/ 6742: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.APEv2Parser = void 0; -const debug_1 = __webpack_require__(1227); -const strtok3 = __webpack_require__(5849); -const token_types_1 = __webpack_require__(3416); -const util = __webpack_require__(3769); -const BasicParser_1 = __webpack_require__(7805); -const APEv2Token_1 = __webpack_require__(876); -const debug = (0, debug_1.default)('music-metadata:parser:APEv2'); -const tagFormat = 'APEv2'; -const preamble = 'APETAGEX'; -class APEv2Parser extends BasicParser_1.BasicParser { - constructor() { - super(...arguments); - this.ape = {}; - } - static tryParseApeHeader(metadata, tokenizer, options) { - const apeParser = new APEv2Parser(); - apeParser.init(metadata, tokenizer, options); - return apeParser.tryParseApeHeader(); - } - /** - * Calculate the media file duration - * @param ah ApeHeader - * @return {number} duration in seconds - */ - static calculateDuration(ah) { - let duration = ah.totalFrames > 1 ? ah.blocksPerFrame * (ah.totalFrames - 1) : 0; - duration += ah.finalFrameBlocks; - return duration / ah.sampleRate; - } - /** - * Calculates the APEv1 / APEv2 first field offset - * @param reader - * @param offset - */ - static async findApeFooterOffset(reader, offset) { - // Search for APE footer header at the end of the file - const apeBuf = Buffer.alloc(APEv2Token_1.TagFooter.len); - await reader.randomRead(apeBuf, 0, APEv2Token_1.TagFooter.len, offset - APEv2Token_1.TagFooter.len); - const tagFooter = APEv2Token_1.TagFooter.get(apeBuf, 0); - if (tagFooter.ID === 'APETAGEX') { - debug(`APE footer header at offset=${offset}`); - return { footer: tagFooter, offset: offset - tagFooter.size }; - } - } - static parseTagFooter(metadata, buffer, options) { - const footer = APEv2Token_1.TagFooter.get(buffer, buffer.length - APEv2Token_1.TagFooter.len); - if (footer.ID !== preamble) - throw new Error('Unexpected APEv2 Footer ID preamble value.'); - strtok3.fromBuffer(buffer); - const apeParser = new APEv2Parser(); - apeParser.init(metadata, strtok3.fromBuffer(buffer), options); - return apeParser.parseTags(footer); - } - /** - * Parse APEv1 / APEv2 header if header signature found - */ - async tryParseApeHeader() { - if (this.tokenizer.fileInfo.size && this.tokenizer.fileInfo.size - this.tokenizer.position < APEv2Token_1.TagFooter.len) { - debug(`No APEv2 header found, end-of-file reached`); - return; - } - const footer = await this.tokenizer.peekToken(APEv2Token_1.TagFooter); - if (footer.ID === preamble) { - await this.tokenizer.ignore(APEv2Token_1.TagFooter.len); - return this.parseTags(footer); - } - else { - debug(`APEv2 header not found at offset=${this.tokenizer.position}`); - if (this.tokenizer.fileInfo.size) { - // Try to read the APEv2 header using just the footer-header - const remaining = this.tokenizer.fileInfo.size - this.tokenizer.position; // ToDo: take ID3v1 into account - const buffer = Buffer.alloc(remaining); - await this.tokenizer.readBuffer(buffer); - return APEv2Parser.parseTagFooter(this.metadata, buffer, this.options); - } - } - } - async parse() { - const descriptor = await this.tokenizer.readToken(APEv2Token_1.DescriptorParser); - if (descriptor.ID !== 'MAC ') - throw new Error('Unexpected descriptor ID'); - this.ape.descriptor = descriptor; - const lenExp = descriptor.descriptorBytes - APEv2Token_1.DescriptorParser.len; - const header = await (lenExp > 0 ? this.parseDescriptorExpansion(lenExp) : this.parseHeader()); - await this.tokenizer.ignore(header.forwardBytes); - return this.tryParseApeHeader(); - } - async parseTags(footer) { - const keyBuffer = Buffer.alloc(256); // maximum tag key length - let bytesRemaining = footer.size - APEv2Token_1.TagFooter.len; - debug(`Parse APE tags at offset=${this.tokenizer.position}, size=${bytesRemaining}`); - for (let i = 0; i < footer.fields; i++) { - if (bytesRemaining < APEv2Token_1.TagItemHeader.len) { - this.metadata.addWarning(`APEv2 Tag-header: ${footer.fields - i} items remaining, but no more tag data to read.`); - break; - } - // Only APEv2 tag has tag item headers - const tagItemHeader = await this.tokenizer.readToken(APEv2Token_1.TagItemHeader); - bytesRemaining -= APEv2Token_1.TagItemHeader.len + tagItemHeader.size; - await this.tokenizer.peekBuffer(keyBuffer, { length: Math.min(keyBuffer.length, bytesRemaining) }); - let zero = util.findZero(keyBuffer, 0, keyBuffer.length); - const key = await this.tokenizer.readToken(new token_types_1.StringType(zero, 'ascii')); - await this.tokenizer.ignore(1); - bytesRemaining -= key.length + 1; - switch (tagItemHeader.flags.dataType) { - case APEv2Token_1.DataType.text_utf8: { // utf-8 text-string - const value = await this.tokenizer.readToken(new token_types_1.StringType(tagItemHeader.size, 'utf8')); - const values = value.split(/\x00/g); - for (const val of values) { - this.metadata.addTag(tagFormat, key, val); - } - break; - } - case APEv2Token_1.DataType.binary: // binary (probably artwork) - if (this.options.skipCovers) { - await this.tokenizer.ignore(tagItemHeader.size); - } - else { - const picData = Buffer.alloc(tagItemHeader.size); - await this.tokenizer.readBuffer(picData); - zero = util.findZero(picData, 0, picData.length); - const description = picData.toString('utf8', 0, zero); - const data = Buffer.from(picData.slice(zero + 1)); - this.metadata.addTag(tagFormat, key, { - description, - data - }); - } - break; - case APEv2Token_1.DataType.external_info: - debug(`Ignore external info ${key}`); - await this.tokenizer.ignore(tagItemHeader.size); - break; - case APEv2Token_1.DataType.reserved: - debug(`Ignore external info ${key}`); - this.metadata.addWarning(`APEv2 header declares a reserved datatype for "${key}"`); - await this.tokenizer.ignore(tagItemHeader.size); - break; - } - } - } - async parseDescriptorExpansion(lenExp) { - await this.tokenizer.ignore(lenExp); - return this.parseHeader(); - } - async parseHeader() { - const header = await this.tokenizer.readToken(APEv2Token_1.Header); - // ToDo before - this.metadata.setFormat('lossless', true); - this.metadata.setFormat('container', 'Monkey\'s Audio'); - this.metadata.setFormat('bitsPerSample', header.bitsPerSample); - this.metadata.setFormat('sampleRate', header.sampleRate); - this.metadata.setFormat('numberOfChannels', header.channel); - this.metadata.setFormat('duration', APEv2Parser.calculateDuration(header)); - return { - forwardBytes: this.ape.descriptor.seekTableBytes + this.ape.descriptor.headerDataBytes + - this.ape.descriptor.apeFrameDataBytes + this.ape.descriptor.terminatingDataBytes - }; - } -} -exports.APEv2Parser = APEv2Parser; - - -/***/ }), - -/***/ 8414: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.APEv2TagMapper = void 0; -const CaseInsensitiveTagMap_1 = __webpack_require__(4132); -/** - * ID3v2.2 tag mappings - */ -const apev2TagMap = { - Title: 'title', - Artist: 'artist', - Artists: 'artists', - 'Album Artist': 'albumartist', - Album: 'album', - Year: 'date', - Originalyear: 'originalyear', - Originaldate: 'originaldate', - Comment: 'comment', - Track: 'track', - Disc: 'disk', - DISCNUMBER: 'disk', - Genre: 'genre', - 'Cover Art (Front)': 'picture', - 'Cover Art (Back)': 'picture', - Composer: 'composer', - Lyrics: 'lyrics', - ALBUMSORT: 'albumsort', - TITLESORT: 'titlesort', - WORK: 'work', - ARTISTSORT: 'artistsort', - ALBUMARTISTSORT: 'albumartistsort', - COMPOSERSORT: 'composersort', - Lyricist: 'lyricist', - Writer: 'writer', - Conductor: 'conductor', - // 'Performer=artist (instrument)': 'performer:instrument', - MixArtist: 'remixer', - Arranger: 'arranger', - Engineer: 'engineer', - Producer: 'producer', - DJMixer: 'djmixer', - Mixer: 'mixer', - Label: 'label', - Grouping: 'grouping', - Subtitle: 'subtitle', - DiscSubtitle: 'discsubtitle', - Compilation: 'compilation', - BPM: 'bpm', - Mood: 'mood', - Media: 'media', - CatalogNumber: 'catalognumber', - MUSICBRAINZ_ALBUMSTATUS: 'releasestatus', - MUSICBRAINZ_ALBUMTYPE: 'releasetype', - RELEASECOUNTRY: 'releasecountry', - Script: 'script', - Language: 'language', - Copyright: 'copyright', - LICENSE: 'license', - EncodedBy: 'encodedby', - EncoderSettings: 'encodersettings', - Barcode: 'barcode', - ISRC: 'isrc', - ASIN: 'asin', - musicbrainz_trackid: 'musicbrainz_recordingid', - musicbrainz_releasetrackid: 'musicbrainz_trackid', - MUSICBRAINZ_ALBUMID: 'musicbrainz_albumid', - MUSICBRAINZ_ARTISTID: 'musicbrainz_artistid', - MUSICBRAINZ_ALBUMARTISTID: 'musicbrainz_albumartistid', - MUSICBRAINZ_RELEASEGROUPID: 'musicbrainz_releasegroupid', - MUSICBRAINZ_WORKID: 'musicbrainz_workid', - MUSICBRAINZ_TRMID: 'musicbrainz_trmid', - MUSICBRAINZ_DISCID: 'musicbrainz_discid', - Acoustid_Id: 'acoustid_id', - ACOUSTID_FINGERPRINT: 'acoustid_fingerprint', - MUSICIP_PUID: 'musicip_puid', - Weblink: 'website', - REPLAYGAIN_TRACK_GAIN: 'replaygain_track_gain', - REPLAYGAIN_TRACK_PEAK: 'replaygain_track_peak', - MP3GAIN_MINMAX: 'replaygain_track_minmax', - MP3GAIN_UNDO: 'replaygain_undo' -}; -class APEv2TagMapper extends CaseInsensitiveTagMap_1.CaseInsensitiveTagMap { - constructor() { - super(['APEv2'], apev2TagMap); - } -} -exports.APEv2TagMapper = APEv2TagMapper; -//# sourceMappingURL=APEv2TagMapper.js.map - -/***/ }), - -/***/ 876: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isBitSet = exports.parseTagFlags = exports.TagField = exports.TagItemHeader = exports.TagFooter = exports.Header = exports.DescriptorParser = exports.DataType = void 0; -const Token = __webpack_require__(3416); -const FourCC_1 = __webpack_require__(8049); -var DataType; -(function (DataType) { - DataType[DataType["text_utf8"] = 0] = "text_utf8"; - DataType[DataType["binary"] = 1] = "binary"; - DataType[DataType["external_info"] = 2] = "external_info"; - DataType[DataType["reserved"] = 3] = "reserved"; -})(DataType = exports.DataType || (exports.DataType = {})); -/** - * APE_DESCRIPTOR: defines the sizes (and offsets) of all the pieces, as well as the MD5 checksum - */ -exports.DescriptorParser = { - len: 52, - get: (buf, off) => { - return { - // should equal 'MAC ' - ID: FourCC_1.FourCcToken.get(buf, off), - // versionIndex number * 1000 (3.81 = 3810) (remember that 4-byte alignment causes this to take 4-bytes) - version: Token.UINT32_LE.get(buf, off + 4) / 1000, - // the number of descriptor bytes (allows later expansion of this header) - descriptorBytes: Token.UINT32_LE.get(buf, off + 8), - // the number of header APE_HEADER bytes - headerBytes: Token.UINT32_LE.get(buf, off + 12), - // the number of header APE_HEADER bytes - seekTableBytes: Token.UINT32_LE.get(buf, off + 16), - // the number of header data bytes (from original file) - headerDataBytes: Token.UINT32_LE.get(buf, off + 20), - // the number of bytes of APE frame data - apeFrameDataBytes: Token.UINT32_LE.get(buf, off + 24), - // the high order number of APE frame data bytes - apeFrameDataBytesHigh: Token.UINT32_LE.get(buf, off + 28), - // the terminating data of the file (not including tag data) - terminatingDataBytes: Token.UINT32_LE.get(buf, off + 32), - // the MD5 hash of the file (see notes for usage... it's a little tricky) - fileMD5: new Token.Uint8ArrayType(16).get(buf, off + 36) - }; - } -}; -/** - * APE_HEADER: describes all of the necessary information about the APE file - */ -exports.Header = { - len: 24, - get: (buf, off) => { - return { - // the compression level (see defines I.E. COMPRESSION_LEVEL_FAST) - compressionLevel: Token.UINT16_LE.get(buf, off), - // any format flags (for future use) - formatFlags: Token.UINT16_LE.get(buf, off + 2), - // the number of audio blocks in one frame - blocksPerFrame: Token.UINT32_LE.get(buf, off + 4), - // the number of audio blocks in the final frame - finalFrameBlocks: Token.UINT32_LE.get(buf, off + 8), - // the total number of frames - totalFrames: Token.UINT32_LE.get(buf, off + 12), - // the bits per sample (typically 16) - bitsPerSample: Token.UINT16_LE.get(buf, off + 16), - // the number of channels (1 or 2) - channel: Token.UINT16_LE.get(buf, off + 18), - // the sample rate (typically 44100) - sampleRate: Token.UINT32_LE.get(buf, off + 20) - }; - } -}; -/** - * APE Tag Header/Footer Version 2.0 - * TAG: describes all the properties of the file [optional] - */ -exports.TagFooter = { - len: 32, - get: (buf, off) => { - return { - // should equal 'APETAGEX' - ID: new Token.StringType(8, 'ascii').get(buf, off), - // equals CURRENT_APE_TAG_VERSION - version: Token.UINT32_LE.get(buf, off + 8), - // the complete size of the tag, including this footer (excludes header) - size: Token.UINT32_LE.get(buf, off + 12), - // the number of fields in the tag - fields: Token.UINT32_LE.get(buf, off + 16), - // reserved for later use (must be zero), - flags: parseTagFlags(Token.UINT32_LE.get(buf, off + 20)) - }; - } -}; -/** - * APE Tag v2.0 Item Header - */ -exports.TagItemHeader = { - len: 8, - get: (buf, off) => { - return { - // Length of assigned value in bytes - size: Token.UINT32_LE.get(buf, off), - // reserved for later use (must be zero), - flags: parseTagFlags(Token.UINT32_LE.get(buf, off + 4)) - }; - } -}; -const TagField = footer => { - return new Token.Uint8ArrayType(footer.size - exports.TagFooter.len); -}; -exports.TagField = TagField; -function parseTagFlags(flags) { - return { - containsHeader: isBitSet(flags, 31), - containsFooter: isBitSet(flags, 30), - isHeader: isBitSet(flags, 31), - readOnly: isBitSet(flags, 0), - dataType: (flags & 6) >> 1 - }; -} -exports.parseTagFlags = parseTagFlags; -/** - * @param num {number} - * @param bit 0 is least significant bit (LSB) - * @return {boolean} true if bit is 1; otherwise false - */ -function isBitSet(num, bit) { - return (num & 1 << bit) !== 0; -} -exports.isBitSet = isBitSet; -//# sourceMappingURL=APEv2Token.js.map - -/***/ }), - -/***/ 5174: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -// ASF Objects -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.WmPictureToken = exports.MetadataLibraryObjectState = exports.MetadataObjectState = exports.ExtendedStreamPropertiesObjectState = exports.ExtendedContentDescriptionObjectState = exports.ContentDescriptionObjectState = exports.readCodecEntries = exports.HeaderExtensionObject = exports.StreamPropertiesObject = exports.FilePropertiesObject = exports.IgnoreObjectState = exports.State = exports.HeaderObjectToken = exports.TopLevelHeaderObjectToken = exports.DataType = void 0; -const util = __webpack_require__(3769); -const Token = __webpack_require__(3416); -const GUID_1 = __webpack_require__(8054); -const AsfUtil_1 = __webpack_require__(2252); -const ID3v2Token_1 = __webpack_require__(8281); -/** - * Data Type: Specifies the type of information being stored. The following values are recognized. - */ -var DataType; -(function (DataType) { - /** - * Unicode string. The data consists of a sequence of Unicode characters. - */ - DataType[DataType["UnicodeString"] = 0] = "UnicodeString"; - /** - * BYTE array. The type of data is implementation-specific. - */ - DataType[DataType["ByteArray"] = 1] = "ByteArray"; - /** - * BOOL. The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer. Only 0x0000 or 0x0001 are permitted values. - */ - DataType[DataType["Bool"] = 2] = "Bool"; - /** - * DWORD. The data is 4 bytes long and should be interpreted as a 32-bit unsigned integer. - */ - DataType[DataType["DWord"] = 3] = "DWord"; - /** - * QWORD. The data is 8 bytes long and should be interpreted as a 64-bit unsigned integer. - */ - DataType[DataType["QWord"] = 4] = "QWord"; - /** - * WORD. The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer. - */ - DataType[DataType["Word"] = 5] = "Word"; -})(DataType = exports.DataType || (exports.DataType = {})); -/** - * Token for: 3. ASF top-level Header Object - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3 - */ -exports.TopLevelHeaderObjectToken = { - len: 30, - get: (buf, off) => { - return { - objectId: GUID_1.default.fromBin(new Token.BufferType(16).get(buf, off)), - objectSize: Number(Token.UINT64_LE.get(buf, off + 16)), - numberOfHeaderObjects: Token.UINT32_LE.get(buf, off + 24) - // Reserved: 2 bytes - }; - } -}; -/** - * Token for: 3.1 Header Object (mandatory, one only) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_1 - */ -exports.HeaderObjectToken = { - len: 24, - get: (buf, off) => { - return { - objectId: GUID_1.default.fromBin(new Token.BufferType(16).get(buf, off)), - objectSize: Number(Token.UINT64_LE.get(buf, off + 16)) - }; - } -}; -class State { - constructor(header) { - this.len = Number(header.objectSize) - exports.HeaderObjectToken.len; - } - postProcessTag(tags, name, valueType, data) { - if (name === 'WM/Picture') { - tags.push({ id: name, value: WmPictureToken.fromBuffer(data) }); - } - else { - const parseAttr = AsfUtil_1.AsfUtil.getParserForAttr(valueType); - if (!parseAttr) { - throw new Error('unexpected value headerType: ' + valueType); - } - tags.push({ id: name, value: parseAttr(data) }); - } - } -} -exports.State = State; -// ToDo: use ignore type -class IgnoreObjectState extends State { - constructor(header) { - super(header); - } - get(buf, off) { - return null; - } -} -exports.IgnoreObjectState = IgnoreObjectState; -/** - * Token for: 3.2: File Properties Object (mandatory, one only) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_2 - */ -class FilePropertiesObject extends State { - constructor(header) { - super(header); - } - get(buf, off) { - return { - fileId: GUID_1.default.fromBin(buf, off), - fileSize: Token.UINT64_LE.get(buf, off + 16), - creationDate: Token.UINT64_LE.get(buf, off + 24), - dataPacketsCount: Token.UINT64_LE.get(buf, off + 32), - playDuration: Token.UINT64_LE.get(buf, off + 40), - sendDuration: Token.UINT64_LE.get(buf, off + 48), - preroll: Token.UINT64_LE.get(buf, off + 56), - flags: { - broadcast: util.getBit(buf, off + 64, 24), - seekable: util.getBit(buf, off + 64, 25) - }, - // flagsNumeric: Token.UINT32_LE.get(buf, off + 64), - minimumDataPacketSize: Token.UINT32_LE.get(buf, off + 68), - maximumDataPacketSize: Token.UINT32_LE.get(buf, off + 72), - maximumBitrate: Token.UINT32_LE.get(buf, off + 76) - }; - } -} -exports.FilePropertiesObject = FilePropertiesObject; -FilePropertiesObject.guid = GUID_1.default.FilePropertiesObject; -/** - * Token for: 3.3 Stream Properties Object (mandatory, one per stream) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_3 - */ -class StreamPropertiesObject extends State { - constructor(header) { - super(header); - } - get(buf, off) { - return { - streamType: GUID_1.default.decodeMediaType(GUID_1.default.fromBin(buf, off)), - errorCorrectionType: GUID_1.default.fromBin(buf, off + 8) - // ToDo - }; - } -} -exports.StreamPropertiesObject = StreamPropertiesObject; -StreamPropertiesObject.guid = GUID_1.default.StreamPropertiesObject; -/** - * 3.4: Header Extension Object (mandatory, one only) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_4 - */ -class HeaderExtensionObject { - constructor() { - this.len = 22; - } - get(buf, off) { - return { - reserved1: GUID_1.default.fromBin(buf, off), - reserved2: buf.readUInt16LE(off + 16), - extensionDataSize: buf.readUInt32LE(off + 18) - }; - } -} -exports.HeaderExtensionObject = HeaderExtensionObject; -HeaderExtensionObject.guid = GUID_1.default.HeaderExtensionObject; -/** - * 3.5: The Codec List Object provides user-friendly information about the codecs and formats used to encode the content found in the ASF file. - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_5 - */ -const CodecListObjectHeader = { - len: 20, - get: (buf, off) => { - return { - entryCount: buf.readUInt16LE(off + 16) - }; - } -}; -async function readString(tokenizer) { - const length = await tokenizer.readNumber(Token.UINT16_LE); - return (await tokenizer.readToken(new Token.StringType(length * 2, 'utf16le'))).replace('\0', ''); -} -/** - * 3.5: Read the Codec-List-Object, which provides user-friendly information about the codecs and formats used to encode the content found in the ASF file. - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_5 - */ -async function readCodecEntries(tokenizer) { - const codecHeader = await tokenizer.readToken(CodecListObjectHeader); - const entries = []; - for (let i = 0; i < codecHeader.entryCount; ++i) { - entries.push(await readCodecEntry(tokenizer)); - } - return entries; -} -exports.readCodecEntries = readCodecEntries; -async function readInformation(tokenizer) { - const length = await tokenizer.readNumber(Token.UINT16_LE); - const buf = Buffer.alloc(length); - await tokenizer.readBuffer(buf); - return buf; -} -/** - * Read Codec-Entries - * @param tokenizer - */ -async function readCodecEntry(tokenizer) { - const type = await tokenizer.readNumber(Token.UINT16_LE); - return { - type: { - videoCodec: (type & 0x0001) === 0x0001, - audioCodec: (type & 0x0002) === 0x0002 - }, - codecName: await readString(tokenizer), - description: await readString(tokenizer), - information: await readInformation(tokenizer) - }; -} -/** - * 3.10 Content Description Object (optional, one only) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_10 - */ -class ContentDescriptionObjectState extends State { - constructor(header) { - super(header); - } - get(buf, off) { - const tags = []; - let pos = off + 10; - for (let i = 0; i < ContentDescriptionObjectState.contentDescTags.length; ++i) { - const length = buf.readUInt16LE(off + i * 2); - if (length > 0) { - const tagName = ContentDescriptionObjectState.contentDescTags[i]; - const end = pos + length; - tags.push({ id: tagName, value: AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, end)) }); - pos = end; - } - } - return tags; - } -} -exports.ContentDescriptionObjectState = ContentDescriptionObjectState; -ContentDescriptionObjectState.guid = GUID_1.default.ContentDescriptionObject; -ContentDescriptionObjectState.contentDescTags = ['Title', 'Author', 'Copyright', 'Description', 'Rating']; -/** - * 3.11 Extended Content Description Object (optional, one only) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/03_asf_top_level_header_object.html#3_11 - */ -class ExtendedContentDescriptionObjectState extends State { - constructor(header) { - super(header); - } - get(buf, off) { - const tags = []; - const attrCount = buf.readUInt16LE(off); - let pos = off + 2; - for (let i = 0; i < attrCount; i += 1) { - const nameLen = buf.readUInt16LE(pos); - pos += 2; - const name = AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen)); - pos += nameLen; - const valueType = buf.readUInt16LE(pos); - pos += 2; - const valueLen = buf.readUInt16LE(pos); - pos += 2; - const value = buf.slice(pos, pos + valueLen); - pos += valueLen; - this.postProcessTag(tags, name, valueType, value); - } - return tags; - } -} -exports.ExtendedContentDescriptionObjectState = ExtendedContentDescriptionObjectState; -ExtendedContentDescriptionObjectState.guid = GUID_1.default.ExtendedContentDescriptionObject; -/** - * 4.1 Extended Stream Properties Object (optional, 1 per media stream) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/04_objects_in_the_asf_header_extension_object.html#4_1 - */ -class ExtendedStreamPropertiesObjectState extends State { - constructor(header) { - super(header); - } - get(buf, off) { - return { - startTime: Token.UINT64_LE.get(buf, off), - endTime: Token.UINT64_LE.get(buf, off + 8), - dataBitrate: buf.readInt32LE(off + 12), - bufferSize: buf.readInt32LE(off + 16), - initialBufferFullness: buf.readInt32LE(off + 20), - alternateDataBitrate: buf.readInt32LE(off + 24), - alternateBufferSize: buf.readInt32LE(off + 28), - alternateInitialBufferFullness: buf.readInt32LE(off + 32), - maximumObjectSize: buf.readInt32LE(off + 36), - flags: { - reliableFlag: util.getBit(buf, off + 40, 0), - seekableFlag: util.getBit(buf, off + 40, 1), - resendLiveCleanpointsFlag: util.getBit(buf, off + 40, 2) - }, - // flagsNumeric: Token.UINT32_LE.get(buf, off + 64), - streamNumber: buf.readInt16LE(off + 42), - streamLanguageId: buf.readInt16LE(off + 44), - averageTimePerFrame: buf.readInt32LE(off + 52), - streamNameCount: buf.readInt32LE(off + 54), - payloadExtensionSystems: buf.readInt32LE(off + 56), - streamNames: [], - streamPropertiesObject: null - }; - } -} -exports.ExtendedStreamPropertiesObjectState = ExtendedStreamPropertiesObjectState; -ExtendedStreamPropertiesObjectState.guid = GUID_1.default.ExtendedStreamPropertiesObject; -/** - * 4.7 Metadata Object (optional, 0 or 1) - * Ref: http://drang.s4.xrea.com/program/tips/id3tag/wmp/04_objects_in_the_asf_header_extension_object.html#4_7 - */ -class MetadataObjectState extends State { - constructor(header) { - super(header); - } - get(uint8Array, off) { - const tags = []; - const buf = Buffer.from(uint8Array); - const descriptionRecordsCount = buf.readUInt16LE(off); - let pos = off + 2; - for (let i = 0; i < descriptionRecordsCount; i += 1) { - pos += 4; - const nameLen = buf.readUInt16LE(pos); - pos += 2; - const dataType = buf.readUInt16LE(pos); - pos += 2; - const dataLen = buf.readUInt32LE(pos); - pos += 4; - const name = AsfUtil_1.AsfUtil.parseUnicodeAttr(buf.slice(pos, pos + nameLen)); - pos += nameLen; - const data = buf.slice(pos, pos + dataLen); - pos += dataLen; - this.postProcessTag(tags, name, dataType, data); - } - return tags; - } -} -exports.MetadataObjectState = MetadataObjectState; -MetadataObjectState.guid = GUID_1.default.MetadataObject; -// 4.8 Metadata Library Object (optional, 0 or 1) -class MetadataLibraryObjectState extends MetadataObjectState { - constructor(header) { - super(header); - } -} -exports.MetadataLibraryObjectState = MetadataLibraryObjectState; -MetadataLibraryObjectState.guid = GUID_1.default.MetadataLibraryObject; -/** - * Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd757977(v=vs.85).aspx - */ -class WmPictureToken { - constructor(len) { - this.len = len; - } - static fromBase64(base64str) { - return this.fromBuffer(Buffer.from(base64str, 'base64')); - } - static fromBuffer(buffer) { - const pic = new WmPictureToken(buffer.length); - return pic.get(buffer, 0); - } - get(buffer, offset) { - const typeId = buffer.readUInt8(offset++); - const size = buffer.readInt32LE(offset); - let index = 5; - while (buffer.readUInt16BE(index) !== 0) { - index += 2; - } - const format = buffer.slice(5, index).toString('utf16le'); - while (buffer.readUInt16BE(index) !== 0) { - index += 2; - } - const description = buffer.slice(5, index).toString('utf16le'); - return { - type: ID3v2Token_1.AttachedPictureType[typeId], - format, - description, - size, - data: buffer.slice(index + 4) - }; - } -} -exports.WmPictureToken = WmPictureToken; - - -/***/ }), - -/***/ 1004: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.AsfParser = void 0; -const debug_1 = __webpack_require__(1227); -const type_1 = __webpack_require__(6032); -const GUID_1 = __webpack_require__(8054); -const AsfObject = __webpack_require__(5174); -const BasicParser_1 = __webpack_require__(7805); -const debug = (0, debug_1.default)('music-metadata:parser:ASF'); -const headerType = 'asf'; -/** - * Windows Media Metadata Usage Guidelines - * - Ref: https://msdn.microsoft.com/en-us/library/ms867702.aspx - * - * Ref: - * - https://tools.ietf.org/html/draft-fleischman-asf-01 - * - https://hwiegman.home.xs4all.nl/fileformats/asf/ASF_Specification.pdf - * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/index.html - * - https://msdn.microsoft.com/en-us/library/windows/desktop/ee663575(v=vs.85).aspx - */ -class AsfParser extends BasicParser_1.BasicParser { - async parse() { - const header = await this.tokenizer.readToken(AsfObject.TopLevelHeaderObjectToken); - if (!header.objectId.equals(GUID_1.default.HeaderObject)) { - throw new Error('expected asf header; but was not found; got: ' + header.objectId.str); - } - try { - await this.parseObjectHeader(header.numberOfHeaderObjects); - } - catch (err) { - debug('Error while parsing ASF: %s', err); - } - } - async parseObjectHeader(numberOfObjectHeaders) { - let tags; - do { - // Parse common header of the ASF Object (3.1) - const header = await this.tokenizer.readToken(AsfObject.HeaderObjectToken); - // Parse data part of the ASF Object - debug('header GUID=%s', header.objectId.str); - switch (header.objectId.str) { - case AsfObject.FilePropertiesObject.guid.str: // 3.2 - const fpo = await this.tokenizer.readToken(new AsfObject.FilePropertiesObject(header)); - this.metadata.setFormat('duration', Number(fpo.playDuration / BigInt(1000)) / 10000 - Number(fpo.preroll) / 1000); - this.metadata.setFormat('bitrate', fpo.maximumBitrate); - break; - case AsfObject.StreamPropertiesObject.guid.str: // 3.3 - const spo = await this.tokenizer.readToken(new AsfObject.StreamPropertiesObject(header)); - this.metadata.setFormat('container', 'ASF/' + spo.streamType); - break; - case AsfObject.HeaderExtensionObject.guid.str: // 3.4 - const extHeader = await this.tokenizer.readToken(new AsfObject.HeaderExtensionObject()); - await this.parseExtensionObject(extHeader.extensionDataSize); - break; - case AsfObject.ContentDescriptionObjectState.guid.str: // 3.10 - tags = await this.tokenizer.readToken(new AsfObject.ContentDescriptionObjectState(header)); - this.addTags(tags); - break; - case AsfObject.ExtendedContentDescriptionObjectState.guid.str: // 3.11 - tags = await this.tokenizer.readToken(new AsfObject.ExtendedContentDescriptionObjectState(header)); - this.addTags(tags); - break; - case GUID_1.default.CodecListObject.str: - const codecs = await AsfObject.readCodecEntries(this.tokenizer); - codecs.forEach(codec => { - this.metadata.addStreamInfo({ - type: codec.type.videoCodec ? type_1.TrackType.video : type_1.TrackType.audio, - codecName: codec.codecName - }); - }); - const audioCodecs = codecs.filter(codec => codec.type.audioCodec).map(codec => codec.codecName).join('/'); - this.metadata.setFormat('codec', audioCodecs); - break; - case GUID_1.default.StreamBitratePropertiesObject.str: - // ToDo? - await this.tokenizer.ignore(header.objectSize - AsfObject.HeaderObjectToken.len); - break; - case GUID_1.default.PaddingObject.str: - // ToDo: register bytes pad - debug('Padding: %s bytes', header.objectSize - AsfObject.HeaderObjectToken.len); - await this.tokenizer.ignore(header.objectSize - AsfObject.HeaderObjectToken.len); - break; - default: - this.metadata.addWarning('Ignore ASF-Object-GUID: ' + header.objectId.str); - debug('Ignore ASF-Object-GUID: %s', header.objectId.str); - await this.tokenizer.readToken(new AsfObject.IgnoreObjectState(header)); - } - } while (--numberOfObjectHeaders); - // done - } - addTags(tags) { - tags.forEach(tag => { - this.metadata.addTag(headerType, tag.id, tag.value); - }); - } - async parseExtensionObject(extensionSize) { - do { - // Parse common header of the ASF Object (3.1) - const header = await this.tokenizer.readToken(AsfObject.HeaderObjectToken); - const remaining = header.objectSize - AsfObject.HeaderObjectToken.len; - // Parse data part of the ASF Object - switch (header.objectId.str) { - case AsfObject.ExtendedStreamPropertiesObjectState.guid.str: // 4.1 - // ToDo: extended stream header properties are ignored - await this.tokenizer.readToken(new AsfObject.ExtendedStreamPropertiesObjectState(header)); - break; - case AsfObject.MetadataObjectState.guid.str: // 4.7 - const moTags = await this.tokenizer.readToken(new AsfObject.MetadataObjectState(header)); - this.addTags(moTags); - break; - case AsfObject.MetadataLibraryObjectState.guid.str: // 4.8 - const mlTags = await this.tokenizer.readToken(new AsfObject.MetadataLibraryObjectState(header)); - this.addTags(mlTags); - break; - case GUID_1.default.PaddingObject.str: - // ToDo: register bytes pad - await this.tokenizer.ignore(remaining); - break; - case GUID_1.default.CompatibilityObject.str: - this.tokenizer.ignore(remaining); - break; - case GUID_1.default.ASF_Index_Placeholder_Object.str: - await this.tokenizer.ignore(remaining); - break; - default: - this.metadata.addWarning('Ignore ASF-Object-GUID: ' + header.objectId.str); - // console.log("Ignore ASF-Object-GUID: %s", header.objectId.str); - await this.tokenizer.readToken(new AsfObject.IgnoreObjectState(header)); - break; - } - extensionSize -= header.objectSize; - } while (extensionSize > 0); - } -} -exports.AsfParser = AsfParser; - - -/***/ }), - -/***/ 9004: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.AsfTagMapper = void 0; -const GenericTagMapper_1 = __webpack_require__(9918); -/** - * ASF Metadata tag mappings. - * See http://msdn.microsoft.com/en-us/library/ms867702.aspx - */ -const asfTagMap = { - Title: 'title', - Author: 'artist', - 'WM/AlbumArtist': 'albumartist', - 'WM/AlbumTitle': 'album', - 'WM/Year': 'date', - 'WM/OriginalReleaseTime': 'originaldate', - 'WM/OriginalReleaseYear': 'originalyear', - Description: 'comment', - 'WM/TrackNumber': 'track', - 'WM/PartOfSet': 'disk', - 'WM/Genre': 'genre', - 'WM/Composer': 'composer', - 'WM/Lyrics': 'lyrics', - 'WM/AlbumSortOrder': 'albumsort', - 'WM/TitleSortOrder': 'titlesort', - 'WM/ArtistSortOrder': 'artistsort', - 'WM/AlbumArtistSortOrder': 'albumartistsort', - 'WM/ComposerSortOrder': 'composersort', - 'WM/Writer': 'lyricist', - 'WM/Conductor': 'conductor', - 'WM/ModifiedBy': 'remixer', - 'WM/Engineer': 'engineer', - 'WM/Producer': 'producer', - 'WM/DJMixer': 'djmixer', - 'WM/Mixer': 'mixer', - 'WM/Publisher': 'label', - 'WM/ContentGroupDescription': 'grouping', - 'WM/SubTitle': 'subtitle', - 'WM/SetSubTitle': 'discsubtitle', - // 'WM/PartOfSet': 'totaldiscs', - 'WM/IsCompilation': 'compilation', - 'WM/SharedUserRating': 'rating', - 'WM/BeatsPerMinute': 'bpm', - 'WM/Mood': 'mood', - 'WM/Media': 'media', - 'WM/CatalogNo': 'catalognumber', - 'MusicBrainz/Album Status': 'releasestatus', - 'MusicBrainz/Album Type': 'releasetype', - 'MusicBrainz/Album Release Country': 'releasecountry', - 'WM/Script': 'script', - 'WM/Language': 'language', - Copyright: 'copyright', - LICENSE: 'license', - 'WM/EncodedBy': 'encodedby', - 'WM/EncodingSettings': 'encodersettings', - 'WM/Barcode': 'barcode', - 'WM/ISRC': 'isrc', - 'MusicBrainz/Track Id': 'musicbrainz_recordingid', - 'MusicBrainz/Release Track Id': 'musicbrainz_trackid', - 'MusicBrainz/Album Id': 'musicbrainz_albumid', - 'MusicBrainz/Artist Id': 'musicbrainz_artistid', - 'MusicBrainz/Album Artist Id': 'musicbrainz_albumartistid', - 'MusicBrainz/Release Group Id': 'musicbrainz_releasegroupid', - 'MusicBrainz/Work Id': 'musicbrainz_workid', - 'MusicBrainz/TRM Id': 'musicbrainz_trmid', - 'MusicBrainz/Disc Id': 'musicbrainz_discid', - 'Acoustid/Id': 'acoustid_id', - 'Acoustid/Fingerprint': 'acoustid_fingerprint', - 'MusicIP/PUID': 'musicip_puid', - 'WM/ARTISTS': 'artists', - 'WM/InitialKey': 'key', - ASIN: 'asin', - 'WM/Work': 'work', - 'WM/AuthorURL': 'website', - 'WM/Picture': 'picture' -}; -class AsfTagMapper extends GenericTagMapper_1.CommonTagMapper { - static toRating(rating) { - return { - rating: parseFloat(rating + 1) / 5 - }; - } - constructor() { - super(['asf'], asfTagMap); - } - postMap(tag) { - switch (tag.id) { - case 'WM/SharedUserRating': - const keys = tag.id.split(':'); - tag.value = AsfTagMapper.toRating(tag.value); - tag.id = keys[0]; - break; - } - } -} -exports.AsfTagMapper = AsfTagMapper; -//# sourceMappingURL=AsfTagMapper.js.map - -/***/ }), - -/***/ 2252: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.AsfUtil = void 0; -const Token = __webpack_require__(3416); -const util = __webpack_require__(3769); -class AsfUtil { - static getParserForAttr(i) { - return AsfUtil.attributeParsers[i]; - } - static parseUnicodeAttr(uint8Array) { - return util.stripNulls(util.decodeString(uint8Array, 'utf16le')); - } - static parseByteArrayAttr(buf) { - return Buffer.from(buf); - } - static parseBoolAttr(buf, offset = 0) { - return AsfUtil.parseWordAttr(buf, offset) === 1; - } - static parseDWordAttr(buf, offset = 0) { - return buf.readUInt32LE(offset); - } - static parseQWordAttr(buf, offset = 0) { - return Token.UINT64_LE.get(buf, offset); - } - static parseWordAttr(buf, offset = 0) { - return buf.readUInt16LE(offset); - } -} -exports.AsfUtil = AsfUtil; -AsfUtil.attributeParsers = [ - AsfUtil.parseUnicodeAttr, - AsfUtil.parseByteArrayAttr, - AsfUtil.parseBoolAttr, - AsfUtil.parseDWordAttr, - AsfUtil.parseQWordAttr, - AsfUtil.parseWordAttr, - AsfUtil.parseByteArrayAttr -]; - - -/***/ }), - -/***/ 8054: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -/** - * Ref: - * - https://tools.ietf.org/html/draft-fleischman-asf-01, Appendix A: ASF GUIDs - * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/10_asf_guids.html - * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/index.html - * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/10_asf_guids.html - * - * ASF File Structure: - * - https://msdn.microsoft.com/en-us/library/windows/desktop/ee663575(v=vs.85).aspx - * - * ASF GUIDs: - * - http://drang.s4.xrea.com/program/tips/id3tag/wmp/10_asf_guids.html - * - https://github.com/dji-sdk/FFmpeg/blob/master/libavformat/asf.c - */ -class GUID { - constructor(str) { - this.str = str; - } - static fromBin(bin, offset = 0) { - return new GUID(this.decode(bin, offset)); - } - /** - * Decode GUID in format like "B503BF5F-2EA9-CF11-8EE3-00C00C205365" - * @param objectId Binary GUID - * @param offset Read offset in bytes, default 0 - * @returns GUID as dashed hexadecimal representation - */ - static decode(objectId, offset = 0) { - const guid = objectId.readUInt32LE(offset).toString(16) + "-" + - objectId.readUInt16LE(offset + 4).toString(16) + "-" + - objectId.readUInt16LE(offset + 6).toString(16) + "-" + - objectId.readUInt16BE(offset + 8).toString(16) + "-" + - objectId.slice(offset + 10, offset + 16).toString('hex'); - return guid.toUpperCase(); - } - /** - * Decode stream type - * @param mediaType Media type GUID - * @returns Media type - */ - static decodeMediaType(mediaType) { - switch (mediaType.str) { - case GUID.AudioMedia.str: return 'audio'; - case GUID.VideoMedia.str: return 'video'; - case GUID.CommandMedia.str: return 'command'; - case GUID.Degradable_JPEG_Media.str: return 'degradable-jpeg'; - case GUID.FileTransferMedia.str: return 'file-transfer'; - case GUID.BinaryMedia.str: return 'binary'; - } - } - /** - * Encode GUID - * @param guid GUID like: "B503BF5F-2EA9-CF11-8EE3-00C00C205365" - * @returns Encoded Binary GUID - */ - static encode(str) { - const bin = Buffer.alloc(16); - bin.writeUInt32LE(parseInt(str.slice(0, 8), 16), 0); - bin.writeUInt16LE(parseInt(str.slice(9, 13), 16), 4); - bin.writeUInt16LE(parseInt(str.slice(14, 18), 16), 6); - Buffer.from(str.slice(19, 23), "hex").copy(bin, 8); - Buffer.from(str.slice(24), "hex").copy(bin, 10); - return bin; - } - equals(guid) { - return this.str === guid.str; - } - toBin() { - return GUID.encode(this.str); - } -} -exports["default"] = GUID; -// 10.1 Top-level ASF object GUIDs -GUID.HeaderObject = new GUID("75B22630-668E-11CF-A6D9-00AA0062CE6C"); -GUID.DataObject = new GUID("75B22636-668E-11CF-A6D9-00AA0062CE6C"); -GUID.SimpleIndexObject = new GUID("33000890-E5B1-11CF-89F4-00A0C90349CB"); -GUID.IndexObject = new GUID("D6E229D3-35DA-11D1-9034-00A0C90349BE"); -GUID.MediaObjectIndexObject = new GUID("FEB103F8-12AD-4C64-840F-2A1D2F7AD48C"); -GUID.TimecodeIndexObject = new GUID("3CB73FD0-0C4A-4803-953D-EDF7B6228F0C"); -// 10.2 Header Object GUIDs -GUID.FilePropertiesObject = new GUID("8CABDCA1-A947-11CF-8EE4-00C00C205365"); -GUID.StreamPropertiesObject = new GUID("B7DC0791-A9B7-11CF-8EE6-00C00C205365"); -GUID.HeaderExtensionObject = new GUID("5FBF03B5-A92E-11CF-8EE3-00C00C205365"); -GUID.CodecListObject = new GUID("86D15240-311D-11D0-A3A4-00A0C90348F6"); -GUID.ScriptCommandObject = new GUID("1EFB1A30-0B62-11D0-A39B-00A0C90348F6"); -GUID.MarkerObject = new GUID("F487CD01-A951-11CF-8EE6-00C00C205365"); -GUID.BitrateMutualExclusionObject = new GUID("D6E229DC-35DA-11D1-9034-00A0C90349BE"); -GUID.ErrorCorrectionObject = new GUID("75B22635-668E-11CF-A6D9-00AA0062CE6C"); -GUID.ContentDescriptionObject = new GUID("75B22633-668E-11CF-A6D9-00AA0062CE6C"); -GUID.ExtendedContentDescriptionObject = new GUID("D2D0A440-E307-11D2-97F0-00A0C95EA850"); -GUID.ContentBrandingObject = new GUID("2211B3FA-BD23-11D2-B4B7-00A0C955FC6E"); -GUID.StreamBitratePropertiesObject = new GUID("7BF875CE-468D-11D1-8D82-006097C9A2B2"); -GUID.ContentEncryptionObject = new GUID("2211B3FB-BD23-11D2-B4B7-00A0C955FC6E"); -GUID.ExtendedContentEncryptionObject = new GUID("298AE614-2622-4C17-B935-DAE07EE9289C"); -GUID.DigitalSignatureObject = new GUID("2211B3FC-BD23-11D2-B4B7-00A0C955FC6E"); -GUID.PaddingObject = new GUID("1806D474-CADF-4509-A4BA-9AABCB96AAE8"); -// 10.3 Header Extension Object GUIDs -GUID.ExtendedStreamPropertiesObject = new GUID("14E6A5CB-C672-4332-8399-A96952065B5A"); -GUID.AdvancedMutualExclusionObject = new GUID("A08649CF-4775-4670-8A16-6E35357566CD"); -GUID.GroupMutualExclusionObject = new GUID("D1465A40-5A79-4338-B71B-E36B8FD6C249"); -GUID.StreamPrioritizationObject = new GUID("D4FED15B-88D3-454F-81F0-ED5C45999E24"); -GUID.BandwidthSharingObject = new GUID("A69609E6-517B-11D2-B6AF-00C04FD908E9"); -GUID.LanguageListObject = new GUID("7C4346A9-EFE0-4BFC-B229-393EDE415C85"); -GUID.MetadataObject = new GUID("C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA"); -GUID.MetadataLibraryObject = new GUID("44231C94-9498-49D1-A141-1D134E457054"); -GUID.IndexParametersObject = new GUID("D6E229DF-35DA-11D1-9034-00A0C90349BE"); -GUID.MediaObjectIndexParametersObject = new GUID("6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7"); -GUID.TimecodeIndexParametersObject = new GUID("F55E496D-9797-4B5D-8C8B-604DFE9BFB24"); -GUID.CompatibilityObject = new GUID("26F18B5D-4584-47EC-9F5F-0E651F0452C9"); -GUID.AdvancedContentEncryptionObject = new GUID("43058533-6981-49E6-9B74-AD12CB86D58C"); -// 10.4 Stream Properties Object Stream Type GUIDs -GUID.AudioMedia = new GUID("F8699E40-5B4D-11CF-A8FD-00805F5C442B"); -GUID.VideoMedia = new GUID("BC19EFC0-5B4D-11CF-A8FD-00805F5C442B"); -GUID.CommandMedia = new GUID("59DACFC0-59E6-11D0-A3AC-00A0C90348F6"); -GUID.JFIF_Media = new GUID("B61BE100-5B4E-11CF-A8FD-00805F5C442B"); -GUID.Degradable_JPEG_Media = new GUID("35907DE0-E415-11CF-A917-00805F5C442B"); -GUID.FileTransferMedia = new GUID("91BD222C-F21C-497A-8B6D-5AA86BFC0185"); -GUID.BinaryMedia = new GUID("3AFB65E2-47EF-40F2-AC2C-70A90D71D343"); -GUID.ASF_Index_Placeholder_Object = new GUID("D9AADE20-7C17-4F9C-BC28-8555DD98E2A2"); - - -/***/ }), - -/***/ 7805: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.BasicParser = void 0; -class BasicParser { - /** - * Initialize parser with output (metadata), input (tokenizer) & parsing options (options). - * @param {INativeMetadataCollector} metadata Output - * @param {ITokenizer} tokenizer Input - * @param {IOptions} options Parsing options - */ - init(metadata, tokenizer, options) { - this.metadata = metadata; - this.tokenizer = tokenizer; - this.options = options; - return this; - } -} -exports.BasicParser = BasicParser; - - -/***/ }), - -/***/ 4132: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.CaseInsensitiveTagMap = void 0; -const GenericTagMapper_1 = __webpack_require__(9918); -class CaseInsensitiveTagMap extends GenericTagMapper_1.CommonTagMapper { - constructor(tagTypes, tagMap) { - const upperCaseMap = {}; - for (const tag of Object.keys(tagMap)) { - upperCaseMap[tag.toUpperCase()] = tagMap[tag]; - } - super(tagTypes, upperCaseMap); - } - /** - * @tag Native header tag - * @return common tag name (alias) - */ - getCommonName(tag) { - return this.tagMap[tag.toUpperCase()]; - } -} -exports.CaseInsensitiveTagMap = CaseInsensitiveTagMap; -//# sourceMappingURL=CaseInsensitiveTagMap.js.map - -/***/ }), - -/***/ 6592: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.CombinedTagMapper = void 0; -const ID3v1TagMap_1 = __webpack_require__(2939); -const ID3v24TagMapper_1 = __webpack_require__(4005); -const AsfTagMapper_1 = __webpack_require__(9004); -const ID3v22TagMapper_1 = __webpack_require__(7183); -const APEv2TagMapper_1 = __webpack_require__(8414); -const MP4TagMapper_1 = __webpack_require__(7852); -const VorbisTagMapper_1 = __webpack_require__(9860); -const RiffInfoTagMap_1 = __webpack_require__(5756); -const MatroskaTagMapper_1 = __webpack_require__(5481); -class CombinedTagMapper { - constructor() { - this.tagMappers = {}; - [ - new ID3v1TagMap_1.ID3v1TagMapper(), - new ID3v22TagMapper_1.ID3v22TagMapper(), - new ID3v24TagMapper_1.ID3v24TagMapper(), - new MP4TagMapper_1.MP4TagMapper(), - new MP4TagMapper_1.MP4TagMapper(), - new VorbisTagMapper_1.VorbisTagMapper(), - new APEv2TagMapper_1.APEv2TagMapper(), - new AsfTagMapper_1.AsfTagMapper(), - new RiffInfoTagMap_1.RiffInfoTagMapper(), - new MatroskaTagMapper_1.MatroskaTagMapper() - ].forEach(mapper => { - this.registerTagMapper(mapper); - }); - } - /** - * Convert native to generic (common) tags - * @param tagType Originating tag format - * @param tag Native tag to map to a generic tag id - * @param warnings - * @return Generic tag result (output of this function) - */ - mapTag(tagType, tag, warnings) { - const tagMapper = this.tagMappers[tagType]; - if (tagMapper) { - return this.tagMappers[tagType].mapGenericTag(tag, warnings); - } - throw new Error('No generic tag mapper defined for tag-format: ' + tagType); - } - registerTagMapper(genericTagMapper) { - for (const tagType of genericTagMapper.tagTypes) { - this.tagMappers[tagType] = genericTagMapper; - } - } -} -exports.CombinedTagMapper = CombinedTagMapper; -//# sourceMappingURL=CombinedTagMapper.js.map - -/***/ }), - -/***/ 8049: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.FourCcToken = void 0; -const util = __webpack_require__(3769); -const validFourCC = /^[\x21-\x7e©][\x20-\x7e\x00()]{3}/; -/** - * Token for read FourCC - * Ref: https://en.wikipedia.org/wiki/FourCC - */ -exports.FourCcToken = { - len: 4, - get: (buf, off) => { - const id = buf.toString('binary', off, off + exports.FourCcToken.len); - switch (id) { - default: - if (!id.match(validFourCC)) { - throw new Error(`FourCC contains invalid characters: ${util.a2hex(id)} "${id}"`); - } - } - return id; - }, - put: (buffer, offset, id) => { - const str = Buffer.from(id, 'binary'); - if (str.length !== 4) - throw new Error('Invalid length'); - return str.copy(buffer, offset); - } -}; -//# sourceMappingURL=FourCC.js.map - -/***/ }), - -/***/ 9918: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.CommonTagMapper = void 0; -class CommonTagMapper { - constructor(tagTypes, tagMap) { - this.tagTypes = tagTypes; - this.tagMap = tagMap; - } - static toIntOrNull(str) { - const cleaned = parseInt(str, 10); - return isNaN(cleaned) ? null : cleaned; - } - // TODO: a string of 1of1 would fail to be converted - // converts 1/10 to no : 1, of : 10 - // or 1 to no : 1, of : 0 - static normalizeTrack(origVal) { - const split = origVal.toString().split('/'); - return { - no: parseInt(split[0], 10) || null, - of: parseInt(split[1], 10) || null - }; - } - /** - * Process and set common tags - * write common tags to - * @param tag Native tag - * @param warnings Register warnings - * @return common name - */ - mapGenericTag(tag, warnings) { - tag = { id: tag.id, value: tag.value }; // clone object - this.postMap(tag, warnings); - // Convert native tag event to generic 'alias' tag - const id = this.getCommonName(tag.id); - return id ? { id, value: tag.value } : null; - } - /** - * Convert native tag key to common tag key - * @tag Native header tag - * @return common tag name (alias) - */ - getCommonName(tag) { - return this.tagMap[tag]; - } - /** - * Handle post mapping exceptions / correction - * @param tag Tag e.g. {"©alb", "Buena Vista Social Club") - * @param warnings Used to register warnings - */ - postMap(tag, warnings) { - return; - } -} -exports.CommonTagMapper = CommonTagMapper; -CommonTagMapper.maxRatingScore = 1; -//# sourceMappingURL=GenericTagMapper.js.map - -/***/ }), - -/***/ 103: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isUnique = exports.isSingleton = exports.commonTags = void 0; -exports.commonTags = { - year: { multiple: false }, - track: { multiple: false }, - disk: { multiple: false }, - title: { multiple: false }, - artist: { multiple: false }, - artists: { multiple: true, unique: true }, - albumartist: { multiple: false }, - album: { multiple: false }, - date: { multiple: false }, - originaldate: { multiple: false }, - originalyear: { multiple: false }, - comment: { multiple: true, unique: false }, - genre: { multiple: true, unique: true }, - picture: { multiple: true, unique: true }, - composer: { multiple: true, unique: true }, - lyrics: { multiple: true, unique: false }, - albumsort: { multiple: false, unique: true }, - titlesort: { multiple: false, unique: true }, - work: { multiple: false, unique: true }, - artistsort: { multiple: false, unique: true }, - albumartistsort: { multiple: false, unique: true }, - composersort: { multiple: false, unique: true }, - lyricist: { multiple: true, unique: true }, - writer: { multiple: true, unique: true }, - conductor: { multiple: true, unique: true }, - remixer: { multiple: true, unique: true }, - arranger: { multiple: true, unique: true }, - engineer: { multiple: true, unique: true }, - producer: { multiple: true, unique: true }, - technician: { multiple: true, unique: true }, - djmixer: { multiple: true, unique: true }, - mixer: { multiple: true, unique: true }, - label: { multiple: true, unique: true }, - grouping: { multiple: false }, - subtitle: { multiple: true }, - discsubtitle: { multiple: false }, - totaltracks: { multiple: false }, - totaldiscs: { multiple: false }, - compilation: { multiple: false }, - rating: { multiple: true }, - bpm: { multiple: false }, - mood: { multiple: false }, - media: { multiple: false }, - catalognumber: { multiple: true, unique: true }, - tvShow: { multiple: false }, - tvShowSort: { multiple: false }, - tvSeason: { multiple: false }, - tvEpisode: { multiple: false }, - tvEpisodeId: { multiple: false }, - tvNetwork: { multiple: false }, - podcast: { multiple: false }, - podcasturl: { multiple: false }, - releasestatus: { multiple: false }, - releasetype: { multiple: true }, - releasecountry: { multiple: false }, - script: { multiple: false }, - language: { multiple: false }, - copyright: { multiple: false }, - license: { multiple: false }, - encodedby: { multiple: false }, - encodersettings: { multiple: false }, - gapless: { multiple: false }, - barcode: { multiple: false }, - isrc: { multiple: true }, - asin: { multiple: false }, - musicbrainz_recordingid: { multiple: false }, - musicbrainz_trackid: { multiple: false }, - musicbrainz_albumid: { multiple: false }, - musicbrainz_artistid: { multiple: true }, - musicbrainz_albumartistid: { multiple: true }, - musicbrainz_releasegroupid: { multiple: false }, - musicbrainz_workid: { multiple: false }, - musicbrainz_trmid: { multiple: false }, - musicbrainz_discid: { multiple: false }, - acoustid_id: { multiple: false }, - acoustid_fingerprint: { multiple: false }, - musicip_puid: { multiple: false }, - musicip_fingerprint: { multiple: false }, - website: { multiple: false }, - 'performer:instrument': { multiple: true, unique: true }, - averageLevel: { multiple: false }, - peakLevel: { multiple: false }, - notes: { multiple: true, unique: false }, - key: { multiple: false }, - originalalbum: { multiple: false }, - originalartist: { multiple: false }, - discogs_artist_id: { multiple: true, unique: true }, - discogs_release_id: { multiple: false }, - discogs_label_id: { multiple: false }, - discogs_master_release_id: { multiple: false }, - discogs_votes: { multiple: false }, - discogs_rating: { multiple: false }, - replaygain_track_peak: { multiple: false }, - replaygain_track_gain: { multiple: false }, - replaygain_album_peak: { multiple: false }, - replaygain_album_gain: { multiple: false }, - replaygain_track_minmax: { multiple: false }, - replaygain_album_minmax: { multiple: false }, - replaygain_undo: { multiple: false }, - description: { multiple: true }, - longDescription: { multiple: false }, - category: { multiple: true }, - hdVideo: { multiple: false }, - keywords: { multiple: true }, - movement: { multiple: false }, - movementIndex: { multiple: false }, - movementTotal: { multiple: false }, - podcastId: { multiple: false }, - showMovement: { multiple: false }, - stik: { multiple: false } -}; -/** - * @param alias Name of common tag - * @returns {boolean|*} true if given alias is mapped as a singleton', otherwise false - */ -function isSingleton(alias) { - return exports.commonTags.hasOwnProperty(alias) && !exports.commonTags[alias].multiple; -} -exports.isSingleton = isSingleton; -/** - * @param alias Common (generic) tag - * @returns {boolean|*} true if given alias is a singleton or explicitly marked as unique - */ -function isUnique(alias) { - return !exports.commonTags[alias].multiple || exports.commonTags[alias].unique; -} -exports.isUnique = isUnique; -//# sourceMappingURL=GenericTagTypes.js.map - -/***/ }), - -/***/ 7584: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.joinArtists = exports.MetadataCollector = void 0; -const type_1 = __webpack_require__(6032); -const debug_1 = __webpack_require__(1227); -const GenericTagTypes_1 = __webpack_require__(103); -const CombinedTagMapper_1 = __webpack_require__(6592); -const GenericTagMapper_1 = __webpack_require__(9918); -const Util_1 = __webpack_require__(3769); -const FileType = __webpack_require__(1); -const debug = (0, debug_1.default)('music-metadata:collector'); -const TagPriority = ['matroska', 'APEv2', 'vorbis', 'ID3v2.4', 'ID3v2.3', 'ID3v2.2', 'exif', 'asf', 'iTunes', 'ID3v1']; -/** - * Provided to the parser to uodate the metadata result. - * Responsible for triggering async updates - */ -class MetadataCollector { - constructor(opts) { - this.opts = opts; - this.format = { - tagTypes: [], - trackInfo: [] - }; - this.native = {}; - this.common = { - track: { no: null, of: null }, - disk: { no: null, of: null }, - movementIndex: {} - }; - this.quality = { - warnings: [] - }; - /** - * Keeps track of origin priority for each mapped id - */ - this.commonOrigin = {}; - /** - * Maps a tag type to a priority - */ - this.originPriority = {}; - this.tagMapper = new CombinedTagMapper_1.CombinedTagMapper(); - let priority = 1; - for (const tagType of TagPriority) { - this.originPriority[tagType] = priority++; - } - this.originPriority.artificial = 500; // Filled using alternative tags - this.originPriority.id3v1 = 600; // Consider worst due to field length limit - } - /** - * @returns {boolean} true if one or more tags have been found - */ - hasAny() { - return Object.keys(this.native).length > 0; - } - addStreamInfo(streamInfo) { - debug(`streamInfo: type=${type_1.TrackType[streamInfo.type]}, codec=${streamInfo.codecName}`); - this.format.trackInfo.push(streamInfo); - } - setFormat(key, value) { - debug(`format: ${key} = ${value}`); - this.format[key] = value; // as any to override readonly - if (this.opts.observer) { - this.opts.observer({ metadata: this, tag: { type: 'format', id: key, value } }); - } - } - addTag(tagType, tagId, value) { - debug(`tag ${tagType}.${tagId} = ${value}`); - if (!this.native[tagType]) { - this.format.tagTypes.push(tagType); - this.native[tagType] = []; - } - this.native[tagType].push({ id: tagId, value }); - this.toCommon(tagType, tagId, value); - } - addWarning(warning) { - this.quality.warnings.push({ message: warning }); - } - postMap(tagType, tag) { - // Common tag (alias) found - // check if we need to do something special with common tag - // if the event has been aliased then we need to clean it before - // it is emitted to the user. e.g. genre (20) -> Electronic - switch (tag.id) { - case 'artist': - if (this.commonOrigin.artist === this.originPriority[tagType]) { - // Assume the artist field is used as artists - return this.postMap('artificial', { id: 'artists', value: tag.value }); - } - if (!this.common.artists) { - // Fill artists using artist source - this.setGenericTag('artificial', { id: 'artists', value: tag.value }); - } - break; - case 'artists': - if (!this.common.artist || this.commonOrigin.artist === this.originPriority.artificial) { - if (!this.common.artists || this.common.artists.indexOf(tag.value) === -1) { - // Fill artist using artists source - const artists = (this.common.artists || []).concat([tag.value]); - const value = joinArtists(artists); - const artistTag = { id: 'artist', value }; - this.setGenericTag('artificial', artistTag); - } - } - break; - case 'picture': - this.postFixPicture(tag.value).then(picture => { - if (picture !== null) { - tag.value = picture; - this.setGenericTag(tagType, tag); - } - }); - return; - case 'totaltracks': - this.common.track.of = GenericTagMapper_1.CommonTagMapper.toIntOrNull(tag.value); - return; - case 'totaldiscs': - this.common.disk.of = GenericTagMapper_1.CommonTagMapper.toIntOrNull(tag.value); - return; - case 'movementTotal': - this.common.movementIndex.of = GenericTagMapper_1.CommonTagMapper.toIntOrNull(tag.value); - return; - case 'track': - case 'disk': - case 'movementIndex': - const of = this.common[tag.id].of; // store of value, maybe maybe overwritten - this.common[tag.id] = GenericTagMapper_1.CommonTagMapper.normalizeTrack(tag.value); - this.common[tag.id].of = of != null ? of : this.common[tag.id].of; - return; - case 'bpm': - case 'year': - case 'originalyear': - tag.value = parseInt(tag.value, 10); - break; - case 'date': - // ToDo: be more strict on 'YYYY...' - const year = parseInt(tag.value.substr(0, 4), 10); - if (!isNaN(year)) { - this.common.year = year; - } - break; - case 'discogs_label_id': - case 'discogs_release_id': - case 'discogs_master_release_id': - case 'discogs_artist_id': - case 'discogs_votes': - tag.value = typeof tag.value === 'string' ? parseInt(tag.value, 10) : tag.value; - break; - case 'replaygain_track_gain': - case 'replaygain_track_peak': - case 'replaygain_album_gain': - case 'replaygain_album_peak': - tag.value = (0, Util_1.toRatio)(tag.value); - break; - case 'replaygain_track_minmax': - tag.value = tag.value.split(',').map(v => parseInt(v, 10)); - break; - case 'replaygain_undo': - const minMix = tag.value.split(',').map(v => parseInt(v, 10)); - tag.value = { - leftChannel: minMix[0], - rightChannel: minMix[1] - }; - break; - case 'gapless': // iTunes gap-less flag - case 'compilation': - case 'podcast': - case 'showMovement': - tag.value = tag.value === '1' || tag.value === 1; // boolean - break; - case 'isrc': // Only keep unique values - if (this.common[tag.id] && this.common[tag.id].indexOf(tag.value) !== -1) - return; - break; - default: - // nothing to do - } - if (tag.value !== null) { - this.setGenericTag(tagType, tag); - } - } - /** - * Convert native tags to common tags - * @returns {IAudioMetadata} Native + common tags - */ - toCommonMetadata() { - return { - format: this.format, - native: this.native, - quality: this.quality, - common: this.common - }; - } - /** - * Fix some common issues with picture object - * @param picture Picture - */ - async postFixPicture(picture) { - if (picture.data && picture.data.length > 0) { - if (!picture.format) { - const fileType = await FileType.fromBuffer(picture.data); - if (fileType) { - picture.format = fileType.mime; - } - else { - return null; - } - } - picture.format = picture.format.toLocaleLowerCase(); - switch (picture.format) { - case 'image/jpg': - picture.format = 'image/jpeg'; // ToDo: register warning - } - return picture; - } - this.addWarning(`Empty picture tag found`); - return null; - } - /** - * Convert native tag to common tags - */ - toCommon(tagType, tagId, value) { - const tag = { id: tagId, value }; - const genericTag = this.tagMapper.mapTag(tagType, tag, this); - if (genericTag) { - this.postMap(tagType, genericTag); - } - } - /** - * Set generic tag - */ - setGenericTag(tagType, tag) { - debug(`common.${tag.id} = ${tag.value}`); - const prio0 = this.commonOrigin[tag.id] || 1000; - const prio1 = this.originPriority[tagType]; - if ((0, GenericTagTypes_1.isSingleton)(tag.id)) { - if (prio1 <= prio0) { - this.common[tag.id] = tag.value; - this.commonOrigin[tag.id] = prio1; - } - else { - return debug(`Ignore native tag (singleton): ${tagType}.${tag.id} = ${tag.value}`); - } - } - else { - if (prio1 === prio0) { - if (!(0, GenericTagTypes_1.isUnique)(tag.id) || this.common[tag.id].indexOf(tag.value) === -1) { - this.common[tag.id].push(tag.value); - } - else { - debug(`Ignore duplicate value: ${tagType}.${tag.id} = ${tag.value}`); - } - // no effect? this.commonOrigin[tag.id] = prio1; - } - else if (prio1 < prio0) { - this.common[tag.id] = [tag.value]; - this.commonOrigin[tag.id] = prio1; - } - else { - return debug(`Ignore native tag (list): ${tagType}.${tag.id} = ${tag.value}`); - } - } - if (this.opts.observer) { - this.opts.observer({ metadata: this, tag: { type: 'common', id: tag.id, value: tag.value } }); - } - // ToDo: trigger metadata event - } -} -exports.MetadataCollector = MetadataCollector; -function joinArtists(artists) { - if (artists.length > 2) { - return artists.slice(0, artists.length - 1).join(', ') + ' & ' + artists[artists.length - 1]; - } - return artists.join(' & '); -} -exports.joinArtists = joinArtists; -//# sourceMappingURL=MetadataCollector.js.map - -/***/ }), - -/***/ 9461: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.RandomUint8ArrayReader = void 0; -/** - * Provides abstract Uint8Array access via the IRandomRead interface - */ -class RandomUint8ArrayReader { - constructor(uint8Array) { - this.uint8Array = uint8Array; - this.fileSize = uint8Array.length; - } - /** - * Read from a given position of an abstracted file or buffer. - * @param uint8Array - Uint8Array that the data will be written to. - * @param offset - Offset in the buffer to start writing at. - * @param length - Integer specifying the number of bytes to read. - * @param position - Specifies where to begin reading from in the file. - * @return Promise providing bytes read - */ - async randomRead(uint8Array, offset, length, position) { - uint8Array.set(this.uint8Array.subarray(position, position + length), offset); - return length; - } -} -exports.RandomUint8ArrayReader = RandomUint8ArrayReader; - - -/***/ }), - -/***/ 3769: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.toRatio = exports.dbToRatio = exports.ratioToDb = exports.a2hex = exports.isBitSet = exports.getBitAllignedNumber = exports.stripNulls = exports.decodeString = exports.trimRightNull = exports.findZero = exports.getBit = void 0; -function getBit(buf, off, bit) { - return (buf[off] & (1 << bit)) !== 0; -} -exports.getBit = getBit; -/** - * Found delimiting zero in uint8Array - * @param uint8Array Uint8Array to find the zero delimiter in - * @param start Offset in uint8Array - * @param end Last position to parse in uint8Array - * @param encoding The string encoding used - * @return Absolute position on uint8Array where zero found - */ -function findZero(uint8Array, start, end, encoding) { - let i = start; - if (encoding === 'utf16le') { - while (uint8Array[i] !== 0 || uint8Array[i + 1] !== 0) { - if (i >= end) - return end; - i += 2; - } - return i; - } - else { - while (uint8Array[i] !== 0) { - if (i >= end) - return end; - i++; - } - return i; - } -} -exports.findZero = findZero; -function trimRightNull(x) { - const pos0 = x.indexOf('\0'); - return pos0 === -1 ? x : x.substr(0, pos0); -} -exports.trimRightNull = trimRightNull; -function swapBytes(uint8Array) { - const l = uint8Array.length; - if ((l & 1) !== 0) - throw new Error('Buffer length must be even'); - for (let i = 0; i < l; i += 2) { - const a = uint8Array[i]; - uint8Array[i] = uint8Array[i + 1]; - uint8Array[i + 1] = a; - } - return uint8Array; -} -/** - * Decode string - */ -function decodeString(uint8Array, encoding) { - // annoying workaround for a double BOM issue - // https://github.com/leetreveil/musicmetadata/issues/84 - if (uint8Array[0] === 0xFF && uint8Array[1] === 0xFE) { // little endian - return decodeString(uint8Array.subarray(2), encoding); - } - else if (encoding === 'utf16le' && uint8Array[0] === 0xFE && uint8Array[1] === 0xFF) { - // BOM, indicating big endian decoding - if ((uint8Array.length & 1) !== 0) - throw new Error('Expected even number of octets for 16-bit unicode string'); - return decodeString(swapBytes(uint8Array), encoding); - } - return Buffer.from(uint8Array).toString(encoding); -} -exports.decodeString = decodeString; -function stripNulls(str) { - str = str.replace(/^\x00+/g, ''); - str = str.replace(/\x00+$/g, ''); - return str; -} -exports.stripNulls = stripNulls; -/** - * Read bit-aligned number start from buffer - * Total offset in bits = byteOffset * 8 + bitOffset - * @param source Byte buffer - * @param byteOffset Starting offset in bytes - * @param bitOffset Starting offset in bits: 0 = lsb - * @param len Length of number in bits - * @return Decoded bit aligned number - */ -function getBitAllignedNumber(source, byteOffset, bitOffset, len) { - const byteOff = byteOffset + ~~(bitOffset / 8); - const bitOff = bitOffset % 8; - let value = source[byteOff]; - value &= 0xff >> bitOff; - const bitsRead = 8 - bitOff; - const bitsLeft = len - bitsRead; - if (bitsLeft < 0) { - value >>= (8 - bitOff - len); - } - else if (bitsLeft > 0) { - value <<= bitsLeft; - value |= getBitAllignedNumber(source, byteOffset, bitOffset + bitsRead, bitsLeft); - } - return value; -} -exports.getBitAllignedNumber = getBitAllignedNumber; -/** - * Read bit-aligned number start from buffer - * Total offset in bits = byteOffset * 8 + bitOffset - * @param source Byte Uint8Array - * @param byteOffset Starting offset in bytes - * @param bitOffset Starting offset in bits: 0 = most significant bit, 7 is the least significant bit - * @return True if bit is set - */ -function isBitSet(source, byteOffset, bitOffset) { - return getBitAllignedNumber(source, byteOffset, bitOffset, 1) === 1; -} -exports.isBitSet = isBitSet; -function a2hex(str) { - const arr = []; - for (let i = 0, l = str.length; i < l; i++) { - const hex = Number(str.charCodeAt(i)).toString(16); - arr.push(hex.length === 1 ? '0' + hex : hex); - } - return arr.join(' '); -} -exports.a2hex = a2hex; -/** - * Convert power ratio to DB - * ratio: [0..1] - */ -function ratioToDb(ratio) { - return 10 * Math.log10(ratio); -} -exports.ratioToDb = ratioToDb; -/** - * Convert dB to ratio - * db Decibels - */ -function dbToRatio(dB) { - return Math.pow(10, dB / 10); -} -exports.dbToRatio = dbToRatio; -/** - * Convert replay gain to ratio and Decibel - * @param value string holding a ratio like '0.034' or '-7.54 dB' - */ -function toRatio(value) { - const ps = value.split(' ').map(p => p.trim().toLowerCase()); - // @ts-ignore - if (ps.length >= 1) { - const v = parseFloat(ps[0]); - return ps.length === 2 && ps[1] === 'db' ? { - dB: v, - ratio: dbToRatio(v) - } : { - dB: ratioToDb(v), - ratio: v - }; - } -} -exports.toRatio = toRatio; -//# sourceMappingURL=Util.js.map - -/***/ }), - -/***/ 523: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.scanAppendingHeaders = exports.selectCover = exports.ratingToStars = exports.orderTags = exports.parseFromTokenizer = exports.parseBuffer = exports.parseStream = void 0; -const strtok3 = __webpack_require__(5849); -const ParserFactory_1 = __webpack_require__(3275); -const RandomUint8ArrayReader_1 = __webpack_require__(9461); -const APEv2Parser_1 = __webpack_require__(6742); -const ID3v1Parser_1 = __webpack_require__(2282); -const Lyrics3_1 = __webpack_require__(9941); -/** - * Parse audio from Node Stream.Readable - * @param stream - Stream to read the audio track from - * @param options - Parsing options - * @param fileInfo - File information object or MIME-type string - * @returns Metadata - */ -function parseStream(stream, fileInfo, options = {}) { - return parseFromTokenizer(strtok3.fromStream(stream, typeof fileInfo === 'string' ? { mimeType: fileInfo } : fileInfo), options); -} -exports.parseStream = parseStream; -/** - * Parse audio from Node Buffer - * @param uint8Array - Uint8Array holding audio data - * @param fileInfo - File information object or MIME-type string - * @param options - Parsing options - * @returns Metadata - * Ref: https://github.com/Borewit/strtok3/blob/e6938c81ff685074d5eb3064a11c0b03ca934c1d/src/index.ts#L15 - */ -async function parseBuffer(uint8Array, fileInfo, options = {}) { - const bufferReader = new RandomUint8ArrayReader_1.RandomUint8ArrayReader(uint8Array); - await scanAppendingHeaders(bufferReader, options); - const tokenizer = strtok3.fromBuffer(uint8Array, typeof fileInfo === 'string' ? { mimeType: fileInfo } : fileInfo); - return parseFromTokenizer(tokenizer, options); -} -exports.parseBuffer = parseBuffer; -/** - * Parse audio from ITokenizer source - * @param tokenizer - Audio source implementing the tokenizer interface - * @param options - Parsing options - * @returns Metadata - */ -function parseFromTokenizer(tokenizer, options) { - return ParserFactory_1.ParserFactory.parseOnContentType(tokenizer, options); -} -exports.parseFromTokenizer = parseFromTokenizer; -/** - * Create a dictionary ordered by their tag id (key) - * @param nativeTags list of tags - * @returns tags indexed by id - */ -function orderTags(nativeTags) { - const tags = {}; - for (const tag of nativeTags) { - (tags[tag.id] = (tags[tag.id] || [])).push(tag.value); - } - return tags; -} -exports.orderTags = orderTags; -/** - * Convert rating to 1-5 star rating - * @param rating: Normalized rating [0..1] (common.rating[n].rating) - * @returns Number of stars: 1, 2, 3, 4 or 5 stars - */ -function ratingToStars(rating) { - return rating === undefined ? 0 : 1 + Math.round(rating * 4); -} -exports.ratingToStars = ratingToStars; -/** - * Select most likely cover image. - * @param pictures Usually metadata.common.picture - * @return Cover image, if any, otherwise null - */ -function selectCover(pictures) { - return pictures ? pictures.reduce((acc, cur) => { - if (cur.name && cur.name.toLowerCase() in ['front', 'cover', 'cover (front)']) - return cur; - return acc; - }) : null; -} -exports.selectCover = selectCover; -async function scanAppendingHeaders(randomReader, options = {}) { - let apeOffset = randomReader.fileSize; - if (await (0, ID3v1Parser_1.hasID3v1Header)(randomReader)) { - apeOffset -= 128; - const lyricsLen = await (0, Lyrics3_1.getLyricsHeaderLength)(randomReader); - apeOffset -= lyricsLen; - } - options.apeHeader = await APEv2Parser_1.APEv2Parser.findApeFooterOffset(randomReader, apeOffset); -} -exports.scanAppendingHeaders = scanAppendingHeaders; - - -/***/ }), - -/***/ 6789: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.DsdiffParser = void 0; -const Token = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const strtok3 = __webpack_require__(5849); -const FourCC_1 = __webpack_require__(8049); -const BasicParser_1 = __webpack_require__(7805); -const ID3v2Parser_1 = __webpack_require__(8928); -const DsdiffToken_1 = __webpack_require__(9187); -const debug = (0, debug_1.default)('music-metadata:parser:aiff'); -/** - * DSDIFF - Direct Stream Digital Interchange File Format (Phillips) - * - * Ref: - * - http://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_Spec.pdf - */ -class DsdiffParser extends BasicParser_1.BasicParser { - async parse() { - const header = await this.tokenizer.readToken(DsdiffToken_1.ChunkHeader64); - if (header.chunkID !== 'FRM8') - throw new Error('Unexpected chunk-ID'); - const type = (await this.tokenizer.readToken(FourCC_1.FourCcToken)).trim(); - switch (type) { - case 'DSD': - this.metadata.setFormat('container', `DSDIFF/${type}`); - this.metadata.setFormat('lossless', true); - return this.readFmt8Chunks(header.chunkSize - BigInt(FourCC_1.FourCcToken.len)); - default: - throw Error(`Unsupported DSDIFF type: ${type}`); - } - } - async readFmt8Chunks(remainingSize) { - while (remainingSize >= DsdiffToken_1.ChunkHeader64.len) { - const chunkHeader = await this.tokenizer.readToken(DsdiffToken_1.ChunkHeader64); - // If the data is an odd number of bytes in length, a pad byte must be added at the end - debug(`Chunk id=${chunkHeader.chunkID}`); - await this.readData(chunkHeader); - remainingSize -= (BigInt(DsdiffToken_1.ChunkHeader64.len) + chunkHeader.chunkSize); - } - } - async readData(header) { - debug(`Reading data of chunk[ID=${header.chunkID}, size=${header.chunkSize}]`); - const p0 = this.tokenizer.position; - switch (header.chunkID.trim()) { - case 'FVER': // 3.1 FORMAT VERSION CHUNK - const version = await this.tokenizer.readToken(Token.UINT32_LE); - debug(`DSDIFF version=${version}`); - break; - case 'PROP': // 3.2 PROPERTY CHUNK - const propType = await this.tokenizer.readToken(FourCC_1.FourCcToken); - if (propType !== 'SND ') - throw new Error('Unexpected PROP-chunk ID'); - await this.handleSoundPropertyChunks(header.chunkSize - BigInt(FourCC_1.FourCcToken.len)); - break; - case 'ID3': // Unofficial ID3 tag support - const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(Number(header.chunkSize))); - const rst = strtok3.fromBuffer(id3_data); - await new ID3v2Parser_1.ID3v2Parser().parse(this.metadata, rst, this.options); - break; - default: - debug(`Ignore chunk[ID=${header.chunkID}, size=${header.chunkSize}]`); - break; - case 'DSD': - this.metadata.setFormat('numberOfSamples', Number(header.chunkSize * BigInt(8) / BigInt(this.metadata.format.numberOfChannels))); - this.metadata.setFormat('duration', this.metadata.format.numberOfSamples / this.metadata.format.sampleRate); - break; - } - const remaining = header.chunkSize - BigInt(this.tokenizer.position - p0); - if (remaining > 0) { - debug(`After Parsing chunk, remaining ${remaining} bytes`); - await this.tokenizer.ignore(Number(remaining)); - } - } - async handleSoundPropertyChunks(remainingSize) { - debug(`Parsing sound-property-chunks, remainingSize=${remainingSize}`); - while (remainingSize > 0) { - const sndPropHeader = await this.tokenizer.readToken(DsdiffToken_1.ChunkHeader64); - debug(`Sound-property-chunk[ID=${sndPropHeader.chunkID}, size=${sndPropHeader.chunkSize}]`); - const p0 = this.tokenizer.position; - switch (sndPropHeader.chunkID.trim()) { - case 'FS': // 3.2.1 Sample Rate Chunk - const sampleRate = await this.tokenizer.readToken(Token.UINT32_BE); - this.metadata.setFormat('sampleRate', sampleRate); - break; - case 'CHNL': // 3.2.2 Channels Chunk - const numChannels = await this.tokenizer.readToken(Token.UINT16_BE); - this.metadata.setFormat('numberOfChannels', numChannels); - await this.handleChannelChunks(sndPropHeader.chunkSize - BigInt(Token.UINT16_BE.len)); - break; - case 'CMPR': // 3.2.3 Compression Type Chunk - const compressionIdCode = (await this.tokenizer.readToken(FourCC_1.FourCcToken)).trim(); - const count = await this.tokenizer.readToken(Token.UINT8); - const compressionName = await this.tokenizer.readToken(new Token.StringType(count, 'ascii')); - if (compressionIdCode === 'DSD') { - this.metadata.setFormat('lossless', true); - this.metadata.setFormat('bitsPerSample', 1); - } - this.metadata.setFormat('codec', `${compressionIdCode} (${compressionName})`); - break; - case 'ABSS': // 3.2.4 Absolute Start Time Chunk - const hours = await this.tokenizer.readToken(Token.UINT16_BE); - const minutes = await this.tokenizer.readToken(Token.UINT8); - const seconds = await this.tokenizer.readToken(Token.UINT8); - const samples = await this.tokenizer.readToken(Token.UINT32_BE); - debug(`ABSS ${hours}:${minutes}:${seconds}.${samples}`); - break; - case 'LSCO': // 3.2.5 Loudspeaker Configuration Chunk - const lsConfig = await this.tokenizer.readToken(Token.UINT16_BE); - debug(`LSCO lsConfig=${lsConfig}`); - break; - case 'COMT': - default: - debug(`Unknown sound-property-chunk[ID=${sndPropHeader.chunkID}, size=${sndPropHeader.chunkSize}]`); - await this.tokenizer.ignore(Number(sndPropHeader.chunkSize)); - } - const remaining = sndPropHeader.chunkSize - BigInt(this.tokenizer.position - p0); - if (remaining > 0) { - debug(`After Parsing sound-property-chunk ${sndPropHeader.chunkSize}, remaining ${remaining} bytes`); - await this.tokenizer.ignore(Number(remaining)); - } - remainingSize -= BigInt(DsdiffToken_1.ChunkHeader64.len) + sndPropHeader.chunkSize; - debug(`Parsing sound-property-chunks, remainingSize=${remainingSize}`); - } - if (this.metadata.format.lossless && this.metadata.format.sampleRate && this.metadata.format.numberOfChannels && this.metadata.format.bitsPerSample) { - const bitrate = this.metadata.format.sampleRate * this.metadata.format.numberOfChannels * this.metadata.format.bitsPerSample; - this.metadata.setFormat('bitrate', bitrate); - } - } - async handleChannelChunks(remainingSize) { - debug(`Parsing channel-chunks, remainingSize=${remainingSize}`); - const channels = []; - while (remainingSize >= FourCC_1.FourCcToken.len) { - const channelId = await this.tokenizer.readToken(FourCC_1.FourCcToken); - debug(`Channel[ID=${channelId}]`); - channels.push(channelId); - remainingSize -= BigInt(FourCC_1.FourCcToken.len); - } - debug(`Channels: ${channels.join(', ')}`); - return channels; - } -} -exports.DsdiffParser = DsdiffParser; - - -/***/ }), - -/***/ 9187: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ChunkHeader64 = void 0; -const Token = __webpack_require__(3416); -const FourCC_1 = __webpack_require__(8049); -/** - * DSDIFF chunk header - * The data-size encoding is deviating from EA-IFF 85 - * Ref: http://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_Spec.pdf - */ -exports.ChunkHeader64 = { - len: 12, - get: (buf, off) => { - return { - // Group-ID - chunkID: FourCC_1.FourCcToken.get(buf, off), - // Size - chunkSize: Token.INT64_BE.get(buf, off + 4) - }; - } -}; - - -/***/ }), - -/***/ 4101: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.FormatChunk = exports.ChannelType = exports.DsdChunk = exports.ChunkHeader = void 0; -const Token = __webpack_require__(3416); -const FourCC_1 = __webpack_require__(8049); -/** - * Common chunk DSD header: the 'chunk name (Four-CC)' & chunk size - */ -exports.ChunkHeader = { - len: 12, - get: (buf, off) => { - return { id: FourCC_1.FourCcToken.get(buf, off), size: Token.UINT64_LE.get(buf, off + 4) }; - } -}; -/** - * Common chunk DSD header: the 'chunk name (Four-CC)' & chunk size - */ -exports.DsdChunk = { - len: 16, - get: (buf, off) => { - return { - fileSize: Token.INT64_LE.get(buf, off), - metadataPointer: Token.INT64_LE.get(buf, off + 8) - }; - } -}; -var ChannelType; -(function (ChannelType) { - ChannelType[ChannelType["mono"] = 1] = "mono"; - ChannelType[ChannelType["stereo"] = 2] = "stereo"; - ChannelType[ChannelType["channels"] = 3] = "channels"; - ChannelType[ChannelType["quad"] = 4] = "quad"; - ChannelType[ChannelType["4 channels"] = 5] = "4 channels"; - ChannelType[ChannelType["5 channels"] = 6] = "5 channels"; - ChannelType[ChannelType["5.1 channels"] = 7] = "5.1 channels"; -})(ChannelType = exports.ChannelType || (exports.ChannelType = {})); -/** - * Common chunk DSD header: the 'chunk name (Four-CC)' & chunk size - */ -exports.FormatChunk = { - len: 40, - get: (buf, off) => { - return { - formatVersion: Token.INT32_LE.get(buf, off), - formatID: Token.INT32_LE.get(buf, off + 4), - channelType: Token.INT32_LE.get(buf, off + 8), - channelNum: Token.INT32_LE.get(buf, off + 12), - samplingFrequency: Token.INT32_LE.get(buf, off + 16), - bitsPerSample: Token.INT32_LE.get(buf, off + 20), - sampleCount: Token.INT64_LE.get(buf, off + 24), - blockSizePerChannel: Token.INT32_LE.get(buf, off + 32) - }; - } -}; - - -/***/ }), - -/***/ 1533: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.DsfParser = void 0; -const debug_1 = __webpack_require__(1227); -const AbstractID3Parser_1 = __webpack_require__(5159); -const DsfChunk_1 = __webpack_require__(4101); -const ID3v2Parser_1 = __webpack_require__(8928); -const debug = (0, debug_1.default)('music-metadata:parser:DSF'); -/** - * DSF (dsd stream file) File Parser - * Ref: https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf - */ -class DsfParser extends AbstractID3Parser_1.AbstractID3Parser { - async postId3v2Parse() { - const p0 = this.tokenizer.position; // mark start position, normally 0 - const chunkHeader = await this.tokenizer.readToken(DsfChunk_1.ChunkHeader); - if (chunkHeader.id !== 'DSD ') - throw new Error('Invalid chunk signature'); - this.metadata.setFormat('container', 'DSF'); - this.metadata.setFormat('lossless', true); - const dsdChunk = await this.tokenizer.readToken(DsfChunk_1.DsdChunk); - if (dsdChunk.metadataPointer === BigInt(0)) { - debug(`No ID3v2 tag present`); - } - else { - debug(`expect ID3v2 at offset=${dsdChunk.metadataPointer}`); - await this.parseChunks(dsdChunk.fileSize - chunkHeader.size); - // Jump to ID3 header - await this.tokenizer.ignore(Number(dsdChunk.metadataPointer) - this.tokenizer.position - p0); - return new ID3v2Parser_1.ID3v2Parser().parse(this.metadata, this.tokenizer, this.options); - } - } - async parseChunks(bytesRemaining) { - while (bytesRemaining >= DsfChunk_1.ChunkHeader.len) { - const chunkHeader = await this.tokenizer.readToken(DsfChunk_1.ChunkHeader); - debug(`Parsing chunk name=${chunkHeader.id} size=${chunkHeader.size}`); - switch (chunkHeader.id) { - case 'fmt ': - const formatChunk = await this.tokenizer.readToken(DsfChunk_1.FormatChunk); - this.metadata.setFormat('numberOfChannels', formatChunk.channelNum); - this.metadata.setFormat('sampleRate', formatChunk.samplingFrequency); - this.metadata.setFormat('bitsPerSample', formatChunk.bitsPerSample); - this.metadata.setFormat('numberOfSamples', formatChunk.sampleCount); - this.metadata.setFormat('duration', Number(formatChunk.sampleCount) / formatChunk.samplingFrequency); - const bitrate = formatChunk.bitsPerSample * formatChunk.samplingFrequency * formatChunk.channelNum; - this.metadata.setFormat('bitrate', bitrate); - return; // We got what we want, stop further processing of chunks - default: - this.tokenizer.ignore(Number(chunkHeader.size) - DsfChunk_1.ChunkHeader.len); - break; - } - bytesRemaining -= chunkHeader.size; - } - } -} -exports.DsfParser = DsfParser; - - -/***/ }), - -/***/ 498: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.FlacParser = void 0; -const token_types_1 = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const util = __webpack_require__(3769); -const Vorbis_1 = __webpack_require__(2127); -const AbstractID3Parser_1 = __webpack_require__(5159); -const FourCC_1 = __webpack_require__(8049); -const VorbisParser_1 = __webpack_require__(4210); -const VorbisDecoder_1 = __webpack_require__(441); -const debug = (0, debug_1.default)('music-metadata:parser:FLAC'); -/** - * FLAC supports up to 128 kinds of metadata blocks; currently the following are defined: - * ref: https://xiph.org/flac/format.html#metadata_block - */ -var BlockType; -(function (BlockType) { - BlockType[BlockType["STREAMINFO"] = 0] = "STREAMINFO"; - BlockType[BlockType["PADDING"] = 1] = "PADDING"; - BlockType[BlockType["APPLICATION"] = 2] = "APPLICATION"; - BlockType[BlockType["SEEKTABLE"] = 3] = "SEEKTABLE"; - BlockType[BlockType["VORBIS_COMMENT"] = 4] = "VORBIS_COMMENT"; - BlockType[BlockType["CUESHEET"] = 5] = "CUESHEET"; - BlockType[BlockType["PICTURE"] = 6] = "PICTURE"; -})(BlockType || (BlockType = {})); -class FlacParser extends AbstractID3Parser_1.AbstractID3Parser { - constructor() { - super(...arguments); - this.padding = 0; - } - /** - * Initialize parser with output (metadata), input (tokenizer) & parsing options (options). - * @param {INativeMetadataCollector} metadata Output - * @param {ITokenizer} tokenizer Input - * @param {IOptions} options Parsing options - */ - init(metadata, tokenizer, options) { - super.init(metadata, tokenizer, options); - this.vorbisParser = new VorbisParser_1.VorbisParser(metadata, options); - return this; - } - async postId3v2Parse() { - const fourCC = await this.tokenizer.readToken(FourCC_1.FourCcToken); - if (fourCC.toString() !== 'fLaC') { - throw new Error('Invalid FLAC preamble'); - } - let blockHeader; - do { - // Read block header - blockHeader = await this.tokenizer.readToken(Metadata.BlockHeader); - // Parse block data - await this.parseDataBlock(blockHeader); - } while (!blockHeader.lastBlock); - if (this.tokenizer.fileInfo.size && this.metadata.format.duration) { - const dataSize = this.tokenizer.fileInfo.size - this.tokenizer.position; - this.metadata.setFormat('bitrate', 8 * dataSize / this.metadata.format.duration); - } - } - parseDataBlock(blockHeader) { - debug(`blockHeader type=${blockHeader.type}, length=${blockHeader.length}`); - switch (blockHeader.type) { - case BlockType.STREAMINFO: - return this.parseBlockStreamInfo(blockHeader.length); - case BlockType.PADDING: - this.padding += blockHeader.length; - break; - case BlockType.APPLICATION: - break; - case BlockType.SEEKTABLE: - break; - case BlockType.VORBIS_COMMENT: - return this.parseComment(blockHeader.length); - case BlockType.CUESHEET: - break; - case BlockType.PICTURE: - return this.parsePicture(blockHeader.length).then(); - default: - this.metadata.addWarning('Unknown block type: ' + blockHeader.type); - } - // Ignore data block - return this.tokenizer.ignore(blockHeader.length).then(); - } - /** - * Parse STREAMINFO - */ - async parseBlockStreamInfo(dataLen) { - if (dataLen !== Metadata.BlockStreamInfo.len) - throw new Error('Unexpected block-stream-info length'); - const streamInfo = await this.tokenizer.readToken(Metadata.BlockStreamInfo); - this.metadata.setFormat('container', 'FLAC'); - this.metadata.setFormat('codec', 'FLAC'); - this.metadata.setFormat('lossless', true); - this.metadata.setFormat('numberOfChannels', streamInfo.channels); - this.metadata.setFormat('bitsPerSample', streamInfo.bitsPerSample); - this.metadata.setFormat('sampleRate', streamInfo.sampleRate); - if (streamInfo.totalSamples > 0) { - this.metadata.setFormat('duration', streamInfo.totalSamples / streamInfo.sampleRate); - } - } - /** - * Parse VORBIS_COMMENT - * Ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-640004.2.3 - */ - async parseComment(dataLen) { - const data = await this.tokenizer.readToken(new token_types_1.Uint8ArrayType(dataLen)); - const decoder = new VorbisDecoder_1.VorbisDecoder(data, 0); - decoder.readStringUtf8(); // vendor (skip) - const commentListLength = decoder.readInt32(); - for (let i = 0; i < commentListLength; i++) { - const tag = decoder.parseUserComment(); - this.vorbisParser.addTag(tag.key, tag.value); - } - } - async parsePicture(dataLen) { - if (this.options.skipCovers) { - return this.tokenizer.ignore(dataLen); - } - else { - const picture = await this.tokenizer.readToken(new Vorbis_1.VorbisPictureToken(dataLen)); - this.vorbisParser.addTag('METADATA_BLOCK_PICTURE', picture); - } - } -} -exports.FlacParser = FlacParser; -class Metadata { -} -Metadata.BlockHeader = { - len: 4, - get: (buf, off) => { - return { - lastBlock: util.getBit(buf, off, 7), - type: util.getBitAllignedNumber(buf, off, 1, 7), - length: token_types_1.UINT24_BE.get(buf, off + 1) - }; - } -}; -/** - * METADATA_BLOCK_DATA - * Ref: https://xiph.org/flac/format.html#metadata_block_streaminfo - */ -Metadata.BlockStreamInfo = { - len: 34, - get: (buf, off) => { - return { - // The minimum block size (in samples) used in the stream. - minimumBlockSize: token_types_1.UINT16_BE.get(buf, off), - // The maximum block size (in samples) used in the stream. - // (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream. - maximumBlockSize: token_types_1.UINT16_BE.get(buf, off + 2) / 1000, - // The minimum frame size (in bytes) used in the stream. - // May be 0 to imply the value is not known. - minimumFrameSize: token_types_1.UINT24_BE.get(buf, off + 4), - // The maximum frame size (in bytes) used in the stream. - // May be 0 to imply the value is not known. - maximumFrameSize: token_types_1.UINT24_BE.get(buf, off + 7), - // Sample rate in Hz. Though 20 bits are available, - // the maximum sample rate is limited by the structure of frame headers to 655350Hz. - // Also, a value of 0 is invalid. - sampleRate: token_types_1.UINT24_BE.get(buf, off + 10) >> 4, - // probably slower: sampleRate: common.getBitAllignedNumber(buf, off + 10, 0, 20), - // (number of channels)-1. FLAC supports from 1 to 8 channels - channels: util.getBitAllignedNumber(buf, off + 12, 4, 3) + 1, - // bits per sample)-1. - // FLAC supports from 4 to 32 bits per sample. Currently the reference encoder and decoders only support up to 24 bits per sample. - bitsPerSample: util.getBitAllignedNumber(buf, off + 12, 7, 5) + 1, - // Total samples in stream. - // 'Samples' means inter-channel sample, i.e. one second of 44.1Khz audio will have 44100 samples regardless of the number of channels. - // A value of zero here means the number of total samples is unknown. - totalSamples: util.getBitAllignedNumber(buf, off + 13, 4, 36), - // the MD5 hash of the file (see notes for usage... it's a littly tricky) - fileMD5: new token_types_1.Uint8ArrayType(16).get(buf, off + 18) - }; - } -}; - - -/***/ }), - -/***/ 2282: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.hasID3v1Header = exports.ID3v1Parser = exports.Genres = void 0; -const debug_1 = __webpack_require__(1227); -const token_types_1 = __webpack_require__(3416); -const util = __webpack_require__(3769); -const BasicParser_1 = __webpack_require__(7805); -const APEv2Parser_1 = __webpack_require__(6742); -const debug = (0, debug_1.default)('music-metadata:parser:ID3v1'); -/** - * ID3v1 Genre mappings - * Ref: https://de.wikipedia.org/wiki/Liste_der_ID3v1-Genres - */ -exports.Genres = [ - 'Blues', 'Classic Rock', 'Country', 'Dance', 'Disco', 'Funk', 'Grunge', 'Hip-Hop', - 'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B', 'Rap', 'Reggae', 'Rock', - 'Techno', 'Industrial', 'Alternative', 'Ska', 'Death Metal', 'Pranks', 'Soundtrack', - 'Euro-Techno', 'Ambient', 'Trip-Hop', 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance', - 'Classical', 'Instrumental', 'Acid', 'House', 'Game', 'Sound Clip', 'Gospel', 'Noise', - 'Alt. Rock', 'Bass', 'Soul', 'Punk', 'Space', 'Meditative', 'Instrumental Pop', - 'Instrumental Rock', 'Ethnic', 'Gothic', 'Darkwave', 'Techno-Industrial', - 'Electronic', 'Pop-Folk', 'Eurodance', 'Dream', 'Southern Rock', 'Comedy', 'Cult', - 'Gangsta Rap', 'Top 40', 'Christian Rap', 'Pop/Funk', 'Jungle', 'Native American', - 'Cabaret', 'New Wave', 'Psychedelic', 'Rave', 'Showtunes', 'Trailer', 'Lo-Fi', 'Tribal', - 'Acid Punk', 'Acid Jazz', 'Polka', 'Retro', 'Musical', 'Rock & Roll', 'Hard Rock', - 'Folk', 'Folk/Rock', 'National Folk', 'Swing', 'Fast-Fusion', 'Bebob', 'Latin', 'Revival', - 'Celtic', 'Bluegrass', 'Avantgarde', 'Gothic Rock', 'Progressive Rock', 'Psychedelic Rock', - 'Symphonic Rock', 'Slow Rock', 'Big Band', 'Chorus', 'Easy Listening', 'Acoustic', 'Humour', - 'Speech', 'Chanson', 'Opera', 'Chamber Music', 'Sonata', 'Symphony', 'Booty Bass', 'Primus', - 'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba', 'Folklore', - 'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle', 'Duet', 'Punk Rock', 'Drum Solo', - 'A Cappella', 'Euro-House', 'Dance Hall', 'Goa', 'Drum & Bass', 'Club-House', - 'Hardcore', 'Terror', 'Indie', 'BritPop', 'Negerpunk', 'Polsk Punk', 'Beat', - 'Christian Gangsta Rap', 'Heavy Metal', 'Black Metal', 'Crossover', 'Contemporary Christian', - 'Christian Rock', 'Merengue', 'Salsa', 'Thrash Metal', 'Anime', 'JPop', 'Synthpop', - 'Abstract', 'Art Rock', 'Baroque', 'Bhangra', 'Big Beat', 'Breakbeat', 'Chillout', - 'Downtempo', 'Dub', 'EBM', 'Eclectic', 'Electro', 'Electroclash', 'Emo', 'Experimental', - 'Garage', 'Global', 'IDM', 'Illbient', 'Industro-Goth', 'Jam Band', 'Krautrock', - 'Leftfield', 'Lounge', 'Math Rock', 'New Romantic', 'Nu-Breakz', 'Post-Punk', 'Post-Rock', - 'Psytrance', 'Shoegaze', 'Space Rock', 'Trop Rock', 'World Music', 'Neoclassical', 'Audiobook', - 'Audio Theatre', 'Neue Deutsche Welle', 'Podcast', 'Indie Rock', 'G-Funk', 'Dubstep', - 'Garage Rock', 'Psybient' -]; -/** - * Spec: http://id3.org/ID3v1 - * Wiki: https://en.wikipedia.org/wiki/ID3 - */ -const Iid3v1Token = { - len: 128, - /** - * @param buf Buffer possibly holding the 128 bytes ID3v1.1 metadata header - * @param off Offset in buffer in bytes - * @returns ID3v1.1 header if first 3 bytes equals 'TAG', otherwise null is returned - */ - get: (buf, off) => { - const header = new Id3v1StringType(3).get(buf, off); - return header === 'TAG' ? { - header, - title: new Id3v1StringType(30).get(buf, off + 3), - artist: new Id3v1StringType(30).get(buf, off + 33), - album: new Id3v1StringType(30).get(buf, off + 63), - year: new Id3v1StringType(4).get(buf, off + 93), - comment: new Id3v1StringType(28).get(buf, off + 97), - // ID3v1.1 separator for track - zeroByte: token_types_1.UINT8.get(buf, off + 127), - // track: ID3v1.1 field added by Michael Mutschler - track: token_types_1.UINT8.get(buf, off + 126), - genre: token_types_1.UINT8.get(buf, off + 127) - } : null; - } -}; -class Id3v1StringType extends token_types_1.StringType { - constructor(len) { - super(len, 'binary'); - } - get(buf, off) { - let value = super.get(buf, off); - value = util.trimRightNull(value); - value = value.trim(); - return value.length > 0 ? value : undefined; - } -} -class ID3v1Parser extends BasicParser_1.BasicParser { - static getGenre(genreIndex) { - if (genreIndex < exports.Genres.length) { - return exports.Genres[genreIndex]; - } - return undefined; // ToDO: generate warning - } - async parse() { - if (!this.tokenizer.fileInfo.size) { - debug('Skip checking for ID3v1 because the file-size is unknown'); - return; - } - if (this.options.apeHeader) { - this.tokenizer.ignore(this.options.apeHeader.offset - this.tokenizer.position); - const apeParser = new APEv2Parser_1.APEv2Parser(); - apeParser.init(this.metadata, this.tokenizer, this.options); - await apeParser.parseTags(this.options.apeHeader.footer); - } - const offset = this.tokenizer.fileInfo.size - Iid3v1Token.len; - if (this.tokenizer.position > offset) { - debug('Already consumed the last 128 bytes'); - return; - } - const header = await this.tokenizer.readToken(Iid3v1Token, offset); - if (header) { - debug('ID3v1 header found at: pos=%s', this.tokenizer.fileInfo.size - Iid3v1Token.len); - for (const id of ['title', 'artist', 'album', 'comment', 'track', 'year']) { - if (header[id] && header[id] !== '') - this.addTag(id, header[id]); - } - const genre = ID3v1Parser.getGenre(header.genre); - if (genre) - this.addTag('genre', genre); - } - else { - debug('ID3v1 header not found at: pos=%s', this.tokenizer.fileInfo.size - Iid3v1Token.len); - } - } - addTag(id, value) { - this.metadata.addTag('ID3v1', id, value); - } -} -exports.ID3v1Parser = ID3v1Parser; -async function hasID3v1Header(reader) { - if (reader.fileSize >= 128) { - const tag = Buffer.alloc(3); - await reader.randomRead(tag, 0, tag.length, reader.fileSize - 128); - return tag.toString('binary') === 'TAG'; - } - return false; -} -exports.hasID3v1Header = hasID3v1Header; - - -/***/ }), - -/***/ 2939: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ID3v1TagMapper = void 0; -const GenericTagMapper_1 = __webpack_require__(9918); -/** - * ID3v1 tag mappings - */ -const id3v1TagMap = { - title: 'title', - artist: 'artist', - album: 'album', - year: 'year', - comment: 'comment', - track: 'track', - genre: 'genre' -}; -class ID3v1TagMapper extends GenericTagMapper_1.CommonTagMapper { - constructor() { - super(['ID3v1'], id3v1TagMap); - } -} -exports.ID3v1TagMapper = ID3v1TagMapper; -//# sourceMappingURL=ID3v1TagMap.js.map - -/***/ }), - -/***/ 5159: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.AbstractID3Parser = void 0; -const core_1 = __webpack_require__(5849); -const debug_1 = __webpack_require__(1227); -const ID3v2Token_1 = __webpack_require__(8281); -const ID3v2Parser_1 = __webpack_require__(8928); -const ID3v1Parser_1 = __webpack_require__(2282); -const BasicParser_1 = __webpack_require__(7805); -const debug = (0, debug_1.default)('music-metadata:parser:ID3'); -/** - * Abstract parser which tries take ID3v2 and ID3v1 headers. - */ -class AbstractID3Parser extends BasicParser_1.BasicParser { - constructor() { - super(...arguments); - this.id3parser = new ID3v2Parser_1.ID3v2Parser(); - } - static async startsWithID3v2Header(tokenizer) { - return (await tokenizer.peekToken(ID3v2Token_1.ID3v2Header)).fileIdentifier === 'ID3'; - } - async parse() { - try { - await this.parseID3v2(); - } - catch (err) { - if (err instanceof core_1.EndOfStreamError) { - debug(`End-of-stream`); - } - else { - throw err; - } - } - } - finalize() { - return; - } - async parseID3v2() { - await this.tryReadId3v2Headers(); - debug('End of ID3v2 header, go to MPEG-parser: pos=%s', this.tokenizer.position); - await this.postId3v2Parse(); - if (this.options.skipPostHeaders && this.metadata.hasAny()) { - this.finalize(); - } - else { - const id3v1parser = new ID3v1Parser_1.ID3v1Parser(); - await id3v1parser.init(this.metadata, this.tokenizer, this.options).parse(); - this.finalize(); - } - } - async tryReadId3v2Headers() { - const id3Header = await this.tokenizer.peekToken(ID3v2Token_1.ID3v2Header); - if (id3Header.fileIdentifier === 'ID3') { - debug('Found ID3v2 header, pos=%s', this.tokenizer.position); - await this.id3parser.parse(this.metadata, this.tokenizer, this.options); - return this.tryReadId3v2Headers(); - } - } -} -exports.AbstractID3Parser = AbstractID3Parser; - - -/***/ }), - -/***/ 907: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.FrameParser = exports.parseGenre = void 0; -const debug_1 = __webpack_require__(1227); -const Token = __webpack_require__(3416); -const util = __webpack_require__(3769); -const ID3v2Token_1 = __webpack_require__(8281); -const ID3v1Parser_1 = __webpack_require__(2282); -const debug = (0, debug_1.default)('music-metadata:id3v2:frame-parser'); -const defaultEnc = 'latin1'; // latin1 == iso-8859-1; -function parseGenre(origVal) { - // match everything inside parentheses - const genres = []; - let code; - let word = ''; - for (const c of origVal) { - if (typeof code === 'string') { - if (c === '(' && code === '') { - word += '('; - code = undefined; - } - else if (c === ')') { - if (word !== '') { - genres.push(word); - word = ''; - } - const genre = parseGenreCode(code); - if (genre) { - genres.push(genre); - } - code = undefined; - } - else - code += c; - } - else if (c === '(') { - code = ''; - } - else { - word += c; - } - } - if (word) { - if (genres.length === 0 && word.match(/^\d*$/)) { - word = ID3v1Parser_1.Genres[word]; - } - genres.push(word); - } - return genres; -} -exports.parseGenre = parseGenre; -function parseGenreCode(code) { - if (code === 'RX') - return 'Remix'; - if (code === 'CR') - return 'Cover'; - if (code.match(/^\d*$/)) { - return ID3v1Parser_1.Genres[code]; - } -} -class FrameParser { - /** - * Create id3v2 frame parser - * @param major - Major version, e.g. (4) for id3v2.4 - * @param warningCollector - Used to collect decode issue - */ - constructor(major, warningCollector) { - this.major = major; - this.warningCollector = warningCollector; - } - readData(uint8Array, type, includeCovers) { - if (uint8Array.length === 0) { - this.warningCollector.addWarning(`id3v2.${this.major} header has empty tag type=${type}`); - return; - } - const { encoding, bom } = ID3v2Token_1.TextEncodingToken.get(uint8Array, 0); - const length = uint8Array.length; - let offset = 0; - let output = []; // ToDo - const nullTerminatorLength = FrameParser.getNullTerminatorLength(encoding); - let fzero; - const out = {}; - debug(`Parsing tag type=${type}, encoding=${encoding}, bom=${bom}`); - switch (type !== 'TXXX' && type[0] === 'T' ? 'T*' : type) { - case 'T*': // 4.2.1. Text information frames - details - case 'IPLS': // v2.3: Involved people list - case 'MVIN': - case 'MVNM': - case 'PCS': - case 'PCST': - let text; - try { - text = util.decodeString(uint8Array.slice(1), encoding).replace(/\x00+$/, ''); - } - catch (error) { - this.warningCollector.addWarning(`id3v2.${this.major} type=${type} header has invalid string value: ${error.message}`); - } - switch (type) { - case 'TMCL': // Musician credits list - case 'TIPL': // Involved people list - case 'IPLS': // Involved people list - output = this.splitValue(type, text); - output = FrameParser.functionList(output); - break; - case 'TRK': - case 'TRCK': - case 'TPOS': - output = text; - break; - case 'TCOM': - case 'TEXT': - case 'TOLY': - case 'TOPE': - case 'TPE1': - case 'TSRC': - // id3v2.3 defines that TCOM, TEXT, TOLY, TOPE & TPE1 values are separated by / - output = this.splitValue(type, text); - break; - case 'TCO': - case 'TCON': - output = this.splitValue(type, text).map(v => parseGenre(v)).reduce((acc, val) => acc.concat(val), []); - break; - case 'PCS': - case 'PCST': - // TODO: Why `default` not results `1` but `''`? - output = this.major >= 4 ? this.splitValue(type, text) : [text]; - output = (Array.isArray(output) && output[0] === '') ? 1 : 0; - break; - default: - output = this.major >= 4 ? this.splitValue(type, text) : [text]; - } - break; - case 'TXXX': - output = FrameParser.readIdentifierAndData(uint8Array, offset + 1, length, encoding); - output = { - description: output.id, - text: this.splitValue(type, util.decodeString(output.data, encoding).replace(/\x00+$/, '')) - }; - break; - case 'PIC': - case 'APIC': - if (includeCovers) { - const pic = {}; - offset += 1; - switch (this.major) { - case 2: - pic.format = util.decodeString(uint8Array.slice(offset, offset + 3), 'latin1'); // 'latin1'; // latin1 == iso-8859-1; - offset += 3; - break; - case 3: - case 4: - fzero = util.findZero(uint8Array, offset, length, defaultEnc); - pic.format = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc); - offset = fzero + 1; - break; - default: - throw new Error('Warning: unexpected major versionIndex: ' + this.major); - } - pic.format = FrameParser.fixPictureMimeType(pic.format); - pic.type = ID3v2Token_1.AttachedPictureType[uint8Array[offset]]; - offset += 1; - fzero = util.findZero(uint8Array, offset, length, encoding); - pic.description = util.decodeString(uint8Array.slice(offset, fzero), encoding); - offset = fzero + nullTerminatorLength; - pic.data = Buffer.from(uint8Array.slice(offset, length)); - output = pic; - } - break; - case 'CNT': - case 'PCNT': - output = Token.UINT32_BE.get(uint8Array, 0); - break; - case 'SYLT': - // skip text encoding (1 byte), - // language (3 bytes), - // time stamp format (1 byte), - // content tagTypes (1 byte), - // content descriptor (1 byte) - offset += 7; - output = []; - while (offset < length) { - const txt = uint8Array.slice(offset, offset = util.findZero(uint8Array, offset, length, encoding)); - offset += 5; // push offset forward one + 4 byte timestamp - output.push(util.decodeString(txt, encoding)); - } - break; - case 'ULT': - case 'USLT': - case 'COM': - case 'COMM': - offset += 1; - out.language = util.decodeString(uint8Array.slice(offset, offset + 3), defaultEnc); - offset += 3; - fzero = util.findZero(uint8Array, offset, length, encoding); - out.description = util.decodeString(uint8Array.slice(offset, fzero), encoding); - offset = fzero + nullTerminatorLength; - out.text = util.decodeString(uint8Array.slice(offset, length), encoding).replace(/\x00+$/, ''); - output = [out]; - break; - case 'UFID': - output = FrameParser.readIdentifierAndData(uint8Array, offset, length, defaultEnc); - output = { owner_identifier: output.id, identifier: output.data }; - break; - case 'PRIV': // private frame - output = FrameParser.readIdentifierAndData(uint8Array, offset, length, defaultEnc); - output = { owner_identifier: output.id, data: output.data }; - break; - case 'POPM': // Popularimeter - fzero = util.findZero(uint8Array, offset, length, defaultEnc); - const email = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc); - offset = fzero + 1; - const dataLen = length - offset; - output = { - email, - rating: Token.UINT8.get(uint8Array, offset), - counter: dataLen >= 5 ? Token.UINT32_BE.get(uint8Array, offset + 1) : undefined - }; - break; - case 'GEOB': { // General encapsulated object - fzero = util.findZero(uint8Array, offset + 1, length, encoding); - const mimeType = util.decodeString(uint8Array.slice(offset + 1, fzero), defaultEnc); - offset = fzero + 1; - fzero = util.findZero(uint8Array, offset, length - offset, encoding); - const filename = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc); - offset = fzero + 1; - fzero = util.findZero(uint8Array, offset, length - offset, encoding); - const description = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc); - output = { - type: mimeType, - filename, - description, - data: uint8Array.slice(offset + 1, length) - }; - break; - } - // W-Frames: - case 'WCOM': - case 'WCOP': - case 'WOAF': - case 'WOAR': - case 'WOAS': - case 'WORS': - case 'WPAY': - case 'WPUB': - // Decode URL - output = util.decodeString(uint8Array.slice(offset, fzero), defaultEnc); - break; - case 'WXXX': { - // Decode URL - fzero = util.findZero(uint8Array, offset + 1, length, encoding); - const description = util.decodeString(uint8Array.slice(offset + 1, fzero), encoding); - offset = fzero + (encoding === 'utf16le' ? 2 : 1); - output = { description, url: util.decodeString(uint8Array.slice(offset, length), defaultEnc) }; - break; - } - case 'WFD': - case 'WFED': - output = util.decodeString(uint8Array.slice(offset + 1, util.findZero(uint8Array, offset + 1, length, encoding)), encoding); - break; - case 'MCDI': { - // Music CD identifier - output = uint8Array.slice(0, length); - break; - } - default: - debug('Warning: unsupported id3v2-tag-type: ' + type); - break; - } - return output; - } - static fixPictureMimeType(pictureType) { - pictureType = pictureType.toLocaleLowerCase(); - switch (pictureType) { - case 'jpg': - return 'image/jpeg'; - case 'png': - return 'image/png'; - } - return pictureType; - } - /** - * Converts TMCL (Musician credits list) or TIPL (Involved people list) - * @param entries - */ - static functionList(entries) { - const res = {}; - for (let i = 0; i + 1 < entries.length; i += 2) { - const names = entries[i + 1].split(','); - res[entries[i]] = res.hasOwnProperty(entries[i]) ? res[entries[i]].concat(names) : names; - } - return res; - } - /** - * id3v2.4 defines that multiple T* values are separated by 0x00 - * id3v2.3 defines that TCOM, TEXT, TOLY, TOPE & TPE1 values are separated by / - * @param tag - Tag name - * @param text - Concatenated tag value - * @returns Split tag value - */ - splitValue(tag, text) { - let values; - if (this.major < 4) { - values = text.split(/\x00/g); - if (values.length > 1) { - this.warningCollector.addWarning(`ID3v2.${this.major} ${tag} uses non standard null-separator.`); - } - else { - values = text.split(/\//g); - } - } - else { - values = text.split(/\x00/g); - } - return FrameParser.trimArray(values); - } - static trimArray(values) { - return values.map(value => value.replace(/\x00+$/, '').trim()); - } - static readIdentifierAndData(uint8Array, offset, length, encoding) { - const fzero = util.findZero(uint8Array, offset, length, encoding); - const id = util.decodeString(uint8Array.slice(offset, fzero), encoding); - offset = fzero + FrameParser.getNullTerminatorLength(encoding); - return { id, data: uint8Array.slice(offset, length) }; - } - static getNullTerminatorLength(enc) { - return enc === 'utf16le' ? 2 : 1; - } -} -exports.FrameParser = FrameParser; - - -/***/ }), - -/***/ 7183: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ID3v22TagMapper = exports.id3v22TagMap = void 0; -const CaseInsensitiveTagMap_1 = __webpack_require__(4132); -/** - * ID3v2.2 tag mappings - */ -exports.id3v22TagMap = { - TT2: 'title', - TP1: 'artist', - TP2: 'albumartist', - TAL: 'album', - TYE: 'year', - COM: 'comment', - TRK: 'track', - TPA: 'disk', - TCO: 'genre', - PIC: 'picture', - TCM: 'composer', - TOR: 'originaldate', - TOT: 'originalalbum', - TXT: 'lyricist', - TP3: 'conductor', - TPB: 'label', - TT1: 'grouping', - TT3: 'subtitle', - TLA: 'language', - TCR: 'copyright', - WCP: 'license', - TEN: 'encodedby', - TSS: 'encodersettings', - WAR: 'website', - 'COM:iTunPGAP': 'gapless' - /* ToDo: iTunes tags: - 'COM:iTunNORM': , - 'COM:iTunSMPB': 'encoder delay', - 'COM:iTunes_CDDB_IDs' - */ , - PCS: 'podcast', - TCP: "compilation", - TDR: 'date', - TS2: 'albumartistsort', - TSA: 'albumsort', - TSC: 'composersort', - TSP: 'artistsort', - TST: 'titlesort', - WFD: 'podcasturl', - TBP: 'bpm' -}; -class ID3v22TagMapper extends CaseInsensitiveTagMap_1.CaseInsensitiveTagMap { - constructor() { - super(['ID3v2.2'], exports.id3v22TagMap); - } -} -exports.ID3v22TagMapper = ID3v22TagMapper; -//# sourceMappingURL=ID3v22TagMapper.js.map - -/***/ }), - -/***/ 4005: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ID3v24TagMapper = void 0; -const GenericTagMapper_1 = __webpack_require__(9918); -const CaseInsensitiveTagMap_1 = __webpack_require__(4132); -const util = __webpack_require__(3769); -/** - * ID3v2.3/ID3v2.4 tag mappings - */ -const id3v24TagMap = { - // id3v2.3 - TIT2: 'title', - TPE1: 'artist', - 'TXXX:Artists': 'artists', - TPE2: 'albumartist', - TALB: 'album', - TDRV: 'date', - /** - * Original release year - */ - TORY: 'originalyear', - TPOS: 'disk', - TCON: 'genre', - APIC: 'picture', - TCOM: 'composer', - 'USLT:description': 'lyrics', - TSOA: 'albumsort', - TSOT: 'titlesort', - TOAL: 'originalalbum', - TSOP: 'artistsort', - TSO2: 'albumartistsort', - TSOC: 'composersort', - TEXT: 'lyricist', - 'TXXX:Writer': 'writer', - TPE3: 'conductor', - // 'IPLS:instrument': 'performer:instrument', // ToDo - TPE4: 'remixer', - 'IPLS:arranger': 'arranger', - 'IPLS:engineer': 'engineer', - 'IPLS:producer': 'producer', - 'IPLS:DJ-mix': 'djmixer', - 'IPLS:mix': 'mixer', - TPUB: 'label', - TIT1: 'grouping', - TIT3: 'subtitle', - TRCK: 'track', - TCMP: 'compilation', - POPM: 'rating', - TBPM: 'bpm', - TMED: 'media', - 'TXXX:CATALOGNUMBER': 'catalognumber', - 'TXXX:MusicBrainz Album Status': 'releasestatus', - 'TXXX:MusicBrainz Album Type': 'releasetype', - /** - * Release country as documented: https://picard.musicbrainz.org/docs/mappings/#cite_note-0 - */ - 'TXXX:MusicBrainz Album Release Country': 'releasecountry', - /** - * Release country as implemented // ToDo: report - */ - 'TXXX:RELEASECOUNTRY': 'releasecountry', - 'TXXX:SCRIPT': 'script', - TLAN: 'language', - TCOP: 'copyright', - WCOP: 'license', - TENC: 'encodedby', - TSSE: 'encodersettings', - 'TXXX:BARCODE': 'barcode', - 'TXXX:ISRC': 'isrc', - TSRC: 'isrc', - 'TXXX:ASIN': 'asin', - 'TXXX:originalyear': 'originalyear', - 'UFID:http://musicbrainz.org': 'musicbrainz_recordingid', - 'TXXX:MusicBrainz Release Track Id': 'musicbrainz_trackid', - 'TXXX:MusicBrainz Album Id': 'musicbrainz_albumid', - 'TXXX:MusicBrainz Artist Id': 'musicbrainz_artistid', - 'TXXX:MusicBrainz Album Artist Id': 'musicbrainz_albumartistid', - 'TXXX:MusicBrainz Release Group Id': 'musicbrainz_releasegroupid', - 'TXXX:MusicBrainz Work Id': 'musicbrainz_workid', - 'TXXX:MusicBrainz TRM Id': 'musicbrainz_trmid', - 'TXXX:MusicBrainz Disc Id': 'musicbrainz_discid', - 'TXXX:ACOUSTID_ID': 'acoustid_id', - 'TXXX:Acoustid Id': 'acoustid_id', - 'TXXX:Acoustid Fingerprint': 'acoustid_fingerprint', - 'TXXX:MusicIP PUID': 'musicip_puid', - 'TXXX:MusicMagic Fingerprint': 'musicip_fingerprint', - WOAR: 'website', - // id3v2.4 - // ToDo: In same sequence as defined at http://id3.org/id3v2.4.0-frames - TDRC: 'date', - TYER: 'year', - TDOR: 'originaldate', - // 'TMCL:instrument': 'performer:instrument', - 'TIPL:arranger': 'arranger', - 'TIPL:engineer': 'engineer', - 'TIPL:producer': 'producer', - 'TIPL:DJ-mix': 'djmixer', - 'TIPL:mix': 'mixer', - TMOO: 'mood', - // additional mappings: - SYLT: 'lyrics', - TSST: 'discsubtitle', - TKEY: 'key', - COMM: 'comment', - TOPE: 'originalartist', - // Windows Media Player - 'PRIV:AverageLevel': 'averageLevel', - 'PRIV:PeakLevel': 'peakLevel', - // Discogs - 'TXXX:DISCOGS_ARTIST_ID': 'discogs_artist_id', - 'TXXX:DISCOGS_ARTISTS': 'artists', - 'TXXX:DISCOGS_ARTIST_NAME': 'artists', - 'TXXX:DISCOGS_ALBUM_ARTISTS': 'albumartist', - 'TXXX:DISCOGS_CATALOG': 'catalognumber', - 'TXXX:DISCOGS_COUNTRY': 'releasecountry', - 'TXXX:DISCOGS_DATE': 'originaldate', - 'TXXX:DISCOGS_LABEL': 'label', - 'TXXX:DISCOGS_LABEL_ID': 'discogs_label_id', - 'TXXX:DISCOGS_MASTER_RELEASE_ID': 'discogs_master_release_id', - 'TXXX:DISCOGS_RATING': 'discogs_rating', - 'TXXX:DISCOGS_RELEASED': 'date', - 'TXXX:DISCOGS_RELEASE_ID': 'discogs_release_id', - 'TXXX:DISCOGS_VOTES': 'discogs_votes', - 'TXXX:CATALOGID': 'catalognumber', - 'TXXX:STYLE': 'genre', - 'TXXX:REPLAYGAIN_TRACK_PEAK': 'replaygain_track_peak', - 'TXXX:REPLAYGAIN_TRACK_GAIN': 'replaygain_track_gain', - 'TXXX:REPLAYGAIN_ALBUM_PEAK': 'replaygain_album_peak', - 'TXXX:REPLAYGAIN_ALBUM_GAIN': 'replaygain_album_gain', - 'TXXX:MP3GAIN_MINMAX': 'replaygain_track_minmax', - 'TXXX:MP3GAIN_ALBUM_MINMAX': 'replaygain_album_minmax', - 'TXXX:MP3GAIN_UNDO': 'replaygain_undo', - MVNM: 'movement', - MVIN: 'movementIndex', - PCST: 'podcast', - TCAT: 'category', - TDES: 'description', - TDRL: 'date', - TGID: 'podcastId', - TKWD: 'keywords', - WFED: 'podcasturl' -}; -class ID3v24TagMapper extends CaseInsensitiveTagMap_1.CaseInsensitiveTagMap { - static toRating(popm) { - return { - source: popm.email, - rating: popm.rating > 0 ? (popm.rating - 1) / 254 * GenericTagMapper_1.CommonTagMapper.maxRatingScore : undefined - }; - } - constructor() { - super(['ID3v2.3', 'ID3v2.4'], id3v24TagMap); - } - /** - * Handle post mapping exceptions / correction - * @param tag to post map - * @param warnings Wil be used to register (collect) warnings - * @return Common value e.g. "Buena Vista Social Club" - */ - postMap(tag, warnings) { - switch (tag.id) { - case 'UFID': // decode MusicBrainz Recording Id - if (tag.value.owner_identifier === 'http://musicbrainz.org') { - tag.id += ':' + tag.value.owner_identifier; - tag.value = util.decodeString(tag.value.identifier, 'latin1'); // latin1 == iso-8859-1 - } - break; - case 'PRIV': - switch (tag.value.owner_identifier) { - // decode Windows Media Player - case 'AverageLevel': - case 'PeakValue': - tag.id += ':' + tag.value.owner_identifier; - tag.value = tag.value.data.length === 4 ? tag.value.data.readUInt32LE(0) : null; - if (tag.value === null) { - warnings.addWarning(`Failed to parse PRIV:PeakValue`); - } - break; - default: - warnings.addWarning(`Unknown PRIV owner-identifier: ${tag.value.owner_identifier}`); - } - break; - case 'COMM': - tag.value = tag.value ? tag.value.text : null; - break; - case 'POPM': - tag.value = ID3v24TagMapper.toRating(tag.value); - break; - default: - break; - } - } -} -exports.ID3v24TagMapper = ID3v24TagMapper; -//# sourceMappingURL=ID3v24TagMapper.js.map - -/***/ }), - -/***/ 8928: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ID3v2Parser = void 0; -const Token = __webpack_require__(3416); -const util = __webpack_require__(3769); -const FrameParser_1 = __webpack_require__(907); -const ID3v2Token_1 = __webpack_require__(8281); -class ID3v2Parser { - static removeUnsyncBytes(buffer) { - let readI = 0; - let writeI = 0; - while (readI < buffer.length - 1) { - if (readI !== writeI) { - buffer[writeI] = buffer[readI]; - } - readI += (buffer[readI] === 0xFF && buffer[readI + 1] === 0) ? 2 : 1; - writeI++; - } - if (readI < buffer.length) { - buffer[writeI++] = buffer[readI]; - } - return buffer.slice(0, writeI); - } - static getFrameHeaderLength(majorVer) { - switch (majorVer) { - case 2: - return 6; - case 3: - case 4: - return 10; - default: - throw new Error('header versionIndex is incorrect'); - } - } - static readFrameFlags(b) { - return { - status: { - tag_alter_preservation: util.getBit(b, 0, 6), - file_alter_preservation: util.getBit(b, 0, 5), - read_only: util.getBit(b, 0, 4) - }, - format: { - grouping_identity: util.getBit(b, 1, 7), - compression: util.getBit(b, 1, 3), - encryption: util.getBit(b, 1, 2), - unsynchronisation: util.getBit(b, 1, 1), - data_length_indicator: util.getBit(b, 1, 0) - } - }; - } - static readFrameData(uint8Array, frameHeader, majorVer, includeCovers, warningCollector) { - const frameParser = new FrameParser_1.FrameParser(majorVer, warningCollector); - switch (majorVer) { - case 2: - return frameParser.readData(uint8Array, frameHeader.id, includeCovers); - case 3: - case 4: - if (frameHeader.flags.format.unsynchronisation) { - uint8Array = ID3v2Parser.removeUnsyncBytes(uint8Array); - } - if (frameHeader.flags.format.data_length_indicator) { - uint8Array = uint8Array.slice(4, uint8Array.length); - } - return frameParser.readData(uint8Array, frameHeader.id, includeCovers); - default: - throw new Error('Unexpected majorVer: ' + majorVer); - } - } - /** - * Create a combined tag key, of tag & description - * @param tag e.g.: COM - * @param description e.g. iTunPGAP - * @returns string e.g. COM:iTunPGAP - */ - static makeDescriptionTagName(tag, description) { - return tag + (description ? ':' + description : ''); - } - async parse(metadata, tokenizer, options) { - this.tokenizer = tokenizer; - this.metadata = metadata; - this.options = options; - const id3Header = await this.tokenizer.readToken(ID3v2Token_1.ID3v2Header); - if (id3Header.fileIdentifier !== 'ID3') { - throw new Error('expected ID3-header file-identifier \'ID3\' was not found'); - } - this.id3Header = id3Header; - this.headerType = ('ID3v2.' + id3Header.version.major); - return id3Header.flags.isExtendedHeader ? this.parseExtendedHeader() : this.parseId3Data(id3Header.size); - } - async parseExtendedHeader() { - const extendedHeader = await this.tokenizer.readToken(ID3v2Token_1.ExtendedHeader); - const dataRemaining = extendedHeader.size - ID3v2Token_1.ExtendedHeader.len; - return dataRemaining > 0 ? this.parseExtendedHeaderData(dataRemaining, extendedHeader.size) : this.parseId3Data(this.id3Header.size - extendedHeader.size); - } - async parseExtendedHeaderData(dataRemaining, extendedHeaderSize) { - await this.tokenizer.ignore(dataRemaining); - return this.parseId3Data(this.id3Header.size - extendedHeaderSize); - } - async parseId3Data(dataLen) { - const uint8Array = await this.tokenizer.readToken(new Token.Uint8ArrayType(dataLen)); - for (const tag of this.parseMetadata(uint8Array)) { - if (tag.id === 'TXXX') { - if (tag.value) { - for (const text of tag.value.text) { - this.addTag(ID3v2Parser.makeDescriptionTagName(tag.id, tag.value.description), text); - } - } - } - else if (tag.id === 'COM') { - for (const value of tag.value) { - this.addTag(ID3v2Parser.makeDescriptionTagName(tag.id, value.description), value.text); - } - } - else if (tag.id === 'COMM') { - for (const value of tag.value) { - this.addTag(ID3v2Parser.makeDescriptionTagName(tag.id, value.description), value); - } - } - else if (Array.isArray(tag.value)) { - for (const value of tag.value) { - this.addTag(tag.id, value); - } - } - else { - this.addTag(tag.id, tag.value); - } - } - } - addTag(id, value) { - this.metadata.addTag(this.headerType, id, value); - } - parseMetadata(data) { - let offset = 0; - const tags = []; - while (true) { - if (offset === data.length) - break; - const frameHeaderLength = ID3v2Parser.getFrameHeaderLength(this.id3Header.version.major); - if (offset + frameHeaderLength > data.length) { - this.metadata.addWarning('Illegal ID3v2 tag length'); - break; - } - const frameHeaderBytes = data.slice(offset, offset += frameHeaderLength); - const frameHeader = this.readFrameHeader(frameHeaderBytes, this.id3Header.version.major); - const frameDataBytes = data.slice(offset, offset += frameHeader.length); - const values = ID3v2Parser.readFrameData(frameDataBytes, frameHeader, this.id3Header.version.major, !this.options.skipCovers, this.metadata); - if (values) { - tags.push({ id: frameHeader.id, value: values }); - } - } - return tags; - } - readFrameHeader(uint8Array, majorVer) { - let header; - switch (majorVer) { - case 2: - header = { - id: Buffer.from(uint8Array.slice(0, 3)).toString('ascii'), - length: Token.UINT24_BE.get(uint8Array, 3) - }; - if (!header.id.match(/[A-Z0-9]{3}/g)) { - this.metadata.addWarning(`Invalid ID3v2.${this.id3Header.version.major} frame-header-ID: ${header.id}`); - } - break; - case 3: - case 4: - header = { - id: Buffer.from(uint8Array.slice(0, 4)).toString('ascii'), - length: (majorVer === 4 ? ID3v2Token_1.UINT32SYNCSAFE : Token.UINT32_BE).get(uint8Array, 4), - flags: ID3v2Parser.readFrameFlags(uint8Array.slice(8, 10)) - }; - if (!header.id.match(/[A-Z0-9]{4}/g)) { - this.metadata.addWarning(`Invalid ID3v2.${this.id3Header.version.major} frame-header-ID: ${header.id}`); - } - break; - default: - throw new Error('Unexpected majorVer: ' + majorVer); - } - return header; - } -} -exports.ID3v2Parser = ID3v2Parser; - - -/***/ }), - -/***/ 8281: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.TextEncodingToken = exports.ExtendedHeader = exports.ID3v2Header = exports.UINT32SYNCSAFE = exports.AttachedPictureType = void 0; -const Token = __webpack_require__(3416); -const util = __webpack_require__(3769); -/** - * The picture type according to the ID3v2 APIC frame - * Ref: http://id3.org/id3v2.3.0#Attached_picture - */ -var AttachedPictureType; -(function (AttachedPictureType) { - AttachedPictureType[AttachedPictureType["Other"] = 0] = "Other"; - AttachedPictureType[AttachedPictureType["32x32 pixels 'file icon' (PNG only)"] = 1] = "32x32 pixels 'file icon' (PNG only)"; - AttachedPictureType[AttachedPictureType["Other file icon"] = 2] = "Other file icon"; - AttachedPictureType[AttachedPictureType["Cover (front)"] = 3] = "Cover (front)"; - AttachedPictureType[AttachedPictureType["Cover (back)"] = 4] = "Cover (back)"; - AttachedPictureType[AttachedPictureType["Leaflet page"] = 5] = "Leaflet page"; - AttachedPictureType[AttachedPictureType["Media (e.g. label side of CD)"] = 6] = "Media (e.g. label side of CD)"; - AttachedPictureType[AttachedPictureType["Lead artist/lead performer/soloist"] = 7] = "Lead artist/lead performer/soloist"; - AttachedPictureType[AttachedPictureType["Artist/performer"] = 8] = "Artist/performer"; - AttachedPictureType[AttachedPictureType["Conductor"] = 9] = "Conductor"; - AttachedPictureType[AttachedPictureType["Band/Orchestra"] = 10] = "Band/Orchestra"; - AttachedPictureType[AttachedPictureType["Composer"] = 11] = "Composer"; - AttachedPictureType[AttachedPictureType["Lyricist/text writer"] = 12] = "Lyricist/text writer"; - AttachedPictureType[AttachedPictureType["Recording Location"] = 13] = "Recording Location"; - AttachedPictureType[AttachedPictureType["During recording"] = 14] = "During recording"; - AttachedPictureType[AttachedPictureType["During performance"] = 15] = "During performance"; - AttachedPictureType[AttachedPictureType["Movie/video screen capture"] = 16] = "Movie/video screen capture"; - AttachedPictureType[AttachedPictureType["A bright coloured fish"] = 17] = "A bright coloured fish"; - AttachedPictureType[AttachedPictureType["Illustration"] = 18] = "Illustration"; - AttachedPictureType[AttachedPictureType["Band/artist logotype"] = 19] = "Band/artist logotype"; - AttachedPictureType[AttachedPictureType["Publisher/Studio logotype"] = 20] = "Publisher/Studio logotype"; -})(AttachedPictureType = exports.AttachedPictureType || (exports.AttachedPictureType = {})); -/** - * 28 bits (representing up to 256MB) integer, the msb is 0 to avoid 'false syncsignals'. - * 4 * %0xxxxxxx - */ -exports.UINT32SYNCSAFE = { - get: (buf, off) => { - return buf[off + 3] & 0x7f | ((buf[off + 2]) << 7) | - ((buf[off + 1]) << 14) | ((buf[off]) << 21); - }, - len: 4 -}; -/** - * ID3v2 header - * Ref: http://id3.org/id3v2.3.0#ID3v2_header - * ToDo - */ -exports.ID3v2Header = { - len: 10, - get: (buf, off) => { - return { - // ID3v2/file identifier "ID3" - fileIdentifier: new Token.StringType(3, 'ascii').get(buf, off), - // ID3v2 versionIndex - version: { - major: Token.INT8.get(buf, off + 3), - revision: Token.INT8.get(buf, off + 4) - }, - // ID3v2 flags - flags: { - // Unsynchronisation - unsynchronisation: util.getBit(buf, off + 5, 7), - // Extended header - isExtendedHeader: util.getBit(buf, off + 5, 6), - // Experimental indicator - expIndicator: util.getBit(buf, off + 5, 5), - footer: util.getBit(buf, off + 5, 4) - }, - size: exports.UINT32SYNCSAFE.get(buf, off + 6) - }; - } -}; -exports.ExtendedHeader = { - len: 10, - get: (buf, off) => { - return { - // Extended header size - size: Token.UINT32_BE.get(buf, off), - // Extended Flags - extendedFlags: Token.UINT16_BE.get(buf, off + 4), - // Size of padding - sizeOfPadding: Token.UINT32_BE.get(buf, off + 6), - // CRC data present - crcDataPresent: util.getBit(buf, off + 4, 31) - }; - } -}; -exports.TextEncodingToken = { - len: 1, - get: (uint8Array, off) => { - switch (uint8Array[off]) { - case 0x00: - return { encoding: 'latin1' }; // binary - case 0x01: - return { encoding: 'utf16le', bom: true }; - case 0x02: - return { encoding: 'utf16le', bom: false }; - case 0x03: - return { encoding: 'utf8', bom: false }; - default: - return { encoding: 'utf8', bom: false }; - } - } -}; - - -/***/ }), - -/***/ 4633: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Header = void 0; -const Token = __webpack_require__(3416); -const FourCC_1 = __webpack_require__(8049); -/** - * Common AIFF chunk header - */ -exports.Header = { - len: 8, - get: (buf, off) => { - return { - // Chunk type ID - chunkID: FourCC_1.FourCcToken.get(buf, off), - // Chunk size - chunkSize: Number(BigInt(Token.UINT32_BE.get(buf, off + 4))) - }; - } -}; - - -/***/ }), - -/***/ 9941: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getLyricsHeaderLength = exports.endTag2 = void 0; -exports.endTag2 = 'LYRICS200'; -async function getLyricsHeaderLength(reader) { - if (reader.fileSize >= 143) { - const buf = Buffer.alloc(15); - await reader.randomRead(buf, 0, buf.length, reader.fileSize - 143); - const txt = buf.toString('binary'); - const tag = txt.substr(6); - if (tag === exports.endTag2) { - return parseInt(txt.substr(0, 6), 10) + 15; - } - } - return 0; -} -exports.getLyricsHeaderLength = getLyricsHeaderLength; - - -/***/ }), - -/***/ 3121: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.elements = void 0; -const types_1 = __webpack_require__(8591); -/** - * Elements of document type description - * Derived from https://github.com/tungol/EBML/blob/master/doctypes/matroska.dtd - * Extended with: - * - https://www.matroska.org/technical/specs/index.html - */ -exports.elements = { - 0x1a45dfa3: { - name: 'ebml', - container: { - 0x4286: { name: 'ebmlVersion', value: types_1.DataType.uint }, - 0x42f7: { name: 'ebmlReadVersion', value: types_1.DataType.uint }, - 0x42f2: { name: 'ebmlMaxIDWidth', value: types_1.DataType.uint }, - 0x42f3: { name: 'ebmlMaxSizeWidth', value: types_1.DataType.uint }, - 0x4282: { name: 'docType', value: types_1.DataType.string }, - 0x4287: { name: 'docTypeVersion', value: types_1.DataType.uint }, - 0x4285: { name: 'docTypeReadVersion', value: types_1.DataType.uint } // 5.1.7 - } - }, - // Matroska segments - 0x18538067: { - name: 'segment', - container: { - // Meta Seek Information - 0x114d9b74: { - name: 'seekHead', - container: { - 0x4dbb: { - name: 'seek', - container: { - 0x53ab: { name: 'seekId', value: types_1.DataType.binary }, - 0x53ac: { name: 'seekPosition', value: types_1.DataType.uint } - } - } - } - }, - // Segment Information - 0x1549a966: { - name: 'info', - container: { - 0x73a4: { name: 'uid', value: types_1.DataType.uid }, - 0x7384: { name: 'filename', value: types_1.DataType.string }, - 0x3cb923: { name: 'prevUID', value: types_1.DataType.uid }, - 0x3c83ab: { name: 'prevFilename', value: types_1.DataType.string }, - 0x3eb923: { name: 'nextUID', value: types_1.DataType.uid }, - 0x3e83bb: { name: 'nextFilename', value: types_1.DataType.string }, - 0x2ad7b1: { name: 'timecodeScale', value: types_1.DataType.uint }, - 0x4489: { name: 'duration', value: types_1.DataType.float }, - 0x4461: { name: 'dateUTC', value: types_1.DataType.uint }, - 0x7ba9: { name: 'title', value: types_1.DataType.string }, - 0x4d80: { name: 'muxingApp', value: types_1.DataType.string }, - 0x5741: { name: 'writingApp', value: types_1.DataType.string } - } - }, - // Cluster - 0x1f43b675: { - name: 'cluster', - multiple: true, - container: { - 0xe7: { name: 'timecode', value: types_1.DataType.uid }, - 0xa3: { name: 'unknown', value: types_1.DataType.binary }, - 0xa7: { name: 'position', value: types_1.DataType.uid }, - 0xab: { name: 'prevSize', value: types_1.DataType.uid } - } - }, - // Track - 0x1654ae6b: { - name: 'tracks', - container: { - 0xae: { - name: 'entries', - multiple: true, - container: { - 0xd7: { name: 'trackNumber', value: types_1.DataType.uint }, - 0x73c5: { name: 'uid', value: types_1.DataType.uid }, - 0x83: { name: 'trackType', value: types_1.DataType.uint }, - 0xb9: { name: 'flagEnabled', value: types_1.DataType.bool }, - 0x88: { name: 'flagDefault', value: types_1.DataType.bool }, - 0x55aa: { name: 'flagForced', value: types_1.DataType.bool }, - 0x9c: { name: 'flagLacing', value: types_1.DataType.bool }, - 0x6de7: { name: 'minCache', value: types_1.DataType.uint }, - 0x6de8: { name: 'maxCache', value: types_1.DataType.uint }, - 0x23e383: { name: 'defaultDuration', value: types_1.DataType.uint }, - 0x23314f: { name: 'timecodeScale', value: types_1.DataType.float }, - 0x536e: { name: 'name', value: types_1.DataType.string }, - 0x22b59c: { name: 'language', value: types_1.DataType.string }, - 0x86: { name: 'codecID', value: types_1.DataType.string }, - 0x63a2: { name: 'codecPrivate', value: types_1.DataType.binary }, - 0x258688: { name: 'codecName', value: types_1.DataType.string }, - 0x3a9697: { name: 'codecSettings', value: types_1.DataType.string }, - 0x3b4040: { name: 'codecInfoUrl', value: types_1.DataType.string }, - 0x26b240: { name: 'codecDownloadUrl', value: types_1.DataType.string }, - 0xaa: { name: 'codecDecodeAll', value: types_1.DataType.bool }, - 0x6fab: { name: 'trackOverlay', value: types_1.DataType.uint }, - // Video - 0xe0: { - name: 'video', - container: { - 0x9a: { name: 'flagInterlaced', value: types_1.DataType.bool }, - 0x53b8: { name: 'stereoMode', value: types_1.DataType.uint }, - 0xb0: { name: 'pixelWidth', value: types_1.DataType.uint }, - 0xba: { name: 'pixelHeight', value: types_1.DataType.uint }, - 0x54b0: { name: 'displayWidth', value: types_1.DataType.uint }, - 0x54ba: { name: 'displayHeight', value: types_1.DataType.uint }, - 0x54b3: { name: 'aspectRatioType', value: types_1.DataType.uint }, - 0x2eb524: { name: 'colourSpace', value: types_1.DataType.uint }, - 0x2fb523: { name: 'gammaValue', value: types_1.DataType.float } - } - }, - // Audio - 0xe1: { - name: 'audio', - container: { - 0xb5: { name: 'samplingFrequency', value: types_1.DataType.float }, - 0x78b5: { name: 'outputSamplingFrequency', value: types_1.DataType.float }, - 0x9f: { name: 'channels', value: types_1.DataType.uint }, - 0x94: { name: 'channels', value: types_1.DataType.uint }, - 0x7d7b: { name: 'channelPositions', value: types_1.DataType.binary }, - 0x6264: { name: 'bitDepth', value: types_1.DataType.uint } - } - }, - // Content Encoding - 0x6d80: { - name: 'contentEncodings', - container: { - 0x6240: { - name: 'contentEncoding', - container: { - 0x5031: { name: 'order', value: types_1.DataType.uint }, - 0x5032: { name: 'scope', value: types_1.DataType.bool }, - 0x5033: { name: 'type', value: types_1.DataType.uint }, - 0x5034: { - name: 'contentEncoding', - container: { - 0x4254: { name: 'contentCompAlgo', value: types_1.DataType.uint }, - 0x4255: { name: 'contentCompSettings', value: types_1.DataType.binary } - } - }, - 0x5035: { - name: 'contentEncoding', - container: { - 0x47e1: { name: 'contentEncAlgo', value: types_1.DataType.uint }, - 0x47e2: { name: 'contentEncKeyID', value: types_1.DataType.binary }, - 0x47e3: { name: 'contentSignature ', value: types_1.DataType.binary }, - 0x47e4: { name: 'ContentSigKeyID ', value: types_1.DataType.binary }, - 0x47e5: { name: 'contentSigAlgo ', value: types_1.DataType.uint }, - 0x47e6: { name: 'contentSigHashAlgo ', value: types_1.DataType.uint } - } - }, - 0x6264: { name: 'bitDepth', value: types_1.DataType.uint } - } - } - } - } - } - } - } - }, - // Cueing Data - 0x1c53bb6b: { - name: 'cues', - container: { - 0xbb: { - name: 'cuePoint', - container: { - 0xb3: { name: 'cueTime', value: types_1.DataType.uid }, - 0xb7: { - name: 'positions', - container: { - 0xf7: { name: 'track', value: types_1.DataType.uint }, - 0xf1: { name: 'clusterPosition', value: types_1.DataType.uint }, - 0x5378: { name: 'blockNumber', value: types_1.DataType.uint }, - 0xea: { name: 'codecState', value: types_1.DataType.uint }, - 0xdb: { - name: 'reference', container: { - 0x96: { name: 'time', value: types_1.DataType.uint }, - 0x97: { name: 'cluster', value: types_1.DataType.uint }, - 0x535f: { name: 'number', value: types_1.DataType.uint }, - 0xeb: { name: 'codecState', value: types_1.DataType.uint } - } - }, - 0xf0: { name: 'relativePosition', value: types_1.DataType.uint } // extended - } - } - } - } - } - }, - // Attachment - 0x1941a469: { - name: 'attachments', - container: { - 0x61a7: { - name: 'attachedFiles', - multiple: true, - container: { - 0x467e: { name: 'description', value: types_1.DataType.string }, - 0x466e: { name: 'name', value: types_1.DataType.string }, - 0x4660: { name: 'mimeType', value: types_1.DataType.string }, - 0x465c: { name: 'data', value: types_1.DataType.binary }, - 0x46ae: { name: 'uid', value: types_1.DataType.uid } - } - } - } - }, - // Chapters - 0x1043a770: { - name: 'chapters', - container: { - 0x45b9: { - name: 'editionEntry', - container: { - 0xb6: { - name: 'chapterAtom', - container: { - 0x73c4: { name: 'uid', value: types_1.DataType.uid }, - 0x91: { name: 'timeStart', value: types_1.DataType.uint }, - 0x92: { name: 'timeEnd', value: types_1.DataType.uid }, - 0x98: { name: 'hidden', value: types_1.DataType.bool }, - 0x4598: { name: 'enabled', value: types_1.DataType.uid }, - 0x8f: { name: 'track', container: { - 0x89: { name: 'trackNumber', value: types_1.DataType.uid }, - 0x80: { - name: 'display', container: { - 0x85: { name: 'string', value: types_1.DataType.string }, - 0x437c: { name: 'language ', value: types_1.DataType.string }, - 0x437e: { name: 'country ', value: types_1.DataType.string } - } - } - } - } - } - } - } - } - } - }, - // Tagging - 0x1254c367: { - name: 'tags', - container: { - 0x7373: { - name: 'tag', - multiple: true, - container: { - 0x63c0: { - name: 'target', - container: { - 0x63c5: { name: 'tagTrackUID', value: types_1.DataType.uid }, - 0x63c4: { name: 'tagChapterUID', value: types_1.DataType.uint }, - 0x63c6: { name: 'tagAttachmentUID', value: types_1.DataType.uid }, - 0x63ca: { name: 'targetType', value: types_1.DataType.string }, - 0x68ca: { name: 'targetTypeValue', value: types_1.DataType.uint }, - 0x63c9: { name: 'tagEditionUID', value: types_1.DataType.uid } // extended - } - }, - 0x67c8: { - name: 'simpleTags', - multiple: true, - container: { - 0x45a3: { name: 'name', value: types_1.DataType.string }, - 0x4487: { name: 'string', value: types_1.DataType.string }, - 0x4485: { name: 'binary', value: types_1.DataType.binary }, - 0x447a: { name: 'language', value: types_1.DataType.string }, - 0x447b: { name: 'languageIETF', value: types_1.DataType.string }, - 0x4484: { name: 'default', value: types_1.DataType.bool } // extended - } - } - } - } - } - } - } - } -}; - - -/***/ }), - -/***/ 78: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MatroskaParser = void 0; -const token_types_1 = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const BasicParser_1 = __webpack_require__(7805); -const types_1 = __webpack_require__(8591); -const matroskaDtd = __webpack_require__(3121); -const debug = (0, debug_1.default)('music-metadata:parser:matroska'); -/** - * Extensible Binary Meta Language (EBML) parser - * https://en.wikipedia.org/wiki/Extensible_Binary_Meta_Language - * http://matroska.sourceforge.net/technical/specs/rfc/index.html - * - * WEBM VP8 AUDIO FILE - */ -class MatroskaParser extends BasicParser_1.BasicParser { - constructor() { - super(); - this.padding = 0; - this.parserMap = new Map(); - this.ebmlMaxIDLength = 4; - this.ebmlMaxSizeLength = 8; - this.parserMap.set(types_1.DataType.uint, e => this.readUint(e)); - this.parserMap.set(types_1.DataType.string, e => this.readString(e)); - this.parserMap.set(types_1.DataType.binary, e => this.readBuffer(e)); - this.parserMap.set(types_1.DataType.uid, async (e) => await this.readUint(e) === 1); - this.parserMap.set(types_1.DataType.bool, e => this.readFlag(e)); - this.parserMap.set(types_1.DataType.float, e => this.readFloat(e)); - } - /** - * Initialize parser with output (metadata), input (tokenizer) & parsing options (options). - * @param {INativeMetadataCollector} metadata Output - * @param {ITokenizer} tokenizer Input - * @param {IOptions} options Parsing options - */ - init(metadata, tokenizer, options) { - super.init(metadata, tokenizer, options); - return this; - } - async parse() { - const matroska = await this.parseContainer(matroskaDtd.elements, this.tokenizer.fileInfo.size, []); - this.metadata.setFormat('container', `EBML/${matroska.ebml.docType}`); - if (matroska.segment) { - const info = matroska.segment.info; - if (info) { - const timecodeScale = info.timecodeScale ? info.timecodeScale : 1000000; - const duration = info.duration * timecodeScale / 1000000000; - this.addTag('segment:title', info.title); - this.metadata.setFormat('duration', duration); - } - const audioTracks = matroska.segment.tracks; - if (audioTracks && audioTracks.entries) { - audioTracks.entries.forEach(entry => { - const stream = { - codecName: entry.codecID.replace('A_', '').replace('V_', ''), - codecSettings: entry.codecSettings, - flagDefault: entry.flagDefault, - flagLacing: entry.flagLacing, - flagEnabled: entry.flagEnabled, - language: entry.language, - name: entry.name, - type: entry.trackType, - audio: entry.audio, - video: entry.video - }; - this.metadata.addStreamInfo(stream); - }); - const audioTrack = audioTracks.entries - .filter(entry => { - return entry.trackType === types_1.TrackType.audio.valueOf(); - }) - .reduce((acc, cur) => { - if (!acc) { - return cur; - } - if (!acc.flagDefault && cur.flagDefault) { - return cur; - } - if (cur.trackNumber && cur.trackNumber < acc.trackNumber) { - return cur; - } - return acc; - }, null); - if (audioTrack) { - this.metadata.setFormat('codec', audioTrack.codecID.replace('A_', '')); - this.metadata.setFormat('sampleRate', audioTrack.audio.samplingFrequency); - this.metadata.setFormat('numberOfChannels', audioTrack.audio.channels); - } - if (matroska.segment.tags) { - matroska.segment.tags.tag.forEach(tag => { - const target = tag.target; - const targetType = (target === null || target === void 0 ? void 0 : target.targetTypeValue) ? types_1.TargetType[target.targetTypeValue] : ((target === null || target === void 0 ? void 0 : target.targetType) ? target.targetType : 'track'); - tag.simpleTags.forEach(simpleTag => { - const value = simpleTag.string ? simpleTag.string : simpleTag.binary; - this.addTag(`${targetType}:${simpleTag.name}`, value); - }); - }); - } - if (matroska.segment.attachments) { - matroska.segment.attachments.attachedFiles - .filter(file => file.mimeType.startsWith('image/')) - .map(file => { - return { - data: file.data, - format: file.mimeType, - description: file.description, - name: file.name - }; - }).forEach(picture => { - this.addTag('picture', picture); - }); - } - } - } - } - async parseContainer(container, posDone, path) { - const tree = {}; - while (this.tokenizer.position < posDone) { - let element; - try { - element = await this.readElement(); - } - catch (error) { - if (error.message === 'End-Of-Stream') { - break; - } - throw error; - } - const type = container[element.id]; - if (type) { - debug(`Element: name=${type.name}, container=${!!type.container}`); - if (type.container) { - const res = await this.parseContainer(type.container, element.len >= 0 ? this.tokenizer.position + element.len : -1, path.concat([type.name])); - if (type.multiple) { - if (!tree[type.name]) { - tree[type.name] = []; - } - tree[type.name].push(res); - } - else { - tree[type.name] = res; - } - } - else { - tree[type.name] = await this.parserMap.get(type.value)(element); - } - } - else { - switch (element.id) { - case 0xec: // void - this.padding += element.len; - await this.tokenizer.ignore(element.len); - break; - default: - debug(`parseEbml: path=${path.join('/')}, unknown element: id=${element.id.toString(16)}`); - this.padding += element.len; - await this.tokenizer.ignore(element.len); - } - } - } - return tree; - } - async readVintData(maxLength) { - const msb = await this.tokenizer.peekNumber(token_types_1.UINT8); - let mask = 0x80; - let oc = 1; - // Calculate VINT_WIDTH - while ((msb & mask) === 0) { - if (oc > maxLength) { - throw new Error('VINT value exceeding maximum size'); - } - ++oc; - mask >>= 1; - } - const id = Buffer.alloc(oc); - await this.tokenizer.readBuffer(id); - return id; - } - async readElement() { - const id = await this.readVintData(this.ebmlMaxIDLength); - const lenField = await this.readVintData(this.ebmlMaxSizeLength); - lenField[0] ^= 0x80 >> (lenField.length - 1); - const nrLen = Math.min(6, lenField.length); // JavaScript can max read 6 bytes integer - return { - id: id.readUIntBE(0, id.length), - len: lenField.readUIntBE(lenField.length - nrLen, nrLen) - }; - } - isMaxValue(vintData) { - if (vintData.length === this.ebmlMaxSizeLength) { - for (let n = 1; n < this.ebmlMaxSizeLength; ++n) { - if (vintData[n] !== 0xff) - return false; - } - return true; - } - return false; - } - async readFloat(e) { - switch (e.len) { - case 0: - return 0.0; - case 4: - return this.tokenizer.readNumber(token_types_1.Float32_BE); - case 8: - return this.tokenizer.readNumber(token_types_1.Float64_BE); - case 10: - return this.tokenizer.readNumber(token_types_1.Float64_BE); - default: - throw new Error(`Invalid IEEE-754 float length: ${e.len}`); - } - } - async readFlag(e) { - return (await this.readUint(e)) === 1; - } - async readUint(e) { - const buf = await this.readBuffer(e); - const nrLen = Math.min(6, e.len); // JavaScript can max read 6 bytes integer - return buf.readUIntBE(e.len - nrLen, nrLen); - } - async readString(e) { - const rawString = await this.tokenizer.readToken(new token_types_1.StringType(e.len, 'utf-8')); - return rawString.replace(/\00.*$/g, ''); - } - async readBuffer(e) { - const buf = Buffer.alloc(e.len); - await this.tokenizer.readBuffer(buf); - return buf; - } - addTag(tagId, value) { - this.metadata.addTag('matroska', tagId, value); - } -} -exports.MatroskaParser = MatroskaParser; - - -/***/ }), - -/***/ 5481: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MatroskaTagMapper = void 0; -const CaseInsensitiveTagMap_1 = __webpack_require__(4132); -/** - * EBML Tag map - */ -const ebmlTagMap = { - 'segment:title': 'title', - 'album:ARTIST': 'albumartist', - 'album:ARTISTSORT': 'albumartistsort', - 'album:TITLE': 'album', - 'album:DATE_RECORDED': 'originaldate', - 'album:PART_NUMBER': 'disk', - 'album:TOTAL_PARTS': 'totaltracks', - 'track:ARTIST': 'artist', - 'track:ARTISTSORT': 'artistsort', - 'track:TITLE': 'title', - 'track:PART_NUMBER': 'track', - 'track:MUSICBRAINZ_TRACKID': 'musicbrainz_recordingid', - 'track:MUSICBRAINZ_ALBUMID': 'musicbrainz_albumid', - 'track:MUSICBRAINZ_ARTISTID': 'musicbrainz_artistid', - 'track:PUBLISHER': 'label', - 'track:GENRE': 'genre', - 'track:ENCODER': 'encodedby', - 'track:ENCODER_OPTIONS': 'encodersettings', - 'edition:TOTAL_PARTS': 'totaldiscs', - picture: 'picture' -}; -class MatroskaTagMapper extends CaseInsensitiveTagMap_1.CaseInsensitiveTagMap { - constructor() { - super(['matroska'], ebmlTagMap); - } -} -exports.MatroskaTagMapper = MatroskaTagMapper; -//# sourceMappingURL=MatroskaTagMapper.js.map - -/***/ }), - -/***/ 8591: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.TrackType = exports.TargetType = exports.DataType = void 0; -var DataType; -(function (DataType) { - DataType[DataType["string"] = 0] = "string"; - DataType[DataType["uint"] = 1] = "uint"; - DataType[DataType["uid"] = 2] = "uid"; - DataType[DataType["bool"] = 3] = "bool"; - DataType[DataType["binary"] = 4] = "binary"; - DataType[DataType["float"] = 5] = "float"; -})(DataType = exports.DataType || (exports.DataType = {})); -var TargetType; -(function (TargetType) { - TargetType[TargetType["shot"] = 10] = "shot"; - TargetType[TargetType["scene"] = 20] = "scene"; - TargetType[TargetType["track"] = 30] = "track"; - TargetType[TargetType["part"] = 40] = "part"; - TargetType[TargetType["album"] = 50] = "album"; - TargetType[TargetType["edition"] = 60] = "edition"; - TargetType[TargetType["collection"] = 70] = "collection"; -})(TargetType = exports.TargetType || (exports.TargetType = {})); -var TrackType; -(function (TrackType) { - TrackType[TrackType["video"] = 1] = "video"; - TrackType[TrackType["audio"] = 2] = "audio"; - TrackType[TrackType["complex"] = 3] = "complex"; - TrackType[TrackType["logo"] = 4] = "logo"; - TrackType[TrackType["subtitle"] = 17] = "subtitle"; - TrackType[TrackType["button"] = 18] = "button"; - TrackType[TrackType["control"] = 32] = "control"; -})(TrackType = exports.TrackType || (exports.TrackType = {})); -//# sourceMappingURL=types.js.map - -/***/ }), - -/***/ 9134: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Atom = void 0; -const debug_1 = __webpack_require__(1227); -const AtomToken = __webpack_require__(1060); -const debug = (0, debug_1.default)('music-metadata:parser:MP4:Atom'); -class Atom { - constructor(header, extended, parent) { - this.header = header; - this.extended = extended; - this.parent = parent; - this.children = []; - this.atomPath = (this.parent ? this.parent.atomPath + '.' : '') + this.header.name; - } - static async readAtom(tokenizer, dataHandler, parent, remaining) { - // Parse atom header - const offset = tokenizer.position; - // debug(`Reading next token on offset=${offset}...`); // buf.toString('ascii') - const header = await tokenizer.readToken(AtomToken.Header); - const extended = header.length === BigInt(1); - if (extended) { - header.length = await tokenizer.readToken(AtomToken.ExtendedSize); - } - const atomBean = new Atom(header, header.length === BigInt(1), parent); - const payloadLength = atomBean.getPayloadLength(remaining); - debug(`parse atom name=${atomBean.atomPath}, extended=${atomBean.extended}, offset=${offset}, len=${atomBean.header.length}`); // buf.toString('ascii') - await atomBean.readData(tokenizer, dataHandler, payloadLength); - return atomBean; - } - getHeaderLength() { - return this.extended ? 16 : 8; - } - getPayloadLength(remaining) { - return (this.header.length === BigInt(0) ? remaining : Number(this.header.length)) - this.getHeaderLength(); - } - async readAtoms(tokenizer, dataHandler, size) { - while (size > 0) { - const atomBean = await Atom.readAtom(tokenizer, dataHandler, this, size); - this.children.push(atomBean); - size -= atomBean.header.length === BigInt(0) ? size : Number(atomBean.header.length); - } - } - async readData(tokenizer, dataHandler, remaining) { - switch (this.header.name) { - // "Container" atoms, contains nested atoms - case 'moov': // The Movie Atom: contains other atoms - case 'udta': // User defined atom - case 'trak': - case 'mdia': // Media atom - case 'minf': // Media Information Atom - case 'stbl': // The Sample Table Atom - case '': - case 'ilst': - case 'tref': - return this.readAtoms(tokenizer, dataHandler, this.getPayloadLength(remaining)); - case 'meta': // Metadata Atom, ref: https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW8 - // meta has 4 bytes of padding, ignore - await tokenizer.ignore(4); - return this.readAtoms(tokenizer, dataHandler, this.getPayloadLength(remaining) - 4); - case 'mdhd': // Media header atom - case 'mvhd': // 'movie' => 'mvhd': movie header atom; child of Movie Atom - case 'tkhd': - case 'stsz': - case 'mdat': - default: - return dataHandler(this, remaining); - } - } -} -exports.Atom = Atom; - - -/***/ }), - -/***/ 1060: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ChapterText = exports.StcoAtom = exports.StszAtom = exports.StscAtom = exports.SampleToChunkToken = exports.SttsAtom = exports.TimeToSampleToken = exports.SoundSampleDescriptionV0 = exports.SoundSampleDescriptionVersion = exports.StsdAtom = exports.TrackHeaderAtom = exports.NameAtom = exports.DataAtom = exports.MvhdAtom = exports.MdhdAtom = exports.FixedLengthAtom = exports.mhdr = exports.tkhd = exports.ftyp = exports.ExtendedSize = exports.Header = void 0; -const Token = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const FourCC_1 = __webpack_require__(8049); -const debug = (0, debug_1.default)('music-metadata:parser:MP4:atom'); -exports.Header = { - len: 8, - get: (buf, off) => { - const length = Token.UINT32_BE.get(buf, off); - if (length < 0) - throw new Error('Invalid atom header length'); - return { - length: BigInt(length), - name: new Token.StringType(4, 'binary').get(buf, off + 4) - }; - }, - put: (buf, off, hdr) => { - Token.UINT32_BE.put(buf, off, Number(hdr.length)); - return FourCC_1.FourCcToken.put(buf, off + 4, hdr.name); - } -}; -/** - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap1/qtff1.html#//apple_ref/doc/uid/TP40000939-CH203-38190 - */ -exports.ExtendedSize = Token.UINT64_BE; -exports.ftyp = { - len: 4, - get: (buf, off) => { - return { - type: new Token.StringType(4, 'ascii').get(buf, off) - }; - } -}; -exports.tkhd = { - len: 4, - get: (buf, off) => { - return { - type: new Token.StringType(4, 'ascii').get(buf, off) - }; - } -}; -/** - * Token: Movie Header Atom - */ -exports.mhdr = { - len: 8, - get: (buf, off) => { - return { - version: Token.UINT8.get(buf, off), - flags: Token.UINT24_BE.get(buf, off + 1), - nextItemID: Token.UINT32_BE.get(buf, off + 4) - }; - } -}; -/** - * Base class for 'fixed' length atoms. - * In some cases these atoms are longer then the sum of the described fields. - * Issue: https://github.com/Borewit/music-metadata/issues/120 - */ -class FixedLengthAtom { - /** - * - * @param {number} len Length as specified in the size field - * @param {number} expLen Total length of sum of specified fields in the standard - */ - constructor(len, expLen, atomId) { - this.len = len; - if (len < expLen) { - throw new Error(`Atom ${atomId} expected to be ${expLen}, but specifies ${len} bytes long.`); - } - else if (len > expLen) { - debug(`Warning: atom ${atomId} expected to be ${expLen}, but was actually ${len} bytes long.`); - } - } -} -exports.FixedLengthAtom = FixedLengthAtom; -/** - * Timestamp stored in seconds since Mac Epoch (1 January 1904) - */ -const SecondsSinceMacEpoch = { - len: 4, - get: (buf, off) => { - const secondsSinceUnixEpoch = Token.UINT32_BE.get(buf, off) - 2082844800; - return new Date(secondsSinceUnixEpoch * 1000); - } -}; -/** - * Token: Media Header Atom - * Ref: - * - https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-SW34 - * - https://wiki.multimedia.cx/index.php/QuickTime_container#mdhd - */ -class MdhdAtom extends FixedLengthAtom { - constructor(len) { - super(len, 24, 'mdhd'); - this.len = len; - } - get(buf, off) { - return { - version: Token.UINT8.get(buf, off + 0), - flags: Token.UINT24_BE.get(buf, off + 1), - creationTime: SecondsSinceMacEpoch.get(buf, off + 4), - modificationTime: SecondsSinceMacEpoch.get(buf, off + 8), - timeScale: Token.UINT32_BE.get(buf, off + 12), - duration: Token.UINT32_BE.get(buf, off + 16), - language: Token.UINT16_BE.get(buf, off + 20), - quality: Token.UINT16_BE.get(buf, off + 22) - }; - } -} -exports.MdhdAtom = MdhdAtom; -/** - * Token: Movie Header Atom - */ -class MvhdAtom extends FixedLengthAtom { - constructor(len) { - super(len, 100, 'mvhd'); - this.len = len; - } - get(buf, off) { - return { - version: Token.UINT8.get(buf, off), - flags: Token.UINT24_BE.get(buf, off + 1), - creationTime: SecondsSinceMacEpoch.get(buf, off + 4), - modificationTime: SecondsSinceMacEpoch.get(buf, off + 8), - timeScale: Token.UINT32_BE.get(buf, off + 12), - duration: Token.UINT32_BE.get(buf, off + 16), - preferredRate: Token.UINT32_BE.get(buf, off + 20), - preferredVolume: Token.UINT16_BE.get(buf, off + 24), - // ignore reserver: 10 bytes - // ignore matrix structure: 36 bytes - previewTime: Token.UINT32_BE.get(buf, off + 72), - previewDuration: Token.UINT32_BE.get(buf, off + 76), - posterTime: Token.UINT32_BE.get(buf, off + 80), - selectionTime: Token.UINT32_BE.get(buf, off + 84), - selectionDuration: Token.UINT32_BE.get(buf, off + 88), - currentTime: Token.UINT32_BE.get(buf, off + 92), - nextTrackID: Token.UINT32_BE.get(buf, off + 96) - }; - } -} -exports.MvhdAtom = MvhdAtom; -/** - * Data Atom Structure - */ -class DataAtom { - constructor(len) { - this.len = len; - } - get(buf, off) { - return { - type: { - set: Token.UINT8.get(buf, off + 0), - type: Token.UINT24_BE.get(buf, off + 1) - }, - locale: Token.UINT24_BE.get(buf, off + 4), - value: Buffer.from(new Token.Uint8ArrayType(this.len - 8).get(buf, off + 8)) - }; - } -} -exports.DataAtom = DataAtom; -/** - * Data Atom Structure - * Ref: https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW31 - */ -class NameAtom { - constructor(len) { - this.len = len; - } - get(buf, off) { - return { - version: Token.UINT8.get(buf, off), - flags: Token.UINT24_BE.get(buf, off + 1), - name: new Token.StringType(this.len - 4, 'utf-8').get(buf, off + 4) - }; - } -} -exports.NameAtom = NameAtom; -/** - * Track Header Atoms structure - * Ref: https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25550 - */ -class TrackHeaderAtom { - constructor(len) { - this.len = len; - } - get(buf, off) { - return { - version: Token.UINT8.get(buf, off), - flags: Token.UINT24_BE.get(buf, off + 1), - creationTime: SecondsSinceMacEpoch.get(buf, off + 4), - modificationTime: SecondsSinceMacEpoch.get(buf, off + 8), - trackId: Token.UINT32_BE.get(buf, off + 12), - // reserved 4 bytes - duration: Token.UINT32_BE.get(buf, off + 20), - layer: Token.UINT16_BE.get(buf, off + 24), - alternateGroup: Token.UINT16_BE.get(buf, off + 26), - volume: Token.UINT16_BE.get(buf, off + 28) // ToDo: fixed point - // ToDo: add remaining fields - }; - } -} -exports.TrackHeaderAtom = TrackHeaderAtom; -/** - * Atom: Sample Description Atom ('stsd') - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691 - */ -const stsdHeader = { - len: 8, - get: (buf, off) => { - return { - version: Token.UINT8.get(buf, off), - flags: Token.UINT24_BE.get(buf, off + 1), - numberOfEntries: Token.UINT32_BE.get(buf, off + 4) - }; - } -}; -/** - * Atom: Sample Description Atom ('stsd') - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691 - */ -class SampleDescriptionTable { - constructor(len) { - this.len = len; - } - get(buf, off) { - return { - dataFormat: FourCC_1.FourCcToken.get(buf, off), - dataReferenceIndex: Token.UINT16_BE.get(buf, off + 10), - description: new Token.Uint8ArrayType(this.len - 12).get(buf, off + 12) - }; - } -} -/** - * Atom: Sample-description Atom ('stsd') - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25691 - */ -class StsdAtom { - constructor(len) { - this.len = len; - } - get(buf, off) { - const header = stsdHeader.get(buf, off); - off += stsdHeader.len; - const table = []; - for (let n = 0; n < header.numberOfEntries; ++n) { - const size = Token.UINT32_BE.get(buf, off); // Sample description size - off += Token.UINT32_BE.len; - table.push(new SampleDescriptionTable(size).get(buf, off)); - off += size; - } - return { - header, - table - }; - } -} -exports.StsdAtom = StsdAtom; -/** - * Common Sound Sample Description (version & revision) - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-57317 - */ -exports.SoundSampleDescriptionVersion = { - len: 8, - get(buf, off) { - return { - version: Token.INT16_BE.get(buf, off), - revision: Token.INT16_BE.get(buf, off + 2), - vendor: Token.INT32_BE.get(buf, off + 4) - }; - } -}; -/** - * Sound Sample Description (Version 0) - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-130736 - */ -exports.SoundSampleDescriptionV0 = { - len: 12, - get(buf, off) { - return { - numAudioChannels: Token.INT16_BE.get(buf, off + 0), - sampleSize: Token.INT16_BE.get(buf, off + 2), - compressionId: Token.INT16_BE.get(buf, off + 4), - packetSize: Token.INT16_BE.get(buf, off + 6), - sampleRate: Token.UINT16_BE.get(buf, off + 8) + Token.UINT16_BE.get(buf, off + 10) / 10000 - }; - } -}; -class SimpleTableAtom { - constructor(len, token) { - this.len = len; - this.token = token; - } - get(buf, off) { - const nrOfEntries = Token.INT32_BE.get(buf, off + 4); - return { - version: Token.INT8.get(buf, off + 0), - flags: Token.INT24_BE.get(buf, off + 1), - numberOfEntries: nrOfEntries, - entries: readTokenTable(buf, this.token, off + 8, this.len - 8, nrOfEntries) - }; - } -} -exports.TimeToSampleToken = { - len: 8, - get(buf, off) { - return { - count: Token.INT32_BE.get(buf, off + 0), - duration: Token.INT32_BE.get(buf, off + 4) - }; - } -}; -/** - * Time-to-sample('stts') atom. - * Store duration information for a media’s samples. - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25696 - */ -class SttsAtom extends SimpleTableAtom { - constructor(len) { - super(len, exports.TimeToSampleToken); - this.len = len; - } -} -exports.SttsAtom = SttsAtom; -exports.SampleToChunkToken = { - len: 12, - get(buf, off) { - return { - firstChunk: Token.INT32_BE.get(buf, off), - samplesPerChunk: Token.INT32_BE.get(buf, off + 4), - sampleDescriptionId: Token.INT32_BE.get(buf, off + 8) - }; - } -}; -/** - * Sample-to-Chunk ('stsc') atom interface - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25706 - */ -class StscAtom extends SimpleTableAtom { - constructor(len) { - super(len, exports.SampleToChunkToken); - this.len = len; - } -} -exports.StscAtom = StscAtom; -/** - * Sample-size ('stsz') atom - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25710 - */ -class StszAtom { - constructor(len) { - this.len = len; - } - get(buf, off) { - const nrOfEntries = Token.INT32_BE.get(buf, off + 8); - return { - version: Token.INT8.get(buf, off), - flags: Token.INT24_BE.get(buf, off + 1), - sampleSize: Token.INT32_BE.get(buf, off + 4), - numberOfEntries: nrOfEntries, - entries: readTokenTable(buf, Token.INT32_BE, off + 12, this.len - 12, nrOfEntries) - }; - } -} -exports.StszAtom = StszAtom; -/** - * Chunk offset atom, 'stco' - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25715 - */ -class StcoAtom extends SimpleTableAtom { - constructor(len) { - super(len, Token.INT32_BE); - this.len = len; - } -} -exports.StcoAtom = StcoAtom; -/** - * Token used to decode text-track from 'mdat' atom (raw data stream) - */ -class ChapterText { - constructor(len) { - this.len = len; - } - get(buf, off) { - const titleLen = Token.INT16_BE.get(buf, off + 0); - const str = new Token.StringType(titleLen, 'utf-8'); - return str.get(buf, off + 2); - } -} -exports.ChapterText = ChapterText; -function readTokenTable(buf, token, off, remainingLen, numberOfEntries) { - debug(`remainingLen=${remainingLen}, numberOfEntries=${numberOfEntries} * token-len=${token.len}`); - if (remainingLen === 0) - return []; - if (remainingLen !== numberOfEntries * token.len) - throw new Error('mismatch number-of-entries with remaining atom-length'); - const entries = []; - // parse offset-table - for (let n = 0; n < numberOfEntries; ++n) { - entries.push(token.get(buf, off)); - off += token.len; - } - return entries; -} - - -/***/ }), - -/***/ 8841: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MP4Parser = void 0; -const debug_1 = __webpack_require__(1227); -const Token = __webpack_require__(3416); -const BasicParser_1 = __webpack_require__(7805); -const ID3v1Parser_1 = __webpack_require__(2282); -const type_1 = __webpack_require__(6032); -const Atom_1 = __webpack_require__(9134); -const AtomToken = __webpack_require__(1060); -const debug = (0, debug_1.default)('music-metadata:parser:MP4'); -const tagFormat = 'iTunes'; -const encoderDict = { - raw: { - lossy: false, - format: 'raw' - }, - MAC3: { - lossy: true, - format: 'MACE 3:1' - }, - MAC6: { - lossy: true, - format: 'MACE 6:1' - }, - ima4: { - lossy: true, - format: 'IMA 4:1' - }, - ulaw: { - lossy: true, - format: 'uLaw 2:1' - }, - alaw: { - lossy: true, - format: 'uLaw 2:1' - }, - Qclp: { - lossy: true, - format: 'QUALCOMM PureVoice' - }, - '.mp3': { - lossy: true, - format: 'MPEG-1 layer 3' - }, - alac: { - lossy: false, - format: 'ALAC' - }, - 'ac-3': { - lossy: true, - format: 'AC-3' - }, - mp4a: { - lossy: true, - format: 'MPEG-4/AAC' - }, - mp4s: { - lossy: true, - format: 'MP4S' - }, - // Closed Captioning Media, https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-SW87 - c608: { - lossy: true, - format: 'CEA-608' - }, - c708: { - lossy: true, - format: 'CEA-708' - } -}; -function distinct(value, index, self) { - return self.indexOf(value) === index; -} -/* - * Parser for the MP4 (MPEG-4 Part 14) container format - * Standard: ISO/IEC 14496-14 - * supporting: - * - QuickTime container - * - MP4 File Format - * - 3GPP file format - * - 3GPP2 file format - * - * MPEG-4 Audio / Part 3 (.m4a)& MPEG 4 Video (m4v, mp4) extension. - * Support for Apple iTunes tags as found in a M4A/M4V files. - * Ref: - * https://en.wikipedia.org/wiki/ISO_base_media_file_format - * https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html - * http://atomicparsley.sourceforge.net/mpeg-4files.html - * https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata - * https://wiki.multimedia.cx/index.php/QuickTime_container - */ -class MP4Parser extends BasicParser_1.BasicParser { - constructor() { - super(...arguments); - this.atomParsers = { - /** - * Parse movie header (mvhd) atom - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-56313 - */ - mvhd: async (len) => { - const mvhd = await this.tokenizer.readToken(new AtomToken.MvhdAtom(len)); - this.metadata.setFormat('creationTime', mvhd.creationTime); - this.metadata.setFormat('modificationTime', mvhd.modificationTime); - }, - /** - * Parse media header (mdhd) atom - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-25615 - */ - mdhd: async (len) => { - const mdhd_data = await this.tokenizer.readToken(new AtomToken.MdhdAtom(len)); - // this.parse_mxhd(mdhd_data, this.currentTrack); - const td = this.getTrackDescription(); - td.creationTime = mdhd_data.creationTime; - td.modificationTime = mdhd_data.modificationTime; - td.timeScale = mdhd_data.timeScale; - td.duration = mdhd_data.duration; - }, - chap: async (len) => { - const td = this.getTrackDescription(); - const trackIds = []; - while (len >= Token.UINT32_BE.len) { - trackIds.push(await this.tokenizer.readNumber(Token.UINT32_BE)); - len -= Token.UINT32_BE.len; - } - td.chapterList = trackIds; - }, - tkhd: async (len) => { - const track = (await this.tokenizer.readToken(new AtomToken.TrackHeaderAtom(len))); - this.tracks.push(track); - }, - /** - * Parse mdat atom. - * Will scan for chapters - */ - mdat: async (len) => { - this.audioLengthInBytes = len; - this.calculateBitRate(); - if (this.options.includeChapters) { - const trackWithChapters = this.tracks.filter(track => track.chapterList); - if (trackWithChapters.length === 1) { - const chapterTrackIds = trackWithChapters[0].chapterList; - const chapterTracks = this.tracks.filter(track => chapterTrackIds.indexOf(track.trackId) !== -1); - if (chapterTracks.length === 1) { - return this.parseChapterTrack(chapterTracks[0], trackWithChapters[0], len); - } - } - } - await this.tokenizer.ignore(len); - }, - ftyp: async (len) => { - const types = []; - while (len > 0) { - const ftype = await this.tokenizer.readToken(AtomToken.ftyp); - len -= AtomToken.ftyp.len; - const value = ftype.type.replace(/\W/g, ''); - if (value.length > 0) { - types.push(value); // unshift for backward compatibility - } - } - debug(`ftyp: ${types.join('/')}`); - const x = types.filter(distinct).join('/'); - this.metadata.setFormat('container', x); - }, - /** - * Parse sample description atom - */ - stsd: async (len) => { - const stsd = await this.tokenizer.readToken(new AtomToken.StsdAtom(len)); - const trackDescription = this.getTrackDescription(); - trackDescription.soundSampleDescription = stsd.table.map(dfEntry => this.parseSoundSampleDescription(dfEntry)); - }, - /** - * sample-to-Chunk Atoms - */ - stsc: async (len) => { - const stsc = await this.tokenizer.readToken(new AtomToken.StscAtom(len)); - this.getTrackDescription().sampleToChunkTable = stsc.entries; - }, - /** - * time to sample - */ - stts: async (len) => { - const stts = await this.tokenizer.readToken(new AtomToken.SttsAtom(len)); - this.getTrackDescription().timeToSampleTable = stts.entries; - }, - /** - * Parse sample-sizes atom ('stsz') - */ - stsz: async (len) => { - const stsz = await this.tokenizer.readToken(new AtomToken.StszAtom(len)); - const td = this.getTrackDescription(); - td.sampleSize = stsz.sampleSize; - td.sampleSizeTable = stsz.entries; - }, - /** - * Parse chunk-offset atom ('stco') - */ - stco: async (len) => { - const stco = await this.tokenizer.readToken(new AtomToken.StcoAtom(len)); - this.getTrackDescription().chunkOffsetTable = stco.entries; // remember chunk offsets - }, - date: async (len) => { - const date = await this.tokenizer.readToken(new Token.StringType(len, 'utf-8')); - this.addTag('date', date); - } - }; - } - static read_BE_Integer(array, signed) { - const integerType = (signed ? 'INT' : 'UINT') + array.length * 8 + (array.length > 1 ? '_BE' : ''); - const token = Token[integerType]; - if (!token) { - throw new Error('Token for integer type not found: "' + integerType + '"'); - } - return Number(token.get(array, 0)); - } - async parse() { - this.tracks = []; - let remainingFileSize = this.tokenizer.fileInfo.size; - while (!this.tokenizer.fileInfo.size || remainingFileSize > 0) { - try { - const token = await this.tokenizer.peekToken(AtomToken.Header); - if (token.name === '\0\0\0\0') { - const errMsg = `Error at offset=${this.tokenizer.position}: box.id=0`; - debug(errMsg); - this.addWarning(errMsg); - break; - } - } - catch (error) { - const errMsg = `Error at offset=${this.tokenizer.position}: ${error.message}`; - debug(errMsg); - this.addWarning(errMsg); - break; - } - const rootAtom = await Atom_1.Atom.readAtom(this.tokenizer, (atom, remaining) => this.handleAtom(atom, remaining), null, remainingFileSize); - remainingFileSize -= rootAtom.header.length === BigInt(0) ? remainingFileSize : Number(rootAtom.header.length); - } - // Post process metadata - const formatList = []; - this.tracks.forEach(track => { - const trackFormats = []; - track.soundSampleDescription.forEach(ssd => { - const streamInfo = {}; - const encoderInfo = encoderDict[ssd.dataFormat]; - if (encoderInfo) { - trackFormats.push(encoderInfo.format); - streamInfo.codecName = encoderInfo.format; - } - else { - streamInfo.codecName = `<${ssd.dataFormat}>`; - } - if (ssd.description) { - const { description } = ssd; - if (description.sampleRate > 0) { - streamInfo.type = type_1.TrackType.audio; - streamInfo.audio = { - samplingFrequency: description.sampleRate, - bitDepth: description.sampleSize, - channels: description.numAudioChannels - }; - } - } - this.metadata.addStreamInfo(streamInfo); - }); - if (trackFormats.length >= 1) { - formatList.push(trackFormats.join('/')); - } - }); - if (formatList.length > 0) { - this.metadata.setFormat('codec', formatList.filter(distinct).join('+')); - } - const audioTracks = this.tracks.filter(track => { - return track.soundSampleDescription.length >= 1 && track.soundSampleDescription[0].description && track.soundSampleDescription[0].description.numAudioChannels > 0; - }); - if (audioTracks.length >= 1) { - const audioTrack = audioTracks[0]; - const duration = audioTrack.duration / audioTrack.timeScale; - this.metadata.setFormat('duration', duration); // calculate duration in seconds - const ssd = audioTrack.soundSampleDescription[0]; - if (ssd.description) { - this.metadata.setFormat('sampleRate', ssd.description.sampleRate); - this.metadata.setFormat('bitsPerSample', ssd.description.sampleSize); - this.metadata.setFormat('numberOfChannels', ssd.description.numAudioChannels); - } - const encoderInfo = encoderDict[ssd.dataFormat]; - if (encoderInfo) { - this.metadata.setFormat('lossless', !encoderInfo.lossy); - } - this.calculateBitRate(); - } - } - async handleAtom(atom, remaining) { - if (atom.parent) { - switch (atom.parent.header.name) { - case 'ilst': - case '': - return this.parseMetadataItemData(atom); - } - } - // const payloadLength = atom.getPayloadLength(remaining); - if (this.atomParsers[atom.header.name]) { - return this.atomParsers[atom.header.name](remaining); - } - else { - debug(`No parser for atom path=${atom.atomPath}, payload-len=${remaining}, ignoring atom`); - await this.tokenizer.ignore(remaining); - } - } - getTrackDescription() { - return this.tracks[this.tracks.length - 1]; - } - calculateBitRate() { - if (this.audioLengthInBytes && this.metadata.format.duration) { - this.metadata.setFormat('bitrate', 8 * this.audioLengthInBytes / this.metadata.format.duration); - } - } - addTag(id, value) { - this.metadata.addTag(tagFormat, id, value); - } - addWarning(message) { - debug('Warning: ' + message); - this.metadata.addWarning(message); - } - /** - * Parse data of Meta-item-list-atom (item of 'ilst' atom) - * @param metaAtom - * Ref: https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW8 - */ - parseMetadataItemData(metaAtom) { - let tagKey = metaAtom.header.name; - return metaAtom.readAtoms(this.tokenizer, async (child, remaining) => { - const payLoadLength = child.getPayloadLength(remaining); - switch (child.header.name) { - case 'data': // value atom - return this.parseValueAtom(tagKey, child); - case 'name': // name atom (optional) - const name = await this.tokenizer.readToken(new AtomToken.NameAtom(payLoadLength)); - tagKey += ':' + name.name; - break; - case 'mean': // name atom (optional) - const mean = await this.tokenizer.readToken(new AtomToken.NameAtom(payLoadLength)); - // console.log(" %s[%s] = %s", tagKey, header.name, mean.name); - tagKey += ':' + mean.name; - break; - default: - const dataAtom = await this.tokenizer.readToken(new Token.BufferType(payLoadLength)); - this.addWarning('Unsupported meta-item: ' + tagKey + '[' + child.header.name + '] => value=' + dataAtom.toString('hex') + ' ascii=' + dataAtom.toString('ascii')); - } - }, metaAtom.getPayloadLength(0)); - } - async parseValueAtom(tagKey, metaAtom) { - const dataAtom = await this.tokenizer.readToken(new AtomToken.DataAtom(Number(metaAtom.header.length) - AtomToken.Header.len)); - if (dataAtom.type.set !== 0) { - throw new Error('Unsupported type-set != 0: ' + dataAtom.type.set); - } - // Use well-known-type table - // Ref: https://developer.apple.com/library/content/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35 - switch (dataAtom.type.type) { - case 0: // reserved: Reserved for use where no type needs to be indicated - switch (tagKey) { - case 'trkn': - case 'disk': - const num = Token.UINT8.get(dataAtom.value, 3); - const of = Token.UINT8.get(dataAtom.value, 5); - // console.log(" %s[data] = %s/%s", tagKey, num, of); - this.addTag(tagKey, num + '/' + of); - break; - case 'gnre': - const genreInt = Token.UINT8.get(dataAtom.value, 1); - const genreStr = ID3v1Parser_1.Genres[genreInt - 1]; - // console.log(" %s[data] = %s", tagKey, genreStr); - this.addTag(tagKey, genreStr); - break; - default: - // console.log(" reserved-data: name=%s, len=%s, set=%s, type=%s, locale=%s, value{ hex=%s, ascii=%s }", - // header.name, header.length, dataAtom.type.set, dataAtom.type.type, dataAtom.locale, dataAtom.value.toString('hex'), dataAtom.value.toString('ascii')); - } - break; - case 1: // UTF-8: Without any count or NULL terminator - case 18: // Unknown: Found in m4b in combination with a '©gen' tag - this.addTag(tagKey, dataAtom.value.toString('utf-8')); - break; - case 13: // JPEG - if (this.options.skipCovers) - break; - this.addTag(tagKey, { - format: 'image/jpeg', - data: Buffer.from(dataAtom.value) - }); - break; - case 14: // PNG - if (this.options.skipCovers) - break; - this.addTag(tagKey, { - format: 'image/png', - data: Buffer.from(dataAtom.value) - }); - break; - case 21: // BE Signed Integer - this.addTag(tagKey, MP4Parser.read_BE_Integer(dataAtom.value, true)); - break; - case 22: // BE Unsigned Integer - this.addTag(tagKey, MP4Parser.read_BE_Integer(dataAtom.value, false)); - break; - case 65: // An 8-bit signed integer - this.addTag(tagKey, dataAtom.value.readInt8(0)); - break; - case 66: // A big-endian 16-bit signed integer - this.addTag(tagKey, dataAtom.value.readInt16BE(0)); - break; - case 67: // A big-endian 32-bit signed integer - this.addTag(tagKey, dataAtom.value.readInt32BE(0)); - break; - default: - this.addWarning(`atom key=${tagKey}, has unknown well-known-type (data-type): ${dataAtom.type.type}`); - } - } - /** - * @param sampleDescription - * Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html#//apple_ref/doc/uid/TP40000939-CH205-128916 - */ - parseSoundSampleDescription(sampleDescription) { - const ssd = { - dataFormat: sampleDescription.dataFormat, - dataReferenceIndex: sampleDescription.dataReferenceIndex - }; - let offset = 0; - const version = AtomToken.SoundSampleDescriptionVersion.get(sampleDescription.description, offset); - offset += AtomToken.SoundSampleDescriptionVersion.len; - if (version.version === 0 || version.version === 1) { - // Sound Sample Description (Version 0) - ssd.description = AtomToken.SoundSampleDescriptionV0.get(sampleDescription.description, offset); - } - else { - debug(`Warning: sound-sample-description ${version} not implemented`); - } - return ssd; - } - async parseChapterTrack(chapterTrack, track, len) { - if (!chapterTrack.sampleSize) { - if (chapterTrack.chunkOffsetTable.length !== chapterTrack.sampleSizeTable.length) - throw new Error('Expected equal chunk-offset-table & sample-size-table length.'); - } - const chapters = []; - for (let i = 0; i < chapterTrack.chunkOffsetTable.length && len > 0; ++i) { - const chunkOffset = chapterTrack.chunkOffsetTable[i]; - const nextChunkLen = chunkOffset - this.tokenizer.position; - const sampleSize = chapterTrack.sampleSize > 0 ? chapterTrack.sampleSize : chapterTrack.sampleSizeTable[i]; - len -= nextChunkLen + sampleSize; - if (len < 0) - throw new Error('Chapter chunk exceeding token length'); - await this.tokenizer.ignore(nextChunkLen); - const title = await this.tokenizer.readToken(new AtomToken.ChapterText(sampleSize)); - debug(`Chapter ${i + 1}: ${title}`); - const chapter = { - title, - sampleOffset: this.findSampleOffset(track, this.tokenizer.position) - }; - debug(`Chapter title=${chapter.title}, offset=${chapter.sampleOffset}/${this.tracks[0].duration}`); - chapters.push(chapter); - } - this.metadata.setFormat('chapters', chapters); - await this.tokenizer.ignore(len); - } - findSampleOffset(track, chapterOffset) { - let totalDuration = 0; - track.timeToSampleTable.forEach(e => { - totalDuration += e.count * e.duration; - }); - debug(`Total duration=${totalDuration}`); - let chunkIndex = 0; - while (chunkIndex < track.chunkOffsetTable.length && track.chunkOffsetTable[chunkIndex] < chapterOffset) { - ++chunkIndex; - } - return this.getChunkDuration(chunkIndex + 1, track); - } - getChunkDuration(chunkId, track) { - let ttsi = 0; - let ttsc = track.timeToSampleTable[ttsi].count; - let ttsd = track.timeToSampleTable[ttsi].duration; - let curChunkId = 1; - let samplesPerChunk = this.getSamplesPerChunk(curChunkId, track.sampleToChunkTable); - let totalDuration = 0; - while (curChunkId < chunkId) { - const nrOfSamples = Math.min(ttsc, samplesPerChunk); - totalDuration += nrOfSamples * ttsd; - ttsc -= nrOfSamples; - samplesPerChunk -= nrOfSamples; - if (samplesPerChunk === 0) { - ++curChunkId; - samplesPerChunk = this.getSamplesPerChunk(curChunkId, track.sampleToChunkTable); - } - else { - ++ttsi; - ttsc = track.timeToSampleTable[ttsi].count; - ttsd = track.timeToSampleTable[ttsi].duration; - } - } - return totalDuration; - } - getSamplesPerChunk(chunkId, stcTable) { - for (let i = 0; i < stcTable.length - 1; ++i) { - if (chunkId >= stcTable[i].firstChunk && chunkId < stcTable[i + 1].firstChunk) { - return stcTable[i].samplesPerChunk; - } - } - return stcTable[stcTable.length - 1].samplesPerChunk; - } -} -exports.MP4Parser = MP4Parser; - - -/***/ }), - -/***/ 7852: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MP4TagMapper = exports.tagType = void 0; -const CaseInsensitiveTagMap_1 = __webpack_require__(4132); -/** - * Ref: https://github.com/sergiomb2/libmp4v2/wiki/iTunesMetadata - */ -const mp4TagMap = { - '©nam': 'title', - '©ART': 'artist', - aART: 'albumartist', - /** - * ToDo: Album artist seems to be stored here while Picard documentation says: aART - */ - '----:com.apple.iTunes:Band': 'albumartist', - '©alb': 'album', - '©day': 'date', - '©cmt': 'comment', - '©com': 'comment', - trkn: 'track', - disk: 'disk', - '©gen': 'genre', - covr: 'picture', - '©wrt': 'composer', - '©lyr': 'lyrics', - soal: 'albumsort', - sonm: 'titlesort', - soar: 'artistsort', - soaa: 'albumartistsort', - soco: 'composersort', - '----:com.apple.iTunes:LYRICIST': 'lyricist', - '----:com.apple.iTunes:CONDUCTOR': 'conductor', - '----:com.apple.iTunes:REMIXER': 'remixer', - '----:com.apple.iTunes:ENGINEER': 'engineer', - '----:com.apple.iTunes:PRODUCER': 'producer', - '----:com.apple.iTunes:DJMIXER': 'djmixer', - '----:com.apple.iTunes:MIXER': 'mixer', - '----:com.apple.iTunes:LABEL': 'label', - '©grp': 'grouping', - '----:com.apple.iTunes:SUBTITLE': 'subtitle', - '----:com.apple.iTunes:DISCSUBTITLE': 'discsubtitle', - cpil: 'compilation', - tmpo: 'bpm', - '----:com.apple.iTunes:MOOD': 'mood', - '----:com.apple.iTunes:MEDIA': 'media', - '----:com.apple.iTunes:CATALOGNUMBER': 'catalognumber', - tvsh: 'tvShow', - tvsn: 'tvSeason', - tves: 'tvEpisode', - sosn: 'tvShowSort', - tven: 'tvEpisodeId', - tvnn: 'tvNetwork', - pcst: 'podcast', - purl: 'podcasturl', - '----:com.apple.iTunes:MusicBrainz Album Status': 'releasestatus', - '----:com.apple.iTunes:MusicBrainz Album Type': 'releasetype', - '----:com.apple.iTunes:MusicBrainz Album Release Country': 'releasecountry', - '----:com.apple.iTunes:SCRIPT': 'script', - '----:com.apple.iTunes:LANGUAGE': 'language', - cprt: 'copyright', - '©cpy': 'copyright', - '----:com.apple.iTunes:LICENSE': 'license', - '©too': 'encodedby', - pgap: 'gapless', - '----:com.apple.iTunes:BARCODE': 'barcode', - '----:com.apple.iTunes:ISRC': 'isrc', - '----:com.apple.iTunes:ASIN': 'asin', - '----:com.apple.iTunes:NOTES': 'comment', - '----:com.apple.iTunes:MusicBrainz Track Id': 'musicbrainz_recordingid', - '----:com.apple.iTunes:MusicBrainz Release Track Id': 'musicbrainz_trackid', - '----:com.apple.iTunes:MusicBrainz Album Id': 'musicbrainz_albumid', - '----:com.apple.iTunes:MusicBrainz Artist Id': 'musicbrainz_artistid', - '----:com.apple.iTunes:MusicBrainz Album Artist Id': 'musicbrainz_albumartistid', - '----:com.apple.iTunes:MusicBrainz Release Group Id': 'musicbrainz_releasegroupid', - '----:com.apple.iTunes:MusicBrainz Work Id': 'musicbrainz_workid', - '----:com.apple.iTunes:MusicBrainz TRM Id': 'musicbrainz_trmid', - '----:com.apple.iTunes:MusicBrainz Disc Id': 'musicbrainz_discid', - '----:com.apple.iTunes:Acoustid Id': 'acoustid_id', - '----:com.apple.iTunes:Acoustid Fingerprint': 'acoustid_fingerprint', - '----:com.apple.iTunes:MusicIP PUID': 'musicip_puid', - '----:com.apple.iTunes:fingerprint': 'musicip_fingerprint', - '----:com.apple.iTunes:replaygain_track_gain': 'replaygain_track_gain', - '----:com.apple.iTunes:replaygain_track_peak': 'replaygain_track_peak', - '----:com.apple.iTunes:replaygain_album_gain': 'replaygain_album_gain', - '----:com.apple.iTunes:replaygain_album_peak': 'replaygain_album_peak', - '----:com.apple.iTunes:replaygain_track_minmax': 'replaygain_track_minmax', - '----:com.apple.iTunes:replaygain_album_minmax': 'replaygain_album_minmax', - '----:com.apple.iTunes:replaygain_undo': 'replaygain_undo', - // Additional mappings: - gnre: 'genre', - '----:com.apple.iTunes:ALBUMARTISTSORT': 'albumartistsort', - '----:com.apple.iTunes:ARTISTS': 'artists', - '----:com.apple.iTunes:ORIGINALDATE': 'originaldate', - '----:com.apple.iTunes:ORIGINALYEAR': 'originalyear', - // '----:com.apple.iTunes:PERFORMER': 'performer' - desc: 'description', - ldes: 'longDescription', - '©mvn': 'movement', - '©mvi': 'movementIndex', - '©mvc': 'movementTotal', - '©wrk': 'work', - catg: 'category', - egid: 'podcastId', - hdvd: 'hdVideo', - keyw: 'keywords', - shwm: 'showMovement', - stik: 'stik' -}; -exports.tagType = 'iTunes'; -class MP4TagMapper extends CaseInsensitiveTagMap_1.CaseInsensitiveTagMap { - constructor() { - super([exports.tagType], mp4TagMap); - } -} -exports.MP4TagMapper = MP4TagMapper; -//# sourceMappingURL=MP4TagMapper.js.map - -/***/ }), - -/***/ 5261: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -/** - * Extended Lame Header - */ -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ExtendedLameHeader = void 0; -const Token = __webpack_require__(3416); -const common = __webpack_require__(3769); -const ReplayGainDataFormat_1 = __webpack_require__(6118); -/** - * Info Tag - * @link http://gabriel.mp3-tech.org/mp3infotag.html - * @link https://github.com/quodlibet/mutagen/blob/abd58ee58772224334a18817c3fb31103572f70e/mutagen/mp3/_util.py#L112 - */ -exports.ExtendedLameHeader = { - len: 27, - get: (buf, off) => { - const track_peak = Token.UINT32_BE.get(buf, off + 2); - return { - revision: common.getBitAllignedNumber(buf, off, 0, 4), - vbr_method: common.getBitAllignedNumber(buf, off, 4, 4), - lowpass_filter: 100 * Token.UINT8.get(buf, off + 1), - track_peak: track_peak === 0 ? undefined : track_peak / Math.pow(2, 23), - track_gain: ReplayGainDataFormat_1.ReplayGain.get(buf, 6), - album_gain: ReplayGainDataFormat_1.ReplayGain.get(buf, 8), - music_length: Token.UINT32_BE.get(buf, off + 20), - music_crc: Token.UINT8.get(buf, off + 24), - header_crc: Token.UINT16_BE.get(buf, off + 24) - }; - } -}; - - -/***/ }), - -/***/ 60: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MpegParser = void 0; -const Token = __webpack_require__(3416); -const core_1 = __webpack_require__(5849); -const debug_1 = __webpack_require__(1227); -const common = __webpack_require__(3769); -const AbstractID3Parser_1 = __webpack_require__(5159); -const XingTag_1 = __webpack_require__(3566); -const debug = (0, debug_1.default)('music-metadata:parser:mpeg'); -/** - * Cache buffer size used for searching synchronization preabmle - */ -const maxPeekLen = 1024; -/** - * MPEG-4 Audio definitions - * Ref: https://wiki.multimedia.cx/index.php/MPEG-4_Audio - */ -const MPEG4 = { - /** - * Audio Object Types - */ - AudioObjectTypes: [ - 'AAC Main', - 'AAC LC', - 'AAC SSR', - 'AAC LTP' // Long Term Prediction - ], - /** - * Sampling Frequencies - * https://wiki.multimedia.cx/index.php/MPEG-4_Audio#Sampling_Frequencies - */ - SamplingFrequencies: [ - 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, undefined, undefined, -1 - ] - /** - * Channel Configurations - */ -}; -const MPEG4_ChannelConfigurations = [ - undefined, - ['front-center'], - ['front-left', 'front-right'], - ['front-center', 'front-left', 'front-right'], - ['front-center', 'front-left', 'front-right', 'back-center'], - ['front-center', 'front-left', 'front-right', 'back-left', 'back-right'], - ['front-center', 'front-left', 'front-right', 'back-left', 'back-right', 'LFE-channel'], - ['front-center', 'front-left', 'front-right', 'side-left', 'side-right', 'back-left', 'back-right', 'LFE-channel'] -]; -/** - * MPEG Audio Layer I/II/III frame header - * Ref: https://www.mp3-tech.org/programmer/frame_header.html - * Bit layout: AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM - * Ref: https://wiki.multimedia.cx/index.php/ADTS - */ -class MpegFrameHeader { - constructor(buf, off) { - // B(20,19): MPEG Audio versionIndex ID - this.versionIndex = common.getBitAllignedNumber(buf, off + 1, 3, 2); - // C(18,17): Layer description - this.layer = MpegFrameHeader.LayerDescription[common.getBitAllignedNumber(buf, off + 1, 5, 2)]; - if (this.versionIndex > 1 && this.layer === 0) { - this.parseAdtsHeader(buf, off); // Audio Data Transport Stream (ADTS) - } - else { - this.parseMpegHeader(buf, off); // Conventional MPEG header - } - // D(16): Protection bit (if true 16-bit CRC follows header) - this.isProtectedByCRC = !common.isBitSet(buf, off + 1, 7); - } - calcDuration(numFrames) { - return numFrames * this.calcSamplesPerFrame() / this.samplingRate; - } - calcSamplesPerFrame() { - return MpegFrameHeader.samplesInFrameTable[this.version === 1 ? 0 : 1][this.layer]; - } - calculateSideInfoLength() { - if (this.layer !== 3) - return 2; - if (this.channelModeIndex === 3) { - // mono - if (this.version === 1) { - return 17; - } - else if (this.version === 2 || this.version === 2.5) { - return 9; - } - } - else { - if (this.version === 1) { - return 32; - } - else if (this.version === 2 || this.version === 2.5) { - return 17; - } - } - } - calcSlotSize() { - return [null, 4, 1, 1][this.layer]; - } - parseMpegHeader(buf, off) { - this.container = 'MPEG'; - // E(15,12): Bitrate index - this.bitrateIndex = common.getBitAllignedNumber(buf, off + 2, 0, 4); - // F(11,10): Sampling rate frequency index - this.sampRateFreqIndex = common.getBitAllignedNumber(buf, off + 2, 4, 2); - // G(9): Padding bit - this.padding = common.isBitSet(buf, off + 2, 6); - // H(8): Private bit - this.privateBit = common.isBitSet(buf, off + 2, 7); - // I(7,6): Channel Mode - this.channelModeIndex = common.getBitAllignedNumber(buf, off + 3, 0, 2); - // J(5,4): Mode extension (Only used in Joint stereo) - this.modeExtension = common.getBitAllignedNumber(buf, off + 3, 2, 2); - // K(3): Copyright - this.isCopyrighted = common.isBitSet(buf, off + 3, 4); - // L(2): Original - this.isOriginalMedia = common.isBitSet(buf, off + 3, 5); - // M(3): The original bit indicates, if it is set, that the frame is located on its original media. - this.emphasis = common.getBitAllignedNumber(buf, off + 3, 7, 2); - this.version = MpegFrameHeader.VersionID[this.versionIndex]; - this.channelMode = MpegFrameHeader.ChannelMode[this.channelModeIndex]; - this.codec = `MPEG ${this.version} Layer ${this.layer}`; - // Calculate bitrate - const bitrateInKbps = this.calcBitrate(); - if (!bitrateInKbps) { - throw new Error('Cannot determine bit-rate'); - } - this.bitrate = bitrateInKbps * 1000; - // Calculate sampling rate - this.samplingRate = this.calcSamplingRate(); - if (this.samplingRate == null) { - throw new Error('Cannot determine sampling-rate'); - } - } - parseAdtsHeader(buf, off) { - debug(`layer=0 => ADTS`); - this.version = this.versionIndex === 2 ? 4 : 2; - this.container = 'ADTS/MPEG-' + this.version; - const profileIndex = common.getBitAllignedNumber(buf, off + 2, 0, 2); - this.codec = 'AAC'; - this.codecProfile = MPEG4.AudioObjectTypes[profileIndex]; - debug(`MPEG-4 audio-codec=${this.codec}`); - const samplingFrequencyIndex = common.getBitAllignedNumber(buf, off + 2, 2, 4); - this.samplingRate = MPEG4.SamplingFrequencies[samplingFrequencyIndex]; - debug(`sampling-rate=${this.samplingRate}`); - const channelIndex = common.getBitAllignedNumber(buf, off + 2, 7, 3); - this.mp4ChannelConfig = MPEG4_ChannelConfigurations[channelIndex]; - debug(`channel-config=${this.mp4ChannelConfig.join('+')}`); - this.frameLength = common.getBitAllignedNumber(buf, off + 3, 6, 2) << 11; - } - calcBitrate() { - if (this.bitrateIndex === 0x00 || // free - this.bitrateIndex === 0x0F) { // reserved - return; - } - const codecIndex = `${Math.floor(this.version)}${this.layer}`; - return MpegFrameHeader.bitrate_index[this.bitrateIndex][codecIndex]; - } - calcSamplingRate() { - if (this.sampRateFreqIndex === 0x03) - return null; // 'reserved' - return MpegFrameHeader.sampling_rate_freq_index[this.version][this.sampRateFreqIndex]; - } -} -MpegFrameHeader.SyncByte1 = 0xFF; -MpegFrameHeader.SyncByte2 = 0xE0; -MpegFrameHeader.VersionID = [2.5, null, 2, 1]; -MpegFrameHeader.LayerDescription = [0, 3, 2, 1]; -MpegFrameHeader.ChannelMode = ['stereo', 'joint_stereo', 'dual_channel', 'mono']; -MpegFrameHeader.bitrate_index = { - 0x01: { 11: 32, 12: 32, 13: 32, 21: 32, 22: 8, 23: 8 }, - 0x02: { 11: 64, 12: 48, 13: 40, 21: 48, 22: 16, 23: 16 }, - 0x03: { 11: 96, 12: 56, 13: 48, 21: 56, 22: 24, 23: 24 }, - 0x04: { 11: 128, 12: 64, 13: 56, 21: 64, 22: 32, 23: 32 }, - 0x05: { 11: 160, 12: 80, 13: 64, 21: 80, 22: 40, 23: 40 }, - 0x06: { 11: 192, 12: 96, 13: 80, 21: 96, 22: 48, 23: 48 }, - 0x07: { 11: 224, 12: 112, 13: 96, 21: 112, 22: 56, 23: 56 }, - 0x08: { 11: 256, 12: 128, 13: 112, 21: 128, 22: 64, 23: 64 }, - 0x09: { 11: 288, 12: 160, 13: 128, 21: 144, 22: 80, 23: 80 }, - 0x0A: { 11: 320, 12: 192, 13: 160, 21: 160, 22: 96, 23: 96 }, - 0x0B: { 11: 352, 12: 224, 13: 192, 21: 176, 22: 112, 23: 112 }, - 0x0C: { 11: 384, 12: 256, 13: 224, 21: 192, 22: 128, 23: 128 }, - 0x0D: { 11: 416, 12: 320, 13: 256, 21: 224, 22: 144, 23: 144 }, - 0x0E: { 11: 448, 12: 384, 13: 320, 21: 256, 22: 160, 23: 160 } -}; -MpegFrameHeader.sampling_rate_freq_index = { - 1: { 0x00: 44100, 0x01: 48000, 0x02: 32000 }, - 2: { 0x00: 22050, 0x01: 24000, 0x02: 16000 }, - 2.5: { 0x00: 11025, 0x01: 12000, 0x02: 8000 } -}; -MpegFrameHeader.samplesInFrameTable = [ - /* Layer I II III */ - [0, 384, 1152, 1152], - [0, 384, 1152, 576] // MPEG-2(.5 -]; -/** - * MPEG Audio Layer I/II/III - */ -const FrameHeader = { - len: 4, - get: (buf, off) => { - return new MpegFrameHeader(buf, off); - } -}; -function getVbrCodecProfile(vbrScale) { - return 'V' + Math.floor((100 - vbrScale) / 10); -} -class MpegParser extends AbstractID3Parser_1.AbstractID3Parser { - constructor() { - super(...arguments); - this.frameCount = 0; - this.syncFrameCount = -1; - this.countSkipFrameData = 0; - this.totalDataLength = 0; - this.bitrates = []; - this.calculateEofDuration = false; - this.buf_frame_header = Buffer.alloc(4); - this.syncPeek = { - buf: Buffer.alloc(maxPeekLen), - len: 0 - }; - } - /** - * Called after ID3 headers have been parsed - */ - async postId3v2Parse() { - this.metadata.setFormat('lossless', false); - try { - let quit = false; - while (!quit) { - await this.sync(); - quit = await this.parseCommonMpegHeader(); - } - } - catch (err) { - if (err instanceof core_1.EndOfStreamError) { - debug(`End-of-stream`); - if (this.calculateEofDuration) { - const numberOfSamples = this.frameCount * this.samplesPerFrame; - this.metadata.setFormat('numberOfSamples', numberOfSamples); - const duration = numberOfSamples / this.metadata.format.sampleRate; - debug(`Calculate duration at EOF: ${duration} sec.`, duration); - this.metadata.setFormat('duration', duration); - } - } - else { - throw err; - } - } - } - /** - * Called after file has been fully parsed, this allows, if present, to exclude the ID3v1.1 header length - */ - finalize() { - const format = this.metadata.format; - const hasID3v1 = this.metadata.native.hasOwnProperty('ID3v1'); - if (format.duration && this.tokenizer.fileInfo.size) { - const mpegSize = this.tokenizer.fileInfo.size - this.mpegOffset - (hasID3v1 ? 128 : 0); - if (format.codecProfile && format.codecProfile[0] === 'V') { - this.metadata.setFormat('bitrate', mpegSize * 8 / format.duration); - } - } - else if (this.tokenizer.fileInfo.size && format.codecProfile === 'CBR') { - const mpegSize = this.tokenizer.fileInfo.size - this.mpegOffset - (hasID3v1 ? 128 : 0); - const numberOfSamples = Math.round(mpegSize / this.frame_size) * this.samplesPerFrame; - this.metadata.setFormat('numberOfSamples', numberOfSamples); - const duration = numberOfSamples / format.sampleRate; - debug("Calculate CBR duration based on file size: %s", duration); - this.metadata.setFormat('duration', duration); - } - } - async sync() { - let gotFirstSync = false; - while (true) { - let bo = 0; - this.syncPeek.len = await this.tokenizer.peekBuffer(this.syncPeek.buf, { length: maxPeekLen, mayBeLess: true }); - if (this.syncPeek.len <= 163) { - throw new core_1.EndOfStreamError(); - } - while (true) { - if (gotFirstSync && (this.syncPeek.buf[bo] & 0xE0) === 0xE0) { - this.buf_frame_header[0] = MpegFrameHeader.SyncByte1; - this.buf_frame_header[1] = this.syncPeek.buf[bo]; - await this.tokenizer.ignore(bo); - debug(`Sync at offset=${this.tokenizer.position - 1}, frameCount=${this.frameCount}`); - if (this.syncFrameCount === this.frameCount) { - debug(`Re-synced MPEG stream, frameCount=${this.frameCount}`); - this.frameCount = 0; - this.frame_size = 0; - } - this.syncFrameCount = this.frameCount; - return; // sync - } - else { - gotFirstSync = false; - bo = this.syncPeek.buf.indexOf(MpegFrameHeader.SyncByte1, bo); - if (bo === -1) { - if (this.syncPeek.len < this.syncPeek.buf.length) { - throw new core_1.EndOfStreamError(); - } - await this.tokenizer.ignore(this.syncPeek.len); - break; // continue with next buffer - } - else { - ++bo; - gotFirstSync = true; - } - } - } - } - } - /** - * Combined ADTS & MPEG (MP2 & MP3) header handling - * @return {Promise} true if parser should quit - */ - async parseCommonMpegHeader() { - if (this.frameCount === 0) { - this.mpegOffset = this.tokenizer.position - 1; - } - await this.tokenizer.peekBuffer(this.buf_frame_header, { offset: 1, length: 3 }); - let header; - try { - header = FrameHeader.get(this.buf_frame_header, 0); - } - catch (err) { - await this.tokenizer.ignore(1); - this.metadata.addWarning('Parse error: ' + err.message); - return false; // sync - } - await this.tokenizer.ignore(3); - this.metadata.setFormat('container', header.container); - this.metadata.setFormat('codec', header.codec); - this.metadata.setFormat('lossless', false); - this.metadata.setFormat('sampleRate', header.samplingRate); - this.frameCount++; - return header.version >= 2 && header.layer === 0 ? this.parseAdts(header) : this.parseAudioFrameHeader(header); - } - /** - * @return {Promise} true if parser should quit - */ - async parseAudioFrameHeader(header) { - this.metadata.setFormat('numberOfChannels', header.channelMode === 'mono' ? 1 : 2); - this.metadata.setFormat('bitrate', header.bitrate); - if (this.frameCount < 20 * 10000) { - debug('offset=%s MP%s bitrate=%s sample-rate=%s', this.tokenizer.position - 4, header.layer, header.bitrate, header.samplingRate); - } - const slot_size = header.calcSlotSize(); - if (slot_size === null) { - throw new Error('invalid slot_size'); - } - const samples_per_frame = header.calcSamplesPerFrame(); - debug(`samples_per_frame=${samples_per_frame}`); - const bps = samples_per_frame / 8.0; - const fsize = (bps * header.bitrate / header.samplingRate) + - ((header.padding) ? slot_size : 0); - this.frame_size = Math.floor(fsize); - this.audioFrameHeader = header; - this.bitrates.push(header.bitrate); - // xtra header only exists in first frame - if (this.frameCount === 1) { - this.offset = FrameHeader.len; - await this.skipSideInformation(); - return false; - } - if (this.frameCount === 3) { - // the stream is CBR if the first 3 frame bitrates are the same - if (this.areAllSame(this.bitrates)) { - // Actual calculation will be done in finalize - this.samplesPerFrame = samples_per_frame; - this.metadata.setFormat('codecProfile', 'CBR'); - if (this.tokenizer.fileInfo.size) - return true; // Will calculate duration based on the file size - } - else if (this.metadata.format.duration) { - return true; // We already got the duration, stop processing MPEG stream any further - } - if (!this.options.duration) { - return true; // Enforce duration not enabled, stop processing entire stream - } - } - // once we know the file is VBR attach listener to end of - // stream so we can do the duration calculation when we - // have counted all the frames - if (this.options.duration && this.frameCount === 4) { - this.samplesPerFrame = samples_per_frame; - this.calculateEofDuration = true; - } - this.offset = 4; - if (header.isProtectedByCRC) { - await this.parseCrc(); - return false; - } - else { - await this.skipSideInformation(); - return false; - } - } - async parseAdts(header) { - const buf = Buffer.alloc(3); - await this.tokenizer.readBuffer(buf); - header.frameLength += common.getBitAllignedNumber(buf, 0, 0, 11); - this.totalDataLength += header.frameLength; - this.samplesPerFrame = 1024; - const framesPerSec = header.samplingRate / this.samplesPerFrame; - const bytesPerFrame = this.frameCount === 0 ? 0 : this.totalDataLength / this.frameCount; - const bitrate = 8 * bytesPerFrame * framesPerSec + 0.5; - this.metadata.setFormat('bitrate', bitrate); - debug(`frame-count=${this.frameCount}, size=${header.frameLength} bytes, bit-rate=${bitrate}`); - await this.tokenizer.ignore(header.frameLength > 7 ? header.frameLength - 7 : 1); - // Consume remaining header and frame data - if (this.frameCount === 3) { - this.metadata.setFormat('codecProfile', header.codecProfile); - if (header.mp4ChannelConfig) { - this.metadata.setFormat('numberOfChannels', header.mp4ChannelConfig.length); - } - if (this.options.duration) { - this.calculateEofDuration = true; - } - else { - return true; // Stop parsing after the third frame - } - } - return false; - } - async parseCrc() { - this.crc = await this.tokenizer.readNumber(Token.INT16_BE); - this.offset += 2; - return this.skipSideInformation(); - } - async skipSideInformation() { - const sideinfo_length = this.audioFrameHeader.calculateSideInfoLength(); - // side information - await this.tokenizer.readToken(new Token.Uint8ArrayType(sideinfo_length)); - this.offset += sideinfo_length; - await this.readXtraInfoHeader(); - return; - } - async readXtraInfoHeader() { - const headerTag = await this.tokenizer.readToken(XingTag_1.InfoTagHeaderTag); - this.offset += XingTag_1.InfoTagHeaderTag.len; // 12 - switch (headerTag) { - case 'Info': - this.metadata.setFormat('codecProfile', 'CBR'); - return this.readXingInfoHeader(); - case 'Xing': - const infoTag = await this.readXingInfoHeader(); - const codecProfile = getVbrCodecProfile(infoTag.vbrScale); - this.metadata.setFormat('codecProfile', codecProfile); - return null; - case 'Xtra': - // ToDo: ??? - break; - case 'LAME': - const version = await this.tokenizer.readToken(XingTag_1.LameEncoderVersion); - if (this.frame_size >= this.offset + XingTag_1.LameEncoderVersion.len) { - this.offset += XingTag_1.LameEncoderVersion.len; - this.metadata.setFormat('tool', 'LAME ' + version); - await this.skipFrameData(this.frame_size - this.offset); - return null; - } - else { - this.metadata.addWarning('Corrupt LAME header'); - break; - } - // ToDo: ??? - } - // ToDo: promise duration??? - const frameDataLeft = this.frame_size - this.offset; - if (frameDataLeft < 0) { - this.metadata.addWarning('Frame ' + this.frameCount + 'corrupt: negative frameDataLeft'); - } - else { - await this.skipFrameData(frameDataLeft); - } - return null; - } - /** - * Ref: http://gabriel.mp3-tech.org/mp3infotag.html - * @returns {Promise} - */ - async readXingInfoHeader() { - const offset = this.tokenizer.position; - const infoTag = await (0, XingTag_1.readXingHeader)(this.tokenizer); - this.offset += this.tokenizer.position - offset; - if (infoTag.lame) { - this.metadata.setFormat('tool', 'LAME ' + common.stripNulls(infoTag.lame.version)); - if (infoTag.lame.extended) { - // this.metadata.setFormat('trackGain', infoTag.lame.extended.track_gain); - this.metadata.setFormat('trackPeakLevel', infoTag.lame.extended.track_peak); - if (infoTag.lame.extended.track_gain) { - this.metadata.setFormat('trackGain', infoTag.lame.extended.track_gain.adjustment); - } - if (infoTag.lame.extended.album_gain) { - this.metadata.setFormat('albumGain', infoTag.lame.extended.album_gain.adjustment); - } - this.metadata.setFormat('duration', infoTag.lame.extended.music_length / 1000); - } - } - if (infoTag.streamSize) { - const duration = this.audioFrameHeader.calcDuration(infoTag.numFrames); - this.metadata.setFormat('duration', duration); - debug('Get duration from Xing header: %s', this.metadata.format.duration); - return infoTag; - } - // frames field is not present - const frameDataLeft = this.frame_size - this.offset; - await this.skipFrameData(frameDataLeft); - return infoTag; - } - async skipFrameData(frameDataLeft) { - if (frameDataLeft < 0) - throw new Error('frame-data-left cannot be negative'); - await this.tokenizer.ignore(frameDataLeft); - this.countSkipFrameData += frameDataLeft; - } - areAllSame(array) { - const first = array[0]; - return array.every(element => { - return element === first; - }); - } -} -exports.MpegParser = MpegParser; - - -/***/ }), - -/***/ 6118: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ReplayGain = void 0; -const common = __webpack_require__(3769); -/** - * https://github.com/Borewit/music-metadata/wiki/Replay-Gain-Data-Format#name-code - */ -var NameCode; -(function (NameCode) { - /** - * not set - */ - NameCode[NameCode["not_set"] = 0] = "not_set"; - /** - * Radio Gain Adjustment - */ - NameCode[NameCode["radio"] = 1] = "radio"; - /** - * Audiophile Gain Adjustment - */ - NameCode[NameCode["audiophile"] = 2] = "audiophile"; -})(NameCode || (NameCode = {})); -/** - * https://github.com/Borewit/music-metadata/wiki/Replay-Gain-Data-Format#originator-code - */ -var ReplayGainOriginator; -(function (ReplayGainOriginator) { - /** - * Replay Gain unspecified - */ - ReplayGainOriginator[ReplayGainOriginator["unspecified"] = 0] = "unspecified"; - /** - * Replay Gain pre-set by artist/producer/mastering engineer - */ - ReplayGainOriginator[ReplayGainOriginator["engineer"] = 1] = "engineer"; - /** - * Replay Gain set by user - */ - ReplayGainOriginator[ReplayGainOriginator["user"] = 2] = "user"; - /** - * Replay Gain determined automatically, as described on this site - */ - ReplayGainOriginator[ReplayGainOriginator["automatic"] = 3] = "automatic"; - /** - * Set by simple RMS average - */ - ReplayGainOriginator[ReplayGainOriginator["rms_average"] = 4] = "rms_average"; -})(ReplayGainOriginator || (ReplayGainOriginator = {})); -/** - * Replay Gain Data Format - * - * https://github.com/Borewit/music-metadata/wiki/Replay-Gain-Data-Format - */ -exports.ReplayGain = { - len: 2, - get: (buf, off) => { - const gain_type = common.getBitAllignedNumber(buf, off, 0, 3); - const sign = common.getBitAllignedNumber(buf, off, 6, 1); - const gain_adj = common.getBitAllignedNumber(buf, off, 7, 9) / 10.0; - if (gain_type > 0) { - return { - type: common.getBitAllignedNumber(buf, off, 0, 3), - origin: common.getBitAllignedNumber(buf, off, 3, 3), - adjustment: (sign ? -gain_adj : gain_adj) - }; - } - return undefined; - } -}; - - -/***/ }), - -/***/ 3566: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.readXingHeader = exports.XingHeaderFlags = exports.LameEncoderVersion = exports.InfoTagHeaderTag = void 0; -const Token = __webpack_require__(3416); -const util = __webpack_require__(3769); -const ExtendedLameHeader_1 = __webpack_require__(5261); -/** - * Info Tag: Xing, LAME - */ -exports.InfoTagHeaderTag = new Token.StringType(4, 'ascii'); -/** - * LAME TAG value - * Did not find any official documentation for this - * Value e.g.: "3.98.4" - */ -exports.LameEncoderVersion = new Token.StringType(6, 'ascii'); -/** - * Info Tag - * Ref: http://gabriel.mp3-tech.org/mp3infotag.html - */ -exports.XingHeaderFlags = { - len: 4, - get: (buf, off) => { - return { - frames: util.isBitSet(buf, off, 31), - bytes: util.isBitSet(buf, off, 30), - toc: util.isBitSet(buf, off, 29), - vbrScale: util.isBitSet(buf, off, 28) - }; - } -}; -// /** -// * XING Header Tag -// * Ref: http://gabriel.mp3-tech.org/mp3infotag.html -// */ -async function readXingHeader(tokenizer) { - const flags = await tokenizer.readToken(exports.XingHeaderFlags); - const xingInfoTag = {}; - if (flags.frames) { - xingInfoTag.numFrames = await tokenizer.readToken(Token.UINT32_BE); - } - if (flags.bytes) { - xingInfoTag.streamSize = await tokenizer.readToken(Token.UINT32_BE); - } - if (flags.toc) { - xingInfoTag.toc = Buffer.alloc(100); - await tokenizer.readBuffer(xingInfoTag.toc); - } - if (flags.vbrScale) { - xingInfoTag.vbrScale = await tokenizer.readToken(Token.UINT32_BE); - } - const lameTag = await tokenizer.peekToken(new Token.StringType(4, 'ascii')); - if (lameTag === 'LAME') { - await tokenizer.ignore(4); - xingInfoTag.lame = { - version: await tokenizer.readToken(new Token.StringType(5, 'ascii')) - }; - const match = xingInfoTag.lame.version.match(/\d+.\d+/g); - if (match) { - const majorMinorVersion = xingInfoTag.lame.version.match(/\d+.\d+/g)[0]; // e.g. 3.97 - const version = majorMinorVersion.split('.').map(n => parseInt(n, 10)); - if (version[0] >= 3 && version[1] >= 90) { - xingInfoTag.lame.extended = await tokenizer.readToken(ExtendedLameHeader_1.ExtendedLameHeader); - } - } - } - return xingInfoTag; -} -exports.readXingHeader = readXingHeader; - - -/***/ }), - -/***/ 9606: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -const debug_1 = __webpack_require__(1227); -const Token = __webpack_require__(3416); -const AbstractID3Parser_1 = __webpack_require__(5159); -const MpcSv8Parser_1 = __webpack_require__(5170); -const MpcSv7Parser_1 = __webpack_require__(3928); -const debug = (0, debug_1.default)('music-metadata:parser:musepack'); -class MusepackParser extends AbstractID3Parser_1.AbstractID3Parser { - async postId3v2Parse() { - const signature = await this.tokenizer.peekToken(new Token.StringType(3, 'binary')); - let mpcParser; - switch (signature) { - case 'MP+': { - debug('Musepack stream-version 7'); - mpcParser = new MpcSv7Parser_1.MpcSv7Parser(); - break; - } - case 'MPC': { - debug('Musepack stream-version 8'); - mpcParser = new MpcSv8Parser_1.MpcSv8Parser(); - break; - } - default: { - throw new Error('Invalid Musepack signature prefix'); - } - } - mpcParser.init(this.metadata, this.tokenizer, this.options); - return mpcParser.parse(); - } -} -exports["default"] = MusepackParser; - - -/***/ }), - -/***/ 2812: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.BitReader = void 0; -const Token = __webpack_require__(3416); -class BitReader { - constructor(tokenizer) { - this.tokenizer = tokenizer; - this.pos = 0; - this.dword = undefined; - } - /** - * - * @param bits 1..30 bits - */ - async read(bits) { - while (this.dword === undefined) { - this.dword = await this.tokenizer.readToken(Token.UINT32_LE); - } - let out = this.dword; - this.pos += bits; - if (this.pos < 32) { - out >>>= (32 - this.pos); - return out & ((1 << bits) - 1); - } - else { - this.pos -= 32; - if (this.pos === 0) { - this.dword = undefined; - return out & ((1 << bits) - 1); - } - else { - this.dword = await this.tokenizer.readToken(Token.UINT32_LE); - if (this.pos) { - out <<= this.pos; - out |= this.dword >>> (32 - this.pos); - } - return out & ((1 << bits) - 1); - } - } - } - async ignore(bits) { - if (this.pos > 0) { - const remaining = 32 - this.pos; - this.dword = undefined; - bits -= remaining; - this.pos = 0; - } - const remainder = bits % 32; - const numOfWords = (bits - remainder) / 32; - await this.tokenizer.ignore(numOfWords * 4); - return this.read(remainder); - } -} -exports.BitReader = BitReader; - - -/***/ }), - -/***/ 3928: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MpcSv7Parser = void 0; -const debug_1 = __webpack_require__(1227); -const BasicParser_1 = __webpack_require__(7805); -const APEv2Parser_1 = __webpack_require__(6742); -const BitReader_1 = __webpack_require__(2812); -const SV7 = __webpack_require__(8153); -const debug = (0, debug_1.default)('music-metadata:parser:musepack'); -class MpcSv7Parser extends BasicParser_1.BasicParser { - constructor() { - super(...arguments); - this.audioLength = 0; - } - async parse() { - const header = await this.tokenizer.readToken(SV7.Header); - if (header.signature !== 'MP+') - throw new Error('Unexpected magic number'); - debug(`stream-version=${header.streamMajorVersion}.${header.streamMinorVersion}`); - this.metadata.setFormat('container', 'Musepack, SV7'); - this.metadata.setFormat('sampleRate', header.sampleFrequency); - const numberOfSamples = 1152 * (header.frameCount - 1) + header.lastFrameLength; - this.metadata.setFormat('numberOfSamples', numberOfSamples); - this.duration = numberOfSamples / header.sampleFrequency; - this.metadata.setFormat('duration', this.duration); - this.bitreader = new BitReader_1.BitReader(this.tokenizer); - this.metadata.setFormat('numberOfChannels', header.midSideStereo || header.intensityStereo ? 2 : 1); - const version = await this.bitreader.read(8); - this.metadata.setFormat('codec', (version / 100).toFixed(2)); - await this.skipAudioData(header.frameCount); - debug(`End of audio stream, switching to APEv2, offset=${this.tokenizer.position}`); - return APEv2Parser_1.APEv2Parser.tryParseApeHeader(this.metadata, this.tokenizer, this.options); - } - async skipAudioData(frameCount) { - while (frameCount-- > 0) { - const frameLength = await this.bitreader.read(20); - this.audioLength += 20 + frameLength; - await this.bitreader.ignore(frameLength); - } - // last frame - const lastFrameLength = await this.bitreader.read(11); - this.audioLength += lastFrameLength; - this.metadata.setFormat('bitrate', this.audioLength / this.duration); - } -} -exports.MpcSv7Parser = MpcSv7Parser; - - -/***/ }), - -/***/ 8153: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Header = void 0; -const Token = __webpack_require__(3416); -const util = __webpack_require__(3769); -/** - * BASIC STRUCTURE - */ -exports.Header = { - len: 6 * 4, - get: (buf, off) => { - const header = { - // word 0 - signature: Buffer.from(buf).toString('latin1', off, off + 3), - // versionIndex number * 1000 (3.81 = 3810) (remember that 4-byte alignment causes this to take 4-bytes) - streamMinorVersion: util.getBitAllignedNumber(buf, off + 3, 0, 4), - streamMajorVersion: util.getBitAllignedNumber(buf, off + 3, 4, 4), - // word 1 - frameCount: Token.UINT32_LE.get(buf, off + 4), - // word 2 - maxLevel: Token.UINT16_LE.get(buf, off + 8), - sampleFrequency: [44100, 48000, 37800, 32000][util.getBitAllignedNumber(buf, off + 10, 0, 2)], - link: util.getBitAllignedNumber(buf, off + 10, 2, 2), - profile: util.getBitAllignedNumber(buf, off + 10, 4, 4), - maxBand: util.getBitAllignedNumber(buf, off + 11, 0, 6), - intensityStereo: util.isBitSet(buf, off + 11, 6), - midSideStereo: util.isBitSet(buf, off + 11, 7), - // word 3 - titlePeak: Token.UINT16_LE.get(buf, off + 12), - titleGain: Token.UINT16_LE.get(buf, off + 14), - // word 4 - albumPeak: Token.UINT16_LE.get(buf, off + 16), - albumGain: Token.UINT16_LE.get(buf, off + 18), - // word - lastFrameLength: (Token.UINT32_LE.get(buf, off + 20) >>> 20) & 0x7FF, - trueGapless: util.isBitSet(buf, off + 23, 0) - }; - header.lastFrameLength = header.trueGapless ? (Token.UINT32_LE.get(buf, 20) >>> 20) & 0x7FF : 0; - return header; - } -}; - - -/***/ }), - -/***/ 5170: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.MpcSv8Parser = void 0; -const debug_1 = __webpack_require__(1227); -const BasicParser_1 = __webpack_require__(7805); -const APEv2Parser_1 = __webpack_require__(6742); -const FourCC_1 = __webpack_require__(8049); -const SV8 = __webpack_require__(8850); -const debug = (0, debug_1.default)('music-metadata:parser:musepack'); -class MpcSv8Parser extends BasicParser_1.BasicParser { - constructor() { - super(...arguments); - this.audioLength = 0; - } - async parse() { - const signature = await this.tokenizer.readToken(FourCC_1.FourCcToken); - if (signature !== 'MPCK') - throw new Error('Invalid Magic number'); - this.metadata.setFormat('container', 'Musepack, SV8'); - return this.parsePacket(); - } - async parsePacket() { - const sv8reader = new SV8.StreamReader(this.tokenizer); - do { - const header = await sv8reader.readPacketHeader(); - debug(`packet-header key=${header.key}, payloadLength=${header.payloadLength}`); - switch (header.key) { - case 'SH': // Stream Header - const sh = await sv8reader.readStreamHeader(header.payloadLength); - this.metadata.setFormat('numberOfSamples', sh.sampleCount); - this.metadata.setFormat('sampleRate', sh.sampleFrequency); - this.metadata.setFormat('duration', sh.sampleCount / sh.sampleFrequency); - this.metadata.setFormat('numberOfChannels', sh.channelCount); - break; - case 'AP': // Audio Packet - this.audioLength += header.payloadLength; - await this.tokenizer.ignore(header.payloadLength); - break; - case 'RG': // Replaygain - case 'EI': // Encoder Info - case 'SO': // Seek Table Offset - case 'ST': // Seek Table - case 'CT': // Chapter-Tag - await this.tokenizer.ignore(header.payloadLength); - break; - case 'SE': // Stream End - this.metadata.setFormat('bitrate', this.audioLength * 8 / this.metadata.format.duration); - return APEv2Parser_1.APEv2Parser.tryParseApeHeader(this.metadata, this.tokenizer, this.options); - default: - throw new Error(`Unexpected header: ${header.key}`); - } - } while (true); - } -} -exports.MpcSv8Parser = MpcSv8Parser; - - -/***/ }), - -/***/ 8850: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.StreamReader = void 0; -const Token = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const util = __webpack_require__(3769); -const debug = (0, debug_1.default)('music-metadata:parser:musepack:sv8'); -const PacketKey = new Token.StringType(2, 'binary'); -/** - * Stream Header Packet part 1 - * Ref: http://trac.musepack.net/musepack/wiki/SV8Specification#StreamHeaderPacket - */ -const SH_part1 = { - len: 5, - get: (buf, off) => { - return { - crc: Token.UINT32_LE.get(buf, off), - streamVersion: Token.UINT8.get(buf, off + 4) - }; - } -}; -/** - * Stream Header Packet part 3 - * Ref: http://trac.musepack.net/musepack/wiki/SV8Specification#StreamHeaderPacket - */ -const SH_part3 = { - len: 2, - get: (buf, off) => { - return { - sampleFrequency: [44100, 48000, 37800, 32000][util.getBitAllignedNumber(buf, off, 0, 3)], - maxUsedBands: util.getBitAllignedNumber(buf, off, 3, 5), - channelCount: util.getBitAllignedNumber(buf, off + 1, 0, 4) + 1, - msUsed: util.isBitSet(buf, off + 1, 4), - audioBlockFrames: util.getBitAllignedNumber(buf, off + 1, 5, 3) - }; - } -}; -class StreamReader { - constructor(tokenizer) { - this.tokenizer = tokenizer; - } - async readPacketHeader() { - const key = await this.tokenizer.readToken(PacketKey); - const size = await this.readVariableSizeField(); - return { - key, - payloadLength: size.value - 2 - size.len - }; - } - async readStreamHeader(size) { - const streamHeader = {}; - debug(`Reading SH at offset=${this.tokenizer.position}`); - const part1 = await this.tokenizer.readToken(SH_part1); - size -= SH_part1.len; - Object.assign(streamHeader, part1); - debug(`SH.streamVersion = ${part1.streamVersion}`); - const sampleCount = await this.readVariableSizeField(); - size -= sampleCount.len; - streamHeader.sampleCount = sampleCount.value; - const bs = await this.readVariableSizeField(); - size -= bs.len; - streamHeader.beginningOfSilence = bs.value; - const part3 = await this.tokenizer.readToken(SH_part3); - size -= SH_part3.len; - Object.assign(streamHeader, part3); - // assert.equal(size, 0); - await this.tokenizer.ignore(size); - return streamHeader; - } - async readVariableSizeField(len = 1, hb = 0) { - let n = await this.tokenizer.readNumber(Token.UINT8); - if ((n & 0x80) === 0) { - return { len, value: hb + n }; - } - n &= 0x7F; - n += hb; - return this.readVariableSizeField(len + 1, n << 7); - } -} -exports.StreamReader = StreamReader; - - -/***/ }), - -/***/ 1915: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.OggParser = exports.SegmentTable = void 0; -const Token = __webpack_require__(3416); -const core_1 = __webpack_require__(5849); -const debug_1 = __webpack_require__(1227); -const util = __webpack_require__(3769); -const FourCC_1 = __webpack_require__(8049); -const BasicParser_1 = __webpack_require__(7805); -const VorbisParser_1 = __webpack_require__(4210); -const OpusParser_1 = __webpack_require__(1272); -const SpeexParser_1 = __webpack_require__(573); -const TheoraParser_1 = __webpack_require__(2630); -const debug = (0, debug_1.default)('music-metadata:parser:ogg'); -class SegmentTable { - constructor(header) { - this.len = header.page_segments; - } - static sum(buf, off, len) { - let s = 0; - for (let i = off; i < off + len; ++i) { - s += buf[i]; - } - return s; - } - get(buf, off) { - return { - totalPageSize: SegmentTable.sum(buf, off, this.len) - }; - } -} -exports.SegmentTable = SegmentTable; -/** - * Parser for Ogg logical bitstream framing - */ -class OggParser extends BasicParser_1.BasicParser { - /** - * Parse page - * @returns {Promise} - */ - async parse() { - debug('pos=%s, parsePage()', this.tokenizer.position); - try { - let header; - do { - header = await this.tokenizer.readToken(OggParser.Header); - if (header.capturePattern !== 'OggS') - throw new Error('Invalid Ogg capture pattern'); - this.metadata.setFormat('container', 'Ogg'); - this.header = header; - this.pageNumber = header.pageSequenceNo; - debug('page#=%s, Ogg.id=%s', header.pageSequenceNo, header.capturePattern); - const segmentTable = await this.tokenizer.readToken(new SegmentTable(header)); - debug('totalPageSize=%s', segmentTable.totalPageSize); - const pageData = await this.tokenizer.readToken(new Token.Uint8ArrayType(segmentTable.totalPageSize)); - debug('firstPage=%s, lastPage=%s, continued=%s', header.headerType.firstPage, header.headerType.lastPage, header.headerType.continued); - if (header.headerType.firstPage) { - const id = new Token.StringType(7, 'ascii').get(Buffer.from(pageData), 0); - switch (id) { - case '\x01vorbis': // Ogg/Vorbis - debug('Set page consumer to Ogg/Vorbis'); - this.pageConsumer = new VorbisParser_1.VorbisParser(this.metadata, this.options); - break; - case 'OpusHea': // Ogg/Opus - debug('Set page consumer to Ogg/Opus'); - this.pageConsumer = new OpusParser_1.OpusParser(this.metadata, this.options, this.tokenizer); - break; - case 'Speex ': // Ogg/Speex - debug('Set page consumer to Ogg/Speex'); - this.pageConsumer = new SpeexParser_1.SpeexParser(this.metadata, this.options, this.tokenizer); - break; - case 'fishead': - case '\x00theora': // Ogg/Theora - debug('Set page consumer to Ogg/Theora'); - this.pageConsumer = new TheoraParser_1.TheoraParser(this.metadata, this.options, this.tokenizer); - break; - default: - throw new Error('gg audio-codec not recognized (id=' + id + ')'); - } - } - this.pageConsumer.parsePage(header, pageData); - } while (!header.headerType.lastPage); - } - catch (err) { - if (err instanceof core_1.EndOfStreamError) { - this.metadata.addWarning('Last OGG-page is not marked with last-page flag'); - debug(`End-of-stream`); - this.metadata.addWarning('Last OGG-page is not marked with last-page flag'); - if (this.header) { - this.pageConsumer.calculateDuration(this.header); - } - } - else if (err.message.startsWith('FourCC')) { - if (this.pageNumber > 0) { - // ignore this error: work-around if last OGG-page is not marked with last-page flag - this.metadata.addWarning('Invalid FourCC ID, maybe last OGG-page is not marked with last-page flag'); - this.pageConsumer.flush(); - } - } - else { - throw err; - } - } - } -} -exports.OggParser = OggParser; -OggParser.Header = { - len: 27, - get: (buf, off) => { - return { - capturePattern: FourCC_1.FourCcToken.get(buf, off), - version: Token.UINT8.get(buf, off + 4), - headerType: { - continued: util.getBit(buf, off + 5, 0), - firstPage: util.getBit(buf, off + 5, 1), - lastPage: util.getBit(buf, off + 5, 2) - }, - // packet_flag: buf.readUInt8(off + 5), - absoluteGranulePosition: Number(Token.UINT64_LE.get(buf, off + 6)), - streamSerialNumber: Token.UINT32_LE.get(buf, off + 14), - pageSequenceNo: Token.UINT32_LE.get(buf, off + 18), - pageChecksum: Token.UINT32_LE.get(buf, off + 22), - page_segments: Token.UINT8.get(buf, off + 26) - }; - } -}; - - -/***/ }), - -/***/ 5044: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.IdHeader = void 0; -const Token = __webpack_require__(3416); -/** - * Opus ID Header parser - * Ref: https://wiki.xiph.org/OggOpus#ID_Header - */ -class IdHeader { - constructor(len) { - this.len = len; - if (len < 19) { - throw new Error("ID-header-page 0 should be at least 19 bytes long"); - } - } - get(buf, off) { - return { - magicSignature: new Token.StringType(8, 'ascii').get(buf, off + 0), - version: buf.readUInt8(off + 8), - channelCount: buf.readUInt8(off + 9), - preSkip: buf.readInt16LE(off + 10), - inputSampleRate: buf.readInt32LE(off + 12), - outputGain: buf.readInt16LE(off + 16), - channelMapping: buf.readUInt8(off + 18) - }; - } -} -exports.IdHeader = IdHeader; - - -/***/ }), - -/***/ 1272: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.OpusParser = void 0; -const Token = __webpack_require__(3416); -const VorbisParser_1 = __webpack_require__(4210); -const Opus = __webpack_require__(5044); -/** - * Opus parser - * Internet Engineering Task Force (IETF) - RFC 6716 - * Used by OggParser - */ -class OpusParser extends VorbisParser_1.VorbisParser { - constructor(metadata, options, tokenizer) { - super(metadata, options); - this.tokenizer = tokenizer; - this.lastPos = -1; - } - /** - * Parse first Opus Ogg page - * @param {IPageHeader} header - * @param {Buffer} pageData - */ - parseFirstPage(header, pageData) { - this.metadata.setFormat('codec', 'Opus'); - // Parse Opus ID Header - this.idHeader = new Opus.IdHeader(pageData.length).get(pageData, 0); - if (this.idHeader.magicSignature !== "OpusHead") - throw new Error("Illegal ogg/Opus magic-signature"); - this.metadata.setFormat('sampleRate', this.idHeader.inputSampleRate); - this.metadata.setFormat('numberOfChannels', this.idHeader.channelCount); - } - parseFullPage(pageData) { - const magicSignature = new Token.StringType(8, 'ascii').get(pageData, 0); - switch (magicSignature) { - case 'OpusTags': - this.parseUserCommentList(pageData, 8); - this.lastPos = this.tokenizer.position - pageData.length; - break; - default: - break; - } - } - calculateDuration(header) { - if (this.metadata.format.sampleRate && header.absoluteGranulePosition >= 0) { - // Calculate duration - const pos_48bit = header.absoluteGranulePosition - this.idHeader.preSkip; - this.metadata.setFormat('numberOfSamples', pos_48bit); - this.metadata.setFormat('duration', pos_48bit / 48000); - if (this.lastPos !== -1 && this.tokenizer.fileInfo.size && this.metadata.format.duration) { - const dataSize = this.tokenizer.fileInfo.size - this.lastPos; - this.metadata.setFormat('bitrate', 8 * dataSize / this.metadata.format.duration); - } - } - } -} -exports.OpusParser = OpusParser; - - -/***/ }), - -/***/ 6666: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Header = void 0; -const Token = __webpack_require__(3416); -const util = __webpack_require__(3769); -/** - * Speex Header Packet - * Ref: https://www.speex.org/docs/manual/speex-manual/node8.html#SECTION00830000000000000000 - */ -exports.Header = { - len: 80, - get: (buf, off) => { - return { - speex: new Token.StringType(8, 'ascii').get(buf, off + 0), - version: util.trimRightNull(new Token.StringType(20, 'ascii').get(buf, off + 8)), - version_id: buf.readInt32LE(off + 28), - header_size: buf.readInt32LE(off + 32), - rate: buf.readInt32LE(off + 36), - mode: buf.readInt32LE(off + 40), - mode_bitstream_version: buf.readInt32LE(off + 44), - nb_channels: buf.readInt32LE(off + 48), - bitrate: buf.readInt32LE(off + 52), - frame_size: buf.readInt32LE(off + 56), - vbr: buf.readInt32LE(off + 60), - frames_per_packet: buf.readInt32LE(off + 64), - extra_headers: buf.readInt32LE(off + 68), - reserved1: buf.readInt32LE(off + 72), - reserved2: buf.readInt32LE(off + 76) - }; - } -}; - - -/***/ }), - -/***/ 573: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.SpeexParser = void 0; -const debug_1 = __webpack_require__(1227); -const VorbisParser_1 = __webpack_require__(4210); -const Speex = __webpack_require__(6666); -const debug = (0, debug_1.default)('music-metadata:parser:ogg:speex'); -/** - * Speex, RFC 5574 - * Ref: - * - https://www.speex.org/docs/manual/speex-manual/ - * - https://tools.ietf.org/html/rfc5574 - */ -class SpeexParser extends VorbisParser_1.VorbisParser { - constructor(metadata, options, tokenizer) { - super(metadata, options); - this.tokenizer = tokenizer; - } - /** - * Parse first Speex Ogg page - * @param {IPageHeader} header - * @param {Buffer} pageData - */ - parseFirstPage(header, pageData) { - debug('First Ogg/Speex page'); - const speexHeader = Speex.Header.get(pageData, 0); - this.metadata.setFormat('codec', `Speex ${speexHeader.version}`); - this.metadata.setFormat('numberOfChannels', speexHeader.nb_channels); - this.metadata.setFormat('sampleRate', speexHeader.rate); - if (speexHeader.bitrate !== -1) { - this.metadata.setFormat('bitrate', speexHeader.bitrate); - } - } -} -exports.SpeexParser = SpeexParser; - - -/***/ }), - -/***/ 5177: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.IdentificationHeader = void 0; -const Token = __webpack_require__(3416); -/** - * 6.2 Identification Header - * Ref: https://theora.org/doc/Theora.pdf: 6.2 Identification Header Decode - */ -exports.IdentificationHeader = { - len: 42, - get: (buf, off) => { - return { - id: new Token.StringType(7, 'ascii').get(buf, off), - vmaj: buf.readUInt8(off + 7), - vmin: buf.readUInt8(off + 8), - vrev: buf.readUInt8(off + 9), - vmbw: buf.readUInt16BE(off + 10), - vmbh: buf.readUInt16BE(off + 17), - nombr: Token.UINT24_BE.get(buf, off + 37), - nqual: buf.readUInt8(off + 40) - }; - } -}; - - -/***/ }), - -/***/ 2630: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.TheoraParser = void 0; -const debug_1 = __webpack_require__(1227); -const Theora_1 = __webpack_require__(5177); -const debug = (0, debug_1.default)('music-metadata:parser:ogg:theora'); -/** - * Ref: - * - https://theora.org/doc/Theora.pdf - */ -class TheoraParser { - constructor(metadata, options, tokenizer) { - this.metadata = metadata; - this.tokenizer = tokenizer; - } - /** - * Vorbis 1 parser - * @param header Ogg Page Header - * @param pageData Page data - */ - parsePage(header, pageData) { - if (header.headerType.firstPage) { - this.parseFirstPage(header, pageData); - } - } - flush() { - debug('flush'); - } - calculateDuration(header) { - debug('duration calculation not implemented'); - } - /** - * Parse first Theora Ogg page. the initial identification header packet - * @param {IPageHeader} header - * @param {Buffer} pageData - */ - parseFirstPage(header, pageData) { - debug('First Ogg/Theora page'); - this.metadata.setFormat('codec', 'Theora'); - const idHeader = Theora_1.IdentificationHeader.get(pageData, 0); - this.metadata.setFormat('bitrate', idHeader.nombr); - } -} -exports.TheoraParser = TheoraParser; - - -/***/ }), - -/***/ 2127: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.IdentificationHeader = exports.CommonHeader = exports.VorbisPictureToken = void 0; -const Token = __webpack_require__(3416); -const ID3v2Token_1 = __webpack_require__(8281); -/** - * Parse the METADATA_BLOCK_PICTURE - * Ref: https://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE - * Ref: https://xiph.org/flac/format.html#metadata_block_picture - * // ToDo: move to ID3 / APIC? - */ -class VorbisPictureToken { - constructor(len) { - this.len = len; - } - static fromBase64(base64str) { - return this.fromBuffer(Buffer.from(base64str, 'base64')); - } - static fromBuffer(buffer) { - const pic = new VorbisPictureToken(buffer.length); - return pic.get(buffer, 0); - } - get(buffer, offset) { - const type = ID3v2Token_1.AttachedPictureType[Token.UINT32_BE.get(buffer, offset)]; - const mimeLen = Token.UINT32_BE.get(buffer, offset += 4); - const format = buffer.toString('utf-8', offset += 4, offset + mimeLen); - const descLen = Token.UINT32_BE.get(buffer, offset += mimeLen); - const description = buffer.toString('utf-8', offset += 4, offset + descLen); - const width = Token.UINT32_BE.get(buffer, offset += descLen); - const height = Token.UINT32_BE.get(buffer, offset += 4); - const colour_depth = Token.UINT32_BE.get(buffer, offset += 4); - const indexed_color = Token.UINT32_BE.get(buffer, offset += 4); - const picDataLen = Token.UINT32_BE.get(buffer, offset += 4); - const data = Buffer.from(buffer.slice(offset += 4, offset + picDataLen)); - return { - type, - format, - description, - width, - height, - colour_depth, - indexed_color, - data - }; - } -} -exports.VorbisPictureToken = VorbisPictureToken; -/** - * Comment header decoder - * Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-620004.2.1 - */ -exports.CommonHeader = { - len: 7, - get: (buf, off) => { - return { - packetType: buf.readUInt8(off), - vorbis: new Token.StringType(6, 'ascii').get(buf, off + 1) - }; - } -}; -/** - * Identification header decoder - * Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-630004.2.2 - */ -exports.IdentificationHeader = { - len: 23, - get: (uint8Array, off) => { - const dataView = new DataView(uint8Array.buffer, uint8Array.byteOffset); - return { - version: dataView.getUint32(off + 0, true), - channelMode: dataView.getUint8(off + 4), - sampleRate: dataView.getUint32(off + 5, true), - bitrateMax: dataView.getUint32(off + 9, true), - bitrateNominal: dataView.getUint32(off + 13, true), - bitrateMin: dataView.getUint32(off + 17, true) - }; - } -}; - - -/***/ }), - -/***/ 441: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.VorbisDecoder = void 0; -const Token = __webpack_require__(3416); -class VorbisDecoder { - constructor(data, offset) { - this.data = data; - this.offset = offset; - } - readInt32() { - const value = Token.UINT32_LE.get(this.data, this.offset); - this.offset += 4; - return value; - } - readStringUtf8() { - const len = this.readInt32(); - const value = Buffer.from(this.data).toString('utf-8', this.offset, this.offset + len); - this.offset += len; - return value; - } - parseUserComment() { - const offset0 = this.offset; - const v = this.readStringUtf8(); - const idx = v.indexOf('='); - return { - key: v.slice(0, idx).toUpperCase(), - value: v.slice(idx + 1), - len: this.offset - offset0 - }; - } -} -exports.VorbisDecoder = VorbisDecoder; - - -/***/ }), - -/***/ 4210: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.VorbisParser = void 0; -const Token = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const VorbisDecoder_1 = __webpack_require__(441); -const Vorbis_1 = __webpack_require__(2127); -const debug = (0, debug_1.default)('music-metadata:parser:ogg:vorbis1'); -/** - * Vorbis 1 Parser. - * Used by OggParser - */ -class VorbisParser { - constructor(metadata, options) { - this.metadata = metadata; - this.options = options; - this.pageSegments = []; - } - /** - * Vorbis 1 parser - * @param header Ogg Page Header - * @param pageData Page data - */ - parsePage(header, pageData) { - if (header.headerType.firstPage) { - this.parseFirstPage(header, pageData); - } - else { - if (header.headerType.continued) { - if (this.pageSegments.length === 0) { - throw new Error("Cannot continue on previous page"); - } - this.pageSegments.push(pageData); - } - if (header.headerType.lastPage || !header.headerType.continued) { - // Flush page segments - if (this.pageSegments.length > 0) { - const fullPage = Buffer.concat(this.pageSegments); - this.parseFullPage(fullPage); - } - // Reset page segments - this.pageSegments = header.headerType.lastPage ? [] : [pageData]; - } - } - if (header.headerType.lastPage) { - this.calculateDuration(header); - } - } - flush() { - this.parseFullPage(Buffer.concat(this.pageSegments)); - } - parseUserComment(pageData, offset) { - const decoder = new VorbisDecoder_1.VorbisDecoder(pageData, offset); - const tag = decoder.parseUserComment(); - this.addTag(tag.key, tag.value); - return tag.len; - } - addTag(id, value) { - if (id === 'METADATA_BLOCK_PICTURE' && (typeof value === 'string')) { - if (this.options.skipCovers) { - debug(`Ignore picture`); - return; - } - value = Vorbis_1.VorbisPictureToken.fromBase64(value); - debug(`Push picture: id=${id}, format=${value.format}`); - } - else { - debug(`Push tag: id=${id}, value=${value}`); - } - this.metadata.addTag('vorbis', id, value); - } - calculateDuration(header) { - if (this.metadata.format.sampleRate && header.absoluteGranulePosition >= 0) { - // Calculate duration - this.metadata.setFormat('numberOfSamples', header.absoluteGranulePosition); - this.metadata.setFormat('duration', this.metadata.format.numberOfSamples / this.metadata.format.sampleRate); - } - } - /** - * Parse first Ogg/Vorbis page - * @param {IPageHeader} header - * @param {Buffer} pageData - */ - parseFirstPage(header, pageData) { - this.metadata.setFormat('codec', 'Vorbis I'); - debug("Parse first page"); - // Parse Vorbis common header - const commonHeader = Vorbis_1.CommonHeader.get(pageData, 0); - if (commonHeader.vorbis !== 'vorbis') - throw new Error('Metadata does not look like Vorbis'); - if (commonHeader.packetType === 1) { - const idHeader = Vorbis_1.IdentificationHeader.get(pageData, Vorbis_1.CommonHeader.len); - this.metadata.setFormat('sampleRate', idHeader.sampleRate); - this.metadata.setFormat('bitrate', idHeader.bitrateNominal); - this.metadata.setFormat('numberOfChannels', idHeader.channelMode); - debug("sample-rate=%s[hz], bitrate=%s[b/s], channel-mode=%s", idHeader.sampleRate, idHeader.bitrateNominal, idHeader.channelMode); - } - else - throw new Error('First Ogg page should be type 1: the identification header'); - } - parseFullPage(pageData) { - // New page - const commonHeader = Vorbis_1.CommonHeader.get(pageData, 0); - debug("Parse full page: type=%s, byteLength=%s", commonHeader.packetType, pageData.byteLength); - switch (commonHeader.packetType) { - case 3: // type 3: comment header - return this.parseUserCommentList(pageData, Vorbis_1.CommonHeader.len); - case 1: // type 1: the identification header - case 5: // type 5: setup header type - break; // ignore - } - } - /** - * Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-840005.2 - */ - parseUserCommentList(pageData, offset) { - const strLen = Token.UINT32_LE.get(pageData, offset); - offset += 4; - // const vendorString = new Token.StringType(strLen, 'utf-8').get(pageData, offset); - offset += strLen; - let userCommentListLength = Token.UINT32_LE.get(pageData, offset); - offset += 4; - while (userCommentListLength-- > 0) { - offset += this.parseUserComment(pageData, offset); - } - } -} -exports.VorbisParser = VorbisParser; - - -/***/ }), - -/***/ 9860: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.VorbisTagMapper = void 0; -const GenericTagMapper_1 = __webpack_require__(9918); -/** - * Vorbis tag mappings - * - * Mapping from native header format to one or possibly more 'common' entries - * The common entries aim to read the same information from different media files - * independent of the underlying format - */ -const vorbisTagMap = { - TITLE: 'title', - ARTIST: 'artist', - ARTISTS: 'artists', - ALBUMARTIST: 'albumartist', - 'ALBUM ARTIST': 'albumartist', - ALBUM: 'album', - DATE: 'date', - ORIGINALDATE: 'originaldate', - ORIGINALYEAR: 'originalyear', - COMMENT: 'comment', - TRACKNUMBER: 'track', - DISCNUMBER: 'disk', - GENRE: 'genre', - METADATA_BLOCK_PICTURE: 'picture', - COMPOSER: 'composer', - LYRICS: 'lyrics', - ALBUMSORT: 'albumsort', - TITLESORT: 'titlesort', - WORK: 'work', - ARTISTSORT: 'artistsort', - ALBUMARTISTSORT: 'albumartistsort', - COMPOSERSORT: 'composersort', - LYRICIST: 'lyricist', - WRITER: 'writer', - CONDUCTOR: 'conductor', - // 'PERFORMER=artist (instrument)': 'performer:instrument', // ToDo - REMIXER: 'remixer', - ARRANGER: 'arranger', - ENGINEER: 'engineer', - PRODUCER: 'producer', - DJMIXER: 'djmixer', - MIXER: 'mixer', - LABEL: 'label', - GROUPING: 'grouping', - SUBTITLE: 'subtitle', - DISCSUBTITLE: 'discsubtitle', - TRACKTOTAL: 'totaltracks', - DISCTOTAL: 'totaldiscs', - COMPILATION: 'compilation', - RATING: 'rating', - BPM: 'bpm', - KEY: 'key', - MOOD: 'mood', - MEDIA: 'media', - CATALOGNUMBER: 'catalognumber', - RELEASESTATUS: 'releasestatus', - RELEASETYPE: 'releasetype', - RELEASECOUNTRY: 'releasecountry', - SCRIPT: 'script', - LANGUAGE: 'language', - COPYRIGHT: 'copyright', - LICENSE: 'license', - ENCODEDBY: 'encodedby', - ENCODERSETTINGS: 'encodersettings', - BARCODE: 'barcode', - ISRC: 'isrc', - ASIN: 'asin', - MUSICBRAINZ_TRACKID: 'musicbrainz_recordingid', - MUSICBRAINZ_RELEASETRACKID: 'musicbrainz_trackid', - MUSICBRAINZ_ALBUMID: 'musicbrainz_albumid', - MUSICBRAINZ_ARTISTID: 'musicbrainz_artistid', - MUSICBRAINZ_ALBUMARTISTID: 'musicbrainz_albumartistid', - MUSICBRAINZ_RELEASEGROUPID: 'musicbrainz_releasegroupid', - MUSICBRAINZ_WORKID: 'musicbrainz_workid', - MUSICBRAINZ_TRMID: 'musicbrainz_trmid', - MUSICBRAINZ_DISCID: 'musicbrainz_discid', - ACOUSTID_ID: 'acoustid_id', - ACOUSTID_ID_FINGERPRINT: 'acoustid_fingerprint', - MUSICIP_PUID: 'musicip_puid', - // 'FINGERPRINT=MusicMagic Fingerprint {fingerprint}': 'musicip_fingerprint', // ToDo - WEBSITE: 'website', - NOTES: 'notes', - TOTALTRACKS: 'totaltracks', - TOTALDISCS: 'totaldiscs', - // Discogs - DISCOGS_ARTIST_ID: 'discogs_artist_id', - DISCOGS_ARTISTS: 'artists', - DISCOGS_ARTIST_NAME: 'artists', - DISCOGS_ALBUM_ARTISTS: 'albumartist', - DISCOGS_CATALOG: 'catalognumber', - DISCOGS_COUNTRY: 'releasecountry', - DISCOGS_DATE: 'originaldate', - DISCOGS_LABEL: 'label', - DISCOGS_LABEL_ID: 'discogs_label_id', - DISCOGS_MASTER_RELEASE_ID: 'discogs_master_release_id', - DISCOGS_RATING: 'discogs_rating', - DISCOGS_RELEASED: 'date', - DISCOGS_RELEASE_ID: 'discogs_release_id', - DISCOGS_VOTES: 'discogs_votes', - CATALOGID: 'catalognumber', - STYLE: 'genre', - // - REPLAYGAIN_TRACK_GAIN: 'replaygain_track_gain', - REPLAYGAIN_TRACK_PEAK: 'replaygain_track_peak', - REPLAYGAIN_ALBUM_GAIN: 'replaygain_album_gain', - REPLAYGAIN_ALBUM_PEAK: 'replaygain_album_peak', - // To Sure if these (REPLAYGAIN_MINMAX, REPLAYGAIN_ALBUM_MINMAX & REPLAYGAIN_UNDO) are used for Vorbis: - REPLAYGAIN_MINMAX: 'replaygain_track_minmax', - REPLAYGAIN_ALBUM_MINMAX: 'replaygain_album_minmax', - REPLAYGAIN_UNDO: 'replaygain_undo' -}; -class VorbisTagMapper extends GenericTagMapper_1.CommonTagMapper { - static toRating(email, rating) { - return { - source: email ? email.toLowerCase() : email, - rating: parseFloat(rating) * GenericTagMapper_1.CommonTagMapper.maxRatingScore - }; - } - constructor() { - super(['vorbis'], vorbisTagMap); - } - postMap(tag) { - if (tag.id.indexOf('RATING:') === 0) { - const keys = tag.id.split(':'); - tag.value = VorbisTagMapper.toRating(keys[1], tag.value); - tag.id = keys[0]; - } - } -} -exports.VorbisTagMapper = VorbisTagMapper; -//# sourceMappingURL=VorbisTagMapper.js.map - -/***/ }), - -/***/ 3211: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ListInfoTagValue = exports.Header = void 0; -const Token = __webpack_require__(3416); -/** - * Common RIFF chunk header - */ -exports.Header = { - len: 8, - get: (buf, off) => { - return { - // Group-ID - chunkID: buf.toString('binary', off, off + 4), - // Size - chunkSize: Token.UINT32_LE.get(buf, 4) - }; - } -}; -/** - * Token to parse RIFF-INFO tag value - */ -class ListInfoTagValue { - constructor(tagHeader) { - this.tagHeader = tagHeader; - this.len = tagHeader.chunkSize; - this.len += this.len & 1; // if it is an odd length, round up to even - } - get(buf, off) { - return new Token.StringType(this.tagHeader.chunkSize, 'ascii').get(buf, off); - } -} -exports.ListInfoTagValue = ListInfoTagValue; - - -/***/ }), - -/***/ 5756: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.RiffInfoTagMapper = exports.riffInfoTagMap = void 0; -const GenericTagMapper_1 = __webpack_require__(9918); -/** - * RIFF Info Tags; part of the EXIF 2.3 - * Ref: http://owl.phy.queensu.ca/~phil/exiftool/TagNames/RIFF.html#Info - */ -exports.riffInfoTagMap = { - IART: 'artist', - ICRD: 'date', - INAM: 'title', - TITL: 'title', - IPRD: 'album', - ITRK: 'track', - COMM: 'comment', - ICMT: 'comment', - ICNT: 'releasecountry', - GNRE: 'genre', - IWRI: 'writer', - RATE: 'rating', - YEAR: 'year', - ISFT: 'encodedby', - CODE: 'encodedby', - TURL: 'website', - IGNR: 'genre', - IENG: 'engineer', - ITCH: 'technician', - IMED: 'media', - IRPD: 'album' // Product, where the file was intended for -}; -class RiffInfoTagMapper extends GenericTagMapper_1.CommonTagMapper { - constructor() { - super(['exif'], exports.riffInfoTagMap); - } -} -exports.RiffInfoTagMapper = RiffInfoTagMapper; -//# sourceMappingURL=RiffInfoTagMap.js.map - -/***/ }), - -/***/ 6032: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.TrackType = void 0; -var types_1 = __webpack_require__(8591); -Object.defineProperty(exports, "TrackType", ({ enumerable: true, get: function () { return types_1.TrackType; } })); -//# sourceMappingURL=type.js.map - -/***/ }), - -/***/ 8053: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.BroadcastAudioExtensionChunk = void 0; -const Token = __webpack_require__(3416); -/** - * Broadcast Audio Extension Chunk - * Ref: https://tech.ebu.ch/docs/tech/tech3285.pdf - */ -exports.BroadcastAudioExtensionChunk = { - len: 420, - get: (uint8array, off) => { - return { - description: new Token.StringType(256, 'ascii').get(uint8array, off).trim(), - originator: new Token.StringType(32, 'ascii').get(uint8array, off + 256).trim(), - originatorReference: new Token.StringType(32, 'ascii').get(uint8array, off + 288).trim(), - originationDate: new Token.StringType(10, 'ascii').get(uint8array, off + 320).trim(), - originationTime: new Token.StringType(8, 'ascii').get(uint8array, off + 330).trim(), - timeReferenceLow: Token.UINT32_LE.get(uint8array, off + 338), - timeReferenceHigh: Token.UINT32_LE.get(uint8array, off + 342), - version: Token.UINT16_LE.get(uint8array, off + 346), - umid: new Token.Uint8ArrayType(64).get(uint8array, off + 348), - loudnessValue: Token.UINT16_LE.get(uint8array, off + 412), - maxTruePeakLevel: Token.UINT16_LE.get(uint8array, off + 414), - maxMomentaryLoudness: Token.UINT16_LE.get(uint8array, off + 416), - maxShortTermLoudness: Token.UINT16_LE.get(uint8array, off + 418) - }; - } -}; - - -/***/ }), - -/***/ 9975: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.FactChunk = exports.Format = exports.WaveFormat = void 0; -/** - * Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317599(v=vs.85).aspx - */ -var WaveFormat; -(function (WaveFormat) { - WaveFormat[WaveFormat["PCM"] = 1] = "PCM"; - // MPEG-4 and AAC Audio Types - WaveFormat[WaveFormat["ADPCM"] = 2] = "ADPCM"; - WaveFormat[WaveFormat["IEEE_FLOAT"] = 3] = "IEEE_FLOAT"; - WaveFormat[WaveFormat["MPEG_ADTS_AAC"] = 5632] = "MPEG_ADTS_AAC"; - WaveFormat[WaveFormat["MPEG_LOAS"] = 5634] = "MPEG_LOAS"; - WaveFormat[WaveFormat["RAW_AAC1"] = 255] = "RAW_AAC1"; - // Dolby Audio Types - WaveFormat[WaveFormat["DOLBY_AC3_SPDIF"] = 146] = "DOLBY_AC3_SPDIF"; - WaveFormat[WaveFormat["DVM"] = 8192] = "DVM"; - WaveFormat[WaveFormat["RAW_SPORT"] = 576] = "RAW_SPORT"; - WaveFormat[WaveFormat["ESST_AC3"] = 577] = "ESST_AC3"; - WaveFormat[WaveFormat["DRM"] = 9] = "DRM"; - WaveFormat[WaveFormat["DTS2"] = 8193] = "DTS2"; - WaveFormat[WaveFormat["MPEG"] = 80] = "MPEG"; -})(WaveFormat = exports.WaveFormat || (exports.WaveFormat = {})); -/** - * format chunk; chunk-id is "fmt " - * http://soundfile.sapp.org/doc/WaveFormat/ - */ -class Format { - constructor(header) { - if (header.chunkSize < 16) - throw new Error('Invalid chunk size'); - this.len = header.chunkSize; - } - get(buf, off) { - return { - wFormatTag: buf.readUInt16LE(off), - nChannels: buf.readUInt16LE(off + 2), - nSamplesPerSec: buf.readUInt32LE(off + 4), - nAvgBytesPerSec: buf.readUInt32LE(off + 8), - nBlockAlign: buf.readUInt16LE(off + 12), - wBitsPerSample: buf.readUInt16LE(off + 14) - }; - } -} -exports.Format = Format; -/** - * Fact chunk; chunk-id is "fact" - * http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html - * http://www.recordingblogs.com/wiki/fact-chunk-of-a-wave-file - */ -class FactChunk { - constructor(header) { - if (header.chunkSize < 4) { - throw new Error('Invalid fact chunk size.'); - } - this.len = header.chunkSize; - } - get(buf, off) { - return { - dwSampleLength: buf.readUInt32LE(off) - }; - } -} -exports.FactChunk = FactChunk; - - -/***/ }), - -/***/ 2682: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.WaveParser = void 0; -const strtok3 = __webpack_require__(5849); -const Token = __webpack_require__(3416); -const debug_1 = __webpack_require__(1227); -const riff = __webpack_require__(3211); -const WaveChunk = __webpack_require__(9975); -const ID3v2Parser_1 = __webpack_require__(8928); -const util = __webpack_require__(3769); -const FourCC_1 = __webpack_require__(8049); -const BasicParser_1 = __webpack_require__(7805); -const BwfChunk_1 = __webpack_require__(8053); -const debug = (0, debug_1.default)('music-metadata:parser:RIFF'); -/** - * Resource Interchange File Format (RIFF) Parser - * - * WAVE PCM soundfile format - * - * Ref: - * - http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html - * - http://soundfile.sapp.org/doc/WaveFormat - * - * ToDo: Split WAVE part from RIFF parser - */ -class WaveParser extends BasicParser_1.BasicParser { - async parse() { - const riffHeader = await this.tokenizer.readToken(riff.Header); - debug(`pos=${this.tokenizer.position}, parse: chunkID=${riffHeader.chunkID}`); - if (riffHeader.chunkID !== 'RIFF') - return; // Not RIFF format - return this.parseRiffChunk(riffHeader.chunkSize).catch(err => { - if (!(err instanceof strtok3.EndOfStreamError)) { - throw err; - } - }); - } - async parseRiffChunk(chunkSize) { - const type = await this.tokenizer.readToken(FourCC_1.FourCcToken); - this.metadata.setFormat('container', type); - switch (type) { - case 'WAVE': - return this.readWaveChunk(chunkSize - FourCC_1.FourCcToken.len); - default: - throw new Error(`Unsupported RIFF format: RIFF/${type}`); - } - } - async readWaveChunk(remaining) { - while (remaining >= riff.Header.len) { - const header = await this.tokenizer.readToken(riff.Header); - remaining -= riff.Header.len + header.chunkSize; - if (header.chunkSize > remaining) { - this.metadata.addWarning('Data chunk size exceeds file size'); - } - this.header = header; - debug(`pos=${this.tokenizer.position}, readChunk: chunkID=RIFF/WAVE/${header.chunkID}`); - switch (header.chunkID) { - case 'LIST': - await this.parseListTag(header); - break; - case 'fact': // extended Format chunk, - this.metadata.setFormat('lossless', false); - this.fact = await this.tokenizer.readToken(new WaveChunk.FactChunk(header)); - break; - case 'fmt ': // The Util Chunk, non-PCM Formats - const fmt = await this.tokenizer.readToken(new WaveChunk.Format(header)); - let subFormat = WaveChunk.WaveFormat[fmt.wFormatTag]; - if (!subFormat) { - debug('WAVE/non-PCM format=' + fmt.wFormatTag); - subFormat = 'non-PCM (' + fmt.wFormatTag + ')'; - } - this.metadata.setFormat('codec', subFormat); - this.metadata.setFormat('bitsPerSample', fmt.wBitsPerSample); - this.metadata.setFormat('sampleRate', fmt.nSamplesPerSec); - this.metadata.setFormat('numberOfChannels', fmt.nChannels); - this.metadata.setFormat('bitrate', fmt.nBlockAlign * fmt.nSamplesPerSec * 8); - this.blockAlign = fmt.nBlockAlign; - break; - case 'id3 ': // The way Picard, FooBar currently stores, ID3 meta-data - case 'ID3 ': // The way Mp3Tags stores ID3 meta-data - const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(header.chunkSize)); - const rst = strtok3.fromBuffer(id3_data); - await new ID3v2Parser_1.ID3v2Parser().parse(this.metadata, rst, this.options); - break; - case 'data': // PCM-data - if (this.metadata.format.lossless !== false) { - this.metadata.setFormat('lossless', true); - } - let chunkSize = header.chunkSize; - if (this.tokenizer.fileInfo.size) { - const calcRemaining = this.tokenizer.fileInfo.size - this.tokenizer.position; - if (calcRemaining < chunkSize) { - this.metadata.addWarning('data chunk length exceeding file length'); - chunkSize = calcRemaining; - } - } - const numberOfSamples = this.fact ? this.fact.dwSampleLength : (chunkSize === 0xffffffff ? undefined : chunkSize / this.blockAlign); - if (numberOfSamples) { - this.metadata.setFormat('numberOfSamples', numberOfSamples); - this.metadata.setFormat('duration', numberOfSamples / this.metadata.format.sampleRate); - } - this.metadata.setFormat('bitrate', this.metadata.format.numberOfChannels * this.blockAlign * this.metadata.format.sampleRate); // ToDo: check me - await this.tokenizer.ignore(header.chunkSize); - break; - case 'bext': // Broadcast Audio Extension chunk https://tech.ebu.ch/docs/tech/tech3285.pdf - const bext = await this.tokenizer.readToken(BwfChunk_1.BroadcastAudioExtensionChunk); - Object.keys(bext).forEach(key => { - this.metadata.addTag('exif', 'bext.' + key, bext[key]); - }); - break; - case '\x00\x00\x00\x00': // padding ?? - debug(`Ignore padding chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`); - this.metadata.addWarning('Ignore chunk: RIFF/' + header.chunkID); - await this.tokenizer.ignore(header.chunkSize); - break; - default: - debug(`Ignore chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`); - this.metadata.addWarning('Ignore chunk: RIFF/' + header.chunkID); - await this.tokenizer.ignore(header.chunkSize); - } - if (this.header.chunkSize % 2 === 1) { - debug('Read odd padding byte'); // https://wiki.multimedia.cx/index.php/RIFF - await this.tokenizer.ignore(1); - } - } - } - async parseListTag(listHeader) { - const listType = await this.tokenizer.readToken(new Token.StringType(4, 'binary')); - debug('pos=%s, parseListTag: chunkID=RIFF/WAVE/LIST/%s', this.tokenizer.position, listType); - switch (listType) { - case 'INFO': - return this.parseRiffInfoTags(listHeader.chunkSize - 4); - case 'adtl': - default: - this.metadata.addWarning('Ignore chunk: RIFF/WAVE/LIST/' + listType); - debug('Ignoring chunkID=RIFF/WAVE/LIST/' + listType); - return this.tokenizer.ignore(listHeader.chunkSize - 4).then(); - } - } - async parseRiffInfoTags(chunkSize) { - while (chunkSize >= 8) { - const header = await this.tokenizer.readToken(riff.Header); - const valueToken = new riff.ListInfoTagValue(header); - const value = await this.tokenizer.readToken(valueToken); - this.addTag(header.chunkID, util.stripNulls(value)); - chunkSize -= (8 + valueToken.len); - } - if (chunkSize !== 0) { - throw Error('Illegal remaining size: ' + chunkSize); - } - } - addTag(id, value) { - this.metadata.addTag('exif', id, value); - } -} -exports.WaveParser = WaveParser; - - -/***/ }), - -/***/ 5870: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.WavPackParser = void 0; -const Token = __webpack_require__(3416); -const APEv2Parser_1 = __webpack_require__(6742); -const FourCC_1 = __webpack_require__(8049); -const BasicParser_1 = __webpack_require__(7805); -const WavPackToken_1 = __webpack_require__(2989); -const debug_1 = __webpack_require__(1227); -const debug = (0, debug_1.default)('music-metadata:parser:WavPack'); -/** - * WavPack Parser - */ -class WavPackParser extends BasicParser_1.BasicParser { - async parse() { - this.audioDataSize = 0; - // First parse all WavPack blocks - await this.parseWavPackBlocks(); - // try to parse APEv2 header - return APEv2Parser_1.APEv2Parser.tryParseApeHeader(this.metadata, this.tokenizer, this.options); - } - async parseWavPackBlocks() { - do { - const blockId = await this.tokenizer.peekToken(FourCC_1.FourCcToken); - if (blockId !== 'wvpk') - break; - const header = await this.tokenizer.readToken(WavPackToken_1.WavPack.BlockHeaderToken); - if (header.BlockID !== 'wvpk') - throw new Error('Invalid WavPack Block-ID'); - debug(`WavPack header blockIndex=${header.blockIndex}, len=${WavPackToken_1.WavPack.BlockHeaderToken.len}`); - if (header.blockIndex === 0 && !this.metadata.format.container) { - this.metadata.setFormat('container', 'WavPack'); - this.metadata.setFormat('lossless', !header.flags.isHybrid); - // tagTypes: this.type, - this.metadata.setFormat('bitsPerSample', header.flags.bitsPerSample); - if (!header.flags.isDSD) { - // In case isDSD, these values will ne set in ID_DSD_BLOCK - this.metadata.setFormat('sampleRate', header.flags.samplingRate); - this.metadata.setFormat('duration', header.totalSamples / header.flags.samplingRate); - } - this.metadata.setFormat('numberOfChannels', header.flags.isMono ? 1 : 2); - this.metadata.setFormat('numberOfSamples', header.totalSamples); - this.metadata.setFormat('codec', header.flags.isDSD ? 'DSD' : 'PCM'); - } - const ignoreBytes = header.blockSize - (WavPackToken_1.WavPack.BlockHeaderToken.len - 8); - await (header.blockIndex === 0 ? this.parseMetadataSubBlock(header, ignoreBytes) : this.tokenizer.ignore(ignoreBytes)); - if (header.blockSamples > 0) { - this.audioDataSize += header.blockSize; // Count audio data for bit-rate calculation - } - } while (!this.tokenizer.fileInfo.size || this.tokenizer.fileInfo.size - this.tokenizer.position >= WavPackToken_1.WavPack.BlockHeaderToken.len); - this.metadata.setFormat('bitrate', this.audioDataSize * 8 / this.metadata.format.duration); - } - /** - * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf, 3.0 Metadata Sub-blocks - * @param remainingLength - */ - async parseMetadataSubBlock(header, remainingLength) { - while (remainingLength > WavPackToken_1.WavPack.MetadataIdToken.len) { - const id = await this.tokenizer.readToken(WavPackToken_1.WavPack.MetadataIdToken); - const dataSizeInWords = await this.tokenizer.readNumber(id.largeBlock ? Token.UINT24_LE : Token.UINT8); - const data = Buffer.alloc(dataSizeInWords * 2 - (id.isOddSize ? 1 : 0)); - await this.tokenizer.readBuffer(data); - debug(`Metadata Sub-Blocks functionId=0x${id.functionId.toString(16)}, id.largeBlock=${id.largeBlock},data-size=${data.length}`); - switch (id.functionId) { - case 0x0: // ID_DUMMY: could be used to pad WavPack blocks - break; - case 0xe: // ID_DSD_BLOCK - debug('ID_DSD_BLOCK'); - // https://github.com/dbry/WavPack/issues/71#issuecomment-483094813 - const mp = 1 << data.readUInt8(0); - const samplingRate = header.flags.samplingRate * mp * 8; // ToDo: second factor should be read from DSD-metadata block https://github.com/dbry/WavPack/issues/71#issuecomment-483094813 - if (!header.flags.isDSD) - throw new Error('Only expect DSD block if DSD-flag is set'); - this.metadata.setFormat('sampleRate', samplingRate); - this.metadata.setFormat('duration', header.totalSamples / samplingRate); - break; - case 0x24: // ID_ALT_TRAILER: maybe used to embed original ID3 tag header - debug('ID_ALT_TRAILER: trailer for non-wav files'); - break; - case 0x26: // ID_MD5_CHECKSUM - this.metadata.setFormat('audioMD5', data); - break; - case 0x2f: // ID_BLOCK_CHECKSUM - debug(`ID_BLOCK_CHECKSUM: checksum=${data.toString('hex')}`); - break; - default: - debug(`Ignore unsupported meta-sub-block-id functionId=0x${id.functionId.toString(16)}`); - break; - } - remainingLength -= WavPackToken_1.WavPack.MetadataIdToken.len + (id.largeBlock ? Token.UINT24_LE.len : Token.UINT8.len) + dataSizeInWords * 2; - debug(`remainingLength=${remainingLength}`); - if (id.isOddSize) - this.tokenizer.ignore(1); - } - if (remainingLength !== 0) - throw new Error('metadata-sub-block should fit it remaining length'); - } -} -exports.WavPackParser = WavPackParser; - - -/***/ }), - -/***/ 2989: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.WavPack = void 0; -const Token = __webpack_require__(3416); -const FourCC_1 = __webpack_require__(8049); -const SampleRates = [6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, 32000, 44100, - 48000, 64000, 88200, 96000, 192000, -1]; -class WavPack { - static isBitSet(flags, bitOffset) { - return WavPack.getBitAllignedNumber(flags, bitOffset, 1) === 1; - } - static getBitAllignedNumber(flags, bitOffset, len) { - return (flags >>> bitOffset) & (0xffffffff >>> (32 - len)); - } -} -exports.WavPack = WavPack; -/** - * WavPack Block Header - * - * 32-byte little-endian header at the front of every WavPack block - * - * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf (page 2/6: 2.0 "Block Header") - */ -WavPack.BlockHeaderToken = { - len: 32, - get: (buf, off) => { - const flags = Token.UINT32_LE.get(buf, off + 24); - const res = { - // should equal 'wvpk' - BlockID: FourCC_1.FourCcToken.get(buf, off), - // 0x402 to 0x410 are valid for decode - blockSize: Token.UINT32_LE.get(buf, off + 4), - // 0x402 (1026) to 0x410 are valid for decode - version: Token.UINT16_LE.get(buf, off + 8), - // 40-bit total samples for entire file (if block_index == 0 and a value of -1 indicates an unknown length) - totalSamples: /* replace with bigint? (Token.UINT8.get(buf, off + 11) << 32) + */ Token.UINT32_LE.get(buf, off + 12), - // 40-bit block_index - blockIndex: /* replace with bigint? (Token.UINT8.get(buf, off + 10) << 32) + */ Token.UINT32_LE.get(buf, off + 16), - // 40-bit total samples for entire file (if block_index == 0 and a value of -1 indicates an unknown length) - blockSamples: Token.UINT32_LE.get(buf, off + 20), - // various flags for id and decoding - flags: { - bitsPerSample: (1 + WavPack.getBitAllignedNumber(flags, 0, 2)) * 8, - isMono: WavPack.isBitSet(flags, 2), - isHybrid: WavPack.isBitSet(flags, 3), - isJointStereo: WavPack.isBitSet(flags, 4), - crossChannel: WavPack.isBitSet(flags, 5), - hybridNoiseShaping: WavPack.isBitSet(flags, 6), - floatingPoint: WavPack.isBitSet(flags, 7), - samplingRate: SampleRates[WavPack.getBitAllignedNumber(flags, 23, 4)], - isDSD: WavPack.isBitSet(flags, 31) - }, - // crc for actual decoded data - crc: new Token.Uint8ArrayType(4).get(buf, off + 28) - }; - if (res.flags.isDSD) { - res.totalSamples *= 8; - } - return res; - } -}; -/** - * 3.0 Metadata Sub-Blocks - * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf (page 4/6: 3.0 "Metadata Sub-Block") - */ -WavPack.MetadataIdToken = { - len: 1, - get: (buf, off) => { - return { - functionId: WavPack.getBitAllignedNumber(buf[off], 0, 6), - isOptional: WavPack.isBitSet(buf[off], 5), - isOddSize: WavPack.isBitSet(buf[off], 6), - largeBlock: WavPack.isBitSet(buf[off], 7) - }; - } -}; - - -/***/ }), - -/***/ 8985: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.Deferred = void 0; -class Deferred { - constructor() { - this.resolve = () => null; - this.reject = () => null; - this.promise = new Promise((resolve, reject) => { - this.reject = reject; - this.resolve = resolve; - }); - } -} -exports.Deferred = Deferred; - - -/***/ }), - -/***/ 7279: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.EndOfStreamError = exports.defaultMessages = void 0; -exports.defaultMessages = 'End-Of-Stream'; -/** - * Thrown on read operation of the end of file or stream has been reached - */ -class EndOfStreamError extends Error { - constructor() { - super(exports.defaultMessages); - } -} -exports.EndOfStreamError = EndOfStreamError; - - -/***/ }), - -/***/ 6654: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.StreamReader = exports.EndOfStreamError = void 0; -const EndOfFileStream_1 = __webpack_require__(7279); -const Deferred_1 = __webpack_require__(8985); -var EndOfFileStream_2 = __webpack_require__(7279); -Object.defineProperty(exports, "EndOfStreamError", ({ enumerable: true, get: function () { return EndOfFileStream_2.EndOfStreamError; } })); -const maxStreamReadSize = 1 * 1024 * 1024; // Maximum request length on read-stream operation -class StreamReader { - constructor(s) { - this.s = s; - /** - * Deferred used for postponed read request (as not data is yet available to read) - */ - this.deferred = null; - this.endOfStream = false; - /** - * Store peeked data - * @type {Array} - */ - this.peekQueue = []; - if (!s.read || !s.once) { - throw new Error('Expected an instance of stream.Readable'); - } - this.s.once('end', () => this.reject(new EndOfFileStream_1.EndOfStreamError())); - this.s.once('error', err => this.reject(err)); - this.s.once('close', () => this.reject(new Error('Stream closed'))); - } - /** - * Read ahead (peek) from stream. Subsequent read or peeks will return the same data - * @param uint8Array - Uint8Array (or Buffer) to store data read from stream in - * @param offset - Offset target - * @param length - Number of bytes to read - * @returns Number of bytes peeked - */ - async peek(uint8Array, offset, length) { - const bytesRead = await this.read(uint8Array, offset, length); - this.peekQueue.push(uint8Array.subarray(offset, offset + bytesRead)); // Put read data back to peek buffer - return bytesRead; - } - /** - * Read chunk from stream - * @param buffer - Target Uint8Array (or Buffer) to store data read from stream in - * @param offset - Offset target - * @param length - Number of bytes to read - * @returns Number of bytes read - */ - async read(buffer, offset, length) { - if (length === 0) { - return 0; - } - if (this.peekQueue.length === 0 && this.endOfStream) { - throw new EndOfFileStream_1.EndOfStreamError(); - } - let remaining = length; - let bytesRead = 0; - // consume peeked data first - while (this.peekQueue.length > 0 && remaining > 0) { - const peekData = this.peekQueue.pop(); // Front of queue - if (!peekData) - throw new Error('peekData should be defined'); - const lenCopy = Math.min(peekData.length, remaining); - buffer.set(peekData.subarray(0, lenCopy), offset + bytesRead); - bytesRead += lenCopy; - remaining -= lenCopy; - if (lenCopy < peekData.length) { - // remainder back to queue - this.peekQueue.push(peekData.subarray(lenCopy)); - } - } - // continue reading from stream if required - while (remaining > 0 && !this.endOfStream) { - const reqLen = Math.min(remaining, maxStreamReadSize); - const chunkLen = await this.readFromStream(buffer, offset + bytesRead, reqLen); - bytesRead += chunkLen; - if (chunkLen < reqLen) - break; - remaining -= chunkLen; - } - return bytesRead; - } - /** - * Read chunk from stream - * @param buffer Target Uint8Array (or Buffer) to store data read from stream in - * @param offset Offset target - * @param length Number of bytes to read - * @returns Number of bytes read - */ - async readFromStream(buffer, offset, length) { - const readBuffer = this.s.read(length); - if (readBuffer) { - buffer.set(readBuffer, offset); - return readBuffer.length; - } - else { - const request = { - buffer, - offset, - length, - deferred: new Deferred_1.Deferred() - }; - this.deferred = request.deferred; - this.s.once('readable', () => { - this.readDeferred(request); - }); - return request.deferred.promise; - } - } - /** - * Process deferred read request - * @param request Deferred read request - */ - readDeferred(request) { - const readBuffer = this.s.read(request.length); - if (readBuffer) { - request.buffer.set(readBuffer, request.offset); - request.deferred.resolve(readBuffer.length); - this.deferred = null; - } - else { - this.s.once('readable', () => { - this.readDeferred(request); - }); - } - } - reject(err) { - this.endOfStream = true; - if (this.deferred) { - this.deferred.reject(err); - this.deferred = null; - } - } -} -exports.StreamReader = StreamReader; - - -/***/ }), - -/***/ 5167: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.StreamReader = exports.EndOfStreamError = void 0; -var EndOfFileStream_1 = __webpack_require__(7279); -Object.defineProperty(exports, "EndOfStreamError", ({ enumerable: true, get: function () { return EndOfFileStream_1.EndOfStreamError; } })); -var StreamReader_1 = __webpack_require__(6654); -Object.defineProperty(exports, "StreamReader", ({ enumerable: true, get: function () { return StreamReader_1.StreamReader; } })); - - -/***/ }), - -/***/ 4155: -/***/ ((module) => { - -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } - - -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } - - - -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - - -/***/ }), - -/***/ 4281: -/***/ ((module) => { - -"use strict"; - - -function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } - -var codes = {}; - -function createErrorType(code, message, Base) { - if (!Base) { - Base = Error; - } - - function getMessage(arg1, arg2, arg3) { - if (typeof message === 'string') { - return message; - } else { - return message(arg1, arg2, arg3); - } - } - - var NodeError = - /*#__PURE__*/ - function (_Base) { - _inheritsLoose(NodeError, _Base); - - function NodeError(arg1, arg2, arg3) { - return _Base.call(this, getMessage(arg1, arg2, arg3)) || this; - } - - return NodeError; - }(Base); - - NodeError.prototype.name = Base.name; - NodeError.prototype.code = code; - codes[code] = NodeError; -} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js - - -function oneOf(expected, thing) { - if (Array.isArray(expected)) { - var len = expected.length; - expected = expected.map(function (i) { - return String(i); - }); - - if (len > 2) { - return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1]; - } else if (len === 2) { - return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]); - } else { - return "of ".concat(thing, " ").concat(expected[0]); - } - } else { - return "of ".concat(thing, " ").concat(String(expected)); - } -} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith - - -function startsWith(str, search, pos) { - return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; -} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith - - -function endsWith(str, search, this_len) { - if (this_len === undefined || this_len > str.length) { - this_len = str.length; - } - - return str.substring(this_len - search.length, this_len) === search; -} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes - - -function includes(str, search, start) { - if (typeof start !== 'number') { - start = 0; - } - - if (start + search.length > str.length) { - return false; - } else { - return str.indexOf(search, start) !== -1; - } -} - -createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { - return 'The value "' + value + '" is invalid for option "' + name + '"'; -}, TypeError); -createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { - // determiner: 'must be' or 'must not be' - var determiner; - - if (typeof expected === 'string' && startsWith(expected, 'not ')) { - determiner = 'must not be'; - expected = expected.replace(/^not /, ''); - } else { - determiner = 'must be'; - } - - var msg; - - if (endsWith(name, ' argument')) { - // For cases like 'first argument' - msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); - } else { - var type = includes(name, '.') ? 'property' : 'argument'; - msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type')); - } - - msg += ". Received type ".concat(typeof actual); - return msg; -}, TypeError); -createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); -createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { - return 'The ' + name + ' method is not implemented'; -}); -createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); -createErrorType('ERR_STREAM_DESTROYED', function (name) { - return 'Cannot call ' + name + ' after a stream was destroyed'; -}); -createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); -createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); -createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); -createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); -createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { - return 'Unknown encoding: ' + arg; -}, TypeError); -createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); -module.exports.q = codes; - - -/***/ }), - -/***/ 6753: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var process = __webpack_require__(4155); -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// a duplex stream is just a stream that is both readable and writable. -// Since JS doesn't have multiple prototypal inheritance, this class -// prototypally inherits from Readable, and then parasitically from -// Writable. - -/**/ - -var objectKeys = Object.keys || function (obj) { - var keys = []; - - for (var key in obj) { - keys.push(key); - } - - return keys; -}; -/**/ - - -module.exports = Duplex; - -var Readable = __webpack_require__(9481); - -var Writable = __webpack_require__(4229); - -__webpack_require__(5717)(Duplex, Readable); - -{ - // Allow the keys array to be GC'ed. - var keys = objectKeys(Writable.prototype); - - for (var v = 0; v < keys.length; v++) { - var method = keys[v]; - if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; - } -} - -function Duplex(options) { - if (!(this instanceof Duplex)) return new Duplex(options); - Readable.call(this, options); - Writable.call(this, options); - this.allowHalfOpen = true; - - if (options) { - if (options.readable === false) this.readable = false; - if (options.writable === false) this.writable = false; - - if (options.allowHalfOpen === false) { - this.allowHalfOpen = false; - this.once('end', onend); - } - } -} - -Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.highWaterMark; - } -}); -Object.defineProperty(Duplex.prototype, 'writableBuffer', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState && this._writableState.getBuffer(); - } -}); -Object.defineProperty(Duplex.prototype, 'writableLength', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.length; - } -}); // the no-half-open enforcer - -function onend() { - // If the writable side ended, then we're ok. - if (this._writableState.ended) return; // no more data can be written. - // But allow more writes to happen in this tick. - - process.nextTick(onEndNT, this); -} - -function onEndNT(self) { - self.end(); -} - -Object.defineProperty(Duplex.prototype, 'destroyed', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - if (this._readableState === undefined || this._writableState === undefined) { - return false; - } - - return this._readableState.destroyed && this._writableState.destroyed; - }, - set: function set(value) { - // we ignore the value if the stream - // has not been initialized yet - if (this._readableState === undefined || this._writableState === undefined) { - return; - } // backward compatibility, the user is explicitly - // managing destroyed - - - this._readableState.destroyed = value; - this._writableState.destroyed = value; - } -}); - -/***/ }), - -/***/ 2725: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// a passthrough stream. -// basically just the most minimal sort of Transform stream. -// Every written chunk gets output as-is. - - -module.exports = PassThrough; - -var Transform = __webpack_require__(4605); - -__webpack_require__(5717)(PassThrough, Transform); - -function PassThrough(options) { - if (!(this instanceof PassThrough)) return new PassThrough(options); - Transform.call(this, options); -} - -PassThrough.prototype._transform = function (chunk, encoding, cb) { - cb(null, chunk); -}; - -/***/ }), - -/***/ 9481: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var process = __webpack_require__(4155); -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - -module.exports = Readable; -/**/ - -var Duplex; -/**/ - -Readable.ReadableState = ReadableState; -/**/ - -var EE = (__webpack_require__(7187).EventEmitter); - -var EElistenerCount = function EElistenerCount(emitter, type) { - return emitter.listeners(type).length; -}; -/**/ - -/**/ - - -var Stream = __webpack_require__(2503); -/**/ - - -var Buffer = (__webpack_require__(8764).Buffer); - -var OurUint8Array = __webpack_require__.g.Uint8Array || function () {}; - -function _uint8ArrayToBuffer(chunk) { - return Buffer.from(chunk); -} - -function _isUint8Array(obj) { - return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; -} -/**/ - - -var debugUtil = __webpack_require__(4616); - -var debug; - -if (debugUtil && debugUtil.debuglog) { - debug = debugUtil.debuglog('stream'); -} else { - debug = function debug() {}; -} -/**/ - - -var BufferList = __webpack_require__(7327); - -var destroyImpl = __webpack_require__(1195); - -var _require = __webpack_require__(2457), - getHighWaterMark = _require.getHighWaterMark; - -var _require$codes = (__webpack_require__(4281)/* .codes */ .q), - ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, - ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF, - ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, - ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; // Lazy loaded to improve the startup performance. - - -var StringDecoder; -var createReadableStreamAsyncIterator; -var from; - -__webpack_require__(5717)(Readable, Stream); - -var errorOrDestroy = destroyImpl.errorOrDestroy; -var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; - -function prependListener(emitter, event, fn) { - // Sadly this is not cacheable as some libraries bundle their own - // event emitter implementation with them. - if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); // This is a hack to make sure that our error handler is attached before any - // userland ones. NEVER DO THIS. This is here only because this code needs - // to continue to work with older versions of Node.js that do not include - // the prependListener() method. The goal is to eventually remove this hack. - - if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; -} - -function ReadableState(options, stream, isDuplex) { - Duplex = Duplex || __webpack_require__(6753); - options = options || {}; // Duplex streams are both readable and writable, but share - // the same options object. - // However, some cases require setting options to different - // values for the readable and the writable sides of the duplex stream. - // These options can be provided separately as readableXXX and writableXXX. - - if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag. Used to make read(n) ignore n and to - // make all the buffer merging and length checks go away - - this.objectMode = !!options.objectMode; - if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; // the point at which it stops calling _read() to fill the buffer - // Note: 0 is a valid value, means "don't call _read preemptively ever" - - this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex); // A linked list is used to store data chunks instead of an array because the - // linked list can remove elements from the beginning faster than - // array.shift() - - this.buffer = new BufferList(); - this.length = 0; - this.pipes = null; - this.pipesCount = 0; - this.flowing = null; - this.ended = false; - this.endEmitted = false; - this.reading = false; // a flag to be able to tell if the event 'readable'/'data' is emitted - // immediately, or on a later tick. We set this to true at first, because - // any actions that shouldn't happen until "later" should generally also - // not happen before the first read call. - - this.sync = true; // whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. - - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - this.resumeScheduled = false; - this.paused = true; // Should close be emitted on destroy. Defaults to true. - - this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'end' (and potentially 'finish') - - this.autoDestroy = !!options.autoDestroy; // has it been destroyed - - this.destroyed = false; // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - - this.defaultEncoding = options.defaultEncoding || 'utf8'; // the number of writers that are awaiting a drain event in .pipe()s - - this.awaitDrain = 0; // if true, a maybeReadMore has been scheduled - - this.readingMore = false; - this.decoder = null; - this.encoding = null; - - if (options.encoding) { - if (!StringDecoder) StringDecoder = (__webpack_require__(2553)/* .StringDecoder */ .s); - this.decoder = new StringDecoder(options.encoding); - this.encoding = options.encoding; - } -} - -function Readable(options) { - Duplex = Duplex || __webpack_require__(6753); - if (!(this instanceof Readable)) return new Readable(options); // Checking for a Stream.Duplex instance is faster here instead of inside - // the ReadableState constructor, at least with V8 6.5 - - var isDuplex = this instanceof Duplex; - this._readableState = new ReadableState(options, this, isDuplex); // legacy - - this.readable = true; - - if (options) { - if (typeof options.read === 'function') this._read = options.read; - if (typeof options.destroy === 'function') this._destroy = options.destroy; - } - - Stream.call(this); -} - -Object.defineProperty(Readable.prototype, 'destroyed', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - if (this._readableState === undefined) { - return false; - } - - return this._readableState.destroyed; - }, - set: function set(value) { - // we ignore the value if the stream - // has not been initialized yet - if (!this._readableState) { - return; - } // backward compatibility, the user is explicitly - // managing destroyed - - - this._readableState.destroyed = value; - } -}); -Readable.prototype.destroy = destroyImpl.destroy; -Readable.prototype._undestroy = destroyImpl.undestroy; - -Readable.prototype._destroy = function (err, cb) { - cb(err); -}; // Manually shove something into the read() buffer. -// This returns true if the highWaterMark has not been hit yet, -// similar to how Writable.write() returns true if you should -// write() some more. - - -Readable.prototype.push = function (chunk, encoding) { - var state = this._readableState; - var skipChunkCheck; - - if (!state.objectMode) { - if (typeof chunk === 'string') { - encoding = encoding || state.defaultEncoding; - - if (encoding !== state.encoding) { - chunk = Buffer.from(chunk, encoding); - encoding = ''; - } - - skipChunkCheck = true; - } - } else { - skipChunkCheck = true; - } - - return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); -}; // Unshift should *always* be something directly out of read() - - -Readable.prototype.unshift = function (chunk) { - return readableAddChunk(this, chunk, null, true, false); -}; - -function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { - debug('readableAddChunk', chunk); - var state = stream._readableState; - - if (chunk === null) { - state.reading = false; - onEofChunk(stream, state); - } else { - var er; - if (!skipChunkCheck) er = chunkInvalid(state, chunk); - - if (er) { - errorOrDestroy(stream, er); - } else if (state.objectMode || chunk && chunk.length > 0) { - if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { - chunk = _uint8ArrayToBuffer(chunk); - } - - if (addToFront) { - if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true); - } else if (state.ended) { - errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); - } else if (state.destroyed) { - return false; - } else { - state.reading = false; - - if (state.decoder && !encoding) { - chunk = state.decoder.write(chunk); - if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); - } else { - addChunk(stream, state, chunk, false); - } - } - } else if (!addToFront) { - state.reading = false; - maybeReadMore(stream, state); - } - } // We can push more data if we are below the highWaterMark. - // Also, if we have no data yet, we can stand some more bytes. - // This is to work around cases where hwm=0, such as the repl. - - - return !state.ended && (state.length < state.highWaterMark || state.length === 0); -} - -function addChunk(stream, state, chunk, addToFront) { - if (state.flowing && state.length === 0 && !state.sync) { - state.awaitDrain = 0; - stream.emit('data', chunk); - } else { - // update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); - if (state.needReadable) emitReadable(stream); - } - - maybeReadMore(stream, state); -} - -function chunkInvalid(state, chunk) { - var er; - - if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { - er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); - } - - return er; -} - -Readable.prototype.isPaused = function () { - return this._readableState.flowing === false; -}; // backwards compatibility. - - -Readable.prototype.setEncoding = function (enc) { - if (!StringDecoder) StringDecoder = (__webpack_require__(2553)/* .StringDecoder */ .s); - var decoder = new StringDecoder(enc); - this._readableState.decoder = decoder; // If setEncoding(null), decoder.encoding equals utf8 - - this._readableState.encoding = this._readableState.decoder.encoding; // Iterate over current buffer to convert already stored Buffers: - - var p = this._readableState.buffer.head; - var content = ''; - - while (p !== null) { - content += decoder.write(p.data); - p = p.next; - } - - this._readableState.buffer.clear(); - - if (content !== '') this._readableState.buffer.push(content); - this._readableState.length = content.length; - return this; -}; // Don't raise the hwm > 1GB - - -var MAX_HWM = 0x40000000; - -function computeNewHighWaterMark(n) { - if (n >= MAX_HWM) { - // TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE. - n = MAX_HWM; - } else { - // Get the next highest power of 2 to prevent increasing hwm excessively in - // tiny amounts - n--; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; - n++; - } - - return n; -} // This function is designed to be inlinable, so please take care when making -// changes to the function body. - - -function howMuchToRead(n, state) { - if (n <= 0 || state.length === 0 && state.ended) return 0; - if (state.objectMode) return 1; - - if (n !== n) { - // Only flow one buffer at a time - if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; - } // If we're asking for more than the current hwm, then raise the hwm. - - - if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); - if (n <= state.length) return n; // Don't have enough - - if (!state.ended) { - state.needReadable = true; - return 0; - } - - return state.length; -} // you can override either this method, or the async _read(n) below. - - -Readable.prototype.read = function (n) { - debug('read', n); - n = parseInt(n, 10); - var state = this._readableState; - var nOrig = n; - if (n !== 0) state.emittedReadable = false; // if we're doing read(0) to trigger a readable event, but we - // already have a bunch of data in the buffer, then just trigger - // the 'readable' event and move on. - - if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { - debug('read: emitReadable', state.length, state.ended); - if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); - return null; - } - - n = howMuchToRead(n, state); // if we've ended, and we're now clear, then finish it up. - - if (n === 0 && state.ended) { - if (state.length === 0) endReadable(this); - return null; - } // All the actual chunk generation logic needs to be - // *below* the call to _read. The reason is that in certain - // synthetic stream cases, such as passthrough streams, _read - // may be a completely synchronous operation which may change - // the state of the read buffer, providing enough data when - // before there was *not* enough. - // - // So, the steps are: - // 1. Figure out what the state of things will be after we do - // a read from the buffer. - // - // 2. If that resulting state will trigger a _read, then call _read. - // Note that this may be asynchronous, or synchronous. Yes, it is - // deeply ugly to write APIs this way, but that still doesn't mean - // that the Readable class should behave improperly, as streams are - // designed to be sync/async agnostic. - // Take note if the _read call is sync or async (ie, if the read call - // has returned yet), so that we know whether or not it's safe to emit - // 'readable' etc. - // - // 3. Actually pull the requested chunks out of the buffer and return. - // if we need a readable event, then we need to do some reading. - - - var doRead = state.needReadable; - debug('need readable', doRead); // if we currently have less than the highWaterMark, then also read some - - if (state.length === 0 || state.length - n < state.highWaterMark) { - doRead = true; - debug('length less than watermark', doRead); - } // however, if we've ended, then there's no point, and if we're already - // reading, then it's unnecessary. - - - if (state.ended || state.reading) { - doRead = false; - debug('reading or ended', doRead); - } else if (doRead) { - debug('do read'); - state.reading = true; - state.sync = true; // if the length is currently zero, then we *need* a readable event. - - if (state.length === 0) state.needReadable = true; // call internal read method - - this._read(state.highWaterMark); - - state.sync = false; // If _read pushed data synchronously, then `reading` will be false, - // and we need to re-evaluate how much data we can return to the user. - - if (!state.reading) n = howMuchToRead(nOrig, state); - } - - var ret; - if (n > 0) ret = fromList(n, state);else ret = null; - - if (ret === null) { - state.needReadable = state.length <= state.highWaterMark; - n = 0; - } else { - state.length -= n; - state.awaitDrain = 0; - } - - if (state.length === 0) { - // If we have nothing in the buffer, then we want to know - // as soon as we *do* get something into the buffer. - if (!state.ended) state.needReadable = true; // If we tried to read() past the EOF, then emit end on the next tick. - - if (nOrig !== n && state.ended) endReadable(this); - } - - if (ret !== null) this.emit('data', ret); - return ret; -}; - -function onEofChunk(stream, state) { - debug('onEofChunk'); - if (state.ended) return; - - if (state.decoder) { - var chunk = state.decoder.end(); - - if (chunk && chunk.length) { - state.buffer.push(chunk); - state.length += state.objectMode ? 1 : chunk.length; - } - } - - state.ended = true; - - if (state.sync) { - // if we are sync, wait until next tick to emit the data. - // Otherwise we risk emitting data in the flow() - // the readable code triggers during a read() call - emitReadable(stream); - } else { - // emit 'readable' now to make sure it gets picked up. - state.needReadable = false; - - if (!state.emittedReadable) { - state.emittedReadable = true; - emitReadable_(stream); - } - } -} // Don't emit readable right away in sync mode, because this can trigger -// another read() call => stack overflow. This way, it might trigger -// a nextTick recursion warning, but that's not so bad. - - -function emitReadable(stream) { - var state = stream._readableState; - debug('emitReadable', state.needReadable, state.emittedReadable); - state.needReadable = false; - - if (!state.emittedReadable) { - debug('emitReadable', state.flowing); - state.emittedReadable = true; - process.nextTick(emitReadable_, stream); - } -} - -function emitReadable_(stream) { - var state = stream._readableState; - debug('emitReadable_', state.destroyed, state.length, state.ended); - - if (!state.destroyed && (state.length || state.ended)) { - stream.emit('readable'); - state.emittedReadable = false; - } // The stream needs another readable event if - // 1. It is not flowing, as the flow mechanism will take - // care of it. - // 2. It is not ended. - // 3. It is below the highWaterMark, so we can schedule - // another readable later. - - - state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; - flow(stream); -} // at this point, the user has presumably seen the 'readable' event, -// and called read() to consume some data. that may have triggered -// in turn another _read(n) call, in which case reading = true if -// it's in progress. -// However, if we're not ended, or reading, and the length < hwm, -// then go ahead and try to read some more preemptively. - - -function maybeReadMore(stream, state) { - if (!state.readingMore) { - state.readingMore = true; - process.nextTick(maybeReadMore_, stream, state); - } -} - -function maybeReadMore_(stream, state) { - // Attempt to read more data if we should. - // - // The conditions for reading more data are (one of): - // - Not enough data buffered (state.length < state.highWaterMark). The loop - // is responsible for filling the buffer with enough data if such data - // is available. If highWaterMark is 0 and we are not in the flowing mode - // we should _not_ attempt to buffer any extra data. We'll get more data - // when the stream consumer calls read() instead. - // - No data in the buffer, and the stream is in flowing mode. In this mode - // the loop below is responsible for ensuring read() is called. Failing to - // call read here would abort the flow and there's no other mechanism for - // continuing the flow if the stream consumer has just subscribed to the - // 'data' event. - // - // In addition to the above conditions to keep reading data, the following - // conditions prevent the data from being read: - // - The stream has ended (state.ended). - // - There is already a pending 'read' operation (state.reading). This is a - // case where the the stream has called the implementation defined _read() - // method, but they are processing the call asynchronously and have _not_ - // called push() with new data. In this case we skip performing more - // read()s. The execution ends in this method again after the _read() ends - // up calling push() with more data. - while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) { - var len = state.length; - debug('maybeReadMore read 0'); - stream.read(0); - if (len === state.length) // didn't get any data, stop spinning. - break; - } - - state.readingMore = false; -} // abstract method. to be overridden in specific implementation classes. -// call cb(er, data) where data is <= n in length. -// for virtual (non-string, non-buffer) streams, "length" is somewhat -// arbitrary, and perhaps not very meaningful. - - -Readable.prototype._read = function (n) { - errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()')); -}; - -Readable.prototype.pipe = function (dest, pipeOpts) { - var src = this; - var state = this._readableState; - - switch (state.pipesCount) { - case 0: - state.pipes = dest; - break; - - case 1: - state.pipes = [state.pipes, dest]; - break; - - default: - state.pipes.push(dest); - break; - } - - state.pipesCount += 1; - debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); - var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; - var endFn = doEnd ? onend : unpipe; - if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn); - dest.on('unpipe', onunpipe); - - function onunpipe(readable, unpipeInfo) { - debug('onunpipe'); - - if (readable === src) { - if (unpipeInfo && unpipeInfo.hasUnpiped === false) { - unpipeInfo.hasUnpiped = true; - cleanup(); - } - } - } - - function onend() { - debug('onend'); - dest.end(); - } // when the dest drains, it reduces the awaitDrain counter - // on the source. This would be more elegant with a .once() - // handler in flow(), but adding and removing repeatedly is - // too slow. - - - var ondrain = pipeOnDrain(src); - dest.on('drain', ondrain); - var cleanedUp = false; - - function cleanup() { - debug('cleanup'); // cleanup event handlers once the pipe is broken - - dest.removeListener('close', onclose); - dest.removeListener('finish', onfinish); - dest.removeListener('drain', ondrain); - dest.removeListener('error', onerror); - dest.removeListener('unpipe', onunpipe); - src.removeListener('end', onend); - src.removeListener('end', unpipe); - src.removeListener('data', ondata); - cleanedUp = true; // if the reader is waiting for a drain event from this - // specific writer, then it would cause it to never start - // flowing again. - // So, if this is awaiting a drain, then we just call it now. - // If we don't know, then assume that we are waiting for one. - - if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); - } - - src.on('data', ondata); - - function ondata(chunk) { - debug('ondata'); - var ret = dest.write(chunk); - debug('dest.write', ret); - - if (ret === false) { - // If the user unpiped during `dest.write()`, it is possible - // to get stuck in a permanently paused state if that write - // also returned false. - // => Check whether `dest` is still a piping destination. - if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { - debug('false write response, pause', state.awaitDrain); - state.awaitDrain++; - } - - src.pause(); - } - } // if the dest has an error, then stop piping into it. - // however, don't suppress the throwing behavior for this. - - - function onerror(er) { - debug('onerror', er); - unpipe(); - dest.removeListener('error', onerror); - if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er); - } // Make sure our error handler is attached before userland ones. - - - prependListener(dest, 'error', onerror); // Both close and finish should trigger unpipe, but only once. - - function onclose() { - dest.removeListener('finish', onfinish); - unpipe(); - } - - dest.once('close', onclose); - - function onfinish() { - debug('onfinish'); - dest.removeListener('close', onclose); - unpipe(); - } - - dest.once('finish', onfinish); - - function unpipe() { - debug('unpipe'); - src.unpipe(dest); - } // tell the dest that it's being piped to - - - dest.emit('pipe', src); // start the flow if it hasn't been started already. - - if (!state.flowing) { - debug('pipe resume'); - src.resume(); - } - - return dest; -}; - -function pipeOnDrain(src) { - return function pipeOnDrainFunctionResult() { - var state = src._readableState; - debug('pipeOnDrain', state.awaitDrain); - if (state.awaitDrain) state.awaitDrain--; - - if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { - state.flowing = true; - flow(src); - } - }; -} - -Readable.prototype.unpipe = function (dest) { - var state = this._readableState; - var unpipeInfo = { - hasUnpiped: false - }; // if we're not piping anywhere, then do nothing. - - if (state.pipesCount === 0) return this; // just one destination. most common case. - - if (state.pipesCount === 1) { - // passed in one, but it's not the right one. - if (dest && dest !== state.pipes) return this; - if (!dest) dest = state.pipes; // got a match. - - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; - if (dest) dest.emit('unpipe', this, unpipeInfo); - return this; - } // slow case. multiple pipe destinations. - - - if (!dest) { - // remove all. - var dests = state.pipes; - var len = state.pipesCount; - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; - - for (var i = 0; i < len; i++) { - dests[i].emit('unpipe', this, { - hasUnpiped: false - }); - } - - return this; - } // try to find the right one. - - - var index = indexOf(state.pipes, dest); - if (index === -1) return this; - state.pipes.splice(index, 1); - state.pipesCount -= 1; - if (state.pipesCount === 1) state.pipes = state.pipes[0]; - dest.emit('unpipe', this, unpipeInfo); - return this; -}; // set up data events if they are asked for -// Ensure readable listeners eventually get something - - -Readable.prototype.on = function (ev, fn) { - var res = Stream.prototype.on.call(this, ev, fn); - var state = this._readableState; - - if (ev === 'data') { - // update readableListening so that resume() may be a no-op - // a few lines down. This is needed to support once('readable'). - state.readableListening = this.listenerCount('readable') > 0; // Try start flowing on next tick if stream isn't explicitly paused - - if (state.flowing !== false) this.resume(); - } else if (ev === 'readable') { - if (!state.endEmitted && !state.readableListening) { - state.readableListening = state.needReadable = true; - state.flowing = false; - state.emittedReadable = false; - debug('on readable', state.length, state.reading); - - if (state.length) { - emitReadable(this); - } else if (!state.reading) { - process.nextTick(nReadingNextTick, this); - } - } - } - - return res; -}; - -Readable.prototype.addListener = Readable.prototype.on; - -Readable.prototype.removeListener = function (ev, fn) { - var res = Stream.prototype.removeListener.call(this, ev, fn); - - if (ev === 'readable') { - // We need to check if there is someone still listening to - // readable and reset the state. However this needs to happen - // after readable has been emitted but before I/O (nextTick) to - // support once('readable', fn) cycles. This means that calling - // resume within the same tick will have no - // effect. - process.nextTick(updateReadableListening, this); - } - - return res; -}; - -Readable.prototype.removeAllListeners = function (ev) { - var res = Stream.prototype.removeAllListeners.apply(this, arguments); - - if (ev === 'readable' || ev === undefined) { - // We need to check if there is someone still listening to - // readable and reset the state. However this needs to happen - // after readable has been emitted but before I/O (nextTick) to - // support once('readable', fn) cycles. This means that calling - // resume within the same tick will have no - // effect. - process.nextTick(updateReadableListening, this); - } - - return res; -}; - -function updateReadableListening(self) { - var state = self._readableState; - state.readableListening = self.listenerCount('readable') > 0; - - if (state.resumeScheduled && !state.paused) { - // flowing needs to be set to true now, otherwise - // the upcoming resume will not flow. - state.flowing = true; // crude way to check if we should resume - } else if (self.listenerCount('data') > 0) { - self.resume(); - } -} - -function nReadingNextTick(self) { - debug('readable nexttick read 0'); - self.read(0); -} // pause() and resume() are remnants of the legacy readable stream API -// If the user uses them, then switch into old mode. - - -Readable.prototype.resume = function () { - var state = this._readableState; - - if (!state.flowing) { - debug('resume'); // we flow only if there is no one listening - // for readable, but we still have to call - // resume() - - state.flowing = !state.readableListening; - resume(this, state); - } - - state.paused = false; - return this; -}; - -function resume(stream, state) { - if (!state.resumeScheduled) { - state.resumeScheduled = true; - process.nextTick(resume_, stream, state); - } -} - -function resume_(stream, state) { - debug('resume', state.reading); - - if (!state.reading) { - stream.read(0); - } - - state.resumeScheduled = false; - stream.emit('resume'); - flow(stream); - if (state.flowing && !state.reading) stream.read(0); -} - -Readable.prototype.pause = function () { - debug('call pause flowing=%j', this._readableState.flowing); - - if (this._readableState.flowing !== false) { - debug('pause'); - this._readableState.flowing = false; - this.emit('pause'); - } - - this._readableState.paused = true; - return this; -}; - -function flow(stream) { - var state = stream._readableState; - debug('flow', state.flowing); - - while (state.flowing && stream.read() !== null) { - ; - } -} // wrap an old-style stream as the async data source. -// This is *not* part of the readable stream interface. -// It is an ugly unfortunate mess of history. - - -Readable.prototype.wrap = function (stream) { - var _this = this; - - var state = this._readableState; - var paused = false; - stream.on('end', function () { - debug('wrapped end'); - - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) _this.push(chunk); - } - - _this.push(null); - }); - stream.on('data', function (chunk) { - debug('wrapped data'); - if (state.decoder) chunk = state.decoder.write(chunk); // don't skip over falsy values in objectMode - - if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; - - var ret = _this.push(chunk); - - if (!ret) { - paused = true; - stream.pause(); - } - }); // proxy all the other methods. - // important when wrapping filters and duplexes. - - for (var i in stream) { - if (this[i] === undefined && typeof stream[i] === 'function') { - this[i] = function methodWrap(method) { - return function methodWrapReturnFunction() { - return stream[method].apply(stream, arguments); - }; - }(i); - } - } // proxy certain important events. - - - for (var n = 0; n < kProxyEvents.length; n++) { - stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); - } // when we try to consume some more bytes, simply unpause the - // underlying stream. - - - this._read = function (n) { - debug('wrapped _read', n); - - if (paused) { - paused = false; - stream.resume(); - } - }; - - return this; -}; - -if (typeof Symbol === 'function') { - Readable.prototype[Symbol.asyncIterator] = function () { - if (createReadableStreamAsyncIterator === undefined) { - createReadableStreamAsyncIterator = __webpack_require__(5850); - } - - return createReadableStreamAsyncIterator(this); - }; -} - -Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState.highWaterMark; - } -}); -Object.defineProperty(Readable.prototype, 'readableBuffer', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState && this._readableState.buffer; - } -}); -Object.defineProperty(Readable.prototype, 'readableFlowing', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState.flowing; - }, - set: function set(state) { - if (this._readableState) { - this._readableState.flowing = state; - } - } -}); // exposed for testing purposes only. - -Readable._fromList = fromList; -Object.defineProperty(Readable.prototype, 'readableLength', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._readableState.length; - } -}); // Pluck off n bytes from an array of buffers. -// Length is the combined lengths of all the buffers in the list. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. - -function fromList(n, state) { - // nothing buffered - if (state.length === 0) return null; - var ret; - if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { - // read it all, truncate the list - if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length); - state.buffer.clear(); - } else { - // read part of list - ret = state.buffer.consume(n, state.decoder); - } - return ret; -} - -function endReadable(stream) { - var state = stream._readableState; - debug('endReadable', state.endEmitted); - - if (!state.endEmitted) { - state.ended = true; - process.nextTick(endReadableNT, state, stream); - } -} - -function endReadableNT(state, stream) { - debug('endReadableNT', state.endEmitted, state.length); // Check that we didn't get one last unshift. - - if (!state.endEmitted && state.length === 0) { - state.endEmitted = true; - stream.readable = false; - stream.emit('end'); - - if (state.autoDestroy) { - // In case of duplex streams we need a way to detect - // if the writable side is ready for autoDestroy as well - var wState = stream._writableState; - - if (!wState || wState.autoDestroy && wState.finished) { - stream.destroy(); - } - } - } -} - -if (typeof Symbol === 'function') { - Readable.from = function (iterable, opts) { - if (from === undefined) { - from = __webpack_require__(889); - } - - return from(Readable, iterable, opts); - }; -} - -function indexOf(xs, x) { - for (var i = 0, l = xs.length; i < l; i++) { - if (xs[i] === x) return i; - } - - return -1; -} - -/***/ }), - -/***/ 4605: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// a transform stream is a readable/writable stream where you do -// something with the data. Sometimes it's called a "filter", -// but that's not a great name for it, since that implies a thing where -// some bits pass through, and others are simply ignored. (That would -// be a valid example of a transform, of course.) -// -// While the output is causally related to the input, it's not a -// necessarily symmetric or synchronous transformation. For example, -// a zlib stream might take multiple plain-text writes(), and then -// emit a single compressed chunk some time in the future. -// -// Here's how this works: -// -// The Transform stream has all the aspects of the readable and writable -// stream classes. When you write(chunk), that calls _write(chunk,cb) -// internally, and returns false if there's a lot of pending writes -// buffered up. When you call read(), that calls _read(n) until -// there's enough pending readable data buffered up. -// -// In a transform stream, the written data is placed in a buffer. When -// _read(n) is called, it transforms the queued up data, calling the -// buffered _write cb's as it consumes chunks. If consuming a single -// written chunk would result in multiple output chunks, then the first -// outputted bit calls the readcb, and subsequent chunks just go into -// the read buffer, and will cause it to emit 'readable' if necessary. -// -// This way, back-pressure is actually determined by the reading side, -// since _read has to be called to start processing a new chunk. However, -// a pathological inflate type of transform can cause excessive buffering -// here. For example, imagine a stream where every byte of input is -// interpreted as an integer from 0-255, and then results in that many -// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in -// 1kb of data being output. In this case, you could write a very small -// amount of input, and end up with a very large amount of output. In -// such a pathological inflating mechanism, there'd be no way to tell -// the system to stop doing the transform. A single 4MB write could -// cause the system to run out of memory. -// -// However, even in such a pathological case, only a single written chunk -// would be consumed, and then the rest would wait (un-transformed) until -// the results of the previous transformed chunk were consumed. - - -module.exports = Transform; - -var _require$codes = (__webpack_require__(4281)/* .codes */ .q), - ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, - ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, - ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING, - ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0; - -var Duplex = __webpack_require__(6753); - -__webpack_require__(5717)(Transform, Duplex); - -function afterTransform(er, data) { - var ts = this._transformState; - ts.transforming = false; - var cb = ts.writecb; - - if (cb === null) { - return this.emit('error', new ERR_MULTIPLE_CALLBACK()); - } - - ts.writechunk = null; - ts.writecb = null; - if (data != null) // single equals check for both `null` and `undefined` - this.push(data); - cb(er); - var rs = this._readableState; - rs.reading = false; - - if (rs.needReadable || rs.length < rs.highWaterMark) { - this._read(rs.highWaterMark); - } -} - -function Transform(options) { - if (!(this instanceof Transform)) return new Transform(options); - Duplex.call(this, options); - this._transformState = { - afterTransform: afterTransform.bind(this), - needTransform: false, - transforming: false, - writecb: null, - writechunk: null, - writeencoding: null - }; // start out asking for a readable event once data is transformed. - - this._readableState.needReadable = true; // we have implemented the _read method, and done the other things - // that Readable wants before the first _read call, so unset the - // sync guard flag. - - this._readableState.sync = false; - - if (options) { - if (typeof options.transform === 'function') this._transform = options.transform; - if (typeof options.flush === 'function') this._flush = options.flush; - } // When the writable side finishes, then flush out anything remaining. - - - this.on('prefinish', prefinish); -} - -function prefinish() { - var _this = this; - - if (typeof this._flush === 'function' && !this._readableState.destroyed) { - this._flush(function (er, data) { - done(_this, er, data); - }); - } else { - done(this, null, null); - } -} - -Transform.prototype.push = function (chunk, encoding) { - this._transformState.needTransform = false; - return Duplex.prototype.push.call(this, chunk, encoding); -}; // This is the part where you do stuff! -// override this function in implementation classes. -// 'chunk' is an input chunk. -// -// Call `push(newChunk)` to pass along transformed output -// to the readable side. You may call 'push' zero or more times. -// -// Call `cb(err)` when you are done with this chunk. If you pass -// an error, then that'll put the hurt on the whole operation. If you -// never call cb(), then you'll never get another chunk. - - -Transform.prototype._transform = function (chunk, encoding, cb) { - cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()')); -}; - -Transform.prototype._write = function (chunk, encoding, cb) { - var ts = this._transformState; - ts.writecb = cb; - ts.writechunk = chunk; - ts.writeencoding = encoding; - - if (!ts.transforming) { - var rs = this._readableState; - if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); - } -}; // Doesn't matter what the args are here. -// _transform does all the work. -// That we got here means that the readable side wants more data. - - -Transform.prototype._read = function (n) { - var ts = this._transformState; - - if (ts.writechunk !== null && !ts.transforming) { - ts.transforming = true; - - this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); - } else { - // mark that we need a transform, so that any data that comes in - // will get processed, now that we've asked for it. - ts.needTransform = true; - } -}; - -Transform.prototype._destroy = function (err, cb) { - Duplex.prototype._destroy.call(this, err, function (err2) { - cb(err2); - }); -}; - -function done(stream, er, data) { - if (er) return stream.emit('error', er); - if (data != null) // single equals check for both `null` and `undefined` - stream.push(data); // TODO(BridgeAR): Write a test for these two error cases - // if there's nothing in the write buffer, then that means - // that nothing more will ever be provided - - if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0(); - if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); - return stream.push(null); -} - -/***/ }), - -/***/ 4229: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var process = __webpack_require__(4155); -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. -// A bit simpler than readable streams. -// Implement an async ._write(chunk, encoding, cb), and it'll handle all -// the drain event emission and buffering. - - -module.exports = Writable; -/* */ - -function WriteReq(chunk, encoding, cb) { - this.chunk = chunk; - this.encoding = encoding; - this.callback = cb; - this.next = null; -} // It seems a linked list but it is not -// there will be only 2 of these for each stream - - -function CorkedRequest(state) { - var _this = this; - - this.next = null; - this.entry = null; - - this.finish = function () { - onCorkedFinish(_this, state); - }; -} -/* */ - -/**/ - - -var Duplex; -/**/ - -Writable.WritableState = WritableState; -/**/ - -var internalUtil = { - deprecate: __webpack_require__(4927) -}; -/**/ - -/**/ - -var Stream = __webpack_require__(2503); -/**/ - - -var Buffer = (__webpack_require__(8764).Buffer); - -var OurUint8Array = __webpack_require__.g.Uint8Array || function () {}; - -function _uint8ArrayToBuffer(chunk) { - return Buffer.from(chunk); -} - -function _isUint8Array(obj) { - return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; -} - -var destroyImpl = __webpack_require__(1195); - -var _require = __webpack_require__(2457), - getHighWaterMark = _require.getHighWaterMark; - -var _require$codes = (__webpack_require__(4281)/* .codes */ .q), - ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, - ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, - ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, - ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE, - ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED, - ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES, - ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END, - ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING; - -var errorOrDestroy = destroyImpl.errorOrDestroy; - -__webpack_require__(5717)(Writable, Stream); - -function nop() {} - -function WritableState(options, stream, isDuplex) { - Duplex = Duplex || __webpack_require__(6753); - options = options || {}; // Duplex streams are both readable and writable, but share - // the same options object. - // However, some cases require setting options to different - // values for the readable and the writable sides of the duplex stream, - // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. - - if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag to indicate whether or not this stream - // contains buffers or objects. - - this.objectMode = !!options.objectMode; - if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write() - - this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); // if _final has been called - - this.finalCalled = false; // drain event flag. - - this.needDrain = false; // at the start of calling end() - - this.ending = false; // when end() has been called, and returned - - this.ended = false; // when 'finish' is emitted - - this.finished = false; // has it been destroyed - - this.destroyed = false; // should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. - - var noDecode = options.decodeStrings === false; - this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - - this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. - - this.length = 0; // a flag to see when we're in the middle of a write. - - this.writing = false; // when true all writes will be buffered until .uncork() call - - this.corked = 0; // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - - this.sync = true; // a flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. - - this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb) - - this.onwrite = function (er) { - onwrite(stream, er); - }; // the callback that the user supplies to write(chunk,encoding,cb) - - - this.writecb = null; // the amount that is being written when _write is called. - - this.writelen = 0; - this.bufferedRequest = null; - this.lastBufferedRequest = null; // number of pending user-supplied write callbacks - // this must be 0 before 'finish' can be emitted - - this.pendingcb = 0; // emit prefinish if the only thing we're waiting for is _write cbs - // This is relevant for synchronous Transform streams - - this.prefinished = false; // True if the error was already emitted and should not be thrown again - - this.errorEmitted = false; // Should close be emitted on destroy. Defaults to true. - - this.emitClose = options.emitClose !== false; // Should .destroy() be called after 'finish' (and potentially 'end') - - this.autoDestroy = !!options.autoDestroy; // count buffered requests - - this.bufferedRequestCount = 0; // allocate the first CorkedRequest, there is always - // one allocated and free to use, and we maintain at most two - - this.corkedRequestsFree = new CorkedRequest(this); -} - -WritableState.prototype.getBuffer = function getBuffer() { - var current = this.bufferedRequest; - var out = []; - - while (current) { - out.push(current); - current = current.next; - } - - return out; -}; - -(function () { - try { - Object.defineProperty(WritableState.prototype, 'buffer', { - get: internalUtil.deprecate(function writableStateBufferGetter() { - return this.getBuffer(); - }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') - }); - } catch (_) {} -})(); // Test _writableState for inheritance to account for Duplex streams, -// whose prototype chain only points to Readable. - - -var realHasInstance; - -if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { - realHasInstance = Function.prototype[Symbol.hasInstance]; - Object.defineProperty(Writable, Symbol.hasInstance, { - value: function value(object) { - if (realHasInstance.call(this, object)) return true; - if (this !== Writable) return false; - return object && object._writableState instanceof WritableState; - } - }); -} else { - realHasInstance = function realHasInstance(object) { - return object instanceof this; - }; -} - -function Writable(options) { - Duplex = Duplex || __webpack_require__(6753); // Writable ctor is applied to Duplexes, too. - // `realHasInstance` is necessary because using plain `instanceof` - // would return false, as no `_writableState` property is attached. - // Trying to use the custom `instanceof` for Writable here will also break the - // Node.js LazyTransform implementation, which has a non-trivial getter for - // `_writableState` that would lead to infinite recursion. - // Checking for a Stream.Duplex instance is faster here instead of inside - // the WritableState constructor, at least with V8 6.5 - - var isDuplex = this instanceof Duplex; - if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options); - this._writableState = new WritableState(options, this, isDuplex); // legacy. - - this.writable = true; - - if (options) { - if (typeof options.write === 'function') this._write = options.write; - if (typeof options.writev === 'function') this._writev = options.writev; - if (typeof options.destroy === 'function') this._destroy = options.destroy; - if (typeof options.final === 'function') this._final = options.final; - } - - Stream.call(this); -} // Otherwise people can pipe Writable streams, which is just wrong. - - -Writable.prototype.pipe = function () { - errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); -}; - -function writeAfterEnd(stream, cb) { - var er = new ERR_STREAM_WRITE_AFTER_END(); // TODO: defer error events consistently everywhere, not just the cb - - errorOrDestroy(stream, er); - process.nextTick(cb, er); -} // Checks that a user-supplied chunk is valid, especially for the particular -// mode the stream is in. Currently this means that `null` is never accepted -// and undefined/non-string values are only allowed in object mode. - - -function validChunk(stream, state, chunk, cb) { - var er; - - if (chunk === null) { - er = new ERR_STREAM_NULL_VALUES(); - } else if (typeof chunk !== 'string' && !state.objectMode) { - er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk); - } - - if (er) { - errorOrDestroy(stream, er); - process.nextTick(cb, er); - return false; - } - - return true; -} - -Writable.prototype.write = function (chunk, encoding, cb) { - var state = this._writableState; - var ret = false; - - var isBuf = !state.objectMode && _isUint8Array(chunk); - - if (isBuf && !Buffer.isBuffer(chunk)) { - chunk = _uint8ArrayToBuffer(chunk); - } - - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; - if (typeof cb !== 'function') cb = nop; - if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { - state.pendingcb++; - ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); - } - return ret; -}; - -Writable.prototype.cork = function () { - this._writableState.corked++; -}; - -Writable.prototype.uncork = function () { - var state = this._writableState; - - if (state.corked) { - state.corked--; - if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); - } -}; - -Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { - // node::ParseEncoding() requires lower case. - if (typeof encoding === 'string') encoding = encoding.toLowerCase(); - if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding); - this._writableState.defaultEncoding = encoding; - return this; -}; - -Object.defineProperty(Writable.prototype, 'writableBuffer', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState && this._writableState.getBuffer(); - } -}); - -function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { - chunk = Buffer.from(chunk, encoding); - } - - return chunk; -} - -Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.highWaterMark; - } -}); // if we're already writing something, then just put this -// in the queue, and wait our turn. Otherwise, call _write -// If we return false, then we need a drain event, so set that flag. - -function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { - if (!isBuf) { - var newChunk = decodeChunk(state, chunk, encoding); - - if (chunk !== newChunk) { - isBuf = true; - encoding = 'buffer'; - chunk = newChunk; - } - } - - var len = state.objectMode ? 1 : chunk.length; - state.length += len; - var ret = state.length < state.highWaterMark; // we must ensure that previous needDrain will not be reset to false. - - if (!ret) state.needDrain = true; - - if (state.writing || state.corked) { - var last = state.lastBufferedRequest; - state.lastBufferedRequest = { - chunk: chunk, - encoding: encoding, - isBuf: isBuf, - callback: cb, - next: null - }; - - if (last) { - last.next = state.lastBufferedRequest; - } else { - state.bufferedRequest = state.lastBufferedRequest; - } - - state.bufferedRequestCount += 1; - } else { - doWrite(stream, state, false, len, chunk, encoding, cb); - } - - return ret; -} - -function doWrite(stream, state, writev, len, chunk, encoding, cb) { - state.writelen = len; - state.writecb = cb; - state.writing = true; - state.sync = true; - if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); - state.sync = false; -} - -function onwriteError(stream, state, sync, er, cb) { - --state.pendingcb; - - if (sync) { - // defer the callback if we are being called synchronously - // to avoid piling up things on the stack - process.nextTick(cb, er); // this can emit finish, and it will always happen - // after error - - process.nextTick(finishMaybe, stream, state); - stream._writableState.errorEmitted = true; - errorOrDestroy(stream, er); - } else { - // the caller expect this to happen before if - // it is async - cb(er); - stream._writableState.errorEmitted = true; - errorOrDestroy(stream, er); // this can emit finish, but finish must - // always follow error - - finishMaybe(stream, state); - } -} - -function onwriteStateUpdate(state) { - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; -} - -function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; - if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK(); - onwriteStateUpdate(state); - if (er) onwriteError(stream, state, sync, er, cb);else { - // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(state) || stream.destroyed; - - if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { - clearBuffer(stream, state); - } - - if (sync) { - process.nextTick(afterWrite, stream, state, finished, cb); - } else { - afterWrite(stream, state, finished, cb); - } - } -} - -function afterWrite(stream, state, finished, cb) { - if (!finished) onwriteDrain(stream, state); - state.pendingcb--; - cb(); - finishMaybe(stream, state); -} // Must force callback to be called on nextTick, so that we don't -// emit 'drain' before the write() consumer gets the 'false' return -// value, and has a chance to attach a 'drain' listener. - - -function onwriteDrain(stream, state) { - if (state.length === 0 && state.needDrain) { - state.needDrain = false; - stream.emit('drain'); - } -} // if there's something in the buffer waiting, then process it - - -function clearBuffer(stream, state) { - state.bufferProcessing = true; - var entry = state.bufferedRequest; - - if (stream._writev && entry && entry.next) { - // Fast case, write everything using _writev() - var l = state.bufferedRequestCount; - var buffer = new Array(l); - var holder = state.corkedRequestsFree; - holder.entry = entry; - var count = 0; - var allBuffers = true; - - while (entry) { - buffer[count] = entry; - if (!entry.isBuf) allBuffers = false; - entry = entry.next; - count += 1; - } - - buffer.allBuffers = allBuffers; - doWrite(stream, state, true, state.length, buffer, '', holder.finish); // doWrite is almost always async, defer these to save a bit of time - // as the hot path ends with doWrite - - state.pendingcb++; - state.lastBufferedRequest = null; - - if (holder.next) { - state.corkedRequestsFree = holder.next; - holder.next = null; - } else { - state.corkedRequestsFree = new CorkedRequest(state); - } - - state.bufferedRequestCount = 0; - } else { - // Slow case, write chunks one-by-one - while (entry) { - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; - doWrite(stream, state, false, len, chunk, encoding, cb); - entry = entry.next; - state.bufferedRequestCount--; // if we didn't call the onwrite immediately, then - // it means that we need to wait until it does. - // also, that means that the chunk and cb are currently - // being processed, so move the buffer counter past them. - - if (state.writing) { - break; - } - } - - if (entry === null) state.lastBufferedRequest = null; - } - - state.bufferedRequest = entry; - state.bufferProcessing = false; -} - -Writable.prototype._write = function (chunk, encoding, cb) { - cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()')); -}; - -Writable.prototype._writev = null; - -Writable.prototype.end = function (chunk, encoding, cb) { - var state = this._writableState; - - if (typeof chunk === 'function') { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); // .end() fully uncorks - - if (state.corked) { - state.corked = 1; - this.uncork(); - } // ignore unnecessary end() calls. - - - if (!state.ending) endWritable(this, state, cb); - return this; -}; - -Object.defineProperty(Writable.prototype, 'writableLength', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - return this._writableState.length; - } -}); - -function needFinish(state) { - return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; -} - -function callFinal(stream, state) { - stream._final(function (err) { - state.pendingcb--; - - if (err) { - errorOrDestroy(stream, err); - } - - state.prefinished = true; - stream.emit('prefinish'); - finishMaybe(stream, state); - }); -} - -function prefinish(stream, state) { - if (!state.prefinished && !state.finalCalled) { - if (typeof stream._final === 'function' && !state.destroyed) { - state.pendingcb++; - state.finalCalled = true; - process.nextTick(callFinal, stream, state); - } else { - state.prefinished = true; - stream.emit('prefinish'); - } - } -} - -function finishMaybe(stream, state) { - var need = needFinish(state); - - if (need) { - prefinish(stream, state); - - if (state.pendingcb === 0) { - state.finished = true; - stream.emit('finish'); - - if (state.autoDestroy) { - // In case of duplex streams we need a way to detect - // if the readable side is ready for autoDestroy as well - var rState = stream._readableState; - - if (!rState || rState.autoDestroy && rState.endEmitted) { - stream.destroy(); - } - } - } - } - - return need; -} - -function endWritable(stream, state, cb) { - state.ending = true; - finishMaybe(stream, state); - - if (cb) { - if (state.finished) process.nextTick(cb);else stream.once('finish', cb); - } - - state.ended = true; - stream.writable = false; -} - -function onCorkedFinish(corkReq, state, err) { - var entry = corkReq.entry; - corkReq.entry = null; - - while (entry) { - var cb = entry.callback; - state.pendingcb--; - cb(err); - entry = entry.next; - } // reuse the free corkReq. - - - state.corkedRequestsFree.next = corkReq; -} - -Object.defineProperty(Writable.prototype, 'destroyed', { - // making it explicit this property is not enumerable - // because otherwise some prototype manipulation in - // userland will fail - enumerable: false, - get: function get() { - if (this._writableState === undefined) { - return false; - } - - return this._writableState.destroyed; - }, - set: function set(value) { - // we ignore the value if the stream - // has not been initialized yet - if (!this._writableState) { - return; - } // backward compatibility, the user is explicitly - // managing destroyed - - - this._writableState.destroyed = value; - } -}); -Writable.prototype.destroy = destroyImpl.destroy; -Writable.prototype._undestroy = destroyImpl.undestroy; - -Writable.prototype._destroy = function (err, cb) { - cb(err); -}; - -/***/ }), - -/***/ 5850: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var process = __webpack_require__(4155); - - -var _Object$setPrototypeO; - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -var finished = __webpack_require__(8610); - -var kLastResolve = Symbol('lastResolve'); -var kLastReject = Symbol('lastReject'); -var kError = Symbol('error'); -var kEnded = Symbol('ended'); -var kLastPromise = Symbol('lastPromise'); -var kHandlePromise = Symbol('handlePromise'); -var kStream = Symbol('stream'); - -function createIterResult(value, done) { - return { - value: value, - done: done - }; -} - -function readAndResolve(iter) { - var resolve = iter[kLastResolve]; - - if (resolve !== null) { - var data = iter[kStream].read(); // we defer if data is null - // we can be expecting either 'end' or - // 'error' - - if (data !== null) { - iter[kLastPromise] = null; - iter[kLastResolve] = null; - iter[kLastReject] = null; - resolve(createIterResult(data, false)); - } - } -} - -function onReadable(iter) { - // we wait for the next tick, because it might - // emit an error with process.nextTick - process.nextTick(readAndResolve, iter); -} - -function wrapForNext(lastPromise, iter) { - return function (resolve, reject) { - lastPromise.then(function () { - if (iter[kEnded]) { - resolve(createIterResult(undefined, true)); - return; - } - - iter[kHandlePromise](resolve, reject); - }, reject); - }; -} - -var AsyncIteratorPrototype = Object.getPrototypeOf(function () {}); -var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = { - get stream() { - return this[kStream]; - }, - - next: function next() { - var _this = this; - - // if we have detected an error in the meanwhile - // reject straight away - var error = this[kError]; - - if (error !== null) { - return Promise.reject(error); - } - - if (this[kEnded]) { - return Promise.resolve(createIterResult(undefined, true)); - } - - if (this[kStream].destroyed) { - // We need to defer via nextTick because if .destroy(err) is - // called, the error will be emitted via nextTick, and - // we cannot guarantee that there is no error lingering around - // waiting to be emitted. - return new Promise(function (resolve, reject) { - process.nextTick(function () { - if (_this[kError]) { - reject(_this[kError]); - } else { - resolve(createIterResult(undefined, true)); - } - }); - }); - } // if we have multiple next() calls - // we will wait for the previous Promise to finish - // this logic is optimized to support for await loops, - // where next() is only called once at a time - - - var lastPromise = this[kLastPromise]; - var promise; - - if (lastPromise) { - promise = new Promise(wrapForNext(lastPromise, this)); - } else { - // fast path needed to support multiple this.push() - // without triggering the next() queue - var data = this[kStream].read(); - - if (data !== null) { - return Promise.resolve(createIterResult(data, false)); - } - - promise = new Promise(this[kHandlePromise]); - } - - this[kLastPromise] = promise; - return promise; - } -}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () { - return this; -}), _defineProperty(_Object$setPrototypeO, "return", function _return() { - var _this2 = this; - - // destroy(err, cb) is a private API - // we can guarantee we have that here, because we control the - // Readable class this is attached to - return new Promise(function (resolve, reject) { - _this2[kStream].destroy(null, function (err) { - if (err) { - reject(err); - return; - } - - resolve(createIterResult(undefined, true)); - }); - }); -}), _Object$setPrototypeO), AsyncIteratorPrototype); - -var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) { - var _Object$create; - - var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, { - value: stream, - writable: true - }), _defineProperty(_Object$create, kLastResolve, { - value: null, - writable: true - }), _defineProperty(_Object$create, kLastReject, { - value: null, - writable: true - }), _defineProperty(_Object$create, kError, { - value: null, - writable: true - }), _defineProperty(_Object$create, kEnded, { - value: stream._readableState.endEmitted, - writable: true - }), _defineProperty(_Object$create, kHandlePromise, { - value: function value(resolve, reject) { - var data = iterator[kStream].read(); - - if (data) { - iterator[kLastPromise] = null; - iterator[kLastResolve] = null; - iterator[kLastReject] = null; - resolve(createIterResult(data, false)); - } else { - iterator[kLastResolve] = resolve; - iterator[kLastReject] = reject; - } - }, - writable: true - }), _Object$create)); - iterator[kLastPromise] = null; - finished(stream, function (err) { - if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') { - var reject = iterator[kLastReject]; // reject if we are waiting for data in the Promise - // returned by next() and store the error - - if (reject !== null) { - iterator[kLastPromise] = null; - iterator[kLastResolve] = null; - iterator[kLastReject] = null; - reject(err); - } - - iterator[kError] = err; - return; - } - - var resolve = iterator[kLastResolve]; - - if (resolve !== null) { - iterator[kLastPromise] = null; - iterator[kLastResolve] = null; - iterator[kLastReject] = null; - resolve(createIterResult(undefined, true)); - } - - iterator[kEnded] = true; - }); - stream.on('readable', onReadable.bind(null, iterator)); - return iterator; -}; - -module.exports = createReadableStreamAsyncIterator; - -/***/ }), - -/***/ 7327: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; - - -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } - -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } - -function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } - -var _require = __webpack_require__(8764), - Buffer = _require.Buffer; - -var _require2 = __webpack_require__(2361), - inspect = _require2.inspect; - -var custom = inspect && inspect.custom || 'inspect'; - -function copyBuffer(src, target, offset) { - Buffer.prototype.copy.call(src, target, offset); -} - -module.exports = -/*#__PURE__*/ -function () { - function BufferList() { - _classCallCheck(this, BufferList); - - this.head = null; - this.tail = null; - this.length = 0; - } - - _createClass(BufferList, [{ - key: "push", - value: function push(v) { - var entry = { - data: v, - next: null - }; - if (this.length > 0) this.tail.next = entry;else this.head = entry; - this.tail = entry; - ++this.length; - } - }, { - key: "unshift", - value: function unshift(v) { - var entry = { - data: v, - next: this.head - }; - if (this.length === 0) this.tail = entry; - this.head = entry; - ++this.length; - } - }, { - key: "shift", - value: function shift() { - if (this.length === 0) return; - var ret = this.head.data; - if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; - --this.length; - return ret; - } - }, { - key: "clear", - value: function clear() { - this.head = this.tail = null; - this.length = 0; - } - }, { - key: "join", - value: function join(s) { - if (this.length === 0) return ''; - var p = this.head; - var ret = '' + p.data; - - while (p = p.next) { - ret += s + p.data; - } - - return ret; - } - }, { - key: "concat", - value: function concat(n) { - if (this.length === 0) return Buffer.alloc(0); - var ret = Buffer.allocUnsafe(n >>> 0); - var p = this.head; - var i = 0; - - while (p) { - copyBuffer(p.data, ret, i); - i += p.data.length; - p = p.next; - } - - return ret; - } // Consumes a specified amount of bytes or characters from the buffered data. - - }, { - key: "consume", - value: function consume(n, hasStrings) { - var ret; - - if (n < this.head.data.length) { - // `slice` is the same for buffers and strings. - ret = this.head.data.slice(0, n); - this.head.data = this.head.data.slice(n); - } else if (n === this.head.data.length) { - // First chunk is a perfect match. - ret = this.shift(); - } else { - // Result spans more than one buffer. - ret = hasStrings ? this._getString(n) : this._getBuffer(n); - } - - return ret; - } - }, { - key: "first", - value: function first() { - return this.head.data; - } // Consumes a specified amount of characters from the buffered data. - - }, { - key: "_getString", - value: function _getString(n) { - var p = this.head; - var c = 1; - var ret = p.data; - n -= ret.length; - - while (p = p.next) { - var str = p.data; - var nb = n > str.length ? str.length : n; - if (nb === str.length) ret += str;else ret += str.slice(0, n); - n -= nb; - - if (n === 0) { - if (nb === str.length) { - ++c; - if (p.next) this.head = p.next;else this.head = this.tail = null; - } else { - this.head = p; - p.data = str.slice(nb); - } - - break; - } - - ++c; - } - - this.length -= c; - return ret; - } // Consumes a specified amount of bytes from the buffered data. - - }, { - key: "_getBuffer", - value: function _getBuffer(n) { - var ret = Buffer.allocUnsafe(n); - var p = this.head; - var c = 1; - p.data.copy(ret); - n -= p.data.length; - - while (p = p.next) { - var buf = p.data; - var nb = n > buf.length ? buf.length : n; - buf.copy(ret, ret.length - n, 0, nb); - n -= nb; - - if (n === 0) { - if (nb === buf.length) { - ++c; - if (p.next) this.head = p.next;else this.head = this.tail = null; - } else { - this.head = p; - p.data = buf.slice(nb); - } - - break; - } - - ++c; - } - - this.length -= c; - return ret; - } // Make sure the linked list only shows the minimal necessary information. - - }, { - key: custom, - value: function value(_, options) { - return inspect(this, _objectSpread({}, options, { - // Only inspect one level. - depth: 0, - // It should not recurse. - customInspect: false - })); - } - }]); - - return BufferList; -}(); - -/***/ }), - -/***/ 1195: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var process = __webpack_require__(4155); - // undocumented cb() API, needed for core, not for public API - -function destroy(err, cb) { - var _this = this; - - var readableDestroyed = this._readableState && this._readableState.destroyed; - var writableDestroyed = this._writableState && this._writableState.destroyed; - - if (readableDestroyed || writableDestroyed) { - if (cb) { - cb(err); - } else if (err) { - if (!this._writableState) { - process.nextTick(emitErrorNT, this, err); - } else if (!this._writableState.errorEmitted) { - this._writableState.errorEmitted = true; - process.nextTick(emitErrorNT, this, err); - } - } - - return this; - } // we set destroyed to true before firing error callbacks in order - // to make it re-entrance safe in case destroy() is called within callbacks - - - if (this._readableState) { - this._readableState.destroyed = true; - } // if this is a duplex stream mark the writable part as destroyed as well - - - if (this._writableState) { - this._writableState.destroyed = true; - } - - this._destroy(err || null, function (err) { - if (!cb && err) { - if (!_this._writableState) { - process.nextTick(emitErrorAndCloseNT, _this, err); - } else if (!_this._writableState.errorEmitted) { - _this._writableState.errorEmitted = true; - process.nextTick(emitErrorAndCloseNT, _this, err); - } else { - process.nextTick(emitCloseNT, _this); - } - } else if (cb) { - process.nextTick(emitCloseNT, _this); - cb(err); - } else { - process.nextTick(emitCloseNT, _this); - } - }); - - return this; -} - -function emitErrorAndCloseNT(self, err) { - emitErrorNT(self, err); - emitCloseNT(self); -} - -function emitCloseNT(self) { - if (self._writableState && !self._writableState.emitClose) return; - if (self._readableState && !self._readableState.emitClose) return; - self.emit('close'); -} - -function undestroy() { - if (this._readableState) { - this._readableState.destroyed = false; - this._readableState.reading = false; - this._readableState.ended = false; - this._readableState.endEmitted = false; - } - - if (this._writableState) { - this._writableState.destroyed = false; - this._writableState.ended = false; - this._writableState.ending = false; - this._writableState.finalCalled = false; - this._writableState.prefinished = false; - this._writableState.finished = false; - this._writableState.errorEmitted = false; - } -} - -function emitErrorNT(self, err) { - self.emit('error', err); -} - -function errorOrDestroy(stream, err) { - // We have tests that rely on errors being emitted - // in the same tick, so changing this is semver major. - // For now when you opt-in to autoDestroy we allow - // the error to be emitted nextTick. In a future - // semver major update we should change the default to this. - var rState = stream._readableState; - var wState = stream._writableState; - if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err); -} - -module.exports = { - destroy: destroy, - undestroy: undestroy, - errorOrDestroy: errorOrDestroy -}; - -/***/ }), - -/***/ 8610: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// Ported from https://github.com/mafintosh/end-of-stream with -// permission from the author, Mathias Buus (@mafintosh). - - -var ERR_STREAM_PREMATURE_CLOSE = (__webpack_require__(4281)/* .codes.ERR_STREAM_PREMATURE_CLOSE */ .q.ERR_STREAM_PREMATURE_CLOSE); - -function once(callback) { - var called = false; - return function () { - if (called) return; - called = true; - - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - callback.apply(this, args); - }; -} - -function noop() {} - -function isRequest(stream) { - return stream.setHeader && typeof stream.abort === 'function'; -} - -function eos(stream, opts, callback) { - if (typeof opts === 'function') return eos(stream, null, opts); - if (!opts) opts = {}; - callback = once(callback || noop); - var readable = opts.readable || opts.readable !== false && stream.readable; - var writable = opts.writable || opts.writable !== false && stream.writable; - - var onlegacyfinish = function onlegacyfinish() { - if (!stream.writable) onfinish(); - }; - - var writableEnded = stream._writableState && stream._writableState.finished; - - var onfinish = function onfinish() { - writable = false; - writableEnded = true; - if (!readable) callback.call(stream); - }; - - var readableEnded = stream._readableState && stream._readableState.endEmitted; - - var onend = function onend() { - readable = false; - readableEnded = true; - if (!writable) callback.call(stream); - }; - - var onerror = function onerror(err) { - callback.call(stream, err); - }; - - var onclose = function onclose() { - var err; - - if (readable && !readableEnded) { - if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); - return callback.call(stream, err); - } - - if (writable && !writableEnded) { - if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); - return callback.call(stream, err); - } - }; - - var onrequest = function onrequest() { - stream.req.on('finish', onfinish); - }; - - if (isRequest(stream)) { - stream.on('complete', onfinish); - stream.on('abort', onclose); - if (stream.req) onrequest();else stream.on('request', onrequest); - } else if (writable && !stream._writableState) { - // legacy streams - stream.on('end', onlegacyfinish); - stream.on('close', onlegacyfinish); - } - - stream.on('end', onend); - stream.on('finish', onfinish); - if (opts.error !== false) stream.on('error', onerror); - stream.on('close', onclose); - return function () { - stream.removeListener('complete', onfinish); - stream.removeListener('abort', onclose); - stream.removeListener('request', onrequest); - if (stream.req) stream.req.removeListener('finish', onfinish); - stream.removeListener('end', onlegacyfinish); - stream.removeListener('close', onlegacyfinish); - stream.removeListener('finish', onfinish); - stream.removeListener('end', onend); - stream.removeListener('error', onerror); - stream.removeListener('close', onclose); - }; -} - -module.exports = eos; - -/***/ }), - -/***/ 889: -/***/ ((module) => { - -module.exports = function () { - throw new Error('Readable.from is not available in the browser') -}; - - -/***/ }), - -/***/ 9946: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// Ported from https://github.com/mafintosh/pump with -// permission from the author, Mathias Buus (@mafintosh). - - -var eos; - -function once(callback) { - var called = false; - return function () { - if (called) return; - called = true; - callback.apply(void 0, arguments); - }; -} - -var _require$codes = (__webpack_require__(4281)/* .codes */ .q), - ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS, - ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; - -function noop(err) { - // Rethrow the error if it exists to avoid swallowing it - if (err) throw err; -} - -function isRequest(stream) { - return stream.setHeader && typeof stream.abort === 'function'; -} - -function destroyer(stream, reading, writing, callback) { - callback = once(callback); - var closed = false; - stream.on('close', function () { - closed = true; - }); - if (eos === undefined) eos = __webpack_require__(8610); - eos(stream, { - readable: reading, - writable: writing - }, function (err) { - if (err) return callback(err); - closed = true; - callback(); - }); - var destroyed = false; - return function (err) { - if (closed) return; - if (destroyed) return; - destroyed = true; // request.destroy just do .end - .abort is what we want - - if (isRequest(stream)) return stream.abort(); - if (typeof stream.destroy === 'function') return stream.destroy(); - callback(err || new ERR_STREAM_DESTROYED('pipe')); - }; -} - -function call(fn) { - fn(); -} - -function pipe(from, to) { - return from.pipe(to); -} - -function popCallback(streams) { - if (!streams.length) return noop; - if (typeof streams[streams.length - 1] !== 'function') return noop; - return streams.pop(); -} - -function pipeline() { - for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) { - streams[_key] = arguments[_key]; - } - - var callback = popCallback(streams); - if (Array.isArray(streams[0])) streams = streams[0]; - - if (streams.length < 2) { - throw new ERR_MISSING_ARGS('streams'); - } - - var error; - var destroys = streams.map(function (stream, i) { - var reading = i < streams.length - 1; - var writing = i > 0; - return destroyer(stream, reading, writing, function (err) { - if (!error) error = err; - if (err) destroys.forEach(call); - if (reading) return; - destroys.forEach(call); - callback(error); - }); - }); - return streams.reduce(pipe); -} - -module.exports = pipeline; - -/***/ }), - -/***/ 2457: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; - - -var ERR_INVALID_OPT_VALUE = (__webpack_require__(4281)/* .codes.ERR_INVALID_OPT_VALUE */ .q.ERR_INVALID_OPT_VALUE); - -function highWaterMarkFrom(options, isDuplex, duplexKey) { - return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null; -} - -function getHighWaterMark(state, options, duplexKey, isDuplex) { - var hwm = highWaterMarkFrom(options, isDuplex, duplexKey); - - if (hwm != null) { - if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) { - var name = isDuplex ? duplexKey : 'highWaterMark'; - throw new ERR_INVALID_OPT_VALUE(name, hwm); - } - - return Math.floor(hwm); - } // Default value - - - return state.objectMode ? 16 : 16 * 1024; -} - -module.exports = { - getHighWaterMark: getHighWaterMark -}; - -/***/ }), - -/***/ 2503: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -module.exports = __webpack_require__(7187).EventEmitter; - - -/***/ }), - -/***/ 8473: -/***/ ((module, exports, __webpack_require__) => { - -exports = module.exports = __webpack_require__(9481); -exports.Stream = exports; -exports.Readable = exports; -exports.Writable = __webpack_require__(4229); -exports.Duplex = __webpack_require__(6753); -exports.Transform = __webpack_require__(4605); -exports.PassThrough = __webpack_require__(2725); -exports.finished = __webpack_require__(8610); -exports.pipeline = __webpack_require__(9946); - - -/***/ }), - -/***/ 8090: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ReadableWebToNodeStream = void 0; -const readable_stream_1 = __webpack_require__(8473); -/** - * Converts a Web-API stream into Node stream.Readable class - * Node stream readable: https://nodejs.org/api/stream.html#stream_readable_streams - * Web API readable-stream: https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream - * Node readable stream: https://nodejs.org/api/stream.html#stream_readable_streams - */ -class ReadableWebToNodeStream extends readable_stream_1.Readable { - /** - * - * @param stream Readable​Stream: https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream - */ - constructor(stream) { - super(); - this.bytesRead = 0; - this.released = false; - this.reader = stream.getReader(); - } - /** - * Implementation of readable._read(size). - * When readable._read() is called, if data is available from the resource, - * the implementation should begin pushing that data into the read queue - * https://nodejs.org/api/stream.html#stream_readable_read_size_1 - */ - async _read() { - // Should start pushing data into the queue - // Read data from the underlying Web-API-readable-stream - if (this.released) { - this.push(null); // Signal EOF - return; - } - this.pendingRead = this.reader.read(); - const data = await this.pendingRead; - // clear the promise before pushing pushing new data to the queue and allow sequential calls to _read() - delete this.pendingRead; - if (data.done || this.released) { - this.push(null); // Signal EOF - } - else { - this.bytesRead += data.value.length; - this.push(data.value); // Push new data to the queue - } - } - /** - * If there is no unresolved read call to Web-API Readable​Stream immediately returns; - * otherwise will wait until the read is resolved. - */ - async waitForReadToComplete() { - if (this.pendingRead) { - await this.pendingRead; - } - } - /** - * Close wrapper - */ - async close() { - await this.syncAndRelease(); - } - async syncAndRelease() { - this.released = true; - await this.waitForReadToComplete(); - await this.reader.releaseLock(); - } -} -exports.ReadableWebToNodeStream = ReadableWebToNodeStream; -//# sourceMappingURL=index.js.map - -/***/ }), - -/***/ 9509: -/***/ ((module, exports, __webpack_require__) => { - -/* eslint-disable node/no-deprecated-api */ -var buffer = __webpack_require__(8764) -var Buffer = buffer.Buffer - -// alternative to using Object.keys for old browsers -function copyProps (src, dst) { - for (var key in src) { - dst[key] = src[key] - } -} -if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { - module.exports = buffer -} else { - // Copy properties from require('buffer') - copyProps(buffer, exports) - exports.Buffer = SafeBuffer -} - -function SafeBuffer (arg, encodingOrOffset, length) { - return Buffer(arg, encodingOrOffset, length) -} - -// Copy static methods from Buffer -copyProps(Buffer, SafeBuffer) - -SafeBuffer.from = function (arg, encodingOrOffset, length) { - if (typeof arg === 'number') { - throw new TypeError('Argument must not be a number') - } - return Buffer(arg, encodingOrOffset, length) -} - -SafeBuffer.alloc = function (size, fill, encoding) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - var buf = Buffer(size) - if (fill !== undefined) { - if (typeof encoding === 'string') { - buf.fill(fill, encoding) - } else { - buf.fill(fill) - } - } else { - buf.fill(0) - } - return buf -} - -SafeBuffer.allocUnsafe = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return Buffer(size) -} - -SafeBuffer.allocUnsafeSlow = function (size) { - if (typeof size !== 'number') { - throw new TypeError('Argument must be a number') - } - return buffer.SlowBuffer(size) -} - - -/***/ }), - -/***/ 2553: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -/**/ - -var Buffer = (__webpack_require__(9509).Buffer); -/**/ - -var isEncoding = Buffer.isEncoding || function (encoding) { - encoding = '' + encoding; - switch (encoding && encoding.toLowerCase()) { - case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': - return true; - default: - return false; - } -}; - -function _normalizeEncoding(enc) { - if (!enc) return 'utf8'; - var retried; - while (true) { - switch (enc) { - case 'utf8': - case 'utf-8': - return 'utf8'; - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return 'utf16le'; - case 'latin1': - case 'binary': - return 'latin1'; - case 'base64': - case 'ascii': - case 'hex': - return enc; - default: - if (retried) return; // undefined - enc = ('' + enc).toLowerCase(); - retried = true; - } - } -}; - -// Do not cache `Buffer.isEncoding` when checking encoding names as some -// modules monkey-patch it to support additional encodings -function normalizeEncoding(enc) { - var nenc = _normalizeEncoding(enc); - if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); - return nenc || enc; -} - -// StringDecoder provides an interface for efficiently splitting a series of -// buffers into a series of JS strings without breaking apart multi-byte -// characters. -exports.s = StringDecoder; -function StringDecoder(encoding) { - this.encoding = normalizeEncoding(encoding); - var nb; - switch (this.encoding) { - case 'utf16le': - this.text = utf16Text; - this.end = utf16End; - nb = 4; - break; - case 'utf8': - this.fillLast = utf8FillLast; - nb = 4; - break; - case 'base64': - this.text = base64Text; - this.end = base64End; - nb = 3; - break; - default: - this.write = simpleWrite; - this.end = simpleEnd; - return; - } - this.lastNeed = 0; - this.lastTotal = 0; - this.lastChar = Buffer.allocUnsafe(nb); -} - -StringDecoder.prototype.write = function (buf) { - if (buf.length === 0) return ''; - var r; - var i; - if (this.lastNeed) { - r = this.fillLast(buf); - if (r === undefined) return ''; - i = this.lastNeed; - this.lastNeed = 0; - } else { - i = 0; - } - if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); - return r || ''; -}; - -StringDecoder.prototype.end = utf8End; - -// Returns only complete characters in a Buffer -StringDecoder.prototype.text = utf8Text; - -// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer -StringDecoder.prototype.fillLast = function (buf) { - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); - } - buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); - this.lastNeed -= buf.length; -}; - -// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a -// continuation byte. If an invalid byte is detected, -2 is returned. -function utf8CheckByte(byte) { - if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; - return byte >> 6 === 0x02 ? -1 : -2; -} - -// Checks at most 3 bytes at the end of a Buffer in order to detect an -// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) -// needed to complete the UTF-8 character (if applicable) are returned. -function utf8CheckIncomplete(self, buf, i) { - var j = buf.length - 1; - if (j < i) return 0; - var nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) self.lastNeed = nb - 1; - return nb; - } - if (--j < i || nb === -2) return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) self.lastNeed = nb - 2; - return nb; - } - if (--j < i || nb === -2) return 0; - nb = utf8CheckByte(buf[j]); - if (nb >= 0) { - if (nb > 0) { - if (nb === 2) nb = 0;else self.lastNeed = nb - 3; - } - return nb; - } - return 0; -} - -// Validates as many continuation bytes for a multi-byte UTF-8 character as -// needed or are available. If we see a non-continuation byte where we expect -// one, we "replace" the validated continuation bytes we've seen so far with -// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding -// behavior. The continuation byte check is included three times in the case -// where all of the continuation bytes for a character exist in the same buffer. -// It is also done this way as a slight performance increase instead of using a -// loop. -function utf8CheckExtraBytes(self, buf, p) { - if ((buf[0] & 0xC0) !== 0x80) { - self.lastNeed = 0; - return '\ufffd'; - } - if (self.lastNeed > 1 && buf.length > 1) { - if ((buf[1] & 0xC0) !== 0x80) { - self.lastNeed = 1; - return '\ufffd'; - } - if (self.lastNeed > 2 && buf.length > 2) { - if ((buf[2] & 0xC0) !== 0x80) { - self.lastNeed = 2; - return '\ufffd'; - } - } - } -} - -// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. -function utf8FillLast(buf) { - var p = this.lastTotal - this.lastNeed; - var r = utf8CheckExtraBytes(this, buf, p); - if (r !== undefined) return r; - if (this.lastNeed <= buf.length) { - buf.copy(this.lastChar, p, 0, this.lastNeed); - return this.lastChar.toString(this.encoding, 0, this.lastTotal); - } - buf.copy(this.lastChar, p, 0, buf.length); - this.lastNeed -= buf.length; -} - -// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a -// partial character, the character's bytes are buffered until the required -// number of bytes are available. -function utf8Text(buf, i) { - var total = utf8CheckIncomplete(this, buf, i); - if (!this.lastNeed) return buf.toString('utf8', i); - this.lastTotal = total; - var end = buf.length - (total - this.lastNeed); - buf.copy(this.lastChar, 0, end); - return buf.toString('utf8', i, end); -} - -// For UTF-8, a replacement character is added when ending on a partial -// character. -function utf8End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) return r + '\ufffd'; - return r; -} - -// UTF-16LE typically needs two bytes per character, but even if we have an even -// number of bytes available, we need to check if we end on a leading/high -// surrogate. In that case, we need to wait for the next two bytes in order to -// decode the last character properly. -function utf16Text(buf, i) { - if ((buf.length - i) % 2 === 0) { - var r = buf.toString('utf16le', i); - if (r) { - var c = r.charCodeAt(r.length - 1); - if (c >= 0xD800 && c <= 0xDBFF) { - this.lastNeed = 2; - this.lastTotal = 4; - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; - return r.slice(0, -1); - } - } - return r; - } - this.lastNeed = 1; - this.lastTotal = 2; - this.lastChar[0] = buf[buf.length - 1]; - return buf.toString('utf16le', i, buf.length - 1); -} - -// For UTF-16LE we do not explicitly append special replacement characters if we -// end on a partial character, we simply let v8 handle that. -function utf16End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) { - var end = this.lastTotal - this.lastNeed; - return r + this.lastChar.toString('utf16le', 0, end); - } - return r; -} - -function base64Text(buf, i) { - var n = (buf.length - i) % 3; - if (n === 0) return buf.toString('base64', i); - this.lastNeed = 3 - n; - this.lastTotal = 3; - if (n === 1) { - this.lastChar[0] = buf[buf.length - 1]; - } else { - this.lastChar[0] = buf[buf.length - 2]; - this.lastChar[1] = buf[buf.length - 1]; - } - return buf.toString('base64', i, buf.length - n); -} - -function base64End(buf) { - var r = buf && buf.length ? this.write(buf) : ''; - if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); - return r; -} - -// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) -function simpleWrite(buf) { - return buf.toString(this.encoding); -} - -function simpleEnd(buf) { - return buf && buf.length ? this.write(buf) : ''; -} - -/***/ }), - -/***/ 842: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.AbstractTokenizer = void 0; -const peek_readable_1 = __webpack_require__(5167); -/** - * Core tokenizer - */ -class AbstractTokenizer { - constructor(fileInfo) { - /** - * Tokenizer-stream position - */ - this.position = 0; - this.numBuffer = new Uint8Array(8); - this.fileInfo = fileInfo ? fileInfo : {}; - } - /** - * Read a token from the tokenizer-stream - * @param token - The token to read - * @param position - If provided, the desired position in the tokenizer-stream - * @returns Promise with token data - */ - async readToken(token, position = this.position) { - const uint8Array = Buffer.alloc(token.len); - const len = await this.readBuffer(uint8Array, { position }); - if (len < token.len) - throw new peek_readable_1.EndOfStreamError(); - return token.get(uint8Array, 0); - } - /** - * Peek a token from the tokenizer-stream. - * @param token - Token to peek from the tokenizer-stream. - * @param position - Offset where to begin reading within the file. If position is null, data will be read from the current file position. - * @returns Promise with token data - */ - async peekToken(token, position = this.position) { - const uint8Array = Buffer.alloc(token.len); - const len = await this.peekBuffer(uint8Array, { position }); - if (len < token.len) - throw new peek_readable_1.EndOfStreamError(); - return token.get(uint8Array, 0); - } - /** - * Read a numeric token from the stream - * @param token - Numeric token - * @returns Promise with number - */ - async readNumber(token) { - const len = await this.readBuffer(this.numBuffer, { length: token.len }); - if (len < token.len) - throw new peek_readable_1.EndOfStreamError(); - return token.get(this.numBuffer, 0); - } - /** - * Read a numeric token from the stream - * @param token - Numeric token - * @returns Promise with number - */ - async peekNumber(token) { - const len = await this.peekBuffer(this.numBuffer, { length: token.len }); - if (len < token.len) - throw new peek_readable_1.EndOfStreamError(); - return token.get(this.numBuffer, 0); - } - /** - * Ignore number of bytes, advances the pointer in under tokenizer-stream. - * @param length - Number of bytes to ignore - * @return resolves the number of bytes ignored, equals length if this available, otherwise the number of bytes available - */ - async ignore(length) { - if (this.fileInfo.size !== undefined) { - const bytesLeft = this.fileInfo.size - this.position; - if (length > bytesLeft) { - this.position += bytesLeft; - return bytesLeft; - } - } - this.position += length; - return length; - } - async close() { - // empty - } - normalizeOptions(uint8Array, options) { - if (options && options.position !== undefined && options.position < this.position) { - throw new Error('`options.position` must be equal or greater than `tokenizer.position`'); - } - if (options) { - return { - mayBeLess: options.mayBeLess === true, - offset: options.offset ? options.offset : 0, - length: options.length ? options.length : (uint8Array.length - (options.offset ? options.offset : 0)), - position: options.position ? options.position : this.position - }; - } - return { - mayBeLess: false, - offset: 0, - length: uint8Array.length, - position: this.position - }; - } -} -exports.AbstractTokenizer = AbstractTokenizer; - - -/***/ }), - -/***/ 778: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.BufferTokenizer = void 0; -const peek_readable_1 = __webpack_require__(5167); -const AbstractTokenizer_1 = __webpack_require__(842); -class BufferTokenizer extends AbstractTokenizer_1.AbstractTokenizer { - /** - * Construct BufferTokenizer - * @param uint8Array - Uint8Array to tokenize - * @param fileInfo - Pass additional file information to the tokenizer - */ - constructor(uint8Array, fileInfo) { - super(fileInfo); - this.uint8Array = uint8Array; - this.fileInfo.size = this.fileInfo.size ? this.fileInfo.size : uint8Array.length; - } - /** - * Read buffer from tokenizer - * @param uint8Array - Uint8Array to tokenize - * @param options - Read behaviour options - * @returns {Promise} - */ - async readBuffer(uint8Array, options) { - if (options && options.position) { - if (options.position < this.position) { - throw new Error('`options.position` must be equal or greater than `tokenizer.position`'); - } - this.position = options.position; - } - const bytesRead = await this.peekBuffer(uint8Array, options); - this.position += bytesRead; - return bytesRead; - } - /** - * Peek (read ahead) buffer from tokenizer - * @param uint8Array - * @param options - Read behaviour options - * @returns {Promise} - */ - async peekBuffer(uint8Array, options) { - const normOptions = this.normalizeOptions(uint8Array, options); - const bytes2read = Math.min(this.uint8Array.length - normOptions.position, normOptions.length); - if ((!normOptions.mayBeLess) && bytes2read < normOptions.length) { - throw new peek_readable_1.EndOfStreamError(); - } - else { - uint8Array.set(this.uint8Array.subarray(normOptions.position, normOptions.position + bytes2read), normOptions.offset); - return bytes2read; - } - } - async close() { - // empty - } -} -exports.BufferTokenizer = BufferTokenizer; - - -/***/ }), - -/***/ 599: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.ReadStreamTokenizer = void 0; -const AbstractTokenizer_1 = __webpack_require__(842); -const peek_readable_1 = __webpack_require__(5167); -const maxBufferSize = 256000; -class ReadStreamTokenizer extends AbstractTokenizer_1.AbstractTokenizer { - constructor(stream, fileInfo) { - super(fileInfo); - this.streamReader = new peek_readable_1.StreamReader(stream); - } - /** - * Get file information, an HTTP-client may implement this doing a HEAD request - * @return Promise with file information - */ - async getFileInfo() { - return this.fileInfo; - } - /** - * Read buffer from tokenizer - * @param uint8Array - Target Uint8Array to fill with data read from the tokenizer-stream - * @param options - Read behaviour options - * @returns Promise with number of bytes read - */ - async readBuffer(uint8Array, options) { - const normOptions = this.normalizeOptions(uint8Array, options); - const skipBytes = normOptions.position - this.position; - if (skipBytes > 0) { - await this.ignore(skipBytes); - return this.readBuffer(uint8Array, options); - } - else if (skipBytes < 0) { - throw new Error('`options.position` must be equal or greater than `tokenizer.position`'); - } - if (normOptions.length === 0) { - return 0; - } - const bytesRead = await this.streamReader.read(uint8Array, normOptions.offset, normOptions.length); - this.position += bytesRead; - if ((!options || !options.mayBeLess) && bytesRead < normOptions.length) { - throw new peek_readable_1.EndOfStreamError(); - } - return bytesRead; - } - /** - * Peek (read ahead) buffer from tokenizer - * @param uint8Array - Uint8Array (or Buffer) to write data to - * @param options - Read behaviour options - * @returns Promise with number of bytes peeked - */ - async peekBuffer(uint8Array, options) { - const normOptions = this.normalizeOptions(uint8Array, options); - let bytesRead = 0; - if (normOptions.position) { - const skipBytes = normOptions.position - this.position; - if (skipBytes > 0) { - const skipBuffer = new Uint8Array(normOptions.length + skipBytes); - bytesRead = await this.peekBuffer(skipBuffer, { mayBeLess: normOptions.mayBeLess }); - uint8Array.set(skipBuffer.subarray(skipBytes), normOptions.offset); - return bytesRead - skipBytes; - } - else if (skipBytes < 0) { - throw new Error('Cannot peek from a negative offset in a stream'); - } - } - if (normOptions.length > 0) { - try { - bytesRead = await this.streamReader.peek(uint8Array, normOptions.offset, normOptions.length); - } - catch (err) { - if (options && options.mayBeLess && err instanceof peek_readable_1.EndOfStreamError) { - return 0; - } - throw err; - } - if ((!normOptions.mayBeLess) && bytesRead < normOptions.length) { - throw new peek_readable_1.EndOfStreamError(); - } - } - return bytesRead; - } - async ignore(length) { - // debug(`ignore ${this.position}...${this.position + length - 1}`); - const bufSize = Math.min(maxBufferSize, length); - const buf = new Uint8Array(bufSize); - let totBytesRead = 0; - while (totBytesRead < length) { - const remaining = length - totBytesRead; - const bytesRead = await this.readBuffer(buf, { length: Math.min(bufSize, remaining) }); - if (bytesRead < 0) { - return bytesRead; - } - totBytesRead += bytesRead; - } - return totBytesRead; - } -} -exports.ReadStreamTokenizer = ReadStreamTokenizer; - - -/***/ }), - -/***/ 5849: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.fromBuffer = exports.fromStream = exports.EndOfStreamError = void 0; -const ReadStreamTokenizer_1 = __webpack_require__(599); -const BufferTokenizer_1 = __webpack_require__(778); -var peek_readable_1 = __webpack_require__(5167); -Object.defineProperty(exports, "EndOfStreamError", ({ enumerable: true, get: function () { return peek_readable_1.EndOfStreamError; } })); -/** - * Construct ReadStreamTokenizer from given Stream. - * Will set fileSize, if provided given Stream has set the .path property/ - * @param stream - Read from Node.js Stream.Readable - * @param fileInfo - Pass the file information, like size and MIME-type of the corresponding stream. - * @returns ReadStreamTokenizer - */ -function fromStream(stream, fileInfo) { - fileInfo = fileInfo ? fileInfo : {}; - return new ReadStreamTokenizer_1.ReadStreamTokenizer(stream, fileInfo); -} -exports.fromStream = fromStream; -/** - * Construct ReadStreamTokenizer from given Buffer. - * @param uint8Array - Uint8Array to tokenize - * @param fileInfo - Pass additional file information to the tokenizer - * @returns BufferTokenizer - */ -function fromBuffer(uint8Array, fileInfo) { - return new BufferTokenizer_1.BufferTokenizer(uint8Array, fileInfo); -} -exports.fromBuffer = fromBuffer; - - -/***/ }), - -/***/ 3416: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -/* provided dependency */ var Buffer = __webpack_require__(8764)["Buffer"]; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.AnsiStringType = exports.StringType = exports.BufferType = exports.Uint8ArrayType = exports.IgnoreType = exports.Float80_LE = exports.Float80_BE = exports.Float64_LE = exports.Float64_BE = exports.Float32_LE = exports.Float32_BE = exports.Float16_LE = exports.Float16_BE = exports.INT64_BE = exports.UINT64_BE = exports.INT64_LE = exports.UINT64_LE = exports.INT32_LE = exports.INT32_BE = exports.INT24_BE = exports.INT24_LE = exports.INT16_LE = exports.INT16_BE = exports.INT8 = exports.UINT32_BE = exports.UINT32_LE = exports.UINT24_BE = exports.UINT24_LE = exports.UINT16_BE = exports.UINT16_LE = exports.UINT8 = void 0; -const ieee754 = __webpack_require__(645); -// Primitive types -function dv(array) { - return new DataView(array.buffer, array.byteOffset); -} -/** - * 8-bit unsigned integer - */ -exports.UINT8 = { - len: 1, - get(array, offset) { - return dv(array).getUint8(offset); - }, - put(array, offset, value) { - dv(array).setUint8(offset, value); - return offset + 1; - } -}; -/** - * 16-bit unsigned integer, Little Endian byte order - */ -exports.UINT16_LE = { - len: 2, - get(array, offset) { - return dv(array).getUint16(offset, true); - }, - put(array, offset, value) { - dv(array).setUint16(offset, value, true); - return offset + 2; - } -}; -/** - * 16-bit unsigned integer, Big Endian byte order - */ -exports.UINT16_BE = { - len: 2, - get(array, offset) { - return dv(array).getUint16(offset); - }, - put(array, offset, value) { - dv(array).setUint16(offset, value); - return offset + 2; - } -}; -/** - * 24-bit unsigned integer, Little Endian byte order - */ -exports.UINT24_LE = { - len: 3, - get(array, offset) { - const dataView = dv(array); - return dataView.getUint8(offset) + (dataView.getUint16(offset + 1, true) << 8); - }, - put(array, offset, value) { - const dataView = dv(array); - dataView.setUint8(offset, value & 0xff); - dataView.setUint16(offset + 1, value >> 8, true); - return offset + 3; - } -}; -/** - * 24-bit unsigned integer, Big Endian byte order - */ -exports.UINT24_BE = { - len: 3, - get(array, offset) { - const dataView = dv(array); - return (dataView.getUint16(offset) << 8) + dataView.getUint8(offset + 2); - }, - put(array, offset, value) { - const dataView = dv(array); - dataView.setUint16(offset, value >> 8); - dataView.setUint8(offset + 2, value & 0xff); - return offset + 3; - } -}; -/** - * 32-bit unsigned integer, Little Endian byte order - */ -exports.UINT32_LE = { - len: 4, - get(array, offset) { - return dv(array).getUint32(offset, true); - }, - put(array, offset, value) { - dv(array).setUint32(offset, value, true); - return offset + 4; - } -}; -/** - * 32-bit unsigned integer, Big Endian byte order - */ -exports.UINT32_BE = { - len: 4, - get(array, offset) { - return dv(array).getUint32(offset); - }, - put(array, offset, value) { - dv(array).setUint32(offset, value); - return offset + 4; - } -}; -/** - * 8-bit signed integer - */ -exports.INT8 = { - len: 1, - get(array, offset) { - return dv(array).getInt8(offset); - }, - put(array, offset, value) { - dv(array).setInt8(offset, value); - return offset + 2; - } -}; -/** - * 16-bit signed integer, Big Endian byte order - */ -exports.INT16_BE = { - len: 2, - get(array, offset) { - return dv(array).getInt16(offset); - }, - put(array, offset, value) { - dv(array).setInt16(offset, value); - return offset + 2; - } -}; -/** - * 16-bit signed integer, Little Endian byte order - */ -exports.INT16_LE = { - len: 2, - get(array, offset) { - return dv(array).getInt16(offset, true); - }, - put(array, offset, value) { - dv(array).setInt16(offset, value, true); - return offset + 2; - } -}; -/** - * 24-bit signed integer, Little Endian byte order - */ -exports.INT24_LE = { - len: 3, - get(array, offset) { - const unsigned = exports.UINT24_LE.get(array, offset); - return unsigned > 0x7fffff ? unsigned - 0x1000000 : unsigned; - }, - put(array, offset, value) { - const dataView = dv(array); - dataView.setUint8(offset, value & 0xff); - dataView.setUint16(offset + 1, value >> 8, true); - return offset + 3; - } -}; -/** - * 24-bit signed integer, Big Endian byte order - */ -exports.INT24_BE = { - len: 3, - get(array, offset) { - const unsigned = exports.UINT24_BE.get(array, offset); - return unsigned > 0x7fffff ? unsigned - 0x1000000 : unsigned; - }, - put(array, offset, value) { - const dataView = dv(array); - dataView.setUint16(offset, value >> 8); - dataView.setUint8(offset + 2, value & 0xff); - return offset + 3; - } -}; -/** - * 32-bit signed integer, Big Endian byte order - */ -exports.INT32_BE = { - len: 4, - get(array, offset) { - return dv(array).getInt32(offset); - }, - put(array, offset, value) { - dv(array).setInt32(offset, value); - return offset + 4; - } -}; -/** - * 32-bit signed integer, Big Endian byte order - */ -exports.INT32_LE = { - len: 4, - get(array, offset) { - return dv(array).getInt32(offset, true); - }, - put(array, offset, value) { - dv(array).setInt32(offset, value, true); - return offset + 4; - } -}; -/** - * 64-bit unsigned integer, Little Endian byte order - */ -exports.UINT64_LE = { - len: 8, - get(array, offset) { - return dv(array).getBigUint64(offset, true); - }, - put(array, offset, value) { - dv(array).setBigUint64(offset, value, true); - return offset + 8; - } -}; -/** - * 64-bit signed integer, Little Endian byte order - */ -exports.INT64_LE = { - len: 8, - get(array, offset) { - return dv(array).getBigInt64(offset, true); - }, - put(array, offset, value) { - dv(array).setBigInt64(offset, value, true); - return offset + 8; - } -}; -/** - * 64-bit unsigned integer, Big Endian byte order - */ -exports.UINT64_BE = { - len: 8, - get(array, offset) { - return dv(array).getBigUint64(offset); - }, - put(array, offset, value) { - dv(array).setBigUint64(offset, value); - return offset + 8; - } -}; -/** - * 64-bit signed integer, Big Endian byte order - */ -exports.INT64_BE = { - len: 8, - get(array, offset) { - return dv(array).getBigInt64(offset); - }, - put(array, offset, value) { - dv(array).setBigInt64(offset, value); - return offset + 8; - } -}; -/** - * IEEE 754 16-bit (half precision) float, big endian - */ -exports.Float16_BE = { - len: 2, - get(dataView, offset) { - return ieee754.read(dataView, offset, false, 10, this.len); - }, - put(dataView, offset, value) { - ieee754.write(dataView, value, offset, false, 10, this.len); - return offset + this.len; - } -}; -/** - * IEEE 754 16-bit (half precision) float, little endian - */ -exports.Float16_LE = { - len: 2, - get(array, offset) { - return ieee754.read(array, offset, true, 10, this.len); - }, - put(array, offset, value) { - ieee754.write(array, value, offset, true, 10, this.len); - return offset + this.len; - } -}; -/** - * IEEE 754 32-bit (single precision) float, big endian - */ -exports.Float32_BE = { - len: 4, - get(array, offset) { - return dv(array).getFloat32(offset); - }, - put(array, offset, value) { - dv(array).setFloat32(offset, value); - return offset + 4; - } -}; -/** - * IEEE 754 32-bit (single precision) float, little endian - */ -exports.Float32_LE = { - len: 4, - get(array, offset) { - return dv(array).getFloat32(offset, true); - }, - put(array, offset, value) { - dv(array).setFloat32(offset, value, true); - return offset + 4; - } -}; -/** - * IEEE 754 64-bit (double precision) float, big endian - */ -exports.Float64_BE = { - len: 8, - get(array, offset) { - return dv(array).getFloat64(offset); - }, - put(array, offset, value) { - dv(array).setFloat64(offset, value); - return offset + 8; - } -}; -/** - * IEEE 754 64-bit (double precision) float, little endian - */ -exports.Float64_LE = { - len: 8, - get(array, offset) { - return dv(array).getFloat64(offset, true); - }, - put(array, offset, value) { - dv(array).setFloat64(offset, value, true); - return offset + 8; - } -}; -/** - * IEEE 754 80-bit (extended precision) float, big endian - */ -exports.Float80_BE = { - len: 10, - get(array, offset) { - return ieee754.read(array, offset, false, 63, this.len); - }, - put(array, offset, value) { - ieee754.write(array, value, offset, false, 63, this.len); - return offset + this.len; - } -}; -/** - * IEEE 754 80-bit (extended precision) float, little endian - */ -exports.Float80_LE = { - len: 10, - get(array, offset) { - return ieee754.read(array, offset, true, 63, this.len); - }, - put(array, offset, value) { - ieee754.write(array, value, offset, true, 63, this.len); - return offset + this.len; - } -}; -/** - * Ignore a given number of bytes - */ -class IgnoreType { - /** - * @param len number of bytes to ignore - */ - constructor(len) { - this.len = len; - } - // ToDo: don't read, but skip data - get(array, off) { - } -} -exports.IgnoreType = IgnoreType; -class Uint8ArrayType { - constructor(len) { - this.len = len; - } - get(array, offset) { - return array.subarray(offset, offset + this.len); - } -} -exports.Uint8ArrayType = Uint8ArrayType; -class BufferType { - constructor(len) { - this.len = len; - } - get(uint8Array, off) { - return Buffer.from(uint8Array.subarray(off, off + this.len)); - } -} -exports.BufferType = BufferType; -/** - * Consume a fixed number of bytes from the stream and return a string with a specified encoding. - */ -class StringType { - constructor(len, encoding) { - this.len = len; - this.encoding = encoding; - } - get(uint8Array, offset) { - return Buffer.from(uint8Array).toString(this.encoding, offset, offset + this.len); - } -} -exports.StringType = StringType; -/** - * ANSI Latin 1 String - * Using windows-1252 / ISO 8859-1 decoding - */ -class AnsiStringType { - constructor(len) { - this.len = len; - } - static decode(buffer, offset, until) { - let str = ''; - for (let i = offset; i < until; ++i) { - str += AnsiStringType.codePointToString(AnsiStringType.singleByteDecoder(buffer[i])); - } - return str; - } - static inRange(a, min, max) { - return min <= a && a <= max; - } - static codePointToString(cp) { - if (cp <= 0xFFFF) { - return String.fromCharCode(cp); - } - else { - cp -= 0x10000; - return String.fromCharCode((cp >> 10) + 0xD800, (cp & 0x3FF) + 0xDC00); - } - } - static singleByteDecoder(bite) { - if (AnsiStringType.inRange(bite, 0x00, 0x7F)) { - return bite; - } - const codePoint = AnsiStringType.windows1252[bite - 0x80]; - if (codePoint === null) { - throw Error('invaliding encoding'); - } - return codePoint; - } - get(buffer, offset = 0) { - return AnsiStringType.decode(buffer, offset, offset + this.len); - } -} -exports.AnsiStringType = AnsiStringType; -AnsiStringType.windows1252 = [8364, 129, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, - 8249, 338, 141, 381, 143, 144, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, - 8482, 353, 8250, 339, 157, 382, 376, 160, 161, 162, 163, 164, 165, 166, 167, 168, - 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255]; - - -/***/ }), - -/***/ 9620: -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.fetchFromUrl = exports.parseBlob = exports.parseReadableStream = exports.parseNodeStream = exports.selectCover = exports.ratingToStars = exports.orderTags = exports.parseFromTokenizer = exports.parseBuffer = void 0; -const initDebug = __webpack_require__(1227); -const mm = __webpack_require__(523); -const readable_web_to_node_stream_1 = __webpack_require__(8090); -const debug = initDebug('music-metadata-browser:main'); -var core_1 = __webpack_require__(523); -Object.defineProperty(exports, "parseBuffer", ({ enumerable: true, get: function () { return core_1.parseBuffer; } })); -Object.defineProperty(exports, "parseFromTokenizer", ({ enumerable: true, get: function () { return core_1.parseFromTokenizer; } })); -Object.defineProperty(exports, "orderTags", ({ enumerable: true, get: function () { return core_1.orderTags; } })); -Object.defineProperty(exports, "ratingToStars", ({ enumerable: true, get: function () { return core_1.ratingToStars; } })); -Object.defineProperty(exports, "selectCover", ({ enumerable: true, get: function () { return core_1.selectCover; } })); -/** - * Parse audio Stream - * @param stream - ReadableStream - * @param contentType - MIME-Type - * @param options - Parsing options - * @returns Metadata - */ -exports.parseNodeStream = mm.parseStream; -/** - * Parse Web API ReadableStream: https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream - * @param stream - ReadableStream (web stream according WTWG Streams Standard) - * @param fileInfo FileInfo object or MIME-Type - * @param options - Parsing options - * @returns Metadata - */ -async function parseReadableStream(stream, fileInfo, options) { - const ns = new readable_web_to_node_stream_1.ReadableWebToNodeStream(stream); - const res = await (0, exports.parseNodeStream)(ns, typeof fileInfo === 'string' ? { mimeType: fileInfo } : fileInfo, options); - await ns.close(); - return res; -} -exports.parseReadableStream = parseReadableStream; -/** - * Parse Web API File - * @param blob - Blob to parse - * @param options - Parsing options - * @returns Metadata - */ -async function parseBlob(blob, options) { - const fileInfo = { mimeType: blob.type, size: blob.size }; - if (blob instanceof File) { - fileInfo.path = blob.name; - } - const stream = (blob.stream ? blob.stream() : convertBlobToReadableStream(blob)); - return parseReadableStream(stream, { mimeType: blob.type, size: blob.size }, options); -} -exports.parseBlob = parseBlob; -/** - * Convert Blob to ReadableStream - * Fallback for Safari versions < 14.1 - * @param blob - */ -function convertBlobToReadableStream(blob) { - const fileReader = new FileReader(); - return new ReadableStream({ - start(controller) { - // The following function handles each data chunk - fileReader.onloadend = event => { - let data = event.target.result; - if (data instanceof ArrayBuffer) { - data = new Uint8Array(data); - } - controller.enqueue(data); - controller.close(); - }; - fileReader.onerror = error => { - controller.close(); - }; - fileReader.onabort = error => { - controller.close(); - }; - fileReader.readAsArrayBuffer(blob); - } - }); -} -/** - * Parse fetched file, using the Web Fetch API - * @param audioTrackUrl - URL to download the audio track from - * @param options - Parsing options - * @returns Metadata - */ -async function fetchFromUrl(audioTrackUrl, options) { - const response = await fetch(audioTrackUrl); - const fileInfo = { - size: parseInt(response.headers.get('Content-Length'), 10), - mimeType: response.headers.get('Content-Type') - }; - if (response.ok) { - if (response.body) { - const res = await parseReadableStream(response.body, fileInfo, options); - debug('Closing HTTP-readable-stream...'); - if (!response.body.locked) { // Prevent error in Firefox - await response.body.cancel(); - } - debug('HTTP-readable-stream closed.'); - return res; - } - else { - // Fall back on Blob - return parseBlob(await response.blob(), options); - } - } - else { - throw new Error(`HTTP error status=${response.status}: ${response.statusText}`); - } -} -exports.fetchFromUrl = fetchFromUrl; - - -/***/ }), - -/***/ 4927: -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - - -/** - * Module exports. - */ - -module.exports = deprecate; - -/** - * Mark that a method should not be used. - * Returns a modified function which warns once by default. - * - * If `localStorage.noDeprecation = true` is set, then it is a no-op. - * - * If `localStorage.throwDeprecation = true` is set, then deprecated functions - * will throw an Error when invoked. - * - * If `localStorage.traceDeprecation = true` is set, then deprecated functions - * will invoke `console.trace()` instead of `console.error()`. - * - * @param {Function} fn - the function to deprecate - * @param {String} msg - the string to print to the console when `fn` is invoked - * @returns {Function} a new "deprecated" version of `fn` - * @api public - */ - -function deprecate (fn, msg) { - if (config('noDeprecation')) { - return fn; - } - - var warned = false; - function deprecated() { - if (!warned) { - if (config('throwDeprecation')) { - throw new Error(msg); - } else if (config('traceDeprecation')) { - console.trace(msg); - } else { - console.warn(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } - - return deprecated; -} - -/** - * Checks `localStorage` for boolean values for the given `name`. - * - * @param {String} name - * @returns {Boolean} - * @api private - */ - -function config (name) { - // accessing global.localStorage can trigger a DOMException in sandboxed iframes - try { - if (!__webpack_require__.g.localStorage) return false; - } catch (_) { - return false; - } - var val = __webpack_require__.g.localStorage[name]; - if (null == val) return false; - return String(val).toLowerCase() === 'true'; -} - - -/***/ }), - -/***/ 2361: -/***/ (() => { - -/* (ignored) */ - -/***/ }), - -/***/ 4616: -/***/ (() => { - -/* (ignored) */ - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/global */ -/******/ (() => { -/******/ __webpack_require__.g = (function() { -/******/ if (typeof globalThis === 'object') return globalThis; -/******/ try { -/******/ return this || new Function('return this')(); -/******/ } catch (e) { -/******/ if (typeof window === 'object') return window; -/******/ } -/******/ })(); -/******/ })(); -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __webpack_require__(9620); -/******/ -/******/ return __webpack_exports__; -/******/ })() -; -}); \ No newline at end of file diff --git a/src/util/audio.ts b/src/util/audio.ts index 0ce63fc8f..8aaaa4d2f 100644 --- a/src/util/audio.ts +++ b/src/util/audio.ts @@ -1,3 +1,5 @@ +import { fetchBlob } from './files'; + type AudioMetadata = { title?: string; performer?: string; @@ -6,8 +8,9 @@ type AudioMetadata = { }; export async function parseAudioMetadata(url: string): Promise { - const { fetchFromUrl, selectCover } = await import('../lib/music-metadata-browser'); - const metadata = await fetchFromUrl(url); + const { parseBlob, selectCover } = await import('music-metadata'); + const blob = await fetchBlob(url); + const metadata = await parseBlob(blob); const { common: { title, artist, picture }, format: { duration } } = metadata; const cover = selectCover(picture);