utils.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. 'use strict';
  2. function parseContentType(str) {
  3. if (str.length === 0)
  4. return;
  5. const params = Object.create(null);
  6. let i = 0;
  7. // Parse type
  8. for (; i < str.length; ++i) {
  9. const code = str.charCodeAt(i);
  10. if (TOKEN[code] !== 1) {
  11. if (code !== 47/* '/' */ || i === 0)
  12. return;
  13. break;
  14. }
  15. }
  16. // Check for type without subtype
  17. if (i === str.length)
  18. return;
  19. const type = str.slice(0, i).toLowerCase();
  20. // Parse subtype
  21. const subtypeStart = ++i;
  22. for (; i < str.length; ++i) {
  23. const code = str.charCodeAt(i);
  24. if (TOKEN[code] !== 1) {
  25. // Make sure we have a subtype
  26. if (i === subtypeStart)
  27. return;
  28. if (parseContentTypeParams(str, i, params) === undefined)
  29. return;
  30. break;
  31. }
  32. }
  33. // Make sure we have a subtype
  34. if (i === subtypeStart)
  35. return;
  36. const subtype = str.slice(subtypeStart, i).toLowerCase();
  37. return { type, subtype, params };
  38. }
  39. function parseContentTypeParams(str, i, params) {
  40. while (i < str.length) {
  41. // Consume whitespace
  42. for (; i < str.length; ++i) {
  43. const code = str.charCodeAt(i);
  44. if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
  45. break;
  46. }
  47. // Ended on whitespace
  48. if (i === str.length)
  49. break;
  50. // Check for malformed parameter
  51. if (str.charCodeAt(i++) !== 59/* ';' */)
  52. return;
  53. // Consume whitespace
  54. for (; i < str.length; ++i) {
  55. const code = str.charCodeAt(i);
  56. if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
  57. break;
  58. }
  59. // Ended on whitespace (malformed)
  60. if (i === str.length)
  61. return;
  62. let name;
  63. const nameStart = i;
  64. // Parse parameter name
  65. for (; i < str.length; ++i) {
  66. const code = str.charCodeAt(i);
  67. if (TOKEN[code] !== 1) {
  68. if (code !== 61/* '=' */)
  69. return;
  70. break;
  71. }
  72. }
  73. // No value (malformed)
  74. if (i === str.length)
  75. return;
  76. name = str.slice(nameStart, i);
  77. ++i; // Skip over '='
  78. // No value (malformed)
  79. if (i === str.length)
  80. return;
  81. let value = '';
  82. let valueStart;
  83. if (str.charCodeAt(i) === 34/* '"' */) {
  84. valueStart = ++i;
  85. let escaping = false;
  86. // Parse quoted value
  87. for (; i < str.length; ++i) {
  88. const code = str.charCodeAt(i);
  89. if (code === 92/* '\\' */) {
  90. if (escaping) {
  91. valueStart = i;
  92. escaping = false;
  93. } else {
  94. value += str.slice(valueStart, i);
  95. escaping = true;
  96. }
  97. continue;
  98. }
  99. if (code === 34/* '"' */) {
  100. if (escaping) {
  101. valueStart = i;
  102. escaping = false;
  103. continue;
  104. }
  105. value += str.slice(valueStart, i);
  106. break;
  107. }
  108. if (escaping) {
  109. valueStart = i - 1;
  110. escaping = false;
  111. }
  112. // Invalid unescaped quoted character (malformed)
  113. if (QDTEXT[code] !== 1)
  114. return;
  115. }
  116. // No end quote (malformed)
  117. if (i === str.length)
  118. return;
  119. ++i; // Skip over double quote
  120. } else {
  121. valueStart = i;
  122. // Parse unquoted value
  123. for (; i < str.length; ++i) {
  124. const code = str.charCodeAt(i);
  125. if (TOKEN[code] !== 1) {
  126. // No value (malformed)
  127. if (i === valueStart)
  128. return;
  129. break;
  130. }
  131. }
  132. value = str.slice(valueStart, i);
  133. }
  134. name = name.toLowerCase();
  135. if (params[name] === undefined)
  136. params[name] = value;
  137. }
  138. return params;
  139. }
  140. function parseDisposition(str, defDecoder) {
  141. if (str.length === 0)
  142. return;
  143. const params = Object.create(null);
  144. let i = 0;
  145. for (; i < str.length; ++i) {
  146. const code = str.charCodeAt(i);
  147. if (TOKEN[code] !== 1) {
  148. if (parseDispositionParams(str, i, params, defDecoder) === undefined)
  149. return;
  150. break;
  151. }
  152. }
  153. const type = str.slice(0, i).toLowerCase();
  154. return { type, params };
  155. }
  156. function parseDispositionParams(str, i, params, defDecoder) {
  157. while (i < str.length) {
  158. // Consume whitespace
  159. for (; i < str.length; ++i) {
  160. const code = str.charCodeAt(i);
  161. if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
  162. break;
  163. }
  164. // Ended on whitespace
  165. if (i === str.length)
  166. break;
  167. // Check for malformed parameter
  168. if (str.charCodeAt(i++) !== 59/* ';' */)
  169. return;
  170. // Consume whitespace
  171. for (; i < str.length; ++i) {
  172. const code = str.charCodeAt(i);
  173. if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
  174. break;
  175. }
  176. // Ended on whitespace (malformed)
  177. if (i === str.length)
  178. return;
  179. let name;
  180. const nameStart = i;
  181. // Parse parameter name
  182. for (; i < str.length; ++i) {
  183. const code = str.charCodeAt(i);
  184. if (TOKEN[code] !== 1) {
  185. if (code === 61/* '=' */)
  186. break;
  187. return;
  188. }
  189. }
  190. // No value (malformed)
  191. if (i === str.length)
  192. return;
  193. let value = '';
  194. let valueStart;
  195. let charset;
  196. //~ let lang;
  197. name = str.slice(nameStart, i);
  198. if (name.charCodeAt(name.length - 1) === 42/* '*' */) {
  199. // Extended value
  200. const charsetStart = ++i;
  201. // Parse charset name
  202. for (; i < str.length; ++i) {
  203. const code = str.charCodeAt(i);
  204. if (CHARSET[code] !== 1) {
  205. if (code !== 39/* '\'' */)
  206. return;
  207. break;
  208. }
  209. }
  210. // Incomplete charset (malformed)
  211. if (i === str.length)
  212. return;
  213. charset = str.slice(charsetStart, i);
  214. ++i; // Skip over the '\''
  215. //~ const langStart = ++i;
  216. // Parse language name
  217. for (; i < str.length; ++i) {
  218. const code = str.charCodeAt(i);
  219. if (code === 39/* '\'' */)
  220. break;
  221. }
  222. // Incomplete language (malformed)
  223. if (i === str.length)
  224. return;
  225. //~ lang = str.slice(langStart, i);
  226. ++i; // Skip over the '\''
  227. // No value (malformed)
  228. if (i === str.length)
  229. return;
  230. valueStart = i;
  231. let encode = 0;
  232. // Parse value
  233. for (; i < str.length; ++i) {
  234. const code = str.charCodeAt(i);
  235. if (EXTENDED_VALUE[code] !== 1) {
  236. if (code === 37/* '%' */) {
  237. let hexUpper;
  238. let hexLower;
  239. if (i + 2 < str.length
  240. && (hexUpper = HEX_VALUES[str.charCodeAt(i + 1)]) !== -1
  241. && (hexLower = HEX_VALUES[str.charCodeAt(i + 2)]) !== -1) {
  242. const byteVal = (hexUpper << 4) + hexLower;
  243. value += str.slice(valueStart, i);
  244. value += String.fromCharCode(byteVal);
  245. i += 2;
  246. valueStart = i + 1;
  247. if (byteVal >= 128)
  248. encode = 2;
  249. else if (encode === 0)
  250. encode = 1;
  251. continue;
  252. }
  253. // '%' disallowed in non-percent encoded contexts (malformed)
  254. return;
  255. }
  256. break;
  257. }
  258. }
  259. value += str.slice(valueStart, i);
  260. value = convertToUTF8(value, charset, encode);
  261. if (value === undefined)
  262. return;
  263. } else {
  264. // Non-extended value
  265. ++i; // Skip over '='
  266. // No value (malformed)
  267. if (i === str.length)
  268. return;
  269. if (str.charCodeAt(i) === 34/* '"' */) {
  270. valueStart = ++i;
  271. let escaping = false;
  272. // Parse quoted value
  273. for (; i < str.length; ++i) {
  274. const code = str.charCodeAt(i);
  275. if (code === 92/* '\\' */) {
  276. if (escaping) {
  277. valueStart = i;
  278. escaping = false;
  279. } else {
  280. value += str.slice(valueStart, i);
  281. escaping = true;
  282. }
  283. continue;
  284. }
  285. if (code === 34/* '"' */) {
  286. if (escaping) {
  287. valueStart = i;
  288. escaping = false;
  289. continue;
  290. }
  291. value += str.slice(valueStart, i);
  292. break;
  293. }
  294. if (escaping) {
  295. valueStart = i - 1;
  296. escaping = false;
  297. }
  298. // Invalid unescaped quoted character (malformed)
  299. if (QDTEXT[code] !== 1)
  300. return;
  301. }
  302. // No end quote (malformed)
  303. if (i === str.length)
  304. return;
  305. ++i; // Skip over double quote
  306. } else {
  307. valueStart = i;
  308. // Parse unquoted value
  309. for (; i < str.length; ++i) {
  310. const code = str.charCodeAt(i);
  311. if (TOKEN[code] !== 1) {
  312. // No value (malformed)
  313. if (i === valueStart)
  314. return;
  315. break;
  316. }
  317. }
  318. value = str.slice(valueStart, i);
  319. }
  320. value = defDecoder(value, 2);
  321. if (value === undefined)
  322. return;
  323. }
  324. name = name.toLowerCase();
  325. if (params[name] === undefined)
  326. params[name] = value;
  327. }
  328. return params;
  329. }
  330. function getDecoder(charset) {
  331. let lc;
  332. while (true) {
  333. switch (charset) {
  334. case 'utf-8':
  335. case 'utf8':
  336. return decoders.utf8;
  337. case 'latin1':
  338. case 'ascii': // TODO: Make these a separate, strict decoder?
  339. case 'us-ascii':
  340. case 'iso-8859-1':
  341. case 'iso8859-1':
  342. case 'iso88591':
  343. case 'iso_8859-1':
  344. case 'windows-1252':
  345. case 'iso_8859-1:1987':
  346. case 'cp1252':
  347. case 'x-cp1252':
  348. return decoders.latin1;
  349. case 'utf16le':
  350. case 'utf-16le':
  351. case 'ucs2':
  352. case 'ucs-2':
  353. return decoders.utf16le;
  354. case 'base64':
  355. return decoders.base64;
  356. default:
  357. if (lc === undefined) {
  358. lc = true;
  359. charset = charset.toLowerCase();
  360. continue;
  361. }
  362. return decoders.other.bind(charset);
  363. }
  364. }
  365. }
  366. const decoders = {
  367. utf8: (data, hint) => {
  368. if (data.length === 0)
  369. return '';
  370. if (typeof data === 'string') {
  371. // If `data` never had any percent-encoded bytes or never had any that
  372. // were outside of the ASCII range, then we can safely just return the
  373. // input since UTF-8 is ASCII compatible
  374. if (hint < 2)
  375. return data;
  376. data = Buffer.from(data, 'latin1');
  377. }
  378. return data.utf8Slice(0, data.length);
  379. },
  380. latin1: (data, hint) => {
  381. if (data.length === 0)
  382. return '';
  383. if (typeof data === 'string')
  384. return data;
  385. return data.latin1Slice(0, data.length);
  386. },
  387. utf16le: (data, hint) => {
  388. if (data.length === 0)
  389. return '';
  390. if (typeof data === 'string')
  391. data = Buffer.from(data, 'latin1');
  392. return data.ucs2Slice(0, data.length);
  393. },
  394. base64: (data, hint) => {
  395. if (data.length === 0)
  396. return '';
  397. if (typeof data === 'string')
  398. data = Buffer.from(data, 'latin1');
  399. return data.base64Slice(0, data.length);
  400. },
  401. other: (data, hint) => {
  402. if (data.length === 0)
  403. return '';
  404. if (typeof data === 'string')
  405. data = Buffer.from(data, 'latin1');
  406. try {
  407. const decoder = new TextDecoder(this);
  408. return decoder.decode(data);
  409. } catch {}
  410. },
  411. };
  412. function convertToUTF8(data, charset, hint) {
  413. const decode = getDecoder(charset);
  414. if (decode)
  415. return decode(data, hint);
  416. }
  417. function basename(path) {
  418. if (typeof path !== 'string')
  419. return '';
  420. for (let i = path.length - 1; i >= 0; --i) {
  421. switch (path.charCodeAt(i)) {
  422. case 0x2F: // '/'
  423. case 0x5C: // '\'
  424. path = path.slice(i + 1);
  425. return (path === '..' || path === '.' ? '' : path);
  426. }
  427. }
  428. return (path === '..' || path === '.' ? '' : path);
  429. }
  430. const TOKEN = [
  431. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  432. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  433. 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0,
  434. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
  435. 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  436. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
  437. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  438. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
  439. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  440. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  441. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  442. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  443. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  444. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  445. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  446. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  447. ];
  448. const QDTEXT = [
  449. 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
  450. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  451. 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  452. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  453. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  454. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
  455. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  456. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
  457. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  458. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  459. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  460. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  461. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  462. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  463. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  464. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  465. ];
  466. const CHARSET = [
  467. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  468. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  469. 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0,
  470. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
  471. 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  472. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
  473. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  474. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0,
  475. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  476. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  477. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  478. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  479. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  480. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  481. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  482. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  483. ];
  484. const EXTENDED_VALUE = [
  485. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  486. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  487. 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0,
  488. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
  489. 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  490. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
  491. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  492. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
  493. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  494. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  495. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  496. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  497. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  498. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  499. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  500. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  501. ];
  502. /* eslint-disable no-multi-spaces */
  503. const HEX_VALUES = [
  504. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  505. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  506. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  507. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
  508. -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  509. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  510. -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  511. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  512. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  513. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  514. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  515. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  516. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  517. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  518. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  519. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  520. ];
  521. /* eslint-enable no-multi-spaces */
  522. module.exports = {
  523. basename,
  524. convertToUTF8,
  525. getDecoder,
  526. parseContentType,
  527. parseDisposition,
  528. };