mht文件解码,base64编码解码
2006-07-03 12:58
751 查看
////////////////////////////////////////////////////////////////////////////////////////
/*////demht.cpp DEV-CPP4.9 gcc下通过
base64编码,将3字节,24位数据,每6位一取(0-63范围),组成4字节数据,查表得到映射符号。
如果无3字节,添加映射为‘='
base64解码,将4字节符号取出,查表得到相应4字节数据,重组运算为3字节数据。 */
/*MHT文件大体结构,以"----XXXXXXX"分割为许多部分
编码分为base64和普通文本两种格式。用CBase64类解码出。
其普通文本中,非字符全部用字节=HEX码表示,解码时hex2c反解出来。 网上有很多Base64例子都不能正常执行,所以自己写了个。写得有些乱,没有优化过:P*/
////////////////////////////////////////////////////////////////////////////////////////
#include <cstdlib>
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
typedef vector < unsigned char > BufArray;
char hex2c(char hex[2])
{
char *table = "0123456789ABCDEF";
int hi = 0;
int low = 0;
while (table[hi] != hex[0])
{
hi++;
};
while (table[low] != hex[1])
{
low++;
};
char ret = (char)((hi << 4) | low);
return ret;
};
class CBase64
{
char *baseTable;
public:
CBase64()
{
baseTable =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghzijklmnopqrstuvwxyz0123456789+/=";
};
~CBase64()
{
};
private:
void encode(unsigned char in[3], unsigned char out[4], int valid)
{
int pc[4] =
{
0, 0, 0, 0
};
int zero = 0;
if (valid == 3)
{
pc[0] = (in[0] >> 2) &0x3f;
pc[1] = ((in[0] << 4) | (in[1] >> 4)) &0x3f;
pc[2] = ((in[1] << 2) | (in[2] >> 6)) &0x3f;
pc[3] = in[2] &0x3f;
}
else if (valid == 2)
{
pc[0] = (in[0] >> 2) &0x3f;
pc[1] = ((in[0] << 4) | (in[1] >> 4)) &0x3f;
pc[2] = ((in[1] << 2) | (zero >> 6)) &0x3f;
pc[3] = 64;
}
else if (valid == 1)
{
pc[0] = (in[0] >> 2) &0x3f;
pc[1] = ((in[0] << 4) | (zero >> 4)) &0x3f;
pc[2] = 64;
pc[3] = 64;
};
out[0] = baseTable[pc[0]];
out[1] = baseTable[pc[1]];
out[2] = baseTable[pc[2]];
out[3] = baseTable[pc[3]];
};
int decode(unsigned char in[4], unsigned char out[3])
{
int ret;
if (in[2] == '=')
{
ret = 1;
}
else if (in[3] == '=')
{
ret = 2;
}
else
{
ret = 3;
};
int pc[4] =
{
0, 0, 0, 0
};
if (ret == 3)
{
pc[0] = getpos(in[0]);
pc[1] = getpos(in[1]);
pc[2] = getpos(in[2]);
pc[3] = getpos(in[3]);
}
else if (ret == 2)
{
pc[0] = getpos(in[0]);
pc[1] = getpos(in[1]);
pc[2] = getpos(in[2]);
}
else
{
pc[0] = getpos(in[0]);
pc[1] = getpos(in[1]);
};
out[0] = ((pc[0] << 2) | (pc[1] >> 4));
out[1] = ((pc[1] << 4) | (pc[2] >> 2));
out[2] = ((pc[2] << 6) | pc[3]);
return ret;
};
int getpos(unsigned char c)
{
int ret = 0;
while (c != baseTable[ret])
{
ret++;
};
return ret;
};
public:
//基本编码方法,注意使用后测试out并delete
int bin2base64(unsigned char *data, int len, unsigned char * &out)
{
int baselen;
int cycle;
if (len % 3 == 0)
{
baselen = len / 3 * 4;
cycle = len / 3;
}
else
{
baselen = (len / 3+1) *4;
cycle = (len / 3+1);
};
if (baselen != 0)
{
out = new unsigned char[baselen + 1];
int offd = 0;
int offo = 0;
for (int i = 0; i < cycle - 1; i++, offd += 3, offo += 4)
{
encode((data + offd), (out + offo), 3);
};
if (len % 3)
{
encode((data + offd), (out + offo), len % 3);
}
else
{
encode((data + offd), (out + offo), 3);
};
};
return baselen;
};
//基本解码方法,注意使用后测试out并delete
int base642bin(unsigned char *data, int len, unsigned char * &out)
{
//必然为4的倍数否则是有错的。
if (len % 4 != 0)
{
cout << "Error Base64 Code's Len" << endl;
return 0;
};
int binlen = 0;
int cycle = len / 4;
out = new unsigned char[cycle *3];
int offb = 0;
int offo = 0;
int n;
for (int i = 0; i < cycle; i++, offo += 3, offb += 4)
{
n = decode((data + offb), (out + offo));
binlen += n;
};
return binlen;
};
//编码文件
void Base64(const char *infile, const char *outfile)
{
ifstream inf(infile, ios::in | ios::binary);
if (inf.fail())
{
cout << "Error Open infile" << endl;
exit(1);
};
ofstream outf(outfile, ios::out);
if (outf.fail())
{
cout << "Error Open outfile" << endl;
exit(1);
};
BufArray buf;
char c[1];
while (!inf.eof())
{
inf.read(c, 1); //测试一下很有必要!
if (inf.good())
{
buf.push_back(c[0]);
}
};
int size = buf.size();
if (size)
{
unsigned char *bindata = new unsigned char[size];
for (int i = 0; i < size; i++)
{
bindata[i] = buf[i];
};
unsigned char *strout = 0;
int strlen = bin2base64(bindata, size, strout);
char *ms =
"Content-Type: .../... Content-Transfer-Encoding: base64 Content-Location: ... ";
char *rets = " ";
outf.write(ms, 79);
int linesize = 72;
int off = 0;
while (strlen >= linesize)
{
strlen -= linesize;
outf.write((const char*)strout + off, linesize);
outf.write(rets, 1);
off += linesize;
};
outf.write((const char*)strout + off, strlen);
outf.write(rets, 1);
if (strout)
{
delete []strout;
}
delete []bindata;
};
inf.close();
outf.close();
};
//解码文件
void GetFile(const char *infile, const char *outfile)
{
ifstream inf(infile, ios::in);
if (inf.fail())
{
cout << "Error Open infile" << endl;
exit(1);
};
ofstream outf(outfile, ios::out | ios::binary);
if (outf.fail())
{
cout << "Error Open outfile" << outfile << endl;
exit(1);
};
const int size = 1024 * 8;
char str[size];
int *pstart = (int*) &str[0];
*pstart = 0;
string s = "";
string temp;
while (!inf.eof())
{
inf.getline(str, size);
temp = str;
if (temp != "")
{
if (temp.find("-") != temp.npos){}
else
{
s += temp;
};
};
};
if (s != "")
{
unsigned char *outb = 0;
int len = base642bin((unsigned char*)s.c_str(), s.length(), outb);
if (len > 0)
{
outf.write((const char*)outb, len);
}
if (outb)
{
delete []outb;
}
}
else
{
cout << "some error in infile" << endl;
inf.close();
outf.close();
exit(1);
};
inf.close();
outf.close();
};
};
int main(int argc, char *argv[])
{
if (argc == 2)
{
if (argv[1][0] == '-' || argv[1][0] == '/')
{
goto USEAGE;
}
ifstream inf(argv[1], ios::in);
if (inf.fail())
{
cout << "不能打开文件" << argv[1] << endl;
exit(1);
};
const int linelen = 1024 * 32;
char *buf = new char[linelen];
string basemark = "Content-Transfer-Encoding: base64";
string basefilemark = "Content-Location: file:///";
string filemark = "Content-Location: file://";
string httpmark = "Content-Location: http://";
string tempfile = "C:/tmp.b64";
string partmark = "---";
string filetowrite = "";
string strbuf = "";
string strtemp = "";
bool basestart = false;
bool normalstart = false;
//按行处理,直至文件结束。
while (!inf.eof())
{
inf.getline(buf, linelen); //收集一行数据
if (inf.good())
{
strtemp = buf;
}
if (strtemp != "")
{
if (!basestart && !normalstart)
{
if (strtemp.find(basemark) != strtemp.npos)
{
basestart = true;
cout << "base64start" << endl;
};
if (!normalstart)
{
if (strtemp.find(filemark) != strtemp.npos || strtemp.find(httpmark)
!= strtemp.npos)
{
cout << "normalstart" << endl;
//分析写出解码文件地址
if (strtemp.find(basefilemark) != strtemp.npos)
{
filetowrite = strtemp.substr(basefilemark.length(),
(strtemp.length() - basefilemark.length()));
while (filetowrite.find("/") != filetowrite.npos)
{
filetowrite.replace(filetowrite.find("/"), 1, "/");
};
}
else if (strtemp.find(httpmark) != strtemp.npos)
{
filetowrite = strtemp.substr(httpmark.length(), (strtemp.length
() - httpmark.length()));
filetowrite = "C:/demht/" + filetowrite;
while (filetowrite.find("/") != filetowrite.npos)
{
filetowrite.replace(filetowrite.find("/"), 1, "/");
};
filetowrite = filetowrite.substr(0, filetowrite.find_first_of(
"?"));
}
else
{
filetowrite = strtemp.substr(filemark.length(), (strtemp.length
() - filemark.length()));
};
normalstart = true;
inf.getline(buf, linelen);
inf.getline(buf, linelen);
//直接取得正文第一行
strtemp = buf;
};
};
};
};
if (basestart)
//在Base64编码的解码处理内。
{
if (filetowrite == "")
{
if (strtemp.find(filemark) != strtemp.npos || strtemp.find(httpmark)
!= strtemp.npos)
{
//分析写出解码文件地址
if (strtemp.find(basefilemark) != strtemp.npos)
{
filetowrite = strtemp.substr(basefilemark.length(),
(strtemp.length() - basefilemark.length()));
while (filetowrite.find("/") != filetowrite.npos)
{
filetowrite.replace(filetowrite.find("/"), 1, "/");
};
}
else if (strtemp.find(httpmark) != strtemp.npos)
{
filetowrite = strtemp.substr(httpmark.length(), (strtemp.length()
- httpmark.length()));
filetowrite = "C:/demht/" + filetowrite;
while (filetowrite.find("/") != filetowrite.npos)
{
filetowrite.replace(filetowrite.find("/"), 1, "/");
};
filetowrite = filetowrite.substr(0, filetowrite.find_first_of("?")
);
}
else
{
filetowrite = strtemp.substr(filemark.length(), (strtemp.length()
- filemark.length()));
};
};
};
if (strtemp.find(partmark) != strtemp.npos)
{
//处理完毕一部分数据收集。开始写入。
string dir = filetowrite.substr(0, filetowrite.find_last_of("/"));
string cmddir = "if not exist " + dir + " md " + dir;
system(cmddir.c_str());
ofstream outf(tempfile.c_str(), ios::out);
//写入临时文件
outf.write(strbuf.c_str(), strbuf.length());
outf.close();
//通过CBase64类,得到解码文件。
CBase64 a;
cout << "write=>" << filetowrite << endl;
a.GetFile((char*)tempfile.c_str(), filetowrite.c_str());
cout << "base64end" << endl;
basestart = false;
strbuf = "";
filetowrite = "";
}
else
{
strbuf += strtemp + " ";
};
}
else if (normalstart)
//在普通文本处理内
{
if (strtemp.find(partmark) != strtemp.npos)
{
//处理完毕一部分开始写入
string dir = filetowrite.substr(0, filetowrite.find_last_of("/"));
string cmddir = "if not exist " + dir + " md " + dir;
system(cmddir.c_str());
ofstream outf;
cout << "write=>" << filetowrite << endl;
outf.open(filetowrite.c_str(), ios::out);
if (outf.fail())
{
cout << "error! out normalfile" << filetowrite << endl;
exit(1);
};
outf.write(strbuf.c_str(), strbuf.length());
outf.close();
cout << "normalend" << endl;
normalstart = false;
strbuf = "";
filetowrite = "";
}
else
{
if (strtemp != "")
{
bool cat = false; //最后一个为'='表示连接不换行
if (strtemp.at(strtemp.length() - 1) == '=')
{
strtemp = strtemp.substr(0, strtemp.length() - 1);
cat = true;
}
else
{
cat = false;
}; //处理一些=号输出代码。
int epos = strtemp.find_first_of("=");
while (epos != strtemp.npos)
{
string realc;
string hexs = strtemp.substr(epos + 1, 2);
realc = hex2c((char*)hexs.c_str());
strtemp = strtemp.replace(epos, 3, realc);
epos = strtemp.find_first_of("=", epos + 1);
};
if (!cat)
{
strbuf += strtemp + " ";
}
else
{
strbuf += strtemp;
}
strtemp = "";
}
else
{
strbuf += " ";
};
};
};
};
inf.close();
delete []buf;
system("if exist c:/tmp.b64 del c:/tmp.b64");
}
else
//处理命令的其他情况
{
USEAGE: cout << "MHT文件解码工具,作者苏晓 2006年7月 ";
cout << "使用方法: ";
cout << argv[0] << " <mhtfile> " << endl;
cout << " 注意事项:生成文件依据 Content-Location: ";
cout << " 如果是file://不变 如果是http://映射生成到C:/demht/下" << endl;
};
//system("PAUSE");
return EXIT_SUCCESS;
};
相关文章推荐
- java利用Base64编码和解码图片文件
- (java)利用BASE64编码和解码图片文件
- [置顶] Python语言处理整个文件的base64编码解码源码共享
- 编码文件为Base64编码形式和解码Base64编码文件
- (java)利用BASE64编码和解码图片文件
- java使用Base64编码和解码的图像文件
- java利用Base64编码和解码图片文件
- Python 和 VBScript 对文件编码-解码的方式 (Hex, Base64) 的疑问
- java利用Base64编码和解码图片文件
- Swift base64编码解码
- base64格式的编码与解码
- Base64编码解码与实现
- Base64 编码 解码
- Base64实现编码、解码原理
- 在 Java 中如何进行 BASE64 编码和解码
- Java如何进行Base64的编码(Encode)与解码(Decode)?
- OPENSSL Base64编码和解码
- JS实现base64编码与解码
- 【C#】图片的Base64编码和解码
- Symbian平台下Base64编码及解码