int main(int argc, char** argv) { if (argc<2) { printf("ERROR: sdpk2/sdmd2 path required\n"); return 1; } const char* path=argv[1]; size_t len=strlen(path); if (strncmp((path+len)-5, "sdmd2", 5)==0) { SDMD2 table(path); if (table.load()) { table.printInfo(); } else { return 1; } } else if (strncmp((path+len)-5, "sdpk2", 5)==0) { SDPK2 pak(path); if (pak.open()) { //pak.printInfo(0, true); if (argc>2) { __hash_str_ptr=argv[2]; if (argc>3) { path=argv[3]; } else { path=argv[2]; } MD5Hash hash; if (strncmp(__hash_str_ptr, "-a", 2)==0) { __hash_str_ptr=__hash_str; if (strncmp(path, "-a", 2)==0) { path="dump/"; } const EntryVec& entries=pak.getEntries(); for (size_t i=0; i<entries.size(); ++i) { entries[i].hash().getExisting(__hash_str, false); dump_entry(pak, entries[i], path, __hash_str_ptr); } } else if (hash.set(__hash_str_ptr)) { const Entry* entry=pak.findEntry(hash); if (entry) { dump_entry(pak, *entry, "dump/", path); } else { printf("Entry [%s] not found\n", __hash_str_ptr); return 1; } } else { printf("Malformed hash\n"); return 1; } } pak.close(); } else { return 1; } } else { printf("File extension not recognized\n"); } return 0; }
string path_files_md5_hash(const string& dir) { /* computes md5 hash of all files in the directory */ MD5Hash hash; path_files_md5_hash_recursive(hash, dir); return hash.get_hex(); }
MD5Hash HashFromString(const char* str) { MD5Hash result; Require(std::strlen(str) == 2 * result.size()); for (MD5Hash::iterator it = result.begin(), lim = result.end(); it != lim; ++it) { *it = Hex2Bin(str[0], str[1]); str += 2; } return result; }
int TestMD5() { MD5Hash md5; const char *teststring = NULL; size_t length = 0; /* These tests are from FIPS PUB 180-1 */ teststring = ""; length = strlen(teststring); md5.Process(teststring, length); TEST_ASSERT(strcmp(md5.ToString(), "d41d8cd98f00b204e9800998ecf8427e") == 0); teststring = "a"; length = strlen(teststring); md5.Process(teststring, length); TEST_ASSERT(strcmp(md5.ToString(), "0cc175b9c0f1b6a831c399e269772661") == 0); teststring = "abc"; length = strlen(teststring); md5.Process(teststring, length); TEST_ASSERT(strcmp(md5.ToString(), "900150983cd24fb0d6963f7d28e17f72") == 0); teststring = "message digest"; length = strlen(teststring); md5.Process(teststring, length); TEST_ASSERT(strcmp(md5.ToString(), "f96b697d7cb7938d525a2f31aaf161d0") == 0); teststring = "abcdefghijklmnopqrstuvwxyz"; length = strlen(teststring); md5.Process(teststring, length); TEST_ASSERT(strcmp(md5.ToString(), "c3fcd3d76192e4007dfb496cca67e13b") == 0); teststring = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; length = strlen(teststring); md5.Process(teststring, length); TEST_ASSERT(strcmp(md5.ToString(), "d174ab98d277d9f5a5611c2c9f419d9f") == 0); teststring = "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; length = strlen(teststring); md5.Process(teststring, length); TEST_ASSERT(strcmp(md5.ToString(), "57edf4a22be3c955ac49da2e2107b67a") == 0); MD5Hash otherhash; otherhash.Process("cheese", 6); TEST_ASSERT(otherhash != md5 && md5 != otherhash); otherhash.Process(teststring, length); TEST_ASSERT(otherhash == md5 && md5 == otherhash); #ifdef FILE_CHECKSUM TextReader file; file.Open("testfile"); md5.Process((CoreIOReader *)&file); TEST_ASSERT(strcmp(md5.ToString(), "bc2471d759c6ae2eb44482f571b02a40") == 0); #endif return 0; }
const string& CacheData::get_filename() { if(!have_filename) { MD5Hash hash; foreach(const CacheBuffer& buffer, buffers) if(buffer.size) hash.append((uint8_t*)buffer.data, buffer.size); filename = name + "_" + hash.get_hex(); have_filename = true; }
static void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset); for (size_t i = 0; i < a.size(); i++) { md5.append((uint8_t*)&a[i], sizeof(T)); } }
static void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { /* Don't compare 4th element used for padding. */ const array<float3>& a = *(const array<float3>*)(((char*)node) + socket.struct_offset); for (size_t i = 0; i < a.size(); i++) { md5.append((uint8_t*)&a[i], sizeof(float) * 3); } }
static void path_files_md5_hash_recursive(MD5Hash& hash, const string& dir) { if(path_exists(dir)) { directory_iterator it(dir), it_end; for(; it != it_end; ++it) { if(path_is_directory(it->path())) { path_files_md5_hash_recursive(hash, it->path()); } else { string filepath = it->path(); hash.append((const uint8_t*)filepath.c_str(), filepath.size()); hash.append_file(filepath); } } } }
static void path_files_md5_hash_recursive(MD5Hash& hash, const string& dir) { if(boost::filesystem::exists(dir)) { boost::filesystem::directory_iterator it(dir), it_end; for(; it != it_end; it++) { if(boost::filesystem::is_directory(it->status())) { path_files_md5_hash_recursive(hash, it->path().string()); } else { string filepath = it->path().string(); hash.append((const uint8_t*)filepath.c_str(), filepath.size()); hash.append_file(filepath); } } } }
TEST(testarchive, test_archive) { File::deleteFile("test/data/out/gtest.h"); try { Archive("test/data/gtest_h.zip").extract("test/data/out/"); } catch(const Exception& e) { FAIL() << e.getError(); } auto md5 = [](string path) { File f(path, File::READ, File::OPEN); MD5Hash h; auto buf = f.read(); h.update(buf.c_str(), buf.size()); return MD5Value(h.finalize()); }; ASSERT_EQ(md5("test/gtest.h"), md5("test/data/out/gtest.h")); }
void Node::hash(MD5Hash& md5) { md5.append(type->name.string()); foreach(const SocketType& socket, type->inputs) { md5.append(socket.name.string()); switch(socket.type) { case SocketType::BOOLEAN: value_hash<bool>(this, socket, md5); break; case SocketType::FLOAT: value_hash<float>(this, socket, md5); break; case SocketType::INT: value_hash<int>(this, socket, md5); break; case SocketType::UINT: value_hash<uint>(this, socket, md5); break; case SocketType::COLOR: float3_hash(this, socket, md5); break; case SocketType::VECTOR: float3_hash(this, socket, md5); break; case SocketType::POINT: float3_hash(this, socket, md5); break; case SocketType::NORMAL: float3_hash(this, socket, md5); break; case SocketType::POINT2: value_hash<float2>(this, socket, md5); break; case SocketType::CLOSURE: break; case SocketType::STRING: value_hash<ustring>(this, socket, md5); break; case SocketType::ENUM: value_hash<int>(this, socket, md5); break; case SocketType::TRANSFORM: value_hash<Transform>(this, socket, md5); break; case SocketType::NODE: value_hash<void*>(this, socket, md5); break; case SocketType::BOOLEAN_ARRAY: array_hash<bool>(this, socket, md5); break; case SocketType::FLOAT_ARRAY: array_hash<float>(this, socket, md5); break; case SocketType::INT_ARRAY: array_hash<int>(this, socket, md5); break; case SocketType::COLOR_ARRAY: float3_array_hash(this, socket, md5); break; case SocketType::VECTOR_ARRAY: float3_array_hash(this, socket, md5); break; case SocketType::POINT_ARRAY: float3_array_hash(this, socket, md5); break; case SocketType::NORMAL_ARRAY: float3_array_hash(this, socket, md5); break; case SocketType::POINT2_ARRAY: array_hash<float2>(this, socket, md5); break; case SocketType::STRING_ARRAY: array_hash<ustring>(this, socket, md5); break; case SocketType::TRANSFORM_ARRAY: array_hash<Transform>(this, socket, md5); break; case SocketType::NODE_ARRAY: array_hash<void*>(this, socket, md5); break; case SocketType::UNDEFINED: break; } } }
static void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { /* Don't compare 4th element used for padding. */ md5.append(((uint8_t*)node) + socket.struct_offset, sizeof(float) * 3); }
static void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5) { md5.append(((uint8_t*)node) + socket.struct_offset, socket.size()); }
bool DevEffect::Load(const char *path,DevEffect::DefGenerator *dg) { // clear effect ClearEffect(); file_time = GetFileTime(path); p_path = string(path).c_str(); // load file vector<char> data; if(!ScrambleLoad(path,data)) return false; // compute partial hash MD5Hash md5; md5.Update((byte*)&data[0],(int)data.size()); // build skip list string skip_list; BuildSkipList(&data[0],skip_list); // build defines vector<string> defs; if(dg) dg(defs); else defs.push_back(":"); // create pool if(defs.size()>=2) { if(FAILED(D3DXCreateEffectPool(&pool))) { return false; } } // compile for(int i=0;i<(int)defs.size();i++) { vector<D3DXMACRO> macros; vector<byte> bin; MD5Hash hash = md5; byte bhash[16]; // build final hash defs[i].push_back(0); hash.Update((byte*)&defs[i][0],(int)defs.size()); hash.Final(bhash); // get macros ShatterDefsList(&defs[i][0],macros); // build binary path string bpath = FilePathGetPart((string("shaders/")+path).c_str(),true,true,false); if(defs[i].c_str()[0]) { bpath += "-"; bpath += defs[i].c_str(); } bpath += ".fxx"; // precompile effect if(!GetPrecompiledBinary(data,defs[i].c_str(),path,bpath.c_str(),macros,bhash,bin)) return false; if(!CompileVersion(defs[i].c_str(),path,bin,macros,skip_list.c_str())) return false; } if(fx_list.size()<=0) return false; fx = fx_list[0]; // load textures D3DXHANDLE h, ha; const char *str; int id = 0; while( (h = fx->GetParameter(NULL,id)) ) { ha = fx->GetAnnotationByName(h,"Load"); if(ha) if(SUCCEEDED(fx->GetString(ha,&str))) { DevTexture *t = new DevTexture(); t->Load(str); fx->SetTexture(h,t->GetTexture()); textures.push_back(t); } id++; } return true; }