您的位置:首页 > 移动开发 > IOS开发

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;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息