base64.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*! https://mths.be/base64 v1.0.0 by @mathias | MIT license */
  2. ;(function(root) {
  3. // Detect free variables `exports`.
  4. var freeExports = typeof exports == 'object' && exports;
  5. // Detect free variable `module`.
  6. var freeModule = typeof module == 'object' && module &&
  7. module.exports == freeExports && module;
  8. /*--------------------------------------------------------------------------*/
  9. var InvalidCharacterError = function(message) {
  10. this.message = message;
  11. };
  12. InvalidCharacterError.prototype = new Error;
  13. InvalidCharacterError.prototype.name = 'InvalidCharacterError';
  14. var error = function(message) {
  15. // Note: the error messages used throughout this file match those used by
  16. // the native `atob`/`btoa` implementation in Chromium.
  17. throw new InvalidCharacterError(message);
  18. };
  19. var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  20. // http://whatwg.org/html/common-microsyntaxes.html#space-character
  21. var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g;
  22. // `decode` is designed to be fully compatible with `atob` as described in the
  23. // HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob
  24. // The optimized base64-decoding algorithm used is based on @atk’s excellent
  25. // implementation. https://gist.github.com/atk/1020396
  26. var decode = function(input) {
  27. input = String(input)
  28. .replace(REGEX_SPACE_CHARACTERS, '');
  29. var length = input.length;
  30. if (length % 4 == 0) {
  31. input = input.replace(/==?$/, '');
  32. length = input.length;
  33. }
  34. if (
  35. length % 4 == 1 ||
  36. // http://whatwg.org/C#alphanumeric-ascii-characters
  37. /[^+a-zA-Z0-9/]/.test(input)
  38. ) {
  39. error(
  40. 'Invalid character: the string to be decoded is not correctly encoded.'
  41. );
  42. }
  43. var bitCounter = 0;
  44. var bitStorage;
  45. var buffer;
  46. var output = '';
  47. var position = -1;
  48. while (++position < length) {
  49. buffer = TABLE.indexOf(input.charAt(position));
  50. bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer;
  51. // Unless this is the first of a group of 4 characters…
  52. if (bitCounter++ % 4) {
  53. // …convert the first 8 bits to a single ASCII character.
  54. output += String.fromCharCode(
  55. 0xFF & bitStorage >> (-2 * bitCounter & 6)
  56. );
  57. }
  58. }
  59. return output;
  60. };
  61. // `encode` is designed to be fully compatible with `btoa` as described in the
  62. // HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa
  63. var encode = function(input) {
  64. input = String(input);
  65. if (/[^\0-\xFF]/.test(input)) {
  66. // Note: no need to special-case astral symbols here, as surrogates are
  67. // matched, and the input is supposed to only contain ASCII anyway.
  68. error(
  69. 'The string to be encoded contains characters outside of the ' +
  70. 'Latin1 range.'
  71. );
  72. }
  73. var padding = input.length % 3;
  74. var output = '';
  75. var position = -1;
  76. var a;
  77. var b;
  78. var c;
  79. var buffer;
  80. // Make sure any padding is handled outside of the loop.
  81. var length = input.length - padding;
  82. while (++position < length) {
  83. // Read three bytes, i.e. 24 bits.
  84. a = input.charCodeAt(position) << 16;
  85. b = input.charCodeAt(++position) << 8;
  86. c = input.charCodeAt(++position);
  87. buffer = a + b + c;
  88. // Turn the 24 bits into four chunks of 6 bits each, and append the
  89. // matching character for each of them to the output.
  90. output += (
  91. TABLE.charAt(buffer >> 18 & 0x3F) +
  92. TABLE.charAt(buffer >> 12 & 0x3F) +
  93. TABLE.charAt(buffer >> 6 & 0x3F) +
  94. TABLE.charAt(buffer & 0x3F)
  95. );
  96. }
  97. if (padding == 2) {
  98. a = input.charCodeAt(position) << 8;
  99. b = input.charCodeAt(++position);
  100. buffer = a + b;
  101. output += (
  102. TABLE.charAt(buffer >> 10) +
  103. TABLE.charAt((buffer >> 4) & 0x3F) +
  104. TABLE.charAt((buffer << 2) & 0x3F) +
  105. '='
  106. );
  107. } else if (padding == 1) {
  108. buffer = input.charCodeAt(position);
  109. output += (
  110. TABLE.charAt(buffer >> 2) +
  111. TABLE.charAt((buffer << 4) & 0x3F) +
  112. '=='
  113. );
  114. }
  115. return output;
  116. };
  117. var base64 = {
  118. 'encode': encode,
  119. 'decode': decode,
  120. 'version': '1.0.0'
  121. };
  122. // Some AMD build optimizers, like r.js, check for specific condition patterns
  123. // like the following:
  124. if (
  125. typeof define == 'function' &&
  126. typeof define.amd == 'object' &&
  127. define.amd
  128. ) {
  129. define(function() {
  130. return base64;
  131. });
  132. } else if (freeExports && !freeExports.nodeType) {
  133. if (freeModule) { // in Node.js or RingoJS v0.8.0+
  134. freeModule.exports = base64;
  135. } else { // in Narwhal or RingoJS v0.7.0-
  136. for (var key in base64) {
  137. base64.hasOwnProperty(key) && (freeExports[key] = base64[key]);
  138. }
  139. }
  140. } else { // in Rhino or a web browser
  141. root.base64 = base64;
  142. }
  143. }(this));