base64.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 <bdlib/src/String.h>
  27. static char *b64enc_bd(const unsigned char *data, size_t *len);
  28. static char *b64dec_bd(const unsigned char *data, size_t *len);
  29. static void b64enc_buf(const unsigned char *data, size_t len, char *dest);
  30. static void b64dec_buf(const unsigned char *data, size_t *len, char *dest);
  31. static void b64dec_bd_buf(const unsigned char *data, size_t *len, char *dest);
  32. static const char base64[65] = ".\\0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  33. static const char base64r[256] = {
  34. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  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. 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, 0,
  38. 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
  39. 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 0, 1, 0, 0, 0,
  40. 0, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
  41. 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, 0, 0, 0,
  42. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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. };
  51. static const char base64to[256] =
  52. {
  53. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  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, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
  56. 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  57. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 62, 0, 63, 0, 0, 0, 26, 27, 28,
  58. 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  59. 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  60. 0, 0, 0, 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
  66. };
  67. int base64_to_int(const char *buf)
  68. {
  69. int i = 0;
  70. while (*buf) {
  71. i = i << 6;
  72. i += base64to[(int) *buf];
  73. buf++;
  74. }
  75. return i;
  76. }
  77. static const char tobase64array[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789[]";
  78. char *int_to_base64(unsigned int val)
  79. {
  80. static char buf_base64[12] = "";
  81. buf_base64[11] = 0;
  82. if (!val) {
  83. buf_base64[10] = 'A';
  84. return buf_base64 + 10;
  85. }
  86. int i = 11;
  87. while (val) {
  88. i--;
  89. buf_base64[i] = tobase64array[val & 0x3f];
  90. val = val >> 6;
  91. }
  92. return buf_base64 + i;
  93. }
  94. /* These are all broken */
  95. #define NUM_ASCII_BYTES 3
  96. #define NUM_ENCODED_BYTES 4
  97. char *
  98. b64enc(const unsigned char *data, size_t len)
  99. {
  100. char *dest = (char *) calloc(1, (len << 2) / 3 + 4 + 1);
  101. b64enc_buf(data, len, dest);
  102. return (dest);
  103. }
  104. /**
  105. * @brief Base64 encode a string
  106. * @param string The string to encode
  107. * @return A new, encoded string
  108. */
  109. bd::String broken_base64Encode(const bd::String& string) {
  110. size_t len = string.length();
  111. char *p = b64enc_bd((unsigned char*) string.cbegin(), &len);
  112. bd::String encoded(p, len);
  113. free(p);
  114. return encoded;
  115. }
  116. /**
  117. * @brief Base64 decode a string
  118. * @param string The string to decode
  119. * @return A new, decoded string
  120. */
  121. bd::String broken_base64Decode(const bd::String& string) {
  122. size_t len = string.length();
  123. char *p = b64dec_bd((unsigned char*) string.cbegin(), &len);
  124. bd::String decoded(p, len);
  125. free(p);
  126. return decoded;
  127. }
  128. /* Encode 3 8-bit bytes to 4 6-bit characters */
  129. static void
  130. b64enc_buf(const unsigned char *data, size_t len, char *dest)
  131. {
  132. #define DB(x) ((unsigned char) ((x + i) < len ? data[x + i] : 0))
  133. size_t t, i;
  134. /* 4-byte blocks */
  135. for (i = 0, t = 0; i < len; i += NUM_ASCII_BYTES, t += NUM_ENCODED_BYTES) {
  136. dest[t] = base64[DB(0) >> 2];
  137. dest[t + 1] = base64[((DB(0) & 3) << 4) | (DB(1) >> 4)];
  138. dest[t + 2] = base64[((DB(1) & 0x0F) << 2) | (DB(2) >> 6)];
  139. dest[t + 3] = base64[(DB(2) & 0x3F)];
  140. }
  141. #undef DB
  142. dest[t] = 0;
  143. }
  144. char *
  145. b64dec(const unsigned char *data, size_t *len)
  146. {
  147. char *dest = (char *) calloc(1, ((*len * 3) >> 2) + 6 + 1);
  148. b64dec_buf(data, len, dest);
  149. return (dest);
  150. }
  151. static void
  152. b64dec_buf(const unsigned char *data, size_t *len, char *dest)
  153. {
  154. #define DB(x) ((unsigned char) (x + i < *len ? base64r[(unsigned char) data[x + i]] : 0))
  155. size_t t, i;
  156. for (i = 0, t = 0; i < *len; i += 4, t += 3) {
  157. dest[t] = (DB(0) << 2) + (DB(1) >> 4);
  158. dest[t + 1] = ((DB(1) & 0x0F) << 4) + (DB(2) >> 2);
  159. dest[t + 2] = ((DB(2) & 3) << 6) + DB(3);
  160. };
  161. #undef DB
  162. t += 3;
  163. t -= (t % 4);
  164. dest[t] = 0;
  165. *len = t;
  166. }
  167. /* These are adapated for use with bd::String */
  168. static char *
  169. b64enc_bd(const unsigned char *data, size_t *len)
  170. {
  171. size_t dlen = (((*len + (NUM_ASCII_BYTES - 1)) / NUM_ASCII_BYTES) * NUM_ENCODED_BYTES);
  172. char *dest = (char *) calloc(1, dlen + 1);
  173. b64enc_buf(data, *len, dest);
  174. *len = dlen;
  175. return (dest);
  176. }
  177. /* Decode 4 6-bit characters to 3 8-bit bytes */
  178. static void
  179. b64dec_bd_buf(const unsigned char *data, size_t *len, char *dest)
  180. {
  181. #define DB(x) ((unsigned char) (x + i < *len ? base64r[(unsigned char) data[x + i]] : 0))
  182. size_t t, i;
  183. int pads = 0;
  184. for (i = 0, t = 0; i < *len; i += NUM_ENCODED_BYTES, t += NUM_ASCII_BYTES) {
  185. dest[t] = (DB(0) << 2) + (DB(1) >> 4);
  186. dest[t + 1] = ((DB(1) & 0x0F) << 4) + (DB(2) >> 2);
  187. dest[t + 2] = ((DB(2) & 3) << 6) + DB(3);
  188. /* Check for nulls (padding) - the >= check is because binary data might contain VALID NULLS */
  189. if ((i + NUM_ENCODED_BYTES) >= *len) {
  190. if (dest[t] == 0) ++pads;
  191. if (dest[t+1] == 0) ++pads;
  192. if (dest[t+2] == 0) ++pads;
  193. }
  194. };
  195. #undef DB
  196. *len = t - pads;
  197. dest[*len] = 0;
  198. }
  199. static char *
  200. b64dec_bd(const unsigned char *data, size_t *len)
  201. {
  202. char *dest = (char *) calloc(1, ((*len * 3) >> 2) + 6 + 1);
  203. b64dec_bd_buf(data, len, dest);
  204. return dest;
  205. }
  206. /* vim: set sts=2 sw=2 ts=8 et: */