一、前言
二、修改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); }
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; }
2.注意key和sign要和你的AppDelegate中设置的key和sign一样:
LuaStack* stack = LuaEngine::getInstance()->getLuaStack(); stack->setXXTEAKeyAndSign(key,strlen(key),sign,strlen(sign));