base64.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2014 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /* base64.c: base64 encoding/decoding
  21. *
  22. */
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include "base64.h"
  26. #include "src/compat/compat.h"
  27. #include <bdlib/src/String.h>
  28. static char *b64enc_bd(const unsigned char *data, size_t *len);
  29. static char *b64dec_bd(const unsigned char *data, size_t *len);
  30. static void b64enc_buf(const unsigned char *data, size_t len, char *dest);
  31. static void b64dec_buf(const unsigned char *data, size_t *len, char *dest);
  32. static void b64dec_bd_buf(const unsigned char *data, size_t *len, char *dest);
  33. static const char base64[65] = ".\\0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  34. static const char base64r[256] = {
  35. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  36. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  37. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  38. 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, 0,
  39. 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
  40. 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 0, 1, 0, 0, 0,
  41. 0, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
  42. 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, 0,
  43. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  44. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  45. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  46. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  47. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  48. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  49. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  50. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  51. };
  52. static char base64to[256] =
  53. {
  54. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  55. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  56. 0, 0, 0, 0, 0, 0, 0, 0, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
  57. 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  58. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62, 0, 63, 0, 0, 0, 26, 27, 28,
  59. 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  60. 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  61. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  62. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  63. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  64. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  65. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  66. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  67. };
  68. int base64_to_int(const char *buf)
  69. {
  70. int i = 0;
  71. while (*buf) {
  72. i = i << 6;
  73. i += base64to[(int) *buf];
  74. buf++;
  75. }
  76. return i;
  77. }
  78. static const char tobase64array[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]";
  79. char *int_to_base64(unsigned int val)
  80. {
  81. static char buf_base64[12] = "";
  82. buf_base64[11] = 0;
  83. if (!val) {
  84. buf_base64[10] = 'A';
  85. return buf_base64 + 10;
  86. }
  87. int i = 11;
  88. while (val) {
  89. i--;
  90. buf_base64[i] = tobase64array[val & 0x3f];
  91. val = val >> 6;
  92. }
  93. return buf_base64 + i;
  94. }
  95. /* These are all broken */
  96. #define NUM_ASCII_BYTES 3
  97. #define NUM_ENCODED_BYTES 4
  98. char *
  99. b64enc(const unsigned char *data, size_t len)
  100. {
  101. char *dest = (char *) my_calloc(1, (len << 2) / 3 + 4 + 1);
  102. b64enc_buf(data, len, dest);
  103. return (dest);
  104. }
  105. /**
  106. * @brief Base64 encode a string
  107. * @param string The string to encode
  108. * @return A new, encoded string
  109. */
  110. bd::String broken_base64Encode(const bd::String& string) {
  111. size_t len = string.length();
  112. char *p = b64enc_bd((unsigned char*) string.data(), &len);
  113. bd::String encoded(p, len);
  114. free(p);
  115. return encoded;
  116. }
  117. /**
  118. * @brief Base64 decode a string
  119. * @param string The string to decode
  120. * @return A new, decoded string
  121. */
  122. bd::String broken_base64Decode(const bd::String& string) {
  123. size_t len = string.length();
  124. char *p = b64dec_bd((unsigned char*) string.data(), &len);
  125. bd::String decoded(p, len);
  126. free(p);
  127. return decoded;
  128. }
  129. /* Encode 3 8-bit bytes to 4 6-bit characters */
  130. static void
  131. b64enc_buf(const unsigned char *data, size_t len, char *dest)
  132. {
  133. #define DB(x) ((unsigned char) ((x + i) < len ? data[x + i] : 0))
  134. size_t t, i;
  135. /* 4-byte blocks */
  136. for (i = 0, t = 0; i < len; i += NUM_ASCII_BYTES, t += NUM_ENCODED_BYTES) {
  137. dest[t] = base64[DB(0) >> 2];
  138. dest[t + 1] = base64[((DB(0) & 3) << 4) | (DB(1) >> 4)];
  139. dest[t + 2] = base64[((DB(1) & 0x0F) << 2) | (DB(2) >> 6)];
  140. dest[t + 3] = base64[(DB(2) & 0x3F)];
  141. }
  142. #undef DB
  143. dest[t] = 0;
  144. }
  145. char *
  146. b64dec(const unsigned char *data, size_t *len)
  147. {
  148. char *dest = (char *) my_calloc(1, ((*len * 3) >> 2) + 6 + 1);
  149. b64dec_buf(data, len, dest);
  150. return (dest);
  151. }
  152. static void
  153. b64dec_buf(const unsigned char *data, size_t *len, char *dest)
  154. {
  155. #define DB(x) ((unsigned char) (x + i < *len ? base64r[(unsigned char) data[x + i]] : 0))
  156. size_t t, i;
  157. for (i = 0, t = 0; i < *len; i += 4, t += 3) {
  158. dest[t] = (DB(0) << 2) + (DB(1) >> 4);
  159. dest[t + 1] = ((DB(1) & 0x0F) << 4) + (DB(2) >> 2);
  160. dest[t + 2] = ((DB(2) & 3) << 6) + DB(3);
  161. };
  162. #undef DB
  163. t += 3;
  164. t -= (t % 4);
  165. dest[t] = 0;
  166. *len = t;
  167. }
  168. /* These are adapated for use with bd::String */
  169. static char *
  170. b64enc_bd(const unsigned char *data, size_t *len)
  171. {
  172. size_t dlen = (((*len + (NUM_ASCII_BYTES - 1)) / NUM_ASCII_BYTES) * NUM_ENCODED_BYTES);
  173. char *dest = (char *) my_calloc(1, dlen + 1);
  174. b64enc_buf(data, *len, dest);
  175. *len = dlen;
  176. return (dest);
  177. }
  178. /* Decode 4 6-bit characters to 3 8-bit bytes */
  179. static void
  180. b64dec_bd_buf(const unsigned char *data, size_t *len, char *dest)
  181. {
  182. #define DB(x) ((unsigned char) (x + i < *len ? base64r[(unsigned char) data[x + i]] : 0))
  183. size_t t, i;
  184. int pads = 0;
  185. for (i = 0, t = 0; i < *len; i += NUM_ENCODED_BYTES, t += NUM_ASCII_BYTES) {
  186. dest[t] = (DB(0) << 2) + (DB(1) >> 4);
  187. dest[t + 1] = ((DB(1) & 0x0F) << 4) + (DB(2) >> 2);
  188. dest[t + 2] = ((DB(2) & 3) << 6) + DB(3);
  189. /* Check for nulls (padding) - the >= check is because binary data might contain VALID NULLS */
  190. if ((i + NUM_ENCODED_BYTES) >= *len) {
  191. if (dest[t] == 0) ++pads;
  192. if (dest[t+1] == 0) ++pads;
  193. if (dest[t+2] == 0) ++pads;
  194. }
  195. };
  196. #undef DB
  197. *len = t - pads;
  198. dest[*len] = 0;
  199. }
  200. static char *
  201. b64dec_bd(const unsigned char *data, size_t *len)
  202. {
  203. char *dest = (char *) my_calloc(1, ((*len * 3) >> 2) + 6 + 1);
  204. b64dec_bd_buf(data, len, dest);
  205. return dest;
  206. }
  207. /* vim: set sts=2 sw=2 ts=8 et: */