diff --git a/UI/CMakeLists.txt b/UI/CMakeLists.txt index 1206f2bef..ae881a3f6 100644 --- a/UI/CMakeLists.txt +++ b/UI/CMakeLists.txt @@ -81,7 +81,6 @@ include_directories(${LIBCURL_INCLUDE_DIRS}) add_definitions(${LIBCURL_DEFINITIONS}) if(WIN32) - include_directories(${OBS_JANSSON_INCLUDE_DIRS}) include_directories(${BLAKE2_INCLUDE_DIR}) set(obs_PLATFORM_SOURCES @@ -96,8 +95,7 @@ if(WIN32) win-update/win-update-helpers.hpp) set(obs_PLATFORM_LIBRARIES crypt32 - blake2 - ${OBS_JANSSON_IMPORT}) + blake2) if(CMAKE_SIZEOF_VOID_P EQUAL 4) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") diff --git a/UI/win-update/updater/CMakeLists.txt b/UI/win-update/updater/CMakeLists.txt index 83309c362..dcf43f6b7 100644 --- a/UI/win-update/updater/CMakeLists.txt +++ b/UI/win-update/updater/CMakeLists.txt @@ -9,17 +9,19 @@ endif() project(updater) -include_directories(${OBS_JANSSON_INCLUDE_DIRS}) include_directories(${LIBLZMA_INCLUDE_DIRS}) +include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/deps/json11") include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs") include_directories(${BLAKE2_INCLUDE_DIR}) set(updater_HEADERS + ${CMAKE_SOURCE_DIR}/deps/json11/json11.hpp ../win-update-helpers.hpp resource.h updater.hpp ) set(updater_SOURCES + ${CMAKE_SOURCE_DIR}/deps/json11/json11.cpp ../win-update-helpers.cpp init-hook-files.c updater.cpp @@ -40,7 +42,6 @@ add_executable(updater WIN32 ${updater_SOURCES} ) target_link_libraries(updater - ${OBS_JANSSON_IMPORT} ${STATIC_ZLIB_PATH} lzma blake2 diff --git a/UI/win-update/updater/updater.cpp b/UI/win-update/updater/updater.cpp index 6a2d6f322..7fe7db809 100644 --- a/UI/win-update/updater/updater.cpp +++ b/UI/win-update/updater/updater.cpp @@ -26,6 +26,7 @@ #include using namespace std; +using namespace json11; /* ----------------------------------------------------------------------- */ @@ -603,68 +604,63 @@ static inline bool is_64bit_file(const char *file) strstr(file, "64.exe") != nullptr; } -static inline bool has_str(const char *file, const char *str) -{ - return (file && str) ? (strstr(file, str) != nullptr) : false; -} - #define UTF8ToWideBuf(wide, utf8) UTF8ToWide(wide, _countof(wide), utf8) #define WideToUTF8Buf(utf8, wide) WideToUTF8(utf8, _countof(utf8), wide) #define UPDATE_URL L"https://cdn-fastly.obsproject.com/update_studio" -static bool AddPackageUpdateFiles(json_t *root, size_t idx, +static bool AddPackageUpdateFiles(const Json &root, size_t idx, const wchar_t *tempPath) { - json_t *package = json_array_get(root, idx); - json_t *name = json_object_get(package, "name"); - json_t *files = json_object_get(package, "files"); + const Json &package = root[idx]; + const Json &name = package["name"]; + const Json &files = package["files"]; bool isWin64 = is_64bit_windows(); - if (!json_is_array(files)) + if (!files.is_array()) return true; - if (!json_is_string(name)) + if (!name.is_string()) return true; wchar_t wPackageName[512]; - const char *packageName = json_string_value(name); - size_t fileCount = json_array_size(files); + const string &packageName = name.string_value(); + size_t fileCount = files.array_items().size(); - if (!UTF8ToWideBuf(wPackageName, packageName)) + if (!UTF8ToWideBuf(wPackageName, packageName.c_str())) return false; - if (strcmp(packageName, "core") != 0 && - !NonCorePackageInstalled(packageName)) + if (packageName != "core" && + !NonCorePackageInstalled(packageName.c_str())) return true; for (size_t j = 0; j < fileCount; j++) { - json_t *file = json_array_get(files, j); - json_t *fileName = json_object_get(file, "name"); - json_t *hash = json_object_get(file, "hash"); - json_t *size = json_object_get(file, "size"); + const Json &file = files[j]; + const Json &fileName = file["name"]; + const Json &hash = file["hash"]; + const Json &size = file["size"]; - if (!json_is_string(fileName)) + if (!fileName.is_string()) continue; - if (!json_is_string(hash)) + if (!hash.is_string()) continue; - if (!json_is_integer(size)) + if (!size.is_number()) continue; - const char *fileUTF8 = json_string_value(fileName); - const char *hashUTF8 = json_string_value(hash); - int fileSize = (int)json_integer_value(size); + const string &fileUTF8 = fileName.string_value(); + const string &hashUTF8 = hash.string_value(); + int fileSize = size.int_value(); - if (strlen(hashUTF8) != BLAKE2_HASH_LENGTH * 2) + if (hashUTF8.size() != BLAKE2_HASH_LENGTH * 2) continue; - if (!isWin64 && is_64bit_file(fileUTF8)) + if (!isWin64 && is_64bit_file(fileUTF8.c_str())) continue; /* ignore update files of opposite arch to reduce download */ - if ((is32bit && has_str(fileUTF8, "/64bit/")) || - (!is32bit && has_str(fileUTF8, "/32bit/"))) + if ((is32bit && fileUTF8.find("/64bit/") != string::npos) || + (!is32bit && fileUTF8.find("/32bit/") != string::npos)) continue; /* convert strings to wide */ @@ -674,9 +670,9 @@ static bool AddPackageUpdateFiles(json_t *root, size_t idx, wchar_t updateHashStr[BLAKE2_HASH_STR_LENGTH]; wchar_t tempFilePath[MAX_PATH]; - if (!UTF8ToWideBuf(updateFileName, fileUTF8)) + if (!UTF8ToWideBuf(updateFileName, fileUTF8.c_str())) continue; - if (!UTF8ToWideBuf(updateHashStr, hashUTF8)) + if (!UTF8ToWideBuf(updateHashStr, hashUTF8.c_str())) continue; /* make sure paths are safe */ @@ -928,7 +924,7 @@ static wchar_t tempPath[MAX_PATH] = {}; L"https://obsproject.com/update_studio/getpatchmanifest" #define HASH_NULL L"0000000000000000000000000000000000000000" -static bool UpdateVS2019Redists(json_t *root) +static bool UpdateVS2019Redists(const Json &root) { /* ------------------------------------------ * * Initialize session */ @@ -992,18 +988,18 @@ static bool UpdateVS2019Redists(json_t *root) /* ------------------------------------------ * * Get expected hash */ - json_t *redistJson = json_object_get( - root, is32bit ? "vc2019_redist_x86" : "vc2019_redist_x64"); - if (!redistJson) { + const char *which = is32bit ? "vc2019_redist_x86" : "vc2019_redist_x64"; + const Json &redistJson = root[which]; + if (!redistJson.is_string()) { Status(L"Update failed: Could not parse VC2019 redist json"); return false; } - const char *expectedHashUTF8 = json_string_value(redistJson); + const string &expectedHashUTF8 = redistJson.string_value(); wchar_t expectedHashWide[BLAKE2_HASH_STR_LENGTH]; BYTE expectedHash[BLAKE2_HASH_LENGTH]; - if (!UTF8ToWideBuf(expectedHashWide, expectedHashUTF8)) { + if (!UTF8ToWideBuf(expectedHashWide, expectedHashUTF8.c_str())) { DeleteFile(destPath.c_str()); Status(L"Update failed: Couldn't convert Json for redist hash"); return false; @@ -1218,18 +1214,18 @@ static bool Update(wchar_t *cmdLine) return false; } - json_error_t error; - root = json_loads(manifestFile.c_str(), 0, &error); + string error; + root = Json::parse(manifestFile, error); - if (!root) { + if (!error.empty()) { Status(L"Update failed: Couldn't parse update " L"manifest: %S", - error.text); + error.c_str()); return false; } } - if (!json_is_object(root.get())) { + if (!root.is_object()) { Status(L"Update failed: Invalid update manifest"); return false; } @@ -1237,10 +1233,8 @@ static bool Update(wchar_t *cmdLine) /* ------------------------------------- * * Parse current manifest update files */ - json_t *packages = json_object_get(root, "packages"); - size_t packageCount = json_array_size(packages); - - for (size_t i = 0; i < packageCount; i++) { + const Json::array &packages = root["packages"].array_items(); + for (size_t i = 0; i < packages.size(); i++) { if (!AddPackageUpdateFiles(packages, i, tempPath)) { Status(L"Update failed: Failed to process update packages"); return false; @@ -1271,7 +1265,7 @@ static bool Update(wchar_t *cmdLine) /* ------------------------------------- * * Generate file hash json */ - Json files(json_array()); + Json::array files; for (update_t &update : updates) { wchar_t whash_string[BLAKE2_HASH_STR_LENGTH]; @@ -1296,10 +1290,10 @@ static bool Update(wchar_t *cmdLine) package_path += "/"; package_path += outputPath; - json_t *obj = json_object(); - json_object_set(obj, "name", json_string(package_path.c_str())); - json_object_set(obj, "hash", json_string(hash_string)); - json_array_append_new(files, obj); + files.emplace_back(Json::object{ + {"name", package_path}, + {"hash", hash_string}, + }); } /* ------------------------------------- * @@ -1307,18 +1301,20 @@ static bool Update(wchar_t *cmdLine) string newManifest; - if (json_array_size(files) > 0) { - char *post_body = json_dumps(files, JSON_COMPACT); + if (files.size() > 0) { + string post_body; + Json(files).dump(post_body); int responseCode; - int len = (int)strlen(post_body); + int len = (int)post_body.size(); uLong compressSize = compressBound(len); string compressedJson; compressedJson.resize(compressSize); compress2((Bytef *)&compressedJson[0], &compressSize, - (const Bytef *)post_body, len, Z_BEST_COMPRESSION); + (const Bytef *)post_body.c_str(), len, + Z_BEST_COMPRESSION); compressedJson.resize(compressSize); bool success = !!HTTPPostData(PATCH_MANIFEST_URL, @@ -1326,7 +1322,6 @@ static bool Update(wchar_t *cmdLine) (int)compressedJson.size(), L"Accept-Encoding: gzip", &responseCode, newManifest); - free(post_body); if (!success) return false; @@ -1344,49 +1339,50 @@ static bool Update(wchar_t *cmdLine) /* ------------------------------------- * * Parse new manifest */ - json_error_t error; - root = json_loads(newManifest.c_str(), 0, &error); - if (!root) { + string error; + root = Json::parse(newManifest, error); + if (!error.empty()) { Status(L"Update failed: Couldn't parse patch manifest: %S", - error.text); + error.c_str()); return false; } - if (!json_is_array(root.get())) { + if (!root.is_array()) { Status(L"Update failed: Invalid patch manifest"); return false; } - packageCount = json_array_size(root); + size_t packageCount = root.array_items().size(); for (size_t i = 0; i < packageCount; i++) { - json_t *patch = json_array_get(root, i); + const Json &patch = root[i]; - if (!json_is_object(patch)) { + if (!patch.is_object()) { Status(L"Update failed: Invalid patch manifest"); return false; } - json_t *name_json = json_object_get(patch, "name"); - json_t *hash_json = json_object_get(patch, "hash"); - json_t *source_json = json_object_get(patch, "source"); - json_t *size_json = json_object_get(patch, "size"); + const Json &name_json = patch["name"]; + const Json &hash_json = patch["hash"]; + const Json &source_json = patch["source"]; + const Json &size_json = patch["size"]; - if (!json_is_string(name_json)) + if (!name_json.is_string()) continue; - if (!json_is_string(hash_json)) + if (!hash_json.is_string()) continue; - if (!json_is_string(source_json)) + if (!source_json.is_string()) continue; - if (!json_is_integer(size_json)) + if (!size_json.is_number()) continue; - const char *name = json_string_value(name_json); - const char *hash = json_string_value(hash_json); - const char *source = json_string_value(source_json); - int size = (int)json_integer_value(size_json); + const string &name = name_json.string_value(); + const string &hash = hash_json.string_value(); + const string &source = source_json.string_value(); + int size = size_json.int_value(); - UpdateWithPatchIfAvailable(name, hash, source, size); + UpdateWithPatchIfAvailable(name.c_str(), hash.c_str(), + source.c_str(), size); } /* ------------------------------------- * diff --git a/UI/win-update/updater/updater.hpp b/UI/win-update/updater/updater.hpp index 1297ce6d3..812d1da7a 100644 --- a/UI/win-update/updater/updater.hpp +++ b/UI/win-update/updater/updater.hpp @@ -74,7 +74,7 @@ #endif #include -#include +#include #include "resource.h" bool HTTPGetFile(HINTERNET hConnect, const wchar_t *url, diff --git a/UI/win-update/win-update-helpers.hpp b/UI/win-update/win-update-helpers.hpp index ef6aa5900..3f7040c87 100644 --- a/UI/win-update/win-update-helpers.hpp +++ b/UI/win-update/win-update-helpers.hpp @@ -4,8 +4,6 @@ #include #include -#include - #include #include @@ -69,72 +67,5 @@ public: /* ------------------------------------------------------------------------ */ -class Json { - json_t *json; - -public: - inline Json() : json(nullptr) {} - explicit inline Json(json_t *json_) : json(json_) {} - inline Json(const Json &from) : json(json_incref(from.json)) {} - inline Json(Json &&from) : json(from.json) { from.json = nullptr; } - - inline ~Json() - { - if (json) - json_decref(json); - } - - inline Json &operator=(json_t *json_) - { - if (json) - json_decref(json); - json = json_; - return *this; - } - inline Json &operator=(const Json &from) - { - if (json) - json_decref(json); - json = json_incref(from.json); - return *this; - } - inline Json &operator=(Json &&from) - { - if (json) - json_decref(json); - json = from.json; - from.json = nullptr; - return *this; - } - - inline operator json_t *() const { return json; } - - inline bool operator!() const { return !json; } - - inline const char *GetString(const char *name, - const char *def = nullptr) const - { - json_t *obj(json_object_get(json, name)); - if (!obj) - return def; - return json_string_value(obj); - } - inline int64_t GetInt(const char *name, int def = 0) const - { - json_t *obj(json_object_get(json, name)); - if (!obj) - return def; - return json_integer_value(obj); - } - inline json_t *GetObject(const char *name) const - { - return json_object_get(json, name); - } - - inline json_t *get() const { return json; } -}; - -/* ------------------------------------------------------------------------ */ - std::string vstrprintf(const char *format, va_list args); std::string strprintf(const char *format, ...); diff --git a/UI/win-update/win-update.cpp b/UI/win-update/win-update.cpp index 9371a8c7e..2722ee75c 100644 --- a/UI/win-update/win-update.cpp +++ b/UI/win-update/win-update.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -25,6 +25,7 @@ #endif using namespace std; +using namespace json11; struct QCef; extern QCef *cef; @@ -402,31 +403,31 @@ static bool ParseUpdateManifest(const char *manifest, bool *updatesAvailable, string ¬es_str, int &updateVer) try { - json_error_t error; - Json root(json_loads(manifest, 0, &error)); - if (!root) - throw strprintf("Failed reading json string (%d): %s", - error.line, error.text); + string error; + Json root = Json::parse(manifest, error); + if (!error.empty()) + throw strprintf("Failed reading json string: %s", + error.c_str()); - if (!json_is_object(root.get())) + if (!root.is_object()) throw string("Root of manifest is not an object"); - int major = root.GetInt("version_major"); - int minor = root.GetInt("version_minor"); - int patch = root.GetInt("version_patch"); + int major = root["version_major"].int_value(); + int minor = root["version_minor"].int_value(); + int patch = root["version_patch"].int_value(); if (major == 0) throw strprintf("Invalid version number: %d.%d.%d", major, minor, patch); - json_t *notes = json_object_get(root, "notes"); - if (!json_is_string(notes)) + const Json ¬es = root["notes"]; + if (!notes.is_string()) throw string("'notes' value invalid"); - notes_str = json_string_value(notes); + notes_str = notes.string_value(); - json_t *packages = json_object_get(root, "packages"); - if (!json_is_array(packages)) + const Json &packages = root["packages"]; + if (!packages.is_array()) throw string("'packages' value invalid"); int cur_ver = LIBOBS_API_VER;