base64-decode.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * This code originally came from here
  3. *
  4. * http://base64.sourceforge.net/b64.c
  5. *
  6. * with the following license:
  7. *
  8. * LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
  9. *
  10. * Permission is hereby granted, free of charge, to any person
  11. * obtaining a copy of this software and associated
  12. * documentation files (the "Software"), to deal in the
  13. * Software without restriction, including without limitation
  14. * the rights to use, copy, modify, merge, publish, distribute,
  15. * sublicense, and/or sell copies of the Software, and to
  16. * permit persons to whom the Software is furnished to do so,
  17. * subject to the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall
  20. * be included in all copies or substantial portions of the
  21. * Software.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  24. * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  25. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  26. * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  27. * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  28. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  29. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  30. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. *
  32. * VERSION HISTORY:
  33. * Bob Trower 08/04/01 -- Create Version 0.00.00B
  34. *
  35. * I cleaned it up quite a bit to match the (linux kernel) style of the rest
  36. * of libwebsockets; this version is under LGPL2.1 + SLE like the rest of lws
  37. * since he explicitly allows sublicensing, but I give the URL above so you can
  38. * get the original with Bob's super-liberal terms directly if you prefer.
  39. */
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include "private-libwebsockets.h"
  43. static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  44. "abcdefghijklmnopqrstuvwxyz0123456789+/";
  45. static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
  46. "$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
  47. LWS_VISIBLE int
  48. lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
  49. {
  50. unsigned char triple[3];
  51. int i;
  52. int len;
  53. int line = 0;
  54. int done = 0;
  55. while (in_len) {
  56. len = 0;
  57. for (i = 0; i < 3; i++) {
  58. if (in_len) {
  59. triple[i] = *in++;
  60. len++;
  61. in_len--;
  62. } else
  63. triple[i] = 0;
  64. }
  65. if (done + 4 >= out_size)
  66. return -1;
  67. *out++ = encode[triple[0] >> 2];
  68. *out++ = encode[((triple[0] & 0x03) << 4) |
  69. ((triple[1] & 0xf0) >> 4)];
  70. *out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
  71. ((triple[2] & 0xc0) >> 6)] : '=');
  72. *out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
  73. done += 4;
  74. line += 4;
  75. }
  76. if (done + 1 >= out_size)
  77. return -1;
  78. *out++ = '\0';
  79. return done;
  80. }
  81. /*
  82. * returns length of decoded string in out, or -1 if out was too small
  83. * according to out_size
  84. */
  85. LWS_VISIBLE int
  86. lws_b64_decode_string(const char *in, char *out, int out_size)
  87. {
  88. int len, i, c = 0, done = 0;
  89. unsigned char v, quad[4];
  90. while (*in) {
  91. len = 0;
  92. for (i = 0; i < 4 && *in; i++) {
  93. v = 0;
  94. c = 0;
  95. while (*in && !v) {
  96. c = v = *in++;
  97. v = (v < 43 || v > 122) ? 0 : decode[v - 43];
  98. if (v)
  99. v = (v == '$') ? 0 : v - 61;
  100. }
  101. if (c) {
  102. len++;
  103. if (v)
  104. quad[i] = v - 1;
  105. } else
  106. quad[i] = 0;
  107. }
  108. if (out_size < (done + len - 1))
  109. /* out buffer is too small */
  110. return -1;
  111. /*
  112. * "The '==' sequence indicates that the last group contained
  113. * only one byte, and '=' indicates that it contained two
  114. * bytes." (wikipedia)
  115. */
  116. if (!*in && c == '=')
  117. len--;
  118. if (len >= 2)
  119. *out++ = quad[0] << 2 | quad[1] >> 4;
  120. if (len >= 3)
  121. *out++ = quad[1] << 4 | quad[2] >> 2;
  122. if (len >= 4)
  123. *out++ = ((quad[2] << 6) & 0xc0) | quad[3];
  124. done += len - 1;
  125. }
  126. if (done + 1 >= out_size)
  127. return -1;
  128. *out = '\0';
  129. return done;
  130. }
  131. #if 0
  132. int
  133. lws_b64_selftest(void)
  134. {
  135. char buf[64];
  136. unsigned int n, r = 0;
  137. unsigned int test;
  138. /* examples from https://en.wikipedia.org/wiki/Base64 */
  139. static const char * const plaintext[] = {
  140. "any carnal pleasure.",
  141. "any carnal pleasure",
  142. "any carnal pleasur",
  143. "any carnal pleasu",
  144. "any carnal pleas",
  145. "Admin:kloikloi"
  146. };
  147. static const char * const coded[] = {
  148. "YW55IGNhcm5hbCBwbGVhc3VyZS4=",
  149. "YW55IGNhcm5hbCBwbGVhc3VyZQ==",
  150. "YW55IGNhcm5hbCBwbGVhc3Vy",
  151. "YW55IGNhcm5hbCBwbGVhc3U=",
  152. "YW55IGNhcm5hbCBwbGVhcw==",
  153. "QWRtaW46a2xvaWtsb2k="
  154. };
  155. for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) {
  156. buf[sizeof(buf) - 1] = '\0';
  157. n = lws_b64_encode_string(plaintext[test],
  158. strlen(plaintext[test]), buf, sizeof buf);
  159. if (n != strlen(coded[test]) || strcmp(buf, coded[test])) {
  160. lwsl_err("Failed lws_b64 encode selftest "
  161. "%d result '%s' %d\n", test, buf, n);
  162. r = -1;
  163. }
  164. buf[sizeof(buf) - 1] = '\0';
  165. n = lws_b64_decode_string(coded[test], buf, sizeof buf);
  166. if (n != strlen(plaintext[test]) ||
  167. strcmp(buf, plaintext[test])) {
  168. lwsl_err("Failed lws_b64 decode selftest "
  169. "%d result '%s' / '%s', %d / %d\n",
  170. test, buf, plaintext[test], n, strlen(plaintext[test]));
  171. r = -1;
  172. }
  173. }
  174. lwsl_notice("Base 64 selftests passed\n");
  175. return r;
  176. }
  177. #endif