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

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

 

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

 

原理:

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

 

simple_handler.h:

#include "include/wrapper/cef_resource_manager.h"
class SimpleHandler : public CefClient,
                      public CefDisplayHandler,
                      public CefLifeSpanHandler,
                      public CefRequestHandler{

virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE { return this; }

  // CefRequestHandler methods:
  virtual cef_return_value_t OnBeforeResourceLoad(
	  CefRefPtr<CefBrowser> browser,
	  CefRefPtr<CefFrame> frame,
	  CefRefPtr<CefRequest> request,
	  CefRefPtr<CefRequestCallback> callback) OVERRIDE;
  virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
	  CefRefPtr<CefBrowser> browser,
	  CefRefPtr<CefFrame> frame,
	  CefRefPtr<CefRequest> request) OVERRIDE;

private:
  // Manages the registration and delivery of resources.
	CefRefPtr<CefResourceManager> resource_manager_;

simple_handler.cc:

#include "include/wrapper/cef_stream_resource_handler.h"


namespace {

SimpleHandler* g_instance = NULL;

}  // namespace



// Demonstrate a custom Provider implementation by dumping the request contents.
class RequestDumpResourceProvider : public CefResourceManager::Provider {
public:
	explicit RequestDumpResourceProvider(const std::string& url) : url_(url) {
		DCHECK(!url.empty());
	}

	bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE 
	{
		CEF_REQUIRE_IO_THREAD();

		const std::string& url = request->url();
		if (url != url_) 
		{
			// Not handled by this provider.
			return false;
		}

		//const std::string& dump = shared::DumpRequestContents(request->request());
		std::string str =
			//"<html><body bgcolor=\"white\"><pre>" + dump + "</pre></body></html>";
			"<html><body bgcolor=\"white\"><pre>123123123123</pre></body></html>";
		CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
			static_cast<void*>(const_cast<char*>(str.c_str())), str.size());
		DCHECK(stream.get());
		request->Continue(new CefStreamResourceHandler("text/html", stream));
		return true;
	}

private:
	std::string url_;

	DISALLOW_COPY_AND_ASSIGN(RequestDumpResourceProvider);
};

// Add example Providers to the CefResourceManager.
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager)
{
	if (!CefCurrentlyOn(TID_IO)) 
	{
		// Execute on the browser IO thread.
		CefPostTask(TID_IO, base::Bind(SetupResourceManager, resource_manager));
		return;
	}

	// Add the Provider for dumping request contents.
	resource_manager->AddProvider(
		new RequestDumpResourceProvider("http://www.baidu.com/"), 0,
		std::string());
}



SimpleHandler::SimpleHandler(bool use_views)
    : use_views_(use_views), is_closing_(false) {
  DCHECK(!g_instance);
  g_instance = this;

  //安装资源管理器
  resource_manager_ = new CefResourceManager();
  SetupResourceManager(resource_manager_);
}

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

 

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

simple_handler.h:

#include "include/wrapper/cef_resource_manager.h"

#pragma region 使用Zip管理类
#include "ResourcesManager/ZipFolder.h"
#pragma endregion


class SimpleHandler : public CefClient,
                      public CefDisplayHandler,
                      public CefLifeSpanHandler,
                      public CefRequestHandler{

virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE { return this; }

  // CefRequestHandler methods:
  virtual cef_return_value_t OnBeforeResourceLoad(
	  CefRefPtr<CefBrowser> browser,
	  CefRefPtr<CefFrame> frame,
	  CefRefPtr<CefRequest> request,
	  CefRefPtr<CefRequestCallback> callback) OVERRIDE;
  virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
	  CefRefPtr<CefBrowser> browser,
	  CefRefPtr<CefFrame> frame,
	  CefRefPtr<CefRequest> request) OVERRIDE;

private:
  // Manages the registration and delivery of resources.
	CefRefPtr<CefResourceManager> resource_manager_;
     ZipFolder m_zip;

simple_handler.cc:

#include "include/wrapper/cef_stream_resource_handler.h"


namespace {

SimpleHandler* g_instance = NULL;

}  // namespace



// Demonstrate a custom Provider implementation by dumping the request contents.
class RequestDumpResourceProvider : public CefResourceManager::Provider {
public:
	explicit RequestDumpResourceProvider(ZipFolder *pZip)
	{
		m_pZip = pZip;
	}

	//去除URL中的百分号%转码
	std::string UrlDecode(std::string &SRC)
	{
		std::string ret;
		char ch;
		int ii;
		for (size_t i = 0; i < SRC.length(); i++) {
			if (int(SRC[i]) == 37) {
				sscanf(SRC.substr(i + 1, 2).c_str(), "%x", &ii);
				ch = static_cast<char>(ii);
				ret += ch;
				i = i + 2;
			}
			else {
				ret += SRC[i];
			}
		}
		return (ret);
	}
	bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE 
	{
		CEF_REQUIRE_IO_THREAD();

		std::string url = request->url();
		//if (url != url_) 
		//{
		//	// Not handled by this provider.
		//	return false;
		//}

		url = UrlDecode(url); //去除百分号
		url = UTF8_To_string(url); //UTF8网址转回ANSI编码文本

		//把http://、https://和file:///去掉
		if (url.substr(0, 7) == "http://")
		{
			url.erase(0, 7);
		}
		else if (url.substr(0, 8) == "https://")
		{
			url.erase(0, 8);
		}
		else if (url.substr(0,8) == "file:///")
		{
			url.erase(0, 8);
		}

		string strMyPath2 = g_strMyPath;
		strMyPath2 = replace_all_distinct(strMyPath2, "\\", "/"); //把自身路径的\转成/

		url = replace_all_distinct(url, strMyPath2, "");

		//如果最后一个字符是/也去掉
		//if (url.substr(url.length()-1) == "/")
		//{
		//	url = url.substr(0, url.length() - 1);
		//}


		//在map资源图中寻找
		std::map<std::string, MyResourcesBuf*>::iterator it;
		it = m_pZip->m_mapResources.find(url);
		if (it == m_pZip->m_mapResources.end())
		{
			return false;
		}

		//const std::string& dump = shared::DumpRequestContents(request->request());
		//std::string str =
			//"<html><body bgcolor=\"white\"><pre>" + dump + "</pre></body></html>";
		//	"<html><body bgcolor=\"white\"><pre>123123123123</pre></body></html>";

		 
		CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(
			static_cast<void*>(it->second->lpBuf), it->second->nBufSize);
		DCHECK(stream.get());
		request->Continue(new CefStreamResourceHandler(it->second->lpType, stream));
		return true;
	}

private:
	ZipFolder *m_pZip;

	DISALLOW_COPY_AND_ASSIGN(RequestDumpResourceProvider);
};

// Add example Providers to the CefResourceManager.
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager)
{
	if (!CefCurrentlyOn(TID_IO)) 
	{
		// Execute on the browser IO thread.
		CefPostTask(TID_IO, base::Bind(SetupResourceManager, resource_manager));
		return;
	}

	// Add the Provider for dumping request contents.
	resource_manager->AddProvider(
		new RequestDumpResourceProvider(pZip), 0,
		std::string());
}



SimpleHandler::SimpleHandler(bool use_views)
    : use_views_(use_views), is_closing_(false) {
  DCHECK(!g_instance);
  g_instance = this;

  //从zip文件中加载H5资源
  std::string strMyZipFilePath = g_strMyPath + "native.ntpk"; //模仿PC网易云客户端
  m_zip.LoadZipToMem(strMyZipFilePath,false, "123",16); //解密zip

  resource_manager_ = new CefResourceManager();
  SetupResourceManager(resource_manager_, &m_zip);
  

}

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

#pragma once
#define WRITEBUFFERSIZE	16384
#include <iostream>
#include <map>


#pragma region 使用zlib库
#include "../../zlib/include/zlib.h"
#include "../../zlib/include/zip.h"
#include "../../zlib/include/unzip.h"

#ifdef _DEBUG
#pragma comment(lib,"zlib/lib/x86/Debug/zlib.lib")
#else
#pragma comment(lib,"zlib/lib/x86/Release/zlib.lib")
#endif
#pragma endregion


struct MyResourcesBuf
{
	void *lpBuf;
	int nBufSize;
	char *lpType; //资源类型
};

class ZipFolder  
{
public:
	ZipFolder();
	virtual ~ZipFolder();

public:
	
	//压缩文件夹
	bool Zip_Folder(
		std::string strFolder, //将要被压缩的文件夹路径
		std::string strZipFilePath, //将要生成的zip文件路径
		std::string strZipFileComment, //将要生成的zip文件注释,可以为NULL
		bool bWriteFolderChangeDate, //是否写入文件夹修改日期
		bool bWriteFileChangeDate); //是否写入文件夹里的文件修改日期


	
	//解压缩zip文件(支持多级文件夹)
	bool UnZip(
		std::string strZipFilePath, //将要被解压的zip文件路径
		std::string strExistingFolder); //解压文件存放的路径,路径必须存在

	//解压zip内容到内存
	std::map<std::string, MyResourcesBuf*> m_mapResources;
	bool LoadZipToMem(std::string strZipFilePath, //将要被解压读取的zip文件路径
		bool use3DES_ECB_Decrypt = false, //解压读取时是否使用3DES ECB模式解密
		char* lpsz3DES_ECB_KEY = NULL, //3DES_ECB模式的KEY
		int n3DES_ECB_KEY_LEN = 0); //3DES_ECB模式的KEY 长度

	

private:

	bool ExistFolder(char *lpszFolder);
	bool DetectFolderFile(char *szFolder);

	bool ZipTraversalFolder(
		zipFile zip,
		std::string strSourceFolder,
		std::string strInZipFolder,
		bool bWriteFolderChangeDate,
		bool bWriteFileChangeDate);

	int CreateDir(char *pszDir);

};

 

 

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

// ZipFolder.cpp: implementation of the ZipFolder class.
//
//

#include "ZipFolder.h"
#include <windows.h>

#include <time.h>
#include <utility>
#include <algorithm>

#pragma region 使用3DES库
#include "../../DES/DES.h"
#pragma endregion


//
// Construction/Destruction
//

ZipFolder::ZipFolder()
{

}

ZipFolder::~ZipFolder()
{

}

bool ZipFolder::Zip_Folder(
	std::string strFolder,
	std::string strZipFilePath,
	std::string strZipFileComment,
	bool bWriteFolderChangeDate,
	bool bWriteFileChangeDate)
{
	if (strFolder.substr(strFolder.length() - 1) != "\\")
	{
		//补上斜杠
		strFolder += "\\";
	}
	if (!ExistFolder((char*)strFolder.c_str()))
	{
		return false;
	}

	if (!DetectFolderFile((char*)strFolder.c_str()))
	{
		return FALSE;
	}

	zipFile zip = zipOpen(strZipFilePath.c_str(), APPEND_STATUS_CREATE);
	if (zip == NULL)
	{
		//如果zip文件已存在
		zip = zipOpen(strZipFilePath.c_str(), APPEND_STATUS_ADDINZIP);
		if (zip == NULL)
		{
			return false;
		}
	}

	bool bRet = ZipTraversalFolder(
		zip,
		strFolder,
		"",
		bWriteFolderChangeDate,
		bWriteFileChangeDate);

	zipClose(zip, strZipFileComment.c_str());
	return bRet;
}

bool ZipFolder::UnZip(
	std::string strZipFilePath,
	std::string strExistingFolder)
{
	if (strExistingFolder.substr(strExistingFolder.length() - 1) != "\\")
	{
		//补上斜杠
		strExistingFolder += "\\";
	}
	unzFile zip = unzOpen(strZipFilePath.c_str());
	if (zip == NULL)
	{
		return false;
	}
	unz_global_info	GlobalInfo;
	if (unzGetGlobalInfo(zip, &GlobalInfo) != UNZ_OK)
	{
		unzClose(zip);
		return false;
	}
	if (unzGoToFirstFile(zip) != UNZ_OK)
	{
		unzClose(zip);
		return false;
	}
	for (int i = 0; i < GlobalInfo.number_entry; i++)
	{
		unz_file_info FileInfo;
		char szFileName[MAX_PATH] = { 0 };
		char szExtraField[MAX_PATH] = { 0 };
		char szComment[MAX_PATH] = { 0 };
		if (unzGetCurrentFileInfo(zip, &FileInfo, szFileName, MAX_PATH, szExtraField, MAX_PATH, szComment, MAX_PATH) != UNZ_OK)
		{
			unzClose(zip);
			return FALSE;
		}
		// MessageBox(NULL,szFileName,"Zip中的文件名",0);

		if (std::string(szFileName).substr(std::string(szFileName).length() - 1) == "/")
		{
			//当zip里是目录的时候

			// MessageBox(NULL,szFileName,"经过处理的目录名",0);
			std::string strNewDir = strExistingFolder;
			strNewDir += szFileName;
			//MessageBox(NULL,szDirectory,"要创建的目录名",0);
			if (CreateDir((char*)strNewDir.c_str()) == -1)
			{
				unzClose(zip);
				return FALSE;
			}
		}
		else
		{

			std::string strNewFile = strExistingFolder;
			strNewFile += szFileName;
			//MessageBox(NULL,szNewFileName,"即将新建的文件名",0);

			if (unzOpenCurrentFile(zip) != UNZ_OK)
			{
				unzClose(zip);
				return FALSE;
			}
			HANDLE hNewFile = CreateFileA(strNewFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hNewFile == INVALID_HANDLE_VALUE)
			{
				unzCloseCurrentFile(zip);
				unzClose(zip);
				return FALSE;
			}
			LARGE_INTEGER lisize = { 0 };
			lisize.QuadPart = 0;
			lisize.LowPart = SetFilePointer(hNewFile, lisize.LowPart, &lisize.HighPart, FILE_BEGIN);
			if (lisize.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
			{
				unzCloseCurrentFile(zip);
				unzClose(zip);
				CloseHandle(hNewFile);
				return FALSE;
			}
			char szFileDataBuf[WRITEBUFFERSIZE];
			ULONGLONG uCycles = FileInfo.uncompressed_size / WRITEBUFFERSIZE;
			for (ULONGLONG i = 0; i <= uCycles; i++)
			{
				ZeroMemory(szFileDataBuf, WRITEBUFFERSIZE);
				int nRead = unzReadCurrentFile(zip, szFileDataBuf, WRITEBUFFERSIZE);
				if (nRead == 0)
				{
					break;
				}
				else if (nRead <= 0)
				{
					CloseHandle(hNewFile);
					unzCloseCurrentFile(zip);
					unzClose(zip);
					return FALSE;
				}
				DWORD dwWrite = 0;
				if (!WriteFile(hNewFile, szFileDataBuf, nRead, &dwWrite, NULL))
				{
					CloseHandle(hNewFile);
					unzCloseCurrentFile(zip);
					unzClose(zip);
					return FALSE;
				}
			}
			CloseHandle(hNewFile);
		}
		unzCloseCurrentFile(zip);
		unzGoToNextFile(zip);
	}
	unzClose(zip);
	return TRUE;
}


bool ZipFolder::LoadZipToMem(std::string strZipFilePath, 
	bool use3DES_ECB_Decrypt, char* lpsz3DES_ECB_KEY,int n3DES_ECB_KEY_LEN)
{
	unzFile zip = unzOpen(strZipFilePath.c_str());
	if (zip == NULL)
	{
		return false;
	}
	unz_global_info	GlobalInfo;
	if (unzGetGlobalInfo(zip, &GlobalInfo) != UNZ_OK)
	{
		unzClose(zip);
		return false;
	}
	if (unzGoToFirstFile(zip) != UNZ_OK)
	{
		unzClose(zip);
		return false;
	}
	for (int i = 0; i < GlobalInfo.number_entry; i++)
	{
		unz_file_info FileInfo;
		char szFileName[MAX_PATH] = { 0 };
		char szExtraField[MAX_PATH] = { 0 };
		char szComment[MAX_PATH] = { 0 };
		if (unzGetCurrentFileInfo(zip, &FileInfo, szFileName, MAX_PATH, szExtraField, MAX_PATH, szComment, MAX_PATH) != UNZ_OK)
		{
			unzClose(zip);
			return FALSE;
		}
		// MessageBox(NULL,szFileName,"Zip中的文件名",0);

		if (std::string(szFileName).substr(std::string(szFileName).length() - 1) == "/")
		{
			//当zip里是目录的时候

		}
		else
		{
			//MessageBox(NULL,szNewFileName,"即将新建的文件名",0);

			if (unzOpenCurrentFile(zip) != UNZ_OK)
			{
				unzClose(zip);
				return FALSE;
			}

			char *lpFileDataBuf = new char[FileInfo.uncompressed_size];
			memset(lpFileDataBuf, 0, FileInfo.uncompressed_size);
			unzReadCurrentFile(zip, lpFileDataBuf, FileInfo.uncompressed_size);


		

			//取后缀名
			std::string strEndName = szFileName;
			strEndName = strEndName.substr(strEndName.find_last_of("."));
			transform(strEndName.begin(), strEndName.end(), strEndName.begin(), tolower); //转小写


			MyResourcesBuf *pResBuf = new MyResourcesBuf;

			//如果需要使用3DES解密
			if ( (use3DES_ECB_Decrypt && lpsz3DES_ECB_KEY && n3DES_ECB_KEY_LEN) &&
				(
					strEndName == ".html" ||
					strEndName == ".js" ||
					strEndName == ".css"
					)
				)

			{
				//开始进行3DES解密

				char *lpDecrypt = new char[FileInfo.uncompressed_size];
				memset(lpDecrypt, 0, FileInfo.uncompressed_size);

				des3_ecb_decrypt((unsigned char*)lpDecrypt,
					(unsigned char*)lpFileDataBuf,
					FileInfo.uncompressed_size,
					(unsigned char*)lpsz3DES_ECB_KEY, 16);

				std::string strConvert = lpDecrypt; //利用string来截断最后的00

				delete lpDecrypt;
				delete lpFileDataBuf;


				lpFileDataBuf = new char[strConvert.length()]; //UTF8不能包含最后的00,不然Chrome会报错 好奇怪
				memcpy(lpFileDataBuf, strConvert.c_str(), strConvert.length());
			
				pResBuf->nBufSize = strConvert.length();
				
			}
			else
			{
				pResBuf->nBufSize = FileInfo.uncompressed_size;
			}
			pResBuf->lpBuf = lpFileDataBuf;
			


#pragma region 分配类型名
			std::string strType = "";
			if (strEndName == ".html")
			{
				strType = "text/html";
			}
			else 	if (strEndName == ".js")
			{
				strType = "application/javascript";
			}
			else 	if (strEndName == ".css")
			{
				strType = "text/css";
			}
			else 	if (strEndName == ".jpg" || strEndName == ".jpeg")
			{
				strType = "image/jpeg";
			}
			else 	if (strEndName == ".png")
			{
				strType = "image/png";
			}
			else 	if (strEndName == ".gif")
			{
				strType = "image/gif";
			}
			if (!strType.empty())
			{
				char*lpType = new char[strType.length() + 1];
				strcpy(lpType, strType.c_str());
				pResBuf->lpType = lpType;
			}
#pragma endregion



			m_mapResources.insert(std::pair<std::string, MyResourcesBuf*>(szFileName, pResBuf));

		}
		unzCloseCurrentFile(zip);
		unzGoToNextFile(zip);
	}
	unzClose(zip);
	return true;
}


bool ZipFolder::ZipTraversalFolder(
	zipFile zip,
	std::string strSourceFolder,
	std::string strInZipFolder,
	bool bWriteFolderChangeDate,
	bool bWriteFileChangeDate)
{

	std::string strFindPath = strSourceFolder;
	strFindPath += "*.*";

	WIN32_FIND_DATAA wfd = { 0 };
	HANDLE fhn = FindFirstFileA(strFindPath.c_str(), &wfd);
	if (fhn == INVALID_HANDLE_VALUE)
	{
		FindClose(fhn);
		return FALSE;
	}
	BOOL bRet = TRUE;
	while (bRet)
	{
		if (
			(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
			(lstrcmpA(".", wfd.cFileName) != 0) &&
			(lstrcmpA("..", wfd.cFileName) != 0))
		{
			//zip里的文件夹名

			std::string strNewZipDir = strInZipFolder;
			strNewZipDir += wfd.cFileName;
			strNewZipDir += "/";

			zip_fileinfo ZipFileInfo = { 0 };
			if (bWriteFolderChangeDate)
			{
				time_t CurTime = time(NULL);
				tm * mytime = localtime(&CurTime);
				ZipFileInfo.tmz_date.tm_hour = mytime->tm_hour;
				ZipFileInfo.tmz_date.tm_mday = mytime->tm_mday;
				ZipFileInfo.tmz_date.tm_min = mytime->tm_min;
				ZipFileInfo.tmz_date.tm_mon = mytime->tm_mon;
				ZipFileInfo.tmz_date.tm_sec = mytime->tm_sec;
				ZipFileInfo.tmz_date.tm_year = mytime->tm_year;
				ZipFileInfo.dosDate = 0;
			}

			if (zipOpenNewFileInZip(zip, strNewZipDir.c_str(), &ZipFileInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION) != UNZ_OK)
			{
				return FALSE;
			}
			zipCloseFileInZip(zip);

			std::string strNewSourceFolder = strSourceFolder;
			strNewSourceFolder += wfd.cFileName;
			strNewSourceFolder += "\\";
			ZipTraversalFolder(zip,
				strNewSourceFolder,
				strNewZipDir,
				bWriteFolderChangeDate,
				bWriteFileChangeDate);

		}
		else if (lstrcmpA(".", wfd.cFileName) != 0 && lstrcmpA("..", wfd.cFileName) != 0)
		{

			std::string strInZipFilePath = strInZipFolder;
			strInZipFilePath += wfd.cFileName;

			zip_fileinfo ZipFileInfo = { 0 };
			if (bWriteFileChangeDate)
			{
				time_t CurTime = time(NULL);
				tm * mytime = localtime(&CurTime);
				ZipFileInfo.tmz_date.tm_hour = mytime->tm_hour;
				ZipFileInfo.tmz_date.tm_mday = mytime->tm_mday;
				ZipFileInfo.tmz_date.tm_min = mytime->tm_min;
				ZipFileInfo.tmz_date.tm_mon = mytime->tm_mon;
				ZipFileInfo.tmz_date.tm_sec = mytime->tm_sec;
				ZipFileInfo.tmz_date.tm_year = mytime->tm_year;
				ZipFileInfo.dosDate = 0;
			}


			if (zipOpenNewFileInZip(zip, strInZipFilePath.c_str(), &ZipFileInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION) != UNZ_OK)
			{
				return FALSE;
			}

			std::string strLocalFile = strSourceFolder;
			strLocalFile += wfd.cFileName;
			// MessageBox(NULL,szDestinationFile,"硬盘中的文件名",0);

			HANDLE hDesFile = CreateFileA(strLocalFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hDesFile == INVALID_HANDLE_VALUE)
			{
				return FALSE;
			}
			LARGE_INTEGER lisize = { 0 };
			lisize.QuadPart = 0;
			lisize.LowPart = SetFilePointer(hDesFile, lisize.LowPart, &lisize.HighPart, FILE_BEGIN);
			if (lisize.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
			{
				return FALSE;
			}
			ULARGE_INTEGER ulisize = { 0 };
			ulisize.LowPart = GetFileSize(hDesFile, &ulisize.HighPart);
			if (ulisize.LowPart == INVALID_FILE_SIZE && (GetLastError()) != NO_ERROR)
			{
				return FALSE;
			}
			char szFileDataBuf[WRITEBUFFERSIZE];
			ULONGLONG uCycles = ulisize.QuadPart / WRITEBUFFERSIZE;
			for (ULONGLONG i = 0; i <= uCycles; i++)
			{
				ZeroMemory(szFileDataBuf, WRITEBUFFERSIZE);
				DWORD dwWrite = 0;
				if (!ReadFile(hDesFile, szFileDataBuf, WRITEBUFFERSIZE, &dwWrite, NULL))
				{
					//					CDatabase::ShowError(GetDesktopWindow());
					zipCloseFileInZip(zip);
					return FALSE;
				}
				zipWriteInFileInZip(zip, szFileDataBuf, dwWrite);

				if (dwWrite < WRITEBUFFERSIZE)
				{
					//MessageBox(NULL,"dwWrite<WRITEBUFFERSIZE","",0);
					break;
				}
			}
			zipCloseFileInZip(zip);
			CloseHandle(hDesFile);
			//MessageBox(NULL,"CloseHandle(hDestinationFile);","",0);
		}
		ZeroMemory(&wfd, sizeof(WIN32_FIND_DATAA));
		bRet = FindNextFileA(fhn, &wfd);
	}
	FindClose(fhn);
	return TRUE;
}

bool ZipFolder::DetectFolderFile(char *szFolder)
{
	char Path[MAX_PATH] = { 0 };
	lstrcpyA(Path, szFolder);
	lstrcatA(Path, "*.*");
	WIN32_FIND_DATAA wfd = { 0 };
	HANDLE fhn = FindFirstFileA(Path, &wfd);
	if (fhn == INVALID_HANDLE_VALUE)
	{
		FindClose(fhn);
		return false;
	}
	bool bRet = TRUE;
	while (bRet)
	{
		char TempName[MAX_PATH] = { 0 };
		if (
			(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
			(lstrcmpA(".", wfd.cFileName) != 0) &&
			(lstrcmpA("..", wfd.cFileName) != 0))
		{
			lstrcatA(TempName, szFolder);
			lstrcatA(TempName, wfd.cFileName);
			lstrcatA(TempName, "\\");
			DetectFolderFile(TempName);

		}
		else if (lstrcmpA(".", wfd.cFileName) != 0 && lstrcmpA("..", wfd.cFileName) != 0)
		{
			lstrcatA(TempName, szFolder);
			lstrcatA(TempName, wfd.cFileName);
			HANDLE hFile = CreateFileA(TempName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hFile == INVALID_HANDLE_VALUE)
			{
				FindClose(fhn);
				CloseHandle(hFile);
				return false;
			}
			CloseHandle(hFile);
		}
		ZeroMemory(&wfd, sizeof(WIN32_FIND_DATAA));
		bRet = FindNextFileA(fhn, &wfd);
	}
	FindClose(fhn);
	return true;
}

bool ZipFolder::ExistFolder(char *lpszFolder)
{
	DWORD ftyp = GetFileAttributesA(lpszFolder);
	if (ftyp == INVALID_FILE_ATTRIBUTES)
	{
		return false;  //something is wrong with your path!  
	}
	if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
	{
		return true;   // this is a directory!  
	}
	return false;    // this is not a directory!
}

#pragma region 创建多级目录

#ifdef WIN32  
#include <direct.h>  
#include <io.h>  
#elif LINUX  
#include <stdarg.h>  
#include <sys/stat.h>  
#endif
#ifdef WIN32
#define ACCESS _access  
#define MKDIR(a) _mkdir((a))  
#elif LINUX  
#define ACCESS access  
#define MKDIR(a) mkdir((a),0755)  
#endif  
int ZipFolder::CreateDir(char *pszDir)
{
	int i = 0;
	int iRet;
	int iLen = strlen(pszDir);
	//在末尾加/  
	if (pszDir[iLen - 1] != '\\'&&pszDir[iLen - 1] != '/')
	{
		pszDir[iLen] = '/';
		pszDir[iLen + 1] = '\0';
	}
	// 创建目录  
	for (i = 0; i <= iLen; i++)
	{
		if (pszDir[i] == '\\' || pszDir[i] == '/')
		{
			pszDir[i] = '\0';

			//如果不存在,创建  
			iRet = ACCESS(pszDir, 0);
			if (iRet != 0)
			{
				iRet = MKDIR(pszDir);
				if (iRet != 0)
				{
					return-1;
				}
			}
			//支持linux,将所有\换成/  
			pszDir[i] = '/';
		}
	}
	return 0;
}
#pragma endregion

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值