www.pudn.com > pop3.rar > mimeb64.c


/****************************************************************** 
//  MIME(Quoted-Printable & Base64) Encode/Decode unit. (C) 
//  Copyright (c) 2000, 02 Mental Studio - http://msrc.126.com 
//  Author : Raptor - raptorz@163.com 
//   
//  Base 64:         是一种通用的方法,其原理就是把三个Byte的数据用  
//					 4 个Byte表示,这样,这四个Byte 中,实际用到的 
//					 都只有前面6 bit。 
//  Quote-Printable: 是把一个 8 bit 的字符用两个16进制数值表示,然 
//					 后在前面加"="。 
// 
//  history:  
//         
*******************************************************************/ 
 
#include  
#include  
#include "mimeb64.h" 
 
//--------------------------------------------------------------------------- 
//  4bit binary to char 0-F 
//--------------------------------------------------------------------------- 
char Hex2Chr( unsigned char n ) 
{ 
	n &= 0xF; 
    if ( n < 10 ) 
    	return ( char )( n + '0' ); 
    else 
    	return ( char )( n - 10 + 'A' ); 
} 
 
//--------------------------------------------------------------------------- 
//  char 0-F to 4bit binary 
//--------------------------------------------------------------------------- 
unsigned char Chr2Hex( char c ) 
{ 
	if ( c >= 'a' && c <= 'z' )  //  it's toupper 
    	c = c - 'a' + 'A'; 
    if ( c >= '0' && c <= '9' ) 
    	return ( int )( c - '0' ); 
    else if ( c >= 'A' && c <= 'F' ) 
    	return ( int )( c - 'A' + 10 ); 
    else 
    	return -1; 
} 
 
//--------------------------------------------------------------------------- 
//  Base64 code table 
//  0-63 : A-Z(25) a-z(51), 0-9(61), +(62), /(63) 
//--------------------------------------------------------------------------- 
char  Base2Chr( unsigned char n ) 
{ 
	n &= 0x3F; 
	if ( n < 26 ) 
    	return ( char )( n + 'A' ); 
    else if ( n < 52 ) 
    	return ( char )( n - 26 + 'a' ); 
    else if ( n < 62 ) 
    	return ( char )( n - 52 + '0' ); 
    else if ( n == 62 ) 
    	return '+'; 
    else 
    	return '/'; 
} 
 
//--------------------------------------------------------------------------- 
// Make a char to the base 
//--------------------------------------------------------------------------- 
unsigned char Chr2Base( char c ) 
{ 
	if ( c >= 'A' && c <= 'Z' ) 
    	return ( unsigned char )( c - 'A' ); 
    else if ( c >= 'a' && c <= 'z' ) 
    	return ( unsigned char )( c - 'a' + 26 ); 
    else if ( c >= '0' && c <= '9' ) 
    	return ( unsigned char )( c - '0' + 52 ); 
    else if ( c == '+' ) 
    	return 62; 
    else if ( c == '/' ) 
    	return 63; 
    else 
        return 64;  //  无效字符 
} 
 
//--------------------------------------------------------------------------- 
//  aLen 为 aSrc 的大小, aDest 所指的缓冲区必须至少为 aLen 的 3 倍!!! 
//  返回 aDest 的长度,不包含字符串结束符 
//--------------------------------------------------------------------------- 
int QPEncode( char * const aDest, const unsigned char * aSrc, int aLen ) 
{ 
	char * p = aDest; 
    int    i = 0; 
	int	   iLineLength = 0; 
     
	assert(aDest!=NULL && aSrc!=NULL && aLen>0); 
 
    while ( i++ < aLen ) 
    { 
//		if (('\r' == *aSrc) || ('\n' == *aSrc)) 
//		{ 
//			*p++ = *aSrc++; 
//			continue; 
//		} 
    	*p++ = '='; 
		iLineLength++; 
		if(iLineLength>=QUOTE_LINE_SIZE) 
		{	*p++ = '\r';	*p++ = '\n'; 
			iLineLength = 0; 
		} 
        *p++ = Hex2Chr( (unsigned char)(*aSrc >> 4) ); 
		iLineLength++; 
		if(iLineLength>=QUOTE_LINE_SIZE) 
		{	*p++ = '\r';	*p++ = '\n'; 
			iLineLength = 0; 
		} 
        *p++ = Hex2Chr( (unsigned char)*aSrc++ ); 
		iLineLength++; 
		if(iLineLength>=QUOTE_LINE_SIZE) 
		{	*p++ = '\r';	*p++ = '\n'; 
			iLineLength = 0; 
		} 
    } 
    *p = 0;  //  aDest is an ASCIIZ string 
	return ( p - aDest );  //  exclude the end of zero 
} 
 
//--------------------------------------------------------------------------- 
//  aDest 所指的缓冲区必须至少为 aSrc 长度的 1/3 !!! 
//  返回 aDest 的长度 
//--------------------------------------------------------------------------- 
int QPDecode( unsigned char * const aDest, const char * aSrc ) 
{ 
	unsigned char * p = aDest; 
    int             n = strlen( aSrc ); 
    unsigned char   ch, cl; 
     
    assert(aDest!=NULL && aSrc!=NULL); 
 
    while ( *aSrc )  //  aSrc is an ASCIIZ string 
    { 
    	if ( ( *aSrc == '=' ) && ( n - 2 > 0 ) ) 
        { 
        	ch = Chr2Hex( aSrc[1] ); 
            cl = Chr2Hex( aSrc[2] ); 
            if ( ( ch == ( unsigned char )-1 ) || ( cl == ( unsigned char )-1 ) ) 
            	*p++ = *aSrc++; 
            else 
            { 
				*p++ = ( ch << 4 ) | cl; 
    	        aSrc += 3; 
            } 
        } 
        else 
        	*p++ = *aSrc++; 
    } 
	return ( p - aDest ); 
} 
 
//--------------------------------------------------------------------------- 
//  aLen 为 aSrc 的长度, aDest 所指的缓冲区必须至少为 aLen 的 4/3 倍!!! 
//  返回 aDest 的长度 
//--------------------------------------------------------------------------- 
int Base64Encode( char * const aDest, const unsigned char * aSrc, int aLen ) 
{ 
	char        * p = aDest; 
    int           i; 
    unsigned char t; 
	int		iLineLength = 0; 
	 
	assert(aDest!=NULL && aSrc != NULL && aLen>0); 
 
    for ( i = 0; i < aLen; i++ ) 
    { 
    	switch ( i % 3 ) 
        { 
        case 0 : 
        	*p++ = Base2Chr( (unsigned char)(*aSrc >> 2) ); 
            t = ( *aSrc++ << 4 ) & 0x3F; 
			iLineLength += 1; 
            break; 
        case 1 : 
        	*p++ = Base2Chr( (unsigned char)(t | ( *aSrc >> 4 )) ); 
            t = ( *aSrc++ << 2 ) & 0x3F; 
			iLineLength += 1; 
            break; 
        case 2 : 
        	*p++ = Base2Chr( (unsigned char)(t | ( *aSrc >> 6 )) ); 
			iLineLength += 1; 
			if(iLineLength>=BASE64_LINE_SIZE) 
			{	*p++ = '\r';	 
				*p++ = '\n';	 
				iLineLength = 0; 
			} 
            *p++ = Base2Chr( *aSrc++ ); 
			iLineLength += 1; 
            break; 
        } 
		if(iLineLength>=BASE64_LINE_SIZE) 
		{ 
			*p++ = '\r'; 
			*p++ = '\n'; 
			iLineLength = 0; 
		} 
    } 
    if ( aLen % 3 != 0 ) 
    { 
    	*p++ = Base2Chr( t ); 
        if ( aLen % 3 == 1 ) 
        	*p++ = '='; 
        *p++ = '='; 
    } 
    *p = 0;  //  aDest is an ASCIIZ string 
	return ( p - aDest );  //  exclude the end of zero 
} 
 
//--------------------------------------------------------------------------- 
//  aDest 所指的缓冲区必须至少为 aSrc 长度的 0.75 倍!!! 
//  返回 aDest 的长度 
//--------------------------------------------------------------------------- 
int Base64Decode( unsigned char * const aDest, const char * aSrc ) 
{ 
	unsigned char * p = aDest; 
    int             i; 
	int				n = strlen( aSrc ); 
    unsigned char   c, t; 
	 
	assert(aDest!=NULL && aSrc!=NULL); 
 
    for ( i = 0; i < n; i++ ) 
    { 
    	if ( *aSrc == '=' ) 
        	break; 
        do { 
        	if ( *aSrc ) 
		       	c = Chr2Base( *aSrc++ ); 
            else 
            	c = 65;       //  字符串结束 
        } while ( c == 64 );  //  跳过无效字符,如回车等 
        if ( c == 65 ) 
        	break; 
        switch ( i % 4 ) 
        { 
        case 0 : 
            t = c << 2; 
            break; 
        case 1 : 
            *p++ = ( unsigned char )( t | ( c >> 4 ) ); 
            t = ( unsigned char )( c << 4 ); 
            break; 
        case 2 : 
            *p++ = ( unsigned char )( t | ( c >> 2 ) ); 
            t = ( unsigned char )( c << 6 ); 
            break; 
        case 3 : 
            *p++ = ( unsigned char )( t | c ); 
            break; 
        } 
    } 
	return ( p - aDest ); 
}