CEF3资源重定向、读取加密资源、读取zip资源

网上关于CEF3读取加密资源的中文资料特别少~,所以我就来写一篇教程吧

 

实际应用: PC版的“网易云音乐”就是把H5资源加密成zip文件,启动时动态读取。

原理:

让自己的MyClientHandler来继承 CefRequestHandler这个抽象类,然对其下面的纯虚函数进行重写

simple_handler.h:

  1.  
    #include "include/wrapper/cef_resource_manager.h"
  2.  
    class SimpleHandler : public CefClient,
  3.  
    public CefDisplayHandler,
  4.  
    public CefLifeSpanHandler,
  5.  
    public CefRequestHandler{
  6.  
     
  7.  
    virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE { return this; }
  8.  
     
  9.  
    // CefRequestHandler methods:
  10.  
    virtual cef_return_value_t OnBeforeResourceLoad(
  11.  
    CefRefPtr<CefBrowser> browser,
  12.  
    CefRefPtr<CefFrame> frame,
  13.  
    CefRefPtr<CefRequest> request,
  14.  
    CefRefPtr<CefRequestCallback> callback) OVERRIDE;
  15.  
    virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
  16.  
    CefRefPtr<CefBrowser> browser,
  17.  
    CefRefPtr<CefFrame> frame,
  18.  
    CefRefPtr<CefRequest> request) OVERRIDE;
  19.  
     
  20.  
    private:
  21.  
    // Manages the registration and delivery of resources.
  22.  
    CefRefPtr<CefResourceManager> resource_manager_;

simple_handler.cc:

  1.  
    #include "include/wrapper/cef_stream_resource_handler.h"
  2.  
     
  3.  
     
  4.  
    namespace {
  5.  
     
  6.  
    SimpleHandler* g_instance = NULL;
  7.  
     
  8.  
    } // namespace
  9.  
     
  10.  
     
  11.  
     
  12.  
    // Demonstrate a custom Provider implementation by dumping the request contents.
  13.  
    class RequestDumpResourceProvider : public CefResourceManager::Provider {
  14.  
    public:
  15.  
    explicit RequestDumpResourceProvider(const std::string& url) : url_(url) {
  16.  
    DCHECK(!url.empty());
  17.  
    }
  18.  
     
  19.  
    bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE
  20.  
    {
  21.  
    CEF_REQUIRE_IO_THREAD();
  22.  
     
  23.  
    const std::string& url = request->url();
  24.  
    if (url != url_)
  25.  
    {
  26.  
    // Not handled by this provider.
  27.  
    return false;
  28.  
    }
  29.  
     
  30.  
    //const std::string& dump = shared::DumpRequestContents(request->request());
  31.  
    std::string str =
  32.  
    //"<html><body bgcolor="white"><pre>" + dump + "</pre></body></html>";
  33.  
    "<html><body bgcolor="white"><pre>123123123123</pre></body></html>";
  34.  
    CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
  35.  
    static_cast<void*>(const_cast<char*>(str.c_str())), str.size());
  36.  
    DCHECK(stream.get());
  37.  
    request->Continue(new CefStreamResourceHandler("text/html", stream));
  38.  
    return true;
  39.  
    }
  40.  
     
  41.  
    private:
  42.  
    std::string url_;
  43.  
     
  44.  
    DISALLOW_COPY_AND_ASSIGN(RequestDumpResourceProvider);
  45.  
    };
  46.  
     
  47.  
    // Add example Providers to the CefResourceManager.
  48.  
    void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager)
  49.  
    {
  50.  
    if (!CefCurrentlyOn(TID_IO))
  51.  
    {
  52.  
    // Execute on the browser IO thread.
  53.  
    CefPostTask(TID_IO, base::Bind(SetupResourceManager, resource_manager));
  54.  
    return;
  55.  
    }
  56.  
     
  57.  
    // Add the Provider for dumping request contents.
  58.  
    resource_manager->AddProvider(
  59.  
    new RequestDumpResourceProvider("http://www.baidu.com/"), 0,
  60.  
    std::string());
  61.  
    }
  62.  
     
  63.  
     
  64.  
     
  65.  
    SimpleHandler::SimpleHandler(bool use_views)
  66.  
    : use_views_(use_views), is_closing_(false) {
  67.  
    DCHECK(!g_instance);
  68.  
    g_instance = this;
  69.  
     
  70.  
    //安装资源管理器
  71.  
    resource_manager_ = new CefResourceManager();
  72.  
    SetupResourceManager(resource_manager_);
  73.  
    }

至此,打开http://www.baidu.com,都会被拦截下来,显示123123123123 

实际应用- 带zip解压解密版:

simple_handler.h:

  1.  
    #include "include/wrapper/cef_resource_manager.h"
  2.  
     
  3.  
    #pragma region 使用Zip管理类
  4.  
    #include "ResourcesManager/ZipFolder.h"
  5.  
    #pragma endregion
  6.  
     
  7.  
     
  8.  
    class SimpleHandler : public CefClient,
  9.  
    public CefDisplayHandler,
  10.  
    public CefLifeSpanHandler,
  11.  
    public CefRequestHandler{
  12.  
     
  13.  
    virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE { return this; }
  14.  
     
  15.  
    // CefRequestHandler methods:
  16.  
    virtual cef_return_value_t OnBeforeResourceLoad(
  17.  
    CefRefPtr<CefBrowser> browser,
  18.  
    CefRefPtr<CefFrame> frame,
  19.  
    CefRefPtr<CefRequest> request,
  20.  
    CefRefPtr<CefRequestCallback> callback) OVERRIDE;
  21.  
    virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
  22.  
    CefRefPtr<CefBrowser> browser,
  23.  
    CefRefPtr<CefFrame> frame,
  24.  
    CefRefPtr<CefRequest> request) OVERRIDE;
  25.  
     
  26.  
    private:
  27.  
    // Manages the registration and delivery of resources.
  28.  
    CefRefPtr<CefResourceManager> resource_manager_;
  29.  
    ZipFolder m_zip;

simple_handler.cc:

  1.  
    #include "include/wrapper/cef_stream_resource_handler.h"
  2.  
     
  3.  
     
  4.  
    namespace {
  5.  
     
  6.  
    SimpleHandler* g_instance = NULL;
  7.  
     
  8.  
    } // namespace
  9.  
     
  10.  
     
  11.  
     
  12.  
    // Demonstrate a custom Provider implementation by dumping the request contents.
  13.  
    class RequestDumpResourceProvider : public CefResourceManager::Provider {
  14.  
    public:
  15.  
    explicit RequestDumpResourceProvider(ZipFolder *pZip)
  16.  
    {
  17.  
    m_pZip = pZip;
  18.  
    }
  19.  
     
  20.  
    //去除URL中的百分号%转码
  21.  
    std::string UrlDecode(std::string &SRC)
  22.  
    {
  23.  
    std::string ret;
  24.  
    char ch;
  25.  
    int ii;
  26.  
    for (size_t i = 0; i < SRC.length(); i++) {
  27.  
    if (int(SRC[i]) == 37) {
  28.  
    sscanf(SRC.substr(i + 1, 2).c_str(), "%x", &ii);
  29.  
    ch = static_cast<char>(ii);
  30.  
    ret += ch;
  31.  
    i = i + 2;
  32.  
    }
  33.  
    else {
  34.  
    ret += SRC[i];
  35.  
    }
  36.  
    }
  37.  
    return (ret);
  38.  
    }
  39.  
    bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE
  40.  
    {
  41.  
    CEF_REQUIRE_IO_THREAD();
  42.  
     
  43.  
    std::string url = request->url();
  44.  
    //if (url != url_)
  45.  
    //{
  46.  
    // // Not handled by this provider.
  47.  
    // return false;
  48.  
    //}
  49.  
     
  50.  
    url = UrlDecode(url); //去除百分号
  51.  
    url = UTF8_To_string(url); //UTF8网址转回ANSI编码文本
  52.  
     
  53.  
    //把http://、https://和file:///去掉
  54.  
    if (url.substr(0, 7) == "http://")
  55.  
    {
  56.  
    url.erase(0, 7);
  57.  
    }
  58.  
    else if (url.substr(0, 8) == "https://")
  59.  
    {
  60.  
    url.erase(0, 8);
  61.  
    }
  62.  
    else if (url.substr(0,8) == "file:///")
  63.  
    {
  64.  
    url.erase(0, 8);
  65.  
    }
  66.  
     
  67.  
    string strMyPath2 = g_strMyPath;
  68.  
    strMyPath2 = replace_all_distinct(strMyPath2, "\", "/"); //把自身路径的转成/
  69.  
     
  70.  
    url = replace_all_distinct(url, strMyPath2, "");
  71.  
     
  72.  
    //如果最后一个字符是/也去掉
  73.  
    //if (url.substr(url.length()-1) == "/")
  74.  
    //{
  75.  
    // url = url.substr(0, url.length() - 1);
  76.  
    //}
  77.  
     
  78.  
     
  79.  
    //在map资源图中寻找
  80.  
    std::map<std::string, MyResourcesBuf*>::iterator it;
  81.  
    it = m_pZip->m_mapResources.find(url);
  82.  
    if (it == m_pZip->m_mapResources.end())
  83.  
    {
  84.  
    return false;
  85.  
    }
  86.  
     
  87.  
    //const std::string& dump = shared::DumpRequestContents(request->request());
  88.  
    //std::string str =
  89.  
    //"<html><body bgcolor="white"><pre>" + dump + "</pre></body></html>";
  90.  
    // "<html><body bgcolor="white"><pre>123123123123</pre></body></html>";
  91.  
     
  92.  
     
  93.  
    CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
  94.  
    static_cast<void*>(it->second->lpBuf), it->second->nBufSize);
  95.  
    DCHECK(stream.get());
  96.  
    request->Continue(new CefStreamResourceHandler(it->second->lpType, stream));
  97.  
    return true;
  98.  
    }
  99.  
     
  100.  
    private:
  101.  
    ZipFolder *m_pZip;
  102.  
     
  103.  
    DISALLOW_COPY_AND_ASSIGN(RequestDumpResourceProvider);
  104.  
    };
  105.  
     
  106.  
    // Add example Providers to the CefResourceManager.
  107.  
    void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager)
  108.  
    {
  109.  
    if (!CefCurrentlyOn(TID_IO))
  110.  
    {
  111.  
    // Execute on the browser IO thread.
  112.  
    CefPostTask(TID_IO, base::Bind(SetupResourceManager, resource_manager));
  113.  
    return;
  114.  
    }
  115.  
     
  116.  
    // Add the Provider for dumping request contents.
  117.  
    resource_manager->AddProvider(
  118.  
    new RequestDumpResourceProvider(pZip), 0,
  119.  
    std::string());
  120.  
    }
  121.  
     
  122.  
     
  123.  
     
  124.  
    SimpleHandler::SimpleHandler(bool use_views)
  125.  
    : use_views_(use_views), is_closing_(false) {
  126.  
    DCHECK(!g_instance);
  127.  
    g_instance = this;
  128.  
     
  129.  
    //从zip文件中加载H5资源
  130.  
    std::string strMyZipFilePath = g_strMyPath + "native.ntpk"; //模仿PC网易云客户端
  131.  
    m_zip.LoadZipToMem(strMyZipFilePath,false, "123",16); //解密zip
  132.  
     
  133.  
    resource_manager_ = new CefResourceManager();
  134.  
    SetupResourceManager(resource_manager_, &m_zip);
  135.  
     
  136.  
     
  137.  
    }

 ZipFolder.h(注意,只能操作不带密码的zip压缩包,不要问我为什么,因为zlib不支持

  1.  
    #pragma once
  2.  
    #define WRITEBUFFERSIZE 16384
  3.  
    #include <iostream>
  4.  
    #include <map>
  5.  
     
  6.  
     
  7.  
    #pragma region 使用zlib库
  8.  
    #include "../../zlib/include/zlib.h"
  9.  
    #include "../../zlib/include/zip.h"
  10.  
    #include "../../zlib/include/unzip.h"
  11.  
     
  12.  
    #ifdef _DEBUG
  13.  
    #pragma comment(lib,"zlib/lib/x86/Debug/zlib.lib")
  14.  
    #else
  15.  
    #pragma comment(lib,"zlib/lib/x86/Release/zlib.lib")
  16.  
    #endif
  17.  
    #pragma endregion
  18.  
     
  19.  
     
  20.  
    struct MyResourcesBuf
  21.  
    {
  22.  
    void *lpBuf;
  23.  
    int nBufSize;
  24.  
    char *lpType; //资源类型
  25.  
    };
  26.  
     
  27.  
    class ZipFolder
  28.  
    {
  29.  
    public:
  30.  
    ZipFolder();
  31.  
    virtual ~ZipFolder();
  32.  
     
  33.  
    public:
  34.  
     
  35.  
    //压缩文件夹
  36.  
    bool Zip_Folder(
  37.  
    std::string strFolder, //将要被压缩的文件夹路径
  38.  
    std::string strZipFilePath, //将要生成的zip文件路径
  39.  
    std::string strZipFileComment, //将要生成的zip文件注释,可以为NULL
  40.  
    bool bWriteFolderChangeDate, //是否写入文件夹修改日期
  41.  
    bool bWriteFileChangeDate); //是否写入文件夹里的文件修改日期
  42.  
     
  43.  
     
  44.  
     
  45.  
    //解压缩zip文件(支持多级文件夹)
  46.  
    bool UnZip(
  47.  
    std::string strZipFilePath, //将要被解压的zip文件路径
  48.  
    std::string strExistingFolder); //解压文件存放的路径,路径必须存在
  49.  
     
  50.  
    //解压zip内容到内存
  51.  
    std::map<std::string, MyResourcesBuf*> m_mapResources;
  52.  
    bool LoadZipToMem(std::string strZipFilePath, //将要被解压读取的zip文件路径
  53.  
    bool use3DES_ECB_Decrypt = false, //解压读取时是否使用3DES ECB模式解密
  54.  
    char* lpsz3DES_ECB_KEY = NULL, //3DES_ECB模式的KEY
  55.  
    int n3DES_ECB_KEY_LEN = 0); //3DES_ECB模式的KEY 长度
  56.  
     
  57.  
     
  58.  
     
  59.  
    private:
  60.  
     
  61.  
    bool ExistFolder(char *lpszFolder);
  62.  
    bool DetectFolderFile(char *szFolder);
  63.  
     
  64.  
    bool ZipTraversalFolder(
  65.  
    zipFile zip,
  66.  
    std::string strSourceFolder,
  67.  
    std::string strInZipFolder,
  68.  
    bool bWriteFolderChangeDate,
  69.  
    bool bWriteFileChangeDate);
  70.  
     
  71.  
    int CreateDir(char *pszDir);
  72.  
     
  73.  
    };

 

ZipFolder.cpp (将zip解压读取到内存后,默认不进行任何解密操作,进行3DES解密部分的算法代码太长了就不粘贴了,屏蔽掉即可完美运行)

  1.  
    // ZipFolder.cpp: implementation of the ZipFolder class.
  2.  
    //
  3.  
    //////////////////////////////////////////////////////////////////////
  4.  
     
  5.  
    #include "ZipFolder.h"
  6.  
    #include <windows.h>
  7.  
     
  8.  
    #include <time.h>
  9.  
    #include <utility>
  10.  
    #include <algorithm>
  11.  
     
  12.  
    #pragma region 使用3DES库
  13.  
    #include "../../DES/DES.h"
  14.  
    #pragma endregion
  15.  
     
  16.  
     
  17.  
    //////////////////////////////////////////////////////////////////////
  18.  
    // Construction/Destruction
  19.  
    //////////////////////////////////////////////////////////////////////
  20.  
     
  21.  
    ZipFolder::ZipFolder()
  22.  
    {
  23.  
     
  24.  
    }
  25.  
     
  26.  
    ZipFolder::~ZipFolder()
  27.  
    {
  28.  
     
  29.  
    }
  30.  
     
  31.  
    bool ZipFolder::Zip_Folder(
  32.  
    std::string strFolder,
  33.  
    std::string strZipFilePath,
  34.  
    std::string strZipFileComment,
  35.  
    bool bWriteFolderChangeDate,
  36.  
    bool bWriteFileChangeDate)
  37.  
    {
  38.  
    if (strFolder.substr(strFolder.length() - 1) != "\")
  39.  
    {
  40.  
    //补上斜杠
  41.  
    strFolder += "\";
  42.  
    }
  43.  
    if (!ExistFolder((char*)strFolder.c_str()))
  44.  
    {
  45.  
    return false;
  46.  
    }
  47.  
     
  48.  
    if (!DetectFolderFile((char*)strFolder.c_str()))
  49.  
    {
  50.  
    return FALSE;
  51.  
    }
  52.  
     
  53.  
    zipFile zip = zipOpen(strZipFilePath.c_str(), APPEND_STATUS_CREATE);
  54.  
    if (zip == NULL)
  55.  
    {
  56.  
    //如果zip文件已存在
  57.  
    zip = zipOpen(strZipFilePath.c_str(), APPEND_STATUS_ADDINZIP);
  58.  
    if (zip == NULL)
  59.  
    {
  60.  
    return false;
  61.  
    }
  62.  
    }
  63.  
     
  64.  
    bool bRet = ZipTraversalFolder(
  65.  
    zip,
  66.  
    strFolder,
  67.  
    "",
  68.  
    bWriteFolderChangeDate,
  69.  
    bWriteFileChangeDate);
  70.  
     
  71.  
    zipClose(zip, strZipFileComment.c_str());
  72.  
    return bRet;
  73.  
    }
  74.  
     
  75.  
    bool ZipFolder::UnZip(
  76.  
    std::string strZipFilePath,
  77.  
    std::string strExistingFolder)
  78.  
    {
  79.  
    if (strExistingFolder.substr(strExistingFolder.length() - 1) != "\")
  80.  
    {
  81.  
    //补上斜杠
  82.  
    strExistingFolder += "\";
  83.  
    }
  84.  
    unzFile zip = unzOpen(strZipFilePath.c_str());
  85.  
    if (zip == NULL)
  86.  
    {
  87.  
    return false;
  88.  
    }
  89.  
    unz_global_info GlobalInfo;
  90.  
    if (unzGetGlobalInfo(zip, &GlobalInfo) != UNZ_OK)
  91.  
    {
  92.  
    unzClose(zip);
  93.  
    return false;
  94.  
    }
  95.  
    if (unzGoToFirstFile(zip) != UNZ_OK)
  96.  
    {
  97.  
    unzClose(zip);
  98.  
    return false;
  99.  
    }
  100.  
    for (int i = 0; i < GlobalInfo.number_entry; i++)
  101.  
    {
  102.  
    unz_file_info FileInfo;
  103.  
    char szFileName[MAX_PATH] = { 0 };
  104.  
    char szExtraField[MAX_PATH] = { 0 };
  105.  
    char szComment[MAX_PATH] = { 0 };
  106.  
    if (unzGetCurrentFileInfo(zip, &FileInfo, szFileName, MAX_PATH, szExtraField, MAX_PATH, szComment, MAX_PATH) != UNZ_OK)
  107.  
    {
  108.  
    unzClose(zip);
  109.  
    return FALSE;
  110.  
    }
  111.  
    // MessageBox(NULL,szFileName,"Zip中的文件名",0);
  112.  
     
  113.  
    if (std::string(szFileName).substr(std::string(szFileName).length() - 1) == "/")
  114.  
    {
  115.  
    //当zip里是目录的时候
  116.  
     
  117.  
    // MessageBox(NULL,szFileName,"经过处理的目录名",0);
  118.  
    std::string strNewDir = strExistingFolder;
  119.  
    strNewDir += szFileName;
  120.  
    //MessageBox(NULL,szDirectory,"要创建的目录名",0);
  121.  
    if (CreateDir((char*)strNewDir.c_str()) == -1)
  122.  
    {
  123.  
    unzClose(zip);
  124.  
    return FALSE;
  125.  
    }
  126.  
    }
  127.  
    else
  128.  
    {
  129.  
     
  130.  
    std::string strNewFile = strExistingFolder;
  131.  
    strNewFile += szFileName;
  132.  
    //MessageBox(NULL,szNewFileName,"即将新建的文件名",0);
  133.  
     
  134.  
    if (unzOpenCurrentFile(zip) != UNZ_OK)
  135.  
    {
  136.  
    unzClose(zip);
  137.  
    return FALSE;
  138.  
    }
  139.  
    HANDLE hNewFile = CreateFileA(strNewFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
  140.  
    if (hNewFile == INVALID_HANDLE_VALUE)
  141.  
    {
  142.  
    unzCloseCurrentFile(zip);
  143.  
    unzClose(zip);
  144.  
    return FALSE;
  145.  
    }
  146.  
    LARGE_INTEGER lisize = { 0 };
  147.  
    lisize.QuadPart = 0;
  148.  
    lisize.LowPart = SetFilePointer(hNewFile, lisize.LowPart, &lisize.HighPart, FILE_BEGIN);
  149.  
    if (lisize.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
  150.  
    {
  151.  
    unzCloseCurrentFile(zip);
  152.  
    unzClose(zip);
  153.  
    CloseHandle(hNewFile);
  154.  
    return FALSE;
  155.  
    }
  156.  
    char szFileDataBuf[WRITEBUFFERSIZE];
  157.  
    ULONGLONG uCycles = FileInfo.uncompressed_size / WRITEBUFFERSIZE;
  158.  
    for (ULONGLONG i = 0; i <= uCycles; i++)
  159.  
    {
  160.  
    ZeroMemory(szFileDataBuf, WRITEBUFFERSIZE);
  161.  
    int nRead = unzReadCurrentFile(zip, szFileDataBuf, WRITEBUFFERSIZE);
  162.  
    if (nRead == 0)
  163.  
    {
  164.  
    break;
  165.  
    }
  166.  
    else if (nRead <= 0)
  167.  
    {
  168.  
    CloseHandle(hNewFile);
  169.  
    unzCloseCurrentFile(zip);
  170.  
    unzClose(zip);
  171.  
    return FALSE;
  172.  
    }
  173.  
    DWORD dwWrite = 0;
  174.  
    if (!WriteFile(hNewFile, szFileDataBuf, nRead, &dwWrite, NULL))
  175.  
    {
  176.  
    CloseHandle(hNewFile);
  177.  
    unzCloseCurrentFile(zip);
  178.  
    unzClose(zip);
  179.  
    return FALSE;
  180.  
    }
  181.  
    }
  182.  
    CloseHandle(hNewFile);
  183.  
    }
  184.  
    unzCloseCurrentFile(zip);
  185.  
    unzGoToNextFile(zip);
  186.  
    }
  187.  
    unzClose(zip);
  188.  
    return TRUE;
  189.  
    }
  190.  
     
  191.  
     
  192.  
    bool ZipFolder::LoadZipToMem(std::string strZipFilePath,
  193.  
    bool use3DES_ECB_Decrypt, char* lpsz3DES_ECB_KEY,int n3DES_ECB_KEY_LEN)
  194.  
    {
  195.  
    unzFile zip = unzOpen(strZipFilePath.c_str());
  196.  
    if (zip == NULL)
  197.  
    {
  198.  
    return false;
  199.  
    }
  200.  
    unz_global_info GlobalInfo;
  201.  
    if (unzGetGlobalInfo(zip, &GlobalInfo) != UNZ_OK)
  202.  
    {
  203.  
    unzClose(zip);
  204.  
    return false;
  205.  
    }
  206.  
    if (unzGoToFirstFile(zip) != UNZ_OK)
  207.  
    {
  208.  
    unzClose(zip);
  209.  
    return false;
  210.  
    }
  211.  
    for (int i = 0; i < GlobalInfo.number_entry; i++)
  212.  
    {
  213.  
    unz_file_info FileInfo;
  214.  
    char szFileName[MAX_PATH] = { 0 };
  215.  
    char szExtraField[MAX_PATH] = { 0 };
  216.  
    char szComment[MAX_PATH] = { 0 };
  217.  
    if (unzGetCurrentFileInfo(zip, &FileInfo, szFileName, MAX_PATH, szExtraField, MAX_PATH, szComment, MAX_PATH) != UNZ_OK)
  218.  
    {
  219.  
    unzClose(zip);
  220.  
    return FALSE;
  221.  
    }
  222.  
    // MessageBox(NULL,szFileName,"Zip中的文件名",0);
  223.  
     
  224.  
    if (std::string(szFileName).substr(std::string(szFileName).length() - 1) == "/")
  225.  
    {
  226.  
    //当zip里是目录的时候
  227.  
     
  228.  
    }
  229.  
    else
  230.  
    {
  231.  
    //MessageBox(NULL,szNewFileName,"即将新建的文件名",0);
  232.  
     
  233.  
    if (unzOpenCurrentFile(zip) != UNZ_OK)
  234.  
    {
  235.  
    unzClose(zip);
  236.  
    return FALSE;
  237.  
    }
  238.  
     
  239.  
    char *lpFileDataBuf = new char[FileInfo.uncompressed_size];
  240.  
    memset(lpFileDataBuf, 0, FileInfo.uncompressed_size);
  241.  
    unzReadCurrentFile(zip, lpFileDataBuf, FileInfo.uncompressed_size);
  242.  
     
  243.  
     
  244.  
     
  245.  
     
  246.  
    //取后缀名
  247.  
    std::string strEndName = szFileName;
  248.  
    strEndName = strEndName.substr(strEndName.find_last_of("."));
  249.  
    transform(strEndName.begin(), strEndName.end(), strEndName.begin(), tolower); //转小写
  250.  
     
  251.  
     
  252.  
    MyResourcesBuf *pResBuf = new MyResourcesBuf;
  253.  
     
  254.  
    //如果需要使用3DES解密
  255.  
    if ( (use3DES_ECB_Decrypt && lpsz3DES_ECB_KEY && n3DES_ECB_KEY_LEN) &&
  256.  
    (
  257.  
    strEndName == ".html" ||
  258.  
    strEndName == ".js" ||
  259.  
    strEndName == ".css"
  260.  
    )
  261.  
    )
  262.  
     
  263.  
    {
  264.  
    //开始进行3DES解密
  265.  
     
  266.  
    char *lpDecrypt = new char[FileInfo.uncompressed_size];
  267.  
    memset(lpDecrypt, 0, FileInfo.uncompressed_size);
  268.  
     
  269.  
    des3_ecb_decrypt((unsigned char*)lpDecrypt,
  270.  
    (unsigned char*)lpFileDataBuf,
  271.  
    FileInfo.uncompressed_size,
  272.  
    (unsigned char*)lpsz3DES_ECB_KEY, 16);
  273.  
     
  274.  
    std::string strConvert = lpDecrypt; //利用string来截断最后的00
  275.  
     
  276.  
    delete lpDecrypt;
  277.  
    delete lpFileDataBuf;
  278.  
     
  279.  
     
  280.  
    lpFileDataBuf = new char[strConvert.length()]; //UTF8不能包含最后的00,不然Chrome会报错 好奇怪
  281.  
    memcpy(lpFileDataBuf, strConvert.c_str(), strConvert.length());
  282.  
     
  283.  
    pResBuf->nBufSize = strConvert.length();
  284.  
     
  285.  
    }
  286.  
    else
  287.  
    {
  288.  
    pResBuf->nBufSize = FileInfo.uncompressed_size;
  289.  
    }
  290.  
    pResBuf->lpBuf = lpFileDataBuf;
  291.  
     
  292.  
     
  293.  
     
  294.  
    #pragma region 分配类型名
  295.  
    std::string strType = "";
  296.  
    if (strEndName == ".html")
  297.  
    {
  298.  
    strType = "text/html";
  299.  
    }
  300.  
    else if (strEndName == ".js")
  301.  
    {
  302.  
    strType = "application/javascript";
  303.  
    }
  304.  
    else if (strEndName == ".css")
  305.  
    {
  306.  
    strType = "text/css";
  307.  
    }
  308.  
    else if (strEndName == ".jpg" || strEndName == ".jpeg")
  309.  
    {
  310.  
    strType = "image/jpeg";
  311.  
    }
  312.  
    else if (strEndName == ".png")
  313.  
    {
  314.  
    strType = "image/png";
  315.  
    }
  316.  
    else if (strEndName == ".gif")
  317.  
    {
  318.  
    strType = "image/gif";
  319.  
    }
  320.  
    if (!strType.empty())
  321.  
    {
  322.  
    char*lpType = new char[strType.length() + 1];
  323.  
    strcpy(lpType, strType.c_str());
  324.  
    pResBuf->lpType = lpType;
  325.  
    }
  326.  
    #pragma endregion
  327.  
     
  328.  
     
  329.  
     
  330.  
    m_mapResources.insert(std::pair<std::string, MyResourcesBuf*>(szFileName, pResBuf));
  331.  
     
  332.  
    }
  333.  
    unzCloseCurrentFile(zip);
  334.  
    unzGoToNextFile(zip);
  335.  
    }
  336.  
    unzClose(zip);
  337.  
    return true;
  338.  
    }
  339.  
     
  340.  
     
  341.  
    bool ZipFolder::ZipTraversalFolder(
  342.  
    zipFile zip,
  343.  
    std::string strSourceFolder,
  344.  
    std::string strInZipFolder,
  345.  
    bool bWriteFolderChangeDate,
  346.  
    bool bWriteFileChangeDate)
  347.  
    {
  348.  
     
  349.  
    std::string strFindPath = strSourceFolder;
  350.  
    strFindPath += "*.*";
  351.  
     
  352.  
    WIN32_FIND_DATAA wfd = { 0 };
  353.  
    HANDLE fhn = FindFirstFileA(strFindPath.c_str(), &wfd);
  354.  
    if (fhn == INVALID_HANDLE_VALUE)
  355.  
    {
  356.  
    FindClose(fhn);
  357.  
    return FALSE;
  358.  
    }
  359.  
    BOOL bRet = TRUE;
  360.  
    while (bRet)
  361.  
    {
  362.  
    if (
  363.  
    (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  364.  
    (lstrcmpA(".", wfd.cFileName) != 0) &&
  365.  
    (lstrcmpA("..", wfd.cFileName) != 0))
  366.  
    {
  367.  
    //zip里的文件夹名
  368.  
     
  369.  
    std::string strNewZipDir = strInZipFolder;
  370.  
    strNewZipDir += wfd.cFileName;
  371.  
    strNewZipDir += "/";
  372.  
     
  373.  
    zip_fileinfo ZipFileInfo = { 0 };
  374.  
    if (bWriteFolderChangeDate)
  375.  
    {
  376.  
    time_t CurTime = time(NULL);
  377.  
    tm * mytime = localtime(&CurTime);
  378.  
    ZipFileInfo.tmz_date.tm_hour = mytime->tm_hour;
  379.  
    ZipFileInfo.tmz_date.tm_mday = mytime->tm_mday;
  380.  
    ZipFileInfo.tmz_date.tm_min = mytime->tm_min;
  381.  
    ZipFileInfo.tmz_date.tm_mon = mytime->tm_mon;
  382.  
    ZipFileInfo.tmz_date.tm_sec = mytime->tm_sec;
  383.  
    ZipFileInfo.tmz_date.tm_year = mytime->tm_year;
  384.  
    ZipFileInfo.dosDate = 0;
  385.  
    }
  386.  
     
  387.  
    if (zipOpenNewFileInZip(zip, strNewZipDir.c_str(), &ZipFileInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION) != UNZ_OK)
  388.  
    {
  389.  
    return FALSE;
  390.  
    }
  391.  
    zipCloseFileInZip(zip);
  392.  
     
  393.  
    std::string strNewSourceFolder = strSourceFolder;
  394.  
    strNewSourceFolder += wfd.cFileName;
  395.  
    strNewSourceFolder += "\";
  396.  
    ZipTraversalFolder(zip,
  397.  
    strNewSourceFolder,
  398.  
    strNewZipDir,
  399.  
    bWriteFolderChangeDate,
  400.  
    bWriteFileChangeDate);
  401.  
     
  402.  
    }
  403.  
    else if (lstrcmpA(".", wfd.cFileName) != 0 && lstrcmpA("..", wfd.cFileName) != 0)
  404.  
    {
  405.  
     
  406.  
    std::string strInZipFilePath = strInZipFolder;
  407.  
    strInZipFilePath += wfd.cFileName;
  408.  
     
  409.  
    zip_fileinfo ZipFileInfo = { 0 };
  410.  
    if (bWriteFileChangeDate)
  411.  
    {
  412.  
    time_t CurTime = time(NULL);
  413.  
    tm * mytime = localtime(&CurTime);
  414.  
    ZipFileInfo.tmz_date.tm_hour = mytime->tm_hour;
  415.  
    ZipFileInfo.tmz_date.tm_mday = mytime->tm_mday;
  416.  
    ZipFileInfo.tmz_date.tm_min = mytime->tm_min;
  417.  
    ZipFileInfo.tmz_date.tm_mon = mytime->tm_mon;
  418.  
    ZipFileInfo.tmz_date.tm_sec = mytime->tm_sec;
  419.  
    ZipFileInfo.tmz_date.tm_year = mytime->tm_year;
  420.  
    ZipFileInfo.dosDate = 0;
  421.  
    }
  422.  
     
  423.  
     
  424.  
    if (zipOpenNewFileInZip(zip, strInZipFilePath.c_str(), &ZipFileInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION) != UNZ_OK)
  425.  
    {
  426.  
    return FALSE;
  427.  
    }
  428.  
     
  429.  
    std::string strLocalFile = strSourceFolder;
  430.  
    strLocalFile += wfd.cFileName;
  431.  
    // MessageBox(NULL,szDestinationFile,"硬盘中的文件名",0);
  432.  
     
  433.  
    HANDLE hDesFile = CreateFileA(strLocalFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  434.  
    if (hDesFile == INVALID_HANDLE_VALUE)
  435.  
    {
  436.  
    return FALSE;
  437.  
    }
  438.  
    LARGE_INTEGER lisize = { 0 };
  439.  
    lisize.QuadPart = 0;
  440.  
    lisize.LowPart = SetFilePointer(hDesFile, lisize.LowPart, &lisize.HighPart, FILE_BEGIN);
  441.  
    if (lisize.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
  442.  
    {
  443.  
    return FALSE;
  444.  
    }
  445.  
    ULARGE_INTEGER ulisize = { 0 };
  446.  
    ulisize.LowPart = GetFileSize(hDesFile, &ulisize.HighPart);
  447.  
    if (ulisize.LowPart == INVALID_FILE_SIZE && (GetLastError()) != NO_ERROR)
  448.  
    {
  449.  
    return FALSE;
  450.  
    }
  451.  
    char szFileDataBuf[WRITEBUFFERSIZE];
  452.  
    ULONGLONG uCycles = ulisize.QuadPart / WRITEBUFFERSIZE;
  453.  
    for (ULONGLONG i = 0; i <= uCycles; i++)
  454.  
    {
  455.  
    ZeroMemory(szFileDataBuf, WRITEBUFFERSIZE);
  456.  
    DWORD dwWrite = 0;
  457.  
    if (!ReadFile(hDesFile, szFileDataBuf, WRITEBUFFERSIZE, &dwWrite, NULL))
  458.  
    {
  459.  
    // CDatabase::ShowError(GetDesktopWindow());
  460.  
    zipCloseFileInZip(zip);
  461.  
    return FALSE;
  462.  
    }
  463.  
    zipWriteInFileInZip(zip, szFileDataBuf, dwWrite);
  464.  
     
  465.  
    if (dwWrite < WRITEBUFFERSIZE)
  466.  
    {
  467.  
    //MessageBox(NULL,"dwWrite<WRITEBUFFERSIZE","",0);
  468.  
    break;
  469.  
    }
  470.  
    }
  471.  
    zipCloseFileInZip(zip);
  472.  
    CloseHandle(hDesFile);
  473.  
    //MessageBox(NULL,"CloseHandle(hDestinationFile);","",0);
  474.  
    }
  475.  
    ZeroMemory(&wfd, sizeof(WIN32_FIND_DATAA));
  476.  
    bRet = FindNextFileA(fhn, &wfd);
  477.  
    }
  478.  
    FindClose(fhn);
  479.  
    return TRUE;
  480.  
    }
  481.  
     
  482.  
    bool ZipFolder::DetectFolderFile(char *szFolder)
  483.  
    {
  484.  
    char Path[MAX_PATH] = { 0 };
  485.  
    lstrcpyA(Path, szFolder);
  486.  
    lstrcatA(Path, "*.*");
  487.  
    WIN32_FIND_DATAA wfd = { 0 };
  488.  
    HANDLE fhn = FindFirstFileA(Path, &wfd);
  489.  
    if (fhn == INVALID_HANDLE_VALUE)
  490.  
    {
  491.  
    FindClose(fhn);
  492.  
    return false;
  493.  
    }
  494.  
    bool bRet = TRUE;
  495.  
    while (bRet)
  496.  
    {
  497.  
    char TempName[MAX_PATH] = { 0 };
  498.  
    if (
  499.  
    (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  500.  
    (lstrcmpA(".", wfd.cFileName) != 0) &&
  501.  
    (lstrcmpA("..", wfd.cFileName) != 0))
  502.  
    {
  503.  
    lstrcatA(TempName, szFolder);
  504.  
    lstrcatA(TempName, wfd.cFileName);
  505.  
    lstrcatA(TempName, "\");
  506.  
    DetectFolderFile(TempName);
  507.  
     
  508.  
    }
  509.  
    else if (lstrcmpA(".", wfd.cFileName) != 0 && lstrcmpA("..", wfd.cFileName) != 0)
  510.  
    {
  511.  
    lstrcatA(TempName, szFolder);
  512.  
    lstrcatA(TempName, wfd.cFileName);
  513.  
    HANDLE hFile = CreateFileA(TempName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  514.  
    if (hFile == INVALID_HANDLE_VALUE)
  515.  
    {
  516.  
    FindClose(fhn);
  517.  
    CloseHandle(hFile);
  518.  
    return false;
  519.  
    }
  520.  
    CloseHandle(hFile);
  521.  
    }
  522.  
    ZeroMemory(&wfd, sizeof(WIN32_FIND_DATAA));
  523.  
    bRet = FindNextFileA(fhn, &wfd);
  524.  
    }
  525.  
    FindClose(fhn);
  526.  
    return true;
  527.  
    }
  528.  
     
  529.  
    bool ZipFolder::ExistFolder(char *lpszFolder)
  530.  
    {
  531.  
    DWORD ftyp = GetFileAttributesA(lpszFolder);
  532.  
    if (ftyp == INVALID_FILE_ATTRIBUTES)
  533.  
    {
  534.  
    return false; //something is wrong with your path!
  535.  
    }
  536.  
    if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
  537.  
    {
  538.  
    return true; // this is a directory!
  539.  
    }
  540.  
    return false; // this is not a directory!
  541.  
    }
  542.  
     
  543.  
    #pragma region 创建多级目录
  544.  
     
  545.  
    #ifdef WIN32
  546.  
    #include <direct.h>
  547.  
    #include <io.h>
  548.  
    #elif LINUX
  549.  
    #include <stdarg.h>
  550.  
    #include <sys/stat.h>
  551.  
    #endif
  552.  
    #ifdef WIN32
  553.  
    #define ACCESS _access
  554.  
    #define MKDIR(a) _mkdir((a))
  555.  
    #elif LINUX
  556.  
    #define ACCESS access
  557.  
    #define MKDIR(a) mkdir((a),0755)
  558.  
    #endif
  559.  
    int ZipFolder::CreateDir(char *pszDir)
  560.  
    {
  561.  
    int i = 0;
  562.  
    int iRet;
  563.  
    int iLen = strlen(pszDir);
  564.  
    //在末尾加/
  565.  
    if (pszDir[iLen - 1] != '\'&&pszDir[iLen - 1] != '/')
  566.  
    {
  567.  
    pszDir[iLen] = '/';
  568.  
    pszDir[iLen + 1] = '';
  569.  
    }
  570.  
    // 创建目录
  571.  
    for (i = 0; i <= iLen; i++)
  572.  
    {
  573.  
    if (pszDir[i] == '\' || pszDir[i] == '/')
  574.  
    {
  575.  
    pszDir[i] = '';
  576.  
     
  577.  
    //如果不存在,创建
  578.  
    iRet = ACCESS(pszDir, 0);
  579.  
    if (iRet != 0)
  580.  
    {
  581.  
    iRet = MKDIR(pszDir);
  582.  
    if (iRet != 0)
  583.  
    {
  584.  
    return-1;
  585.  
    }
  586.  
    }
  587.  
    //支持linux,将所有换成/
  588.  
    pszDir[i] = '/';
  589.  
    }
  590.  
    }
  591.  
    return 0;
  592.  
    }
  593.  
    #pragma endregion
  594.  
原文地址:https://www.cnblogs.com/h2zZhou/p/12502229.html