编码规则如下:
- 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;
}
没有评论:
发表评论