@agentdocumentformat/cli 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +45 -0
- package/dist/adf.mjs +162 -0
- package/dist/chunks/APEv2Parser-2CNNHMXV.mjs +22 -0
- package/dist/chunks/AiffParser-7BR4RL6G.mjs +162 -0
- package/dist/chunks/App-L5L37JI5.mjs +16747 -0
- package/dist/chunks/AsfParser-VVRSLFOM.mjs +538 -0
- package/dist/chunks/DsdiffParser-CMD4AX7A.mjs +156 -0
- package/dist/chunks/DsfParser-UOGZDS2M.mjs +94 -0
- package/dist/chunks/FlacParser-HB3T3CD4.mjs +23 -0
- package/dist/chunks/MP4Parser-66HBRUSX.mjs +973 -0
- package/dist/chunks/MatroskaParser-J3HUIMEW.mjs +579 -0
- package/dist/chunks/MpegParser-YW6LIUEW.mjs +442 -0
- package/dist/chunks/MusepackParser-PAUSXP7D.mjs +252 -0
- package/dist/chunks/OggParser-NUBV3GWC.mjs +359 -0
- package/dist/chunks/WavPackParser-WQAGT7TC.mjs +171 -0
- package/dist/chunks/WaveParser-EWLQVDX4.mjs +238 -0
- package/dist/chunks/adf-schema-JRU2BTOG.mjs +62 -0
- package/dist/chunks/build-QF5W473T.mjs +60 -0
- package/dist/chunks/chatgpt-subscription-BQGWYZXE.mjs +23 -0
- package/dist/chunks/chunk-2DIECGFL.mjs +6 -0
- package/dist/chunks/chunk-2NAP2ZF7.mjs +60 -0
- package/dist/chunks/chunk-3AT7IIP7.mjs +25696 -0
- package/dist/chunks/chunk-3GNIDM53.mjs +35 -0
- package/dist/chunks/chunk-3M4ZPOA3.mjs +1477 -0
- package/dist/chunks/chunk-4MQPTCXY.mjs +510 -0
- package/dist/chunks/chunk-5PO5PKRV.mjs +366 -0
- package/dist/chunks/chunk-5QU5VY7N.mjs +52 -0
- package/dist/chunks/chunk-5W7KES6P.mjs +436 -0
- package/dist/chunks/chunk-62NE4LG4.mjs +61 -0
- package/dist/chunks/chunk-64OKE4X3.mjs +45 -0
- package/dist/chunks/chunk-6GJ4QHRI.mjs +1278 -0
- package/dist/chunks/chunk-6VQEXLE2.mjs +144 -0
- package/dist/chunks/chunk-6XUV6EK6.mjs +41 -0
- package/dist/chunks/chunk-776TSXEP.mjs +43 -0
- package/dist/chunks/chunk-7CV2SA3H.mjs +285 -0
- package/dist/chunks/chunk-7MTRVW2U.mjs +3103 -0
- package/dist/chunks/chunk-7N2R2VCG.mjs +1434 -0
- package/dist/chunks/chunk-7T2YMTWL.mjs +374 -0
- package/dist/chunks/chunk-7XYNI52E.mjs +149 -0
- package/dist/chunks/chunk-APHX6HSV.mjs +7731 -0
- package/dist/chunks/chunk-APRU6PHC.mjs +40 -0
- package/dist/chunks/chunk-AUYKRQPJ.mjs +499 -0
- package/dist/chunks/chunk-DXWDD5XJ.mjs +136 -0
- package/dist/chunks/chunk-EWL5FG4I.mjs +39 -0
- package/dist/chunks/chunk-EYX2YLJW.mjs +117 -0
- package/dist/chunks/chunk-F5ELW46V.mjs +27 -0
- package/dist/chunks/chunk-G426FACA.mjs +49 -0
- package/dist/chunks/chunk-GEKSJHIV.mjs +2472 -0
- package/dist/chunks/chunk-HBUENVQL.mjs +570 -0
- package/dist/chunks/chunk-HPVFJYXR.mjs +112 -0
- package/dist/chunks/chunk-HWLWPXQ7.mjs +721 -0
- package/dist/chunks/chunk-I2HJYHFT.mjs +665 -0
- package/dist/chunks/chunk-I3UYSITV.mjs +68 -0
- package/dist/chunks/chunk-IC4JDZCI.mjs +3864 -0
- package/dist/chunks/chunk-IHDDCZBS.mjs +112 -0
- package/dist/chunks/chunk-IIGMZHQQ.mjs +10416 -0
- package/dist/chunks/chunk-KWFOS5WC.mjs +41 -0
- package/dist/chunks/chunk-LAZIXV2F.mjs +5290 -0
- package/dist/chunks/chunk-LFMB4PAA.mjs +10814 -0
- package/dist/chunks/chunk-M2RX3S2T.mjs +49 -0
- package/dist/chunks/chunk-M3WPIJYM.mjs +65 -0
- package/dist/chunks/chunk-NBTUWMGP.mjs +263 -0
- package/dist/chunks/chunk-NGK6PVSF.mjs +2676 -0
- package/dist/chunks/chunk-NZ7JTHEO.mjs +85 -0
- package/dist/chunks/chunk-OQN33RGQ.mjs +52 -0
- package/dist/chunks/chunk-RIX34QHC.mjs +2935 -0
- package/dist/chunks/chunk-SGUTYISF.mjs +16 -0
- package/dist/chunks/chunk-SLJ5L7PY.mjs +1473 -0
- package/dist/chunks/chunk-SLUKGXKH.mjs +68 -0
- package/dist/chunks/chunk-TMT32MXT.mjs +419 -0
- package/dist/chunks/chunk-UYY5M2PB.mjs +151 -0
- package/dist/chunks/chunk-VAUOM3IN.mjs +298 -0
- package/dist/chunks/chunk-VMHTYDH4.mjs +172 -0
- package/dist/chunks/chunk-VZS54AA5.mjs +200 -0
- package/dist/chunks/chunk-WFQUVXML.mjs +295 -0
- package/dist/chunks/chunk-X34PDRUH.mjs +809 -0
- package/dist/chunks/chunk-XNPZBLYL.mjs +33 -0
- package/dist/chunks/chunk-XX7OSWTO.mjs +157 -0
- package/dist/chunks/chunk-XYTWGHFS.mjs +600 -0
- package/dist/chunks/chunk-XYV3VCIX.mjs +336 -0
- package/dist/chunks/chunk-Y5ZLKFLE.mjs +1469 -0
- package/dist/chunks/chunk-ZJKXHM4Q.mjs +230 -0
- package/dist/chunks/cli-TCMBNZF6.mjs +1030 -0
- package/dist/chunks/commands-DTEKM4ZL.mjs +20 -0
- package/dist/chunks/daemon-ZC3FZ2P4.mjs +112449 -0
- package/dist/chunks/daemon-control-WDX7PMTC.mjs +300 -0
- package/dist/chunks/daemon-token-WRSULP7G.mjs +23 -0
- package/dist/chunks/devtools-H7CI2ZVG.mjs +85 -0
- package/dist/chunks/discord-IWDQJA7A.mjs +70588 -0
- package/dist/chunks/dist-C57KYFS2.mjs +4952 -0
- package/dist/chunks/dist-I3XBAGDL.mjs +11 -0
- package/dist/chunks/email-V4Q4VJON.mjs +58679 -0
- package/dist/chunks/environment-NX277MQG.mjs +15 -0
- package/dist/chunks/grok-subscription-4PYX7TBF.mjs +19 -0
- package/dist/chunks/layout-EPJQNFAI.mjs +22 -0
- package/dist/chunks/lib-N7FCZWKH.mjs +4038 -0
- package/dist/chunks/open-OTQDGDH5.mjs +36 -0
- package/dist/chunks/parser-JVY2PWSM.mjs +19 -0
- package/dist/chunks/pipeline-executor-BHBSJX2K.mjs +19 -0
- package/dist/chunks/react-IUIDQ5LX.mjs +11 -0
- package/dist/chunks/screen-54BUTYCW.mjs +27 -0
- package/dist/chunks/slack-3L5QTDZX.mjs +8113 -0
- package/dist/chunks/store-WR7TZJZS.mjs +32 -0
- package/dist/chunks/telegram-5ISVFBV3.mjs +14918 -0
- package/dist/chunks/terminal-O5WO7C5U.mjs +48 -0
- package/dist/chunks/theme-NORU4J74.mjs +20 -0
- package/dist/chunks/themes-F2FKU7CP.mjs +23 -0
- package/dist/chunks/token-6G3HCMNX.mjs +54 -0
- package/dist/chunks/token-util-UXYSDQIW.mjs +12 -0
- package/dist/chunks/tui-ODVYUIMT.mjs +197 -0
- package/dist/chunks/welcome-XHXFV7SH.mjs +32 -0
- package/dist/chunks/whatsapp-XSAMNGPJ.mjs +85412 -0
- package/dist/chunks/xterm-headless-YF53XWXE.mjs +3353 -0
- package/package.json +53 -0
- package/resources/wasm/coreutils.LICENSE +18 -0
- package/resources/wasm/coreutils.wasm +0 -0
|
@@ -0,0 +1,4038 @@
|
|
|
1
|
+
import { createRequire as __adfCreateRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __adfFileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __adfDirname } from 'node:path';
|
|
4
|
+
const require = __adfCreateRequire(import.meta.url);
|
|
5
|
+
const __filename = __adfFileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __adfDirname(__filename);
|
|
7
|
+
import "./chunk-2DIECGFL.mjs";
|
|
8
|
+
import {
|
|
9
|
+
TrackType,
|
|
10
|
+
TrackTypeValueToKeyMap
|
|
11
|
+
} from "./chunk-EWL5FG4I.mjs";
|
|
12
|
+
import {
|
|
13
|
+
hasID3v1Header
|
|
14
|
+
} from "./chunk-VAUOM3IN.mjs";
|
|
15
|
+
import {
|
|
16
|
+
LyricsContentType,
|
|
17
|
+
TimestampFormat
|
|
18
|
+
} from "./chunk-DXWDD5XJ.mjs";
|
|
19
|
+
import {
|
|
20
|
+
APEv2Parser
|
|
21
|
+
} from "./chunk-NBTUWMGP.mjs";
|
|
22
|
+
import {
|
|
23
|
+
decodeString,
|
|
24
|
+
getUintBE,
|
|
25
|
+
toRatio
|
|
26
|
+
} from "./chunk-XX7OSWTO.mjs";
|
|
27
|
+
import {
|
|
28
|
+
EndOfStreamError,
|
|
29
|
+
fromBlob,
|
|
30
|
+
fromBuffer,
|
|
31
|
+
fromFile,
|
|
32
|
+
fromStream,
|
|
33
|
+
fromWebStream
|
|
34
|
+
} from "./chunk-HBUENVQL.mjs";
|
|
35
|
+
import {
|
|
36
|
+
CouldNotDetermineFileTypeError,
|
|
37
|
+
FieldDecodingError,
|
|
38
|
+
INT32_BE,
|
|
39
|
+
InternalParserError,
|
|
40
|
+
StringType,
|
|
41
|
+
UINT16_BE,
|
|
42
|
+
UINT16_LE,
|
|
43
|
+
UINT32_BE,
|
|
44
|
+
UINT32_LE,
|
|
45
|
+
UINT64_LE,
|
|
46
|
+
UINT8,
|
|
47
|
+
UnsupportedFileTypeError,
|
|
48
|
+
makeParseError,
|
|
49
|
+
makeUnexpectedFileContentError,
|
|
50
|
+
textDecode
|
|
51
|
+
} from "./chunk-I2HJYHFT.mjs";
|
|
52
|
+
import {
|
|
53
|
+
require_src
|
|
54
|
+
} from "./chunk-AUYKRQPJ.mjs";
|
|
55
|
+
import "./chunk-NZ7JTHEO.mjs";
|
|
56
|
+
import {
|
|
57
|
+
__commonJS,
|
|
58
|
+
__toESM
|
|
59
|
+
} from "./chunk-M2RX3S2T.mjs";
|
|
60
|
+
|
|
61
|
+
// node_modules/music-metadata/node_modules/content-type/dist/index.js
|
|
62
|
+
var require_dist = __commonJS({
|
|
63
|
+
"node_modules/music-metadata/node_modules/content-type/dist/index.js"(exports) {
|
|
64
|
+
"use strict";
|
|
65
|
+
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
66
|
+
exports.format = format;
|
|
67
|
+
exports.parse = parse2;
|
|
68
|
+
var TEXT_REGEXP = /^[\u0009\u0020-\u007e\u0080-\u00ff]*$/, TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/, QUOTE_REGEXP = /[\\"]/g, TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/, NullObject = /* @__PURE__ */ (() => {
|
|
69
|
+
let C = function() {
|
|
70
|
+
};
|
|
71
|
+
return C.prototype = /* @__PURE__ */ Object.create(null), C;
|
|
72
|
+
})();
|
|
73
|
+
function format(obj) {
|
|
74
|
+
let { type, parameters } = obj;
|
|
75
|
+
if (!type || !TYPE_REGEXP.test(type))
|
|
76
|
+
throw new TypeError(`Invalid type: ${type}`);
|
|
77
|
+
let result = type;
|
|
78
|
+
if (parameters)
|
|
79
|
+
for (let param of Object.keys(parameters)) {
|
|
80
|
+
if (!TOKEN_REGEXP.test(param))
|
|
81
|
+
throw new TypeError(`Invalid parameter name: ${param}`);
|
|
82
|
+
result += `; ${param}=${qstring(parameters[param])}`;
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
function parse2(header, options) {
|
|
87
|
+
let len = header.length, index = skipOWS(header, 0, len), valueStart = index;
|
|
88
|
+
index = skipValue(header, index, len);
|
|
89
|
+
let valueEnd = trailingOWS(header, valueStart, index), type = header.slice(valueStart, valueEnd).toLowerCase(), parameters = options?.parameters === !1 ? new NullObject() : parseParameters(header, index, len);
|
|
90
|
+
return { type, parameters };
|
|
91
|
+
}
|
|
92
|
+
var SP = 32, HTAB = 9, SEMI = 59, EQ = 61, DQUOTE = 34, BSLASH = 92;
|
|
93
|
+
function parseParameters(header, index, len) {
|
|
94
|
+
let parameters = new NullObject();
|
|
95
|
+
parameter: for (; index < len; ) {
|
|
96
|
+
index = skipOWS(header, index + 1, len);
|
|
97
|
+
let keyStart = index;
|
|
98
|
+
for (; index < len; ) {
|
|
99
|
+
let code = header.charCodeAt(index);
|
|
100
|
+
if (code === SEMI)
|
|
101
|
+
continue parameter;
|
|
102
|
+
if (code === EQ) {
|
|
103
|
+
let keyEnd = trailingOWS(header, keyStart, index), key = header.slice(keyStart, keyEnd).toLowerCase();
|
|
104
|
+
if (index = skipOWS(header, index + 1, len), index < len && header.charCodeAt(index) === DQUOTE) {
|
|
105
|
+
index++;
|
|
106
|
+
let value = "";
|
|
107
|
+
for (; index < len; ) {
|
|
108
|
+
let code2 = header.charCodeAt(index++);
|
|
109
|
+
if (code2 === DQUOTE) {
|
|
110
|
+
index = skipValue(header, index, len), parameters[key] === void 0 && (parameters[key] = value);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
if (code2 === BSLASH && index < len) {
|
|
114
|
+
value += header[index++];
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
value += String.fromCharCode(code2);
|
|
118
|
+
}
|
|
119
|
+
continue parameter;
|
|
120
|
+
}
|
|
121
|
+
let valueStart = index;
|
|
122
|
+
if (index = skipValue(header, index, len), parameters[key] === void 0) {
|
|
123
|
+
let valueEnd = trailingOWS(header, valueStart, index);
|
|
124
|
+
parameters[key] = header.slice(valueStart, valueEnd);
|
|
125
|
+
}
|
|
126
|
+
continue parameter;
|
|
127
|
+
}
|
|
128
|
+
index++;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return parameters;
|
|
132
|
+
}
|
|
133
|
+
function skipValue(str, index, len) {
|
|
134
|
+
for (; index < len && str.charCodeAt(index) !== SEMI; )
|
|
135
|
+
index++;
|
|
136
|
+
return index;
|
|
137
|
+
}
|
|
138
|
+
function skipOWS(header, index, len) {
|
|
139
|
+
for (; index < len; ) {
|
|
140
|
+
let char = header.charCodeAt(index);
|
|
141
|
+
if (char !== SP && char !== HTAB)
|
|
142
|
+
break;
|
|
143
|
+
index++;
|
|
144
|
+
}
|
|
145
|
+
return index;
|
|
146
|
+
}
|
|
147
|
+
function trailingOWS(header, start, end) {
|
|
148
|
+
for (; end > start; ) {
|
|
149
|
+
let char = header.charCodeAt(end - 1);
|
|
150
|
+
if (char !== SP && char !== HTAB)
|
|
151
|
+
break;
|
|
152
|
+
end--;
|
|
153
|
+
}
|
|
154
|
+
return end;
|
|
155
|
+
}
|
|
156
|
+
function qstring(str) {
|
|
157
|
+
if (TOKEN_REGEXP.test(str))
|
|
158
|
+
return str;
|
|
159
|
+
if (TEXT_REGEXP.test(str))
|
|
160
|
+
return `"${str.replace(QUOTE_REGEXP, "\\$&")}"`;
|
|
161
|
+
throw new TypeError(`Invalid parameter value: ${str}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// node_modules/music-metadata/lib/index.js
|
|
167
|
+
var import_debug4 = __toESM(require_src(), 1);
|
|
168
|
+
|
|
169
|
+
// node_modules/@tokenizer/inflate/lib/ZipHandler.js
|
|
170
|
+
var import_debug = __toESM(require_src(), 1);
|
|
171
|
+
|
|
172
|
+
// node_modules/@tokenizer/inflate/lib/ZipToken.js
|
|
173
|
+
var Signature = {
|
|
174
|
+
LocalFileHeader: 67324752,
|
|
175
|
+
DataDescriptor: 134695760,
|
|
176
|
+
CentralFileHeader: 33639248,
|
|
177
|
+
EndOfCentralDirectory: 101010256
|
|
178
|
+
}, DataDescriptor = {
|
|
179
|
+
get(array) {
|
|
180
|
+
return {
|
|
181
|
+
signature: UINT32_LE.get(array, 0),
|
|
182
|
+
compressedSize: UINT32_LE.get(array, 8),
|
|
183
|
+
uncompressedSize: UINT32_LE.get(array, 12)
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
len: 16
|
|
187
|
+
}, LocalFileHeaderToken = {
|
|
188
|
+
get(array) {
|
|
189
|
+
let flags = UINT16_LE.get(array, 6);
|
|
190
|
+
return {
|
|
191
|
+
signature: UINT32_LE.get(array, 0),
|
|
192
|
+
minVersion: UINT16_LE.get(array, 4),
|
|
193
|
+
dataDescriptor: !!(flags & 8),
|
|
194
|
+
compressedMethod: UINT16_LE.get(array, 8),
|
|
195
|
+
compressedSize: UINT32_LE.get(array, 18),
|
|
196
|
+
uncompressedSize: UINT32_LE.get(array, 22),
|
|
197
|
+
filenameLength: UINT16_LE.get(array, 26),
|
|
198
|
+
extraFieldLength: UINT16_LE.get(array, 28),
|
|
199
|
+
filename: null
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
len: 30
|
|
203
|
+
}, EndOfCentralDirectoryRecordToken = {
|
|
204
|
+
get(array) {
|
|
205
|
+
return {
|
|
206
|
+
signature: UINT32_LE.get(array, 0),
|
|
207
|
+
nrOfThisDisk: UINT16_LE.get(array, 4),
|
|
208
|
+
nrOfThisDiskWithTheStart: UINT16_LE.get(array, 6),
|
|
209
|
+
nrOfEntriesOnThisDisk: UINT16_LE.get(array, 8),
|
|
210
|
+
nrOfEntriesOfSize: UINT16_LE.get(array, 10),
|
|
211
|
+
sizeOfCd: UINT32_LE.get(array, 12),
|
|
212
|
+
offsetOfStartOfCd: UINT32_LE.get(array, 16),
|
|
213
|
+
zipFileCommentLength: UINT16_LE.get(array, 20)
|
|
214
|
+
};
|
|
215
|
+
},
|
|
216
|
+
len: 22
|
|
217
|
+
}, FileHeader = {
|
|
218
|
+
get(array) {
|
|
219
|
+
let flags = UINT16_LE.get(array, 8);
|
|
220
|
+
return {
|
|
221
|
+
signature: UINT32_LE.get(array, 0),
|
|
222
|
+
minVersion: UINT16_LE.get(array, 6),
|
|
223
|
+
dataDescriptor: !!(flags & 8),
|
|
224
|
+
compressedMethod: UINT16_LE.get(array, 10),
|
|
225
|
+
compressedSize: UINT32_LE.get(array, 20),
|
|
226
|
+
uncompressedSize: UINT32_LE.get(array, 24),
|
|
227
|
+
filenameLength: UINT16_LE.get(array, 28),
|
|
228
|
+
extraFieldLength: UINT16_LE.get(array, 30),
|
|
229
|
+
fileCommentLength: UINT16_LE.get(array, 32),
|
|
230
|
+
relativeOffsetOfLocalHeader: UINT32_LE.get(array, 42),
|
|
231
|
+
filename: null
|
|
232
|
+
};
|
|
233
|
+
},
|
|
234
|
+
len: 46
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// node_modules/@tokenizer/inflate/lib/ZipHandler.js
|
|
238
|
+
function signatureToArray(signature) {
|
|
239
|
+
let signatureBytes = new Uint8Array(UINT32_LE.len);
|
|
240
|
+
return UINT32_LE.put(signatureBytes, 0, signature), signatureBytes;
|
|
241
|
+
}
|
|
242
|
+
var debug = (0, import_debug.default)("tokenizer:inflate"), syncBufferSize = 256 * 1024, ddSignatureArray = signatureToArray(Signature.DataDescriptor), eocdSignatureBytes = signatureToArray(Signature.EndOfCentralDirectory), ZipHandler = class _ZipHandler {
|
|
243
|
+
constructor(tokenizer) {
|
|
244
|
+
this.tokenizer = tokenizer, this.syncBuffer = new Uint8Array(syncBufferSize);
|
|
245
|
+
}
|
|
246
|
+
async isZip() {
|
|
247
|
+
return await this.peekSignature() === Signature.LocalFileHeader;
|
|
248
|
+
}
|
|
249
|
+
peekSignature() {
|
|
250
|
+
return this.tokenizer.peekToken(UINT32_LE);
|
|
251
|
+
}
|
|
252
|
+
async findEndOfCentralDirectoryLocator() {
|
|
253
|
+
let randomReadTokenizer = this.tokenizer, chunkLength = Math.min(16 * 1024, randomReadTokenizer.fileInfo.size), buffer = this.syncBuffer.subarray(0, chunkLength);
|
|
254
|
+
await this.tokenizer.readBuffer(buffer, { position: randomReadTokenizer.fileInfo.size - chunkLength });
|
|
255
|
+
for (let i = buffer.length - 4; i >= 0; i--)
|
|
256
|
+
if (buffer[i] === eocdSignatureBytes[0] && buffer[i + 1] === eocdSignatureBytes[1] && buffer[i + 2] === eocdSignatureBytes[2] && buffer[i + 3] === eocdSignatureBytes[3])
|
|
257
|
+
return randomReadTokenizer.fileInfo.size - chunkLength + i;
|
|
258
|
+
return -1;
|
|
259
|
+
}
|
|
260
|
+
async readCentralDirectory() {
|
|
261
|
+
if (!this.tokenizer.supportsRandomAccess()) {
|
|
262
|
+
debug("Cannot reading central-directory without random-read support");
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
debug("Reading central-directory...");
|
|
266
|
+
let pos = this.tokenizer.position, offset = await this.findEndOfCentralDirectoryLocator();
|
|
267
|
+
if (offset > 0) {
|
|
268
|
+
debug("Central-directory 32-bit signature found");
|
|
269
|
+
let eocdHeader = await this.tokenizer.readToken(EndOfCentralDirectoryRecordToken, offset), files = [];
|
|
270
|
+
this.tokenizer.setPosition(eocdHeader.offsetOfStartOfCd);
|
|
271
|
+
for (let n = 0; n < eocdHeader.nrOfEntriesOfSize; ++n) {
|
|
272
|
+
let entry = await this.tokenizer.readToken(FileHeader);
|
|
273
|
+
if (entry.signature !== Signature.CentralFileHeader)
|
|
274
|
+
throw new Error("Expected Central-File-Header signature");
|
|
275
|
+
entry.filename = await this.tokenizer.readToken(new StringType(entry.filenameLength, "utf-8")), await this.tokenizer.ignore(entry.extraFieldLength), await this.tokenizer.ignore(entry.fileCommentLength), files.push(entry), debug(`Add central-directory file-entry: n=${n + 1}/${files.length}: filename=${files[n].filename}`);
|
|
276
|
+
}
|
|
277
|
+
return this.tokenizer.setPosition(pos), files;
|
|
278
|
+
}
|
|
279
|
+
this.tokenizer.setPosition(pos);
|
|
280
|
+
}
|
|
281
|
+
async unzip(fileCb) {
|
|
282
|
+
let entries = await this.readCentralDirectory();
|
|
283
|
+
if (entries)
|
|
284
|
+
return this.iterateOverCentralDirectory(entries, fileCb);
|
|
285
|
+
let stop = !1;
|
|
286
|
+
do {
|
|
287
|
+
let zipHeader = await this.readLocalFileHeader();
|
|
288
|
+
if (!zipHeader)
|
|
289
|
+
break;
|
|
290
|
+
let next = fileCb(zipHeader);
|
|
291
|
+
stop = !!next.stop;
|
|
292
|
+
let fileData;
|
|
293
|
+
if (await this.tokenizer.ignore(zipHeader.extraFieldLength), zipHeader.dataDescriptor && zipHeader.compressedSize === 0) {
|
|
294
|
+
let chunks = [], len = syncBufferSize;
|
|
295
|
+
debug("Compressed-file-size unknown, scanning for next data-descriptor-signature....");
|
|
296
|
+
let nextHeaderIndex = -1;
|
|
297
|
+
for (; nextHeaderIndex < 0 && len === syncBufferSize; ) {
|
|
298
|
+
len = await this.tokenizer.peekBuffer(this.syncBuffer, { mayBeLess: !0 }), nextHeaderIndex = indexOf(this.syncBuffer.subarray(0, len), ddSignatureArray);
|
|
299
|
+
let size = nextHeaderIndex >= 0 ? nextHeaderIndex : len;
|
|
300
|
+
if (next.handler) {
|
|
301
|
+
let data = new Uint8Array(size);
|
|
302
|
+
await this.tokenizer.readBuffer(data), chunks.push(data);
|
|
303
|
+
} else
|
|
304
|
+
await this.tokenizer.ignore(size);
|
|
305
|
+
}
|
|
306
|
+
debug(`Found data-descriptor-signature at pos=${this.tokenizer.position}`), next.handler && await this.inflate(zipHeader, mergeArrays(chunks), next.handler);
|
|
307
|
+
} else
|
|
308
|
+
next.handler ? (debug(`Reading compressed-file-data: ${zipHeader.compressedSize} bytes`), fileData = new Uint8Array(zipHeader.compressedSize), await this.tokenizer.readBuffer(fileData), await this.inflate(zipHeader, fileData, next.handler)) : (debug(`Ignoring compressed-file-data: ${zipHeader.compressedSize} bytes`), await this.tokenizer.ignore(zipHeader.compressedSize));
|
|
309
|
+
if (debug(`Reading data-descriptor at pos=${this.tokenizer.position}`), zipHeader.dataDescriptor && (await this.tokenizer.readToken(DataDescriptor)).signature !== 134695760)
|
|
310
|
+
throw new Error(`Expected data-descriptor-signature at position ${this.tokenizer.position - DataDescriptor.len}`);
|
|
311
|
+
} while (!stop);
|
|
312
|
+
}
|
|
313
|
+
async iterateOverCentralDirectory(entries, fileCb) {
|
|
314
|
+
for (let fileHeader of entries) {
|
|
315
|
+
let next = fileCb(fileHeader);
|
|
316
|
+
if (next.handler) {
|
|
317
|
+
this.tokenizer.setPosition(fileHeader.relativeOffsetOfLocalHeader);
|
|
318
|
+
let zipHeader = await this.readLocalFileHeader();
|
|
319
|
+
if (zipHeader) {
|
|
320
|
+
await this.tokenizer.ignore(zipHeader.extraFieldLength);
|
|
321
|
+
let fileData = new Uint8Array(fileHeader.compressedSize);
|
|
322
|
+
await this.tokenizer.readBuffer(fileData), await this.inflate(zipHeader, fileData, next.handler);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (next.stop)
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
async inflate(zipHeader, fileData, cb) {
|
|
330
|
+
if (zipHeader.compressedMethod === 0)
|
|
331
|
+
return cb(fileData);
|
|
332
|
+
if (zipHeader.compressedMethod !== 8)
|
|
333
|
+
throw new Error(`Unsupported ZIP compression method: ${zipHeader.compressedMethod}`);
|
|
334
|
+
debug(`Decompress filename=${zipHeader.filename}, compressed-size=${fileData.length}`);
|
|
335
|
+
let uncompressedData = await _ZipHandler.decompressDeflateRaw(fileData);
|
|
336
|
+
return cb(uncompressedData);
|
|
337
|
+
}
|
|
338
|
+
static async decompressDeflateRaw(data) {
|
|
339
|
+
let input = new ReadableStream({
|
|
340
|
+
start(controller) {
|
|
341
|
+
controller.enqueue(data), controller.close();
|
|
342
|
+
}
|
|
343
|
+
}), ds = new DecompressionStream("deflate-raw"), output = input.pipeThrough(ds);
|
|
344
|
+
try {
|
|
345
|
+
let buffer = await new Response(output).arrayBuffer();
|
|
346
|
+
return new Uint8Array(buffer);
|
|
347
|
+
} catch (err) {
|
|
348
|
+
let message = err instanceof Error ? `Failed to deflate ZIP entry: ${err.message}` : "Unknown decompression error in ZIP entry";
|
|
349
|
+
throw new TypeError(message);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async readLocalFileHeader() {
|
|
353
|
+
let signature = await this.tokenizer.peekToken(UINT32_LE);
|
|
354
|
+
if (signature === Signature.LocalFileHeader) {
|
|
355
|
+
let header = await this.tokenizer.readToken(LocalFileHeaderToken);
|
|
356
|
+
return header.filename = await this.tokenizer.readToken(new StringType(header.filenameLength, "utf-8")), header;
|
|
357
|
+
}
|
|
358
|
+
if (signature === Signature.CentralFileHeader)
|
|
359
|
+
return !1;
|
|
360
|
+
throw signature === 3759263696 ? new Error("Encrypted ZIP") : new Error("Unexpected signature");
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
function indexOf(buffer, portion) {
|
|
364
|
+
let bufferLength = buffer.length, portionLength = portion.length;
|
|
365
|
+
if (portionLength > bufferLength)
|
|
366
|
+
return -1;
|
|
367
|
+
for (let i = 0; i <= bufferLength - portionLength; i++) {
|
|
368
|
+
let found = !0;
|
|
369
|
+
for (let j = 0; j < portionLength; j++)
|
|
370
|
+
if (buffer[i + j] !== portion[j]) {
|
|
371
|
+
found = !1;
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
if (found)
|
|
375
|
+
return i;
|
|
376
|
+
}
|
|
377
|
+
return -1;
|
|
378
|
+
}
|
|
379
|
+
function mergeArrays(chunks) {
|
|
380
|
+
let totalLength = chunks.reduce((acc, curr) => acc + curr.length, 0), mergedArray = new Uint8Array(totalLength), offset = 0;
|
|
381
|
+
for (let chunk of chunks)
|
|
382
|
+
mergedArray.set(chunk, offset), offset += chunk.length;
|
|
383
|
+
return mergedArray;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// node_modules/@tokenizer/inflate/lib/GzipHandler.js
|
|
387
|
+
var GzipHandler = class {
|
|
388
|
+
constructor(tokenizer) {
|
|
389
|
+
this.tokenizer = tokenizer;
|
|
390
|
+
}
|
|
391
|
+
inflate() {
|
|
392
|
+
let tokenizer = this.tokenizer;
|
|
393
|
+
return new ReadableStream({
|
|
394
|
+
async pull(controller) {
|
|
395
|
+
let buffer = new Uint8Array(1024), size = await tokenizer.readBuffer(buffer, { mayBeLess: !0 });
|
|
396
|
+
if (size === 0) {
|
|
397
|
+
controller.close();
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
controller.enqueue(buffer.subarray(0, size));
|
|
401
|
+
}
|
|
402
|
+
}).pipeThrough(new DecompressionStream("gzip"));
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// node_modules/file-type/util.js
|
|
407
|
+
function stringToBytes(string, encoding) {
|
|
408
|
+
if (encoding === "utf-16le") {
|
|
409
|
+
let bytes = [];
|
|
410
|
+
for (let index = 0; index < string.length; index++) {
|
|
411
|
+
let code = string.charCodeAt(index);
|
|
412
|
+
bytes.push(code & 255, code >> 8 & 255);
|
|
413
|
+
}
|
|
414
|
+
return bytes;
|
|
415
|
+
}
|
|
416
|
+
if (encoding === "utf-16be") {
|
|
417
|
+
let bytes = [];
|
|
418
|
+
for (let index = 0; index < string.length; index++) {
|
|
419
|
+
let code = string.charCodeAt(index);
|
|
420
|
+
bytes.push(code >> 8 & 255, code & 255);
|
|
421
|
+
}
|
|
422
|
+
return bytes;
|
|
423
|
+
}
|
|
424
|
+
return [...string].map((character) => character.charCodeAt(0));
|
|
425
|
+
}
|
|
426
|
+
function tarHeaderChecksumMatches(arrayBuffer, offset = 0) {
|
|
427
|
+
let readSum = Number.parseInt(new StringType(6).get(arrayBuffer, 148).replace(/\0.*$/, "").trim(), 8);
|
|
428
|
+
if (Number.isNaN(readSum))
|
|
429
|
+
return !1;
|
|
430
|
+
let sum = 256;
|
|
431
|
+
for (let index = offset; index < offset + 148; index++)
|
|
432
|
+
sum += arrayBuffer[index];
|
|
433
|
+
for (let index = offset + 156; index < offset + 512; index++)
|
|
434
|
+
sum += arrayBuffer[index];
|
|
435
|
+
return readSum === sum;
|
|
436
|
+
}
|
|
437
|
+
var uint32SyncSafeToken = {
|
|
438
|
+
get: (buffer, offset) => buffer[offset + 3] & 127 | buffer[offset + 2] << 7 | buffer[offset + 1] << 14 | buffer[offset] << 21,
|
|
439
|
+
len: 4
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
// node_modules/file-type/supported.js
|
|
443
|
+
var extensions = [
|
|
444
|
+
"jpg",
|
|
445
|
+
"png",
|
|
446
|
+
"apng",
|
|
447
|
+
"gif",
|
|
448
|
+
"webp",
|
|
449
|
+
"flif",
|
|
450
|
+
"xcf",
|
|
451
|
+
"cr2",
|
|
452
|
+
"cr3",
|
|
453
|
+
"orf",
|
|
454
|
+
"arw",
|
|
455
|
+
"dng",
|
|
456
|
+
"nef",
|
|
457
|
+
"rw2",
|
|
458
|
+
"raf",
|
|
459
|
+
"tif",
|
|
460
|
+
"bmp",
|
|
461
|
+
"icns",
|
|
462
|
+
"jxr",
|
|
463
|
+
"psd",
|
|
464
|
+
"indd",
|
|
465
|
+
"zip",
|
|
466
|
+
"tar",
|
|
467
|
+
"rar",
|
|
468
|
+
"gz",
|
|
469
|
+
"bz2",
|
|
470
|
+
"7z",
|
|
471
|
+
"dmg",
|
|
472
|
+
"mp4",
|
|
473
|
+
"mid",
|
|
474
|
+
"mkv",
|
|
475
|
+
"webm",
|
|
476
|
+
"mov",
|
|
477
|
+
"avi",
|
|
478
|
+
"mpg",
|
|
479
|
+
"mp2",
|
|
480
|
+
"mp3",
|
|
481
|
+
"m4a",
|
|
482
|
+
"oga",
|
|
483
|
+
"ogg",
|
|
484
|
+
"ogv",
|
|
485
|
+
"opus",
|
|
486
|
+
"flac",
|
|
487
|
+
"wav",
|
|
488
|
+
"spx",
|
|
489
|
+
"amr",
|
|
490
|
+
"pdf",
|
|
491
|
+
"epub",
|
|
492
|
+
"elf",
|
|
493
|
+
"macho",
|
|
494
|
+
"exe",
|
|
495
|
+
"swf",
|
|
496
|
+
"rtf",
|
|
497
|
+
"wasm",
|
|
498
|
+
"woff",
|
|
499
|
+
"woff2",
|
|
500
|
+
"eot",
|
|
501
|
+
"ttf",
|
|
502
|
+
"otf",
|
|
503
|
+
"ttc",
|
|
504
|
+
"ico",
|
|
505
|
+
"flv",
|
|
506
|
+
"ps",
|
|
507
|
+
"xz",
|
|
508
|
+
"sqlite",
|
|
509
|
+
"nes",
|
|
510
|
+
"crx",
|
|
511
|
+
"xpi",
|
|
512
|
+
"cab",
|
|
513
|
+
"deb",
|
|
514
|
+
"ar",
|
|
515
|
+
"rpm",
|
|
516
|
+
"Z",
|
|
517
|
+
"lz",
|
|
518
|
+
"cfb",
|
|
519
|
+
"mxf",
|
|
520
|
+
"mts",
|
|
521
|
+
"blend",
|
|
522
|
+
"bpg",
|
|
523
|
+
"docx",
|
|
524
|
+
"pptx",
|
|
525
|
+
"xlsx",
|
|
526
|
+
"3gp",
|
|
527
|
+
"3g2",
|
|
528
|
+
"j2c",
|
|
529
|
+
"jp2",
|
|
530
|
+
"jpm",
|
|
531
|
+
"jpx",
|
|
532
|
+
"mj2",
|
|
533
|
+
"aif",
|
|
534
|
+
"qcp",
|
|
535
|
+
"odt",
|
|
536
|
+
"ods",
|
|
537
|
+
"odp",
|
|
538
|
+
"xml",
|
|
539
|
+
"mobi",
|
|
540
|
+
"heic",
|
|
541
|
+
"cur",
|
|
542
|
+
"ktx",
|
|
543
|
+
"ape",
|
|
544
|
+
"wv",
|
|
545
|
+
"dcm",
|
|
546
|
+
"ics",
|
|
547
|
+
"glb",
|
|
548
|
+
"pcap",
|
|
549
|
+
"dsf",
|
|
550
|
+
"lnk",
|
|
551
|
+
"alias",
|
|
552
|
+
"voc",
|
|
553
|
+
"ac3",
|
|
554
|
+
"m4v",
|
|
555
|
+
"m4p",
|
|
556
|
+
"m4b",
|
|
557
|
+
"f4v",
|
|
558
|
+
"f4p",
|
|
559
|
+
"f4b",
|
|
560
|
+
"f4a",
|
|
561
|
+
"mie",
|
|
562
|
+
"asf",
|
|
563
|
+
"ogm",
|
|
564
|
+
"ogx",
|
|
565
|
+
"mpc",
|
|
566
|
+
"arrow",
|
|
567
|
+
"shp",
|
|
568
|
+
"aac",
|
|
569
|
+
"mp1",
|
|
570
|
+
"it",
|
|
571
|
+
"s3m",
|
|
572
|
+
"xm",
|
|
573
|
+
"skp",
|
|
574
|
+
"avif",
|
|
575
|
+
"eps",
|
|
576
|
+
"lzh",
|
|
577
|
+
"pgp",
|
|
578
|
+
"asar",
|
|
579
|
+
"stl",
|
|
580
|
+
"chm",
|
|
581
|
+
"3mf",
|
|
582
|
+
"zst",
|
|
583
|
+
"jxl",
|
|
584
|
+
"vcf",
|
|
585
|
+
"jls",
|
|
586
|
+
"pst",
|
|
587
|
+
"dwg",
|
|
588
|
+
"parquet",
|
|
589
|
+
"class",
|
|
590
|
+
"arj",
|
|
591
|
+
"cpio",
|
|
592
|
+
"ace",
|
|
593
|
+
"avro",
|
|
594
|
+
"icc",
|
|
595
|
+
"fbx",
|
|
596
|
+
"vsdx",
|
|
597
|
+
"vtt",
|
|
598
|
+
"apk",
|
|
599
|
+
"drc",
|
|
600
|
+
"lz4",
|
|
601
|
+
"potx",
|
|
602
|
+
"xltx",
|
|
603
|
+
"dotx",
|
|
604
|
+
"xltm",
|
|
605
|
+
"ott",
|
|
606
|
+
"ots",
|
|
607
|
+
"otp",
|
|
608
|
+
"odg",
|
|
609
|
+
"otg",
|
|
610
|
+
"xlsm",
|
|
611
|
+
"docm",
|
|
612
|
+
"dotm",
|
|
613
|
+
"potm",
|
|
614
|
+
"pptm",
|
|
615
|
+
"jar",
|
|
616
|
+
"jmp",
|
|
617
|
+
"rm",
|
|
618
|
+
"sav",
|
|
619
|
+
"ppsm",
|
|
620
|
+
"ppsx",
|
|
621
|
+
"tar.gz",
|
|
622
|
+
"reg",
|
|
623
|
+
"dat"
|
|
624
|
+
], mimeTypes = [
|
|
625
|
+
"image/jpeg",
|
|
626
|
+
"image/png",
|
|
627
|
+
"image/gif",
|
|
628
|
+
"image/webp",
|
|
629
|
+
"image/flif",
|
|
630
|
+
"image/x-xcf",
|
|
631
|
+
"image/x-canon-cr2",
|
|
632
|
+
"image/x-canon-cr3",
|
|
633
|
+
"image/tiff",
|
|
634
|
+
"image/bmp",
|
|
635
|
+
"image/vnd.ms-photo",
|
|
636
|
+
"image/vnd.adobe.photoshop",
|
|
637
|
+
"application/x-indesign",
|
|
638
|
+
"application/epub+zip",
|
|
639
|
+
"application/x-xpinstall",
|
|
640
|
+
"application/vnd.ms-powerpoint.slideshow.macroenabled.12",
|
|
641
|
+
"application/vnd.oasis.opendocument.text",
|
|
642
|
+
"application/vnd.oasis.opendocument.spreadsheet",
|
|
643
|
+
"application/vnd.oasis.opendocument.presentation",
|
|
644
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
645
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
646
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
647
|
+
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
|
648
|
+
"application/zip",
|
|
649
|
+
"application/x-tar",
|
|
650
|
+
"application/x-rar-compressed",
|
|
651
|
+
"application/gzip",
|
|
652
|
+
"application/x-bzip2",
|
|
653
|
+
"application/x-7z-compressed",
|
|
654
|
+
"application/x-apple-diskimage",
|
|
655
|
+
"application/vnd.apache.arrow.file",
|
|
656
|
+
"video/mp4",
|
|
657
|
+
"audio/midi",
|
|
658
|
+
"video/matroska",
|
|
659
|
+
"video/webm",
|
|
660
|
+
"video/quicktime",
|
|
661
|
+
"video/vnd.avi",
|
|
662
|
+
"audio/wav",
|
|
663
|
+
"audio/qcelp",
|
|
664
|
+
"audio/x-ms-asf",
|
|
665
|
+
"video/x-ms-asf",
|
|
666
|
+
"application/vnd.ms-asf",
|
|
667
|
+
"video/mpeg",
|
|
668
|
+
"video/3gpp",
|
|
669
|
+
"audio/mpeg",
|
|
670
|
+
"audio/mp4",
|
|
671
|
+
// RFC 4337
|
|
672
|
+
"video/ogg",
|
|
673
|
+
"audio/ogg",
|
|
674
|
+
"audio/ogg; codecs=opus",
|
|
675
|
+
"application/ogg",
|
|
676
|
+
"audio/flac",
|
|
677
|
+
"audio/ape",
|
|
678
|
+
"audio/wavpack",
|
|
679
|
+
"audio/amr",
|
|
680
|
+
"application/pdf",
|
|
681
|
+
"application/x-elf",
|
|
682
|
+
"application/x-mach-binary",
|
|
683
|
+
"application/x-msdownload",
|
|
684
|
+
"application/x-shockwave-flash",
|
|
685
|
+
"application/rtf",
|
|
686
|
+
"application/wasm",
|
|
687
|
+
"font/woff",
|
|
688
|
+
"font/woff2",
|
|
689
|
+
"application/vnd.ms-fontobject",
|
|
690
|
+
"font/ttf",
|
|
691
|
+
"font/otf",
|
|
692
|
+
"font/collection",
|
|
693
|
+
"image/x-icon",
|
|
694
|
+
"video/x-flv",
|
|
695
|
+
"application/postscript",
|
|
696
|
+
"application/eps",
|
|
697
|
+
"application/x-xz",
|
|
698
|
+
"application/x-sqlite3",
|
|
699
|
+
"application/x-nintendo-nes-rom",
|
|
700
|
+
"application/x-google-chrome-extension",
|
|
701
|
+
"application/vnd.ms-cab-compressed",
|
|
702
|
+
"application/x-deb",
|
|
703
|
+
"application/x-unix-archive",
|
|
704
|
+
"application/x-rpm",
|
|
705
|
+
"application/x-compress",
|
|
706
|
+
"application/x-lzip",
|
|
707
|
+
"application/x-cfb",
|
|
708
|
+
"application/x-mie",
|
|
709
|
+
"application/mxf",
|
|
710
|
+
"video/mp2t",
|
|
711
|
+
"application/x-blender",
|
|
712
|
+
"image/bpg",
|
|
713
|
+
"image/j2c",
|
|
714
|
+
"image/jp2",
|
|
715
|
+
"image/jpx",
|
|
716
|
+
"image/jpm",
|
|
717
|
+
"image/mj2",
|
|
718
|
+
"audio/aiff",
|
|
719
|
+
"application/xml",
|
|
720
|
+
"application/x-mobipocket-ebook",
|
|
721
|
+
"image/heif",
|
|
722
|
+
"image/heif-sequence",
|
|
723
|
+
"image/heic",
|
|
724
|
+
"image/heic-sequence",
|
|
725
|
+
"image/icns",
|
|
726
|
+
"image/ktx",
|
|
727
|
+
"application/dicom",
|
|
728
|
+
"audio/x-musepack",
|
|
729
|
+
"text/calendar",
|
|
730
|
+
"text/vcard",
|
|
731
|
+
"text/vtt",
|
|
732
|
+
"model/gltf-binary",
|
|
733
|
+
"application/vnd.tcpdump.pcap",
|
|
734
|
+
"audio/x-dsf",
|
|
735
|
+
// Non-standard
|
|
736
|
+
"application/x.ms.shortcut",
|
|
737
|
+
// Invented by us
|
|
738
|
+
"application/x.apple.alias",
|
|
739
|
+
// Invented by us
|
|
740
|
+
"audio/x-voc",
|
|
741
|
+
"audio/vnd.dolby.dd-raw",
|
|
742
|
+
"audio/x-m4a",
|
|
743
|
+
"image/apng",
|
|
744
|
+
"image/x-olympus-orf",
|
|
745
|
+
"image/x-sony-arw",
|
|
746
|
+
"image/x-adobe-dng",
|
|
747
|
+
"image/x-nikon-nef",
|
|
748
|
+
"image/x-panasonic-rw2",
|
|
749
|
+
"image/x-fujifilm-raf",
|
|
750
|
+
"video/x-m4v",
|
|
751
|
+
"video/3gpp2",
|
|
752
|
+
"application/x-esri-shape",
|
|
753
|
+
"audio/aac",
|
|
754
|
+
"audio/x-it",
|
|
755
|
+
"audio/x-s3m",
|
|
756
|
+
"audio/x-xm",
|
|
757
|
+
"video/MP1S",
|
|
758
|
+
"video/MP2P",
|
|
759
|
+
"application/vnd.sketchup.skp",
|
|
760
|
+
"image/avif",
|
|
761
|
+
"application/x-lzh-compressed",
|
|
762
|
+
"application/pgp-encrypted",
|
|
763
|
+
"application/x-asar",
|
|
764
|
+
"model/stl",
|
|
765
|
+
"application/vnd.ms-htmlhelp",
|
|
766
|
+
"model/3mf",
|
|
767
|
+
"image/jxl",
|
|
768
|
+
"application/zstd",
|
|
769
|
+
"image/jls",
|
|
770
|
+
"application/vnd.ms-outlook",
|
|
771
|
+
"image/vnd.dwg",
|
|
772
|
+
"application/vnd.apache.parquet",
|
|
773
|
+
"application/java-vm",
|
|
774
|
+
"application/x-arj",
|
|
775
|
+
"application/x-cpio",
|
|
776
|
+
"application/x-ace-compressed",
|
|
777
|
+
"application/avro",
|
|
778
|
+
"application/vnd.iccprofile",
|
|
779
|
+
"application/x.autodesk.fbx",
|
|
780
|
+
// Invented by us
|
|
781
|
+
"application/vnd.visio",
|
|
782
|
+
"application/vnd.android.package-archive",
|
|
783
|
+
"application/vnd.google.draco",
|
|
784
|
+
// Invented by us
|
|
785
|
+
"application/x-lz4",
|
|
786
|
+
// Invented by us
|
|
787
|
+
"application/vnd.openxmlformats-officedocument.presentationml.template",
|
|
788
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
|
789
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
|
790
|
+
"application/vnd.ms-excel.template.macroenabled.12",
|
|
791
|
+
"application/vnd.oasis.opendocument.text-template",
|
|
792
|
+
"application/vnd.oasis.opendocument.spreadsheet-template",
|
|
793
|
+
"application/vnd.oasis.opendocument.presentation-template",
|
|
794
|
+
"application/vnd.oasis.opendocument.graphics",
|
|
795
|
+
"application/vnd.oasis.opendocument.graphics-template",
|
|
796
|
+
"application/vnd.ms-excel.sheet.macroenabled.12",
|
|
797
|
+
"application/vnd.ms-word.document.macroenabled.12",
|
|
798
|
+
"application/vnd.ms-word.template.macroenabled.12",
|
|
799
|
+
"application/vnd.ms-powerpoint.template.macroenabled.12",
|
|
800
|
+
"application/vnd.ms-powerpoint.presentation.macroenabled.12",
|
|
801
|
+
"application/java-archive",
|
|
802
|
+
"application/vnd.rn-realmedia",
|
|
803
|
+
"application/x-spss-sav",
|
|
804
|
+
"application/x-ms-regedit",
|
|
805
|
+
"application/x-ft-windows-registry-hive",
|
|
806
|
+
"application/x-jmp-data"
|
|
807
|
+
];
|
|
808
|
+
|
|
809
|
+
// node_modules/file-type/core.js
|
|
810
|
+
var reasonableDetectionSizeInBytes = 4100, maximumMpegOffsetTolerance = reasonableDetectionSizeInBytes - 2, maximumZipEntrySizeInBytes = 1024 * 1024, maximumZipEntryCount = 1024, maximumZipBufferedReadSizeInBytes = 2 ** 31 - 1, maximumUntrustedSkipSizeInBytes = 16 * 1024 * 1024, maximumUnknownSizePayloadProbeSizeInBytes = maximumZipEntrySizeInBytes, maximumZipTextEntrySizeInBytes = maximumZipEntrySizeInBytes, maximumNestedGzipDetectionSizeInBytes = maximumUntrustedSkipSizeInBytes, maximumNestedGzipProbeDepth = 1, unknownSizeGzipProbeTimeoutInMilliseconds = 100, maximumId3HeaderSizeInBytes = maximumUntrustedSkipSizeInBytes, maximumEbmlDocumentTypeSizeInBytes = 64, maximumEbmlElementPayloadSizeInBytes = maximumUnknownSizePayloadProbeSizeInBytes, maximumEbmlElementCount = 256, maximumPngChunkCount = 512, maximumPngStreamScanBudgetInBytes = maximumUntrustedSkipSizeInBytes, maximumAsfHeaderObjectCount = 512, maximumTiffTagCount = 512, maximumDetectionReentryCount = 256, maximumPngChunkSizeInBytes = maximumUnknownSizePayloadProbeSizeInBytes, maximumAsfHeaderPayloadSizeInBytes = maximumUnknownSizePayloadProbeSizeInBytes, maximumTiffStreamIfdOffsetInBytes = maximumUnknownSizePayloadProbeSizeInBytes, maximumTiffIfdOffsetInBytes = maximumUntrustedSkipSizeInBytes, recoverableZipErrorMessages = /* @__PURE__ */ new Set([
|
|
811
|
+
"Unexpected signature",
|
|
812
|
+
"Encrypted ZIP",
|
|
813
|
+
"Expected Central-File-Header signature"
|
|
814
|
+
]), recoverableZipErrorMessagePrefixes = [
|
|
815
|
+
"ZIP entry count exceeds ",
|
|
816
|
+
"Unsupported ZIP compression method:",
|
|
817
|
+
"ZIP entry compressed data exceeds ",
|
|
818
|
+
"ZIP entry decompressed data exceeds ",
|
|
819
|
+
"Expected data-descriptor-signature at position "
|
|
820
|
+
], recoverableZipErrorCodes = /* @__PURE__ */ new Set([
|
|
821
|
+
"Z_BUF_ERROR",
|
|
822
|
+
"Z_DATA_ERROR",
|
|
823
|
+
"ERR_INVALID_STATE"
|
|
824
|
+
]), ParserHardLimitError = class extends Error {
|
|
825
|
+
};
|
|
826
|
+
function patchWebByobTokenizerClose(tokenizer) {
|
|
827
|
+
let streamReader = tokenizer?.streamReader;
|
|
828
|
+
if (streamReader?.constructor?.name !== "WebStreamByobReader")
|
|
829
|
+
return tokenizer;
|
|
830
|
+
let { reader } = streamReader, cancelAndRelease = async () => {
|
|
831
|
+
await reader.cancel(), reader.releaseLock();
|
|
832
|
+
};
|
|
833
|
+
return streamReader.close = cancelAndRelease, streamReader.abort = async () => {
|
|
834
|
+
streamReader.interrupted = !0, await cancelAndRelease();
|
|
835
|
+
}, tokenizer;
|
|
836
|
+
}
|
|
837
|
+
function getSafeBound(value, maximum, reason) {
|
|
838
|
+
if (!Number.isFinite(value) || value < 0 || value > maximum)
|
|
839
|
+
throw new ParserHardLimitError(`${reason} has invalid size ${value} (maximum ${maximum} bytes)`);
|
|
840
|
+
return value;
|
|
841
|
+
}
|
|
842
|
+
async function safeIgnore(tokenizer, length, { maximumLength = maximumUntrustedSkipSizeInBytes, reason = "skip" } = {}) {
|
|
843
|
+
let safeLength = getSafeBound(length, maximumLength, reason);
|
|
844
|
+
await tokenizer.ignore(safeLength);
|
|
845
|
+
}
|
|
846
|
+
async function safeReadBuffer(tokenizer, buffer, options, { maximumLength = buffer.length, reason = "read" } = {}) {
|
|
847
|
+
let length = options?.length ?? buffer.length, safeLength = getSafeBound(length, maximumLength, reason);
|
|
848
|
+
return tokenizer.readBuffer(buffer, {
|
|
849
|
+
...options,
|
|
850
|
+
length: safeLength
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
async function decompressDeflateRawWithLimit(data, { maximumLength = maximumZipEntrySizeInBytes } = {}) {
|
|
854
|
+
let reader = new ReadableStream({
|
|
855
|
+
start(controller) {
|
|
856
|
+
controller.enqueue(data), controller.close();
|
|
857
|
+
}
|
|
858
|
+
}).pipeThrough(new DecompressionStream("deflate-raw")).getReader(), chunks = [], totalLength = 0;
|
|
859
|
+
try {
|
|
860
|
+
for (; ; ) {
|
|
861
|
+
let { done, value } = await reader.read();
|
|
862
|
+
if (done)
|
|
863
|
+
break;
|
|
864
|
+
if (totalLength += value.length, totalLength > maximumLength)
|
|
865
|
+
throw await reader.cancel(), new Error(`ZIP entry decompressed data exceeds ${maximumLength} bytes`);
|
|
866
|
+
chunks.push(value);
|
|
867
|
+
}
|
|
868
|
+
} finally {
|
|
869
|
+
reader.releaseLock();
|
|
870
|
+
}
|
|
871
|
+
let uncompressedData = new Uint8Array(totalLength), offset = 0;
|
|
872
|
+
for (let chunk of chunks)
|
|
873
|
+
uncompressedData.set(chunk, offset), offset += chunk.length;
|
|
874
|
+
return uncompressedData;
|
|
875
|
+
}
|
|
876
|
+
var zipDataDescriptorSignature = 134695760, zipDataDescriptorLengthInBytes = 16, zipDataDescriptorOverlapLengthInBytes = zipDataDescriptorLengthInBytes - 1;
|
|
877
|
+
function findZipDataDescriptorOffset(buffer, bytesConsumed) {
|
|
878
|
+
if (buffer.length < zipDataDescriptorLengthInBytes)
|
|
879
|
+
return -1;
|
|
880
|
+
let lastPossibleDescriptorOffset = buffer.length - zipDataDescriptorLengthInBytes;
|
|
881
|
+
for (let index = 0; index <= lastPossibleDescriptorOffset; index++)
|
|
882
|
+
if (UINT32_LE.get(buffer, index) === zipDataDescriptorSignature && UINT32_LE.get(buffer, index + 8) === bytesConsumed + index)
|
|
883
|
+
return index;
|
|
884
|
+
return -1;
|
|
885
|
+
}
|
|
886
|
+
function isPngAncillaryChunk(type) {
|
|
887
|
+
return (type.codePointAt(0) & 32) !== 0;
|
|
888
|
+
}
|
|
889
|
+
function mergeByteChunks(chunks, totalLength) {
|
|
890
|
+
let merged = new Uint8Array(totalLength), offset = 0;
|
|
891
|
+
for (let chunk of chunks)
|
|
892
|
+
merged.set(chunk, offset), offset += chunk.length;
|
|
893
|
+
return merged;
|
|
894
|
+
}
|
|
895
|
+
async function readZipDataDescriptorEntryWithLimit(zipHandler, { shouldBuffer, maximumLength = maximumZipEntrySizeInBytes } = {}) {
|
|
896
|
+
let { syncBuffer } = zipHandler, { length: syncBufferLength } = syncBuffer, chunks = [], bytesConsumed = 0;
|
|
897
|
+
for (; ; ) {
|
|
898
|
+
let length = await zipHandler.tokenizer.peekBuffer(syncBuffer, { mayBeLess: !0 }), dataDescriptorOffset = findZipDataDescriptorOffset(syncBuffer.subarray(0, length), bytesConsumed), retainedLength = dataDescriptorOffset >= 0 ? 0 : length === syncBufferLength ? Math.min(zipDataDescriptorOverlapLengthInBytes, length - 1) : 0, chunkLength = dataDescriptorOffset >= 0 ? dataDescriptorOffset : length - retainedLength;
|
|
899
|
+
if (chunkLength === 0)
|
|
900
|
+
break;
|
|
901
|
+
if (bytesConsumed += chunkLength, bytesConsumed > maximumLength)
|
|
902
|
+
throw new Error(`ZIP entry compressed data exceeds ${maximumLength} bytes`);
|
|
903
|
+
if (shouldBuffer) {
|
|
904
|
+
let data = new Uint8Array(chunkLength);
|
|
905
|
+
await zipHandler.tokenizer.readBuffer(data), chunks.push(data);
|
|
906
|
+
} else
|
|
907
|
+
await zipHandler.tokenizer.ignore(chunkLength);
|
|
908
|
+
if (dataDescriptorOffset >= 0)
|
|
909
|
+
break;
|
|
910
|
+
}
|
|
911
|
+
if (hasUnknownFileSize(zipHandler.tokenizer) || (zipHandler.knownSizeDescriptorScannedBytes += bytesConsumed), !!shouldBuffer)
|
|
912
|
+
return mergeByteChunks(chunks, bytesConsumed);
|
|
913
|
+
}
|
|
914
|
+
function getRemainingZipScanBudget(zipHandler, startOffset) {
|
|
915
|
+
return hasUnknownFileSize(zipHandler.tokenizer) ? Math.max(0, maximumUntrustedSkipSizeInBytes - (zipHandler.tokenizer.position - startOffset)) : Math.max(0, maximumZipEntrySizeInBytes - zipHandler.knownSizeDescriptorScannedBytes);
|
|
916
|
+
}
|
|
917
|
+
async function readZipEntryData(zipHandler, zipHeader, { shouldBuffer, maximumDescriptorLength = maximumZipEntrySizeInBytes } = {}) {
|
|
918
|
+
if (zipHeader.dataDescriptor && zipHeader.compressedSize === 0)
|
|
919
|
+
return readZipDataDescriptorEntryWithLimit(zipHandler, {
|
|
920
|
+
shouldBuffer,
|
|
921
|
+
maximumLength: maximumDescriptorLength
|
|
922
|
+
});
|
|
923
|
+
if (!shouldBuffer) {
|
|
924
|
+
await safeIgnore(zipHandler.tokenizer, zipHeader.compressedSize, {
|
|
925
|
+
maximumLength: hasUnknownFileSize(zipHandler.tokenizer) ? maximumZipEntrySizeInBytes : zipHandler.tokenizer.fileInfo.size,
|
|
926
|
+
reason: "ZIP entry compressed data"
|
|
927
|
+
});
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
let maximumLength = getMaximumZipBufferedReadLength(zipHandler.tokenizer);
|
|
931
|
+
if (!Number.isFinite(zipHeader.compressedSize) || zipHeader.compressedSize < 0 || zipHeader.compressedSize > maximumLength)
|
|
932
|
+
throw new Error(`ZIP entry compressed data exceeds ${maximumLength} bytes`);
|
|
933
|
+
let fileData = new Uint8Array(zipHeader.compressedSize);
|
|
934
|
+
return await zipHandler.tokenizer.readBuffer(fileData), fileData;
|
|
935
|
+
}
|
|
936
|
+
ZipHandler.prototype.inflate = async function(zipHeader, fileData, callback) {
|
|
937
|
+
if (zipHeader.compressedMethod === 0)
|
|
938
|
+
return callback(fileData);
|
|
939
|
+
if (zipHeader.compressedMethod !== 8)
|
|
940
|
+
throw new Error(`Unsupported ZIP compression method: ${zipHeader.compressedMethod}`);
|
|
941
|
+
let uncompressedData = await decompressDeflateRawWithLimit(fileData, { maximumLength: maximumZipEntrySizeInBytes });
|
|
942
|
+
return callback(uncompressedData);
|
|
943
|
+
};
|
|
944
|
+
ZipHandler.prototype.unzip = async function(fileCallback) {
|
|
945
|
+
let stop = !1, zipEntryCount = 0, zipScanStart = this.tokenizer.position;
|
|
946
|
+
this.knownSizeDescriptorScannedBytes = 0;
|
|
947
|
+
do {
|
|
948
|
+
if (hasExceededUnknownSizeScanBudget(this.tokenizer, zipScanStart, maximumUntrustedSkipSizeInBytes))
|
|
949
|
+
throw new ParserHardLimitError(`ZIP stream probing exceeds ${maximumUntrustedSkipSizeInBytes} bytes`);
|
|
950
|
+
let zipHeader = await this.readLocalFileHeader();
|
|
951
|
+
if (!zipHeader)
|
|
952
|
+
break;
|
|
953
|
+
if (zipEntryCount++, zipEntryCount > maximumZipEntryCount)
|
|
954
|
+
throw new Error(`ZIP entry count exceeds ${maximumZipEntryCount}`);
|
|
955
|
+
let next = fileCallback(zipHeader);
|
|
956
|
+
stop = !!next.stop, await this.tokenizer.ignore(zipHeader.extraFieldLength);
|
|
957
|
+
let fileData = await readZipEntryData(this, zipHeader, {
|
|
958
|
+
shouldBuffer: !!next.handler,
|
|
959
|
+
maximumDescriptorLength: Math.min(maximumZipEntrySizeInBytes, getRemainingZipScanBudget(this, zipScanStart))
|
|
960
|
+
});
|
|
961
|
+
if (next.handler && await this.inflate(zipHeader, fileData, next.handler), zipHeader.dataDescriptor) {
|
|
962
|
+
let dataDescriptor = new Uint8Array(zipDataDescriptorLengthInBytes);
|
|
963
|
+
if (await this.tokenizer.readBuffer(dataDescriptor), UINT32_LE.get(dataDescriptor, 0) !== zipDataDescriptorSignature)
|
|
964
|
+
throw new Error(`Expected data-descriptor-signature at position ${this.tokenizer.position - dataDescriptor.length}`);
|
|
965
|
+
}
|
|
966
|
+
if (hasExceededUnknownSizeScanBudget(this.tokenizer, zipScanStart, maximumUntrustedSkipSizeInBytes))
|
|
967
|
+
throw new ParserHardLimitError(`ZIP stream probing exceeds ${maximumUntrustedSkipSizeInBytes} bytes`);
|
|
968
|
+
} while (!stop);
|
|
969
|
+
};
|
|
970
|
+
function createByteLimitedReadableStream(stream, maximumBytes) {
|
|
971
|
+
let reader = stream.getReader(), emittedBytes = 0, sourceDone = !1, sourceCanceled = !1, cancelSource = async (reason) => {
|
|
972
|
+
sourceDone || sourceCanceled || (sourceCanceled = !0, await reader.cancel(reason));
|
|
973
|
+
};
|
|
974
|
+
return new ReadableStream({
|
|
975
|
+
async pull(controller) {
|
|
976
|
+
if (emittedBytes >= maximumBytes) {
|
|
977
|
+
controller.close(), await cancelSource();
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
let { done, value } = await reader.read();
|
|
981
|
+
if (done || !value) {
|
|
982
|
+
sourceDone = !0, controller.close();
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
let remainingBytes = maximumBytes - emittedBytes;
|
|
986
|
+
if (value.length > remainingBytes) {
|
|
987
|
+
controller.enqueue(value.subarray(0, remainingBytes)), emittedBytes += remainingBytes, controller.close(), await cancelSource();
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
controller.enqueue(value), emittedBytes += value.length;
|
|
991
|
+
},
|
|
992
|
+
async cancel(reason) {
|
|
993
|
+
await cancelSource(reason);
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
async function fileTypeFromBuffer(input, options) {
|
|
998
|
+
return new FileTypeParser(options).fromBuffer(input);
|
|
999
|
+
}
|
|
1000
|
+
function getFileTypeFromMimeType(mimeType) {
|
|
1001
|
+
switch (mimeType = mimeType.toLowerCase(), mimeType) {
|
|
1002
|
+
case "application/epub+zip":
|
|
1003
|
+
return {
|
|
1004
|
+
ext: "epub",
|
|
1005
|
+
mime: mimeType
|
|
1006
|
+
};
|
|
1007
|
+
case "application/vnd.oasis.opendocument.text":
|
|
1008
|
+
return {
|
|
1009
|
+
ext: "odt",
|
|
1010
|
+
mime: mimeType
|
|
1011
|
+
};
|
|
1012
|
+
case "application/vnd.oasis.opendocument.text-template":
|
|
1013
|
+
return {
|
|
1014
|
+
ext: "ott",
|
|
1015
|
+
mime: mimeType
|
|
1016
|
+
};
|
|
1017
|
+
case "application/vnd.oasis.opendocument.spreadsheet":
|
|
1018
|
+
return {
|
|
1019
|
+
ext: "ods",
|
|
1020
|
+
mime: mimeType
|
|
1021
|
+
};
|
|
1022
|
+
case "application/vnd.oasis.opendocument.spreadsheet-template":
|
|
1023
|
+
return {
|
|
1024
|
+
ext: "ots",
|
|
1025
|
+
mime: mimeType
|
|
1026
|
+
};
|
|
1027
|
+
case "application/vnd.oasis.opendocument.presentation":
|
|
1028
|
+
return {
|
|
1029
|
+
ext: "odp",
|
|
1030
|
+
mime: mimeType
|
|
1031
|
+
};
|
|
1032
|
+
case "application/vnd.oasis.opendocument.presentation-template":
|
|
1033
|
+
return {
|
|
1034
|
+
ext: "otp",
|
|
1035
|
+
mime: mimeType
|
|
1036
|
+
};
|
|
1037
|
+
case "application/vnd.oasis.opendocument.graphics":
|
|
1038
|
+
return {
|
|
1039
|
+
ext: "odg",
|
|
1040
|
+
mime: mimeType
|
|
1041
|
+
};
|
|
1042
|
+
case "application/vnd.oasis.opendocument.graphics-template":
|
|
1043
|
+
return {
|
|
1044
|
+
ext: "otg",
|
|
1045
|
+
mime: mimeType
|
|
1046
|
+
};
|
|
1047
|
+
case "application/vnd.openxmlformats-officedocument.presentationml.slideshow":
|
|
1048
|
+
return {
|
|
1049
|
+
ext: "ppsx",
|
|
1050
|
+
mime: mimeType
|
|
1051
|
+
};
|
|
1052
|
+
case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
|
|
1053
|
+
return {
|
|
1054
|
+
ext: "xlsx",
|
|
1055
|
+
mime: mimeType
|
|
1056
|
+
};
|
|
1057
|
+
case "application/vnd.ms-excel.sheet.macroenabled":
|
|
1058
|
+
return {
|
|
1059
|
+
ext: "xlsm",
|
|
1060
|
+
mime: "application/vnd.ms-excel.sheet.macroenabled.12"
|
|
1061
|
+
};
|
|
1062
|
+
case "application/vnd.openxmlformats-officedocument.spreadsheetml.template":
|
|
1063
|
+
return {
|
|
1064
|
+
ext: "xltx",
|
|
1065
|
+
mime: mimeType
|
|
1066
|
+
};
|
|
1067
|
+
case "application/vnd.ms-excel.template.macroenabled":
|
|
1068
|
+
return {
|
|
1069
|
+
ext: "xltm",
|
|
1070
|
+
mime: "application/vnd.ms-excel.template.macroenabled.12"
|
|
1071
|
+
};
|
|
1072
|
+
case "application/vnd.ms-powerpoint.slideshow.macroenabled":
|
|
1073
|
+
return {
|
|
1074
|
+
ext: "ppsm",
|
|
1075
|
+
mime: "application/vnd.ms-powerpoint.slideshow.macroenabled.12"
|
|
1076
|
+
};
|
|
1077
|
+
case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
|
|
1078
|
+
return {
|
|
1079
|
+
ext: "docx",
|
|
1080
|
+
mime: mimeType
|
|
1081
|
+
};
|
|
1082
|
+
case "application/vnd.ms-word.document.macroenabled":
|
|
1083
|
+
return {
|
|
1084
|
+
ext: "docm",
|
|
1085
|
+
mime: "application/vnd.ms-word.document.macroenabled.12"
|
|
1086
|
+
};
|
|
1087
|
+
case "application/vnd.openxmlformats-officedocument.wordprocessingml.template":
|
|
1088
|
+
return {
|
|
1089
|
+
ext: "dotx",
|
|
1090
|
+
mime: mimeType
|
|
1091
|
+
};
|
|
1092
|
+
case "application/vnd.ms-word.template.macroenabledtemplate":
|
|
1093
|
+
return {
|
|
1094
|
+
ext: "dotm",
|
|
1095
|
+
mime: "application/vnd.ms-word.template.macroenabled.12"
|
|
1096
|
+
};
|
|
1097
|
+
case "application/vnd.openxmlformats-officedocument.presentationml.template":
|
|
1098
|
+
return {
|
|
1099
|
+
ext: "potx",
|
|
1100
|
+
mime: mimeType
|
|
1101
|
+
};
|
|
1102
|
+
case "application/vnd.ms-powerpoint.template.macroenabled":
|
|
1103
|
+
return {
|
|
1104
|
+
ext: "potm",
|
|
1105
|
+
mime: "application/vnd.ms-powerpoint.template.macroenabled.12"
|
|
1106
|
+
};
|
|
1107
|
+
case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
|
|
1108
|
+
return {
|
|
1109
|
+
ext: "pptx",
|
|
1110
|
+
mime: mimeType
|
|
1111
|
+
};
|
|
1112
|
+
case "application/vnd.ms-powerpoint.presentation.macroenabled":
|
|
1113
|
+
return {
|
|
1114
|
+
ext: "pptm",
|
|
1115
|
+
mime: "application/vnd.ms-powerpoint.presentation.macroenabled.12"
|
|
1116
|
+
};
|
|
1117
|
+
case "application/vnd.ms-visio.drawing":
|
|
1118
|
+
return {
|
|
1119
|
+
ext: "vsdx",
|
|
1120
|
+
mime: "application/vnd.visio"
|
|
1121
|
+
};
|
|
1122
|
+
case "application/vnd.ms-package.3dmanufacturing-3dmodel+xml":
|
|
1123
|
+
return {
|
|
1124
|
+
ext: "3mf",
|
|
1125
|
+
mime: "model/3mf"
|
|
1126
|
+
};
|
|
1127
|
+
default:
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
function _check(buffer, headers, options) {
|
|
1131
|
+
options = {
|
|
1132
|
+
offset: 0,
|
|
1133
|
+
...options
|
|
1134
|
+
};
|
|
1135
|
+
for (let [index, header] of headers.entries())
|
|
1136
|
+
if (options.mask) {
|
|
1137
|
+
if (header !== (options.mask[index] & buffer[index + options.offset]))
|
|
1138
|
+
return !1;
|
|
1139
|
+
} else if (header !== buffer[index + options.offset])
|
|
1140
|
+
return !1;
|
|
1141
|
+
return !0;
|
|
1142
|
+
}
|
|
1143
|
+
function normalizeSampleSize(sampleSize) {
|
|
1144
|
+
return Number.isFinite(sampleSize) ? Math.max(1, Math.trunc(sampleSize)) : reasonableDetectionSizeInBytes;
|
|
1145
|
+
}
|
|
1146
|
+
function readByobReaderWithSignal(reader, buffer, signal) {
|
|
1147
|
+
return signal === void 0 ? reader.read(buffer) : (signal.throwIfAborted(), new Promise((resolve, reject) => {
|
|
1148
|
+
let cleanup = () => {
|
|
1149
|
+
signal.removeEventListener("abort", onAbort);
|
|
1150
|
+
}, onAbort = () => {
|
|
1151
|
+
let abortReason = signal.reason;
|
|
1152
|
+
cleanup(), (async () => {
|
|
1153
|
+
try {
|
|
1154
|
+
await reader.cancel(abortReason);
|
|
1155
|
+
} catch {
|
|
1156
|
+
}
|
|
1157
|
+
})(), reject(abortReason);
|
|
1158
|
+
};
|
|
1159
|
+
signal.addEventListener("abort", onAbort, { once: !0 }), (async () => {
|
|
1160
|
+
try {
|
|
1161
|
+
let result = await reader.read(buffer);
|
|
1162
|
+
cleanup(), resolve(result);
|
|
1163
|
+
} catch (error) {
|
|
1164
|
+
cleanup(), reject(error);
|
|
1165
|
+
}
|
|
1166
|
+
})();
|
|
1167
|
+
}));
|
|
1168
|
+
}
|
|
1169
|
+
function normalizeMpegOffsetTolerance(mpegOffsetTolerance) {
|
|
1170
|
+
return Number.isFinite(mpegOffsetTolerance) ? Math.max(0, Math.min(maximumMpegOffsetTolerance, Math.trunc(mpegOffsetTolerance))) : 0;
|
|
1171
|
+
}
|
|
1172
|
+
function getKnownFileSizeOrMaximum(fileSize) {
|
|
1173
|
+
return Number.isFinite(fileSize) ? Math.max(0, fileSize) : Number.MAX_SAFE_INTEGER;
|
|
1174
|
+
}
|
|
1175
|
+
function hasUnknownFileSize(tokenizer) {
|
|
1176
|
+
let fileSize = tokenizer.fileInfo.size;
|
|
1177
|
+
return !Number.isFinite(fileSize) || fileSize === Number.MAX_SAFE_INTEGER;
|
|
1178
|
+
}
|
|
1179
|
+
function hasExceededUnknownSizeScanBudget(tokenizer, startOffset, maximumBytes) {
|
|
1180
|
+
return hasUnknownFileSize(tokenizer) && tokenizer.position - startOffset > maximumBytes;
|
|
1181
|
+
}
|
|
1182
|
+
function getMaximumZipBufferedReadLength(tokenizer) {
|
|
1183
|
+
let fileSize = tokenizer.fileInfo.size, remainingBytes = Number.isFinite(fileSize) ? Math.max(0, fileSize - tokenizer.position) : Number.MAX_SAFE_INTEGER;
|
|
1184
|
+
return Math.min(remainingBytes, maximumZipBufferedReadSizeInBytes);
|
|
1185
|
+
}
|
|
1186
|
+
function isRecoverableZipError(error) {
|
|
1187
|
+
if (error instanceof EndOfStreamError || error instanceof ParserHardLimitError)
|
|
1188
|
+
return !0;
|
|
1189
|
+
if (!(error instanceof Error))
|
|
1190
|
+
return !1;
|
|
1191
|
+
if (recoverableZipErrorMessages.has(error.message) || recoverableZipErrorCodes.has(error.code))
|
|
1192
|
+
return !0;
|
|
1193
|
+
for (let prefix of recoverableZipErrorMessagePrefixes)
|
|
1194
|
+
if (error.message.startsWith(prefix))
|
|
1195
|
+
return !0;
|
|
1196
|
+
return !1;
|
|
1197
|
+
}
|
|
1198
|
+
function canReadZipEntryForDetection(zipHeader, maximumSize = maximumZipEntrySizeInBytes) {
|
|
1199
|
+
let sizes = [zipHeader.compressedSize, zipHeader.uncompressedSize];
|
|
1200
|
+
for (let size of sizes)
|
|
1201
|
+
if (!Number.isFinite(size) || size < 0 || size > maximumSize)
|
|
1202
|
+
return !1;
|
|
1203
|
+
return !0;
|
|
1204
|
+
}
|
|
1205
|
+
function createOpenXmlZipDetectionState() {
|
|
1206
|
+
return {
|
|
1207
|
+
hasContentTypesEntry: !1,
|
|
1208
|
+
hasParsedContentTypesEntry: !1,
|
|
1209
|
+
isParsingContentTypes: !1,
|
|
1210
|
+
hasUnparseableContentTypes: !1,
|
|
1211
|
+
hasWordDirectory: !1,
|
|
1212
|
+
hasPresentationDirectory: !1,
|
|
1213
|
+
hasSpreadsheetDirectory: !1,
|
|
1214
|
+
hasThreeDimensionalModelEntry: !1
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
function updateOpenXmlZipDetectionStateFromFilename(openXmlState, filename) {
|
|
1218
|
+
filename.startsWith("word/") && (openXmlState.hasWordDirectory = !0), filename.startsWith("ppt/") && (openXmlState.hasPresentationDirectory = !0), filename.startsWith("xl/") && (openXmlState.hasSpreadsheetDirectory = !0), filename.startsWith("3D/") && filename.endsWith(".model") && (openXmlState.hasThreeDimensionalModelEntry = !0);
|
|
1219
|
+
}
|
|
1220
|
+
function getOpenXmlFileTypeFromZipEntries(openXmlState) {
|
|
1221
|
+
if (!(!openXmlState.hasContentTypesEntry || openXmlState.hasUnparseableContentTypes || openXmlState.isParsingContentTypes || openXmlState.hasParsedContentTypesEntry)) {
|
|
1222
|
+
if (openXmlState.hasWordDirectory)
|
|
1223
|
+
return {
|
|
1224
|
+
ext: "docx",
|
|
1225
|
+
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
1226
|
+
};
|
|
1227
|
+
if (openXmlState.hasPresentationDirectory)
|
|
1228
|
+
return {
|
|
1229
|
+
ext: "pptx",
|
|
1230
|
+
mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
1231
|
+
};
|
|
1232
|
+
if (openXmlState.hasSpreadsheetDirectory)
|
|
1233
|
+
return {
|
|
1234
|
+
ext: "xlsx",
|
|
1235
|
+
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
1236
|
+
};
|
|
1237
|
+
if (openXmlState.hasThreeDimensionalModelEntry)
|
|
1238
|
+
return {
|
|
1239
|
+
ext: "3mf",
|
|
1240
|
+
mime: "model/3mf"
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
function getOpenXmlMimeTypeFromContentTypesXml(xmlContent) {
|
|
1245
|
+
let endPosition = xmlContent.indexOf('.main+xml"');
|
|
1246
|
+
if (endPosition === -1) {
|
|
1247
|
+
let mimeType = "application/vnd.ms-package.3dmanufacturing-3dmodel+xml";
|
|
1248
|
+
return xmlContent.includes(`ContentType="${mimeType}"`) ? mimeType : void 0;
|
|
1249
|
+
}
|
|
1250
|
+
let truncatedContent = xmlContent.slice(0, endPosition), firstQuotePosition = truncatedContent.lastIndexOf('"');
|
|
1251
|
+
return truncatedContent.slice(firstQuotePosition + 1);
|
|
1252
|
+
}
|
|
1253
|
+
var FileTypeParser = class _FileTypeParser {
|
|
1254
|
+
constructor(options) {
|
|
1255
|
+
let normalizedMpegOffsetTolerance = normalizeMpegOffsetTolerance(options?.mpegOffsetTolerance);
|
|
1256
|
+
this.options = {
|
|
1257
|
+
...options,
|
|
1258
|
+
mpegOffsetTolerance: normalizedMpegOffsetTolerance
|
|
1259
|
+
}, this.detectors = [
|
|
1260
|
+
...this.options.customDetectors ?? [],
|
|
1261
|
+
{ id: "core", detect: this.detectConfident },
|
|
1262
|
+
{ id: "core.imprecise", detect: this.detectImprecise }
|
|
1263
|
+
], this.tokenizerOptions = {
|
|
1264
|
+
abortSignal: this.options.signal
|
|
1265
|
+
}, this.gzipProbeDepth = 0;
|
|
1266
|
+
}
|
|
1267
|
+
getTokenizerOptions() {
|
|
1268
|
+
return {
|
|
1269
|
+
...this.tokenizerOptions
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
createTokenizerFromWebStream(stream) {
|
|
1273
|
+
return patchWebByobTokenizerClose(fromWebStream(stream, this.getTokenizerOptions()));
|
|
1274
|
+
}
|
|
1275
|
+
async parseTokenizer(tokenizer, detectionReentryCount = 0) {
|
|
1276
|
+
this.detectionReentryCount = detectionReentryCount;
|
|
1277
|
+
let initialPosition = tokenizer.position;
|
|
1278
|
+
for (let detector of this.detectors) {
|
|
1279
|
+
let fileType;
|
|
1280
|
+
try {
|
|
1281
|
+
fileType = await detector.detect(tokenizer);
|
|
1282
|
+
} catch (error) {
|
|
1283
|
+
if (error instanceof EndOfStreamError || error instanceof ParserHardLimitError)
|
|
1284
|
+
return;
|
|
1285
|
+
throw error;
|
|
1286
|
+
}
|
|
1287
|
+
if (fileType)
|
|
1288
|
+
return fileType;
|
|
1289
|
+
if (initialPosition !== tokenizer.position)
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
async fromTokenizer(tokenizer) {
|
|
1294
|
+
try {
|
|
1295
|
+
return await this.parseTokenizer(tokenizer);
|
|
1296
|
+
} finally {
|
|
1297
|
+
await tokenizer.close();
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
async fromBuffer(input) {
|
|
1301
|
+
if (!(input instanceof Uint8Array || input instanceof ArrayBuffer))
|
|
1302
|
+
throw new TypeError(`Expected the \`input\` argument to be of type \`Uint8Array\` or \`ArrayBuffer\`, got \`${typeof input}\``);
|
|
1303
|
+
let buffer = input instanceof Uint8Array ? input : new Uint8Array(input);
|
|
1304
|
+
if (buffer?.length > 1)
|
|
1305
|
+
return this.fromTokenizer(fromBuffer(buffer, this.getTokenizerOptions()));
|
|
1306
|
+
}
|
|
1307
|
+
async fromBlob(blob) {
|
|
1308
|
+
this.options.signal?.throwIfAborted();
|
|
1309
|
+
let tokenizer = fromBlob(blob, this.getTokenizerOptions());
|
|
1310
|
+
return this.fromTokenizer(tokenizer);
|
|
1311
|
+
}
|
|
1312
|
+
async fromStream(stream) {
|
|
1313
|
+
this.options.signal?.throwIfAborted();
|
|
1314
|
+
let tokenizer = this.createTokenizerFromWebStream(stream);
|
|
1315
|
+
return this.fromTokenizer(tokenizer);
|
|
1316
|
+
}
|
|
1317
|
+
async toDetectionStream(stream, options) {
|
|
1318
|
+
let sampleSize = normalizeSampleSize(options?.sampleSize ?? reasonableDetectionSizeInBytes), detectedFileType, firstChunk, reader = stream.getReader({ mode: "byob" });
|
|
1319
|
+
try {
|
|
1320
|
+
let { value: chunk, done } = await readByobReaderWithSignal(reader, new Uint8Array(sampleSize), this.options.signal);
|
|
1321
|
+
if (firstChunk = chunk, !done && chunk)
|
|
1322
|
+
try {
|
|
1323
|
+
detectedFileType = await this.fromBuffer(chunk.subarray(0, sampleSize));
|
|
1324
|
+
} catch (error) {
|
|
1325
|
+
if (!(error instanceof EndOfStreamError))
|
|
1326
|
+
throw error;
|
|
1327
|
+
detectedFileType = void 0;
|
|
1328
|
+
}
|
|
1329
|
+
firstChunk = chunk;
|
|
1330
|
+
} finally {
|
|
1331
|
+
reader.releaseLock();
|
|
1332
|
+
}
|
|
1333
|
+
let transformStream = new TransformStream({
|
|
1334
|
+
async start(controller) {
|
|
1335
|
+
controller.enqueue(firstChunk);
|
|
1336
|
+
},
|
|
1337
|
+
transform(chunk, controller) {
|
|
1338
|
+
controller.enqueue(chunk);
|
|
1339
|
+
}
|
|
1340
|
+
}), newStream = stream.pipeThrough(transformStream);
|
|
1341
|
+
return newStream.fileType = detectedFileType, newStream;
|
|
1342
|
+
}
|
|
1343
|
+
async detectGzip(tokenizer) {
|
|
1344
|
+
if (this.gzipProbeDepth >= maximumNestedGzipProbeDepth)
|
|
1345
|
+
return {
|
|
1346
|
+
ext: "gz",
|
|
1347
|
+
mime: "application/gzip"
|
|
1348
|
+
};
|
|
1349
|
+
let gzipHandler = new GzipHandler(tokenizer), limitedInflatedStream = createByteLimitedReadableStream(gzipHandler.inflate(), maximumNestedGzipDetectionSizeInBytes), hasUnknownSize = hasUnknownFileSize(tokenizer), timeout, probeSignal, probeParser, compressedFileType;
|
|
1350
|
+
if (hasUnknownSize) {
|
|
1351
|
+
let timeoutController = new AbortController();
|
|
1352
|
+
timeout = setTimeout(() => {
|
|
1353
|
+
timeoutController.abort(new DOMException(`Operation timed out after ${unknownSizeGzipProbeTimeoutInMilliseconds} ms`, "TimeoutError"));
|
|
1354
|
+
}, unknownSizeGzipProbeTimeoutInMilliseconds), probeSignal = this.options.signal === void 0 ? timeoutController.signal : AbortSignal.any([this.options.signal, timeoutController.signal]), probeParser = new _FileTypeParser({
|
|
1355
|
+
...this.options,
|
|
1356
|
+
signal: probeSignal
|
|
1357
|
+
}), probeParser.gzipProbeDepth = this.gzipProbeDepth + 1;
|
|
1358
|
+
} else
|
|
1359
|
+
this.gzipProbeDepth++;
|
|
1360
|
+
try {
|
|
1361
|
+
compressedFileType = await (probeParser ?? this).fromStream(limitedInflatedStream);
|
|
1362
|
+
} catch (error) {
|
|
1363
|
+
if (error?.name === "AbortError" && probeSignal?.reason?.name !== "TimeoutError")
|
|
1364
|
+
throw error;
|
|
1365
|
+
} finally {
|
|
1366
|
+
clearTimeout(timeout), hasUnknownSize || this.gzipProbeDepth--;
|
|
1367
|
+
}
|
|
1368
|
+
return compressedFileType?.ext === "tar" ? {
|
|
1369
|
+
ext: "tar.gz",
|
|
1370
|
+
mime: "application/gzip"
|
|
1371
|
+
} : {
|
|
1372
|
+
ext: "gz",
|
|
1373
|
+
mime: "application/gzip"
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
check(header, options) {
|
|
1377
|
+
return _check(this.buffer, header, options);
|
|
1378
|
+
}
|
|
1379
|
+
checkString(header, options) {
|
|
1380
|
+
return this.check(stringToBytes(header, options?.encoding), options);
|
|
1381
|
+
}
|
|
1382
|
+
// Detections with a high degree of certainty in identifying the correct file type
|
|
1383
|
+
detectConfident = async (tokenizer) => {
|
|
1384
|
+
if (this.buffer = new Uint8Array(reasonableDetectionSizeInBytes), tokenizer.fileInfo.size === void 0 && (tokenizer.fileInfo.size = Number.MAX_SAFE_INTEGER), this.tokenizer = tokenizer, hasUnknownFileSize(tokenizer) && (await tokenizer.peekBuffer(this.buffer, { length: 3, mayBeLess: !0 }), this.check([31, 139, 8])))
|
|
1385
|
+
return this.detectGzip(tokenizer);
|
|
1386
|
+
if (await tokenizer.peekBuffer(this.buffer, { length: 32, mayBeLess: !0 }), this.check([66, 77]))
|
|
1387
|
+
return {
|
|
1388
|
+
ext: "bmp",
|
|
1389
|
+
mime: "image/bmp"
|
|
1390
|
+
};
|
|
1391
|
+
if (this.check([11, 119]))
|
|
1392
|
+
return {
|
|
1393
|
+
ext: "ac3",
|
|
1394
|
+
mime: "audio/vnd.dolby.dd-raw"
|
|
1395
|
+
};
|
|
1396
|
+
if (this.check([120, 1]))
|
|
1397
|
+
return {
|
|
1398
|
+
ext: "dmg",
|
|
1399
|
+
mime: "application/x-apple-diskimage"
|
|
1400
|
+
};
|
|
1401
|
+
if (this.check([77, 90]))
|
|
1402
|
+
return {
|
|
1403
|
+
ext: "exe",
|
|
1404
|
+
mime: "application/x-msdownload"
|
|
1405
|
+
};
|
|
1406
|
+
if (this.check([37, 33]))
|
|
1407
|
+
return await tokenizer.peekBuffer(this.buffer, { length: 24, mayBeLess: !0 }), this.checkString("PS-Adobe-", { offset: 2 }) && this.checkString(" EPSF-", { offset: 14 }) ? {
|
|
1408
|
+
ext: "eps",
|
|
1409
|
+
mime: "application/eps"
|
|
1410
|
+
} : {
|
|
1411
|
+
ext: "ps",
|
|
1412
|
+
mime: "application/postscript"
|
|
1413
|
+
};
|
|
1414
|
+
if (this.check([31, 160]) || this.check([31, 157]))
|
|
1415
|
+
return {
|
|
1416
|
+
ext: "Z",
|
|
1417
|
+
mime: "application/x-compress"
|
|
1418
|
+
};
|
|
1419
|
+
if (this.check([199, 113]))
|
|
1420
|
+
return {
|
|
1421
|
+
ext: "cpio",
|
|
1422
|
+
mime: "application/x-cpio"
|
|
1423
|
+
};
|
|
1424
|
+
if (this.check([96, 234]))
|
|
1425
|
+
return {
|
|
1426
|
+
ext: "arj",
|
|
1427
|
+
mime: "application/x-arj"
|
|
1428
|
+
};
|
|
1429
|
+
if (this.check([239, 187, 191]))
|
|
1430
|
+
return this.detectionReentryCount >= maximumDetectionReentryCount ? void 0 : (this.detectionReentryCount++, await this.tokenizer.ignore(3), this.detectConfident(tokenizer));
|
|
1431
|
+
if (this.check([71, 73, 70]))
|
|
1432
|
+
return {
|
|
1433
|
+
ext: "gif",
|
|
1434
|
+
mime: "image/gif"
|
|
1435
|
+
};
|
|
1436
|
+
if (this.check([73, 73, 188]))
|
|
1437
|
+
return {
|
|
1438
|
+
ext: "jxr",
|
|
1439
|
+
mime: "image/vnd.ms-photo"
|
|
1440
|
+
};
|
|
1441
|
+
if (this.check([31, 139, 8]))
|
|
1442
|
+
return this.detectGzip(tokenizer);
|
|
1443
|
+
if (this.check([66, 90, 104]))
|
|
1444
|
+
return {
|
|
1445
|
+
ext: "bz2",
|
|
1446
|
+
mime: "application/x-bzip2"
|
|
1447
|
+
};
|
|
1448
|
+
if (this.checkString("ID3")) {
|
|
1449
|
+
await safeIgnore(tokenizer, 6, {
|
|
1450
|
+
maximumLength: 6,
|
|
1451
|
+
reason: "ID3 header prefix"
|
|
1452
|
+
});
|
|
1453
|
+
let id3HeaderLength = await tokenizer.readToken(uint32SyncSafeToken), isUnknownFileSize = hasUnknownFileSize(tokenizer);
|
|
1454
|
+
if (!Number.isFinite(id3HeaderLength) || id3HeaderLength < 0 || isUnknownFileSize && (id3HeaderLength > maximumId3HeaderSizeInBytes || tokenizer.position + id3HeaderLength > maximumId3HeaderSizeInBytes))
|
|
1455
|
+
return;
|
|
1456
|
+
if (tokenizer.position + id3HeaderLength > tokenizer.fileInfo.size)
|
|
1457
|
+
return isUnknownFileSize ? void 0 : {
|
|
1458
|
+
ext: "mp3",
|
|
1459
|
+
mime: "audio/mpeg"
|
|
1460
|
+
};
|
|
1461
|
+
try {
|
|
1462
|
+
await safeIgnore(tokenizer, id3HeaderLength, {
|
|
1463
|
+
maximumLength: isUnknownFileSize ? maximumId3HeaderSizeInBytes : tokenizer.fileInfo.size,
|
|
1464
|
+
reason: "ID3 payload"
|
|
1465
|
+
});
|
|
1466
|
+
} catch (error) {
|
|
1467
|
+
if (error instanceof EndOfStreamError)
|
|
1468
|
+
return;
|
|
1469
|
+
throw error;
|
|
1470
|
+
}
|
|
1471
|
+
return this.detectionReentryCount >= maximumDetectionReentryCount ? void 0 : (this.detectionReentryCount++, this.parseTokenizer(tokenizer, this.detectionReentryCount));
|
|
1472
|
+
}
|
|
1473
|
+
if (this.checkString("MP+"))
|
|
1474
|
+
return {
|
|
1475
|
+
ext: "mpc",
|
|
1476
|
+
mime: "audio/x-musepack"
|
|
1477
|
+
};
|
|
1478
|
+
if ((this.buffer[0] === 67 || this.buffer[0] === 70) && this.check([87, 83], { offset: 1 }))
|
|
1479
|
+
return {
|
|
1480
|
+
ext: "swf",
|
|
1481
|
+
mime: "application/x-shockwave-flash"
|
|
1482
|
+
};
|
|
1483
|
+
if (this.check([255, 216, 255]))
|
|
1484
|
+
return this.check([247], { offset: 3 }) ? {
|
|
1485
|
+
ext: "jls",
|
|
1486
|
+
mime: "image/jls"
|
|
1487
|
+
} : {
|
|
1488
|
+
ext: "jpg",
|
|
1489
|
+
mime: "image/jpeg"
|
|
1490
|
+
};
|
|
1491
|
+
if (this.check([79, 98, 106, 1]))
|
|
1492
|
+
return {
|
|
1493
|
+
ext: "avro",
|
|
1494
|
+
mime: "application/avro"
|
|
1495
|
+
};
|
|
1496
|
+
if (this.checkString("FLIF"))
|
|
1497
|
+
return {
|
|
1498
|
+
ext: "flif",
|
|
1499
|
+
mime: "image/flif"
|
|
1500
|
+
};
|
|
1501
|
+
if (this.checkString("8BPS"))
|
|
1502
|
+
return {
|
|
1503
|
+
ext: "psd",
|
|
1504
|
+
mime: "image/vnd.adobe.photoshop"
|
|
1505
|
+
};
|
|
1506
|
+
if (this.checkString("MPCK"))
|
|
1507
|
+
return {
|
|
1508
|
+
ext: "mpc",
|
|
1509
|
+
mime: "audio/x-musepack"
|
|
1510
|
+
};
|
|
1511
|
+
if (this.checkString("FORM"))
|
|
1512
|
+
return {
|
|
1513
|
+
ext: "aif",
|
|
1514
|
+
mime: "audio/aiff"
|
|
1515
|
+
};
|
|
1516
|
+
if (this.checkString("icns", { offset: 0 }))
|
|
1517
|
+
return {
|
|
1518
|
+
ext: "icns",
|
|
1519
|
+
mime: "image/icns"
|
|
1520
|
+
};
|
|
1521
|
+
if (this.check([80, 75, 3, 4])) {
|
|
1522
|
+
let fileType, openXmlState = createOpenXmlZipDetectionState();
|
|
1523
|
+
try {
|
|
1524
|
+
await new ZipHandler(tokenizer).unzip((zipHeader) => {
|
|
1525
|
+
updateOpenXmlZipDetectionStateFromFilename(openXmlState, zipHeader.filename);
|
|
1526
|
+
let isOpenXmlContentTypesEntry = zipHeader.filename === "[Content_Types].xml", openXmlFileTypeFromEntries = getOpenXmlFileTypeFromZipEntries(openXmlState);
|
|
1527
|
+
if (!isOpenXmlContentTypesEntry && openXmlFileTypeFromEntries)
|
|
1528
|
+
return fileType = openXmlFileTypeFromEntries, {
|
|
1529
|
+
stop: !0
|
|
1530
|
+
};
|
|
1531
|
+
switch (zipHeader.filename) {
|
|
1532
|
+
case "META-INF/mozilla.rsa":
|
|
1533
|
+
return fileType = {
|
|
1534
|
+
ext: "xpi",
|
|
1535
|
+
mime: "application/x-xpinstall"
|
|
1536
|
+
}, {
|
|
1537
|
+
stop: !0
|
|
1538
|
+
};
|
|
1539
|
+
case "META-INF/MANIFEST.MF":
|
|
1540
|
+
return fileType = {
|
|
1541
|
+
ext: "jar",
|
|
1542
|
+
mime: "application/java-archive"
|
|
1543
|
+
}, {
|
|
1544
|
+
stop: !0
|
|
1545
|
+
};
|
|
1546
|
+
case "mimetype":
|
|
1547
|
+
return canReadZipEntryForDetection(zipHeader, maximumZipTextEntrySizeInBytes) ? {
|
|
1548
|
+
async handler(fileData) {
|
|
1549
|
+
let mimeType = new TextDecoder("utf-8").decode(fileData).trim();
|
|
1550
|
+
fileType = getFileTypeFromMimeType(mimeType);
|
|
1551
|
+
},
|
|
1552
|
+
stop: !0
|
|
1553
|
+
} : {};
|
|
1554
|
+
case "[Content_Types].xml":
|
|
1555
|
+
return openXmlState.hasContentTypesEntry = !0, canReadZipEntryForDetection(zipHeader, maximumZipTextEntrySizeInBytes) ? (openXmlState.isParsingContentTypes = !0, {
|
|
1556
|
+
async handler(fileData) {
|
|
1557
|
+
let xmlContent = new TextDecoder("utf-8").decode(fileData), mimeType = getOpenXmlMimeTypeFromContentTypesXml(xmlContent);
|
|
1558
|
+
mimeType && (fileType = getFileTypeFromMimeType(mimeType)), openXmlState.hasParsedContentTypesEntry = !0, openXmlState.isParsingContentTypes = !1;
|
|
1559
|
+
},
|
|
1560
|
+
stop: !0
|
|
1561
|
+
}) : (openXmlState.hasUnparseableContentTypes = !0, {});
|
|
1562
|
+
default:
|
|
1563
|
+
return /classes\d*\.dex/.test(zipHeader.filename) ? (fileType = {
|
|
1564
|
+
ext: "apk",
|
|
1565
|
+
mime: "application/vnd.android.package-archive"
|
|
1566
|
+
}, { stop: !0 }) : {};
|
|
1567
|
+
}
|
|
1568
|
+
});
|
|
1569
|
+
} catch (error) {
|
|
1570
|
+
if (!isRecoverableZipError(error))
|
|
1571
|
+
throw error;
|
|
1572
|
+
openXmlState.isParsingContentTypes && (openXmlState.isParsingContentTypes = !1, openXmlState.hasUnparseableContentTypes = !0);
|
|
1573
|
+
}
|
|
1574
|
+
return fileType ?? getOpenXmlFileTypeFromZipEntries(openXmlState) ?? {
|
|
1575
|
+
ext: "zip",
|
|
1576
|
+
mime: "application/zip"
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
if (this.checkString("OggS")) {
|
|
1580
|
+
await tokenizer.ignore(28);
|
|
1581
|
+
let type = new Uint8Array(8);
|
|
1582
|
+
return await tokenizer.readBuffer(type), _check(type, [79, 112, 117, 115, 72, 101, 97, 100]) ? {
|
|
1583
|
+
ext: "opus",
|
|
1584
|
+
mime: "audio/ogg; codecs=opus"
|
|
1585
|
+
} : _check(type, [128, 116, 104, 101, 111, 114, 97]) ? {
|
|
1586
|
+
ext: "ogv",
|
|
1587
|
+
mime: "video/ogg"
|
|
1588
|
+
} : _check(type, [1, 118, 105, 100, 101, 111, 0]) ? {
|
|
1589
|
+
ext: "ogm",
|
|
1590
|
+
mime: "video/ogg"
|
|
1591
|
+
} : _check(type, [127, 70, 76, 65, 67]) ? {
|
|
1592
|
+
ext: "oga",
|
|
1593
|
+
mime: "audio/ogg"
|
|
1594
|
+
} : _check(type, [83, 112, 101, 101, 120, 32, 32]) ? {
|
|
1595
|
+
ext: "spx",
|
|
1596
|
+
mime: "audio/ogg"
|
|
1597
|
+
} : _check(type, [1, 118, 111, 114, 98, 105, 115]) ? {
|
|
1598
|
+
ext: "ogg",
|
|
1599
|
+
mime: "audio/ogg"
|
|
1600
|
+
} : {
|
|
1601
|
+
ext: "ogx",
|
|
1602
|
+
mime: "application/ogg"
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
if (this.check([80, 75]) && (this.buffer[2] === 3 || this.buffer[2] === 5 || this.buffer[2] === 7) && (this.buffer[3] === 4 || this.buffer[3] === 6 || this.buffer[3] === 8))
|
|
1606
|
+
return {
|
|
1607
|
+
ext: "zip",
|
|
1608
|
+
mime: "application/zip"
|
|
1609
|
+
};
|
|
1610
|
+
if (this.checkString("MThd"))
|
|
1611
|
+
return {
|
|
1612
|
+
ext: "mid",
|
|
1613
|
+
mime: "audio/midi"
|
|
1614
|
+
};
|
|
1615
|
+
if (this.checkString("wOFF") && (this.check([0, 1, 0, 0], { offset: 4 }) || this.checkString("OTTO", { offset: 4 })))
|
|
1616
|
+
return {
|
|
1617
|
+
ext: "woff",
|
|
1618
|
+
mime: "font/woff"
|
|
1619
|
+
};
|
|
1620
|
+
if (this.checkString("wOF2") && (this.check([0, 1, 0, 0], { offset: 4 }) || this.checkString("OTTO", { offset: 4 })))
|
|
1621
|
+
return {
|
|
1622
|
+
ext: "woff2",
|
|
1623
|
+
mime: "font/woff2"
|
|
1624
|
+
};
|
|
1625
|
+
if (this.check([212, 195, 178, 161]) || this.check([161, 178, 195, 212]))
|
|
1626
|
+
return {
|
|
1627
|
+
ext: "pcap",
|
|
1628
|
+
mime: "application/vnd.tcpdump.pcap"
|
|
1629
|
+
};
|
|
1630
|
+
if (this.checkString("DSD "))
|
|
1631
|
+
return {
|
|
1632
|
+
ext: "dsf",
|
|
1633
|
+
mime: "audio/x-dsf"
|
|
1634
|
+
// Non-standard
|
|
1635
|
+
};
|
|
1636
|
+
if (this.checkString("LZIP"))
|
|
1637
|
+
return {
|
|
1638
|
+
ext: "lz",
|
|
1639
|
+
mime: "application/x-lzip"
|
|
1640
|
+
};
|
|
1641
|
+
if (this.checkString("fLaC"))
|
|
1642
|
+
return {
|
|
1643
|
+
ext: "flac",
|
|
1644
|
+
mime: "audio/flac"
|
|
1645
|
+
};
|
|
1646
|
+
if (this.check([66, 80, 71, 251]))
|
|
1647
|
+
return {
|
|
1648
|
+
ext: "bpg",
|
|
1649
|
+
mime: "image/bpg"
|
|
1650
|
+
};
|
|
1651
|
+
if (this.checkString("wvpk"))
|
|
1652
|
+
return {
|
|
1653
|
+
ext: "wv",
|
|
1654
|
+
mime: "audio/wavpack"
|
|
1655
|
+
};
|
|
1656
|
+
if (this.checkString("%PDF"))
|
|
1657
|
+
return {
|
|
1658
|
+
ext: "pdf",
|
|
1659
|
+
mime: "application/pdf"
|
|
1660
|
+
};
|
|
1661
|
+
if (this.check([0, 97, 115, 109]))
|
|
1662
|
+
return {
|
|
1663
|
+
ext: "wasm",
|
|
1664
|
+
mime: "application/wasm"
|
|
1665
|
+
};
|
|
1666
|
+
if (this.check([73, 73])) {
|
|
1667
|
+
let fileType = await this.readTiffHeader(!1);
|
|
1668
|
+
if (fileType)
|
|
1669
|
+
return fileType;
|
|
1670
|
+
}
|
|
1671
|
+
if (this.check([77, 77])) {
|
|
1672
|
+
let fileType = await this.readTiffHeader(!0);
|
|
1673
|
+
if (fileType)
|
|
1674
|
+
return fileType;
|
|
1675
|
+
}
|
|
1676
|
+
if (this.checkString("MAC "))
|
|
1677
|
+
return {
|
|
1678
|
+
ext: "ape",
|
|
1679
|
+
mime: "audio/ape"
|
|
1680
|
+
};
|
|
1681
|
+
if (this.check([26, 69, 223, 163])) {
|
|
1682
|
+
async function readField() {
|
|
1683
|
+
let msb = await tokenizer.peekNumber(UINT8), mask = 128, ic = 0;
|
|
1684
|
+
for (; (msb & mask) === 0 && mask !== 0; )
|
|
1685
|
+
++ic, mask >>= 1;
|
|
1686
|
+
let id = new Uint8Array(ic + 1);
|
|
1687
|
+
return await safeReadBuffer(tokenizer, id, void 0, {
|
|
1688
|
+
maximumLength: id.length,
|
|
1689
|
+
reason: "EBML field"
|
|
1690
|
+
}), id;
|
|
1691
|
+
}
|
|
1692
|
+
async function readElement() {
|
|
1693
|
+
let idField = await readField(), lengthField = await readField();
|
|
1694
|
+
lengthField[0] ^= 128 >> lengthField.length - 1;
|
|
1695
|
+
let nrLength = Math.min(6, lengthField.length), idView = new DataView(idField.buffer), lengthView = new DataView(lengthField.buffer, lengthField.length - nrLength, nrLength);
|
|
1696
|
+
return {
|
|
1697
|
+
id: getUintBE(idView),
|
|
1698
|
+
len: getUintBE(lengthView)
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
async function readChildren(children) {
|
|
1702
|
+
let ebmlElementCount = 0;
|
|
1703
|
+
for (; children > 0; ) {
|
|
1704
|
+
if (ebmlElementCount++, ebmlElementCount > maximumEbmlElementCount || hasExceededUnknownSizeScanBudget(tokenizer, ebmlScanStart, maximumUntrustedSkipSizeInBytes))
|
|
1705
|
+
return;
|
|
1706
|
+
let previousPosition = tokenizer.position, element = await readElement();
|
|
1707
|
+
if (element.id === 17026) {
|
|
1708
|
+
if (element.len > maximumEbmlDocumentTypeSizeInBytes)
|
|
1709
|
+
return;
|
|
1710
|
+
let documentTypeLength = getSafeBound(element.len, maximumEbmlDocumentTypeSizeInBytes, "EBML DocType");
|
|
1711
|
+
return (await tokenizer.readToken(new StringType(documentTypeLength))).replaceAll(/\00.*$/g, "");
|
|
1712
|
+
}
|
|
1713
|
+
if (hasUnknownFileSize(tokenizer) && (!Number.isFinite(element.len) || element.len < 0 || element.len > maximumEbmlElementPayloadSizeInBytes) || (await safeIgnore(tokenizer, element.len, {
|
|
1714
|
+
maximumLength: hasUnknownFileSize(tokenizer) ? maximumEbmlElementPayloadSizeInBytes : tokenizer.fileInfo.size,
|
|
1715
|
+
reason: "EBML payload"
|
|
1716
|
+
}), --children, tokenizer.position <= previousPosition))
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
let rootElement = await readElement(), ebmlScanStart = tokenizer.position;
|
|
1721
|
+
switch (await readChildren(rootElement.len)) {
|
|
1722
|
+
case "webm":
|
|
1723
|
+
return {
|
|
1724
|
+
ext: "webm",
|
|
1725
|
+
mime: "video/webm"
|
|
1726
|
+
};
|
|
1727
|
+
case "matroska":
|
|
1728
|
+
return {
|
|
1729
|
+
ext: "mkv",
|
|
1730
|
+
mime: "video/matroska"
|
|
1731
|
+
};
|
|
1732
|
+
default:
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
if (this.checkString("SQLi"))
|
|
1737
|
+
return {
|
|
1738
|
+
ext: "sqlite",
|
|
1739
|
+
mime: "application/x-sqlite3"
|
|
1740
|
+
};
|
|
1741
|
+
if (this.check([78, 69, 83, 26]))
|
|
1742
|
+
return {
|
|
1743
|
+
ext: "nes",
|
|
1744
|
+
mime: "application/x-nintendo-nes-rom"
|
|
1745
|
+
};
|
|
1746
|
+
if (this.checkString("Cr24"))
|
|
1747
|
+
return {
|
|
1748
|
+
ext: "crx",
|
|
1749
|
+
mime: "application/x-google-chrome-extension"
|
|
1750
|
+
};
|
|
1751
|
+
if (this.checkString("MSCF") || this.checkString("ISc("))
|
|
1752
|
+
return {
|
|
1753
|
+
ext: "cab",
|
|
1754
|
+
mime: "application/vnd.ms-cab-compressed"
|
|
1755
|
+
};
|
|
1756
|
+
if (this.check([237, 171, 238, 219]))
|
|
1757
|
+
return {
|
|
1758
|
+
ext: "rpm",
|
|
1759
|
+
mime: "application/x-rpm"
|
|
1760
|
+
};
|
|
1761
|
+
if (this.check([197, 208, 211, 198]))
|
|
1762
|
+
return {
|
|
1763
|
+
ext: "eps",
|
|
1764
|
+
mime: "application/eps"
|
|
1765
|
+
};
|
|
1766
|
+
if (this.check([40, 181, 47, 253]))
|
|
1767
|
+
return {
|
|
1768
|
+
ext: "zst",
|
|
1769
|
+
mime: "application/zstd"
|
|
1770
|
+
};
|
|
1771
|
+
if (this.check([127, 69, 76, 70]))
|
|
1772
|
+
return {
|
|
1773
|
+
ext: "elf",
|
|
1774
|
+
mime: "application/x-elf"
|
|
1775
|
+
};
|
|
1776
|
+
if (this.check([33, 66, 68, 78]))
|
|
1777
|
+
return {
|
|
1778
|
+
ext: "pst",
|
|
1779
|
+
mime: "application/vnd.ms-outlook"
|
|
1780
|
+
};
|
|
1781
|
+
if (this.checkString("PAR1") || this.checkString("PARE"))
|
|
1782
|
+
return {
|
|
1783
|
+
ext: "parquet",
|
|
1784
|
+
mime: "application/vnd.apache.parquet"
|
|
1785
|
+
};
|
|
1786
|
+
if (this.checkString("ttcf"))
|
|
1787
|
+
return {
|
|
1788
|
+
ext: "ttc",
|
|
1789
|
+
mime: "font/collection"
|
|
1790
|
+
};
|
|
1791
|
+
if (this.check([254, 237, 250, 206]) || this.check([254, 237, 250, 207]) || this.check([206, 250, 237, 254]) || this.check([207, 250, 237, 254]))
|
|
1792
|
+
return {
|
|
1793
|
+
ext: "macho",
|
|
1794
|
+
mime: "application/x-mach-binary"
|
|
1795
|
+
};
|
|
1796
|
+
if (this.check([4, 34, 77, 24]))
|
|
1797
|
+
return {
|
|
1798
|
+
ext: "lz4",
|
|
1799
|
+
mime: "application/x-lz4"
|
|
1800
|
+
// Invented by us
|
|
1801
|
+
};
|
|
1802
|
+
if (this.checkString("regf"))
|
|
1803
|
+
return {
|
|
1804
|
+
ext: "dat",
|
|
1805
|
+
mime: "application/x-ft-windows-registry-hive"
|
|
1806
|
+
};
|
|
1807
|
+
if (this.checkString("$FL2") || this.checkString("$FL3"))
|
|
1808
|
+
return {
|
|
1809
|
+
ext: "sav",
|
|
1810
|
+
mime: "application/x-spss-sav"
|
|
1811
|
+
};
|
|
1812
|
+
if (this.check([79, 84, 84, 79, 0]))
|
|
1813
|
+
return {
|
|
1814
|
+
ext: "otf",
|
|
1815
|
+
mime: "font/otf"
|
|
1816
|
+
};
|
|
1817
|
+
if (this.checkString("#!AMR"))
|
|
1818
|
+
return {
|
|
1819
|
+
ext: "amr",
|
|
1820
|
+
mime: "audio/amr"
|
|
1821
|
+
};
|
|
1822
|
+
if (this.checkString("{\\rtf"))
|
|
1823
|
+
return {
|
|
1824
|
+
ext: "rtf",
|
|
1825
|
+
mime: "application/rtf"
|
|
1826
|
+
};
|
|
1827
|
+
if (this.check([70, 76, 86, 1]))
|
|
1828
|
+
return {
|
|
1829
|
+
ext: "flv",
|
|
1830
|
+
mime: "video/x-flv"
|
|
1831
|
+
};
|
|
1832
|
+
if (this.checkString("IMPM"))
|
|
1833
|
+
return {
|
|
1834
|
+
ext: "it",
|
|
1835
|
+
mime: "audio/x-it"
|
|
1836
|
+
};
|
|
1837
|
+
if (this.checkString("-lh0-", { offset: 2 }) || this.checkString("-lh1-", { offset: 2 }) || this.checkString("-lh2-", { offset: 2 }) || this.checkString("-lh3-", { offset: 2 }) || this.checkString("-lh4-", { offset: 2 }) || this.checkString("-lh5-", { offset: 2 }) || this.checkString("-lh6-", { offset: 2 }) || this.checkString("-lh7-", { offset: 2 }) || this.checkString("-lzs-", { offset: 2 }) || this.checkString("-lz4-", { offset: 2 }) || this.checkString("-lz5-", { offset: 2 }) || this.checkString("-lhd-", { offset: 2 }))
|
|
1838
|
+
return {
|
|
1839
|
+
ext: "lzh",
|
|
1840
|
+
mime: "application/x-lzh-compressed"
|
|
1841
|
+
};
|
|
1842
|
+
if (this.check([0, 0, 1, 186])) {
|
|
1843
|
+
if (this.check([33], { offset: 4, mask: [241] }))
|
|
1844
|
+
return {
|
|
1845
|
+
ext: "mpg",
|
|
1846
|
+
// May also be .ps, .mpeg
|
|
1847
|
+
mime: "video/MP1S"
|
|
1848
|
+
};
|
|
1849
|
+
if (this.check([68], { offset: 4, mask: [196] }))
|
|
1850
|
+
return {
|
|
1851
|
+
ext: "mpg",
|
|
1852
|
+
// May also be .mpg, .m2p, .vob or .sub
|
|
1853
|
+
mime: "video/MP2P"
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
if (this.checkString("ITSF"))
|
|
1857
|
+
return {
|
|
1858
|
+
ext: "chm",
|
|
1859
|
+
mime: "application/vnd.ms-htmlhelp"
|
|
1860
|
+
};
|
|
1861
|
+
if (this.check([202, 254, 186, 190])) {
|
|
1862
|
+
let machOArchitectureCount = UINT32_BE.get(this.buffer, 4), javaClassFileMajorVersion = UINT16_BE.get(this.buffer, 6);
|
|
1863
|
+
if (machOArchitectureCount > 0 && machOArchitectureCount <= 30)
|
|
1864
|
+
return {
|
|
1865
|
+
ext: "macho",
|
|
1866
|
+
mime: "application/x-mach-binary"
|
|
1867
|
+
};
|
|
1868
|
+
if (javaClassFileMajorVersion > 30)
|
|
1869
|
+
return {
|
|
1870
|
+
ext: "class",
|
|
1871
|
+
mime: "application/java-vm"
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
if (this.checkString(".RMF"))
|
|
1875
|
+
return {
|
|
1876
|
+
ext: "rm",
|
|
1877
|
+
mime: "application/vnd.rn-realmedia"
|
|
1878
|
+
};
|
|
1879
|
+
if (this.checkString("DRACO"))
|
|
1880
|
+
return {
|
|
1881
|
+
ext: "drc",
|
|
1882
|
+
mime: "application/vnd.google.draco"
|
|
1883
|
+
// Invented by us
|
|
1884
|
+
};
|
|
1885
|
+
if (this.check([253, 55, 122, 88, 90, 0]))
|
|
1886
|
+
return {
|
|
1887
|
+
ext: "xz",
|
|
1888
|
+
mime: "application/x-xz"
|
|
1889
|
+
};
|
|
1890
|
+
if (this.checkString("<?xml "))
|
|
1891
|
+
return {
|
|
1892
|
+
ext: "xml",
|
|
1893
|
+
mime: "application/xml"
|
|
1894
|
+
};
|
|
1895
|
+
if (this.check([55, 122, 188, 175, 39, 28]))
|
|
1896
|
+
return {
|
|
1897
|
+
ext: "7z",
|
|
1898
|
+
mime: "application/x-7z-compressed"
|
|
1899
|
+
};
|
|
1900
|
+
if (this.check([82, 97, 114, 33, 26, 7]) && (this.buffer[6] === 0 || this.buffer[6] === 1))
|
|
1901
|
+
return {
|
|
1902
|
+
ext: "rar",
|
|
1903
|
+
mime: "application/x-rar-compressed"
|
|
1904
|
+
};
|
|
1905
|
+
if (this.checkString("solid "))
|
|
1906
|
+
return {
|
|
1907
|
+
ext: "stl",
|
|
1908
|
+
mime: "model/stl"
|
|
1909
|
+
};
|
|
1910
|
+
if (this.checkString("AC")) {
|
|
1911
|
+
let version = new StringType(4, "latin1").get(this.buffer, 2);
|
|
1912
|
+
if (version.match("^d*") && version >= 1e3 && version <= 1050)
|
|
1913
|
+
return {
|
|
1914
|
+
ext: "dwg",
|
|
1915
|
+
mime: "image/vnd.dwg"
|
|
1916
|
+
};
|
|
1917
|
+
}
|
|
1918
|
+
if (this.checkString("070707"))
|
|
1919
|
+
return {
|
|
1920
|
+
ext: "cpio",
|
|
1921
|
+
mime: "application/x-cpio"
|
|
1922
|
+
};
|
|
1923
|
+
if (this.checkString("BLENDER"))
|
|
1924
|
+
return {
|
|
1925
|
+
ext: "blend",
|
|
1926
|
+
mime: "application/x-blender"
|
|
1927
|
+
};
|
|
1928
|
+
if (this.checkString("!<arch>"))
|
|
1929
|
+
return await tokenizer.ignore(8), await tokenizer.readToken(new StringType(13, "ascii")) === "debian-binary" ? {
|
|
1930
|
+
ext: "deb",
|
|
1931
|
+
mime: "application/x-deb"
|
|
1932
|
+
} : {
|
|
1933
|
+
ext: "ar",
|
|
1934
|
+
mime: "application/x-unix-archive"
|
|
1935
|
+
};
|
|
1936
|
+
if (this.checkString("WEBVTT") && // One of LF, CR, tab, space, or end of file must follow "WEBVTT" per the spec (see `fixture/fixture-vtt-*.vtt` for examples). Note that `\0` is technically the null character (there is no such thing as an EOF character). However, checking for `\0` gives us the same result as checking for the end of the stream.
|
|
1937
|
+
[`
|
|
1938
|
+
`, "\r", " ", " ", "\0"].some((char7) => this.checkString(char7, { offset: 6 })))
|
|
1939
|
+
return {
|
|
1940
|
+
ext: "vtt",
|
|
1941
|
+
mime: "text/vtt"
|
|
1942
|
+
};
|
|
1943
|
+
if (this.check([137, 80, 78, 71, 13, 10, 26, 10])) {
|
|
1944
|
+
let pngFileType = {
|
|
1945
|
+
ext: "png",
|
|
1946
|
+
mime: "image/png"
|
|
1947
|
+
}, apngFileType = {
|
|
1948
|
+
ext: "apng",
|
|
1949
|
+
mime: "image/apng"
|
|
1950
|
+
};
|
|
1951
|
+
await tokenizer.ignore(8);
|
|
1952
|
+
async function readChunkHeader() {
|
|
1953
|
+
return {
|
|
1954
|
+
length: await tokenizer.readToken(INT32_BE),
|
|
1955
|
+
type: await tokenizer.readToken(new StringType(4, "latin1"))
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
let isUnknownPngStream = hasUnknownFileSize(tokenizer), pngScanStart = tokenizer.position, pngChunkCount = 0, hasSeenImageHeader = !1;
|
|
1959
|
+
do {
|
|
1960
|
+
if (pngChunkCount++, pngChunkCount > maximumPngChunkCount || hasExceededUnknownSizeScanBudget(tokenizer, pngScanStart, maximumPngStreamScanBudgetInBytes))
|
|
1961
|
+
break;
|
|
1962
|
+
let previousPosition = tokenizer.position, chunk = await readChunkHeader();
|
|
1963
|
+
if (chunk.length < 0)
|
|
1964
|
+
return;
|
|
1965
|
+
if (chunk.type === "IHDR") {
|
|
1966
|
+
if (chunk.length !== 13)
|
|
1967
|
+
return;
|
|
1968
|
+
hasSeenImageHeader = !0;
|
|
1969
|
+
}
|
|
1970
|
+
switch (chunk.type) {
|
|
1971
|
+
case "IDAT":
|
|
1972
|
+
return pngFileType;
|
|
1973
|
+
case "acTL":
|
|
1974
|
+
return apngFileType;
|
|
1975
|
+
default:
|
|
1976
|
+
if (!hasSeenImageHeader && chunk.type !== "CgBI")
|
|
1977
|
+
return;
|
|
1978
|
+
if (isUnknownPngStream && chunk.length > maximumPngChunkSizeInBytes)
|
|
1979
|
+
return hasSeenImageHeader && isPngAncillaryChunk(chunk.type) ? pngFileType : void 0;
|
|
1980
|
+
try {
|
|
1981
|
+
await safeIgnore(tokenizer, chunk.length + 4, {
|
|
1982
|
+
maximumLength: isUnknownPngStream ? maximumPngChunkSizeInBytes + 4 : tokenizer.fileInfo.size,
|
|
1983
|
+
reason: "PNG chunk payload"
|
|
1984
|
+
});
|
|
1985
|
+
} catch (error) {
|
|
1986
|
+
if (!isUnknownPngStream && (error instanceof ParserHardLimitError || error instanceof EndOfStreamError))
|
|
1987
|
+
return pngFileType;
|
|
1988
|
+
throw error;
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
if (tokenizer.position <= previousPosition)
|
|
1992
|
+
break;
|
|
1993
|
+
} while (tokenizer.position + 8 < tokenizer.fileInfo.size);
|
|
1994
|
+
return pngFileType;
|
|
1995
|
+
}
|
|
1996
|
+
if (this.check([65, 82, 82, 79, 87, 49, 0, 0]))
|
|
1997
|
+
return {
|
|
1998
|
+
ext: "arrow",
|
|
1999
|
+
mime: "application/vnd.apache.arrow.file"
|
|
2000
|
+
};
|
|
2001
|
+
if (this.check([103, 108, 84, 70, 2, 0, 0, 0]))
|
|
2002
|
+
return {
|
|
2003
|
+
ext: "glb",
|
|
2004
|
+
mime: "model/gltf-binary"
|
|
2005
|
+
};
|
|
2006
|
+
if (this.check([102, 114, 101, 101], { offset: 4 }) || this.check([109, 100, 97, 116], { offset: 4 }) || this.check([109, 111, 111, 118], { offset: 4 }) || this.check([119, 105, 100, 101], { offset: 4 }))
|
|
2007
|
+
return {
|
|
2008
|
+
ext: "mov",
|
|
2009
|
+
mime: "video/quicktime"
|
|
2010
|
+
};
|
|
2011
|
+
if (this.check([73, 73, 82, 79, 8, 0, 0, 0, 24]))
|
|
2012
|
+
return {
|
|
2013
|
+
ext: "orf",
|
|
2014
|
+
mime: "image/x-olympus-orf"
|
|
2015
|
+
};
|
|
2016
|
+
if (this.checkString("gimp xcf "))
|
|
2017
|
+
return {
|
|
2018
|
+
ext: "xcf",
|
|
2019
|
+
mime: "image/x-xcf"
|
|
2020
|
+
};
|
|
2021
|
+
if (this.checkString("ftyp", { offset: 4 }) && (this.buffer[8] & 96) !== 0) {
|
|
2022
|
+
let brandMajor = new StringType(4, "latin1").get(this.buffer, 8).replace("\0", " ").trim();
|
|
2023
|
+
switch (brandMajor) {
|
|
2024
|
+
case "avif":
|
|
2025
|
+
case "avis":
|
|
2026
|
+
return { ext: "avif", mime: "image/avif" };
|
|
2027
|
+
case "mif1":
|
|
2028
|
+
return { ext: "heic", mime: "image/heif" };
|
|
2029
|
+
case "msf1":
|
|
2030
|
+
return { ext: "heic", mime: "image/heif-sequence" };
|
|
2031
|
+
case "heic":
|
|
2032
|
+
case "heix":
|
|
2033
|
+
return { ext: "heic", mime: "image/heic" };
|
|
2034
|
+
case "hevc":
|
|
2035
|
+
case "hevx":
|
|
2036
|
+
return { ext: "heic", mime: "image/heic-sequence" };
|
|
2037
|
+
case "qt":
|
|
2038
|
+
return { ext: "mov", mime: "video/quicktime" };
|
|
2039
|
+
case "M4V":
|
|
2040
|
+
case "M4VH":
|
|
2041
|
+
case "M4VP":
|
|
2042
|
+
return { ext: "m4v", mime: "video/x-m4v" };
|
|
2043
|
+
case "M4P":
|
|
2044
|
+
return { ext: "m4p", mime: "video/mp4" };
|
|
2045
|
+
case "M4B":
|
|
2046
|
+
return { ext: "m4b", mime: "audio/mp4" };
|
|
2047
|
+
case "M4A":
|
|
2048
|
+
return { ext: "m4a", mime: "audio/x-m4a" };
|
|
2049
|
+
case "F4V":
|
|
2050
|
+
return { ext: "f4v", mime: "video/mp4" };
|
|
2051
|
+
case "F4P":
|
|
2052
|
+
return { ext: "f4p", mime: "video/mp4" };
|
|
2053
|
+
case "F4A":
|
|
2054
|
+
return { ext: "f4a", mime: "audio/mp4" };
|
|
2055
|
+
case "F4B":
|
|
2056
|
+
return { ext: "f4b", mime: "audio/mp4" };
|
|
2057
|
+
case "crx":
|
|
2058
|
+
return { ext: "cr3", mime: "image/x-canon-cr3" };
|
|
2059
|
+
default:
|
|
2060
|
+
return brandMajor.startsWith("3g") ? brandMajor.startsWith("3g2") ? { ext: "3g2", mime: "video/3gpp2" } : { ext: "3gp", mime: "video/3gpp" } : { ext: "mp4", mime: "video/mp4" };
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
if (this.checkString(`REGEDIT4\r
|
|
2064
|
+
`))
|
|
2065
|
+
return {
|
|
2066
|
+
ext: "reg",
|
|
2067
|
+
mime: "application/x-ms-regedit"
|
|
2068
|
+
};
|
|
2069
|
+
if (this.check([82, 73, 70, 70])) {
|
|
2070
|
+
if (this.checkString("WEBP", { offset: 8 }))
|
|
2071
|
+
return {
|
|
2072
|
+
ext: "webp",
|
|
2073
|
+
mime: "image/webp"
|
|
2074
|
+
};
|
|
2075
|
+
if (this.check([65, 86, 73], { offset: 8 }))
|
|
2076
|
+
return {
|
|
2077
|
+
ext: "avi",
|
|
2078
|
+
mime: "video/vnd.avi"
|
|
2079
|
+
};
|
|
2080
|
+
if (this.check([87, 65, 86, 69], { offset: 8 }))
|
|
2081
|
+
return {
|
|
2082
|
+
ext: "wav",
|
|
2083
|
+
mime: "audio/wav"
|
|
2084
|
+
};
|
|
2085
|
+
if (this.check([81, 76, 67, 77], { offset: 8 }))
|
|
2086
|
+
return {
|
|
2087
|
+
ext: "qcp",
|
|
2088
|
+
mime: "audio/qcelp"
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
2091
|
+
if (this.check([73, 73, 85, 0, 24, 0, 0, 0, 136, 231, 116, 216]))
|
|
2092
|
+
return {
|
|
2093
|
+
ext: "rw2",
|
|
2094
|
+
mime: "image/x-panasonic-rw2"
|
|
2095
|
+
};
|
|
2096
|
+
if (this.check([48, 38, 178, 117, 142, 102, 207, 17, 166, 217])) {
|
|
2097
|
+
let isMalformedAsf = !1;
|
|
2098
|
+
try {
|
|
2099
|
+
async function readHeader() {
|
|
2100
|
+
let guid = new Uint8Array(16);
|
|
2101
|
+
return await safeReadBuffer(tokenizer, guid, void 0, {
|
|
2102
|
+
maximumLength: guid.length,
|
|
2103
|
+
reason: "ASF header GUID"
|
|
2104
|
+
}), {
|
|
2105
|
+
id: guid,
|
|
2106
|
+
size: Number(await tokenizer.readToken(UINT64_LE))
|
|
2107
|
+
};
|
|
2108
|
+
}
|
|
2109
|
+
await safeIgnore(tokenizer, 30, {
|
|
2110
|
+
maximumLength: 30,
|
|
2111
|
+
reason: "ASF header prelude"
|
|
2112
|
+
});
|
|
2113
|
+
let isUnknownFileSize = hasUnknownFileSize(tokenizer), asfHeaderScanStart = tokenizer.position, asfHeaderObjectCount = 0;
|
|
2114
|
+
for (; tokenizer.position + 24 < tokenizer.fileInfo.size && (asfHeaderObjectCount++, !(asfHeaderObjectCount > maximumAsfHeaderObjectCount || hasExceededUnknownSizeScanBudget(tokenizer, asfHeaderScanStart, maximumUntrustedSkipSizeInBytes))); ) {
|
|
2115
|
+
let previousPosition = tokenizer.position, header = await readHeader(), payload = header.size - 24;
|
|
2116
|
+
if (!Number.isFinite(payload) || payload < 0) {
|
|
2117
|
+
isMalformedAsf = !0;
|
|
2118
|
+
break;
|
|
2119
|
+
}
|
|
2120
|
+
if (_check(header.id, [145, 7, 220, 183, 183, 169, 207, 17, 142, 230, 0, 192, 12, 32, 83, 101])) {
|
|
2121
|
+
let typeId = new Uint8Array(16);
|
|
2122
|
+
if (payload -= await safeReadBuffer(tokenizer, typeId, void 0, {
|
|
2123
|
+
maximumLength: typeId.length,
|
|
2124
|
+
reason: "ASF stream type GUID"
|
|
2125
|
+
}), _check(typeId, [64, 158, 105, 248, 77, 91, 207, 17, 168, 253, 0, 128, 95, 92, 68, 43]))
|
|
2126
|
+
return {
|
|
2127
|
+
ext: "asf",
|
|
2128
|
+
mime: "audio/x-ms-asf"
|
|
2129
|
+
};
|
|
2130
|
+
if (_check(typeId, [192, 239, 25, 188, 77, 91, 207, 17, 168, 253, 0, 128, 95, 92, 68, 43]))
|
|
2131
|
+
return {
|
|
2132
|
+
ext: "asf",
|
|
2133
|
+
mime: "video/x-ms-asf"
|
|
2134
|
+
};
|
|
2135
|
+
break;
|
|
2136
|
+
}
|
|
2137
|
+
if (isUnknownFileSize && payload > maximumAsfHeaderPayloadSizeInBytes) {
|
|
2138
|
+
isMalformedAsf = !0;
|
|
2139
|
+
break;
|
|
2140
|
+
}
|
|
2141
|
+
if (await safeIgnore(tokenizer, payload, {
|
|
2142
|
+
maximumLength: isUnknownFileSize ? maximumAsfHeaderPayloadSizeInBytes : tokenizer.fileInfo.size,
|
|
2143
|
+
reason: "ASF header payload"
|
|
2144
|
+
}), tokenizer.position <= previousPosition) {
|
|
2145
|
+
isMalformedAsf = !0;
|
|
2146
|
+
break;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
} catch (error) {
|
|
2150
|
+
if (error instanceof EndOfStreamError || error instanceof ParserHardLimitError)
|
|
2151
|
+
hasUnknownFileSize(tokenizer) && (isMalformedAsf = !0);
|
|
2152
|
+
else
|
|
2153
|
+
throw error;
|
|
2154
|
+
}
|
|
2155
|
+
return isMalformedAsf ? void 0 : {
|
|
2156
|
+
ext: "asf",
|
|
2157
|
+
mime: "application/vnd.ms-asf"
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
if (this.check([171, 75, 84, 88, 32, 49, 49, 187, 13, 10, 26, 10]))
|
|
2161
|
+
return {
|
|
2162
|
+
ext: "ktx",
|
|
2163
|
+
mime: "image/ktx"
|
|
2164
|
+
};
|
|
2165
|
+
if ((this.check([126, 16, 4]) || this.check([126, 24, 4])) && this.check([48, 77, 73, 69], { offset: 4 }))
|
|
2166
|
+
return {
|
|
2167
|
+
ext: "mie",
|
|
2168
|
+
mime: "application/x-mie"
|
|
2169
|
+
};
|
|
2170
|
+
if (this.check([39, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], { offset: 2 }))
|
|
2171
|
+
return {
|
|
2172
|
+
ext: "shp",
|
|
2173
|
+
mime: "application/x-esri-shape"
|
|
2174
|
+
};
|
|
2175
|
+
if (this.check([255, 79, 255, 81]))
|
|
2176
|
+
return {
|
|
2177
|
+
ext: "j2c",
|
|
2178
|
+
mime: "image/j2c"
|
|
2179
|
+
};
|
|
2180
|
+
if (this.check([0, 0, 0, 12, 106, 80, 32, 32, 13, 10, 135, 10]))
|
|
2181
|
+
switch (await tokenizer.ignore(20), await tokenizer.readToken(new StringType(4, "ascii"))) {
|
|
2182
|
+
case "jp2 ":
|
|
2183
|
+
return {
|
|
2184
|
+
ext: "jp2",
|
|
2185
|
+
mime: "image/jp2"
|
|
2186
|
+
};
|
|
2187
|
+
case "jpx ":
|
|
2188
|
+
return {
|
|
2189
|
+
ext: "jpx",
|
|
2190
|
+
mime: "image/jpx"
|
|
2191
|
+
};
|
|
2192
|
+
case "jpm ":
|
|
2193
|
+
return {
|
|
2194
|
+
ext: "jpm",
|
|
2195
|
+
mime: "image/jpm"
|
|
2196
|
+
};
|
|
2197
|
+
case "mjp2":
|
|
2198
|
+
return {
|
|
2199
|
+
ext: "mj2",
|
|
2200
|
+
mime: "image/mj2"
|
|
2201
|
+
};
|
|
2202
|
+
default:
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
if (this.check([255, 10]) || this.check([0, 0, 0, 12, 74, 88, 76, 32, 13, 10, 135, 10]))
|
|
2206
|
+
return {
|
|
2207
|
+
ext: "jxl",
|
|
2208
|
+
mime: "image/jxl"
|
|
2209
|
+
};
|
|
2210
|
+
if (this.check([254, 255]))
|
|
2211
|
+
return this.checkString("<?xml ", { offset: 2, encoding: "utf-16be" }) ? {
|
|
2212
|
+
ext: "xml",
|
|
2213
|
+
mime: "application/xml"
|
|
2214
|
+
} : void 0;
|
|
2215
|
+
if (this.check([208, 207, 17, 224, 161, 177, 26, 225]))
|
|
2216
|
+
return {
|
|
2217
|
+
ext: "cfb",
|
|
2218
|
+
mime: "application/x-cfb"
|
|
2219
|
+
};
|
|
2220
|
+
if (await tokenizer.peekBuffer(this.buffer, { length: Math.min(256, tokenizer.fileInfo.size), mayBeLess: !0 }), this.check([97, 99, 115, 112], { offset: 36 }))
|
|
2221
|
+
return {
|
|
2222
|
+
ext: "icc",
|
|
2223
|
+
mime: "application/vnd.iccprofile"
|
|
2224
|
+
};
|
|
2225
|
+
if (this.checkString("**ACE", { offset: 7 }) && this.checkString("**", { offset: 12 }))
|
|
2226
|
+
return {
|
|
2227
|
+
ext: "ace",
|
|
2228
|
+
mime: "application/x-ace-compressed"
|
|
2229
|
+
};
|
|
2230
|
+
if (this.checkString("BEGIN:")) {
|
|
2231
|
+
if (this.checkString("VCARD", { offset: 6 }))
|
|
2232
|
+
return {
|
|
2233
|
+
ext: "vcf",
|
|
2234
|
+
mime: "text/vcard"
|
|
2235
|
+
};
|
|
2236
|
+
if (this.checkString("VCALENDAR", { offset: 6 }))
|
|
2237
|
+
return {
|
|
2238
|
+
ext: "ics",
|
|
2239
|
+
mime: "text/calendar"
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
2242
|
+
if (this.checkString("FUJIFILMCCD-RAW"))
|
|
2243
|
+
return {
|
|
2244
|
+
ext: "raf",
|
|
2245
|
+
mime: "image/x-fujifilm-raf"
|
|
2246
|
+
};
|
|
2247
|
+
if (this.checkString("Extended Module:"))
|
|
2248
|
+
return {
|
|
2249
|
+
ext: "xm",
|
|
2250
|
+
mime: "audio/x-xm"
|
|
2251
|
+
};
|
|
2252
|
+
if (this.checkString("Creative Voice File"))
|
|
2253
|
+
return {
|
|
2254
|
+
ext: "voc",
|
|
2255
|
+
mime: "audio/x-voc"
|
|
2256
|
+
};
|
|
2257
|
+
if (this.check([4, 0, 0, 0]) && this.buffer.length >= 16) {
|
|
2258
|
+
let jsonSize = new DataView(this.buffer.buffer).getUint32(12, !0);
|
|
2259
|
+
if (jsonSize > 12 && this.buffer.length >= jsonSize + 16)
|
|
2260
|
+
try {
|
|
2261
|
+
let header = new TextDecoder().decode(this.buffer.subarray(16, jsonSize + 16));
|
|
2262
|
+
if (JSON.parse(header).files)
|
|
2263
|
+
return {
|
|
2264
|
+
ext: "asar",
|
|
2265
|
+
mime: "application/x-asar"
|
|
2266
|
+
};
|
|
2267
|
+
} catch {
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
if (this.check([6, 14, 43, 52, 2, 5, 1, 1, 13, 1, 2, 1, 1, 2]))
|
|
2271
|
+
return {
|
|
2272
|
+
ext: "mxf",
|
|
2273
|
+
mime: "application/mxf"
|
|
2274
|
+
};
|
|
2275
|
+
if (this.checkString("SCRM", { offset: 44 }))
|
|
2276
|
+
return {
|
|
2277
|
+
ext: "s3m",
|
|
2278
|
+
mime: "audio/x-s3m"
|
|
2279
|
+
};
|
|
2280
|
+
if (this.check([71]) && this.check([71], { offset: 188 }))
|
|
2281
|
+
return {
|
|
2282
|
+
ext: "mts",
|
|
2283
|
+
mime: "video/mp2t"
|
|
2284
|
+
};
|
|
2285
|
+
if (this.check([71], { offset: 4 }) && this.check([71], { offset: 196 }))
|
|
2286
|
+
return {
|
|
2287
|
+
ext: "mts",
|
|
2288
|
+
mime: "video/mp2t"
|
|
2289
|
+
};
|
|
2290
|
+
if (this.check([66, 79, 79, 75, 77, 79, 66, 73], { offset: 60 }))
|
|
2291
|
+
return {
|
|
2292
|
+
ext: "mobi",
|
|
2293
|
+
mime: "application/x-mobipocket-ebook"
|
|
2294
|
+
};
|
|
2295
|
+
if (this.check([68, 73, 67, 77], { offset: 128 }))
|
|
2296
|
+
return {
|
|
2297
|
+
ext: "dcm",
|
|
2298
|
+
mime: "application/dicom"
|
|
2299
|
+
};
|
|
2300
|
+
if (this.check([76, 0, 0, 0, 1, 20, 2, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 70]))
|
|
2301
|
+
return {
|
|
2302
|
+
ext: "lnk",
|
|
2303
|
+
mime: "application/x.ms.shortcut"
|
|
2304
|
+
// Invented by us
|
|
2305
|
+
};
|
|
2306
|
+
if (this.check([98, 111, 111, 107, 0, 0, 0, 0, 109, 97, 114, 107, 0, 0, 0, 0]))
|
|
2307
|
+
return {
|
|
2308
|
+
ext: "alias",
|
|
2309
|
+
mime: "application/x.apple.alias"
|
|
2310
|
+
// Invented by us
|
|
2311
|
+
};
|
|
2312
|
+
if (this.checkString("Kaydara FBX Binary \0"))
|
|
2313
|
+
return {
|
|
2314
|
+
ext: "fbx",
|
|
2315
|
+
mime: "application/x.autodesk.fbx"
|
|
2316
|
+
// Invented by us
|
|
2317
|
+
};
|
|
2318
|
+
if (this.check([76, 80], { offset: 34 }) && (this.check([0, 0, 1], { offset: 8 }) || this.check([1, 0, 2], { offset: 8 }) || this.check([2, 0, 2], { offset: 8 })))
|
|
2319
|
+
return {
|
|
2320
|
+
ext: "eot",
|
|
2321
|
+
mime: "application/vnd.ms-fontobject"
|
|
2322
|
+
};
|
|
2323
|
+
if (this.check([6, 6, 237, 245, 216, 29, 70, 229, 189, 49, 239, 231, 254, 116, 183, 29]))
|
|
2324
|
+
return {
|
|
2325
|
+
ext: "indd",
|
|
2326
|
+
mime: "application/x-indesign"
|
|
2327
|
+
};
|
|
2328
|
+
if (this.check([255, 255, 0, 0, 7, 0, 0, 0, 4, 0, 0, 0, 1, 0, 1, 0]) || this.check([0, 0, 255, 255, 0, 0, 0, 7, 0, 0, 0, 4, 0, 1, 0, 1]))
|
|
2329
|
+
return {
|
|
2330
|
+
ext: "jmp",
|
|
2331
|
+
mime: "application/x-jmp-data"
|
|
2332
|
+
};
|
|
2333
|
+
if (await tokenizer.peekBuffer(this.buffer, { length: Math.min(512, tokenizer.fileInfo.size), mayBeLess: !0 }), this.checkString("ustar", { offset: 257 }) && (this.checkString("\0", { offset: 262 }) || this.checkString(" ", { offset: 262 })) || this.check([0, 0, 0, 0, 0, 0], { offset: 257 }) && tarHeaderChecksumMatches(this.buffer))
|
|
2334
|
+
return {
|
|
2335
|
+
ext: "tar",
|
|
2336
|
+
mime: "application/x-tar"
|
|
2337
|
+
};
|
|
2338
|
+
if (this.check([255, 254])) {
|
|
2339
|
+
let encoding = "utf-16le";
|
|
2340
|
+
return this.checkString("<?xml ", { offset: 2, encoding }) ? {
|
|
2341
|
+
ext: "xml",
|
|
2342
|
+
mime: "application/xml"
|
|
2343
|
+
} : this.check([255, 14], { offset: 2 }) && this.checkString("SketchUp Model", { offset: 4, encoding }) ? {
|
|
2344
|
+
ext: "skp",
|
|
2345
|
+
mime: "application/vnd.sketchup.skp"
|
|
2346
|
+
} : this.checkString(`Windows Registry Editor Version 5.00\r
|
|
2347
|
+
`, { offset: 2, encoding }) ? {
|
|
2348
|
+
ext: "reg",
|
|
2349
|
+
mime: "application/x-ms-regedit"
|
|
2350
|
+
} : void 0;
|
|
2351
|
+
}
|
|
2352
|
+
if (this.checkString("-----BEGIN PGP MESSAGE-----"))
|
|
2353
|
+
return {
|
|
2354
|
+
ext: "pgp",
|
|
2355
|
+
mime: "application/pgp-encrypted"
|
|
2356
|
+
};
|
|
2357
|
+
};
|
|
2358
|
+
// Detections with limited supporting data, resulting in a higher likelihood of false positives
|
|
2359
|
+
detectImprecise = async (tokenizer) => {
|
|
2360
|
+
this.buffer = new Uint8Array(reasonableDetectionSizeInBytes);
|
|
2361
|
+
let fileSize = getKnownFileSizeOrMaximum(tokenizer.fileInfo.size);
|
|
2362
|
+
if (await tokenizer.peekBuffer(this.buffer, { length: Math.min(8, fileSize), mayBeLess: !0 }), this.check([0, 0, 1, 186]) || this.check([0, 0, 1, 179]))
|
|
2363
|
+
return {
|
|
2364
|
+
ext: "mpg",
|
|
2365
|
+
mime: "video/mpeg"
|
|
2366
|
+
};
|
|
2367
|
+
if (this.check([0, 1, 0, 0, 0]))
|
|
2368
|
+
return {
|
|
2369
|
+
ext: "ttf",
|
|
2370
|
+
mime: "font/ttf"
|
|
2371
|
+
};
|
|
2372
|
+
if (this.check([0, 0, 1, 0]))
|
|
2373
|
+
return {
|
|
2374
|
+
ext: "ico",
|
|
2375
|
+
mime: "image/x-icon"
|
|
2376
|
+
};
|
|
2377
|
+
if (this.check([0, 0, 2, 0]))
|
|
2378
|
+
return {
|
|
2379
|
+
ext: "cur",
|
|
2380
|
+
mime: "image/x-icon"
|
|
2381
|
+
};
|
|
2382
|
+
if (await tokenizer.peekBuffer(this.buffer, { length: Math.min(2 + this.options.mpegOffsetTolerance, fileSize), mayBeLess: !0 }), this.buffer.length >= 2 + this.options.mpegOffsetTolerance)
|
|
2383
|
+
for (let depth = 0; depth <= this.options.mpegOffsetTolerance; ++depth) {
|
|
2384
|
+
let type = this.scanMpeg(depth);
|
|
2385
|
+
if (type)
|
|
2386
|
+
return type;
|
|
2387
|
+
}
|
|
2388
|
+
};
|
|
2389
|
+
async readTiffTag(bigEndian) {
|
|
2390
|
+
let tagId = await this.tokenizer.readToken(bigEndian ? UINT16_BE : UINT16_LE);
|
|
2391
|
+
switch (await this.tokenizer.ignore(10), tagId) {
|
|
2392
|
+
case 50341:
|
|
2393
|
+
return {
|
|
2394
|
+
ext: "arw",
|
|
2395
|
+
mime: "image/x-sony-arw"
|
|
2396
|
+
};
|
|
2397
|
+
case 50706:
|
|
2398
|
+
return {
|
|
2399
|
+
ext: "dng",
|
|
2400
|
+
mime: "image/x-adobe-dng"
|
|
2401
|
+
};
|
|
2402
|
+
default:
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
async readTiffIFD(bigEndian) {
|
|
2406
|
+
let numberOfTags = await this.tokenizer.readToken(bigEndian ? UINT16_BE : UINT16_LE);
|
|
2407
|
+
if (!(numberOfTags > maximumTiffTagCount) && !(hasUnknownFileSize(this.tokenizer) && 2 + numberOfTags * 12 > maximumTiffIfdOffsetInBytes))
|
|
2408
|
+
for (let n = 0; n < numberOfTags; ++n) {
|
|
2409
|
+
let fileType = await this.readTiffTag(bigEndian);
|
|
2410
|
+
if (fileType)
|
|
2411
|
+
return fileType;
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
async readTiffHeader(bigEndian) {
|
|
2415
|
+
let tiffFileType = {
|
|
2416
|
+
ext: "tif",
|
|
2417
|
+
mime: "image/tiff"
|
|
2418
|
+
}, version = (bigEndian ? UINT16_BE : UINT16_LE).get(this.buffer, 2), ifdOffset = (bigEndian ? UINT32_BE : UINT32_LE).get(this.buffer, 4);
|
|
2419
|
+
if (version === 42) {
|
|
2420
|
+
if (ifdOffset >= 6) {
|
|
2421
|
+
if (this.checkString("CR", { offset: 8 }))
|
|
2422
|
+
return {
|
|
2423
|
+
ext: "cr2",
|
|
2424
|
+
mime: "image/x-canon-cr2"
|
|
2425
|
+
};
|
|
2426
|
+
if (ifdOffset >= 8) {
|
|
2427
|
+
let someId1 = (bigEndian ? UINT16_BE : UINT16_LE).get(this.buffer, 8), someId2 = (bigEndian ? UINT16_BE : UINT16_LE).get(this.buffer, 10);
|
|
2428
|
+
if (someId1 === 28 && someId2 === 254 || someId1 === 31 && someId2 === 11)
|
|
2429
|
+
return {
|
|
2430
|
+
ext: "nef",
|
|
2431
|
+
mime: "image/x-nikon-nef"
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
if (hasUnknownFileSize(this.tokenizer) && ifdOffset > maximumTiffStreamIfdOffsetInBytes)
|
|
2436
|
+
return tiffFileType;
|
|
2437
|
+
let maximumTiffOffset = hasUnknownFileSize(this.tokenizer) ? maximumTiffIfdOffsetInBytes : this.tokenizer.fileInfo.size;
|
|
2438
|
+
try {
|
|
2439
|
+
await safeIgnore(this.tokenizer, ifdOffset, {
|
|
2440
|
+
maximumLength: maximumTiffOffset,
|
|
2441
|
+
reason: "TIFF IFD offset"
|
|
2442
|
+
});
|
|
2443
|
+
} catch (error) {
|
|
2444
|
+
if (error instanceof EndOfStreamError)
|
|
2445
|
+
return;
|
|
2446
|
+
throw error;
|
|
2447
|
+
}
|
|
2448
|
+
let fileType;
|
|
2449
|
+
try {
|
|
2450
|
+
fileType = await this.readTiffIFD(bigEndian);
|
|
2451
|
+
} catch (error) {
|
|
2452
|
+
if (error instanceof EndOfStreamError)
|
|
2453
|
+
return;
|
|
2454
|
+
throw error;
|
|
2455
|
+
}
|
|
2456
|
+
return fileType ?? tiffFileType;
|
|
2457
|
+
}
|
|
2458
|
+
if (version === 43)
|
|
2459
|
+
return tiffFileType;
|
|
2460
|
+
}
|
|
2461
|
+
/**
|
|
2462
|
+
Scan check MPEG 1 or 2 Layer 3 header, or 'layer 0' for ADTS (MPEG sync-word 0xFFE).
|
|
2463
|
+
|
|
2464
|
+
@param offset - Offset to scan for sync-preamble.
|
|
2465
|
+
@returns {{ext: string, mime: string}}
|
|
2466
|
+
*/
|
|
2467
|
+
scanMpeg(offset) {
|
|
2468
|
+
if (this.check([255, 224], { offset, mask: [255, 224] })) {
|
|
2469
|
+
if (this.check([16], { offset: offset + 1, mask: [22] }))
|
|
2470
|
+
return this.check([8], { offset: offset + 1, mask: [8] }) ? {
|
|
2471
|
+
ext: "aac",
|
|
2472
|
+
mime: "audio/aac"
|
|
2473
|
+
} : {
|
|
2474
|
+
ext: "aac",
|
|
2475
|
+
mime: "audio/aac"
|
|
2476
|
+
};
|
|
2477
|
+
if (this.check([2], { offset: offset + 1, mask: [6] }))
|
|
2478
|
+
return {
|
|
2479
|
+
ext: "mp3",
|
|
2480
|
+
mime: "audio/mpeg"
|
|
2481
|
+
};
|
|
2482
|
+
if (this.check([4], { offset: offset + 1, mask: [6] }))
|
|
2483
|
+
return {
|
|
2484
|
+
ext: "mp2",
|
|
2485
|
+
mime: "audio/mpeg"
|
|
2486
|
+
};
|
|
2487
|
+
if (this.check([6], { offset: offset + 1, mask: [6] }))
|
|
2488
|
+
return {
|
|
2489
|
+
ext: "mp1",
|
|
2490
|
+
mime: "audio/mpeg"
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
}, supportedExtensions = new Set(extensions), supportedMimeTypes = new Set(mimeTypes);
|
|
2495
|
+
|
|
2496
|
+
// node_modules/music-metadata/lib/ParserFactory.js
|
|
2497
|
+
var import_content_type = __toESM(require_dist(), 1);
|
|
2498
|
+
|
|
2499
|
+
// node_modules/music-metadata/node_modules/media-typer/dist/index.js
|
|
2500
|
+
var typeRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}$/;
|
|
2501
|
+
function parse(str) {
|
|
2502
|
+
if (!typeRegExp.test(str))
|
|
2503
|
+
throw new TypeError(`Invalid media type: ${str}`);
|
|
2504
|
+
let slashIndex = str.indexOf("/"), type = str.slice(0, slashIndex).toLowerCase(), subtype = str.slice(slashIndex + 1).toLowerCase(), suffix, index = subtype.lastIndexOf("+");
|
|
2505
|
+
return index !== -1 && (suffix = subtype.slice(index + 1), subtype = subtype.slice(0, index)), { type, subtype, suffix };
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
// node_modules/music-metadata/lib/ParserFactory.js
|
|
2509
|
+
var import_debug3 = __toESM(require_src(), 1);
|
|
2510
|
+
|
|
2511
|
+
// node_modules/music-metadata/lib/common/MetadataCollector.js
|
|
2512
|
+
var import_debug2 = __toESM(require_src(), 1);
|
|
2513
|
+
|
|
2514
|
+
// node_modules/music-metadata/lib/common/GenericTagTypes.js
|
|
2515
|
+
var defaultTagInfo = {
|
|
2516
|
+
multiple: !1
|
|
2517
|
+
}, commonTags = {
|
|
2518
|
+
year: defaultTagInfo,
|
|
2519
|
+
track: defaultTagInfo,
|
|
2520
|
+
disk: defaultTagInfo,
|
|
2521
|
+
title: defaultTagInfo,
|
|
2522
|
+
artist: defaultTagInfo,
|
|
2523
|
+
artists: { multiple: !0, unique: !0 },
|
|
2524
|
+
albumartist: defaultTagInfo,
|
|
2525
|
+
albumartists: { multiple: !0, unique: !0 },
|
|
2526
|
+
album: defaultTagInfo,
|
|
2527
|
+
date: defaultTagInfo,
|
|
2528
|
+
originaldate: defaultTagInfo,
|
|
2529
|
+
originalyear: defaultTagInfo,
|
|
2530
|
+
releasedate: defaultTagInfo,
|
|
2531
|
+
comment: { multiple: !0, unique: !1 },
|
|
2532
|
+
genre: { multiple: !0, unique: !0 },
|
|
2533
|
+
picture: { multiple: !0, unique: !0 },
|
|
2534
|
+
composer: { multiple: !0, unique: !0 },
|
|
2535
|
+
lyrics: { multiple: !0, unique: !1 },
|
|
2536
|
+
albumsort: { multiple: !1, unique: !0 },
|
|
2537
|
+
titlesort: { multiple: !1, unique: !0 },
|
|
2538
|
+
work: { multiple: !1, unique: !0 },
|
|
2539
|
+
artistsort: { multiple: !1, unique: !0 },
|
|
2540
|
+
albumartistsort: { multiple: !1, unique: !0 },
|
|
2541
|
+
composersort: { multiple: !1, unique: !0 },
|
|
2542
|
+
lyricist: { multiple: !0, unique: !0 },
|
|
2543
|
+
writer: { multiple: !0, unique: !0 },
|
|
2544
|
+
conductor: { multiple: !0, unique: !0 },
|
|
2545
|
+
remixer: { multiple: !0, unique: !0 },
|
|
2546
|
+
arranger: { multiple: !0, unique: !0 },
|
|
2547
|
+
engineer: { multiple: !0, unique: !0 },
|
|
2548
|
+
producer: { multiple: !0, unique: !0 },
|
|
2549
|
+
technician: { multiple: !0, unique: !0 },
|
|
2550
|
+
djmixer: { multiple: !0, unique: !0 },
|
|
2551
|
+
mixer: { multiple: !0, unique: !0 },
|
|
2552
|
+
label: { multiple: !0, unique: !0 },
|
|
2553
|
+
grouping: defaultTagInfo,
|
|
2554
|
+
subtitle: { multiple: !0 },
|
|
2555
|
+
discsubtitle: defaultTagInfo,
|
|
2556
|
+
totaltracks: defaultTagInfo,
|
|
2557
|
+
totaldiscs: defaultTagInfo,
|
|
2558
|
+
compilation: defaultTagInfo,
|
|
2559
|
+
rating: { multiple: !0 },
|
|
2560
|
+
bpm: defaultTagInfo,
|
|
2561
|
+
mood: defaultTagInfo,
|
|
2562
|
+
media: defaultTagInfo,
|
|
2563
|
+
catalognumber: { multiple: !0, unique: !0 },
|
|
2564
|
+
tvShow: defaultTagInfo,
|
|
2565
|
+
tvShowSort: defaultTagInfo,
|
|
2566
|
+
tvSeason: defaultTagInfo,
|
|
2567
|
+
tvEpisode: defaultTagInfo,
|
|
2568
|
+
tvEpisodeId: defaultTagInfo,
|
|
2569
|
+
tvNetwork: defaultTagInfo,
|
|
2570
|
+
podcast: defaultTagInfo,
|
|
2571
|
+
podcasturl: defaultTagInfo,
|
|
2572
|
+
releasestatus: defaultTagInfo,
|
|
2573
|
+
releasetype: { multiple: !0 },
|
|
2574
|
+
releasecountry: defaultTagInfo,
|
|
2575
|
+
script: defaultTagInfo,
|
|
2576
|
+
language: defaultTagInfo,
|
|
2577
|
+
copyright: defaultTagInfo,
|
|
2578
|
+
license: defaultTagInfo,
|
|
2579
|
+
encodedby: defaultTagInfo,
|
|
2580
|
+
encodersettings: defaultTagInfo,
|
|
2581
|
+
gapless: defaultTagInfo,
|
|
2582
|
+
barcode: defaultTagInfo,
|
|
2583
|
+
isrc: { multiple: !0 },
|
|
2584
|
+
asin: defaultTagInfo,
|
|
2585
|
+
musicbrainz_recordingid: defaultTagInfo,
|
|
2586
|
+
musicbrainz_trackid: defaultTagInfo,
|
|
2587
|
+
musicbrainz_albumid: defaultTagInfo,
|
|
2588
|
+
musicbrainz_artistid: { multiple: !0 },
|
|
2589
|
+
musicbrainz_albumartistid: { multiple: !0 },
|
|
2590
|
+
musicbrainz_releasegroupid: defaultTagInfo,
|
|
2591
|
+
musicbrainz_workid: defaultTagInfo,
|
|
2592
|
+
musicbrainz_trmid: defaultTagInfo,
|
|
2593
|
+
musicbrainz_discid: defaultTagInfo,
|
|
2594
|
+
acoustid_id: defaultTagInfo,
|
|
2595
|
+
acoustid_fingerprint: defaultTagInfo,
|
|
2596
|
+
musicip_puid: defaultTagInfo,
|
|
2597
|
+
musicip_fingerprint: defaultTagInfo,
|
|
2598
|
+
website: defaultTagInfo,
|
|
2599
|
+
"performer:instrument": { multiple: !0, unique: !0 },
|
|
2600
|
+
averageLevel: defaultTagInfo,
|
|
2601
|
+
peakLevel: defaultTagInfo,
|
|
2602
|
+
notes: { multiple: !0, unique: !1 },
|
|
2603
|
+
key: defaultTagInfo,
|
|
2604
|
+
originalalbum: defaultTagInfo,
|
|
2605
|
+
originalartist: defaultTagInfo,
|
|
2606
|
+
discogs_artist_id: { multiple: !0, unique: !0 },
|
|
2607
|
+
discogs_release_id: defaultTagInfo,
|
|
2608
|
+
discogs_label_id: defaultTagInfo,
|
|
2609
|
+
discogs_master_release_id: defaultTagInfo,
|
|
2610
|
+
discogs_votes: defaultTagInfo,
|
|
2611
|
+
discogs_rating: defaultTagInfo,
|
|
2612
|
+
replaygain_track_peak: defaultTagInfo,
|
|
2613
|
+
replaygain_track_gain: defaultTagInfo,
|
|
2614
|
+
replaygain_album_peak: defaultTagInfo,
|
|
2615
|
+
replaygain_album_gain: defaultTagInfo,
|
|
2616
|
+
replaygain_track_minmax: defaultTagInfo,
|
|
2617
|
+
replaygain_album_minmax: defaultTagInfo,
|
|
2618
|
+
replaygain_undo: defaultTagInfo,
|
|
2619
|
+
description: { multiple: !0 },
|
|
2620
|
+
longDescription: defaultTagInfo,
|
|
2621
|
+
category: { multiple: !0 },
|
|
2622
|
+
hdVideo: defaultTagInfo,
|
|
2623
|
+
keywords: { multiple: !0 },
|
|
2624
|
+
movement: defaultTagInfo,
|
|
2625
|
+
movementIndex: defaultTagInfo,
|
|
2626
|
+
movementTotal: defaultTagInfo,
|
|
2627
|
+
podcastId: defaultTagInfo,
|
|
2628
|
+
showMovement: defaultTagInfo,
|
|
2629
|
+
stik: defaultTagInfo,
|
|
2630
|
+
playCounter: defaultTagInfo
|
|
2631
|
+
};
|
|
2632
|
+
function isSingleton(alias) {
|
|
2633
|
+
return commonTags[alias] && !commonTags[alias].multiple;
|
|
2634
|
+
}
|
|
2635
|
+
function isUnique(alias) {
|
|
2636
|
+
return !commonTags[alias].multiple || commonTags[alias].unique || !1;
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
// node_modules/music-metadata/lib/common/GenericTagMapper.js
|
|
2640
|
+
var CommonTagMapper = class {
|
|
2641
|
+
static toIntOrNull(str) {
|
|
2642
|
+
let cleaned = Number.parseInt(str, 10);
|
|
2643
|
+
return Number.isNaN(cleaned) ? null : cleaned;
|
|
2644
|
+
}
|
|
2645
|
+
// TODO: a string of 1of1 would fail to be converted
|
|
2646
|
+
// converts 1/10 to no : 1, of : 10
|
|
2647
|
+
// or 1 to no : 1, of : 0
|
|
2648
|
+
static normalizeTrack(origVal) {
|
|
2649
|
+
let split = origVal.toString().split("/");
|
|
2650
|
+
return {
|
|
2651
|
+
no: Number.parseInt(split[0], 10) || null,
|
|
2652
|
+
of: Number.parseInt(split[1], 10) || null
|
|
2653
|
+
};
|
|
2654
|
+
}
|
|
2655
|
+
constructor(tagTypes, tagMap2) {
|
|
2656
|
+
this.tagTypes = tagTypes, this.tagMap = tagMap2;
|
|
2657
|
+
}
|
|
2658
|
+
/**
|
|
2659
|
+
* Process and set common tags
|
|
2660
|
+
* write common tags to
|
|
2661
|
+
* @param tag Native tag
|
|
2662
|
+
* @param warnings Register warnings
|
|
2663
|
+
* @return common name
|
|
2664
|
+
*/
|
|
2665
|
+
mapGenericTag(tag, warnings) {
|
|
2666
|
+
tag = { id: tag.id, value: tag.value }, this.postMap(tag, warnings);
|
|
2667
|
+
let id = this.getCommonName(tag.id);
|
|
2668
|
+
return id ? { id, value: tag.value } : null;
|
|
2669
|
+
}
|
|
2670
|
+
/**
|
|
2671
|
+
* Convert native tag key to common tag key
|
|
2672
|
+
* @param tag Native header tag
|
|
2673
|
+
* @return common tag name (alias)
|
|
2674
|
+
*/
|
|
2675
|
+
getCommonName(tag) {
|
|
2676
|
+
return this.tagMap[tag];
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* Handle post mapping exceptions / correction
|
|
2680
|
+
* @param tag Tag e.g. {"©alb", "Buena Vista Social Club")
|
|
2681
|
+
* @param warnings Used to register warnings
|
|
2682
|
+
*/
|
|
2683
|
+
postMap(_tag, _warnings) {
|
|
2684
|
+
}
|
|
2685
|
+
};
|
|
2686
|
+
CommonTagMapper.maxRatingScore = 1;
|
|
2687
|
+
|
|
2688
|
+
// node_modules/music-metadata/lib/id3v1/ID3v1TagMap.js
|
|
2689
|
+
var id3v1TagMap = {
|
|
2690
|
+
title: "title",
|
|
2691
|
+
artist: "artist",
|
|
2692
|
+
album: "album",
|
|
2693
|
+
year: "year",
|
|
2694
|
+
comment: "comment",
|
|
2695
|
+
track: "track",
|
|
2696
|
+
genre: "genre"
|
|
2697
|
+
}, ID3v1TagMapper = class extends CommonTagMapper {
|
|
2698
|
+
constructor() {
|
|
2699
|
+
super(["ID3v1"], id3v1TagMap);
|
|
2700
|
+
}
|
|
2701
|
+
};
|
|
2702
|
+
|
|
2703
|
+
// node_modules/music-metadata/lib/common/CaseInsensitiveTagMap.js
|
|
2704
|
+
var CaseInsensitiveTagMap = class extends CommonTagMapper {
|
|
2705
|
+
constructor(tagTypes, tagMap2) {
|
|
2706
|
+
let upperCaseMap = {};
|
|
2707
|
+
for (let tag of Object.keys(tagMap2))
|
|
2708
|
+
upperCaseMap[tag.toUpperCase()] = tagMap2[tag];
|
|
2709
|
+
super(tagTypes, upperCaseMap);
|
|
2710
|
+
}
|
|
2711
|
+
/**
|
|
2712
|
+
* @tag Native header tag
|
|
2713
|
+
* @return common tag name (alias)
|
|
2714
|
+
*/
|
|
2715
|
+
getCommonName(tag) {
|
|
2716
|
+
return this.tagMap[tag.toUpperCase()];
|
|
2717
|
+
}
|
|
2718
|
+
};
|
|
2719
|
+
|
|
2720
|
+
// node_modules/music-metadata/lib/id3v2/ID3v24TagMapper.js
|
|
2721
|
+
var id3v24TagMap = {
|
|
2722
|
+
// id3v2.3
|
|
2723
|
+
TIT2: "title",
|
|
2724
|
+
TPE1: "artist",
|
|
2725
|
+
"TXXX:Artists": "artists",
|
|
2726
|
+
TPE2: "albumartist",
|
|
2727
|
+
TALB: "album",
|
|
2728
|
+
TDRV: "date",
|
|
2729
|
+
// [ 'date', 'year' ] ToDo: improve 'year' mapping
|
|
2730
|
+
/**
|
|
2731
|
+
* Original release year
|
|
2732
|
+
*/
|
|
2733
|
+
TORY: "originalyear",
|
|
2734
|
+
TPOS: "disk",
|
|
2735
|
+
TCON: "genre",
|
|
2736
|
+
APIC: "picture",
|
|
2737
|
+
TCOM: "composer",
|
|
2738
|
+
USLT: "lyrics",
|
|
2739
|
+
TSOA: "albumsort",
|
|
2740
|
+
TSOT: "titlesort",
|
|
2741
|
+
TOAL: "originalalbum",
|
|
2742
|
+
TSOP: "artistsort",
|
|
2743
|
+
TSO2: "albumartistsort",
|
|
2744
|
+
TSOC: "composersort",
|
|
2745
|
+
TEXT: "lyricist",
|
|
2746
|
+
"TXXX:Writer": "writer",
|
|
2747
|
+
TPE3: "conductor",
|
|
2748
|
+
// 'IPLS:instrument': 'performer:instrument', // ToDo
|
|
2749
|
+
TPE4: "remixer",
|
|
2750
|
+
"IPLS:arranger": "arranger",
|
|
2751
|
+
"IPLS:engineer": "engineer",
|
|
2752
|
+
"IPLS:producer": "producer",
|
|
2753
|
+
"IPLS:DJ-mix": "djmixer",
|
|
2754
|
+
"IPLS:mix": "mixer",
|
|
2755
|
+
TPUB: "label",
|
|
2756
|
+
TIT1: "grouping",
|
|
2757
|
+
TIT3: "subtitle",
|
|
2758
|
+
TRCK: "track",
|
|
2759
|
+
TCMP: "compilation",
|
|
2760
|
+
POPM: "rating",
|
|
2761
|
+
TBPM: "bpm",
|
|
2762
|
+
TMED: "media",
|
|
2763
|
+
"TXXX:CATALOGNUMBER": "catalognumber",
|
|
2764
|
+
"TXXX:MusicBrainz Album Status": "releasestatus",
|
|
2765
|
+
"TXXX:MusicBrainz Album Type": "releasetype",
|
|
2766
|
+
/**
|
|
2767
|
+
* Release country as documented: https://picard.musicbrainz.org/docs/mappings/#cite_note-0
|
|
2768
|
+
*/
|
|
2769
|
+
"TXXX:MusicBrainz Album Release Country": "releasecountry",
|
|
2770
|
+
/**
|
|
2771
|
+
* Release country as implemented // ToDo: report
|
|
2772
|
+
*/
|
|
2773
|
+
"TXXX:RELEASECOUNTRY": "releasecountry",
|
|
2774
|
+
"TXXX:SCRIPT": "script",
|
|
2775
|
+
TLAN: "language",
|
|
2776
|
+
TCOP: "copyright",
|
|
2777
|
+
WCOP: "license",
|
|
2778
|
+
TENC: "encodedby",
|
|
2779
|
+
TSSE: "encodersettings",
|
|
2780
|
+
"TXXX:BARCODE": "barcode",
|
|
2781
|
+
"TXXX:ISRC": "isrc",
|
|
2782
|
+
TSRC: "isrc",
|
|
2783
|
+
"TXXX:ASIN": "asin",
|
|
2784
|
+
"TXXX:originalyear": "originalyear",
|
|
2785
|
+
"UFID:http://musicbrainz.org": "musicbrainz_recordingid",
|
|
2786
|
+
"TXXX:MusicBrainz Release Track Id": "musicbrainz_trackid",
|
|
2787
|
+
"TXXX:MusicBrainz Album Id": "musicbrainz_albumid",
|
|
2788
|
+
"TXXX:MusicBrainz Artist Id": "musicbrainz_artistid",
|
|
2789
|
+
"TXXX:MusicBrainz Album Artist Id": "musicbrainz_albumartistid",
|
|
2790
|
+
"TXXX:MusicBrainz Release Group Id": "musicbrainz_releasegroupid",
|
|
2791
|
+
"TXXX:MusicBrainz Work Id": "musicbrainz_workid",
|
|
2792
|
+
"TXXX:MusicBrainz TRM Id": "musicbrainz_trmid",
|
|
2793
|
+
"TXXX:MusicBrainz Disc Id": "musicbrainz_discid",
|
|
2794
|
+
"TXXX:ACOUSTID_ID": "acoustid_id",
|
|
2795
|
+
"TXXX:Acoustid Id": "acoustid_id",
|
|
2796
|
+
"TXXX:Acoustid Fingerprint": "acoustid_fingerprint",
|
|
2797
|
+
"TXXX:MusicIP PUID": "musicip_puid",
|
|
2798
|
+
"TXXX:MusicMagic Fingerprint": "musicip_fingerprint",
|
|
2799
|
+
WOAR: "website",
|
|
2800
|
+
// id3v2.4
|
|
2801
|
+
// ToDo: In same sequence as defined at http://id3.org/id3v2.4.0-frames
|
|
2802
|
+
TDRC: "date",
|
|
2803
|
+
// date YYYY-MM-DD
|
|
2804
|
+
TYER: "year",
|
|
2805
|
+
TDOR: "originaldate",
|
|
2806
|
+
// 'TMCL:instrument': 'performer:instrument',
|
|
2807
|
+
"TIPL:arranger": "arranger",
|
|
2808
|
+
"TIPL:engineer": "engineer",
|
|
2809
|
+
"TIPL:producer": "producer",
|
|
2810
|
+
"TIPL:DJ-mix": "djmixer",
|
|
2811
|
+
"TIPL:mix": "mixer",
|
|
2812
|
+
TMOO: "mood",
|
|
2813
|
+
// additional mappings:
|
|
2814
|
+
SYLT: "lyrics",
|
|
2815
|
+
TSST: "discsubtitle",
|
|
2816
|
+
TKEY: "key",
|
|
2817
|
+
COMM: "comment",
|
|
2818
|
+
TOPE: "originalartist",
|
|
2819
|
+
// Windows Media Player
|
|
2820
|
+
"PRIV:AverageLevel": "averageLevel",
|
|
2821
|
+
"PRIV:PeakLevel": "peakLevel",
|
|
2822
|
+
// Discogs
|
|
2823
|
+
"TXXX:DISCOGS_ARTIST_ID": "discogs_artist_id",
|
|
2824
|
+
"TXXX:DISCOGS_ARTISTS": "artists",
|
|
2825
|
+
"TXXX:DISCOGS_ARTIST_NAME": "artists",
|
|
2826
|
+
"TXXX:DISCOGS_ALBUM_ARTISTS": "albumartist",
|
|
2827
|
+
"TXXX:DISCOGS_CATALOG": "catalognumber",
|
|
2828
|
+
"TXXX:DISCOGS_COUNTRY": "releasecountry",
|
|
2829
|
+
"TXXX:DISCOGS_DATE": "originaldate",
|
|
2830
|
+
"TXXX:DISCOGS_LABEL": "label",
|
|
2831
|
+
"TXXX:DISCOGS_LABEL_ID": "discogs_label_id",
|
|
2832
|
+
"TXXX:DISCOGS_MASTER_RELEASE_ID": "discogs_master_release_id",
|
|
2833
|
+
"TXXX:DISCOGS_RATING": "discogs_rating",
|
|
2834
|
+
"TXXX:DISCOGS_RELEASED": "date",
|
|
2835
|
+
"TXXX:DISCOGS_RELEASE_ID": "discogs_release_id",
|
|
2836
|
+
"TXXX:DISCOGS_VOTES": "discogs_votes",
|
|
2837
|
+
"TXXX:CATALOGID": "catalognumber",
|
|
2838
|
+
"TXXX:STYLE": "genre",
|
|
2839
|
+
"TXXX:REPLAYGAIN_TRACK_PEAK": "replaygain_track_peak",
|
|
2840
|
+
"TXXX:REPLAYGAIN_TRACK_GAIN": "replaygain_track_gain",
|
|
2841
|
+
"TXXX:REPLAYGAIN_ALBUM_PEAK": "replaygain_album_peak",
|
|
2842
|
+
"TXXX:REPLAYGAIN_ALBUM_GAIN": "replaygain_album_gain",
|
|
2843
|
+
"TXXX:MP3GAIN_MINMAX": "replaygain_track_minmax",
|
|
2844
|
+
"TXXX:MP3GAIN_ALBUM_MINMAX": "replaygain_album_minmax",
|
|
2845
|
+
"TXXX:MP3GAIN_UNDO": "replaygain_undo",
|
|
2846
|
+
MVNM: "movement",
|
|
2847
|
+
MVIN: "movementIndex",
|
|
2848
|
+
PCST: "podcast",
|
|
2849
|
+
TCAT: "category",
|
|
2850
|
+
TDES: "description",
|
|
2851
|
+
TDRL: "releasedate",
|
|
2852
|
+
TGID: "podcastId",
|
|
2853
|
+
TKWD: "keywords",
|
|
2854
|
+
WFED: "podcasturl",
|
|
2855
|
+
GRP1: "grouping",
|
|
2856
|
+
PCNT: "playCounter"
|
|
2857
|
+
}, ID3v24TagMapper = class _ID3v24TagMapper extends CaseInsensitiveTagMap {
|
|
2858
|
+
static toRating(popm) {
|
|
2859
|
+
return {
|
|
2860
|
+
source: popm.email,
|
|
2861
|
+
rating: popm.rating > 0 ? (popm.rating - 1) / 254 * CommonTagMapper.maxRatingScore : void 0
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2864
|
+
constructor() {
|
|
2865
|
+
super(["ID3v2.3", "ID3v2.4"], id3v24TagMap);
|
|
2866
|
+
}
|
|
2867
|
+
/**
|
|
2868
|
+
* Handle post mapping exceptions / correction
|
|
2869
|
+
* @param tag to post map
|
|
2870
|
+
* @param warnings Wil be used to register (collect) warnings
|
|
2871
|
+
*/
|
|
2872
|
+
postMap(tag, warnings) {
|
|
2873
|
+
switch (tag.id) {
|
|
2874
|
+
case "UFID":
|
|
2875
|
+
{
|
|
2876
|
+
let idTag = tag.value;
|
|
2877
|
+
idTag.owner_identifier === "http://musicbrainz.org" && (tag.id += `:${idTag.owner_identifier}`, tag.value = decodeString(idTag.identifier, "latin1"));
|
|
2878
|
+
}
|
|
2879
|
+
break;
|
|
2880
|
+
case "PRIV":
|
|
2881
|
+
{
|
|
2882
|
+
let customTag = tag.value;
|
|
2883
|
+
switch (customTag.owner_identifier) {
|
|
2884
|
+
// decode Windows Media Player
|
|
2885
|
+
case "AverageLevel":
|
|
2886
|
+
case "PeakValue":
|
|
2887
|
+
tag.id += `:${customTag.owner_identifier}`, tag.value = customTag.data.length === 4 ? UINT32_LE.get(customTag.data, 0) : null, tag.value === null && warnings.addWarning("Failed to parse PRIV:PeakValue");
|
|
2888
|
+
break;
|
|
2889
|
+
default:
|
|
2890
|
+
warnings.addWarning(`Unknown PRIV owner-identifier: ${customTag.data}`);
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
break;
|
|
2894
|
+
case "POPM":
|
|
2895
|
+
tag.value = _ID3v24TagMapper.toRating(tag.value);
|
|
2896
|
+
break;
|
|
2897
|
+
default:
|
|
2898
|
+
break;
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
|
|
2903
|
+
// node_modules/music-metadata/lib/asf/AsfTagMapper.js
|
|
2904
|
+
var asfTagMap = {
|
|
2905
|
+
Title: "title",
|
|
2906
|
+
Author: "artist",
|
|
2907
|
+
"WM/AlbumArtist": "albumartist",
|
|
2908
|
+
"WM/AlbumTitle": "album",
|
|
2909
|
+
"WM/Year": "date",
|
|
2910
|
+
// changed to 'year' to 'date' based on Picard mappings; ToDo: check me
|
|
2911
|
+
"WM/OriginalReleaseTime": "originaldate",
|
|
2912
|
+
"WM/OriginalReleaseYear": "originalyear",
|
|
2913
|
+
Description: "comment",
|
|
2914
|
+
"WM/TrackNumber": "track",
|
|
2915
|
+
"WM/PartOfSet": "disk",
|
|
2916
|
+
"WM/Genre": "genre",
|
|
2917
|
+
"WM/Composer": "composer",
|
|
2918
|
+
"WM/Lyrics": "lyrics",
|
|
2919
|
+
"WM/AlbumSortOrder": "albumsort",
|
|
2920
|
+
"WM/TitleSortOrder": "titlesort",
|
|
2921
|
+
"WM/ArtistSortOrder": "artistsort",
|
|
2922
|
+
"WM/AlbumArtistSortOrder": "albumartistsort",
|
|
2923
|
+
"WM/ComposerSortOrder": "composersort",
|
|
2924
|
+
"WM/Writer": "lyricist",
|
|
2925
|
+
"WM/Conductor": "conductor",
|
|
2926
|
+
"WM/ModifiedBy": "remixer",
|
|
2927
|
+
"WM/Engineer": "engineer",
|
|
2928
|
+
"WM/Producer": "producer",
|
|
2929
|
+
"WM/DJMixer": "djmixer",
|
|
2930
|
+
"WM/Mixer": "mixer",
|
|
2931
|
+
"WM/Publisher": "label",
|
|
2932
|
+
"WM/ContentGroupDescription": "grouping",
|
|
2933
|
+
"WM/SubTitle": "subtitle",
|
|
2934
|
+
"WM/SetSubTitle": "discsubtitle",
|
|
2935
|
+
// 'WM/PartOfSet': 'totaldiscs',
|
|
2936
|
+
"WM/IsCompilation": "compilation",
|
|
2937
|
+
"WM/SharedUserRating": "rating",
|
|
2938
|
+
"WM/BeatsPerMinute": "bpm",
|
|
2939
|
+
"WM/Mood": "mood",
|
|
2940
|
+
"WM/Media": "media",
|
|
2941
|
+
"WM/CatalogNo": "catalognumber",
|
|
2942
|
+
"MusicBrainz/Album Status": "releasestatus",
|
|
2943
|
+
"MusicBrainz/Album Type": "releasetype",
|
|
2944
|
+
"MusicBrainz/Album Release Country": "releasecountry",
|
|
2945
|
+
"WM/Script": "script",
|
|
2946
|
+
"WM/Language": "language",
|
|
2947
|
+
Copyright: "copyright",
|
|
2948
|
+
LICENSE: "license",
|
|
2949
|
+
"WM/EncodedBy": "encodedby",
|
|
2950
|
+
"WM/EncodingSettings": "encodersettings",
|
|
2951
|
+
"WM/Barcode": "barcode",
|
|
2952
|
+
"WM/ISRC": "isrc",
|
|
2953
|
+
"MusicBrainz/Track Id": "musicbrainz_recordingid",
|
|
2954
|
+
"MusicBrainz/Release Track Id": "musicbrainz_trackid",
|
|
2955
|
+
"MusicBrainz/Album Id": "musicbrainz_albumid",
|
|
2956
|
+
"MusicBrainz/Artist Id": "musicbrainz_artistid",
|
|
2957
|
+
"MusicBrainz/Album Artist Id": "musicbrainz_albumartistid",
|
|
2958
|
+
"MusicBrainz/Release Group Id": "musicbrainz_releasegroupid",
|
|
2959
|
+
"MusicBrainz/Work Id": "musicbrainz_workid",
|
|
2960
|
+
"MusicBrainz/TRM Id": "musicbrainz_trmid",
|
|
2961
|
+
"MusicBrainz/Disc Id": "musicbrainz_discid",
|
|
2962
|
+
"Acoustid/Id": "acoustid_id",
|
|
2963
|
+
"Acoustid/Fingerprint": "acoustid_fingerprint",
|
|
2964
|
+
"MusicIP/PUID": "musicip_puid",
|
|
2965
|
+
"WM/ARTISTS": "artists",
|
|
2966
|
+
"WM/InitialKey": "key",
|
|
2967
|
+
ASIN: "asin",
|
|
2968
|
+
"WM/Work": "work",
|
|
2969
|
+
"WM/AuthorURL": "website",
|
|
2970
|
+
"WM/Picture": "picture"
|
|
2971
|
+
}, AsfTagMapper = class _AsfTagMapper extends CommonTagMapper {
|
|
2972
|
+
static toRating(rating) {
|
|
2973
|
+
return {
|
|
2974
|
+
rating: Number.parseFloat(rating + 1) / 5
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2977
|
+
constructor() {
|
|
2978
|
+
super(["asf"], asfTagMap);
|
|
2979
|
+
}
|
|
2980
|
+
postMap(tag) {
|
|
2981
|
+
if (tag.id === "WM/SharedUserRating") {
|
|
2982
|
+
let keys = tag.id.split(":");
|
|
2983
|
+
tag.value = _AsfTagMapper.toRating(tag.value), tag.id = keys[0];
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
};
|
|
2987
|
+
|
|
2988
|
+
// node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.js
|
|
2989
|
+
var id3v22TagMap = {
|
|
2990
|
+
TT2: "title",
|
|
2991
|
+
TP1: "artist",
|
|
2992
|
+
TP2: "albumartist",
|
|
2993
|
+
TAL: "album",
|
|
2994
|
+
TYE: "year",
|
|
2995
|
+
COM: "comment",
|
|
2996
|
+
TRK: "track",
|
|
2997
|
+
TPA: "disk",
|
|
2998
|
+
TCO: "genre",
|
|
2999
|
+
PIC: "picture",
|
|
3000
|
+
TCM: "composer",
|
|
3001
|
+
TOR: "originaldate",
|
|
3002
|
+
TOT: "originalalbum",
|
|
3003
|
+
TXT: "lyricist",
|
|
3004
|
+
TP3: "conductor",
|
|
3005
|
+
TPB: "label",
|
|
3006
|
+
TT1: "grouping",
|
|
3007
|
+
TT3: "subtitle",
|
|
3008
|
+
TLA: "language",
|
|
3009
|
+
TCR: "copyright",
|
|
3010
|
+
WCP: "license",
|
|
3011
|
+
TEN: "encodedby",
|
|
3012
|
+
TSS: "encodersettings",
|
|
3013
|
+
WAR: "website",
|
|
3014
|
+
PCS: "podcast",
|
|
3015
|
+
TCP: "compilation",
|
|
3016
|
+
TDR: "date",
|
|
3017
|
+
TS2: "albumartistsort",
|
|
3018
|
+
TSA: "albumsort",
|
|
3019
|
+
TSC: "composersort",
|
|
3020
|
+
TSP: "artistsort",
|
|
3021
|
+
TST: "titlesort",
|
|
3022
|
+
WFD: "podcasturl",
|
|
3023
|
+
TBP: "bpm",
|
|
3024
|
+
GP1: "grouping"
|
|
3025
|
+
}, ID3v22TagMapper = class extends CaseInsensitiveTagMap {
|
|
3026
|
+
constructor() {
|
|
3027
|
+
super(["ID3v2.2"], id3v22TagMap);
|
|
3028
|
+
}
|
|
3029
|
+
};
|
|
3030
|
+
|
|
3031
|
+
// node_modules/music-metadata/lib/apev2/APEv2TagMapper.js
|
|
3032
|
+
var apev2TagMap = {
|
|
3033
|
+
Title: "title",
|
|
3034
|
+
Artist: "artist",
|
|
3035
|
+
Artists: "artists",
|
|
3036
|
+
"Album Artist": "albumartist",
|
|
3037
|
+
Album: "album",
|
|
3038
|
+
Year: "date",
|
|
3039
|
+
Originalyear: "originalyear",
|
|
3040
|
+
Originaldate: "originaldate",
|
|
3041
|
+
Releasedate: "releasedate",
|
|
3042
|
+
Comment: "comment",
|
|
3043
|
+
Track: "track",
|
|
3044
|
+
Disc: "disk",
|
|
3045
|
+
DISCNUMBER: "disk",
|
|
3046
|
+
// ToDo: backwards compatibility', valid tag?
|
|
3047
|
+
Genre: "genre",
|
|
3048
|
+
"Cover Art (Front)": "picture",
|
|
3049
|
+
"Cover Art (Back)": "picture",
|
|
3050
|
+
Composer: "composer",
|
|
3051
|
+
Lyrics: "lyrics",
|
|
3052
|
+
ALBUMSORT: "albumsort",
|
|
3053
|
+
TITLESORT: "titlesort",
|
|
3054
|
+
WORK: "work",
|
|
3055
|
+
ARTISTSORT: "artistsort",
|
|
3056
|
+
ALBUMARTISTSORT: "albumartistsort",
|
|
3057
|
+
COMPOSERSORT: "composersort",
|
|
3058
|
+
Lyricist: "lyricist",
|
|
3059
|
+
Writer: "writer",
|
|
3060
|
+
Conductor: "conductor",
|
|
3061
|
+
// 'Performer=artist (instrument)': 'performer:instrument',
|
|
3062
|
+
MixArtist: "remixer",
|
|
3063
|
+
Arranger: "arranger",
|
|
3064
|
+
Engineer: "engineer",
|
|
3065
|
+
Producer: "producer",
|
|
3066
|
+
DJMixer: "djmixer",
|
|
3067
|
+
Mixer: "mixer",
|
|
3068
|
+
Label: "label",
|
|
3069
|
+
Grouping: "grouping",
|
|
3070
|
+
Subtitle: "subtitle",
|
|
3071
|
+
DiscSubtitle: "discsubtitle",
|
|
3072
|
+
Compilation: "compilation",
|
|
3073
|
+
BPM: "bpm",
|
|
3074
|
+
Mood: "mood",
|
|
3075
|
+
Media: "media",
|
|
3076
|
+
CatalogNumber: "catalognumber",
|
|
3077
|
+
MUSICBRAINZ_ALBUMSTATUS: "releasestatus",
|
|
3078
|
+
MUSICBRAINZ_ALBUMTYPE: "releasetype",
|
|
3079
|
+
RELEASECOUNTRY: "releasecountry",
|
|
3080
|
+
Script: "script",
|
|
3081
|
+
Language: "language",
|
|
3082
|
+
Copyright: "copyright",
|
|
3083
|
+
LICENSE: "license",
|
|
3084
|
+
EncodedBy: "encodedby",
|
|
3085
|
+
EncoderSettings: "encodersettings",
|
|
3086
|
+
Barcode: "barcode",
|
|
3087
|
+
ISRC: "isrc",
|
|
3088
|
+
ASIN: "asin",
|
|
3089
|
+
musicbrainz_trackid: "musicbrainz_recordingid",
|
|
3090
|
+
musicbrainz_releasetrackid: "musicbrainz_trackid",
|
|
3091
|
+
MUSICBRAINZ_ALBUMID: "musicbrainz_albumid",
|
|
3092
|
+
MUSICBRAINZ_ARTISTID: "musicbrainz_artistid",
|
|
3093
|
+
MUSICBRAINZ_ALBUMARTISTID: "musicbrainz_albumartistid",
|
|
3094
|
+
MUSICBRAINZ_RELEASEGROUPID: "musicbrainz_releasegroupid",
|
|
3095
|
+
MUSICBRAINZ_WORKID: "musicbrainz_workid",
|
|
3096
|
+
MUSICBRAINZ_TRMID: "musicbrainz_trmid",
|
|
3097
|
+
MUSICBRAINZ_DISCID: "musicbrainz_discid",
|
|
3098
|
+
Acoustid_Id: "acoustid_id",
|
|
3099
|
+
ACOUSTID_FINGERPRINT: "acoustid_fingerprint",
|
|
3100
|
+
MUSICIP_PUID: "musicip_puid",
|
|
3101
|
+
Weblink: "website",
|
|
3102
|
+
REPLAYGAIN_TRACK_GAIN: "replaygain_track_gain",
|
|
3103
|
+
REPLAYGAIN_TRACK_PEAK: "replaygain_track_peak",
|
|
3104
|
+
MP3GAIN_MINMAX: "replaygain_track_minmax",
|
|
3105
|
+
MP3GAIN_UNDO: "replaygain_undo"
|
|
3106
|
+
}, APEv2TagMapper = class extends CaseInsensitiveTagMap {
|
|
3107
|
+
constructor() {
|
|
3108
|
+
super(["APEv2"], apev2TagMap);
|
|
3109
|
+
}
|
|
3110
|
+
};
|
|
3111
|
+
|
|
3112
|
+
// node_modules/music-metadata/lib/mp4/MP4TagMapper.js
|
|
3113
|
+
var mp4TagMap = {
|
|
3114
|
+
"\xA9nam": "title",
|
|
3115
|
+
"\xA9ART": "artist",
|
|
3116
|
+
aART: "albumartist",
|
|
3117
|
+
/**
|
|
3118
|
+
* ToDo: Album artist seems to be stored here while Picard documentation says: aART
|
|
3119
|
+
*/
|
|
3120
|
+
"----:com.apple.iTunes:Band": "albumartist",
|
|
3121
|
+
"\xA9alb": "album",
|
|
3122
|
+
"\xA9day": "date",
|
|
3123
|
+
"\xA9cmt": "comment",
|
|
3124
|
+
"\xA9com": "comment",
|
|
3125
|
+
trkn: "track",
|
|
3126
|
+
disk: "disk",
|
|
3127
|
+
"\xA9gen": "genre",
|
|
3128
|
+
covr: "picture",
|
|
3129
|
+
"\xA9wrt": "composer",
|
|
3130
|
+
"\xA9lyr": "lyrics",
|
|
3131
|
+
soal: "albumsort",
|
|
3132
|
+
sonm: "titlesort",
|
|
3133
|
+
soar: "artistsort",
|
|
3134
|
+
soaa: "albumartistsort",
|
|
3135
|
+
soco: "composersort",
|
|
3136
|
+
"----:com.apple.iTunes:LYRICIST": "lyricist",
|
|
3137
|
+
"----:com.apple.iTunes:CONDUCTOR": "conductor",
|
|
3138
|
+
"----:com.apple.iTunes:REMIXER": "remixer",
|
|
3139
|
+
"----:com.apple.iTunes:ENGINEER": "engineer",
|
|
3140
|
+
"----:com.apple.iTunes:PRODUCER": "producer",
|
|
3141
|
+
"----:com.apple.iTunes:DJMIXER": "djmixer",
|
|
3142
|
+
"----:com.apple.iTunes:MIXER": "mixer",
|
|
3143
|
+
"----:com.apple.iTunes:LABEL": "label",
|
|
3144
|
+
"\xA9grp": "grouping",
|
|
3145
|
+
"----:com.apple.iTunes:SUBTITLE": "subtitle",
|
|
3146
|
+
"----:com.apple.iTunes:DISCSUBTITLE": "discsubtitle",
|
|
3147
|
+
cpil: "compilation",
|
|
3148
|
+
tmpo: "bpm",
|
|
3149
|
+
"----:com.apple.iTunes:MOOD": "mood",
|
|
3150
|
+
"----:com.apple.iTunes:MEDIA": "media",
|
|
3151
|
+
"----:com.apple.iTunes:CATALOGNUMBER": "catalognumber",
|
|
3152
|
+
tvsh: "tvShow",
|
|
3153
|
+
tvsn: "tvSeason",
|
|
3154
|
+
tves: "tvEpisode",
|
|
3155
|
+
sosn: "tvShowSort",
|
|
3156
|
+
tven: "tvEpisodeId",
|
|
3157
|
+
tvnn: "tvNetwork",
|
|
3158
|
+
pcst: "podcast",
|
|
3159
|
+
purl: "podcasturl",
|
|
3160
|
+
"----:com.apple.iTunes:MusicBrainz Album Status": "releasestatus",
|
|
3161
|
+
"----:com.apple.iTunes:MusicBrainz Album Type": "releasetype",
|
|
3162
|
+
"----:com.apple.iTunes:MusicBrainz Album Release Country": "releasecountry",
|
|
3163
|
+
"----:com.apple.iTunes:SCRIPT": "script",
|
|
3164
|
+
"----:com.apple.iTunes:LANGUAGE": "language",
|
|
3165
|
+
cprt: "copyright",
|
|
3166
|
+
"\xA9cpy": "copyright",
|
|
3167
|
+
"----:com.apple.iTunes:LICENSE": "license",
|
|
3168
|
+
"\xA9too": "encodedby",
|
|
3169
|
+
pgap: "gapless",
|
|
3170
|
+
"----:com.apple.iTunes:BARCODE": "barcode",
|
|
3171
|
+
"----:com.apple.iTunes:ISRC": "isrc",
|
|
3172
|
+
"----:com.apple.iTunes:ASIN": "asin",
|
|
3173
|
+
"----:com.apple.iTunes:NOTES": "comment",
|
|
3174
|
+
"----:com.apple.iTunes:MusicBrainz Track Id": "musicbrainz_recordingid",
|
|
3175
|
+
"----:com.apple.iTunes:MusicBrainz Release Track Id": "musicbrainz_trackid",
|
|
3176
|
+
"----:com.apple.iTunes:MusicBrainz Album Id": "musicbrainz_albumid",
|
|
3177
|
+
"----:com.apple.iTunes:MusicBrainz Artist Id": "musicbrainz_artistid",
|
|
3178
|
+
"----:com.apple.iTunes:MusicBrainz Album Artist Id": "musicbrainz_albumartistid",
|
|
3179
|
+
"----:com.apple.iTunes:MusicBrainz Release Group Id": "musicbrainz_releasegroupid",
|
|
3180
|
+
"----:com.apple.iTunes:MusicBrainz Work Id": "musicbrainz_workid",
|
|
3181
|
+
"----:com.apple.iTunes:MusicBrainz TRM Id": "musicbrainz_trmid",
|
|
3182
|
+
"----:com.apple.iTunes:MusicBrainz Disc Id": "musicbrainz_discid",
|
|
3183
|
+
"----:com.apple.iTunes:Acoustid Id": "acoustid_id",
|
|
3184
|
+
"----:com.apple.iTunes:Acoustid Fingerprint": "acoustid_fingerprint",
|
|
3185
|
+
"----:com.apple.iTunes:MusicIP PUID": "musicip_puid",
|
|
3186
|
+
"----:com.apple.iTunes:fingerprint": "musicip_fingerprint",
|
|
3187
|
+
"----:com.apple.iTunes:replaygain_track_gain": "replaygain_track_gain",
|
|
3188
|
+
"----:com.apple.iTunes:replaygain_track_peak": "replaygain_track_peak",
|
|
3189
|
+
"----:com.apple.iTunes:replaygain_album_gain": "replaygain_album_gain",
|
|
3190
|
+
"----:com.apple.iTunes:replaygain_album_peak": "replaygain_album_peak",
|
|
3191
|
+
"----:com.apple.iTunes:replaygain_track_minmax": "replaygain_track_minmax",
|
|
3192
|
+
"----:com.apple.iTunes:replaygain_album_minmax": "replaygain_album_minmax",
|
|
3193
|
+
"----:com.apple.iTunes:replaygain_undo": "replaygain_undo",
|
|
3194
|
+
// Additional mappings:
|
|
3195
|
+
gnre: "genre",
|
|
3196
|
+
// ToDo: check mapping
|
|
3197
|
+
"----:com.apple.iTunes:ALBUMARTISTSORT": "albumartistsort",
|
|
3198
|
+
"----:com.apple.iTunes:ARTISTS": "artists",
|
|
3199
|
+
"----:com.apple.iTunes:ORIGINALDATE": "originaldate",
|
|
3200
|
+
"----:com.apple.iTunes:ORIGINALYEAR": "originalyear",
|
|
3201
|
+
"----:com.apple.iTunes:RELEASEDATE": "releasedate",
|
|
3202
|
+
// '----:com.apple.iTunes:PERFORMER': 'performer'
|
|
3203
|
+
desc: "description",
|
|
3204
|
+
ldes: "longDescription",
|
|
3205
|
+
"\xA9mvn": "movement",
|
|
3206
|
+
"\xA9mvi": "movementIndex",
|
|
3207
|
+
"\xA9mvc": "movementTotal",
|
|
3208
|
+
"\xA9wrk": "work",
|
|
3209
|
+
catg: "category",
|
|
3210
|
+
egid: "podcastId",
|
|
3211
|
+
hdvd: "hdVideo",
|
|
3212
|
+
keyw: "keywords",
|
|
3213
|
+
shwm: "showMovement",
|
|
3214
|
+
stik: "stik",
|
|
3215
|
+
rate: "rating"
|
|
3216
|
+
}, tagType = "iTunes", MP4TagMapper = class extends CaseInsensitiveTagMap {
|
|
3217
|
+
constructor() {
|
|
3218
|
+
super([tagType], mp4TagMap);
|
|
3219
|
+
}
|
|
3220
|
+
postMap(tag, _warnings) {
|
|
3221
|
+
tag.id === "rate" && (tag.value = {
|
|
3222
|
+
source: void 0,
|
|
3223
|
+
rating: Number.parseFloat(tag.value) / 100
|
|
3224
|
+
});
|
|
3225
|
+
}
|
|
3226
|
+
};
|
|
3227
|
+
|
|
3228
|
+
// node_modules/music-metadata/lib/ogg/vorbis/VorbisTagMapper.js
|
|
3229
|
+
var vorbisTagMap = {
|
|
3230
|
+
TITLE: "title",
|
|
3231
|
+
ARTIST: "artist",
|
|
3232
|
+
ARTISTS: "artists",
|
|
3233
|
+
ALBUMARTIST: "albumartist",
|
|
3234
|
+
"ALBUM ARTIST": "albumartist",
|
|
3235
|
+
ALBUM: "album",
|
|
3236
|
+
DATE: "date",
|
|
3237
|
+
ORIGINALDATE: "originaldate",
|
|
3238
|
+
ORIGINALYEAR: "originalyear",
|
|
3239
|
+
RELEASEDATE: "releasedate",
|
|
3240
|
+
COMMENT: "comment",
|
|
3241
|
+
TRACKNUMBER: "track",
|
|
3242
|
+
DISCNUMBER: "disk",
|
|
3243
|
+
GENRE: "genre",
|
|
3244
|
+
METADATA_BLOCK_PICTURE: "picture",
|
|
3245
|
+
COMPOSER: "composer",
|
|
3246
|
+
LYRICS: "lyrics",
|
|
3247
|
+
ALBUMSORT: "albumsort",
|
|
3248
|
+
TITLESORT: "titlesort",
|
|
3249
|
+
WORK: "work",
|
|
3250
|
+
ARTISTSORT: "artistsort",
|
|
3251
|
+
ALBUMARTISTSORT: "albumartistsort",
|
|
3252
|
+
COMPOSERSORT: "composersort",
|
|
3253
|
+
LYRICIST: "lyricist",
|
|
3254
|
+
WRITER: "writer",
|
|
3255
|
+
CONDUCTOR: "conductor",
|
|
3256
|
+
// 'PERFORMER=artist (instrument)': 'performer:instrument', // ToDo
|
|
3257
|
+
REMIXER: "remixer",
|
|
3258
|
+
ARRANGER: "arranger",
|
|
3259
|
+
ENGINEER: "engineer",
|
|
3260
|
+
PRODUCER: "producer",
|
|
3261
|
+
DJMIXER: "djmixer",
|
|
3262
|
+
MIXER: "mixer",
|
|
3263
|
+
LABEL: "label",
|
|
3264
|
+
GROUPING: "grouping",
|
|
3265
|
+
SUBTITLE: "subtitle",
|
|
3266
|
+
DISCSUBTITLE: "discsubtitle",
|
|
3267
|
+
TRACKTOTAL: "totaltracks",
|
|
3268
|
+
DISCTOTAL: "totaldiscs",
|
|
3269
|
+
COMPILATION: "compilation",
|
|
3270
|
+
RATING: "rating",
|
|
3271
|
+
BPM: "bpm",
|
|
3272
|
+
KEY: "key",
|
|
3273
|
+
MOOD: "mood",
|
|
3274
|
+
MEDIA: "media",
|
|
3275
|
+
CATALOGNUMBER: "catalognumber",
|
|
3276
|
+
RELEASESTATUS: "releasestatus",
|
|
3277
|
+
RELEASETYPE: "releasetype",
|
|
3278
|
+
RELEASECOUNTRY: "releasecountry",
|
|
3279
|
+
SCRIPT: "script",
|
|
3280
|
+
LANGUAGE: "language",
|
|
3281
|
+
COPYRIGHT: "copyright",
|
|
3282
|
+
LICENSE: "license",
|
|
3283
|
+
ENCODEDBY: "encodedby",
|
|
3284
|
+
ENCODERSETTINGS: "encodersettings",
|
|
3285
|
+
BARCODE: "barcode",
|
|
3286
|
+
ISRC: "isrc",
|
|
3287
|
+
ASIN: "asin",
|
|
3288
|
+
MUSICBRAINZ_TRACKID: "musicbrainz_recordingid",
|
|
3289
|
+
MUSICBRAINZ_RELEASETRACKID: "musicbrainz_trackid",
|
|
3290
|
+
MUSICBRAINZ_ALBUMID: "musicbrainz_albumid",
|
|
3291
|
+
MUSICBRAINZ_ARTISTID: "musicbrainz_artistid",
|
|
3292
|
+
MUSICBRAINZ_ALBUMARTISTID: "musicbrainz_albumartistid",
|
|
3293
|
+
MUSICBRAINZ_RELEASEGROUPID: "musicbrainz_releasegroupid",
|
|
3294
|
+
MUSICBRAINZ_WORKID: "musicbrainz_workid",
|
|
3295
|
+
MUSICBRAINZ_TRMID: "musicbrainz_trmid",
|
|
3296
|
+
MUSICBRAINZ_DISCID: "musicbrainz_discid",
|
|
3297
|
+
ACOUSTID_ID: "acoustid_id",
|
|
3298
|
+
ACOUSTID_ID_FINGERPRINT: "acoustid_fingerprint",
|
|
3299
|
+
MUSICIP_PUID: "musicip_puid",
|
|
3300
|
+
// 'FINGERPRINT=MusicMagic Fingerprint {fingerprint}': 'musicip_fingerprint', // ToDo
|
|
3301
|
+
WEBSITE: "website",
|
|
3302
|
+
NOTES: "notes",
|
|
3303
|
+
TOTALTRACKS: "totaltracks",
|
|
3304
|
+
TOTALDISCS: "totaldiscs",
|
|
3305
|
+
// Discogs
|
|
3306
|
+
DISCOGS_ARTIST_ID: "discogs_artist_id",
|
|
3307
|
+
DISCOGS_ARTISTS: "artists",
|
|
3308
|
+
DISCOGS_ARTIST_NAME: "artists",
|
|
3309
|
+
DISCOGS_ALBUM_ARTISTS: "albumartist",
|
|
3310
|
+
DISCOGS_CATALOG: "catalognumber",
|
|
3311
|
+
DISCOGS_COUNTRY: "releasecountry",
|
|
3312
|
+
DISCOGS_DATE: "originaldate",
|
|
3313
|
+
DISCOGS_LABEL: "label",
|
|
3314
|
+
DISCOGS_LABEL_ID: "discogs_label_id",
|
|
3315
|
+
DISCOGS_MASTER_RELEASE_ID: "discogs_master_release_id",
|
|
3316
|
+
DISCOGS_RATING: "discogs_rating",
|
|
3317
|
+
DISCOGS_RELEASED: "date",
|
|
3318
|
+
DISCOGS_RELEASE_ID: "discogs_release_id",
|
|
3319
|
+
DISCOGS_VOTES: "discogs_votes",
|
|
3320
|
+
CATALOGID: "catalognumber",
|
|
3321
|
+
STYLE: "genre",
|
|
3322
|
+
//
|
|
3323
|
+
REPLAYGAIN_TRACK_GAIN: "replaygain_track_gain",
|
|
3324
|
+
REPLAYGAIN_TRACK_PEAK: "replaygain_track_peak",
|
|
3325
|
+
REPLAYGAIN_ALBUM_GAIN: "replaygain_album_gain",
|
|
3326
|
+
REPLAYGAIN_ALBUM_PEAK: "replaygain_album_peak",
|
|
3327
|
+
// To Sure if these (REPLAYGAIN_MINMAX, REPLAYGAIN_ALBUM_MINMAX & REPLAYGAIN_UNDO) are used for Vorbis:
|
|
3328
|
+
REPLAYGAIN_MINMAX: "replaygain_track_minmax",
|
|
3329
|
+
REPLAYGAIN_ALBUM_MINMAX: "replaygain_album_minmax",
|
|
3330
|
+
REPLAYGAIN_UNDO: "replaygain_undo"
|
|
3331
|
+
}, VorbisTagMapper = class _VorbisTagMapper extends CommonTagMapper {
|
|
3332
|
+
static toRating(email, rating, maxScore) {
|
|
3333
|
+
return {
|
|
3334
|
+
source: email ? email.toLowerCase() : void 0,
|
|
3335
|
+
rating: Number.parseFloat(rating) / maxScore * CommonTagMapper.maxRatingScore
|
|
3336
|
+
};
|
|
3337
|
+
}
|
|
3338
|
+
constructor() {
|
|
3339
|
+
super(["vorbis"], vorbisTagMap);
|
|
3340
|
+
}
|
|
3341
|
+
postMap(tag) {
|
|
3342
|
+
if (tag.id === "RATING")
|
|
3343
|
+
tag.value = _VorbisTagMapper.toRating(void 0, tag.value, 100);
|
|
3344
|
+
else if (tag.id.indexOf("RATING:") === 0) {
|
|
3345
|
+
let keys = tag.id.split(":");
|
|
3346
|
+
tag.value = _VorbisTagMapper.toRating(keys[1], tag.value, 1), tag.id = keys[0];
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
};
|
|
3350
|
+
|
|
3351
|
+
// node_modules/music-metadata/lib/riff/RiffInfoTagMap.js
|
|
3352
|
+
var riffInfoTagMap = {
|
|
3353
|
+
IART: "artist",
|
|
3354
|
+
// Artist
|
|
3355
|
+
ICRD: "date",
|
|
3356
|
+
// DateCreated
|
|
3357
|
+
INAM: "title",
|
|
3358
|
+
// Title
|
|
3359
|
+
TITL: "title",
|
|
3360
|
+
IPRD: "album",
|
|
3361
|
+
// Product
|
|
3362
|
+
ITRK: "track",
|
|
3363
|
+
IPRT: "track",
|
|
3364
|
+
// Additional tag for track index
|
|
3365
|
+
COMM: "comment",
|
|
3366
|
+
// Comments
|
|
3367
|
+
ICMT: "comment",
|
|
3368
|
+
// Country
|
|
3369
|
+
ICNT: "releasecountry",
|
|
3370
|
+
GNRE: "genre",
|
|
3371
|
+
// Genre
|
|
3372
|
+
IWRI: "writer",
|
|
3373
|
+
// WrittenBy
|
|
3374
|
+
RATE: "rating",
|
|
3375
|
+
YEAR: "year",
|
|
3376
|
+
ISFT: "encodedby",
|
|
3377
|
+
// Software
|
|
3378
|
+
CODE: "encodedby",
|
|
3379
|
+
// EncodedBy
|
|
3380
|
+
TURL: "website",
|
|
3381
|
+
// URL,
|
|
3382
|
+
IGNR: "genre",
|
|
3383
|
+
// Genre
|
|
3384
|
+
IENG: "engineer",
|
|
3385
|
+
// Engineer
|
|
3386
|
+
ITCH: "technician",
|
|
3387
|
+
// Technician
|
|
3388
|
+
IMED: "media",
|
|
3389
|
+
// Original Media
|
|
3390
|
+
IRPD: "album"
|
|
3391
|
+
// Product, where the file was intended for
|
|
3392
|
+
}, RiffInfoTagMapper = class extends CommonTagMapper {
|
|
3393
|
+
constructor() {
|
|
3394
|
+
super(["exif"], riffInfoTagMap);
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
|
|
3398
|
+
// node_modules/music-metadata/lib/matroska/MatroskaTagMapper.js
|
|
3399
|
+
var ebmlTagMap = {
|
|
3400
|
+
"segment:title": "title",
|
|
3401
|
+
"album:ARTIST": "albumartist",
|
|
3402
|
+
"album:ARTISTSORT": "albumartistsort",
|
|
3403
|
+
"album:TITLE": "album",
|
|
3404
|
+
"album:DATE_RECORDED": "originaldate",
|
|
3405
|
+
"album:DATE_RELEASED": "releasedate",
|
|
3406
|
+
"album:PART_NUMBER": "disk",
|
|
3407
|
+
"album:TOTAL_PARTS": "totaltracks",
|
|
3408
|
+
"track:ARTIST": "artist",
|
|
3409
|
+
"track:ARTISTSORT": "artistsort",
|
|
3410
|
+
"track:TITLE": "title",
|
|
3411
|
+
"track:PART_NUMBER": "track",
|
|
3412
|
+
"track:MUSICBRAINZ_TRACKID": "musicbrainz_recordingid",
|
|
3413
|
+
"track:MUSICBRAINZ_ALBUMID": "musicbrainz_albumid",
|
|
3414
|
+
"track:MUSICBRAINZ_ARTISTID": "musicbrainz_artistid",
|
|
3415
|
+
"track:PUBLISHER": "label",
|
|
3416
|
+
"track:GENRE": "genre",
|
|
3417
|
+
"track:ENCODER": "encodedby",
|
|
3418
|
+
"track:ENCODER_OPTIONS": "encodersettings",
|
|
3419
|
+
"edition:TOTAL_PARTS": "totaldiscs",
|
|
3420
|
+
picture: "picture"
|
|
3421
|
+
}, MatroskaTagMapper = class extends CaseInsensitiveTagMap {
|
|
3422
|
+
constructor() {
|
|
3423
|
+
super(["matroska"], ebmlTagMap);
|
|
3424
|
+
}
|
|
3425
|
+
};
|
|
3426
|
+
|
|
3427
|
+
// node_modules/music-metadata/lib/aiff/AiffTagMap.js
|
|
3428
|
+
var tagMap = {
|
|
3429
|
+
NAME: "title",
|
|
3430
|
+
AUTH: "artist",
|
|
3431
|
+
"(c) ": "copyright",
|
|
3432
|
+
ANNO: "comment"
|
|
3433
|
+
}, AiffTagMapper = class extends CommonTagMapper {
|
|
3434
|
+
constructor() {
|
|
3435
|
+
super(["AIFF"], tagMap);
|
|
3436
|
+
}
|
|
3437
|
+
};
|
|
3438
|
+
|
|
3439
|
+
// node_modules/music-metadata/lib/common/CombinedTagMapper.js
|
|
3440
|
+
var CombinedTagMapper = class {
|
|
3441
|
+
constructor() {
|
|
3442
|
+
this.tagMappers = {}, [
|
|
3443
|
+
new ID3v1TagMapper(),
|
|
3444
|
+
new ID3v22TagMapper(),
|
|
3445
|
+
new ID3v24TagMapper(),
|
|
3446
|
+
new MP4TagMapper(),
|
|
3447
|
+
new MP4TagMapper(),
|
|
3448
|
+
new VorbisTagMapper(),
|
|
3449
|
+
new APEv2TagMapper(),
|
|
3450
|
+
new AsfTagMapper(),
|
|
3451
|
+
new RiffInfoTagMapper(),
|
|
3452
|
+
new MatroskaTagMapper(),
|
|
3453
|
+
new AiffTagMapper()
|
|
3454
|
+
].forEach((mapper) => {
|
|
3455
|
+
this.registerTagMapper(mapper);
|
|
3456
|
+
});
|
|
3457
|
+
}
|
|
3458
|
+
/**
|
|
3459
|
+
* Convert native to generic (common) tags
|
|
3460
|
+
* @param tagType Originating tag format
|
|
3461
|
+
* @param tag Native tag to map to a generic tag id
|
|
3462
|
+
* @param warnings
|
|
3463
|
+
* @return Generic tag result (output of this function)
|
|
3464
|
+
*/
|
|
3465
|
+
mapTag(tagType2, tag, warnings) {
|
|
3466
|
+
if (this.tagMappers[tagType2])
|
|
3467
|
+
return this.tagMappers[tagType2].mapGenericTag(tag, warnings);
|
|
3468
|
+
throw new InternalParserError(`No generic tag mapper defined for tag-format: ${tagType2}`);
|
|
3469
|
+
}
|
|
3470
|
+
registerTagMapper(genericTagMapper) {
|
|
3471
|
+
for (let tagType2 of genericTagMapper.tagTypes)
|
|
3472
|
+
this.tagMappers[tagType2] = genericTagMapper;
|
|
3473
|
+
}
|
|
3474
|
+
};
|
|
3475
|
+
|
|
3476
|
+
// node_modules/music-metadata/lib/lrc/LyricsParser.js
|
|
3477
|
+
var TIMESTAMP_REGEX = /\[(\d{2}):(\d{2})\.(\d{2,3})]/;
|
|
3478
|
+
function parseLyrics(input) {
|
|
3479
|
+
return TIMESTAMP_REGEX.test(input) ? parseLrc(input) : toUnsyncedLyrics(input);
|
|
3480
|
+
}
|
|
3481
|
+
function toUnsyncedLyrics(lyrics) {
|
|
3482
|
+
return {
|
|
3483
|
+
contentType: LyricsContentType.lyrics,
|
|
3484
|
+
timeStampFormat: TimestampFormat.notSynchronized,
|
|
3485
|
+
text: lyrics.trim(),
|
|
3486
|
+
syncText: []
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
function parseLrc(lrcString) {
|
|
3490
|
+
let lines = lrcString.split(`
|
|
3491
|
+
`), syncText = [];
|
|
3492
|
+
for (let line of lines) {
|
|
3493
|
+
let match = line.match(TIMESTAMP_REGEX);
|
|
3494
|
+
if (match) {
|
|
3495
|
+
let minutes = Number.parseInt(match[1], 10), seconds = Number.parseInt(match[2], 10), ms = match[3].length === 3 ? Number.parseInt(match[3], 10) : Number.parseInt(match[3], 10) * 10, timestamp = (minutes * 60 + seconds) * 1e3 + ms, text = line.replace(TIMESTAMP_REGEX, "").trim();
|
|
3496
|
+
syncText.push({ timestamp, text });
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
return {
|
|
3500
|
+
contentType: LyricsContentType.lyrics,
|
|
3501
|
+
timeStampFormat: TimestampFormat.milliseconds,
|
|
3502
|
+
text: syncText.map((line) => line.text).join(`
|
|
3503
|
+
`),
|
|
3504
|
+
syncText
|
|
3505
|
+
};
|
|
3506
|
+
}
|
|
3507
|
+
|
|
3508
|
+
// node_modules/music-metadata/lib/common/MetadataCollector.js
|
|
3509
|
+
var debug2 = (0, import_debug2.default)("music-metadata:collector"), TagPriority = ["matroska", "APEv2", "vorbis", "ID3v2.4", "ID3v2.3", "ID3v2.2", "exif", "asf", "iTunes", "AIFF", "ID3v1"], MetadataCollector = class {
|
|
3510
|
+
constructor(opts) {
|
|
3511
|
+
this.format = {
|
|
3512
|
+
tagTypes: [],
|
|
3513
|
+
trackInfo: []
|
|
3514
|
+
}, this.native = {}, this.common = {
|
|
3515
|
+
track: { no: null, of: null },
|
|
3516
|
+
disk: { no: null, of: null },
|
|
3517
|
+
movementIndex: { no: null, of: null }
|
|
3518
|
+
}, this.quality = {
|
|
3519
|
+
warnings: []
|
|
3520
|
+
}, this.commonOrigin = {}, this.originPriority = {}, this.tagMapper = new CombinedTagMapper(), this.opts = opts;
|
|
3521
|
+
let priority = 1;
|
|
3522
|
+
for (let tagType2 of TagPriority)
|
|
3523
|
+
this.originPriority[tagType2] = priority++;
|
|
3524
|
+
this.originPriority.artificial = 500, this.originPriority.id3v1 = 600;
|
|
3525
|
+
}
|
|
3526
|
+
/**
|
|
3527
|
+
* @returns {boolean} true if one or more tags have been found
|
|
3528
|
+
*/
|
|
3529
|
+
hasAny() {
|
|
3530
|
+
return Object.keys(this.native).length > 0;
|
|
3531
|
+
}
|
|
3532
|
+
addStreamInfo(streamInfo) {
|
|
3533
|
+
debug2(`streamInfo: type=${streamInfo.type ? TrackTypeValueToKeyMap[streamInfo.type] : "?"}, codec=${streamInfo.codecName}`), this.format.trackInfo.push(streamInfo);
|
|
3534
|
+
}
|
|
3535
|
+
setFormat(key, value) {
|
|
3536
|
+
debug2(`format: ${key} = ${value}`), this.format[key] = value, this.opts?.observer && this.opts.observer({ metadata: this, tag: { type: "format", id: key, value } });
|
|
3537
|
+
}
|
|
3538
|
+
setAudioOnly() {
|
|
3539
|
+
this.setFormat("hasAudio", !0), this.setFormat("hasVideo", !1);
|
|
3540
|
+
}
|
|
3541
|
+
async addTag(tagType2, tagId, value) {
|
|
3542
|
+
debug2(`tag ${tagType2}.${tagId} = ${value}`), this.native[tagType2] || (this.format.tagTypes.push(tagType2), this.native[tagType2] = []), this.native[tagType2].push({ id: tagId, value }), await this.toCommon(tagType2, tagId, value);
|
|
3543
|
+
}
|
|
3544
|
+
addWarning(warning) {
|
|
3545
|
+
this.quality.warnings.push({ message: warning });
|
|
3546
|
+
}
|
|
3547
|
+
async postMap(tagType2, tag) {
|
|
3548
|
+
switch (tag.id) {
|
|
3549
|
+
case "artist":
|
|
3550
|
+
return this.handleSingularArtistTag(tagType2, tag, "artist", "artists");
|
|
3551
|
+
case "albumartist":
|
|
3552
|
+
return this.handleSingularArtistTag(tagType2, tag, "albumartist", "albumartists");
|
|
3553
|
+
case "artists":
|
|
3554
|
+
return this.handlePluralArtistTag(tagType2, tag, "artist", "artists");
|
|
3555
|
+
case "albumartists":
|
|
3556
|
+
return this.handlePluralArtistTag(tagType2, tag, "albumartist", "albumartists");
|
|
3557
|
+
case "picture":
|
|
3558
|
+
return this.postFixPicture(tag.value).then((picture) => {
|
|
3559
|
+
picture !== null && (tag.value = picture, this.setGenericTag(tagType2, tag));
|
|
3560
|
+
});
|
|
3561
|
+
case "totaltracks":
|
|
3562
|
+
this.common.track.of = CommonTagMapper.toIntOrNull(tag.value);
|
|
3563
|
+
return;
|
|
3564
|
+
case "totaldiscs":
|
|
3565
|
+
this.common.disk.of = CommonTagMapper.toIntOrNull(tag.value);
|
|
3566
|
+
return;
|
|
3567
|
+
case "movementTotal":
|
|
3568
|
+
this.common.movementIndex.of = CommonTagMapper.toIntOrNull(tag.value);
|
|
3569
|
+
return;
|
|
3570
|
+
case "track":
|
|
3571
|
+
case "disk":
|
|
3572
|
+
case "movementIndex": {
|
|
3573
|
+
let of = this.common[tag.id].of;
|
|
3574
|
+
this.common[tag.id] = CommonTagMapper.normalizeTrack(tag.value), this.common[tag.id].of = of ?? this.common[tag.id].of;
|
|
3575
|
+
return;
|
|
3576
|
+
}
|
|
3577
|
+
case "bpm":
|
|
3578
|
+
case "year":
|
|
3579
|
+
case "originalyear":
|
|
3580
|
+
tag.value = Number.parseInt(tag.value, 10);
|
|
3581
|
+
break;
|
|
3582
|
+
case "date": {
|
|
3583
|
+
let year = Number.parseInt(tag.value.substr(0, 4), 10);
|
|
3584
|
+
Number.isNaN(year) || (this.common.year = year);
|
|
3585
|
+
break;
|
|
3586
|
+
}
|
|
3587
|
+
case "discogs_label_id":
|
|
3588
|
+
case "discogs_release_id":
|
|
3589
|
+
case "discogs_master_release_id":
|
|
3590
|
+
case "discogs_artist_id":
|
|
3591
|
+
case "discogs_votes":
|
|
3592
|
+
tag.value = typeof tag.value == "string" ? Number.parseInt(tag.value, 10) : tag.value;
|
|
3593
|
+
break;
|
|
3594
|
+
case "replaygain_track_gain":
|
|
3595
|
+
case "replaygain_track_peak":
|
|
3596
|
+
case "replaygain_album_gain":
|
|
3597
|
+
case "replaygain_album_peak":
|
|
3598
|
+
tag.value = toRatio(tag.value);
|
|
3599
|
+
break;
|
|
3600
|
+
case "replaygain_track_minmax":
|
|
3601
|
+
tag.value = tag.value.split(",").map((v) => Number.parseInt(v, 10));
|
|
3602
|
+
break;
|
|
3603
|
+
case "replaygain_undo": {
|
|
3604
|
+
let minMix = tag.value.split(",").map((v) => Number.parseInt(v, 10));
|
|
3605
|
+
tag.value = {
|
|
3606
|
+
leftChannel: minMix[0],
|
|
3607
|
+
rightChannel: minMix[1]
|
|
3608
|
+
};
|
|
3609
|
+
break;
|
|
3610
|
+
}
|
|
3611
|
+
case "gapless":
|
|
3612
|
+
// iTunes gap-less flag
|
|
3613
|
+
case "compilation":
|
|
3614
|
+
case "podcast":
|
|
3615
|
+
case "showMovement":
|
|
3616
|
+
tag.value = tag.value === "1" || tag.value === 1;
|
|
3617
|
+
break;
|
|
3618
|
+
case "isrc": {
|
|
3619
|
+
let commonTag = this.common[tag.id];
|
|
3620
|
+
if (commonTag && commonTag.indexOf(tag.value) !== -1)
|
|
3621
|
+
return;
|
|
3622
|
+
break;
|
|
3623
|
+
}
|
|
3624
|
+
case "comment":
|
|
3625
|
+
typeof tag.value == "string" && (tag.value = { text: tag.value }), tag.value.descriptor === "iTunPGAP" && this.setGenericTag(tagType2, { id: "gapless", value: tag.value.text === "1" });
|
|
3626
|
+
break;
|
|
3627
|
+
case "lyrics":
|
|
3628
|
+
typeof tag.value == "string" && (tag.value = parseLyrics(tag.value));
|
|
3629
|
+
break;
|
|
3630
|
+
default:
|
|
3631
|
+
}
|
|
3632
|
+
tag.value !== null && this.setGenericTag(tagType2, tag);
|
|
3633
|
+
}
|
|
3634
|
+
/**
|
|
3635
|
+
* Convert native tags to common tags
|
|
3636
|
+
* @returns {IAudioMetadata} Native + common tags
|
|
3637
|
+
*/
|
|
3638
|
+
toCommonMetadata() {
|
|
3639
|
+
return {
|
|
3640
|
+
format: this.format,
|
|
3641
|
+
native: this.native,
|
|
3642
|
+
quality: this.quality,
|
|
3643
|
+
common: this.common
|
|
3644
|
+
};
|
|
3645
|
+
}
|
|
3646
|
+
/**
|
|
3647
|
+
* Handle singular artist tags (artist, albumartist) and cross-populate to plural form
|
|
3648
|
+
*/
|
|
3649
|
+
handleSingularArtistTag(tagType2, tag, singularId, pluralId) {
|
|
3650
|
+
if (this.commonOrigin[singularId] === this.originPriority[tagType2])
|
|
3651
|
+
return this.postMap("artificial", { id: pluralId, value: tag.value });
|
|
3652
|
+
this.common[pluralId] || this.setGenericTag("artificial", { id: pluralId, value: tag.value }), this.setGenericTag(tagType2, tag);
|
|
3653
|
+
}
|
|
3654
|
+
/**
|
|
3655
|
+
* Handle plural artist tags (artists, albumartists) and cross-populate to singular form
|
|
3656
|
+
*/
|
|
3657
|
+
handlePluralArtistTag(tagType2, tag, singularId, pluralId) {
|
|
3658
|
+
if ((!this.common[singularId] || this.commonOrigin[singularId] === this.originPriority.artificial) && (!this.common[pluralId] || this.common[pluralId].indexOf(tag.value) === -1)) {
|
|
3659
|
+
let values = (this.common[pluralId] || []).concat([tag.value]), value = joinArtists(values);
|
|
3660
|
+
this.setGenericTag("artificial", { id: singularId, value });
|
|
3661
|
+
}
|
|
3662
|
+
this.setGenericTag(tagType2, tag);
|
|
3663
|
+
}
|
|
3664
|
+
/**
|
|
3665
|
+
* Fix some common issues with picture object
|
|
3666
|
+
* @param picture Picture
|
|
3667
|
+
*/
|
|
3668
|
+
async postFixPicture(picture) {
|
|
3669
|
+
if (picture.data && picture.data.length > 0) {
|
|
3670
|
+
if (!picture.format) {
|
|
3671
|
+
let fileType = await fileTypeFromBuffer(Uint8Array.from(picture.data));
|
|
3672
|
+
if (fileType)
|
|
3673
|
+
picture.format = fileType.mime;
|
|
3674
|
+
else
|
|
3675
|
+
return null;
|
|
3676
|
+
}
|
|
3677
|
+
return picture.format = picture.format.toLocaleLowerCase(), picture.format === "image/jpg" && (picture.format = "image/jpeg"), picture;
|
|
3678
|
+
}
|
|
3679
|
+
return this.addWarning("Empty picture tag found"), null;
|
|
3680
|
+
}
|
|
3681
|
+
/**
|
|
3682
|
+
* Convert native tag to common tags
|
|
3683
|
+
*/
|
|
3684
|
+
async toCommon(tagType2, tagId, value) {
|
|
3685
|
+
let tag = { id: tagId, value }, genericTag = this.tagMapper.mapTag(tagType2, tag, this);
|
|
3686
|
+
genericTag && await this.postMap(tagType2, genericTag);
|
|
3687
|
+
}
|
|
3688
|
+
/**
|
|
3689
|
+
* Set generic tag
|
|
3690
|
+
*/
|
|
3691
|
+
setGenericTag(tagType2, tag) {
|
|
3692
|
+
debug2(`common.${tag.id} = ${tag.value}`);
|
|
3693
|
+
let prio0 = this.commonOrigin[tag.id] || 1e3, prio1 = this.originPriority[tagType2];
|
|
3694
|
+
if (isSingleton(tag.id))
|
|
3695
|
+
if (prio1 <= prio0)
|
|
3696
|
+
this.common[tag.id] = tag.value, this.commonOrigin[tag.id] = prio1;
|
|
3697
|
+
else
|
|
3698
|
+
return debug2(`Ignore native tag (singleton): ${tagType2}.${tag.id} = ${tag.value}`);
|
|
3699
|
+
else if (prio1 === prio0)
|
|
3700
|
+
!isUnique(tag.id) || this.common[tag.id].indexOf(tag.value) === -1 ? this.common[tag.id].push(tag.value) : debug2(`Ignore duplicate value: ${tagType2}.${tag.id} = ${tag.value}`);
|
|
3701
|
+
else if (prio1 < prio0)
|
|
3702
|
+
this.common[tag.id] = [tag.value], this.commonOrigin[tag.id] = prio1;
|
|
3703
|
+
else
|
|
3704
|
+
return debug2(`Ignore native tag (list): ${tagType2}.${tag.id} = ${tag.value}`);
|
|
3705
|
+
this.opts?.observer && this.opts.observer({ metadata: this, tag: { type: "common", id: tag.id, value: tag.value } });
|
|
3706
|
+
}
|
|
3707
|
+
};
|
|
3708
|
+
function joinArtists(artists) {
|
|
3709
|
+
return artists.length > 2 ? `${artists.slice(0, artists.length - 1).join(", ")} & ${artists[artists.length - 1]}` : artists.join(" & ");
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3712
|
+
// node_modules/music-metadata/lib/mpeg/MpegLoader.js
|
|
3713
|
+
var mpegParserLoader = {
|
|
3714
|
+
parserType: "mpeg",
|
|
3715
|
+
extensions: [".mp2", ".mp3", ".m2a", ".aac", "aacp"],
|
|
3716
|
+
mimeTypes: ["audio/mpeg", "audio/mp3", "audio/aacs", "audio/aacp"],
|
|
3717
|
+
async load() {
|
|
3718
|
+
return (await import("./MpegParser-YW6LIUEW.mjs")).MpegParser;
|
|
3719
|
+
}
|
|
3720
|
+
};
|
|
3721
|
+
|
|
3722
|
+
// node_modules/music-metadata/lib/apev2/Apev2Loader.js
|
|
3723
|
+
var apeParserLoader = {
|
|
3724
|
+
parserType: "apev2",
|
|
3725
|
+
extensions: [".ape"],
|
|
3726
|
+
mimeTypes: ["audio/ape", "audio/monkeys-audio"],
|
|
3727
|
+
async load() {
|
|
3728
|
+
return (await import("./APEv2Parser-2CNNHMXV.mjs")).APEv2Parser;
|
|
3729
|
+
}
|
|
3730
|
+
};
|
|
3731
|
+
|
|
3732
|
+
// node_modules/music-metadata/lib/asf/AsfLoader.js
|
|
3733
|
+
var asfParserLoader = {
|
|
3734
|
+
parserType: "asf",
|
|
3735
|
+
extensions: [".asf", ".wma", ".wmv"],
|
|
3736
|
+
mimeTypes: ["audio/ms-wma", "video/ms-wmv", "audio/ms-asf", "video/ms-asf", "application/vnd.ms-asf"],
|
|
3737
|
+
async load() {
|
|
3738
|
+
return (await import("./AsfParser-VVRSLFOM.mjs")).AsfParser;
|
|
3739
|
+
}
|
|
3740
|
+
};
|
|
3741
|
+
|
|
3742
|
+
// node_modules/music-metadata/lib/dsdiff/DsdiffLoader.js
|
|
3743
|
+
var dsdiffParserLoader = {
|
|
3744
|
+
parserType: "dsdiff",
|
|
3745
|
+
extensions: [".dff"],
|
|
3746
|
+
mimeTypes: ["audio/dsf", "audio/dsd"],
|
|
3747
|
+
async load() {
|
|
3748
|
+
return (await import("./DsdiffParser-CMD4AX7A.mjs")).DsdiffParser;
|
|
3749
|
+
}
|
|
3750
|
+
};
|
|
3751
|
+
|
|
3752
|
+
// node_modules/music-metadata/lib/aiff/AiffLoader.js
|
|
3753
|
+
var aiffParserLoader = {
|
|
3754
|
+
parserType: "aiff",
|
|
3755
|
+
extensions: [".aif", "aiff", "aifc"],
|
|
3756
|
+
mimeTypes: ["audio/aiff", "audio/aif", "audio/aifc", "application/aiff"],
|
|
3757
|
+
async load() {
|
|
3758
|
+
return (await import("./AiffParser-7BR4RL6G.mjs")).AIFFParser;
|
|
3759
|
+
}
|
|
3760
|
+
};
|
|
3761
|
+
|
|
3762
|
+
// node_modules/music-metadata/lib/dsf/DsfLoader.js
|
|
3763
|
+
var dsfParserLoader = {
|
|
3764
|
+
parserType: "dsf",
|
|
3765
|
+
extensions: [".dsf"],
|
|
3766
|
+
mimeTypes: ["audio/dsf"],
|
|
3767
|
+
async load() {
|
|
3768
|
+
return (await import("./DsfParser-UOGZDS2M.mjs")).DsfParser;
|
|
3769
|
+
}
|
|
3770
|
+
};
|
|
3771
|
+
|
|
3772
|
+
// node_modules/music-metadata/lib/flac/FlacLoader.js
|
|
3773
|
+
var flacParserLoader = {
|
|
3774
|
+
parserType: "flac",
|
|
3775
|
+
extensions: [".flac"],
|
|
3776
|
+
mimeTypes: ["audio/flac"],
|
|
3777
|
+
async load() {
|
|
3778
|
+
return (await import("./FlacParser-HB3T3CD4.mjs")).FlacParser;
|
|
3779
|
+
}
|
|
3780
|
+
};
|
|
3781
|
+
|
|
3782
|
+
// node_modules/music-metadata/lib/matroska/MatroskaLoader.js
|
|
3783
|
+
var matroskaParserLoader = {
|
|
3784
|
+
parserType: "matroska",
|
|
3785
|
+
extensions: [".mka", ".mkv", ".mk3d", ".mks", "webm"],
|
|
3786
|
+
mimeTypes: ["audio/matroska", "video/matroska", "audio/webm", "video/webm"],
|
|
3787
|
+
async load() {
|
|
3788
|
+
return (await import("./MatroskaParser-J3HUIMEW.mjs")).MatroskaParser;
|
|
3789
|
+
}
|
|
3790
|
+
};
|
|
3791
|
+
|
|
3792
|
+
// node_modules/music-metadata/lib/mp4/Mp4Loader.js
|
|
3793
|
+
var mp4ParserLoader = {
|
|
3794
|
+
parserType: "mp4",
|
|
3795
|
+
extensions: [".mp4", ".m4a", ".m4b", ".m4pa", "m4v", "m4r", "3gp", ".mov", ".movie", ".qt"],
|
|
3796
|
+
mimeTypes: ["audio/mp4", "audio/m4a", "video/m4v", "video/mp4", "video/quicktime"],
|
|
3797
|
+
async load() {
|
|
3798
|
+
return (await import("./MP4Parser-66HBRUSX.mjs")).MP4Parser;
|
|
3799
|
+
}
|
|
3800
|
+
};
|
|
3801
|
+
|
|
3802
|
+
// node_modules/music-metadata/lib/musepack/MusepackLoader.js
|
|
3803
|
+
var musepackParserLoader = {
|
|
3804
|
+
parserType: "musepack",
|
|
3805
|
+
extensions: [".mpc"],
|
|
3806
|
+
mimeTypes: ["audio/musepack"],
|
|
3807
|
+
async load() {
|
|
3808
|
+
return (await import("./MusepackParser-PAUSXP7D.mjs")).MusepackParser;
|
|
3809
|
+
}
|
|
3810
|
+
};
|
|
3811
|
+
|
|
3812
|
+
// node_modules/music-metadata/lib/ogg/OggLoader.js
|
|
3813
|
+
var oggParserLoader = {
|
|
3814
|
+
parserType: "ogg",
|
|
3815
|
+
extensions: [".ogg", ".ogv", ".oga", ".ogm", ".ogx", ".opus", ".spx"],
|
|
3816
|
+
mimeTypes: ["audio/ogg", "audio/opus", "audio/speex", "video/ogg"],
|
|
3817
|
+
// RFC 7845, RFC 6716, RFC 5574
|
|
3818
|
+
async load() {
|
|
3819
|
+
return (await import("./OggParser-NUBV3GWC.mjs")).OggParser;
|
|
3820
|
+
}
|
|
3821
|
+
};
|
|
3822
|
+
|
|
3823
|
+
// node_modules/music-metadata/lib/wavpack/WavPackLoader.js
|
|
3824
|
+
var wavpackParserLoader = {
|
|
3825
|
+
parserType: "wavpack",
|
|
3826
|
+
extensions: [".wv", ".wvp"],
|
|
3827
|
+
mimeTypes: ["audio/wavpack"],
|
|
3828
|
+
async load() {
|
|
3829
|
+
return (await import("./WavPackParser-WQAGT7TC.mjs")).WavPackParser;
|
|
3830
|
+
}
|
|
3831
|
+
};
|
|
3832
|
+
|
|
3833
|
+
// node_modules/music-metadata/lib/wav/WaveLoader.js
|
|
3834
|
+
var riffParserLoader = {
|
|
3835
|
+
parserType: "riff",
|
|
3836
|
+
extensions: [".wav", "wave", ".bwf"],
|
|
3837
|
+
mimeTypes: ["audio/vnd.wave", "audio/wav", "audio/wave"],
|
|
3838
|
+
async load() {
|
|
3839
|
+
return (await import("./WaveParser-EWLQVDX4.mjs")).WaveParser;
|
|
3840
|
+
}
|
|
3841
|
+
};
|
|
3842
|
+
|
|
3843
|
+
// node_modules/music-metadata/lib/ParserFactory.js
|
|
3844
|
+
var debug3 = (0, import_debug3.default)("music-metadata:parser:factory");
|
|
3845
|
+
function parseHttpContentType(contentType) {
|
|
3846
|
+
let type = import_content_type.default.parse(contentType), mime = parse(type.type);
|
|
3847
|
+
return {
|
|
3848
|
+
type: mime.type,
|
|
3849
|
+
subtype: mime.subtype,
|
|
3850
|
+
suffix: mime.suffix,
|
|
3851
|
+
parameters: type.parameters
|
|
3852
|
+
};
|
|
3853
|
+
}
|
|
3854
|
+
var ParserFactory = class {
|
|
3855
|
+
constructor() {
|
|
3856
|
+
this.parsers = [], [
|
|
3857
|
+
flacParserLoader,
|
|
3858
|
+
mpegParserLoader,
|
|
3859
|
+
apeParserLoader,
|
|
3860
|
+
mp4ParserLoader,
|
|
3861
|
+
matroskaParserLoader,
|
|
3862
|
+
riffParserLoader,
|
|
3863
|
+
oggParserLoader,
|
|
3864
|
+
asfParserLoader,
|
|
3865
|
+
aiffParserLoader,
|
|
3866
|
+
wavpackParserLoader,
|
|
3867
|
+
musepackParserLoader,
|
|
3868
|
+
dsfParserLoader,
|
|
3869
|
+
dsdiffParserLoader
|
|
3870
|
+
].forEach((parser) => {
|
|
3871
|
+
this.registerParser(parser);
|
|
3872
|
+
});
|
|
3873
|
+
}
|
|
3874
|
+
registerParser(parser) {
|
|
3875
|
+
this.parsers.push(parser);
|
|
3876
|
+
}
|
|
3877
|
+
async parse(tokenizer, parserLoader, opts) {
|
|
3878
|
+
if (tokenizer.supportsRandomAccess() ? (debug3("tokenizer supports random-access, scanning for appending headers"), await scanAppendingHeaders(tokenizer, opts)) : debug3("tokenizer does not support random-access, cannot scan for appending headers"), !parserLoader) {
|
|
3879
|
+
let buf = new Uint8Array(4100);
|
|
3880
|
+
if (tokenizer.fileInfo.mimeType && (parserLoader = this.findLoaderForContentType(tokenizer.fileInfo.mimeType)), !parserLoader && tokenizer.fileInfo.path && (parserLoader = this.findLoaderForExtension(tokenizer.fileInfo.path)), !parserLoader) {
|
|
3881
|
+
debug3("Guess parser on content..."), await tokenizer.peekBuffer(buf, { mayBeLess: !0 });
|
|
3882
|
+
let guessedType = await fileTypeFromBuffer(buf, { mpegOffsetTolerance: 10 });
|
|
3883
|
+
if (!guessedType || !guessedType.mime)
|
|
3884
|
+
throw new CouldNotDetermineFileTypeError("Failed to determine audio format");
|
|
3885
|
+
if (debug3(`Guessed file type is mime=${guessedType.mime}, extension=${guessedType.ext}`), parserLoader = this.findLoaderForContentType(guessedType.mime), !parserLoader)
|
|
3886
|
+
throw new UnsupportedFileTypeError(`Guessed MIME-type not supported: ${guessedType.mime}`);
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
debug3(`Loading ${parserLoader.parserType} parser...`);
|
|
3890
|
+
let metadata = new MetadataCollector(opts), ParserImpl = await parserLoader.load(), parser = new ParserImpl(metadata, tokenizer, opts ?? {});
|
|
3891
|
+
return debug3(`Parser ${parserLoader.parserType} loaded`), await parser.parse(), metadata.format.trackInfo && (metadata.format.hasAudio === void 0 && metadata.setFormat("hasAudio", !!metadata.format.trackInfo.find((track) => track.type === TrackType.audio)), metadata.format.hasVideo === void 0 && metadata.setFormat("hasVideo", !!metadata.format.trackInfo.find((track) => track.type === TrackType.video))), metadata.toCommonMetadata();
|
|
3892
|
+
}
|
|
3893
|
+
/**
|
|
3894
|
+
* @param filePath - Path, filename or extension to audio file
|
|
3895
|
+
* @return Parser submodule name
|
|
3896
|
+
*/
|
|
3897
|
+
findLoaderForExtension(filePath) {
|
|
3898
|
+
if (!filePath)
|
|
3899
|
+
return;
|
|
3900
|
+
let extension = getExtension(filePath).toLocaleLowerCase() || filePath;
|
|
3901
|
+
return this.parsers.find((parser) => parser.extensions.indexOf(extension) !== -1);
|
|
3902
|
+
}
|
|
3903
|
+
findLoaderForContentType(httpContentType) {
|
|
3904
|
+
let mime;
|
|
3905
|
+
if (!httpContentType)
|
|
3906
|
+
return;
|
|
3907
|
+
try {
|
|
3908
|
+
mime = parseHttpContentType(httpContentType);
|
|
3909
|
+
} catch {
|
|
3910
|
+
debug3(`Invalid HTTP Content-Type header value: ${httpContentType}`);
|
|
3911
|
+
return;
|
|
3912
|
+
}
|
|
3913
|
+
let subType = mime.subtype.indexOf("x-") === 0 ? mime.subtype.substring(2) : mime.subtype;
|
|
3914
|
+
return this.parsers.find((parser) => parser.mimeTypes.find((loader) => loader.indexOf(`${mime.type}/${subType}`) !== -1));
|
|
3915
|
+
}
|
|
3916
|
+
getSupportedMimeTypes() {
|
|
3917
|
+
let mimeTypeSet = /* @__PURE__ */ new Set();
|
|
3918
|
+
return this.parsers.forEach((loader) => {
|
|
3919
|
+
loader.mimeTypes.forEach((mimeType) => {
|
|
3920
|
+
mimeTypeSet.add(mimeType), mimeTypeSet.add(mimeType.replace("/", "/x-"));
|
|
3921
|
+
});
|
|
3922
|
+
}), Array.from(mimeTypeSet);
|
|
3923
|
+
}
|
|
3924
|
+
};
|
|
3925
|
+
function getExtension(fname) {
|
|
3926
|
+
let i = fname.lastIndexOf(".");
|
|
3927
|
+
return i === -1 ? "" : fname.substring(i);
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
// node_modules/music-metadata/lib/lyrics3/Lyrics3.js
|
|
3931
|
+
var endTag2 = "LYRICS200";
|
|
3932
|
+
async function getLyricsHeaderLength(tokenizer) {
|
|
3933
|
+
let fileSize = tokenizer.fileInfo.size;
|
|
3934
|
+
if (fileSize >= 143) {
|
|
3935
|
+
let buf = new Uint8Array(15), position = tokenizer.position;
|
|
3936
|
+
await tokenizer.readBuffer(buf, { position: fileSize - 143 }), tokenizer.setPosition(position);
|
|
3937
|
+
let txt = textDecode(buf, "latin1");
|
|
3938
|
+
if (txt.substring(6) === endTag2)
|
|
3939
|
+
return Number.parseInt(txt.substring(0, 6), 10) + 15;
|
|
3940
|
+
}
|
|
3941
|
+
return 0;
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
// node_modules/music-metadata/lib/core.js
|
|
3945
|
+
async function parseBlob(blob, options = {}) {
|
|
3946
|
+
let tokenizer = fromBlob(blob);
|
|
3947
|
+
try {
|
|
3948
|
+
return await parseFromTokenizer(tokenizer, options);
|
|
3949
|
+
} finally {
|
|
3950
|
+
await tokenizer.close();
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3953
|
+
async function parseWebStream(webStream, fileInfo, options = {}) {
|
|
3954
|
+
let tokenizer = fromWebStream(webStream, { fileInfo: typeof fileInfo == "string" ? { mimeType: fileInfo } : fileInfo });
|
|
3955
|
+
try {
|
|
3956
|
+
return await parseFromTokenizer(tokenizer, options);
|
|
3957
|
+
} finally {
|
|
3958
|
+
await tokenizer.close();
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
async function parseBuffer(uint8Array, fileInfo, options = {}) {
|
|
3962
|
+
let tokenizer = fromBuffer(uint8Array, { fileInfo: typeof fileInfo == "string" ? { mimeType: fileInfo } : fileInfo });
|
|
3963
|
+
return parseFromTokenizer(tokenizer, options);
|
|
3964
|
+
}
|
|
3965
|
+
function parseFromTokenizer(tokenizer, options) {
|
|
3966
|
+
return new ParserFactory().parse(tokenizer, void 0, options);
|
|
3967
|
+
}
|
|
3968
|
+
function orderTags(nativeTags) {
|
|
3969
|
+
let tags = {};
|
|
3970
|
+
for (let { id, value } of nativeTags)
|
|
3971
|
+
(tags[id] || (tags[id] = [])).push(value);
|
|
3972
|
+
return tags;
|
|
3973
|
+
}
|
|
3974
|
+
function ratingToStars(rating) {
|
|
3975
|
+
return rating === void 0 ? 0 : 1 + Math.round(rating * 4);
|
|
3976
|
+
}
|
|
3977
|
+
function selectCover(pictures) {
|
|
3978
|
+
return pictures ? pictures.reduce((acc, cur) => cur.name && cur.name.toLowerCase() in ["front", "cover", "cover (front)"] ? cur : acc) : null;
|
|
3979
|
+
}
|
|
3980
|
+
async function scanAppendingHeaders(tokenizer, options = {}) {
|
|
3981
|
+
let apeOffset = tokenizer.fileInfo.size;
|
|
3982
|
+
if (await hasID3v1Header(tokenizer)) {
|
|
3983
|
+
apeOffset -= 128;
|
|
3984
|
+
let lyricsLen = await getLyricsHeaderLength(tokenizer);
|
|
3985
|
+
apeOffset -= lyricsLen;
|
|
3986
|
+
}
|
|
3987
|
+
options.apeHeader = await APEv2Parser.findApeFooterOffset(tokenizer, apeOffset);
|
|
3988
|
+
}
|
|
3989
|
+
function getSupportedMimeTypes() {
|
|
3990
|
+
return new ParserFactory().getSupportedMimeTypes();
|
|
3991
|
+
}
|
|
3992
|
+
|
|
3993
|
+
// node_modules/music-metadata/lib/index.js
|
|
3994
|
+
var debug4 = (0, import_debug4.default)("music-metadata:parser");
|
|
3995
|
+
async function parseStream(stream, fileInfo, options = {}) {
|
|
3996
|
+
let tokenizer = await fromStream(stream, { fileInfo: typeof fileInfo == "string" ? { mimeType: fileInfo } : fileInfo });
|
|
3997
|
+
try {
|
|
3998
|
+
return await parseFromTokenizer(tokenizer, options);
|
|
3999
|
+
} finally {
|
|
4000
|
+
await tokenizer.close();
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
async function parseFile(filePath, options = {}) {
|
|
4004
|
+
debug4(`parseFile: ${filePath}`);
|
|
4005
|
+
let fileTokenizer = await fromFile(filePath), parserFactory = new ParserFactory();
|
|
4006
|
+
try {
|
|
4007
|
+
let parserLoader = parserFactory.findLoaderForExtension(filePath);
|
|
4008
|
+
parserLoader || debug4("Parser could not be determined by file extension");
|
|
4009
|
+
try {
|
|
4010
|
+
return await parserFactory.parse(fileTokenizer, parserLoader, options);
|
|
4011
|
+
} catch (error) {
|
|
4012
|
+
throw (error instanceof CouldNotDetermineFileTypeError || error instanceof UnsupportedFileTypeError) && (error.message += `: ${filePath}`), error;
|
|
4013
|
+
}
|
|
4014
|
+
} finally {
|
|
4015
|
+
await fileTokenizer.close();
|
|
4016
|
+
}
|
|
4017
|
+
}
|
|
4018
|
+
export {
|
|
4019
|
+
CouldNotDetermineFileTypeError,
|
|
4020
|
+
FieldDecodingError,
|
|
4021
|
+
InternalParserError,
|
|
4022
|
+
LyricsContentType,
|
|
4023
|
+
TimestampFormat,
|
|
4024
|
+
UnsupportedFileTypeError,
|
|
4025
|
+
getSupportedMimeTypes,
|
|
4026
|
+
makeParseError,
|
|
4027
|
+
makeUnexpectedFileContentError,
|
|
4028
|
+
orderTags,
|
|
4029
|
+
parseBlob,
|
|
4030
|
+
parseBuffer,
|
|
4031
|
+
parseFile,
|
|
4032
|
+
parseFromTokenizer,
|
|
4033
|
+
parseStream,
|
|
4034
|
+
parseWebStream,
|
|
4035
|
+
ratingToStars,
|
|
4036
|
+
scanAppendingHeaders,
|
|
4037
|
+
selectCover
|
|
4038
|
+
};
|