/*
- Copyleft (c) 1999, 2016
-
- Author : scz [email protected]
- Compile : For *nix
-
: gcc -Wall -pipe -O3 -s -o base64 base64.c
-
:
-
: strip base64 or gcc -s
-
: mcs -d base64 (only for Solaris)
-
:
- Compile : For x86/EWindows XP SP1 & VC 7.1
-
: cl base64.c /Febase64.exe /nologo /Os /GB /Gz /Gs65536 /W3 /WX /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /link /RELEASE
-
:
- Create : 2005-04-05 19:43
- Modify : 2006-11-30 13:19
-
- The only thing they can't take from us are our minds. !H */
#if 0
方便测试一些东西,没有更多其它意义。
$ base64 "\x0\x1" [ 4 bytes ] -> 16 bytes per line 00000000 41 41 45 3D AAE= [ 2 bytes ] -> 16 bytes per line 00000000 00 01 .. $ base64 scz [ 4 bytes ] -> 16 bytes per line 00000000 63 32 4E 36 c2N6 [ 3 bytes ] -> 16 bytes per line 00000000 73 63 7A scz $ base64 nsfocus [ 12 bytes ] -> 16 bytes per line 00000000 62 6E 4E 6D 62 32 4E 31-63 77 3D 3D bnNmb2N1cw== [ 7 bytes ] -> 16 bytes per line 00000000 6E 73 66 6F 63 75 73 nsfocus
#endif
/************************************************************************
-
*
-
Head File *
-
*
************************************************************************/
#include <stdio.h> #include <stdlib.h> #include <string.h>
/************************************************************************
-
*
-
Macro *
-
*
************************************************************************/
#if defined(WIN32)
#pragma comment( linker, "/INCREMENTAL:NO" ) #pragma comment( linker, "/merge:.rdata=.text" ) #pragma comment( linker, "/subsystem:console" )
#endif
/************************************************************************
-
*
-
Function Prototype *
-
*
************************************************************************/
static unsigned int base64decode ( unsigned char *in, unsigned int len, unsigned char *out ); static unsigned char base64decodetable ( unsigned char in ); static unsigned int base64encode ( unsigned char *in, unsigned int len, unsigned char *out ); static unsigned char base64encodetable ( unsigned char in ); static unsigned int dosomething ( unsigned char *in, unsigned char *out ); static void hexdump ( FILE *out, unsigned char *in, unsigned int insize, unsigned int count );
/************************************************************************
-
*
-
Static Global Var *
-
*
************************************************************************/
/************************************************************************/
/*
-
BASE64解码算法的本质是8进制转16进制 */ static unsigned int base64decode ( unsigned char *in, unsigned int len, unsigned char *out ) { unsigned int x, y, z; unsigned int i, j; unsigned char bufa[4]; unsigned char bufb[3];
/*
- 由主调函数确保形参有效性 / x = ( len - 4 ) / 4; i = j = 0; for ( z = 0; z < x; z++ ) { for ( y = 0; y < 4; y++ ) { bufa[y] = base64decodetable( in[j+y] ); } / end of for / out[i] = bufa[0] << 2 | ( bufa[1] & 0x30 ) >> 4; out[i+1] = ( bufa[1] & 0x0F ) << 4 | ( bufa[2] & 0x3C ) >> 2; out[i+2] = ( bufa[2] & 0x03 ) << 6 | ( bufa[3] & 0x3F ); i += 3; j += 4; } / end of for / for ( z = 0; z < 4; z++ ) { bufa[z] = base64decodetable( in[j+z] ); } / end of for / /
- 编码算法确保了结尾最多有两个'=' / if ( '=' == in[len-2] ) { y = 2; } else if ( '=' == in[len-1] ) { y = 1; } else { y = 0; } /
- BASE64算法所需填充字节个数是自识别的 / for ( z = 0; z < y; z++ ) { bufa[4-z-1] = 0x00; } / end of for / bufb[0] = bufa[0] << 2 | ( bufa[1] & 0x30 ) >> 4; bufb[1] = ( bufa[1] & 0x0F ) << 4 | ( bufa[2] & 0x3C ) >> 2; bufb[2] = ( bufa[2] & 0x03 ) << 6 | ( bufa[3] & 0x3F ); /
- y必然小于3 / for ( z = 0; z < 3 - y; z++ ) { out[i+z] = bufb[z]; } / end of for / /
- 离开for循环的时候已经z++了 / i += z; return( i ); } / end of base64decode */
/*
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
-
返回0xFF表示失败 */ static unsigned char base64decodetable ( unsigned char in ) { unsigned char out = 0xFF;
if ( in >= 'A' && in <= 'Z' ) { out = in - 'A'; } else if ( in >= 'a' && in <= 'z' ) { out = in - 'a' + 26; } else if ( in >= '0' && in <= '9' ) { out = in - '0' + 52; } else if ( '+' == in ) { out = 62; } else if ( '/' == in ) { out = 63; } return( out ); } /* end of base64decodetable */
/*
-
BASE64编码算法的本质是16进制转8进制 */ static unsigned int base64encode ( unsigned char *in, unsigned int len, unsigned char *out ) { unsigned int x, y, z; unsigned int i, j; unsigned char buf[3];
x = len / 3; y = len % 3; i = j = 0; for ( z = 0; z < x; z++ ) { out[i] = base64encodetable( in[j] >> 2 ); out[i+1] = base64encodetable( ( in[j] & 0x03 ) << 4 | in[j+1] >> 4 ); out[i+2] = base64encodetable( ( in[j+1] & 0x0F ) << 2 | in[j+2] >> 6 ); out[i+3] = base64encodetable( in[j+2] & 0x3F ); i += 4; j += 3; } /* end of for / if ( 0 != y ) { buf[0] = buf[1] = buf[2] = 0x00; for ( z = 0; z < y; z++ ) { buf[z] = in[j+z]; } / end of for / out[i] = base64encodetable( buf[0] >> 2 ); out[i+1] = base64encodetable( ( buf[0] & 0x03 ) << 4 | buf[1] >> 4 ); out[i+2] = base64encodetable( ( buf[1] & 0x0F ) << 2 | buf[2] >> 6 ); out[i+3] = base64encodetable( buf[2] & 0x3F ); i += 4; / * BASE64算法所需填充字节个数是自识别的 / for ( z = 0; z < 3 - y; z++ ) { out[i-z-1] = '='; } / end of for / } return( i ); } / end of base64encode */
/*
-
显然查表更快,但为了满足我病态的追求程序对称美的心理,决定用函数实现。
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
-
返回0xFF表示失败 */ static unsigned char base64encodetable ( unsigned char in ) { unsigned char out = 0xFF;
if ( in <= 25 ) { out = in + 'A'; } else if ( in >= 26 && in <= 51 ) { out = in + 'a' - 26; } else if ( in >= 52 && in <= 61 ) { out = in + '0' - 52; } else if ( 62 == in ) { out = '+'; } else if ( 63 == in ) { out = '/'; } return( out ); } /* end of base64encodetable */
/*
-
2005-05-11 09:42
-
处理\、\xH、\xHH、\r、\n、\t、\0这几种情形 */ static unsigned int dosomething ( unsigned char *in, unsigned char *out ) { unsigned int i, j; unsigned char str[3];
for ( i = 0, j = 0; '\0' != in[i]; i++, j++ ) { if ( '\' != in[i] ) { out[j] = in[i]; } else { switch ( in[i+1] ) { case '\': /* * 出现了两个
/ out[j] = '\'; i++; break; case 'r': / * 出现了\r / out[j] = '\r'; i++; break; case 'n': / * 出现了\n / out[j] = '\n'; i++; break; case 't': / * 出现了\t / out[j] = '\t'; i++; break; case '0': / * 出现了\0 / out[j] = '\0'; i++; break; case 'x': / * 出现了\x / str[1] = str[2] = '\0'; if ( ( in[i+2] >= '0' && in[i+2] <= '9' ) || ( in[i+2] >= 'a' && in[i+2] <= 'f' ) || ( in[i+2] >= 'A' && in[i+2] <= 'F' ) ) { i += 2; str[0] = in[i]; if ( ( in[i+1] >= '0' && in[i+1] <= '9' ) || ( in[i+1] >= 'a' && in[i+1] <= 'f' ) || ( in[i+1] >= 'A' && in[i+1] <= 'F' ) ) { i++; str[1] = in[i]; } / * 按16进制串处理 / out[j] = ( unsigned char )strtoul( str, NULL, 16 ); } else { out[j] = in[i]; } break; case '\0': / * 最后一个
/ default: / * 无需转义 / out[j] = in[i]; break; } / end of switch / } } / end of for / return( j ); } / end of dosomething */
/*
-
2006-06-09 11:09 scz */ static void hexdump ( FILE *out, unsigned char *in, unsigned int insize, unsigned int count ) { unsigned int offset, k, j, i, m;
if ( insize <= 0 || count <= 0 || NULL == in || NULL == out ) { return; } fprintf( out, "[ %u bytes ] -> %u bytes per line\n", insize, count ); i = 0; offset = 0; m = ( count + 1 ) / 2; for ( k = insize / count; k > 0; k--, offset += count ) { fprintf( out, "%08X ", offset ); for ( j = 0; j < count; j++, i++ ) { if ( m == j ) { fprintf( out, "-%02X", in[i] ); } else { fprintf( out, " %02X", in[i] ); } } fprintf( out, " " ); i -= count; for ( j = 0; j < count; j++, i++ ) { /* * if ( isprint( ( int )in[i] ) ) / if ( ( in[i] >= ' ' ) && ( in[i] != 0x7F ) && ( in[i] < 0xFF ) ) #if 0 if ( ( in[i] >= ' ' ) && ( in[i] < 0x7F ) ) #endif { fprintf( out, "%c", in[i] ); } else { fprintf( out, "." ); } } fprintf( out, "\n" ); } / end of for / k = insize - i; if ( k <= 0 ) { return; } fprintf( out, "%08X ", offset ); for ( j = 0 ; j < k; j++, i++ ) { if ( m == j ) { fprintf( out, "-%02X", in[i] ); } else { fprintf( out, " %02X", in[i] ); } } i -= k; for ( j = count - k; j > 0; j-- ) { fprintf( out, " " ); } fprintf( out, " " ); for ( j = 0; j < k; j++, i++ ) { if ( ( in[i] >= ' ' ) && ( in[i] != 0x7F ) && ( in[i] < 0xFF ) ) #if 0 if ( ( in[i] >= ' ' ) && ( in[i] < 0x7F ) ) #endif { fprintf( out, "%c", in[i] ); } else { fprintf( out, "." ); } } fprintf( out, "\n" ); return; } / end of hexdump */
#if !defined(WIN32) int main ( int argc, char * argv[] ) #else int __cdecl main ( int argc, char * argv[] ) #endif { int ret = EXIT_FAILURE; unsigned int i; unsigned char buf[1024];
if ( argc <= 1 )
{
fprintf
(
stderr,
"Usage: %s <string>\n",
argv[0]
);
goto main_exit;
}
i = dosomething( argv[1], argv[1] );
if ( i / 3 * 4 + ( i % 3 ? 4 : 0 ) > 1024 )
{
fprintf
(
stderr,
"Checking your <string>\n"
);
goto main_exit;
}
i = base64encode( argv[1], i, buf );
hexdump( stdout, buf, i, 16 );
i = base64decode( buf, i, argv[1] );
hexdump( stdout, argv[1], i, 16 );
ret = EXIT_SUCCESS;
main_exit:
return( ret );
} /* end of main */
/************************************************************************/