From 4e97ca45bb15118b8e7cce9159844ac135848a90 Mon Sep 17 00:00:00 2001 From: zimbora Date: Sat, 11 May 2024 00:15:12 +0100 Subject: [PATCH] supports file download with redirect, json parse, last version download, version comparison, md5 calculation --- src/update/Dockerfile.linux-x64 | 4 +- src/update/app | 0 src/update/httpclient.cpp | 47 +++++ src/update/httpclient.h | 19 ++ src/update/linux-build.sh | 1 - src/update/makefile | 8 +- src/update/test.cpp | 56 ++++- src/update/update.cpp | 353 ++++++++++++++++++++++++++++++-- src/update/update.h | 29 ++- 9 files changed, 479 insertions(+), 38 deletions(-) create mode 100644 src/update/app create mode 100644 src/update/httpclient.cpp create mode 100644 src/update/httpclient.h diff --git a/src/update/Dockerfile.linux-x64 b/src/update/Dockerfile.linux-x64 index ba80b76cba..fb22fa8085 100644 --- a/src/update/Dockerfile.linux-x64 +++ b/src/update/Dockerfile.linux-x64 @@ -1,10 +1,12 @@ -FROM decenomy/dsw-linux-x64-builder@sha256:49894f78ac27318ed1c018c80e674f99e6b45ac382c9b98a2aa0c94d8bd755a4 +#FROM decenomy/dsw-linux-x64-builder@sha256:49894f78ac27318ed1c018c80e674f99e6b45ac382c9b98a2aa0c94d8bd755a4 +FROM decenomy/local-linux-x64-builder:latest # Set up a development tools directory WORKDIR /home/app COPY . /home/app +RUN make clean RUN make docker_linux_test RUN export PATH="/wrapped:$PATH" diff --git a/src/update/app b/src/update/app new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/update/httpclient.cpp b/src/update/httpclient.cpp new file mode 100644 index 0000000000..bdd795a0f2 --- /dev/null +++ b/src/update/httpclient.cpp @@ -0,0 +1,47 @@ +#include "httpclient.h" + +HTTPClient::HTTPClient() { + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + if (!curl) { + std::cerr << "Error: Failed to initialize libcurl." << std::endl; + } +} + +HTTPClient::~HTTPClient() { + if (curl) { + curl_easy_cleanup(curl); + } + curl_global_cleanup(); +} + +std::string HTTPClient::get(const std::string& url) { + + std::cout << "get info from: " << url << std::endl; + std::string response; + if (curl) { + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // Verify the peer's SSL certificate + curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + // Set User-Agent header + curl_version_info_data *info = curl_version_info(CURLVERSION_NOW); + + if (info) { + curl_easy_setopt(curl, CURLOPT_USERAGENT, info->version); + } + + CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + std::cerr << "Error: Failed to perform HTTP request: " << curl_easy_strerror(res) << std::endl; + } + } + return response; +} + +size_t HTTPClient::writeCallback(void* ptr, size_t size, size_t nmemb, std::string* data) { + data->append((char*)ptr, size * nmemb); + return size * nmemb; +} diff --git a/src/update/httpclient.h b/src/update/httpclient.h new file mode 100644 index 0000000000..78125de213 --- /dev/null +++ b/src/update/httpclient.h @@ -0,0 +1,19 @@ +#ifndef HTTPCLIENT_H +#define HTTPCLIENT_H + +#include +#include +#include + +class HTTPClient { +public: + HTTPClient(); + ~HTTPClient(); + std::string get(const std::string& url); + +private: + CURL* curl; + static size_t writeCallback(void* ptr, size_t size, size_t nmemb, std::string* data); +}; + +#endif // HTTPCLIENT_H diff --git a/src/update/linux-build.sh b/src/update/linux-build.sh index 2d45339682..d6717a38d7 100755 --- a/src/update/linux-build.sh +++ b/src/update/linux-build.sh @@ -23,7 +23,6 @@ docker cp "$container_id":home/app/test ./test # Remove the temporary container docker rm "$container_id" - # To run the container use: #docker run \ # -it \ diff --git a/src/update/makefile b/src/update/makefile index 48d47fd8e4..8392036696 100644 --- a/src/update/makefile +++ b/src/update/makefile @@ -62,8 +62,8 @@ docker_linux_test: -I/DSW/depends/x86_64-pc-linux-gnu/include \ -L/DSW/depends/x86_64-pc-linux-gnu/lib \ -L/DSW/depends/x86_64-pc-linux-gnu/lib64 \ - -o test test.cpp logging.h tinyformat.h update.h update.cpp minizip/unzip.h minizip/unzip.c minizip/ioapi.h minizip/ioapi.c \ - -lcurl -pthread -lz -lssl -lcrypto -ldl -lboost_system-mt-x64 -lboost_filesystem-mt-x64 + -o test test.cpp logging.h tinyformat.h update.h update.cpp httpclient.h httpclient.cpp minizip/unzip.h minizip/unzip.c minizip/ioapi.h minizip/ioapi.c \ + -lcurl -pthread -lz -lssl -lcrypto -ldl -lboost_system-mt-x64 -lboost_filesystem-mt-x64 -lboost_json-mt-x64 docker_linux_app: $(CXX) -DUPDATETEST -DNEWVERSION="$(VERSION)" \ @@ -71,7 +71,7 @@ docker_linux_app: -L/DSW/depends/x86_64-pc-linux-gnu/lib \ -L/DSW/depends/x86_64-pc-linux-gnu/lib64 \ -o app test.cpp logging.h tinyformat.h update.h update.cpp minizip/unzip.h minizip/unzip.c minizip/ioapi.h minizip/ioapi.c \ - -lcurl -pthread -lz -lssl -lcrypto -ldl -lboost_system-mt-x64 -lboost_filesystem-mt-x64 + -lcurl -pthread -lz -lssl -lcrypto -ldl -lboost_system-mt-x64 -lboost_filesystem-mt-x64 -lboost_json-mt-x64 docker_windows_test: /usr/bin/x86_64-w64-mingw32-g++ -DUPDATETEST -static \ @@ -91,4 +91,4 @@ docker_windows_app: clean: - rm test app test.exe \ No newline at end of file + rm test \ No newline at end of file diff --git a/src/update/test.cpp b/src/update/test.cpp index 06f41cac42..4548d2cd0d 100644 --- a/src/update/test.cpp +++ b/src/update/test.cpp @@ -1,11 +1,27 @@ #define COIN "777" +#include #include "update.h" -//#include +#include "httpclient.h" +//#include "clientversion.h" + +#define CLIENT_VERSION_MAJOR 1 +#define CLIENT_VERSION_MINOR 0 +#define CLIENT_VERSION_REVISION 2 +#define CLIENT_VERSION_BUILD 0 + namespace fs = boost::filesystem; +namespace json = boost::json; + +// get it from clientversion.h +static const int CLIENT_VERSION = + 1000000 * CLIENT_VERSION_MAJOR /// + + 10000 * CLIENT_VERSION_MINOR /// + + 100 * CLIENT_VERSION_REVISION /// + + 1 * CLIENT_VERSION_BUILD; // Define the progress callback function -static int downloadProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { +static int DownloadProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { // Calculate progress percentage double progress = (dlnow > 0) ? (dlnow / dltotal) * 100.0 : 0.0; @@ -29,6 +45,30 @@ int main() { std::cout << "Let's update our app" << std::endl; + HTTPClient client; + Update update; + + const std::string url = std::string(UPDATE_URL)+std::string(TICKER)+"/releases/latest"; + std::string response = client.get(url); + + json::value jv = json::parse(response); + update.ParseVersionRequest(jv); + int version = update.GetRemoteVersion(); + std::cout << "remote version: " << version << "\n"; + + if(version > CLIENT_VERSION){ + std::cout << "update app" << std::endl; + update.GetLatestVersion(); + }else{ + std::cout << "current version is the most recent" << std::endl; + } + //std::cout << "Parsed JSON: " << jv << std::endl; + //std::cout << "Serialized JSON: " << boost::json::serialize(jv) << std::endl; + + //std::cout << "Response from " << url << ":\n" << response << std::endl; + return 0; + + /* std::cout << "current version is: " << std::string(VERSION) << std::endl; const char* currentApp = "test"; @@ -48,17 +88,17 @@ int main() { while(1); */ + /* - const std::string url = std::string(UPDATE_URL)+std::string(TICKER)+"/releases/latest"; const std::string outputFileName = "bootstrap.zip"; const std::string extractPath = "bootstrap_"; std::cout << "Download: " << url << std::endl; - if(Bootstrap::isDirectory(extractPath)) - Bootstrap::rmDirectory(extractPath); + if(Bootstrap::IsDirectory(extractPath)) + Bootstrap::RemoveDirectory(extractPath); - if (Bootstrap::DownloadFile(url, outputFileName, downloadProgressCallback)) { + if (Bootstrap::DownloadFile(url, outputFileName, DownloadProgressCallback)) { std::cout << "File downloaded successfully." << std::endl; if (Bootstrap::extractZip(outputFileName, extractPath)) { @@ -67,8 +107,8 @@ int main() { std::cerr << "Error extracting zip file." << std::endl; } - if(Bootstrap::isDirectory(extractPath)) - Bootstrap::rmDirectory(extractPath); + if(Bootstrap::IsDirectory(extractPath)) + Bootstrap::RmDirectory(extractPath); } else { std::cerr << "Error downloading file." << std::endl; diff --git a/src/update/update.cpp b/src/update/update.cpp index c92ea24134..1b25bc1c25 100644 --- a/src/update/update.cpp +++ b/src/update/update.cpp @@ -1,10 +1,90 @@ #include "update.h" +#include +#include +#include +#include + namespace fs = boost::filesystem; +namespace json = boost::json; + static bool log_flag = false; +Latest latest; + +std::string hexToUtf8(const std::string& hex) { + std::string utf8; + for (size_t i = 0; i < hex.length(); i += 2) { + std::string byteString = hex.substr(i, 2); + unsigned char byte = static_cast(std::stoi(byteString, nullptr, 16)); + utf8.push_back(byte); + } + return utf8; +} + +std::string CalculateMD5(const std::string& filePath) { + std::ifstream file(filePath, std::ios::binary); + if (!file) { + std::cerr << "Error opening file: " << filePath << std::endl; + return ""; + } -bool Update::rmDirectory(const std::string& directory_path) { + MD5_CTX mdContext; + MD5_Init(&mdContext); + + const int bufferSize = 4096; + char buffer[bufferSize]; + while (file) { + file.read(buffer, bufferSize); + MD5_Update(&mdContext, buffer, file.gcount()); + } + file.close(); + + unsigned char digest[MD5_DIGEST_LENGTH]; + MD5_Final(digest, &mdContext); + + char md5String[MD5_DIGEST_LENGTH * 2 + 1]; + for(int i = 0; i < MD5_DIGEST_LENGTH; i++) + sprintf(&md5String[i*2], "%02x", (unsigned int)digest[i]); + + return md5String; +} + + +// Callback function to write received headers to a string +size_t headerCallback(void* buffer, size_t size, size_t nmemb, std::string* headers) { + size_t totalSize = size * nmemb; + headers->append((char*)buffer, totalSize); + return totalSize; +} + +std::string RemoveQuotes(const std::string& str) { + std::string result = str; + + // Check if the string starts with a double quote + if (!result.empty() && result.front() == '"') { + result.erase(0, 1); // Erase the first character + } + + // Check if the string ends with a double quote + if (!result.empty() && result.back() == '"') { + result.pop_back(); // Remove the last character + } + + return result; +} + + +bool EndsWith(const std::string& fullString, const std::string& ending) { + if (fullString.length() >= ending.length()) { + return (fullString.compare(fullString.length() - ending.length(), ending.length(), ending) == 0); + } else { + return false; + } +} + + +bool Update::RemoveDirectory(const std::string& directory_path) { try { // Check if the directory exists @@ -23,7 +103,7 @@ bool Update::rmDirectory(const std::string& directory_path) { return true; } -bool Update::isDirectory(const std::string& directory_path) { +bool Update::IsDirectory(const std::string& directory_path) { if (fs::exists(directory_path)) return true; @@ -65,13 +145,8 @@ bool Update::DownloadFile(const std::string& url, const std::string& outputFileN curl_version_info_data *info = curl_version_info(CURLVERSION_NOW); - if (info) { - // Print libcurl version information - LogPrintf("-bootstrap: libcurl version: %s \n", info->version); - LogPrintf("-bootstrap: libcurl SSL version: %s \n", info->ssl_version); - //LogPrintf("-bootstrap: libcurl zlib version: %s \n", info->libz_version); - } else { - LogPrintf("-bootstrap: Failed to retrieve libcurl version information.\n"); + if (!info) { + LogPrintf("-update: Failed to retrieve libcurl version information.\n"); } std::ofstream outputFile(outputFileName, std::ios::binary); @@ -86,6 +161,20 @@ bool Update::DownloadFile(const std::string& url, const std::string& outputFileN curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &outputFile); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + + // Follow redirects + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + + // Set the callback function to receive headers + std::string headers; + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headerCallback); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, &headers); + + // Set User-Agent header + if (info) { + curl_easy_setopt(curl, CURLOPT_USERAGENT, info->version); + } + if(func == nullptr) curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, ProgressCallback); else @@ -106,6 +195,13 @@ bool Update::DownloadFile(const std::string& url, const std::string& outputFileN CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + std::cerr << "Error: Failed to perform HTTP request: " << curl_easy_strerror(res) << std::endl; + } else { + // Print the received headers + std::cout << "Received headers:\n" << headers << std::endl; + } + curl_easy_cleanup(curl); outputFile.close(); @@ -117,7 +213,7 @@ bool Update::DownloadFile(const std::string& url, const std::string& outputFileN return true; } -bool Update::extractZip(const std::string& zipFilePath, const std::string& outputFolderPath) { +bool Update::ExtractZip(const std::string& zipFilePath, const std::string& outputFolderPath) { // Open the zip file unzFile zipFile = unzOpen(zipFilePath.c_str()); @@ -127,7 +223,7 @@ bool Update::extractZip(const std::string& zipFilePath, const std::string& outpu } // Create the output folder if it doesn't exist - if (!ensureOutputFolder(outputFolderPath)) { + if (!EnsureOutputFolder(outputFolderPath)) { LogPrintf("-bootstrap: Error creating output folder: %s \n",outputFolderPath); unzClose(zipFile); return false; @@ -160,8 +256,8 @@ bool Update::extractZip(const std::string& zipFilePath, const std::string& outpu std::string outputPath = std::string(outputFolderPath) + "/" + fileName; LogPrintf("-bootstrap: extract file: %s \n",fileName); - if(endsWithSlash(outputPath)) - ensureOutputFolder(outputPath); + if(EndsWithSlash(outputPath)) + EnsureOutputFolder(outputPath); else{ std::ofstream outFile(outputPath, std::ios::binary); if (!outFile.is_open()) { @@ -198,7 +294,7 @@ bool Update::extractZip(const std::string& zipFilePath, const std::string& outpu } -bool Update::ensureOutputFolder(const std::string& outputPath) { +bool Update::EnsureOutputFolder(const std::string& outputPath) { try { if (!fs::exists(outputPath)) { // Create the directory if it doesn't exist @@ -217,7 +313,234 @@ bool Update::ensureOutputFolder(const std::string& outputPath) { return true; } -bool Update::endsWithSlash(const std::string& str) { +bool Update::EndsWithSlash(const std::string& str) { // Check if the string ends with '/' return !str.empty() && str.back() == '/'; } + +void Update::ParseVersionRequest(json::value const& jv, std::string* indent){ + std::string indent_; + if(! indent) + indent = &indent_; + switch(jv.kind()) + { + case json::kind::object: + { + //std::cout << "{\n"; + indent->append(4, ' '); + auto const& obj = jv.get_object(); + if(! obj.empty()) + { + auto it = obj.begin(); + for(;;) + { + std::string key = json::serialize(it->key()); + if( key.compare("\"tag_name\"") == 0){ + latest.version = json::serialize(it->value().get_string()); + latest.version = RemoveQuotes(latest.version); + //std::cout << "remote version: " << latest.version << "\n"; + //ParseVersionNumber(version); + //std::cout << "local version: " << CLIENT_VERSION << "\n"; + }else if( key.compare("\"browser_download_url\"") == 0 ){ + std::string url = json::serialize(it->value().get_string()); + url = RemoveQuotes(url); + #if defined(__APPLE__) + if( EndsWith(url, "MacOs-x64.zip") || EndsWith(url, "macos-x64.zip") ) + latest.url = url; + #elif defined(__linux__) + if( EndsWith(url, "Linux-x64.zip") || EndsWith(url, "linux-x64.zip") ) + latest.url = url; + #elif defined(_WIN32) + if( EndsWith(url, "Windows-x64.zip") || EndsWith(url, "windows-x64.zip") ) + latest.url = url; + #else + std::cout << "not supported" << "\n"; + #endif + }else + ParseVersionRequest(it->value(), indent); + if(++it == obj.end()) + break; + //std::cout << ",\n"; + } + } + //std::cout << "\n"; + indent->resize(indent->size() - 4); + //std::cout << *indent << "}"; + break; + } + case json::kind::array: + { + //std::cout << "[\n"; + indent->append(4, ' '); + auto const& arr = jv.get_array(); + if(! arr.empty()) + { + auto it = arr.begin(); + for(;;) + { + //std::cout << *indent; + ParseVersionRequest(*it, indent); + if(++it == arr.end()) + break; + //std::cout << ",\n"; + } + } + //std::cout << "\n"; + indent->resize(indent->size() - 4); + //std::cout << *indent << "]"; + break; + } + } +} + +int ParseVersionNumber(std::string& version){ + std::vector versionNumbers; + + if (version.empty()){ + return -1; + std::cerr << "version is empty" << std::endl; + } + + if(version.find("-") > 0){ + version = version.substr(version.find("-")+1); + } + + // Remove the leading "v" from the version string + if(version[0] == 'v') { + version = version.substr(1); + } + + // check if format is x.x.x.x + + // Tokenize the version string based on the '.' delimiter + std::istringstream iss(version); + std::string token; + while (std::getline(iss, token, '.')) { + try { + int number = std::stoi(token); + versionNumbers.push_back(number); + } catch (const std::invalid_argument& ia) { + std::cerr << "Invalid version format: " << ia.what() << std::endl; + return -2; + } + } + + // Calculate the numerical value of the version + int versionValue = 0; + for (int i = 0; i < versionNumbers.size(); ++i) { + versionValue = versionValue * 100 + versionNumbers[i]; + } + + std::cout << "Numerical value of version " << version << ": " << versionValue << std::endl; + + return versionValue; +} + +int Update::GetRemoteVersion(){ + return ParseVersionNumber(latest.version); +} + +std::string base64Decode(const std::string &input, std::string &out) { + static constexpr unsigned char kDecodingTable[] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64 + }; + + size_t in_len = input.size(); + if (in_len % 4 != 0) + return "Input data size is not a multiple of 4"; + + size_t out_len = in_len / 4 * 3; + if (in_len >= 1 && input[in_len - 1] == '=') + out_len--; + if (in_len >= 2 && input[in_len - 2] == '=') + out_len--; + + out.resize(out_len); + + for (size_t i = 0, j = 0; i < in_len;) { + uint32_t a = input[i] == '=' + ? 0 & i++ + : kDecodingTable[static_cast(input[i++])]; + uint32_t b = input[i] == '=' + ? 0 & i++ + : kDecodingTable[static_cast(input[i++])]; + uint32_t c = input[i] == '=' + ? 0 & i++ + : kDecodingTable[static_cast(input[i++])]; + uint32_t d = input[i] == '=' + ? 0 & i++ + : kDecodingTable[static_cast(input[i++])]; + + uint32_t triple = + (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6); + + if (j < out_len) + out[j++] = (triple >> 2 * 8) & 0xFF; + if (j < out_len) + out[j++] = (triple >> 1 * 8) & 0xFF; + if (j < out_len) + out[j++] = (triple >> 0 * 8) & 0xFF; + } + + return ""; +} + +std::string stringToHex(const std::string& input) { + std::string hex; + for (char c : input) { + hex += "0123456789ABCDEF"[((unsigned char)c) >> 4]; + hex += "0123456789ABCDEF"[((unsigned char)c) & 0xf]; + } + return hex; +} + +int Update::GetLatestVersion(){ + + const std::string outputFileName = "app.zip"; + const std::string extractPath = "app_"; + std::cout << "get latest version from: " << latest.url << std::endl; + + if(latest.url.empty()){ + std::cerr << "No valid url to downloading new version" << std::endl; + return -1; + } + if (DownloadFile(latest.url, outputFileName, nullptr)) { + std::cout << "File downloaded successfully." << std::endl; + + std::string hexMD5 = CalculateMD5(outputFileName); + std::cout << "calculated md5: " << hexMD5 << std::endl; + + // get md5 from header + std::string headerMD5 = "Z+Ye9ExZ/IUfkl/Rb5piiQ=="; + std::string decoded = ""; + base64Decode(headerMD5,decoded); + std::string hex = stringToHex(decoded); + std::cout << "headerMD5: " << hex << std::endl; + + if (ExtractZip(outputFileName, extractPath)) { + std::cout << "Zip file extracted successfully." << std::endl; + } else { + std::cerr << "Error extracting zip file." << std::endl; + } + /* + if(IsDirectory(extractPath)) + RemoveDirectory(extractPath); + */ + } else { + std::cerr << "Error downloading file." << std::endl; + } +} \ No newline at end of file diff --git a/src/update/update.h b/src/update/update.h index bab05df1ea..04f03a9b4c 100644 --- a/src/update/update.h +++ b/src/update/update.h @@ -14,6 +14,7 @@ #include #include +#include #include "minizip/unzip.h" #ifdef UPDATETEST @@ -22,12 +23,12 @@ #include "../logging.h" #endif -#ifndef +#ifndef UPDATE_URL #define UPDATE_URL "https://api.github.com/repos/decenomy/" #endif #ifndef TICKER -#define TICKER "SAPP" +#define TICKER "DSW" #endif #ifdef NEWVERSION @@ -38,27 +39,37 @@ #define VERSION "1.0.0.0" #endif +#ifndef APPLE_CA_PATH #define APPLE_CA_PATH "/etc/ssl/cert.pem" +#endif //#define LINUX_CA_PATH "/etc/ssl/certs/ca-certificates.crt" //#define WIN_CA_PATH "" + +struct Latest { + std::string version; + std::string url; +}; + class Update{ public: // Define the function pointer type //using ProgressCallbackFunc = std::function; static int ProgressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow); - static bool init(const char* path); - static bool rmDirectory(const std::string& path); - static bool isDirectory(const std::string& path); + static bool RemoveDirectory(const std::string& path); + static bool IsDirectory(const std::string& path); static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp); static bool DownloadFile(const std::string& url, const std::string& outputFileName, curl_progress_callback); - static bool extractZip(const std::string& inputPath, const std::string& outputPath); - + static bool ExtractZip(const std::string& inputPath, const std::string& outputPath); + void ParseVersionRequest(boost::json::value const& jv, std::string* indent = nullptr); + int GetRemoteVersion(); + int GetLatestVersion(); private: - static bool ensureOutputFolder(const std::string& outputPath); - static bool endsWithSlash(const std::string& str); + static bool EnsureOutputFolder(const std::string& outputPath); + static bool EndsWithSlash(const std::string& str); + }; #endif