Files
Viano-Core/src/tools/client_launcher/Helper.cpp
T

166 lines
7.3 KiB
C++

/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Helper.hpp"
#include "IoContext.h"
#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <fstream>
#include <iostream>
#include <SHA256.h>
#include <stdexcept>
#include <Util.h>
namespace asio = boost::asio;
namespace ssl = asio::ssl;
namespace http = boost::beast::http;
namespace ClientLauncher
{
namespace Helper
{
std::string GetFileChecksum(std::vector<unsigned char> const& data)
{
SHA256Hash h;
h.UpdateData(data.data(), data.size());
h.Finalize();
std::string checksum = ByteArrayToHexStr(h.GetDigest(), h.GetLength());
boost::algorithm::to_lower(checksum);
return checksum;
}
std::vector<unsigned char> ReadFile(boost::filesystem::path const& path)
{
std::ifstream ifs(path.string(), std::ifstream::binary);
if (!ifs)
throw std::runtime_error("could not open " + path.string());
std::vector<unsigned char> binary;
ifs >> std::noskipws;
ifs.seekg(0, std::ios_base::end);
binary.reserve(ifs.tellg());
ifs.seekg(0, std::ios_base::beg);
std::copy(std::istream_iterator<unsigned char>(ifs), std::istream_iterator<unsigned char>(), std::back_inserter(binary));
return binary;
}
void GetFile(std::string const& url, std::ostream& out)
{
try
{
Trinity::Asio::IoContext io_context;
ssl::context ssl_context(ssl::context::tlsv12_client);
ssl_context.set_verify_mode(ssl::verify_peer);
ssl_context.set_default_verify_paths();
ssl_context.set_verify_mode(ssl::verify_none);
ssl::stream<asio::ip::tcp::socket> socket(io_context, ssl_context);
asio::ip::tcp::resolver resolver(io_context);
auto const host = url.substr(url.find("://") + 3, url.find('/', 8) - (url.find("://") + 3));
auto const port = "443";
auto const target = url.substr(url.find('/', 8));
asio::connect(socket.next_layer(), resolver.resolve(host, port));
socket.handshake(ssl::stream_base::client);
http::request<http::string_body> request(http::verb::get, target, 11);
request.set(http::field::host, host);
request.set(http::field::user_agent, "TCPP ClientLauncher");
http::write(socket, request);
boost::beast::flat_buffer buffer;
http::response<http::string_body> response;
http::read(socket, buffer, response);
out << response.body();
}
catch (std::exception& e)
{
std::cerr << "ERROR: " << e.what() << std::endl;
}
}
bool VerifyRequirements(const boost::filesystem::path& commonAppData)
{
std::vector<std::string> requiredFiles
{
{"047329d08d433da2622e9fc2ee96c8dd8f35e7770699d07cf74855b9c8ea9125.pfty"},
{"0a3afee2cade3a0e8b458c4b4660104cac7fc50e2ca9bef0d708942e77f15c1d.auth"},
{"0a3f6f3f0535ea21dbe620085192afc796203047e270e0e1b76f15a739fe1797.pfty"},
{"2753d31092f1978bdd78ebd4fae2d189364ad7108ceb22fbf1413be1f43bef04.pfty"},
{"305bbdab1953e65974a249e276867e13ad2c3cabca3668983cb5ed406251bb7b.pfty"},
{"36b27cd911b33c61730a8b82c8b2495fd16e8024fc3b2dde08861c77a852941c.auth"},
{"3e381d4f83201f4e3c482eb74da12e5ff9dd924da2413d8fb33f5eea9a02c2c2.pfty"},
{"5813f318f7e40a07a7cdfeeec9827942e6fdc5ccee0d4171148443e429ad0ead.pfty"},
{"5e298e530698af905e1247e51ef0b109b352ac310ce7802a1f63613db980ed17.auth"},
{"63bc118937e6ea2faa7b7192676daeb1b7ca87a9c24ed9f5acd60e630b4dd7a4.auth"},
{"7466b2db3f03768aa2527535d4b3c6c9ef9e8fb07c6db88b1019f3d25a2942e8.pfty"},
{"83663d54444eadad40d43725e59bde8eda10276e76fc3c4e6f2ca56332ee8f03.pfty"},
{"870f53d10b4e1b09d6b622cd5671ba4ff1ad69512dfa2c676072c52e45c7f0f9.pfty"},
{"8c43bda10be33a32abbc09fb2279126c7f5953336391276cff588565332fcd40.auth"},
{"8f52906a2c85b416a595702251570f96d3522f39237603115f2f1ab24962043c.auth"},
{"97eeb2e28e9e56ed6a22d09f44e2ff43c93315e006bbad43bafc0defaa6f50ae.auth"},
{"a2ec4b41148214037a2e89a2e557af716d085241b81f5244494bdc77a891ca38.pfty"},
{"a8c77051991b1a6c5dfe412e9f46d8f584349996fbde37c4f2a527c192163502.pfty"},
{"b72e65b6b34d8f859e79b5f28952e26553a796d5e1d75c2b5930bc0daeaa728c.pfty"},
{"c3a1ac0694979e709c3b5486927e558af1e2be02ca96e5615c5a65aacc829226.auth"},
{"e8b82becbe0a0a1bbb5561df69320edbd770897a8deaab23caa6736255e0dc33.pfty"}
};
std::cout << "Validating required module files...\n";
for (uint32 i = 0; i < requiredFiles.size(); i++)
{
boost::filesystem::path modulePath
(commonAppData / std::string(&requiredFiles[i][0], 2) / std::string(&requiredFiles[i][2], 2));
boost::filesystem::path module(modulePath / requiredFiles[i]);
if (!boost::filesystem::exists(module.make_preferred()))
{
std::cout << requiredFiles[i] << " doesn't exist, downloading it...\n";
if (!boost::filesystem::exists(modulePath.make_preferred()))
boost::filesystem::create_directories(modulePath.make_preferred());
}
else
{
if (module.make_preferred().stem().string().compare(Helper::GetFileChecksum(Helper::ReadFile(module.make_preferred()))) == 0)
continue;
else
std::cout << requiredFiles[i] << " is corrupted! Redownloading it...\n";
}
std::ofstream outFile(module.string(), std::ofstream::out | std::ofstream::binary);
GetFile("https://raw.githubusercontent.com/The-Cataclysm-Preservation-Project/AuthModules/master/Windows/ProgramData/Blizzard%20Entertainment/Battle.net/Cache/" +
std::string(&requiredFiles[i][0], 2) + "/" + std::string(&requiredFiles[i][2], 2) + "/" + requiredFiles[i], outFile);
outFile.close();
}
std::cout << "Done.\n";
return true;
}
}
}