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 ); }