cocos2dx的源代码中已经添加了base64的算法,就在base文件夹下,有base64.h和base64.cpp
在int _base64Decode(const unsigned char *input,unsigned int input_len,unsigned char *output,unsigned int *output_len )函数中return之前加上这么一句:
output[output_idx] = '\0';
我也是不太懂为什么官方自带的char*操作函数里连个结束符都不加= =
首先所有的set系列函数最终都调用了setValueForKey,所以加密只用修改这个函数就可以了:
static void setValueForKey(const char* pKey,const char* pValue) { char* pEncodeValue = 0; base64Encode((const unsigned char*)pValue,strlen(pValue),&pEncodeValue); tinyxml2::XMLElement* rootNode; tinyxml2::XMLDocument* doc; tinyxml2::XMLElement* node; // check the params if (! pKey || ! pValue) { return; } // find the node node = getXMLNodeForKey(pKey,&rootNode,&doc); // if node exist,change the content if (node) { if (node->FirstChild()) { node->FirstChild()->SetValue(pEncodeValue); } else { tinyxml2::XMLText* content = doc->NewText(pEncodeValue); node->LinkEndChild(content); } } else { if (rootNode) { tinyxml2::XMLElement* tmpNode = doc->NewElement(pKey);//new tinyxml2::XMLElement(pKey); rootNode->LinkEndChild(tmpNode); tinyxml2::XMLText* content = doc->NewText(pEncodeValue);//new tinyxml2::XMLText(pValue); tmpNode->LinkEndChild(content); } } // save file and free doc if (doc) { doc->SaveFile(FileUtils::getInstance()->getSuitableFOpen(UserDefault::getInstance()->getXMLFilePath()).c_str()); delete doc; } }
这里只加密了pValue,pKey不加密是因为经过base加密后的字符串结尾都会有'=',但xml中标签里等号是特殊字符,所以直接加密pKey会导致xml文件的损坏。
一个解决方法是在代码中把所有的key映射成另外的名字,比如全部映射成"Data01"、"Data02"……这样
其次是解密,由于get系列函数并没有调用一个共同的getValue函数,所以需要修改所有的get函数,但修改内容是一样的,所以只示范一个:
bool UserDefault::getBoolForKey(const char* pKey,bool defaultValue) { const char* value = nullptr; tinyxml2::XMLElement* rootNode; tinyxml2::XMLDocument* doc; tinyxml2::XMLElement* node; node = getXMLNodeForKey(pKey,&doc); // find the node if (node && node->FirstChild()) { value = (const char*)(node->FirstChild()->Value()); } bool ret = defaultValue; if (value) { unsigned char* pDecodeValue = 0; base64Decode((const unsigned char*)value,strlen(value),&pDecodeValue); ret = (! strcmp((const char*)pDecodeValue,"true")); } if (doc) delete doc; return ret; }
这样,CCUserDefault的简单加密解密就完成了,重新编译工程,测试你的代码,就可以看到UserDefault.xml文件中已经存储了加密信息,同时读取也不会有什么问题。
最后是一点吐槽,UserDefault顾名思义应该是存储一些用户设置之类的数据,大概是因为这样所以官方尽管引入了base64算法却没有给它加上,我真的很想知道为什么cocos2dx没有专门的管理游戏存档的类= =