base64.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. https://github.com/superwills/NibbleAndAHalf
  3. base64.h -- Fast base64 encoding and decoding.
  4. version 1.0.0, April 17, 2013 143a
  5. Copyright (C) 2013 William Sherif
  6. This software is provided 'as-is', without any express or implied
  7. warranty. In no event will the authors be held liable for any damages
  8. arising from the use of this software.
  9. Permission is granted to anyone to use this software for any purpose,
  10. including commercial applications, and to alter it and redistribute it
  11. freely, subject to the following restrictions:
  12. 1. The origin of this software must not be misrepresented; you must not
  13. claim that you wrote the original software. If you use this software
  14. in a product, an acknowledgment in the product documentation would be
  15. appreciated but is not required.
  16. 2. Altered source versions must be plainly marked as such, and must not be
  17. misrepresented as being the original software.
  18. 3. This notice may not be removed or altered from any source distribution.
  19. William Sherif
  20. will.sherif@gmail.com
  21. YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz
  22. */
  23. #include "base64.h"
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. static const char* b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
  27. // maps A=>0,B=>1..
  28. static const unsigned char unb64[]={
  29. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10
  30. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20
  31. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30
  32. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40
  33. 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50
  34. 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60
  35. 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70
  36. 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80
  37. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90
  38. 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100
  39. 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110
  40. 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120
  41. 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130
  42. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140
  43. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150
  44. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160
  45. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170
  46. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180
  47. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190
  48. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200
  49. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210
  50. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220
  51. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230
  52. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240
  53. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250
  54. 0, 0, 0, 0, 0, 0,
  55. }; // This array has 256 elements
  56. // Converts binary data of length=len to base64 characters.
  57. // Length of the resultant string is stored in flen
  58. // (you must pass pointer flen).
  59. char* UA_base64( const void* binaryData, int len, int *flen )
  60. {
  61. const unsigned char* bin = (const unsigned char*) binaryData ;
  62. char* res ;
  63. int rc = 0 ; // result counter
  64. int byteNo ; // I need this after the loop
  65. int modulusLen = len % 3 ;
  66. int pad = ((modulusLen&1)<<1) + ((modulusLen&2)>>1) ; // 2 gives 1 and 1 gives 2, but 0 gives 0.
  67. *flen = 4*(len + pad)/3 ;
  68. res = (char*) malloc( (size_t)(*flen + 1) ) ; // and one for the null
  69. if( !res )
  70. {
  71. puts( "ERROR: base64 could not allocate enough memory." ) ;
  72. puts( "I must stop because I could not get enough" ) ;
  73. return 0;
  74. }
  75. for( byteNo = 0 ; byteNo <= len-3 ; byteNo+=3 )
  76. {
  77. unsigned char BYTE0=bin[byteNo];
  78. unsigned char BYTE1=bin[byteNo+1];
  79. unsigned char BYTE2=bin[byteNo+2];
  80. res[rc++] = b64[ BYTE0 >> 2 ] ;
  81. res[rc++] = b64[ ((0x3&BYTE0)<<4) + (BYTE1 >> 4) ] ;
  82. res[rc++] = b64[ ((0x0f&BYTE1)<<2) + (BYTE2>>6) ] ;
  83. res[rc++] = b64[ 0x3f&BYTE2 ] ;
  84. }
  85. if( pad==2 )
  86. {
  87. res[rc++] = b64[ bin[byteNo] >> 2 ] ;
  88. res[rc++] = b64[ (0x3&bin[byteNo])<<4 ] ;
  89. res[rc++] = '=';
  90. res[rc++] = '=';
  91. }
  92. else if( pad==1 )
  93. {
  94. res[rc++] = b64[ bin[byteNo] >> 2 ] ;
  95. res[rc++] = b64[ ((0x3&bin[byteNo])<<4) + (bin[byteNo+1] >> 4) ] ;
  96. res[rc++] = b64[ (0x0f&bin[byteNo+1])<<2 ] ;
  97. res[rc++] = '=';
  98. }
  99. res[rc]=0; // NULL TERMINATOR! ;)
  100. return res ;
  101. }
  102. unsigned char* UA_unbase64( const char* ascii, int len, int *flen )
  103. {
  104. const unsigned char *safeAsciiPtr = (const unsigned char*)ascii ;
  105. unsigned char *bin ;
  106. int cb=0;
  107. int charNo;
  108. int pad = 0 ;
  109. if( len < 2 ) { // 2 accesses below would be OOB.
  110. // catch empty string, return NULL as result.
  111. puts( "ERROR: You passed an invalid base64 string (too short). You get NULL back." ) ;
  112. *flen=0;
  113. return 0 ;
  114. }
  115. if( safeAsciiPtr[ len-1 ]=='=' ) ++pad ;
  116. if( safeAsciiPtr[ len-2 ]=='=' ) ++pad ;
  117. *flen = 3*len/4 - pad ;
  118. bin = (unsigned char*)malloc( (size_t) (*flen) ) ;
  119. if( !bin )
  120. {
  121. puts( "ERROR: unbase64 could not allocate enough memory." ) ;
  122. puts( "I must stop because I could not get enough" ) ;
  123. return 0;
  124. }
  125. for( charNo=0; charNo <= len - 4 - pad ; charNo+=4 )
  126. {
  127. int A=unb64[safeAsciiPtr[charNo]];
  128. int B=unb64[safeAsciiPtr[charNo+1]];
  129. int C=unb64[safeAsciiPtr[charNo+2]];
  130. int D=unb64[safeAsciiPtr[charNo+3]];
  131. bin[cb++] = (unsigned char)((A<<2) | (B>>4)) ;
  132. bin[cb++] = (unsigned char)((B<<4) | (C>>2)) ;
  133. bin[cb++] = (unsigned char)((C<<6) | (D)) ;
  134. }
  135. if( pad==1 )
  136. {
  137. int A=unb64[safeAsciiPtr[charNo]];
  138. int B=unb64[safeAsciiPtr[charNo+1]];
  139. int C=unb64[safeAsciiPtr[charNo+2]];
  140. bin[cb++] = (unsigned char)((A<<2) | (B>>4)) ;
  141. bin[cb++] = (unsigned char)((B<<4) | (C>>2)) ;
  142. }
  143. else if( pad==2 )
  144. {
  145. int A=unb64[safeAsciiPtr[charNo]];
  146. int B=unb64[safeAsciiPtr[charNo+1]];
  147. bin[cb++] = (unsigned char)((A<<2) | (B>>4)) ;
  148. }
  149. return bin ;
  150. }