编码规则如下:
- ASCII中,[33,126]之间除了'=',在QP中都可以直接显示无需编码。0-32 + '=' + 127-254这些字符是需要进行QP编码的。
- 编码方法:如空格在ASCII中用0x20十六进制表示,QP编码将其十六进制用字符表示,在其前加'='号,为=20。QP编码中,'='符号后必须为大写。
- 普通文本中有'\r\n'换行符号,在QP中,编码为=0D=0A,但不换行。
- QP编码每行的长度限制为最多76个字符,到达后需要添加QP中的软换行(=\r\n),直接将软换行加入QP编码中,其中'='算在76字符内,而'\r\n'不算。
- QP编码的所有行不能以空格或TAB结尾,必须为软换行(=\r\n)或可打印的字符。
- 代码中最好加入异常处理:QP编码不为大写,结尾为空格等。
更详细规则参考RFC 2045
代码实现:
#define MAX_LINE_LEN 76 /* RFC规定QP编码单行最大长度 */ /* src_len 源字符串长度 * dst_len dst缓冲区大小 */ static int encode_quoted(const char *src, int src_len, char *dst, int dst_len) { int i = 0; int cur_line_len = 0; /* 记录单行长度 */ int dst_alen = 0; /* 向dst输出总长度 */ /* 保证dst不被写越界 */ for (i = 0; i < src_len && dst_alen < dst_len - 3; i++, src++) { /* ASCII 33-60,62-126原样输出,其余需编码 */ if ((*src >= '!') && (*src <= '~') && (*src != '=')) { *dst++ = *src; dst_alen++; cur_line_len++; } else { sprintf(dst, "=%02X", *src); dst += 3; dst_alen += 3; cur_line_len += 3; } /* 单行长度限制 * 结尾=\r\n中\r\n不计入 */ if (cur_line_len >= MAX_LINE_LEN-3) { sprintf(dst, "=\r\n"); dst += 3; dst_alen += 3; cur_line_len = 0; } } *dst = '\0'; return dst_alen; } static int decode_quoted(const char *src, int src_len, char *dst, int dst_len) { int j = 0; int dst_alen = 0; for (dst_alen = 0, j = 0; dst_alen < dst_len && j < src_len; dst_alen++, dst++) { if (strncmp(src, "=\r\n", 3) == 0) { src += 3; j += 3; } else { if (*src == '=') { sscanf(src, "=%02hhX", dst); src += 3; j += 3; } else { *dst = (char)*src++; j++; } } } *dst = '\0'; return dst_alen; }
没有评论:
发表评论