(c++)常用的编解码函数 BASE64 URL UU Quoted-Printable

#include "scode.h"
#include <iostream>
Scode::Scode()
{
}
Scode::~Scode()
{
}
/*Uuencode编码*/
/* Uuencode的算法很简单,编码时它将3个字符顺序放入一个 24 位的缓冲区,
* 缺字符的地方补零,然后将缓冲区截断成为 4 个部分,高位在先,
* 每个部分 6 位,用下面的64个字符重新表示:
* "`!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_"
* 在文件的开头有“begin xxx 被编码的文件名”,在文件的结尾有“end”,
用来标志Uue文件的开始和结束。编码时,每次读取源文件的45个字符,
不足45个的用“0”补足为3的整数倍(如:23补为24),
然后输入目标文件一个ASCII为:“32+实际读取的字符数”的字符作为每一行的开始。
读取的字符编码后输入目标文件,再输入一个“换行符”。如果源文件被编码完了,
那么输入“`(ASCII为96)”和一个“换行符”表示编码结束。

解码时它将4个字符分别转换为4个6位字符后,截取有用的后六位放入一个 24 位的缓冲区,即得3个二进制代码。
*/
string Scode::Uu_encode(string src)
{
int len=src.size();
//cout<<len<<endl;
int iii=len%3;
char nul=0;
if(iii>0)
for(int ii=0;ii<(3-iii);ii++)src+=nul;//把串补足为3的整数倍
len=src.size();
//cout<<len<<endl;
int len2=len%45;
int len1=len-len2;
string dst;
if(len1>0)
for(int l=0;l<len/45;l++)
{
string tmp=src.substr(l*45,45);
dst+='M';
//cout<<dst<<endl;
char chasc[3];
char chuue[4];
for(int j=0;j<45;j+=3)
{
strcpy(chasc,tmp.substr(j,3).c_str());
//int i,k=2;
//char t=0;
chuue[0]=(chasc[0]&0xFF)>>2;
chuue[1]=(chasc[0]&0x03)<<4|((chasc[1]&0xf0)>>4);
chuue[2]=(chasc[1]&0x0F)<<2|((chasc[2]&0xc0)>>6);
chuue[3]=chasc[2]&0x3F;
for(int i=0;i<4;i++)
{
if(*(chuue+i)==0) *(chuue+i)+=96;
else
chuue[i]+=32;
dst+=chuue[i];

}
//cout<<chasc<<"/t"<<chuue<<endl;
}
dst+="/r/n";
//cout<<dst<<endl;
}
if(len2>0)
{
string tmp=src.substr(len1,len2);
//cout<<len1<<"/t"<<len2<<endl;
char aa=32+len2;
dst+=aa;
char chasc[3];
char chuue[4];
for(int j=0;j<len2;j+=3)
{
strcpy(chasc,tmp.substr(j,3).c_str());
chuue[0]=(chasc[0]&0xFF)>>2;
chuue[1]=(chasc[0]&0x03)<<4|((chasc[1]&0xf0)>>4);
chuue[2]=(chasc[1]&0x0F)<<2|((chasc[2]&0xc0)>>6);
chuue[3]=chasc[2]&0x3F;
for(int i=0;i<4;i++)
{
if(*(chuue+i)==0) *(chuue+i)+=96;
else
chuue[i]+=32;
dst+=chuue[i];
}

//dst+=chuue;
}
dst+="/r/n";
}
dst+="`/r/n";
//cout<<dst<<endl;
return dst;
}



/*Uuencode解码*/

string Scode::Uu_decode(string src)
{

string tmp;
for(int i=0;i<src.size();i++)
if((src[i]=='/n')||(src[i]=='/r')||(src[i]==' '))
;
else
tmp+=src[i];
//if(tmp[0]!='M')return "error";
int len=tmp.size();
int len2=len%61;
int len1=len-len2;
// cout<<len<<"/t"<<len1<<"/t"<<len2<<endl;
string dst;
if(len1>0)
{
for(int l=0;l<len/61;l++)
{
string tmp1=tmp.substr(l*61+1,60);
// cout<<tmp1<<endl;
//if((len2-1)%4!=0)return "error";
for(int j=0;j<60;j+=4)
{
char chuue[4];
char chasc[3];
strncpy(chuue,tmp1.substr(j,4).c_str(),4);
//cout<<chuue<<endl;
for(int k=0;k<4;k++)
{
if(chuue[k]==96) chuue[k]=0;
else chuue[k]-=32;
}
chasc[0]=(chuue[0]&0xFF)<<2|((chuue[1]>>4)&0x03);
chasc[1]=chuue[1]<<4|chuue[2]>>2;
chasc[2]=chuue[2]<<6|chuue[3];
for(int i=0;i<3;i++)
dst+=chasc[i];
//cout<<j<<endl;
}
// cout<<dst<<endl;
}
}
if(len2>0)
{
{
//if()
int aaa=(tmp[len1]-32)*4/3;
if(aaa>len2)return "error";
//cout<<tmp[len1]<<"/t"<<len1<<"/t"<<len2<<endl;
string tmp1=tmp.substr(len1+1,aaa);
//if((len2-2)%4!=0)return "error";
for(int j=0;j<aaa;j+=4)
{
char chuue[4];
char chasc[3];
strncpy(chuue,tmp1.substr(j,4).c_str(),4);
for(int i=0;i<4;i++)
{
if(chuue[i]==96) chuue[i]=0;
else chuue[i]-=32;
}
chasc[0]=(chuue[0]&0xFF)<<2|chuue[1]>>4;
chasc[1]=chuue[1]<<4|chuue[2]>>2;
chasc[2]=chuue[2]<<6|chuue[3];
for(int i=0;i<3;i++)
dst+=chasc[i];
}
}

}
dst+='/0';
return dst;
}

string Scode::Url_encode(string url)
{
int i = 0;
char c;
char temp[4];
string encoded_url;
if(url.size()>0) {
while (i != url.size()) {
c=url[i];
if( 'a' <= c && c <= 'z'
|| 'A' <= c && c <= 'Z'
|| '0' <= c && c <= '9'
|| c == '-' || c == '_' || c == '.'|| c=='/' )
encoded_url+=c;
else
{
sprintf(temp,"%%%X",c & 0xff);
encoded_url+=temp;
}
i++;
}
return encoded_url;
} else {

//return "";
}
}
string Scode::Url_decode(string url)
{
char c, c1, c2,tmp;
string dst;
int i=0;
while(i<url.size())
{
c=url[i];
if( c == '%' )
{
if(i<url.size()-2)
{
c1 = url[i+1];
c2 = url[i+2];
c1 = tolower(c1);
c2 = tolower(c2);
if( ! isxdigit(c1) || ! isxdigit(c2) ) continue;
tmp = ((c1>'9')?(c1-'a'+10):(c1-'0'))*16+((c2>'9')?(c2-'a'+10):(c2-'0'));
dst+=tmp;
i+=3;
}
} else if( c == '+' )
{
dst+=' ';
i++;
}
else
{
dst+=c;
i++;
}
}
dst+='/0';
return dst;

}

//Quoted-Printable也是MIME邮件中常用的编码方式之一。同Base64一样,
//它也将输入的字符串或数据编码成全是ASCII码的可打印字符串。

//Quoted-Printable编码的基本方法是:输入数据在33-6062-126范围内的,
//直接输出;其它的需编码为“=”加两个字节的HEX码(大写)。
//为保证输出行不超过规定长度,可在行尾加“=/r/n”序列作为软回车。

string Scode::Qp_encode(string src)
{
int line_len;
int max_line_len=62;
// 输出的行长度计数
line_len = 0;
char tmp[3];
string dst;
for (int i = 0; i < src.size(); i++)
{ // ASCII 33-60, 62-126原样输出,其余的需编码
if ((src[i] >= '!') && (src[i] <= '~') && (src[i] != '='))
{
dst+=src[i];
line_len++;
}
else
{
char c1 = 0x0F & (src[i] >> 4);
char c2 = 0x0F & src[i];

dst += '=';
dst += (c1 < 0xA) ? (c1 + 48):(c1 + 55);
dst += (c2 < 0xA) ? (c2 + 48):(c2 + 55);
line_len += 3;
} // 输出换行?
if (line_len >= max_line_len)
{
sprintf(tmp, "=/r/n");
dst+=tmp;
line_len = 0;
}
} // 输出加个结束符
dst += '/0';
return dst;
}

//Quoted-Printable解码很简单,将编码过程反过来就行了。

string Scode::Qp_decode(string src)
{
// 输出的字符计数
int i = 0;
string dst;
char tmp=0;
while (i < src.size())
{
if (src[i] == '=') // 是编码字节
{
if(i<src.size()-2)
{
char ch1=src[i+1];
char ch2=src[i+2];
if ((src[i+1]=='/r')||(src[i+1]=='/n')) continue;
tmp = ((ch1>'9')?(ch1-'A'+10):(ch1-'0'))*16+((ch2>'9')?(ch2-'A'+10):(ch2-'0'));
dst+=tmp;
i += 3;
}
}
else // 非编码字节
{
dst += src[i];
i++;
}

} // 输出加个结束符
dst += '/0';
return dst;
}
string Scode::Base64_encode(string in)
{
const char base64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const char base64_pad='=';
string out;
int inlen=in.size();
int inlen1,inlen2=inlen % 3;
inlen1=inlen-inlen2;
int i;
//cout<<inlen<<" "<<inlen1<<endl;
if(inlen1>0)
for (i=0; i<inlen1; i += 3)
{
out+= base64_table[(in[i] & 0xFF) >> 2];
//cout<<out<<endl;
//printf("%c/n",base64_table[in[i] >> 2]);

out+= base64_table[((in[i] & 0x3)<<4) | ((in[i+1]&0xF0) >> 4)];
out+= base64_table[((in[i+1] & 0xF)<<2) | ((in[i+2]&0xC0) >> 6)];
out+= base64_table[in[i+2] & 0x3f];
if(((i+3)%72)==0)
out+="/n";
}
if (inlen2>0)
{
unsigned char fragment;
out+= base64_table[(in[inlen1] & 0xFF) >> 2];
//cout<<inlen1<<out<<endl;
//printf("%c/n",base64_table[in[inlen1] >> 2]);

fragment = (in[inlen1] & 0x3)<<4;
if (inlen2 > 1)
fragment |= (in[inlen1+1] & 0xF0) >> 4;
out+= base64_table[fragment];
out+= (inlen2 < 2) ? base64_pad : base64_table[(in[inlen1+1] & 0xF)<<2];
out+= base64_pad;
}
out+= '/0';
return out;
}
string Scode::Base64_decode(string in)
{
const char base64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const char base64_pad='=';
string out;
int cur=0;
int ch, i = 0, j = 0, k;
char *chp;
/* run through the whole string, converting as we go */
while ((ch = in[cur++]) != '/0') {
if (ch == base64_pad) break;
chp = strchr(base64_table, ch);
if (chp == 0) continue;
ch = chp - base64_table;
//cout<<"ch "<<ch<<endl;
switch(i % 4) {
case 0:
out += ch << 2;
break;
case 1:
out[j++] |= ch >> 4;
out += (ch & 0x0f) << 4;
break;
case 2:
out[j++] |= ch >>2;
out+= (ch & 0x03) << 6;
break;
case 3:
out[j++] |= ch;
break;
}
i++;
}
k = j;
/* mop things up if we ended on a boundary */
if (ch == base64_pad) {
switch(i % 4) {
case 0:
case 1:
return 0;
case 2:
k++;
case 3:
{
char aa=0;
out+= aa;
k++;
}
}
}
out += '/0';
return out;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值