aboutsummaryrefslogtreecommitdiff
path: root/src/tools/connection_patcher/Helper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/connection_patcher/Helper.cpp')
-rw-r--r--src/tools/connection_patcher/Helper.cpp139
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;
+ }
}
}