Node-Red configuration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

uint8-from-base64.js 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. 'use strict';
  2. var globalThis = require('../internals/global-this');
  3. var uncurryThis = require('../internals/function-uncurry-this');
  4. var anObjectOrUndefined = require('../internals/an-object-or-undefined');
  5. var aString = require('../internals/a-string');
  6. var hasOwn = require('../internals/has-own-property');
  7. var base64Map = require('../internals/base64-map');
  8. var getAlphabetOption = require('../internals/get-alphabet-option');
  9. var notDetached = require('../internals/array-buffer-not-detached');
  10. var base64Alphabet = base64Map.c2i;
  11. var base64UrlAlphabet = base64Map.c2iUrl;
  12. var SyntaxError = globalThis.SyntaxError;
  13. var TypeError = globalThis.TypeError;
  14. var at = uncurryThis(''.charAt);
  15. var skipAsciiWhitespace = function (string, index) {
  16. var length = string.length;
  17. for (;index < length; index++) {
  18. var chr = at(string, index);
  19. if (chr !== ' ' && chr !== '\t' && chr !== '\n' && chr !== '\f' && chr !== '\r') break;
  20. } return index;
  21. };
  22. var decodeBase64Chunk = function (chunk, alphabet, throwOnExtraBits) {
  23. var chunkLength = chunk.length;
  24. if (chunkLength < 4) {
  25. chunk += chunkLength === 2 ? 'AA' : 'A';
  26. }
  27. var triplet = (alphabet[at(chunk, 0)] << 18)
  28. + (alphabet[at(chunk, 1)] << 12)
  29. + (alphabet[at(chunk, 2)] << 6)
  30. + alphabet[at(chunk, 3)];
  31. var chunkBytes = [
  32. (triplet >> 16) & 255,
  33. (triplet >> 8) & 255,
  34. triplet & 255
  35. ];
  36. if (chunkLength === 2) {
  37. if (throwOnExtraBits && chunkBytes[1] !== 0) {
  38. throw new SyntaxError('Extra bits');
  39. }
  40. return [chunkBytes[0]];
  41. }
  42. if (chunkLength === 3) {
  43. if (throwOnExtraBits && chunkBytes[2] !== 0) {
  44. throw new SyntaxError('Extra bits');
  45. }
  46. return [chunkBytes[0], chunkBytes[1]];
  47. }
  48. return chunkBytes;
  49. };
  50. var writeBytes = function (bytes, elements, written) {
  51. var elementsLength = elements.length;
  52. for (var index = 0; index < elementsLength; index++) {
  53. bytes[written + index] = elements[index];
  54. }
  55. return written + elementsLength;
  56. };
  57. /* eslint-disable max-statements, max-depth -- TODO */
  58. module.exports = function (string, options, into, maxLength) {
  59. aString(string);
  60. anObjectOrUndefined(options);
  61. var alphabet = getAlphabetOption(options) === 'base64' ? base64Alphabet : base64UrlAlphabet;
  62. var lastChunkHandling = options ? options.lastChunkHandling : undefined;
  63. if (lastChunkHandling === undefined) lastChunkHandling = 'loose';
  64. if (lastChunkHandling !== 'loose' && lastChunkHandling !== 'strict' && lastChunkHandling !== 'stop-before-partial') {
  65. throw new TypeError('Incorrect `lastChunkHandling` option');
  66. }
  67. if (into) notDetached(into.buffer);
  68. var bytes = into || [];
  69. var written = 0;
  70. var read = 0;
  71. var chunk = '';
  72. var index = 0;
  73. if (maxLength) while (true) {
  74. index = skipAsciiWhitespace(string, index);
  75. if (index === string.length) {
  76. if (chunk.length > 0) {
  77. if (lastChunkHandling === 'stop-before-partial') {
  78. break;
  79. }
  80. if (lastChunkHandling === 'loose') {
  81. if (chunk.length === 1) {
  82. throw new SyntaxError('Malformed padding: exactly one additional character');
  83. }
  84. written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, false), written);
  85. } else {
  86. throw new SyntaxError('Missing padding');
  87. }
  88. }
  89. read = string.length;
  90. break;
  91. }
  92. var chr = at(string, index);
  93. ++index;
  94. if (chr === '=') {
  95. if (chunk.length < 2) {
  96. throw new SyntaxError('Padding is too early');
  97. }
  98. index = skipAsciiWhitespace(string, index);
  99. if (chunk.length === 2) {
  100. if (index === string.length) {
  101. if (lastChunkHandling === 'stop-before-partial') {
  102. break;
  103. }
  104. throw new SyntaxError('Malformed padding: only one =');
  105. }
  106. if (at(string, index) === '=') {
  107. ++index;
  108. index = skipAsciiWhitespace(string, index);
  109. }
  110. }
  111. if (index < string.length) {
  112. throw new SyntaxError('Unexpected character after padding');
  113. }
  114. written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, lastChunkHandling === 'strict'), written);
  115. read = string.length;
  116. break;
  117. }
  118. if (!hasOwn(alphabet, chr)) {
  119. throw new SyntaxError('Unexpected character');
  120. }
  121. var remainingBytes = maxLength - written;
  122. if (remainingBytes === 1 && chunk.length === 2 || remainingBytes === 2 && chunk.length === 3) {
  123. // special case: we can fit exactly the number of bytes currently represented by chunk, so we were just checking for `=`
  124. break;
  125. }
  126. chunk += chr;
  127. if (chunk.length === 4) {
  128. written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, false), written);
  129. chunk = '';
  130. read = index;
  131. if (written === maxLength) {
  132. break;
  133. }
  134. }
  135. }
  136. return { bytes: bytes, read: read, written: written };
  137. };