一、前言
1.我将要给大家分享的是XXTEA加密方式,对图片资源进行加密。
2.需要工具:quick-lua中已经集成图片加密工具,但是我没有用quick,所以单独把这个加密文件夹拎出来了。点击下载加密工具。
http://pan.baidu.com/s/1pLyI6NL
二、修改CCFileUtils.h和cpp文件
1.找到frameworks\cocos2d-x\cocos\platform\CCFileUtils.h,添加一个结构体ResEncryptData:
class CC_DLL FileUtils
{
public:
//=====添加代码
static struct ResEncryptData{
ResEncryptData(){
allowNoEncrpt = true;
key = "key123456";
sign = "sign520";
}
std::string key;
std::string sign;
bool allowNoEncrpt;
}encryptData;
static unsigned char* decryptBuffer(unsigned char* buf,unsigned long size,unsigned long *newSize);
//=====添加结束
/**
* Gets the instance of FileUtils.
*/
static FileUtils* getInstance();
/**
* Destroys the instance of FileUtils.
*/
static void destroyInstance();2.
找到
frameworks\cocos2d-x\cocos\platform\
CCFileUtils.cpp,添加对应的实现代码:
//头文件声明=====
#include "xxtea/xxtea.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#include "xxtea/xxtea.cpp"
#endif
unsigned char* FileUtils::decryptBuffer(unsigned char* buf,unsigned long *newSize){
unsigned char *m_xxteaKey = (unsigned char *)FileUtils::encryptData.key.c_str();
unsigned char *m_xxteaSign = (unsigned char *)FileUtils::encryptData.sign.c_str();
xxtea_long m_xxteaSignLen = FileUtils::encryptData.sign.length();
xxtea_long m_xxteaKeyLen = FileUtils::encryptData.key.length();
if (NULL==buf) return NULL;
unsigned char* buffer = NULL;
bool isXXTEA = true;
for (unsigned int i = 0; isXXTEA && i < m_xxteaSignLen && i < size; ++i)
{
if(buf[i] != m_xxteaSign[i]){
isXXTEA = false;
break;
}
}
if(m_xxteaSignLen == 0){
isXXTEA = false;
}
if (isXXTEA)
{
// decrypt XXTEA
xxtea_long len = 0;
buffer = xxtea_decrypt(buf + m_xxteaSignLen,(xxtea_long)size - (xxtea_long)m_xxteaSignLen,(unsigned char*)m_xxteaKey,(xxtea_long)m_xxteaKeyLen,&len);
delete []buf;
buf = NULL;
size = len;
}
else
{
if(FileUtils::getInstance()->encryptData.allowNoEncrpt)
{buffer = buf;}
}
*newSize = size;
return buffer;
}
3.在上面那个文件中: frameworks\cocos2d-x\cocos\platform\ CCFileUtils.cpp,修改getData函数:
static Data getData(const std::string& filename,bool forString)
{
if (filename.empty())
{
return Data::Null;
}
Data ret;
unsigned char* buffer = nullptr;
size_t size = 0;
size_t readsize;
const char* mode = nullptr;
if (forString)
mode = "rt";
else
mode = "rb";
do
{
// Read the file from hardware
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
FILE *fp = fopen(fullPath.c_str(),mode);
CC_BREAK_IF(!fp);
fseek(fp,SEEK_END);
size = ftell(fp);
fseek(fp,SEEK_SET);
if (forString)
{
buffer = (unsigned char*)malloc(sizeof(unsigned char) * (size + 1));
buffer[size] = '\0';
}
else
{
buffer = (unsigned char*)malloc(sizeof(unsigned char) * size);
}
readsize = fread(buffer,sizeof(unsigned char),size,fp);
fclose(fp);
if (forString && readsize < size)
{
buffer[readsize] = '\0';
}
} while (0);
if (nullptr == buffer || 0 == readsize)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") Failed!");
cclOG("%s",msg.c_str());
}
else
{
//ret.fastSet(buffer,readsize);
//======新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(buffer,readsize,&newSize);
ret.fastSet(newBuffer,newSize);
}
4.在上面那个文件中:frameworks\cocos2d-x\cocos\platform\CCFileUtils.cpp,修改getFileData函数:
unsigned char* FileUtils::getFileData(const std::string& filename,const char* mode,ssize_t *size)
{
unsigned char * buffer = nullptr;
CCASSERT(!filename.empty() && size != nullptr && mode != nullptr,"Invalid parameters.");
*size = 0;
do
{
// read the file from hardware
const std::string fullPath = fullPathForFilename(filename);
FILE *fp = fopen(fullPath.c_str(),mode);
CC_BREAK_IF(!fp);
fseek(fp,SEEK_END);
*size = ftell(fp);
fseek(fp,SEEK_SET);
buffer = (unsigned char*)malloc(*size);
*size = fread(buffer,*size,fp);
fclose(fp);
} while (0);
if (!buffer)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") Failed!");
cclOG("%s",msg.c_str());
}else{
//新的改动=========
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(buffer,&newSize);
*size = newSize;
buffer = newBuffer;
}
return buffer;
}
三、修改CCFileUtils-win32.cpp文件
1.找到 frameworks\cocos2d-x\cocos\platform\win32\ CCFileUtils-win32.cpp,添加对应的代码:static Data getData(const std::string& filename,bool forString)
{
if (filename.empty())
{
return Data::Null;
}
unsigned char *buffer = nullptr;
size_t size = 0;
do
{
// read the file from hardware
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
WCHAR wszBuf[CC_MAX_PATH] = {0};
MultiBytetoWideChar(CP_UTF8,fullPath.c_str(),-1,wszBuf,sizeof(wszBuf)/sizeof(wszBuf[0]));
HANDLE fileHandle = ::CreateFileW(wszBuf,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,nullptr);
CC_BREAK_IF(fileHandle == INVALID_HANDLE_VALUE);
size = ::GetFileSize(fileHandle,nullptr);
if (forString)
{
buffer = (unsigned char*) malloc(size + 1);
buffer[size] = '\0';
}
else
{
buffer = (unsigned char*) malloc(size);
}
DWORD sizeRead = 0;
BOOL successed = FALSE;
successed = ::ReadFile(fileHandle,buffer,&sizeRead,nullptr);
::CloseHandle(fileHandle);
if (!successed)
{
// should determine buffer value,or it will cause memory leak
if (buffer)
{
free(buffer);
buffer = nullptr;
}
}
} while (0);
Data ret;
if (buffer == nullptr || size == 0)
{
std::string msg = "Get data from file(";
// Gets error code.
DWORD errorCode = ::GetLastError();
char errorCodeBuffer[20] = {0};
snprintf(errorCodeBuffer,sizeof(errorCodeBuffer),"%d",errorCode);
msg = msg + filename + ") Failed,error code is " + errorCodeBuffer;
cclOG("%s",msg.c_str());
if (buffer)
free(buffer);
}
else
{
//新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(buffer,&newSize);
//ret.fastSet(buffer,size);
ret.fastSet(newBuffer,newSize);
}
return ret;
}
unsigned char* FileUtilsWin32::getFileData(const std::string& filename,ssize_t* size)
{
unsigned char * pBuffer = nullptr;
*size = 0;
do
{
// read the file from hardware
std::string fullPath = fullPathForFilename(filename);
WCHAR wszBuf[CC_MAX_PATH] = {0};
MultiBytetoWideChar(CP_UTF8,nullptr);
CC_BREAK_IF(fileHandle == INVALID_HANDLE_VALUE);
*size = ::GetFileSize(fileHandle,nullptr);
pBuffer = (unsigned char*) malloc(*size);
DWORD sizeRead = 0;
BOOL successed = FALSE;
successed = ::ReadFile(fileHandle,pBuffer,nullptr);
::CloseHandle(fileHandle);
if (!successed)
{
free(pBuffer);
pBuffer = nullptr;
}
} while (0);
if (! pBuffer)
{
std::string msg = "Get data from file(";
// Gets error code.
DWORD errorCode = ::GetLastError();
char errorCodeBuffer[20] = {0};
snprintf(errorCodeBuffer,msg.c_str());
}else{
//新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(pBuffer,&newSize);
*size = newSize;
pBuffer = newBuffer;
}
return pBuffer;
}
四、修改CCFileUtils-android.cpp文件
1.找到 frameworks\cocos2d-x\cocos\platform\android\ CCFileUtils-android.cpp,添加对应的代码:Data FileUtilsAndroid::getData(const std::string& filename,bool forString)
{
if (filename.empty())
{
return Data::Null;
}
unsigned char* data = nullptr;
ssize_t size = 0;
string fullPath = fullPathForFilename(filename);
cocosplay::updateAssets(fullPath);
if (fullPath[0] != '/')
{
string relativePath = string();
size_t position = fullPath.find("assets/");
if (0 == position) {
// "assets/" is at the beginning of the path and we don't want it
relativePath += fullPath.substr(strlen("assets/"));
} else {
relativePath += fullPath;
}
cclOGINFO("relative path = %s",relativePath.c_str());
if (nullptr == FileUtilsAndroid::assetmanager) {
LOGD("... FileUtilsAndroid::assetmanager is nullptr");
return Data::Null;
}
// read asset data
AAsset* asset =
AAssetManager_open(FileUtilsAndroid::assetmanager,relativePath.c_str(),AASSET_MODE_UNKNowN);
if (nullptr == asset) {
LOGD("asset is nullptr");
return Data::Null;
}
off_t fileSize = AAsset_getLength(asset);
if (forString)
{
data = (unsigned char*) malloc(fileSize + 1);
data[fileSize] = '\0';
}
else
{
data = (unsigned char*) malloc(fileSize);
}
int bytesread = AAsset_read(asset,(void*)data,fileSize);
size = bytesread;
AAsset_close(asset);
}
else
{
do
{
// read rrom other path than user set it
//cclOG("GETTING FILE ABSOLUTE DATA: %s",filename);
const char* mode = nullptr;
if (forString)
mode = "rt";
else
mode = "rb";
FILE *fp = fopen(fullPath.c_str(),mode);
CC_BREAK_IF(!fp);
long fileSize;
fseek(fp,SEEK_END);
fileSize = ftell(fp);
fseek(fp,SEEK_SET);
if (forString)
{
data = (unsigned char*) malloc(fileSize + 1);
data[fileSize] = '\0';
}
else
{
data = (unsigned char*) malloc(fileSize);
}
fileSize = fread(data,fileSize,fp);
fclose(fp);
size = fileSize;
} while (0);
}
Data ret;
if (data == nullptr || size == 0)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") Failed!");
cclOG("%s",msg.c_str());
}
else
{
//新的改动==========
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(data,&newSize);
// ret.fastSet(data,newSize);
cocosplay::notifyFileLoaded(fullPath);
}
return ret;
}
unsigned char* FileUtilsAndroid::getFileData(const std::string& filename,ssize_t * size)
{
unsigned char * data = 0;
if ( filename.empty() || (! mode) )
{
return 0;
}
string fullPath = fullPathForFilename(filename);
cocosplay::updateAssets(fullPath);
if (fullPath[0] != '/')
{
string relativePath = string();
size_t position = fullPath.find("assets/");
if (0 == position) {
// "assets/" is at the beginning of the path and we don't want it
relativePath += fullPath.substr(strlen("assets/"));
} else {
relativePath += fullPath;
}
LOGD("relative path = %s",relativePath.c_str());
if (nullptr == FileUtilsAndroid::assetmanager) {
LOGD("... FileUtilsAndroid::assetmanager is nullptr");
return nullptr;
}
// read asset data
AAsset* asset =
AAssetManager_open(FileUtilsAndroid::assetmanager,AASSET_MODE_UNKNowN);
if (nullptr == asset) {
LOGD("asset is nullptr");
return nullptr;
}
off_t fileSize = AAsset_getLength(asset);
data = (unsigned char*) malloc(fileSize);
int bytesread = AAsset_read(asset,fileSize);
if (size)
{
*size = bytesread;
}
AAsset_close(asset);
}
else
{
do
{
// read rrom other path than user set it
//cclOG("GETTING FILE ABSOLUTE DATA: %s",filename);
FILE *fp = fopen(fullPath.c_str(),SEEK_SET);
data = (unsigned char*) malloc(fileSize);
fileSize = fread(data,fp);
fclose(fp);
if (size)
{
*size = fileSize;
}
} while (0);
}
if (! data)
{
std::string msg = "Get data from file(";
msg.append(filename).append(") Failed!");
cclOG("%s",msg.c_str());
}
else
{
//新的改动
unsigned long newSize = 0;
unsigned char *newBuffer = FileUtils::decryptBuffer(data,&newSize);
*size = newSize;
data = newBuffer;
cocosplay::notifyFileLoaded(fullPath);
}
return data;
}
五、修改CCFileUtils-apple.mm文件
1.找到 frameworks\cocos2d-x\cocos\platform\apple\ CCFileUtils-apple.cpp,修改对应的代码:getValueMapFromFile。以便读取plist文件,是因为ios读取plist文件方式和android和win32不同。ValueMap FileUtilsApple::getValueMapFromFile(const std::string& filename)
{
//====新的改动
std::string fullPath = fullPathForFilename(filename);
Data d = FileUtils::getDataFromFile(filename);
unsigned long fileSize = d.getSize();
unsigned char* pFileData = d.getBytes();
NSData *data = [[[NSData alloc] initWithBytes:pFileData length:fileSize] autorelease];
nspropertyListFormat format;
Nsstring *error;
NSMutableDictionary *dict = (NSMutableDictionary *)[
nspropertyListSerialization propertyListFromData:data
mutabilityOption:nspropertyListMutableContainersAndLeaves
format:&format
errorDescription:&error];
//====改动结束
//std::string fullPath = fullPathForFilename(filename);
//Nsstring* path = [Nsstring stringWithUTF8String:fullPath.c_str()];
//NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:path];
ValueMap ret;
if (dict != nil)
{
for (id key in [dict allKeys])
{
id value = [dict objectForKey:key];
addValuetoDict(key,value,ret);
}
}
return ret;
}
六、大功告成!
1.重新编译c++代码,把res文件夹替换成加密后的文件夹,即可正常运行。
2.注意key和sign要和你的AppDelegate中设置的key和sign一样:
LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); stack->setXXTEAKeyAndSign(key,strlen(key),sign,strlen(sign));