bool RarVolume::ReadRar5Volume(DiskFile& file) { debug("Reading rar5-file %s", *m_filename); file.Seek(8); while (!file.Eof()) { RarBlock block = ReadRar5Block(file); if (!block.type) { return false; } if (block.type == RAR5_BLOCK_MAIN) { uint64 arcflags; if (!ReadV(file, &block, &arcflags)) return false; if (arcflags & RAR5_MAIN_VOLNR) { uint64 volnr; if (!ReadV(file, &block, &volnr)) return false; m_volumeNo = (uint32)volnr; } m_newNaming = true; m_multiVolume = (arcflags & RAR5_MAIN_ISVOL) != 0; } else if (block.type == RAR5_BLOCK_ENCRYPTION) { uint64 val; if (!ReadV(file, &block, &val)) return false; if (val != 0) return false; // supporting only AES if (!ReadV(file, &block, &val)) return false; uint8 kdfCount; uint8 salt[16]; if (!Read(file, &block, &kdfCount, sizeof(kdfCount))) return false; if (!Read(file, &block, &salt, sizeof(salt))) return false; m_encrypted = true; if (m_password.Empty()) return false; if (!DecryptRar5Prepare(kdfCount, salt)) return false; } else if (block.type == RAR5_BLOCK_FILE) { RarFile innerFile; if (!ReadRar5File(file, block, innerFile)) return false; m_files.push_back(std::move(innerFile)); } else if (block.type == RAR5_BLOCK_ENDARC) { uint64 endflags; if (!ReadV(file, &block, &endflags)) return false; m_hasNextVolume = (endflags & RAR5_ENDARC_NEXTVOL) != 0; break; } else if (block.type < 1 || block.type > 5) { // inlvaid block type return false; } uint64 skip = block.trailsize; if (m_encrypted) { skip -= 16 - m_decryptPos; if (m_decryptPos < 16) { skip += skip % 16 > 0 ? 16 - skip % 16 : 0; m_decryptPos = 16; } DecryptFree(); } if (!file.Seek(skip, DiskFile::soCur)) { return false; } } return true; }
bool RarVolume::ReadRar3Volume(DiskFile& file) { debug("Reading rar3-file %s", *m_filename); while (!file.Eof()) { RarBlock block = ReadRar3Block(file); if (!block.type) { return false; } if (block.type == RAR3_BLOCK_MAIN) { if (block.flags & RAR3_MAIN_PASSWORD) { m_encrypted = true; if (m_password.Empty()) return false; } m_newNaming = block.flags & RAR3_MAIN_NEWNUMBERING; m_multiVolume = block.flags & RAR3_MAIN_VOLUME; } else if (block.type == RAR3_BLOCK_FILE) { RarFile innerFile; if (!ReadRar3File(file, block, innerFile)) return false; m_files.push_back(std::move(innerFile)); } else if (block.type == RAR3_BLOCK_ENDARC) { if (block.flags & RAR3_ENDARC_DATACRC) { if (!Skip(file, &block, 4)) return false; } if (block.flags & RAR3_ENDARC_VOLNUMBER) { if (!Read32(file, &block, &m_volumeNo)) return false; m_hasNextVolume = (block.flags & RAR3_ENDARC_NEXTVOL) != 0; } break; } else if (block.type < 0x72 || block.type > 0x7b) { // inlvaid block type return false; } uint64 skip = block.trailsize; if (m_encrypted) { skip -= 16 - m_decryptPos; m_decryptPos = 16; DecryptFree(); } if (!file.Seek(skip, DiskFile::soCur)) { return false; } } return true; }