diff --git a/header/gMod_XorStream.h b/header/gMod_XorStream.h index 28a37bf..62fa802 100644 --- a/header/gMod_XorStream.h +++ b/header/gMod_XorStream.h @@ -6,7 +6,7 @@ class gMod_XorStream : public std::streambuf { public: - gMod_XorStream(std::istream& stream) : innerStream(stream) { + gMod_XorStream(std::ifstream& stream) : innerStream(stream) { if (!innerStream.seekg(0, std::ios::end).good() || !innerStream.seekg(0, std::ios::beg).good()) { throw std::invalid_argument("Provided stream needs to have SEEK set to True"); } @@ -57,16 +57,34 @@ public: } std::vector ReadToEnd() { - std::vector buffer(length); - for (auto c = ReadByte(); c != traits_type::eof(); c = ReadByte()) { - buffer.push_back(static_cast(c)); + const size_t bufferSize = 1024; + char buffer[bufferSize]; + std::vector streamData; + streamData.reserve(length); // Reserve memory to avoid frequent reallocations + + innerStream.clear(); // Clear any error state of the stream + innerStream.seekg(0, std::ios::beg); // Go to the beginning of the stream + + while(true) { + innerStream.read(buffer, bufferSize); + auto readBytes = innerStream.gcount(); + if (readBytes == 0) { + break; + } + + const auto readBytesSize = static_cast(readBytes); + for (auto i = 0; i < readBytes; i++) { + buffer[i] = XOR(buffer[i], streamData.size() + i); + } + + streamData.insert(streamData.end(), buffer, buffer + readBytes); } - return buffer; + return streamData; } private: - std::istream& innerStream; + std::ifstream& innerStream; long originalStreamLength; long length; @@ -80,9 +98,11 @@ private: char_type ReadByte() { char_type byte; + auto position = innerStream.tellg(); if (innerStream.get(byte)) { - return XOR(byte, innerStream.tellg()); + return XOR(byte, position); } + return traits_type::eof(); } diff --git a/source/gMod_FileLoader.cpp b/source/gMod_FileLoader.cpp index 61d8492..52595f0 100644 --- a/source/gMod_FileLoader.cpp +++ b/source/gMod_FileLoader.cpp @@ -33,14 +33,14 @@ std::vector gMod_FileLoader::GetTpfContents() try { auto istream = std::ifstream(file_name, std::ios::binary); auto xorstream = gMod_XorStream(istream); - + const auto buffer = xorstream.ReadToEnd(); const std::string password(TPF_PASSWORD.begin(), TPF_PASSWORD.end()); - libzippp::ZipArchive zipArchive(file_name, password); - zipArchive.setErrorHandlerCallback([](const std::string& message, const std::string& strerror, int zip_error_code, int system_error_code) -> void { + auto zipArchive = libzippp::ZipArchive::fromBuffer(buffer.data(), buffer.size(), false, password); + zipArchive->setErrorHandlerCallback([](const std::string& message, const std::string& strerror, int zip_error_code, int system_error_code) -> void { Message("GetTpfContents: %s %s %d %d\n", message.c_str(), strerror.c_str(), zip_error_code, system_error_code); }); - zipArchive.open(); - LoadEntries(zipArchive, entries); + zipArchive->open(); + LoadEntries(*zipArchive, entries); } catch (const std::exception& e) { throw std::runtime_error("Failed to open zip file: " + file_name + "\n" + e.what());