diff --git a/src/client/component/download.cpp b/src/client/component/download.cpp index 2cf1e450..49bca99f 100644 --- a/src/client/component/download.cpp +++ b/src/client/component/download.cpp @@ -8,6 +8,8 @@ #include "game/ui_scripting/execution.hpp" +#include "utils/hash.hpp" + #include #include #include @@ -165,7 +167,7 @@ namespace download const auto url = utils::string::va("%s/%s", base.data(), file.name.data()); console::debug("Downloading %s from %s: %s\n", file.name.data(), base.data(), url); - const auto data = utils::http::get_data(url, {}, {}, &progress_callback); + auto data = utils::http::get_data(url, {}, {}, &progress_callback); if (!data.has_value()) { menu_error("Download failed: An unknown error occurred, please try again."); @@ -177,7 +179,7 @@ namespace download return; } - const auto& result = data.value(); + auto& result = data.value(); if (result.code != CURLE_OK) { menu_error(utils::string::va("Download failed: %s (%i)\n", @@ -192,7 +194,7 @@ namespace download return; } - const auto hash = utils::cryptography::sha1::compute(result.buffer, true); + const auto hash = utils::hash::get_buffer_hash(result.buffer, file.name); if (hash != file.hash) { menu_error(utils::string::va("Download failed: file hash doesn't match the server's (%s: %s != %s)\n", diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index 8d3af0d2..9a484405 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -211,7 +211,11 @@ namespace party } const auto hash = utils::hash::get_file_hash(file); - hash_cache.insert(std::make_pair(file, hash)); + if (!hash.empty()) + { + hash_cache.insert(std::make_pair(file, hash)); + } + return hash; } @@ -271,6 +275,7 @@ namespace party } const auto hash = get_file_hash(filename); + console::debug("hash != source_hash => %s != %s\n", source_hash.data(), hash.data()); if (hash != source_hash) { files.emplace_back(filename, source_hash); @@ -327,6 +332,7 @@ namespace party if (!has_to_download) { const auto hash = get_file_hash(file_path); + console::debug("has_to_download = %s != %s\n", source_hash.data(), hash.data()); has_to_download = source_hash != hash; } diff --git a/src/client/utils/hash.cpp b/src/client/utils/hash.cpp index 56ad536c..2995c796 100644 --- a/src/client/utils/hash.cpp +++ b/src/client/utils/hash.cpp @@ -3,6 +3,7 @@ #include "game/game.hpp" #include "hash.hpp" +#include "component/console.hpp" #include #include @@ -30,6 +31,8 @@ namespace utils::hash game::DB_AuthHash empty_hash{}; if (!std::memcmp(header.hash.bytes, empty_hash.bytes, hash_size)) { + console::warn("Computing pakfile hash because its missing, this may take some time...\n"); + hash_state state; sha256_init(&state); @@ -82,6 +85,40 @@ namespace utils::hash hash.append(reinterpret_cast(&crc_value), sizeof(crc_value)); return utils::string::dump_hex(hash, ""); } + + std::string get_pakfile_buffer_hash(std::string& buffer) + { + if (buffer.size() < sizeof(game::XPakHeader)) + { + return {}; + } + + constexpr auto hash_size = sizeof(game::DB_AuthHash); + const auto header = reinterpret_cast(buffer.data()); + + game::DB_AuthHash empty_hash{}; + if (!std::memcmp(header->hash.bytes, empty_hash.bytes, hash_size)) + { + console::warn("Computing pakfile hash because its missing, this may take some time...\n"); + const auto hash_start = reinterpret_cast(buffer.data() + sizeof(game::XPakHeader)); + const auto len = buffer.size() - sizeof(game::XPakHeader); + const auto hash = utils::cryptography::sha256::compute(hash_start, len, false); + std::memcpy(header->hash.bytes, hash.data(), sizeof(header->hash)); + } + + std::string hash = {header->hash.bytes, header->hash.bytes + hash_size}; + return utils::string::dump_hex(hash, ""); + } + + std::string get_generic_buffer_hash(const std::string& buffer) + { + auto crc_value = crc32(0L, Z_NULL, 0); + crc_value = crc32(crc_value, reinterpret_cast(buffer.data()), + static_cast(buffer.size())); + std::string hash; + hash.append(reinterpret_cast(&crc_value), sizeof(crc_value)); + return utils::string::dump_hex(hash, ""); + } } std::string get_file_hash(const std::string& file) @@ -105,4 +142,16 @@ namespace utils::hash return get_file_hash_generic(file_stream, file_size); } } + + std::string get_buffer_hash(std::string& buffer, const std::string& filename) + { + if (filename.ends_with(".pak")) + { + return get_pakfile_buffer_hash(buffer); + } + else + { + return get_generic_buffer_hash(buffer); + } + } } diff --git a/src/client/utils/hash.hpp b/src/client/utils/hash.hpp index e67ed873..4e5c9e56 100644 --- a/src/client/utils/hash.hpp +++ b/src/client/utils/hash.hpp @@ -3,4 +3,5 @@ namespace utils::hash { std::string get_file_hash(const std::string& file); + std::string get_buffer_hash(std::string& buffer, const std::string& filename); }