base64.js 4.8 KB

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