aboutsummaryrefslogtreecommitdiff
path: root/src/tools/extractor_common
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2020-11-06 00:27:01 +0100
committerShauren <shauren.trinity@gmail.com>2020-12-08 18:16:46 +0100
commit587ec1fd21ac7cba275fbe9131ae5a694465834d (patch)
treedd946e51f1e5f1ad79d0189b5f53526912bb5027 /src/tools/extractor_common
parent6b6d5aff0530d43875572edc9616bc788ed8a26c (diff)
Tools/Extractors: Load additional tact keys from wow.tools (optional for extracting)
Diffstat (limited to 'src/tools/extractor_common')
-rw-r--r--src/tools/extractor_common/CascHandles.cpp126
-rw-r--r--src/tools/extractor_common/CascHandles.h2
2 files changed, 118 insertions, 10 deletions
diff --git a/src/tools/extractor_common/CascHandles.cpp b/src/tools/extractor_common/CascHandles.cpp
index 868c4af27c5..c4ff0db19db 100644
--- a/src/tools/extractor_common/CascHandles.cpp
+++ b/src/tools/extractor_common/CascHandles.cpp
@@ -16,8 +16,16 @@
*/
#include "CascHandles.h"
+#include "IoContext.h"
+#include "Resolver.h"
#include <CascLib.h>
+#include <boost/asio/streambuf.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/asio/ssl/stream.hpp>
#include <boost/filesystem/operations.hpp>
+#include <string>
char const* CASC::HumanReadableCASCError(uint32 error)
{
@@ -43,10 +51,113 @@ char const* CASC::HumanReadableCASCError(uint32 error)
}
}
+namespace
+{
+ Optional<std::string> DownloadFile(std::string const& serverName, int16 port, std::string const& getCommand)
+ {
+ boost::system::error_code error;
+ Trinity::Asio::IoContext ioContext;
+ boost::asio::ssl::context sslContext(boost::asio::ssl::context::sslv23);
+ sslContext.set_options(boost::asio::ssl::context::no_sslv2, error);
+ sslContext.set_options(boost::asio::ssl::context::no_sslv3, error);
+ sslContext.set_options(boost::asio::ssl::context::no_tlsv1, error);
+ sslContext.set_options(boost::asio::ssl::context::no_tlsv1_1, error);
+ sslContext.set_default_verify_paths(error);
+
+ boost::asio::ip::tcp::resolver resolver(ioContext);
+
+ Optional<boost::asio::ip::tcp::endpoint> endpoint = Trinity::Net::Resolve(resolver, boost::asio::ip::tcp::v4(), serverName, std::to_string(port));
+ if (!endpoint)
+ return {};
+
+ boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(ioContext, sslContext);
+ socket.set_verify_mode(boost::asio::ssl::verify_none, error);
+ if (error)
+ return {};
+
+ socket.lowest_layer().connect(*endpoint, error);
+ if (error)
+ return {};
+
+ if (!SSL_set_tlsext_host_name(socket.native_handle(), serverName.c_str()))
+ return {};
+
+ socket.handshake(boost::asio::ssl::stream_base::client, error);
+ if (error)
+ return {};
+
+ boost::asio::streambuf request;
+ std::ostream request_stream(&request);
+
+ request_stream << "GET " << getCommand << " HTTP/1.0\r\n";
+ request_stream << "Host: " << serverName << "\r\n";
+ request_stream << "Connection: close\r\n\r\n";
+
+ // Send the request.
+ boost::asio::write(socket, request);
+
+ // Read the response status line.
+ boost::asio::streambuf response;
+ boost::asio::read_until(socket, response, "\r\n");
+
+ // Check that response is OK.
+ std::string http_version;
+ uint32 status_code;
+ std::string status_message;
+ std::istream response_stream(&response);
+
+ response_stream >> http_version;
+ response_stream >> status_code;
+ std::getline(response_stream, status_message);
+
+ if (status_code != 200)
+ {
+ printf("Downloading tact key list failed with server response %u %s", status_code, status_message.c_str());
+ return {};
+ }
+
+ // Read the response headers, which are terminated by a blank line.
+ boost::asio::read_until(socket, response, "\r\n\r\n");
+
+ // Process the response headers.
+ std::string header;
+ while (std::getline(response_stream, header) && header != "\r")
+ {
+ }
+
+ std::stringstream rawBody;
+
+ // Write whatever content we already have to output.
+ if (response.size() > 0)
+ rawBody << &response;
+
+ // Read until EOF, writing data to output as we go.
+ while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error))
+ rawBody << &response;
+
+ return rawBody.str();
+ }
+
+ template<typename T>
+ bool GetStorageInfo(HANDLE storage, CASC_STORAGE_INFO_CLASS storageInfoClass, T* value)
+ {
+ size_t infoDataSizeNeeded = 0;
+ return ::CascGetStorageInfo(storage, storageInfoClass, value, sizeof(T), &infoDataSizeNeeded);
+ }
+}
+
CASC::Storage::Storage(HANDLE handle) : _handle(handle)
{
}
+bool CASC::Storage::LoadOnlineTactKeys()
+{
+ // attempt to download only once, not every storage opening
+ static Optional<std::string> const tactKeys = DownloadFile("wow.tools", 443, "/api.php?type=tactkeys");
+
+ return tactKeys && CascImportKeysFromString(_handle, tactKeys->c_str());
+}
+
CASC::Storage::~Storage()
{
::CascCloseStorage(_handle);
@@ -71,17 +182,12 @@ CASC::Storage* CASC::Storage::Open(boost::filesystem::path const& path, uint32 l
}
printf("Opened casc storage '%s'\n", path.string().c_str());
- return new Storage(handle);
-}
+ Storage* storage = new Storage(handle);
-namespace CASC
-{
- template<typename T>
- static bool GetStorageInfo(HANDLE storage, CASC_STORAGE_INFO_CLASS storageInfoClass, T* value)
- {
- size_t infoDataSizeNeeded = 0;
- return ::CascGetStorageInfo(storage, storageInfoClass, value, sizeof(T), &infoDataSizeNeeded);
- }
+ if (!storage->LoadOnlineTactKeys())
+ printf("Failed to load additional encryption keys from wow.tools, some files might not be extracted.\n");
+
+ return storage;
}
uint32 CASC::Storage::GetBuildNumber() const
diff --git a/src/tools/extractor_common/CascHandles.h b/src/tools/extractor_common/CascHandles.h
index 357d39a124e..cf40020feb6 100644
--- a/src/tools/extractor_common/CascHandles.h
+++ b/src/tools/extractor_common/CascHandles.h
@@ -53,6 +53,8 @@ namespace CASC
private:
Storage(HANDLE handle);
+ bool LoadOnlineTactKeys();
+
HANDLE _handle;
};