// 測試平臺: 在Win2K下的Cygwin gcc編譯通過,測試沒有發現問題(如果你發現了還請告訴我,謝謝!)
// 調用的庫: strlen() ( 其實可以自己寫一個類似的功能函數來取長度的 )
/*
*********************************************************************************************************
* 昆明XXXX有限公司
* 技術研發部
*
* (c) Copyright 2005-2006, kmajian
* All Rights Reserved
*
* Base-64的編解碼程序文件
*
* File : BASE64.C
* By : kmajian
* Date : 2006-6-23
*********************************************************************************************************
*/
#include "CONFIG.H"
#include "base64.h"
#define CH_EMPTY 0xFF
static const uint8 baseAlp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
*********************************************************************************************************
* Base64編碼
*
* 函數名稱 : base64enc
* 功能描述 : 把特定內存塊編碼爲Base64編碼, 存入目的字符串
* 調用模塊 : 無
* 參 數 : *sOut 目標字符緩衝區
* *pIn 需要轉變爲Base64編碼的內存塊
* iLen 內存塊長度
* 返 回 : uint16 生成編碼的長度
*********************************************************************************************************
*/
uint16 base64enc(void *pIn, uint16 iLen, char * sOut)
{
uint8 *pBuf = ( uint8 * )pIn;
uint8 swiBuf[ 4 ];
uint16 i, n;
uint16 iReturn = 0;
uint16 iLenM3 = iLen % 3;
uint16 iLenD3 = iLen / 3;
uint16 iLenD3p;
if( iLenM3 == 0 ) // 如果iLenM3等於0則iLenD3p就爲iLenD3,否則爲(iLenD3+1)
iLenD3p = iLenD3;
else
iLenD3p = iLenD3;
if( iLen < 1 )
{
return iReturn;
}
for( i = 0; i < iLenD3p; i++ )
{
swiBuf[ 0 ] = ( *pBuf ) >> 2; // 把第一個字符右移2位得到一個個目標字符
swiBuf[ 1 ] = ( ( *pBuf ) << 4 ) & 0x30; // 把第一個字符左移四位,然後與0x30相與,
// 得到第二個目標字符的第5、6位
pBuf++;
swiBuf[ 1 ] = swiBuf[ 1 ] + ( ( *pBuf ) >> 4 ); // 把第二個字符右移4位,然後與得到的目標5、6位相加
// 得到第二個目標字符
swiBuf[ 2 ] = ( ( *pBuf ) << 2 ) & 0x3C; // 把第二個字符左移2位,然後與0x3C相與,
// 得到第二個目標字符的第3、4、5、6位
pBuf++;
swiBuf[ 2 ] = swiBuf[ 2 ] + ( ( *pBuf ) >> 6 ); // 把第三個字符右移6位,然後與得到的目標3、4、5、6
// 位相加,得到第三個目標字符
swiBuf[ 3 ] = ( *pBuf ) & 0x3F; // 第三個字符與0x3F相與,得到第四個目標字符
pBuf++;
for( n = 0; n < 4; n++ ) // 取得需要的Base64編碼
{
*sOut = baseAlp[ swiBuf[ n ] ];
sOut++;
iReturn++;
}
}
switch( iLenM3 ) // 對不足三個字符的編碼處理
{
case 1: swiBuf[ 0 ] = ( *pBuf ) >> 2;
swiBuf[ 1 ] = ( ( *pBuf ) << 4 ) & 0x30;
swiBuf[ 2 ] = '=';
swiBuf[ 3 ] = '=';
for( n = 0; n < 4; n++ )
{
if( swiBuf[ n ] == '=' )
{
*sOut = '=';
}
else
{
*sOut = baseAlp[ swiBuf[ n ] ];
}
sOut++;
iReturn++;
}
break;
case 2: swiBuf[ 0 ] = ( *pBuf ) >> 2;
swiBuf[ 1 ] = ( ( *pBuf ) << 4 ) & 0x30;
pBuf++;
swiBuf[ 1 ] = swiBuf[ 1 ] + ( ( *pBuf ) >> 4 );
swiBuf[ 2 ] = ( ( *pBuf ) << 2 ) & 0x3C;
swiBuf[ 3 ] = '=';
for( n = 0; n < 4; n++ )
{
if( swiBuf[ n ] == '=' )
{
*sOut = '=';
}
else
{
*sOut = baseAlp[ swiBuf[ n ] ];
}
sOut++;
iReturn++;
}
break;
default:break;
}
*sOut = '/0';
return iReturn;
}
/*
*********************************************************************************************************
* Base64解碼
*
* 函數名稱 : base64dec
* 功能描述 : 把送入的字符串按Base64方式解碼, 存入目的緩衝區
* 調用模塊 : 無
* 參 數 : *sIn 源字符串
* *pOut 輸出內存塊
* 返 回 : uint16 解碼後內容的長度
*********************************************************************************************************
*/
uint16 base64dec(const char *sIn, void * const pOut)
{
uint8 *outBuf = ( uint8 * )pOut;
uint8 cTemp;
uint8 cBuf[ 3 ];
uint16 iReturn = 0;
uint16 i, n;
uint16 cLen;
uint16 aLen;
cLen = strlen( sIn );
if( ( cLen % 4 ) != 0 )
{
return iReturn;
}
aLen = cLen / 4;
for( i = 0; i < aLen; i++ )
{
cTemp = GetB64Char( *sIn );
sIn++;
cBuf[ 0 ] = cTemp << 2;
cTemp = GetB64Char( *sIn );
sIn++;
cBuf[ 0 ] = cBuf[ 0 ] + ( cTemp >> 4 );
cBuf[ 1 ] = cTemp << 4;
cTemp = GetB64Char( *sIn );
sIn++;
if( cTemp == CH_EMPTY )
{
*outBuf = cBuf[ 0 ];
outBuf++;
*outBuf = cBuf[ 1 ];
iReturn = iReturn + 2;
return iReturn;
}
else
{
cBuf[ 1 ] = cBuf[ 1 ] + ( cTemp >> 2 );
cBuf[ 2 ] = cTemp << 6;
}
cTemp = GetB64Char( *sIn );
sIn++;
if( cTemp == CH_EMPTY )
{
*outBuf = cBuf[ 0 ];
outBuf++;
*outBuf = cBuf[ 1 ];
outBuf++;
*outBuf = cBuf[ 2 ];
iReturn = iReturn + 3;
return iReturn;
}
else
{
cBuf[ 2 ] = cBuf[ 2 ] + cTemp;
}
for( n = 0; n < 3; n++ )
{
*outBuf = cBuf[ n ];
outBuf++;
iReturn++;
}
}
return iReturn;
}
// 獲取Base64編碼值
uint8 GetB64Char( const uint8 ch )
{
uint8 n;
if( ch == '=' )
{
return CH_EMPTY;
}
else
{
for( n = 0; n < strlen( baseAlp ); n++ )
{
if( ch == baseAlp[ n ] )
{
break;
}
}
return n;
}
}
/*
*********************************************************************************************************
* END
*********************************************************************************************************
*/