From: Holger Schemel Date: Tue, 6 Apr 2021 21:40:45 +0000 (+0200) Subject: cleanup of code for Base64 encoding and decoding X-Git-Tag: 4.3.0.0~191 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=195333e38da4b8195579937eb048cc9e55e9393c;p=rocksndiamonds.git cleanup of code for Base64 encoding and decoding --- diff --git a/src/libgame/base64.c b/src/libgame/base64.c index 46267fd5..485f81bc 100644 --- a/src/libgame/base64.c +++ b/src/libgame/base64.c @@ -40,151 +40,155 @@ */ +// ---------------------------------------------------------------------------- +// Base64 encoder/decoder code was altered for integration in Rocks'n'Diamonds +// ---------------------------------------------------------------------------- + #include #include #include "base64.h" -const static char* b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ; - -// maps A=>0,B=>1.. -const static unsigned char unb64[]={ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40 - 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50 - 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60 - 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70 - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80 - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90 - 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100 - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110 - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120 - 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250 - 0, 0, 0, 0, 0, 0, -}; // This array has 256 elements - -// Converts binary data of length=len to base64 characters. -// Length of the resultant string is stored in flen -// (you must pass pointer flen). -char* base64( const void* binaryData, int len, int *flen ) +const static char *b64encode = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +int base64_encoded_size(int unencoded_size) { - const unsigned char* bin = (const unsigned char*) binaryData ; - char* res ; + int mod = unencoded_size % 3; + int pad = (mod > 0 ? 3 - mod : 0); - int rc = 0 ; // result counter - int byteNo ; // I need this after the loop + return 4 * (unencoded_size + pad) / 3 + 1; +} - int modulusLen = len % 3 ; - int pad = ((modulusLen&1)<<1) + ((modulusLen&2)>>1) ; // 2 gives 1 and 1 gives 2, but 0 gives 0. +void base64_encode(char *encoded_data, + const void *unencoded_ptr, int unencoded_size) +{ + const byte *unencoded_data = (const byte *)unencoded_ptr; + char *ptr = encoded_data; + int i; - *flen = 4*(len + pad)/3 ; - res = (char*) malloc( *flen + 1 ) ; // and one for the null - if( !res ) - { - puts( "ERROR: base64 could not allocate enough memory." ) ; - puts( "I must stop because I could not get enough" ) ; - return 0; - } + int mod = unencoded_size % 3; + int pad = (mod > 0 ? 3 - mod : 0); - for( byteNo = 0 ; byteNo <= len-3 ; byteNo+=3 ) + for (i = 0; i <= unencoded_size - 3; i += 3) { - unsigned char BYTE0=bin[byteNo]; - unsigned char BYTE1=bin[byteNo+1]; - unsigned char BYTE2=bin[byteNo+2]; - res[rc++] = b64[ BYTE0 >> 2 ] ; - res[rc++] = b64[ ((0x3&BYTE0)<<4) + (BYTE1 >> 4) ] ; - res[rc++] = b64[ ((0x0f&BYTE1)<<2) + (BYTE2>>6) ] ; - res[rc++] = b64[ 0x3f&BYTE2 ] ; + byte byte0 = unencoded_data[i]; + byte byte1 = unencoded_data[i + 1]; + byte byte2 = unencoded_data[i + 2]; + + *ptr++ = b64encode[byte0 >> 2]; + *ptr++ = b64encode[((byte0 & 0x03) << 4) + (byte1 >> 4)]; + *ptr++ = b64encode[((byte1 & 0x0f) << 2) + (byte2 >> 6)]; + *ptr++ = b64encode[byte2 & 0x3f]; } - if( pad==2 ) + if (pad == 1) { - res[rc++] = b64[ bin[byteNo] >> 2 ] ; - res[rc++] = b64[ (0x3&bin[byteNo])<<4 ] ; - res[rc++] = '='; - res[rc++] = '='; + byte byte0 = unencoded_data[i]; + byte byte1 = unencoded_data[i + 1]; + + *ptr++ = b64encode[byte0 >> 2]; + *ptr++ = b64encode[((byte0 & 0x03) << 4) + (byte1 >> 4)]; + *ptr++ = b64encode[((byte1 & 0x0f) << 2)]; + *ptr++ = '='; } - else if( pad==1 ) + else if (pad == 2) { - res[rc++] = b64[ bin[byteNo] >> 2 ] ; - res[rc++] = b64[ ((0x3&bin[byteNo])<<4) + (bin[byteNo+1] >> 4) ] ; - res[rc++] = b64[ (0x0f&bin[byteNo+1])<<2 ] ; - res[rc++] = '='; + byte byte0 = unencoded_data[i]; + + *ptr++ = b64encode[byte0 >> 2]; + *ptr++ = b64encode[(byte0 & 0x03) << 4]; + *ptr++ = '='; + *ptr++ = '='; } - res[rc]=0; // NULL TERMINATOR! ;) - return res ; + *ptr++= '\0'; } -unsigned char* unbase64( const char* ascii, int len, int *flen ) +const static byte b64decode[] = { - const unsigned char *safeAsciiPtr = (const unsigned char*)ascii ; - unsigned char *bin ; - int cb=0; - int charNo; - int pad = 0 ; - - if( len < 2 ) { // 2 accesses below would be OOB. - // catch empty string, return NULL as result. - puts( "ERROR: You passed an invalid base64 string (too short). You get NULL back." ) ; - *flen=0; - return 0 ; - } - if( safeAsciiPtr[ len-1 ]=='=' ) ++pad ; - if( safeAsciiPtr[ len-2 ]=='=' ) ++pad ; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, // 32 + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, // 48 + + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64 + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, // 80 + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96 + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, // 112 + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 144 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 176 + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 208 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 224 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240 +}; + +int base64_decoded_size(const char *encoded_data) +{ + int encoded_size = strlen(encoded_data); - *flen = 3*len/4 - pad ; - bin = (unsigned char*)malloc( *flen ) ; - if( !bin ) - { - puts( "ERROR: unbase64 could not allocate enough memory." ) ; - puts( "I must stop because I could not get enough" ) ; + if (encoded_size < 2) return 0; - } - for( charNo=0; charNo <= len - 4 - pad ; charNo+=4 ) + int pad = 0; + + if (encoded_data[encoded_size - 1] == '=') + pad++; + if (encoded_data[encoded_size - 2] == '=') + pad++; + + return 3 * encoded_size / 4 - pad; +} + +void base64_decode(byte *decoded_data, const char *encoded_ptr) +{ + const byte *encoded_data = (const byte *)encoded_ptr; + byte *ptr = decoded_data; + int encoded_size = strlen(encoded_ptr); + int i; + + if (encoded_size < 2) + return; + + int pad = 0; + + if (encoded_data[encoded_size - 1] == '=') + pad++; + if (encoded_data[encoded_size - 2] == '=') + pad++; + + for (i = 0; i <= encoded_size - 4 - pad; i += 4) { - int A=unb64[safeAsciiPtr[charNo]]; - int B=unb64[safeAsciiPtr[charNo+1]]; - int C=unb64[safeAsciiPtr[charNo+2]]; - int D=unb64[safeAsciiPtr[charNo+3]]; - - bin[cb++] = (A<<2) | (B>>4) ; - bin[cb++] = (B<<4) | (C>>2) ; - bin[cb++] = (C<<6) | (D) ; + byte byte0 = b64decode[encoded_data[i]]; + byte byte1 = b64decode[encoded_data[i + 1]]; + byte byte2 = b64decode[encoded_data[i + 2]]; + byte byte3 = b64decode[encoded_data[i + 3]]; + + *ptr++ = (byte0 << 2) | (byte1 >> 4); + *ptr++ = (byte1 << 4) | (byte2 >> 2); + *ptr++ = (byte2 << 6) | (byte3); } - if( pad==1 ) + if (pad == 1) { - int A=unb64[safeAsciiPtr[charNo]]; - int B=unb64[safeAsciiPtr[charNo+1]]; - int C=unb64[safeAsciiPtr[charNo+2]]; + byte byte0 = b64decode[encoded_data[i]]; + byte byte1 = b64decode[encoded_data[i + 1]]; + byte byte2 = b64decode[encoded_data[i + 2]]; - bin[cb++] = (A<<2) | (B>>4) ; - bin[cb++] = (B<<4) | (C>>2) ; + *ptr++ = (byte0 << 2) | (byte1 >> 4); + *ptr++ = (byte1 << 4) | (byte2 >> 2); } - else if( pad==2 ) + else if (pad == 2) { - int A=unb64[safeAsciiPtr[charNo]]; - int B=unb64[safeAsciiPtr[charNo+1]]; + byte byte0 = b64decode[encoded_data[i]]; + byte byte1 = b64decode[encoded_data[i + 1]]; - bin[cb++] = (A<<2) | (B>>4) ; + *ptr++ = (byte0 << 2) | (byte1 >> 4); } - - return bin ; } diff --git a/src/libgame/base64.h b/src/libgame/base64.h index beffe9ca..3c76e6a0 100644 --- a/src/libgame/base64.h +++ b/src/libgame/base64.h @@ -12,7 +12,13 @@ #ifndef BASE64_H #define BASE64_H -char* base64( const void* binaryData, int len, int *flen ); -unsigned char* unbase64( const char* ascii, int len, int *flen ); +#include "system.h" + + +int base64_encoded_size(int); +int base64_decoded_size(const char *); + +void base64_encode(char *, const void *, int); +void base64_decode(byte *, const char *); #endif