static int ApplyMpqPatch( TMPQFile * hf, TPatchHeader * pPatchHeader) { unsigned char md5_digest[MD5_DIGEST_SIZE]; hash_state md5_state; int nError = ERROR_SUCCESS; // Verify the original file before patching if(pPatchHeader->dwSizeBeforePatch != 0) { md5_init(&md5_state); md5_process(&md5_state, hf->pbFileData, hf->cbFileData); md5_done(&md5_state, md5_digest); if(memcmp(pPatchHeader->md5_before_patch, md5_digest, MD5_DIGEST_SIZE)) nError = ERROR_FILE_CORRUPT; } // Apply the patch if(nError == ERROR_SUCCESS) { switch(pPatchHeader->dwPatchType) { case 0x59504f43: // 'COPY' nError = ApplyMpqPatch_COPY(hf, pPatchHeader); break; case 0x30445342: // 'BSD0' nError = ApplyMpqPatch_BSD0(hf, pPatchHeader); break; default: nError = ERROR_FILE_CORRUPT; break; } } // Verify MD5 after patch if(nError == ERROR_SUCCESS && pPatchHeader->dwSizeAfterPatch != 0) { // Verify the patched file md5_init(&md5_state); md5_process(&md5_state, hf->pbFileData, hf->cbFileData); md5_done(&md5_state, md5_digest); if(memcmp(pPatchHeader->md5_after_patch, md5_digest, MD5_DIGEST_SIZE)) nError = ERROR_FILE_CORRUPT; } return nError; }
// Creates a MD5 hash from a file specified in "filename" and returns it as string // (based on Ronald L. Rivest's code from RFC1321 "The MD5 Message-Digest Algorithm") string getHashFromFile(const string &filename) { const S32 ChunkSize = 1024; unsigned int len; unsigned char buffer[ChunkSize], digest[16]; // Open file FILE *file = fopen (filename.c_str(), "rb"); if(!file) return "-1"; // Init md5 hash_state md; md5_init(&md); // Read the file while( (len = (unsigned int)fread (buffer, 1, ChunkSize, file)) ) md5_process(&md, buffer, len); // Generate hash, close the file, and return the hash as string md5_done(&md, digest); fclose (file); return convToString(digest); }
// Very simple/stupid MD5-based RNG that samples "entropy" from various PS2 control registers static unsigned long rng_ps2(unsigned char *buf, unsigned long len, void (*callback)(void)) { static unsigned long lastx[2] = { 0xaab7cb4b2fd3b2b9, 0xcec58aff72afe49f }; // md5sum of bits.c unsigned long j; unsigned int samples[10]; // number of sample data sources int l; hash_state md; for (j = 0; j < len; j += sizeof(lastx)) { md5_init(&md); samples[0] = *T2_COUNT; samples[1] = *T3_COUNT; samples[2] = *IPU_TOP; samples[3] = *GIF_TAG0; samples[4] = *GIF_TAG1; samples[5] = *GIF_TAG2; samples[6] = *VIF1_CODE; samples[7] = *VIF0_CODE; samples[8] = *D0_MADR; samples[9] = *D1_MADR; md5_process(&md, (unsigned char *)(&samples[0]), sizeof(samples)); // include previous round md5_process(&md, (unsigned char *)(&lastx[0]), sizeof(lastx)); md5_done(&md, (unsigned char *)(&lastx[0])); l = min(sizeof(lastx), len-j); memcpy(buf+j, &lastx[0], l); //min(sizeof(lastx), len-j)); } return len; }
ICACHE_FLASH_ATTR void md5(const uint8_t *buf, size_t len, uint8_t *hash) { Md5State s; md5_init(&s); md5_proc(&s, buf, len); md5_done(&s, hash); }
int process(int fd, const char *name, int fork) { static unsigned char buffer[4096]; hash_state md; unsigned char hash[16]; md5_init(&md); for(;;) { long l = read(fd, buffer, sizeof(buffer)); if (l == 0) break; if (l < 0) { if (errno == EINTR) continue; perror("read"); return -1; } md5_process(&md, buffer, l); } md5_done(&md, hash); fprintf(stdout, "MD5 (%s%s) = %s\n", name, fork ? "+" : "", unhash(hash)); return 0; }
string PHPBB3Password::md5(string data) { unsigned char hash[16]; hash_state state; md5_init(&state); md5_process(&state, (const unsigned char *)data.c_str(), data.length()); md5_done(&state, hash); string ret; for (int i=0; i<16; i++) ret += hash[i]; return ret; }
// Internal hash function, calling the basic methods from md5.h static string hash(const string &text) { unsigned char outBuffer[16] = ""; hash_state md; md5_init(&md); md5_process(&md, (unsigned char*)text.c_str(), (unsigned int)text.length()); md5_done(&md, outBuffer); // Convert the hash to a string and return it return convToString(outBuffer); }
// from md5_test int test() { static const struct { char *msg; unsigned char hash[16]; } tests[] = { { "", { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, { "a", {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, { "abc", { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, { "message digest", { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, { "abcdefghijklmnopqrstuvwxyz", { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, { NULL, { 0 } } }; unsigned i; unsigned ok; hash_state md; unsigned char hash[16]; for (i = 0; tests[i].msg != NULL; i++) { md5_init(&md); md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); md5_done(&md, hash); ok = !memcmp(hash, tests[i].hash, 16); printf("MD5 (\"%s\") = %s - %s\n", tests[i].msg, unhash(hash), ok ? "verified correct" : "INCORRECT RESULT!"); if (!ok) return -1; } return 0; }
void CNWNXODBC::WriteScorcoData(char *param, BYTE* pData, int Length) { // This function either stores the object or computes a hash value of it if (strcmp(param, "HASH") == 0) { unsigned char out[16]; hash_state md; md5_init(&md); md5_process(&md, pData, Length); md5_done(&md, out); for (int j = 0; j < 16; j += 4) { sprintf(&lastHash[j*2], "%.2x%.2x%.2x%.2x", out[j], out[j+1], out[j+2], out[j+3]); } Log("* MD5 hash (writescorcodata, length): %s, %d\n", lastHash, Length); } else if (Length > 0) { //Log ("o Writing scorco data.\n"); if (!db->WriteScorcoData(scorcoSQL, pData, Length)) if (logLevel > logNothing) Log ("! SQL Error: %s\n", db->GetErrorMessage ()); } }
// Return the final computed hash string IncrementalHasher::getHash() { U8 digest[16]; md5_done(&mHashState, digest); return convToString(digest); }
static DWORD VerifyFile( HANDLE hMpq, const char * szFileName, LPDWORD pdwCrc32, char * pMD5, DWORD dwFlags) { hash_state md5_state; unsigned char * pFileMd5; unsigned char md5[MD5_DIGEST_SIZE]; TFileEntry * pFileEntry; TMPQFile * hf; BYTE Buffer[0x1000]; HANDLE hFile = NULL; DWORD dwVerifyResult = 0; DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ; DWORD dwTotalBytes = 0; DWORD dwBytesRead; DWORD dwCrc32 = 0; // Fix the open type for patched archives if(SFileIsPatchedArchive(hMpq)) dwSearchScope = SFILE_OPEN_PATCHED_FILE; // Attempt to open the file if(SFileOpenFileEx(hMpq, szFileName, dwSearchScope, &hFile)) { // Get the file size hf = (TMPQFile *)hFile; pFileEntry = hf->pFileEntry; dwTotalBytes = SFileGetFileSize(hFile, NULL); // Initialize the CRC32 and MD5 contexts md5_init(&md5_state); dwCrc32 = crc32(0, Z_NULL, 0); // If we have to verify raw data MD5, do it if(dwFlags & SFILE_VERIFY_RAW_MD5) { if(hf->ha->pHeader->dwRawChunkSize != 0) { // Note: we have to open the file from the MPQ where it was open from if(VerifyRawMpqData(hf->ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize) != ERROR_SUCCESS) dwVerifyResult |= VERIFY_FILE_RAW_MD5_ERROR; dwVerifyResult |= VERIFY_FILE_HAS_RAW_MD5; } } // Also turn on sector checksum verification if(dwFlags & SFILE_VERIFY_SECTOR_CRC) hf->bCheckSectorCRCs = true; // Go through entire file and update both CRC32 and MD5 for(;;) { // Read data from file SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL); if(dwBytesRead == 0) { if(GetLastError() == ERROR_CHECKSUM_ERROR) dwVerifyResult |= VERIFY_FILE_SECTOR_CRC_ERROR; break; } // Update CRC32 value if(dwFlags & SFILE_VERIFY_FILE_CRC) dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead); // Update MD5 value if(dwFlags & SFILE_VERIFY_FILE_MD5) md5_process(&md5_state, Buffer, dwBytesRead); // Decrement the total size dwTotalBytes -= dwBytesRead; } // If the file has sector checksums, indicate it in the flags if(dwFlags & SFILE_VERIFY_SECTOR_CRC) { if((hf->pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->SectorChksums != NULL && hf->SectorChksums[0] != 0) dwVerifyResult |= VERIFY_FILE_HAS_SECTOR_CRC; } // Check if the entire file has been read // No point in checking CRC32 and MD5 if not // Skip checksum checks if the file has patches if(dwTotalBytes == 0) { // Check CRC32 and MD5 only if there is no patches if(hf->hfPatchFile == NULL) { // Check if the CRC32 matches. if(dwFlags & SFILE_VERIFY_FILE_CRC) { // Only check the CRC32 if it is valid if(pFileEntry->dwCrc32 != 0) { dwVerifyResult |= VERIFY_FILE_HAS_CHECKSUM; if(dwCrc32 != pFileEntry->dwCrc32) dwVerifyResult |= VERIFY_FILE_CHECKSUM_ERROR; } } // Check if MD5 matches if(dwFlags & SFILE_VERIFY_FILE_MD5) { // Patch files have their MD5 saved in the patch info pFileMd5 = (hf->pPatchInfo != NULL) ? hf->pPatchInfo->md5 : pFileEntry->md5; md5_done(&md5_state, md5); // Only check the MD5 if it is valid if(is_valid_md5(pFileMd5)) { dwVerifyResult |= VERIFY_FILE_HAS_MD5; if(memcmp(md5, pFileMd5, MD5_DIGEST_SIZE)) dwVerifyResult |= VERIFY_FILE_MD5_ERROR; } } } else { // Patched files are MD5-checked automatically dwVerifyResult |= VERIFY_FILE_HAS_MD5; } } else { dwVerifyResult |= VERIFY_READ_ERROR; } SFileCloseFile(hFile); } else { // Remember that the file couldn't be open dwVerifyResult |= VERIFY_OPEN_ERROR; } // If the caller required CRC32 and/or MD5, give it to him if(pdwCrc32 != NULL) *pdwCrc32 = dwCrc32; if(pMD5 != NULL) memcpy(pMD5, md5, MD5_DIGEST_SIZE); return dwVerifyResult; }
static int VerifyRawMpqData( TMPQArchive * ha, ULONGLONG ByteOffset, DWORD dwDataSize) { hash_state md5_state; ULONGLONG DataOffset = ha->MpqPos + ByteOffset; LPBYTE pbDataChunk; LPBYTE pbMD5Array1; // Calculated MD5 array LPBYTE pbMD5Array2; // MD5 array loaded from the MPQ DWORD dwBytesInChunk; DWORD dwChunkCount; DWORD dwChunkSize = ha->pHeader->dwRawChunkSize; DWORD dwMD5Size; int nError = ERROR_SUCCESS; // Get the number of data chunks to calculate MD5 assert(dwChunkSize != 0); dwChunkCount = dwDataSize / dwChunkSize; if(dwDataSize % dwChunkSize) dwChunkCount++; dwMD5Size = dwChunkCount * MD5_DIGEST_SIZE; // Allocate space for data chunk and for the MD5 array pbDataChunk = ALLOCMEM(BYTE, dwChunkSize); if(pbDataChunk == NULL) return ERROR_NOT_ENOUGH_MEMORY; // Allocate space for MD5 array pbMD5Array1 = ALLOCMEM(BYTE, dwMD5Size); pbMD5Array2 = ALLOCMEM(BYTE, dwMD5Size); if(pbMD5Array1 == NULL || pbMD5Array2 == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; // Calculate MD5 of each data chunk if(nError == ERROR_SUCCESS) { LPBYTE pbMD5 = pbMD5Array1; for(DWORD i = 0; i < dwChunkCount; i++) { // Get the number of bytes in the chunk dwBytesInChunk = STORMLIB_MIN(dwChunkSize, dwDataSize); // Read the data chunk if(!FileStream_Read(ha->pStream, &DataOffset, pbDataChunk, dwBytesInChunk)) { nError = ERROR_FILE_CORRUPT; break; } // Calculate MD5 md5_init(&md5_state); md5_process(&md5_state, pbDataChunk, dwBytesInChunk); md5_done(&md5_state, pbMD5); // Move pointers and offsets DataOffset += dwBytesInChunk; dwDataSize -= dwBytesInChunk; pbMD5 += MD5_DIGEST_SIZE; } } // Read the MD5 array if(nError == ERROR_SUCCESS) { // Read the array of MD5 if(!FileStream_Read(ha->pStream, &DataOffset, pbMD5Array2, dwMD5Size)) nError = GetLastError(); } // Compare the array of MD5 if(nError == ERROR_SUCCESS) { // Compare the MD5 if(memcmp(pbMD5Array1, pbMD5Array2, dwMD5Size)) nError = ERROR_FILE_CORRUPT; } // Free memory and return result if(pbMD5Array2 != NULL) FREEMEM(pbMD5Array2); if(pbMD5Array1 != NULL) FREEMEM(pbMD5Array1); if(pbDataChunk != NULL) FREEMEM(pbDataChunk); return nError; }
static bool CalculateMpqHashMd5( TMPQArchive * ha, PMPQ_SIGNATURE_INFO pSI, LPBYTE pMd5Digest) { hash_state md5_state; ULONGLONG BeginBuffer; ULONGLONG EndBuffer; LPBYTE pbDigestBuffer = NULL; // Allocate buffer for creating the MPQ digest. pbDigestBuffer = ALLOCMEM(BYTE, MPQ_DIGEST_UNIT_SIZE); if(pbDigestBuffer == NULL) return false; // Initialize the MD5 hash state md5_init(&md5_state); // Set the byte offset of begin of the data BeginBuffer = pSI->BeginMpqData; // Create the digest for(;;) { ULONGLONG BytesRemaining; LPBYTE pbSigBegin = NULL; LPBYTE pbSigEnd = NULL; DWORD dwToRead = MPQ_DIGEST_UNIT_SIZE; // Check the number of bytes remaining BytesRemaining = pSI->EndMpqData - BeginBuffer; if(BytesRemaining < MPQ_DIGEST_UNIT_SIZE) dwToRead = (DWORD)BytesRemaining; if(dwToRead == 0) break; // Read the next chunk if(!FileStream_Read(ha->pStream, &BeginBuffer, pbDigestBuffer, dwToRead)) { FREEMEM(pbDigestBuffer); return false; } // Move the current byte offset EndBuffer = BeginBuffer + dwToRead; // Check if the signature is within the loaded digest if(BeginBuffer <= pSI->BeginExclude && pSI->BeginExclude < EndBuffer) pbSigBegin = pbDigestBuffer + (size_t)(pSI->BeginExclude - BeginBuffer); if(BeginBuffer <= pSI->EndExclude && pSI->EndExclude < EndBuffer) pbSigEnd = pbDigestBuffer + (size_t)(pSI->EndExclude - BeginBuffer); // Zero the part that belongs to the signature if(pbSigBegin != NULL || pbSigEnd != NULL) { if(pbSigBegin == NULL) pbSigBegin = pbDigestBuffer; if(pbSigEnd == NULL) pbSigEnd = pbDigestBuffer + dwToRead; memset(pbSigBegin, 0, (pbSigEnd - pbSigBegin)); } // Pass the buffer to the hashing function md5_process(&md5_state, pbDigestBuffer, dwToRead); // Move pointers BeginBuffer += dwToRead; } // Finalize the MD5 hash md5_done(&md5_state, pMd5Digest); FREEMEM(pbDigestBuffer); return true; }
int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD dwCompression) { TMPQArchive * ha; TFileEntry * pFileEntry; int nError = ERROR_SUCCESS; // Don't bother if the caller gave us zero size if(pvData == NULL || dwSize == 0) return ERROR_SUCCESS; // Get pointer to the MPQ archive pFileEntry = hf->pFileEntry; ha = hf->ha; // Allocate file buffers if(hf->pbFileSector == NULL) { ULONGLONG RawFilePos = hf->RawFilePos; // Allocate buffer for file sector hf->nAddFileError = nError = AllocateSectorBuffer(hf); if(nError != ERROR_SUCCESS) return nError; // Allocate patch info, if the data is patch if(hf->pPatchInfo == NULL && IsIncrementalPatchFile(pvData, dwSize, &hf->dwPatchedFileSize)) { // Set the MPQ_FILE_PATCH_FILE flag hf->pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE; // Allocate the patch info hf->nAddFileError = nError = AllocatePatchInfo(hf, false); if(nError != ERROR_SUCCESS) return nError; } // Allocate sector offsets if(hf->SectorOffsets == NULL) { hf->nAddFileError = nError = AllocateSectorOffsets(hf, false); if(nError != ERROR_SUCCESS) return nError; } // Create array of sector checksums if(hf->SectorChksums == NULL && (pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC)) { hf->nAddFileError = nError = AllocateSectorChecksums(hf, false); if(nError != ERROR_SUCCESS) return nError; } // Pre-save the patch info, if any if(hf->pPatchInfo != NULL) { if(!FileStream_Write(ha->pStream, &RawFilePos, hf->pPatchInfo, hf->pPatchInfo->dwLength)) nError = GetLastError(); pFileEntry->dwCmpSize += hf->pPatchInfo->dwLength; RawFilePos += hf->pPatchInfo->dwLength; } // Pre-save the sector offset table, just to reserve space in the file. // Note that we dont need to swap the sector positions, nor encrypt the table // at the moment, as it will be written again after writing all file sectors. if(hf->SectorOffsets != NULL) { if(!FileStream_Write(ha->pStream, &RawFilePos, hf->SectorOffsets, hf->SectorOffsets[0])) nError = GetLastError(); pFileEntry->dwCmpSize += hf->SectorOffsets[0]; RawFilePos += hf->SectorOffsets[0]; } } // Write the MPQ data to the file if(nError == ERROR_SUCCESS) { // Save the first sector compression to the file structure // Note that the entire first file sector will be compressed // by compression that was passed to the first call of SFileAddFile_Write if(hf->dwFilePos == 0) hf->dwCompression0 = dwCompression; // Write the data to the MPQ nError = WriteDataToMpqFile(ha, hf, (LPBYTE)pvData, dwSize, dwCompression); } // If it succeeded and we wrote all the file data, // we need to re-save sector offset table if(nError == ERROR_SUCCESS) { if(hf->dwFilePos >= pFileEntry->dwFileSize) { // Finish calculating CRC32 hf->pFileEntry->dwCrc32 = hf->dwCrc32; // Finish calculating MD5 md5_done((hash_state *)hf->hctx, hf->pFileEntry->md5); // If we also have sector checksums, write them to the file if(hf->SectorChksums != NULL) { nError = WriteSectorChecksums(hf); } // Now write patch info if(hf->pPatchInfo != NULL) { memcpy(hf->pPatchInfo->md5, hf->pFileEntry->md5, MD5_DIGEST_SIZE); hf->pPatchInfo->dwDataSize = hf->pFileEntry->dwFileSize; hf->pFileEntry->dwFileSize = hf->dwPatchedFileSize; nError = WritePatchInfo(hf); } // Now write sector offsets to the file if(hf->SectorOffsets != NULL) { nError = WriteSectorOffsets(hf); } // Write the MD5 hashes of each file chunk, if required if(ha->pHeader->dwRawChunkSize != 0) { nError = WriteMpqDataMD5(ha->pStream, ha->MpqPos + hf->pFileEntry->ByteOffset, hf->pFileEntry->dwCmpSize, ha->pHeader->dwRawChunkSize); } } } // Store the error code from the Write File operation hf->nAddFileError = nError; return nError; }
DWORD WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags) { hash_state md5_state; unsigned char md5[MD5_DIGEST_SIZE]; TFileEntry * pFileEntry; TMPQFile * hf; BYTE Buffer[0x1000]; HANDLE hFile = NULL; DWORD dwVerifyResult = 0; DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ; DWORD dwTotalBytes = 0; DWORD dwBytesRead; DWORD dwCrc32; // Fix the open type for patched archives if (SFileIsPatchedArchive(hMpq)) dwSearchScope = SFILE_OPEN_PATCHED_FILE; // Attempt to open the file if (SFileOpenFileEx(hMpq, szFileName, dwSearchScope, &hFile)) { // Get the file size hf = (TMPQFile *)hFile; pFileEntry = hf->pFileEntry; dwTotalBytes = SFileGetFileSize(hFile, NULL); // Initialize the CRC32 and MD5 contexts md5_init(&md5_state); dwCrc32 = crc32(0, Z_NULL, 0); // Also turn on sector checksum verification hf->bCheckSectorCRCs = true; // Go through entire file and update both CRC32 and MD5 for (;;) { // Read data from file SFileReadFile(hFile, Buffer, sizeof(Buffer), &dwBytesRead, NULL); if (dwBytesRead == 0) { if (GetLastError() == ERROR_CHECKSUM_ERROR) dwVerifyResult |= VERIFY_SECTOR_CHECKSUM_ERROR; break; } // Update CRC32 value if (dwFlags & MPQ_ATTRIBUTE_CRC32) dwCrc32 = crc32(dwCrc32, Buffer, dwBytesRead); // Update MD5 value if (dwFlags & MPQ_ATTRIBUTE_MD5) md5_process(&md5_state, Buffer, dwBytesRead); // Decrement the total size dwTotalBytes -= dwBytesRead; } // If the file has sector checksums, indicate it in the flags if ((hf->pFileEntry->dwFlags & MPQ_FILE_SECTOR_CRC) && hf->SectorChksums != NULL && hf->SectorChksums[0] != 0) dwVerifyResult |= VERIFY_SECTORS_HAVE_CHECKSUM; // Check if the entire file has been read // No point in checking CRC32 and MD5 if not // Skip checksum checks if the file has patches if (dwTotalBytes == 0) { // Check CRC32 and MD5 only if there is no patches if (hf->hfPatchFile == NULL) { // Check if the CRC32 matches. if (dwFlags & MPQ_ATTRIBUTE_CRC32) { // Some files may have their CRC zeroed if (pFileEntry->dwCrc32 != 0) { dwVerifyResult |= VERIFY_FILE_HAS_CHECKSUM; if (dwCrc32 != pFileEntry->dwCrc32) dwVerifyResult |= VERIFY_FILE_CHECKSUM_ERROR; } } // Check if MD5 matches if (dwFlags & MPQ_ATTRIBUTE_MD5) { md5_done(&md5_state, md5); // Some files have the MD5 zeroed. Don't check MD5 in that case if (is_valid_md5(pFileEntry->md5)) { dwVerifyResult |= VERIFY_FILE_HAS_MD5; if (memcmp(md5, pFileEntry->md5, MD5_DIGEST_SIZE)) dwVerifyResult |= VERIFY_FILE_MD5_ERROR; } } } else { // Patched files are MD5-checked automatically dwVerifyResult |= VERIFY_FILE_HAS_MD5; } } else { dwVerifyResult |= VERIFY_READ_ERROR; } SFileCloseFile(hFile); } else { // Remember that the file couldn't be open dwVerifyResult |= VERIFY_OPEN_ERROR; } return dwVerifyResult; }
void Organizer::md5(Doublon *d) { hash_state md; unsigned char *out = new unsigned char[16]; unsigned char buf[4096]; unsigned int nbLu=0; QSqlQuery query; query.prepare("SELECT md5 FROM fic WHERE path=:path"); query.bindValue(":path",d->getPath()); query.exec(); bool update = true; if (query.next() && query.value(0).toString().length() > 0) { update= false; memcpy((unsigned char*)out,query.value(0).toString().toStdString().c_str(),sizeof(unsigned char)*16); } else { try { int fd; fd = open(d->getPath(),O_RDONLY); if (fd == -1) { throw -1 ; } md5_init(&md); while (nbLu != boost::filesystem::file_size(d->getPath())) { unsigned int tmp; tmp = read(fd,buf,sizeof(buf)); md5_process(&md,buf, tmp); nbLu += tmp; } md5_done(&md, out); close(fd); } catch (int i) { perror("open"); } } d->setKey(out); if (update) { query.prepare("UPDATE fic SET md5=:md5 WHERE path=:path"); query.bindValue(":md5",d->getKey()->toString().c_str()); query.bindValue(":path",d->getPath()); query.exec(); } }