前段时间在做邮件解码的时候碰到MIME的Base64编码和QP编码
1.Base64编码
Base64要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式.
解码算法大概可以分为如下几步几步:
读取数据3字节用AND取前6位,放入新的变量中右移两位,高两位清0AND取第一个字节的后2位和第二个字节的前4位移位放入新变量中右移两位,清0……依此类推。
// 解码后的长度一般比原文少用占1/4的存储空间,请保证buf有足够的空间
inline int Base64Decode(char * buf, const char * base64code, int src_len)
{
if (src_len == 0)
src_len = strlen(base64code);
int len = 0;
unsigned char* psrc = (unsigned char*)base64code;
char * pbuf = buf;
int i ;
for ( i = 0; i < src_len - 4; i += 4)
{
unsigned long ulTmp = *(unsigned long*)psrc;
register int b0 = (GetB64Index((char)B0(ulTmp)) << 2 | GetB64Index((char)B1(ulTmp)) << 2 >> 6) & 0xFF;
register int b1 = (GetB64Index((char)B1(ulTmp)) << 4 | GetB64Index((char)B2(ulTmp)) << 2 >> 4) & 0xFF;
register int b2 = (GetB64Index((char)B2(ulTmp)) << 6 | GetB64Index((char)B3(ulTmp)) << 2 >> 2) & 0xFF;
// *((unsigned long*)pbuf) = b0 | b1 << 8 | b2 << 16;
*pbuf++ = b0;
*pbuf++ = b1;
*pbuf++ = b2;
psrc += 4;
// pbuf += 4;
len += 3;
}
// 处理最后余下的不足4字节的数据
if (i < src_len)
{
int rest = src_len - i;
unsigned long ulTmp = 0;
for (int j = 0; j < rest; ++j)
{
*(((unsigned char*)&ulTmp) + j) = *psrc++;
}
register int b0 = (GetB64Index((char)B0(ulTmp)) << 2 | GetB64Index((char)B1(ulTmp)) << 2 >> 6) & 0xFF;
*pbuf++ = b0;
len ++;
if ('=' != B1(ulTmp) && '=' != B2(ulTmp))
{
register int b1 = (GetB64Index((char)B1(ulTmp)) << 4 | GetB64Index((char)B2(ulTmp)) << 2 >> 4) & 0xFF;
*pbuf++ = b1;
len ++;
}
if ('=' != B2(ulTmp) && '=' != B3(ulTmp))
{
register int b2 = (GetB64Index((char)B2(ulTmp)) << 6 | GetB64Index((char)B3(ulTmp)) << 2 >> 2) & 0xFF;
*pbuf++ = b2;
len ++;
}
}
*pbuf = '\0';
return len;
}
inline int Base64Decode(char * buf, const char * base64code, int src_len)
{
if (src_len == 0)
src_len = strlen(base64code);
int len = 0;
unsigned char* psrc = (unsigned char*)base64code;
char * pbuf = buf;
int i ;
for ( i = 0; i < src_len - 4; i += 4)
{
unsigned long ulTmp = *(unsigned long*)psrc;
register int b0 = (GetB64Index((char)B0(ulTmp)) << 2 | GetB64Index((char)B1(ulTmp)) << 2 >> 6) & 0xFF;
register int b1 = (GetB64Index((char)B1(ulTmp)) << 4 | GetB64Index((char)B2(ulTmp)) << 2 >> 4) & 0xFF;
register int b2 = (GetB64Index((char)B2(ulTmp)) << 6 | GetB64Index((char)B3(ulTmp)) << 2 >> 2) & 0xFF;
// *((unsigned long*)pbuf) = b0 | b1 << 8 | b2 << 16;
*pbuf++ = b0;
*pbuf++ = b1;
*pbuf++ = b2;
psrc += 4;
// pbuf += 4;
len += 3;
}
// 处理最后余下的不足4字节的数据
if (i < src_len)
{
int rest = src_len - i;
unsigned long ulTmp = 0;
for (int j = 0; j < rest; ++j)
{
*(((unsigned char*)&ulTmp) + j) = *psrc++;
}
register int b0 = (GetB64Index((char)B0(ulTmp)) << 2 | GetB64Index((char)B1(ulTmp)) << 2 >> 6) & 0xFF;
*pbuf++ = b0;
len ++;
if ('=' != B1(ulTmp) && '=' != B2(ulTmp))
{
register int b1 = (GetB64Index((char)B1(ulTmp)) << 4 | GetB64Index((char)B2(ulTmp)) << 2 >> 4) & 0xFF;
*pbuf++ = b1;
len ++;
}
if ('=' != B2(ulTmp) && '=' != B3(ulTmp))
{
register int b2 = (GetB64Index((char)B2(ulTmp)) << 6 | GetB64Index((char)B3(ulTmp)) << 2 >> 2) & 0xFF;
*pbuf++ = b2;
len ++;
}
}
*pbuf = '\0';
return len;
}