diff options
Diffstat (limited to 'src/tools/connection_patcher/Helper.cpp')
-rw-r--r-- | src/tools/connection_patcher/Helper.cpp | 139 |
1 files changed, 132 insertions, 7 deletions
diff --git a/src/tools/connection_patcher/Helper.cpp b/src/tools/connection_patcher/Helper.cpp index 6407560f093..5489b54a338 100644 --- a/src/tools/connection_patcher/Helper.cpp +++ b/src/tools/connection_patcher/Helper.cpp @@ -18,15 +18,97 @@ #include "Helper.hpp" -#include <SHA256.h> -#include <Util.h> - -#include <stdexcept> - namespace Connection_Patcher { namespace Helper { + // adapted from http://stackoverflow.com/questions/8593608/how-can-i-copy-a-directory-using-boost-filesystem + void CopyDir(boost::filesystem::path const & source, boost::filesystem::path const & destination) + { + namespace fs = boost::filesystem; + if (!fs::exists(source) || !fs::is_directory(source)) + throw std::invalid_argument("Source directory " + source.string() + " does not exist or is not a directory."); + + if (fs::exists(destination)) + throw std::invalid_argument("Destination directory " + destination.string() + " already exists."); + + if (!fs::create_directory(destination)) + throw std::runtime_error("Unable to create destination directory" + destination.string()); + + for (fs::directory_iterator file(source); file != fs::directory_iterator(); ++file) + { + fs::path current(file->path()); + if (fs::is_directory(current)) + CopyDir(current, destination / current.filename()); + else + fs::copy_file(current, destination / current.filename()); + } + } + + // adapted from http://stackoverflow.com/questions/21422094/boostasio-download-image-file-from-server + void DownloadFile(const std::string& serverName, int port, const std::string& getCommand, std::ostream& out) + { + using namespace boost::asio; + using boost::asio::ip::tcp; + + io_service io_service; + + // Get a list of endpoints corresponding to the server name. + tcp::resolver resolver(io_service); + tcp::resolver::query query(serverName, std::to_string(port)); + tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); + tcp::resolver::iterator end; + + // Try each endpoint until we successfully establish a connection. + tcp::socket socket(io_service); + boost::system::error_code error = boost::asio::error::host_not_found; + while (error && endpoint_iterator != end) + { + socket.close(); + socket.connect(*endpoint_iterator++, error); + } + + boost::asio::streambuf request; + std::ostream request_stream(&request); + + request_stream << "GET " << getCommand << " HTTP/1.0\r\n"; + request_stream << "Host: " << serverName << ':' << port << "\r\n"; + request_stream << "Accept: */*\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::istream response_stream(&response); + std::string http_version; + response_stream >> http_version; + unsigned int status_code; + response_stream >> status_code; + std::string status_message; + std::getline(response_stream, status_message); + + // 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") + { } + + // Write whatever content we already have to output. + if (response.size() > 0) + out << &response; + + // Read until EOF, writing data to output as we go. + while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)) + out << &response; + } + Constants::BinaryTypes GetBinaryType(std::vector<unsigned char> const& data) { // Check MS-DOS magic @@ -41,9 +123,7 @@ namespace Connection_Patcher return Constants::BinaryTypes(*reinterpret_cast<uint16_t const*>(data.data() + peOffset + 4)); } else - { return Constants::BinaryTypes(*reinterpret_cast<uint32_t const*>(data.data())); - } } std::string GetFileChecksum(std::vector<unsigned char> const& data) @@ -54,5 +134,50 @@ namespace Connection_Patcher return ByteArrayToHexStr(h.GetDigest(), h.GetLength()); } + + std::set<size_t> SearchOffset(std::vector<unsigned char> const& binary, std::vector<unsigned char> const& pattern) + { + std::set<size_t> offsets; + for (size_t i = 0; (i + pattern.size()) < binary.size(); i++) + { + size_t matches = 0; + + for (size_t j = 0; j < pattern.size(); j++) + { + if (pattern[j] == 0) + { + matches++; + continue; + } + + if (binary[i + j] != pattern[j]) + break; + + matches++; + } + + if (matches == pattern.size()) + { + offsets.insert(i); + i += matches; + } + } + + return offsets.empty() ? throw std::runtime_error("unable to find pattern") : offsets; + } + + uint32_t GetBuildNumber(std::vector<unsigned char> const& binary) + { + std::set<size_t> offsets = SearchOffset(binary, Patterns::Common::BinaryVersion()); + + if (!offsets.empty()) + { + size_t const verOffset = (*offsets.begin()); + std::string ver(&binary[verOffset + 16], &binary[verOffset + 21]); + + return std::stoi(ver); + } + return 0; + } } } |