QP加密编码解码

来源:互联网 发布:Mac下载慢 编辑:程序博客网 时间:2024/05/19 00:09

      QP(Quoted-Printable)也是MIME邮件中常用的编码方式之一。同Base64 一样,它也将输入的字符串或数据编码成全是ASCII码的可打印字符串。Quoted-Printable编码的基本方法是:输入数据在 33-60、62-126范围内的,直接输出;其它的需编码为"="加两个字节的HEX码(大写)。为保证输出行不超过规定长度,可在行尾加"=/r/n"序列作为软回车。

 

QP编码规则如下:
    规则1:除了换行符,其它任何8位长度的字节必须被表示成一个"="号加上高四位的十六进制数
            和低四位的十六进制数,十六进制数是用"0123456789ABCDEF"的ASCII字符码表示,其中"ABCDEF"都必须是大写;
    规则2:当8位长度的字节值在33至60(包括33和60),62至126(包括62和126)之间时,直接用该数据对应的ASCII码来表示;
    规则3:当8位长度的字节值是9和32时,用该数据对应的ASCII码(9:TAB(HT),32:SPACE)来表示,
            但若是出现在行尾则必须按规则1进行转换;
    规则4:对于CRLF换行符必须用"=0D=0A"来代替;
    规则5:QP编码每行不得超过76个字符(不包含最后的"/r/n"两个字符),否则必须换行,
            换行方法是:在结尾处加上"=/r/n"
      其它:符号"-"不用进行QP编码,所以不要用"-"符号来表示实体之间的分界,
            最好用"=_"来代替,对于"!"#$[/]^'{|}~"这些字符必须按规则1进行转换.

参考代码如下(C++代码)

#include <string.h>
#include <stdio.h>
#include <string>

using namespace std;
// 字符转换为Hex
string Char2Hex(unsigned char cVal)
{
    string strTemp;
    unsigned char cTempBuf1[10] = {0};
    unsigned char cTempBuf2[10] = {0};
    sprintf_s((char*)cTempBuf1, 10 * sizeof(unsigned char), "%02X", cVal);

    cTempBuf2[0] = toupper(cTempBuf1[0]);
    cTempBuf2[1] = toupper(cTempBuf1[1]);
    cTempBuf2[2] = '/0';
    strTemp = (char*)cTempBuf2;

    return strTemp;
}

 

// QP编码

bool QPEnCoding(string& aStr, bool &IsChanged)
{
    IsChanged = false;
    int length = (int)aStr.size();//.length();
    if (length <= 0)
    {
        return false;
    }

    unsigned char *c_copy = new unsigned char[length +1];
    strcpy_s((char*)c_copy, (length +1) * sizeof(unsigned char), aStr.c_str());
    aStr.clear();

    int nLineLen = 0;
    for (int i = 0; i < length; i++)
    {
        // c_copy[i] 介于 33 到 126 之间, 且c_copy[i]的值不为'='的时候, 直接输出
        if ((c_copy[i] >= '!') && (c_copy[i] <= '~') && (c_copy[i] != '='))
        {
            aStr += (char)c_copy[i];
            nLineLen ++;
        }
        // 其它的需编码为'='加两个字节的HEX码(大写)
        else
        {
            aStr  += "=";
            aStr  += Char2Hex(c_copy[i]);
            nLineLen += 3;
            IsChanged = true;
        }

        // 保证输出行不超过规定长度, 可在行尾加"=/r/n"序列作为软回车
        if (nLineLen >= 73)
        {
            aStr += "=/r/n";
            nLineLen = 0;
        }
    }

    // 释放内存
    delete[] c_copy;
    c_copy = NULL;

    return true;
}

// QP解码

bool QPDeCoding(string& aStr, bool &IsChanged)
{
    // 输出的字符计数
    IsChanged  = false;
    int nSrcLen = (int)aStr.size();
    if (nSrcLen <= 0)
    {
        return false;
    }

    unsigned char* pcTemp1 = 0;
    unsigned char* pDst = new unsigned char[nSrcLen +1];
    memset(pDst, 0, nSrcLen +1);
    pcTemp1 = pDst;

    char* pcTemp2 = 0;
    char* pSrc = new char[nSrcLen +1];
    strcpy_s((char*)pSrc, (nSrcLen + 1) * sizeof(char), aStr.c_str());
    aStr.clear();
    pcTemp2 = pSrc;

    int i = 0;
    while (i < nSrcLen)
    {
        // 软回车,跳过
        if (strncmp(pSrc, "=/r/n", 3) == 0)
        {
            pSrc += 3;
            i += 3;
        }
        else
        {
            // 是编码字节
            if (*pSrc == '=')
            {
                sscanf_s(pSrc, "=%02X", pDst++);
                pSrc += 3;
                i += 3;
                IsChanged = true;
            }
            // 非编码字节
            else
            {
                *pDst++ = (unsigned char)*pSrc++;
                i ++;
            }
        }
    }

    // 输出加个结束符
    pDst = '/0';
    aStr = (char*)pcTemp1;

    delete[] pcTemp1;
    pcTemp1 = 0;

    delete[] pcTemp2;
    pcTemp2 = 0;

    return true;
}

原创粉丝点击