mht文件解码,base64编码解码

本文介绍了一个Base64编码和解码的具体实现方法,包括如何将24位的三字节数据转换为四字节的Base64编码,并讨论了如何处理不同长度的数据输入。此外,还提供了一个完整的C++示例程序,该程序能够解析MHT文件中的Base64编码内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

////////////////////////////////////////////////////////////////////////////////////////
/*////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=
        {
            
0000
        };
        
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=
        {
            
0000
        };
        
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 + 12);
              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;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值