#include #include #include #include #include "mail_decoder_codec.h" /*- * 64 char lines * pad input with 0 * left over chars are set to = * 1 byte => xx== * 2 bytes => xxx= * 3 bytes => xxxx */ static const char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #define conv_bin2ascii(a) (data_bin2ascii[(a)&0x3f]) /*- * 0xF0 is a EOLN * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). * 0xF2 is EOF * 0xE0 is ignore at start of line. * 0xFF is error */ #define B64_EOLN 0xF0 #define B64_CR 0xF1 #define B64_EOF 0xF2 #define B64_WS 0xE0 #define B64_ERROR 0xFF #define B64_NOT_BASE64(a) (((a)|0x13) == 0xF3) #define B64_BASE64(a) !B64_NOT_BASE64(a) static const unsigned char data_ascii2bin[128] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; //切记不可以如此调用: conv_ascii2bin(x++); 因为会++两次 #define conv_ascii2bin(aa) (((aa) & 0x80)?(0xFF):data_ascii2bin[(aa)]) /*static unsigned char conv_ascii2bin(unsigned char a) { if (a & 0x80) return B64_ERROR; return data_ascii2bin[a]; //return (((a) & 0x80)?B64_ERROR:data_ascii2bin[(a)]); } */ /********************************************************************* 函数名称:Base64_EncodeBlock 功能简介:对一完整BASE64编码块进行编码 输入参数:in:待编码的字符; inl:in的长度 输出参数:out:编码后存储的缓冲区; 返回值:编码后的长度 *********************************************************************/ int Base64_EncodeBlock(const unsigned char *in, int inl, unsigned char *out) { int i, ret = 0; unsigned long l; for (i = inl; i > 0; i -= 3) { if (i >= 3) { l = (((unsigned long)in[0]) << 16L) | (((unsigned long)in[1]) << 8L) | in[2]; *(out++) = conv_bin2ascii(l >> 18L); *(out++) = conv_bin2ascii(l >> 12L); *(out++) = conv_bin2ascii(l >> 6L); *(out++) = conv_bin2ascii(l); } else { l = ((unsigned long)in[0]) << 16L; if (i == 2) l |= ((unsigned long)in[1] << 8L); *(out++) = conv_bin2ascii(l >> 18L); *(out++) = conv_bin2ascii(l >> 12L); *(out++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L); *(out++) = '='; } ret += 4; in += 3; } *out = '\0'; return (ret); } /********************************************************************* 函数名称:Base64_DecodeBlock 功能简介:对一完整BASE64编码块进行解析,自动忽略首尾非BASE64编码字符 输入参数:in:待解码的字符; inl:in的长度 输出参数:out:解码后存储的缓冲区; 必须保证有足够的空间,一般达到@inl大小即可; 返回值:<0:失败;>=0:解码后的长度 *********************************************************************/ int Base64_DecodeBlock(const unsigned char *in, int inl, unsigned char *out, int outsize) { int i, ret = 0; unsigned char a, b, c, d; unsigned long l; /* ignore not-base64-encoded charactor. */ while ((conv_ascii2bin(*in) == B64_WS) && (inl > 0)) { in++; inl--; } while ((inl > 3) && (B64_NOT_BASE64(conv_ascii2bin(in[inl - 1])))) inl--; if (inl % 4 != 0) return -1; if(outsize < (inl*3)/4) return -2; for (i = 0; i < inl; i += 4) { a = conv_ascii2bin(*(in)); b = conv_ascii2bin(*(in+1)); c = conv_ascii2bin(*(in+2)); d = conv_ascii2bin(*(in+3)); if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) return (-1); l = ((((unsigned long)a) << 18L) | (((unsigned long)b) << 12L) | (((unsigned long)c) << 6L) | (((unsigned long)d))); *(out++) = (unsigned char)(l >> 16L) & 0xff; *(out++) = (unsigned char)(l >> 8L) & 0xff; *(out++) = (unsigned char)(l) & 0xff; ret += 3; in+=4; } for(i = inl; i > 0; i -= 4) { if(*(in-3) == '=') { in -= 4; ret -= 3; continue; } while(*(--in) == '=') ret -= 1; break; } return ret; } void Base64_DecodeInit(decode_handle_t *handle) { handle->length = 0; } /********************************************************************* 函数名称:Base64_DecodeFeed 功能简介:对部分BASE64编码块进行解析,自动忽略首尾非BASE64编码字符 输入参数:in:待解码的字符; inl:in的长度,可能不是4的倍数,对于小于4的部分,会转存一下, 下次解码时将其拼接到输入数据的头部;转存的最大长度为3, 因为如果达到了4,就可以将该部分解码出来; 输出参数:out:解码后存储的缓冲区; 返回值:-1:失败;0:需要更多的数据;>0:解码后的长度 *********************************************************************/ int Base64_DecodeFeed(decode_handle_t *handle, const unsigned char *in, int inl, unsigned char *out, int outsize) { int i, j=0, dst_len = 0; const unsigned char *pc=in, *pend=in+inl; unsigned char de[4]; unsigned long l; /* ignore not-base64-encoded charactor. */ while(pcpc && B64_NOT_BASE64(conv_ascii2bin(*(pend-1)))) pend--; if(handle->length>0) { while(pclength<4) { handle->enc_data[handle->length++] = *pc; pc++; } if(handle->length < 4) { return 0; } else { for(i=0; i<4; i++) { de[j++] = conv_ascii2bin(handle->enc_data[i]); } } } do { while(j < 4 && pc outsize) return -2; if ((de[0] & 0x80) || (de[1] & 0x80) || (de[2] & 0x80) || (de[3] & 0x80)) return (-1); l = ((((unsigned long)de[0]) << 18L) | (((unsigned long)de[1]) << 12L) | (((unsigned long)de[2]) << 6L) | (((unsigned long)de[3]))); *(out++) = (unsigned char)(l >> 16L) & 0xff; *(out++) = (unsigned char)(l >> 8L) & 0xff; *(out++) = (unsigned char)(l) & 0xff; dst_len += 3; }while(pc < pend); pc--; //有残留,进行缓存,不要存换行符 if(j>0) { handle->length = j; while(j>0 && pc>=in) { handle->enc_data[j-1] = *pc; pc--; j--; } return dst_len; } //无解码残留 else if(pc>=in && *pc == '=') { dst_len -= 1; pc--; if((pc>=in && *pc == '=') ||(handle->length>0 && handle->enc_data[handle->length-1]=='=')) dst_len -= 1; } handle->length = 0; return dst_len; } /********************************************************************* 函数名称:Base64_DecodeFeed_r_n 功能简介:与Base64_DecodeFeed不同之处在于: 输入数据任何位置有可能出现'\r'或'\n',或一起出现; 输入参数:同Base64_DecodeFeed 输出参数:同Base64_DecodeFeed 返回值:同Base64_DecodeFeed *********************************************************************/ int Base64_DecodeFeed_r_n(decode_handle_t *handle, const unsigned char *in, int inl, unsigned char *out, int outsize) { int i, j=0, dst_len = 0; const unsigned char *pc=in, *pend=in+inl; unsigned char de[4]; unsigned long l; /* ignore not-base64-encoded charactor. */ while(pcpc && B64_NOT_BASE64(conv_ascii2bin(*(pend-1)))) pend--; //上一次有残留,先补齐4个字符到handle(为了结尾处判断残留是否是换行符) if(handle->length>0) { while(pclength<4) { if(*pc=='\r' || *pc=='\n' || *pc==' ' || *pc=='\t') { pc++; continue; } handle->enc_data[handle->length++] = *pc; pc++; } if(handle->length < 4) { return 0; } else { for(i=0; i<4; i++) { de[j++] = conv_ascii2bin(handle->enc_data[i]); } } } do { while(j < 4) { while(pc= pend) break; de[j++] = conv_ascii2bin(*pc); pc++; } if(j < 4) break; j = 0; if(dst_len + 3 > outsize) return -2; if ((de[0] & 0x80) || (de[1] & 0x80) || (de[2] & 0x80) || (de[3] & 0x80)) return (-1); l = ((((unsigned long)de[0]) << 18L) | (((unsigned long)de[1]) << 12L) | (((unsigned long)de[2]) << 6L) | (((unsigned long)de[3]))); *(out++) = (unsigned char)(l >> 16L) & 0xff; *(out++) = (unsigned char)(l >> 8L) & 0xff; *(out++) = (unsigned char)(l) & 0xff; dst_len += 3; }while(pc < pend); pc--; //有残留,进行缓存,不要存换行符 if(j>0) { handle->length = j; while(j>0) { while(pc>=in && (*pc == '\r' || *pc == '\n' || *pc==' ' || *pc=='\t')) { pc--; continue; } handle->enc_data[j-1] = *pc; pc--; j--; } return dst_len; } //无解码残留,如果尾部是=,修正实际的解码后长度 else if(pc>=in && *pc == '=') { dst_len -= 1; pc--; if((pc>=in && *pc == '=') ||(handle->length>0 && handle->enc_data[handle->length-1]=='=')) dst_len -= 1; } handle->length = 0; return dst_len; } static unsigned char decode_hex( char *streamptr ) { unsigned char result = 0; char blivit; blivit = *streamptr++; if ( blivit >= 'a' ) blivit -= ' '; if ( blivit > '9' ) blivit -= 0x07; result = blivit & 0x0F; result <<= 4; blivit = *streamptr++; if ( blivit >= 'a' ) blivit -= ' '; if ( blivit > '9' ) blivit -= 0x07; result |= blivit & 0x0F; return result; } /********************************************************************* 函数名称:QP_DecodeBlock 功能简介:对一完整QP编码块进行解析,会忽略'\r''\n'字符 输入参数:in:待解码的字符; inl:in的长度 输出参数:out:解码后存储的缓冲区, 必须保证有足够的空间,一般达到@inl大小即可; 返回值:解码后的长度 *********************************************************************/ //"PPPPPP=X",如果X是一16进制数,是否保留"=X"?目前是保留。 int QP_DecodeBlock(const unsigned char *in, int inl, unsigned char *out) { int index=0, index2=0; //分别是buf、enc_data里内容长度 const unsigned char *temp=in, *inputend=in+inl; unsigned char value; int state=0; char buf[2]; int dst_len=0; if(inl == 0) return 0; while(temp '9')) && ((*temp < 'A') || (*temp > 'F')) && ((*temp < 'a') || (*temp > 'f'))) { out[dst_len++] = '='; out[dst_len] = '\0'; if(index!=0) //遇到了=XY串,其中X是16进制数,Y不是 { out[dst_len++] = buf[0]; out[dst_len] = '\0'; } if(*temp== '=') { state = 1; } else { out[dst_len++] = *temp; out[dst_len] = '\0'; state=0; index2=0; } index=0; } //是可解码的字符,但是不够 else if(index<1) { buf[index++]=*temp; } //进行解码 else { buf[index++]=*temp; value=decode_hex(buf); out[dst_len++] = value; out[dst_len]='\0'; index=0; state=0; index2=0; } temp=temp+1; break; case 2: state = 0; index = 0; index2 = 0; if(*temp == '=') { index2++; state=1; } else if(*temp!='\n' && *temp!='\r') { out[dst_len++] = *temp; out[dst_len]='\0'; } temp++; break; default: break; } } //保留最后不足以进行解码的数据 if(index2!=0) { out[dst_len++] = '='; out[dst_len]='\0'; if(index!=0) { out[dst_len++] = buf[0]; out[dst_len]='\0'; } } return dst_len; } void QP_DecodeInit(decode_handle_t *handle) { handle->length = 0; } /********************************************************************* 函数名称:QP_DecodeFeed 功能简介:对部分QP编码块进行解析 输入参数:in:待解码的字符; inl:in的长度,可能不足以解码出来,对于不足以解码的部分, 会转存一下,下次解码时优先解决该部分,转存的最大长度为2; 如果为1,必然是'=';如果为2,必然是"=X";X是一个16进制数; 输出参数:out:解码后存储的缓冲区; 返回值:-1:失败;0:需要更多的数据;>0:解码后的长度 *********************************************************************/ int QP_DecodeFeed(decode_handle_t *handle,const unsigned char *in, int inl, unsigned char *out) { int index=0, index2=0; //分别是buf、enc_data里内容长度 const unsigned char *temp=in, *inputend=in+inl; unsigned char value; int state=0; char buf[2]; int dst_len=0; if(inl == 0) return 0; if(handle->length > 0) { if(handle->length == 1) { state = 1; index2 = 1; } else if(handle->length == 2) { if(handle->enc_data[1] == '\n') { state = 2; index2 = 2; } else { state = 1; index2 = 1; index = 1; buf[0] = handle->enc_data[1]; } } handle->length = 0; } while(temp '9')) && ((*temp < 'A') || (*temp > 'F')) && ((*temp < 'a') || (*temp > 'f'))) { out[dst_len++] = '='; out[dst_len] = '\0'; if(index!=0) //遇到了=XY串,其中X是16进制数,Y不是 { out[dst_len++] = buf[0]; out[dst_len] = '\0'; } if(*temp== '=') { state = 1; } else { out[dst_len++] = *temp; out[dst_len] = '\0'; state=0; index2=0; } index=0; } //是可解码的字符,但是不够 else if(index<1) { buf[index++]=*temp; } //进行解码 else { buf[index++]=*temp; value=decode_hex(buf); out[dst_len++] = value; out[dst_len]='\0'; index=0; state=0; index2=0; } temp=temp+1; break; case 2: state = 0; index = 0; index2 = 0; if(*temp == '=') { index2++; state=1; } else if(*temp!='\n' && *temp!='\r') { out[dst_len++] = *temp; out[dst_len]='\0'; } temp++; break; default: break; } } if(index2!=0) { handle->enc_data[0] = '='; handle->length = 1; if(index2 == 2) handle->enc_data[handle->length++] = '\n'; else if(index!=0) { handle->enc_data[1] = buf[0]; handle->length = 2; } } return dst_len; }