mht文件解码,base64编码解码

 

 

/// /
/* 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;
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值