static bool IsPartOfMultipartArchive(const StlString& fname) { StlString fname_nopath; size_t last_slash_pos = fname.find_last_of(_T('\\')); if (fname.size() == last_slash_pos) { LOG(("[IsPartOfMultipartArchive] ERROR: wrong file name: %S\n", (wstring(fname.begin(), fname.end())).c_str())); return false; } fname_nopath = (StlString::npos == last_slash_pos) ? fname : fname.substr(last_slash_pos + 1); boost::tregex re(_T("(.*)(\\.part)([0-9]+)(\\.rar)"), boost::tregex::perl|boost::tregex::icase); bool ret_val = false; if (boost::regex_match(fname_nopath, re)) { size_t pos; pos = fname_nopath.find_last_of(_T('.')); if (StlString::npos != pos) { StlString tmp = fname_nopath.substr(0, pos); pos = tmp.find_last_of(_T(".part")); if (StlString::npos != pos && pos < tmp.size() - 1) { tmp = tmp.substr(pos + 1); int part_num = _ttoi(tmp.c_str()); ret_val = (part_num != 1); } } } return ret_val; }
bool Downloader::CheckMd5(const std::string& url, const StlString& file_name) { FileDescriptorList::iterator file_desc_iter = FindDescriptor(url); if (file_desc_iter == file_desc_list_.end()) { LOG(("[CheckMd5] ERROR: File descriptor not found for URL %s\n", url.c_str())); return false; } HANDLE file_handle = OpenOrCreate(file_name, GENERIC_READ); if (INVALID_HANDLE_VALUE == file_handle) { LOG(("[CheckMd5] ERROR: Could not open file: %S\n", std::wstring(file_name.begin(), file_name.end()).c_str())); return false; } MD5 file_md5; file_md5.reset(); bool ret_val = true; vector <BYTE> buf; const unsigned int BUF_SIZE = 1024 * 1024; buf.resize(BUF_SIZE); ULARGE_INTEGER offset, size; size.LowPart = GetFileSize(file_handle, &size.HighPart); list<string>::iterator md5_iter = file_desc_iter->md5_list_.begin(); for (offset.QuadPart = 0; offset.QuadPart < size.QuadPart; offset.QuadPart += PART_SIZE, md5_iter++) { DWORD read_size; MD5 part_md5; part_md5.reset(); ULONG64 pos = 0; do { if (ReadFile(file_handle, &buf[0], BUF_SIZE, &read_size, NULL)) { LOG(("Read OK, pos=0x%llx, read_size=0x%x\n", pos, read_size)); file_md5.append(&buf[0], read_size); part_md5.append(&buf[0], read_size); pos += read_size; if (pos == PART_SIZE || read_size != BUF_SIZE) { part_md5.finish(); string md5_str = part_md5.getFingerprint(); if (md5_str != *md5_iter) { // MD5 is wrong ret_val = false; goto __end; } break; } } else { ret_val = false; goto __end; } } while (read_size == BUF_SIZE); if (distance(md5_iter, file_desc_iter->md5_list_.end()) == 1) { // MD5 list is too short ret_val = false; goto __end; } } file_md5.finish(); if (ret_val && md5_iter != file_desc_iter->md5_list_.end()) { // Check total MD5 if (file_md5.getFingerprint() != *md5_iter) ret_val = false; } __end: CloseHandle(file_handle); return ret_val; }