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