diff --git a/src/api.cpp b/src/api.cpp index b84226b..2bb6ce3 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -83,47 +83,40 @@ int API::getAPIConfig() std::string url = "https://api.gog.com/downloader2/status/stable/"; // Stable API //std::string url = "https://api.gog.com/downloader2/status/beta/"; // Beta API //std::string url = "https://api.gog.com/downloader2/status/e77989ed21758e78331b20e477fc5582/"; // Development API? Not sure because the downloader version number it reports is lower than beta. - int res = 0; std::string json = this->getResponse(url); - if (!json.empty()) - { - Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << root << std::endl; - #endif - this->config.oauth_authorize_temp_token = root["config"]["oauth_authorize_temp_token"].asString() + "/"; - this->config.oauth_get_temp_token = root["config"]["oauth_get_temp_token"].asString() + "/"; - this->config.oauth_get_token = root["config"]["oauth_get_token"].asString() + "/"; - this->config.get_user_games = root["config"]["get_user_games"].asString() + "/"; - this->config.get_user_details = root["config"]["get_user_details"].asString() + "/"; - this->config.get_installer_link = root["config"]["get_installer_link"].asString() + "/"; - this->config.get_game_details = root["config"]["get_game_details"].asString() + "/"; - this->config.get_extra_link = root["config"]["get_extra_link"].asString() + "/"; - this->config.set_app_status = root["config"]["set_app_status"].asString() + "/"; - res = 1; - } - else - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << json << std::endl; - #endif - this->setError(jsonparser->getFormattedErrorMessages()); - res = 0; - } - delete jsonparser; - } - else - { + if (json.empty()) { this->setError("Found nothing in " + url); - res = 0; + return 0; } - return res; + Json::Value root; + std::istringstream json_stream(json); + + try { + json_stream >> root; + } catch (const Json::Exception& exc) { + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << json << std::endl; + #endif + this->setError(exc.what()); + return 0; + } + + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getAPIConfig)" << std::endl << root << std::endl; + #endif + this->config.oauth_authorize_temp_token = root["config"]["oauth_authorize_temp_token"].asString() + "/"; + this->config.oauth_get_temp_token = root["config"]["oauth_get_temp_token"].asString() + "/"; + this->config.oauth_get_token = root["config"]["oauth_get_token"].asString() + "/"; + this->config.get_user_games = root["config"]["get_user_games"].asString() + "/"; + this->config.get_user_details = root["config"]["get_user_details"].asString() + "/"; + this->config.get_installer_link = root["config"]["get_installer_link"].asString() + "/"; + this->config.get_game_details = root["config"]["get_game_details"].asString() + "/"; + this->config.get_extra_link = root["config"]["get_extra_link"].asString() + "/"; + this->config.set_app_status = root["config"]["set_app_status"].asString() + "/"; + return 1; } int API::login(const std::string& email, const std::string& password) @@ -191,48 +184,41 @@ int API::login(const std::string& email, const std::string& password) int API::getUserDetails() { - int res = 0; std::string url; url = this->config.get_user_details; std::string json = this->getResponseOAuth(url); - if (!json.empty()) - { - Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << root << std::endl; - #endif - this->user.id = std::stoull(root["user"]["id"].asString()); - this->user.username = root["user"]["xywka"].asString(); - this->user.email = root["user"]["email"].asString(); - this->user.avatar_big = root["user"]["avatar"]["big"].asString(); - this->user.avatar_small = root["user"]["avatar"]["small"].asString(); - this->user.notifications_forum = root["user"]["notifications"]["forum"].isInt() ? root["user"]["notifications"]["forum"].asInt() : std::stoi(root["user"]["notifications"]["forum"].asString()); - this->user.notifications_games = root["user"]["notifications"]["games"].isInt() ? root["user"]["notifications"]["games"].asInt() : std::stoi(root["user"]["notifications"]["games"].asString()); - this->user.notifications_messages = root["user"]["notifications"]["messages"].isInt() ? root["user"]["notifications"]["messages"].asInt() : std::stoi(root["user"]["notifications"]["messages"].asString()); - res = 1; - } - else - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << json << std::endl; - #endif - this->setError(jsonparser->getFormattedErrorMessages()); - res = 0; - } - delete jsonparser; - } - else - { + if (json.empty()) { this->setError("Found nothing in " + url); - res = 0; + return 0; } - return res; + Json::Value root; + std::istringstream json_stream(json); + + try { + json_stream >> root; + } catch (const Json::Exception& exc) { + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << json << std::endl; + #endif + this->setError(exc.what()); + return 0; + } + + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getUserDetails)" << std::endl << root << std::endl; + #endif + this->user.id = std::stoull(root["user"]["id"].asString()); + this->user.username = root["user"]["xywka"].asString(); + this->user.email = root["user"]["email"].asString(); + this->user.avatar_big = root["user"]["avatar"]["big"].asString(); + this->user.avatar_small = root["user"]["avatar"]["small"].asString(); + this->user.notifications_forum = root["user"]["notifications"]["forum"].isInt() ? root["user"]["notifications"]["forum"].asInt() : std::stoi(root["user"]["notifications"]["forum"].asString()); + this->user.notifications_games = root["user"]["notifications"]["games"].isInt() ? root["user"]["notifications"]["games"].asInt() : std::stoi(root["user"]["notifications"]["games"].asString()); + this->user.notifications_messages = root["user"]["notifications"]["messages"].isInt() ? root["user"]["notifications"]["messages"].asInt() : std::stoi(root["user"]["notifications"]["messages"].asString()); + return 1; } @@ -311,267 +297,265 @@ gameDetails API::getGameDetails(const std::string& game_name, const unsigned int url = this->config.get_game_details + game_name + "/" + "installer_win_en"; // can't get game details without file id, any file id seems to return all details which is good for us std::string json = this->getResponseOAuth(url); - if (!json.empty()) - { - Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) + if (json.empty()) { + this->setError("Found nothing in " + url); + return game; + } + + Json::Value root; + std::istringstream json_stream(json); + + try { + json_stream >> root; + } catch (Json::Exception exc) { + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << json << std::endl; + #endif + this->setError(exc.what()); + return game; + } + + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << root << std::endl; + #endif + game.gamename = game_name; + game.title = root["game"]["title"].asString(); + game.icon = root["game"]["icon"].asString(); + std::vector membernames = root["game"].getMemberNames(); + + // Installer details + // Create a list of installers from JSON + std::vector installers; + for (unsigned int i = 0; i < GlobalConstants::PLATFORMS.size(); ++i) + { // Check against the specified platforms + if (platform & GlobalConstants::PLATFORMS[i].id) { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << root << std::endl; - #endif - game.gamename = game_name; - game.title = root["game"]["title"].asString(); - game.icon = root["game"]["icon"].asString(); - std::vector membernames = root["game"].getMemberNames(); - - // Installer details - // Create a list of installers from JSON - std::vector installers; - for (unsigned int i = 0; i < GlobalConstants::PLATFORMS.size(); ++i) - { // Check against the specified platforms - if (platform & GlobalConstants::PLATFORMS[i].id) - { - std::string installer = "installer_" + GlobalConstants::PLATFORMS[i].code + "_"; - for (unsigned int j = 0; j < GlobalConstants::LANGUAGES.size(); ++j) - { // Check against the specified languages - if (lang & GlobalConstants::LANGUAGES[j].id) - { // Make sure that the installer exists in the JSON - if (root["game"].isMember(installer+GlobalConstants::LANGUAGES[j].code)) - { - gameFileInfo installerInfo; - installerInfo.jsonNode = root["game"][installer+GlobalConstants::LANGUAGES[j].code]; - installerInfo.platform = GlobalConstants::PLATFORMS[i].id; - installerInfo.language = GlobalConstants::LANGUAGES[j].id; - installers.push_back(installerInfo); - } - } - } - } - } - - for ( unsigned int i = 0; i < installers.size(); ++i ) - { - for ( unsigned int index = 0; index < installers[i].jsonNode.size(); ++index ) - { - Json::Value installer = installers[i].jsonNode[index]; - unsigned int language = installers[i].language; - std::string path = installer["link"].asString(); - path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL); - - // Check for duplicate installers in different languages and add languageId of duplicate installer to the original installer - // https://secure.gog.com/forum/general/introducing_the_beta_release_of_the_new_gogcom_downloader/post1483 - if (useDuplicateHandler) - { - bool bDuplicate = false; - for (unsigned int j = 0; j < game.installers.size(); ++j) - { - if (game.installers[j].path == path) - { - game.installers[j].language |= language; // Add language code to installer - bDuplicate = true; - break; - } - } - if (bDuplicate) - continue; - } - - gameFile gf; - gf.type = GFTYPE_INSTALLER; - gf.gamename = game.gamename; - gf.updated = installer["notificated"].isInt() ? installer["notificated"].asInt() : std::stoi(installer["notificated"].asString()); - gf.id = installer["id"].isInt() ? std::to_string(installer["id"].asInt()) : installer["id"].asString(); - gf.name = installer["name"].asString(); - gf.path = path; - gf.size = installer["size"].asString(); - gf.language = language; - gf.platform = installers[i].platform; - gf.silent = installer["silent"].isInt() ? installer["silent"].asInt() : std::stoi(installer["silent"].asString()); - - game.installers.push_back(gf); - } - } - - // Extra details - const Json::Value extras = root["game"]["extras"]; - for ( unsigned int index = 0; index < extras.size(); ++index ) - { - Json::Value extra = extras[index]; - - gameFile gf; - gf.type = GFTYPE_EXTRA; - gf.gamename = game.gamename; - gf.updated = false; // extras don't have "updated" flag - gf.id = extra["id"].isInt() ? std::to_string(extra["id"].asInt()) : extra["id"].asString(); - gf.name = extra["name"].asString(); - gf.path = extra["link"].asString(); - gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL); - gf.size = extra["size_mb"].asString(); - - game.extras.push_back(gf); - } - - // Patch details - for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i) + std::string installer = "installer_" + GlobalConstants::PLATFORMS[i].code + "_"; + for (unsigned int j = 0; j < GlobalConstants::LANGUAGES.size(); ++j) { // Check against the specified languages - if (lang & GlobalConstants::LANGUAGES[i].id) - { - // Try to find a patch - _regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+patch\\d+", _regex_namespace_::regex_constants::icase); // regex for patch node names - std::vector patches; - for (unsigned int j = 0; j < membernames.size(); ++j) + if (lang & GlobalConstants::LANGUAGES[j].id) + { // Make sure that the installer exists in the JSON + if (root["game"].isMember(installer+GlobalConstants::LANGUAGES[j].code)) { - if (_regex_namespace_::regex_match(membernames[j], re)) - { // Regex matches, we have a patch node - gameFileInfo patchInfo; - patchInfo.jsonNode = root["game"][membernames[j]]; - patchInfo.language = GlobalConstants::LANGUAGES[i].id; - if (patchInfo.jsonNode["link"].asString().find("/mac/") != std::string::npos) - patchInfo.platform = GlobalConstants::PLATFORM_MAC; - else if (patchInfo.jsonNode["link"].asString().find("/linux/") != std::string::npos) - patchInfo.platform = GlobalConstants::PLATFORM_LINUX; - else - patchInfo.platform = GlobalConstants::PLATFORM_WINDOWS; - - if (platform & patchInfo.platform) - patches.push_back(patchInfo); - } - } - - if (!patches.empty()) // found at least one patch - { - for (unsigned int j = 0; j < patches.size(); ++j) - { - Json::Value patchnode = patches[j].jsonNode; - if (patchnode.isArray()) // Patch has multiple files - { - for ( unsigned int index = 0; index < patchnode.size(); ++index ) - { - Json::Value patch = patchnode[index]; - std::string path = patch["link"].asString(); - path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL); - - // Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch - if (useDuplicateHandler) - { - bool bDuplicate = false; - for (unsigned int j = 0; j < game.patches.size(); ++j) - { - if (game.patches[j].path == path) - { - game.patches[j].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch - bDuplicate = true; - break; - } - } - if (bDuplicate) - continue; - } - - gameFile gf; - gf.type = GFTYPE_PATCH; - gf.gamename = game.gamename; - gf.updated = patch["notificated"].isInt() ? patch["notificated"].asInt() : std::stoi(patch["notificated"].asString()); - gf.id = patch["id"].isInt() ? std::to_string(patch["id"].asInt()) : patch["id"].asString(); - gf.name = patch["name"].asString(); - gf.path = path; - gf.size = patch["size"].asString(); - gf.language = GlobalConstants::LANGUAGES[i].id; - gf.platform = patches[j].platform; - - game.patches.push_back(gf); - } - } - else // Patch is a single file - { - std::string path = patchnode["link"].asString(); - path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL); - - // Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch - if (useDuplicateHandler) - { - bool bDuplicate = false; - for (unsigned int k = 0; k < game.patches.size(); ++k) - { - if (game.patches[k].path == path) - { - game.patches[k].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch - bDuplicate = true; - break; - } - } - if (bDuplicate) - continue; - } - - gameFile gf; - gf.type = GFTYPE_PATCH; - gf.gamename = game.gamename; - gf.updated = patchnode["notificated"].isInt() ? patchnode["notificated"].asInt() : std::stoi(patchnode["notificated"].asString()); - gf.id = patchnode["id"].isInt() ? std::to_string(patchnode["id"].asInt()) : patchnode["id"].asString(); - gf.name = patchnode["name"].asString(); - gf.path = path; - gf.size = patchnode["size"].asString(); - gf.language = GlobalConstants::LANGUAGES[i].id; - gf.platform = patches[j].platform; - - game.patches.push_back(gf); - } - } + gameFileInfo installerInfo; + installerInfo.jsonNode = root["game"][installer+GlobalConstants::LANGUAGES[j].code]; + installerInfo.platform = GlobalConstants::PLATFORMS[i].id; + installerInfo.language = GlobalConstants::LANGUAGES[j].id; + installers.push_back(installerInfo); } } } + } + } - // Language pack details - for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i) - { // Check against the specified languages - if (lang & GlobalConstants::LANGUAGES[i].id) + for ( unsigned int i = 0; i < installers.size(); ++i ) + { + for ( unsigned int index = 0; index < installers[i].jsonNode.size(); ++index ) + { + Json::Value installer = installers[i].jsonNode[index]; + unsigned int language = installers[i].language; + std::string path = installer["link"].asString(); + path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL); + + // Check for duplicate installers in different languages and add languageId of duplicate installer to the original installer + // https://secure.gog.com/forum/general/introducing_the_beta_release_of_the_new_gogcom_downloader/post1483 + if (useDuplicateHandler) + { + bool bDuplicate = false; + for (unsigned int j = 0; j < game.installers.size(); ++j) { - // Try to find a language pack - _regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+langpack\\d+", _regex_namespace_::regex_constants::icase); // regex for language pack node names - std::vector langpacknames; - for (unsigned int j = 0; j < membernames.size(); ++j) + if (game.installers[j].path == path) { - if (_regex_namespace_::regex_match(membernames[j], re)) - langpacknames.push_back(membernames[j]); + game.installers[j].language |= language; // Add language code to installer + bDuplicate = true; + break; } + } + if (bDuplicate) + continue; + } - if (!langpacknames.empty()) // found at least one language pack + gameFile gf; + gf.type = GFTYPE_INSTALLER; + gf.gamename = game.gamename; + gf.updated = installer["notificated"].isInt() ? installer["notificated"].asInt() : std::stoi(installer["notificated"].asString()); + gf.id = installer["id"].isInt() ? std::to_string(installer["id"].asInt()) : installer["id"].asString(); + gf.name = installer["name"].asString(); + gf.path = path; + gf.size = installer["size"].asString(); + gf.language = language; + gf.platform = installers[i].platform; + gf.silent = installer["silent"].isInt() ? installer["silent"].asInt() : std::stoi(installer["silent"].asString()); + + game.installers.push_back(gf); + } + } + + // Extra details + const Json::Value extras = root["game"]["extras"]; + for ( unsigned int index = 0; index < extras.size(); ++index ) + { + Json::Value extra = extras[index]; + + gameFile gf; + gf.type = GFTYPE_EXTRA; + gf.gamename = game.gamename; + gf.updated = false; // extras don't have "updated" flag + gf.id = extra["id"].isInt() ? std::to_string(extra["id"].asInt()) : extra["id"].asString(); + gf.name = extra["name"].asString(); + gf.path = extra["link"].asString(); + gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL); + gf.size = extra["size_mb"].asString(); + + game.extras.push_back(gf); + } + + // Patch details + for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i) + { // Check against the specified languages + if (lang & GlobalConstants::LANGUAGES[i].id) + { + // Try to find a patch + _regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+patch\\d+", _regex_namespace_::regex_constants::icase); // regex for patch node names + std::vector patches; + for (unsigned int j = 0; j < membernames.size(); ++j) + { + if (_regex_namespace_::regex_match(membernames[j], re)) + { // Regex matches, we have a patch node + gameFileInfo patchInfo; + patchInfo.jsonNode = root["game"][membernames[j]]; + patchInfo.language = GlobalConstants::LANGUAGES[i].id; + if (patchInfo.jsonNode["link"].asString().find("/mac/") != std::string::npos) + patchInfo.platform = GlobalConstants::PLATFORM_MAC; + else if (patchInfo.jsonNode["link"].asString().find("/linux/") != std::string::npos) + patchInfo.platform = GlobalConstants::PLATFORM_LINUX; + else + patchInfo.platform = GlobalConstants::PLATFORM_WINDOWS; + + if (platform & patchInfo.platform) + patches.push_back(patchInfo); + } + } + + if (!patches.empty()) // found at least one patch + { + for (unsigned int j = 0; j < patches.size(); ++j) + { + Json::Value patchnode = patches[j].jsonNode; + if (patchnode.isArray()) // Patch has multiple files { - for (unsigned int j = 0; j < langpacknames.size(); ++j) + for ( unsigned int index = 0; index < patchnode.size(); ++index ) { - Json::Value langpack = root["game"][langpacknames[j]]; + Json::Value patch = patchnode[index]; + std::string path = patch["link"].asString(); + path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL); + + // Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch + if (useDuplicateHandler) + { + bool bDuplicate = false; + for (unsigned int j = 0; j < game.patches.size(); ++j) + { + if (game.patches[j].path == path) + { + game.patches[j].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch + bDuplicate = true; + break; + } + } + if (bDuplicate) + continue; + } gameFile gf; - gf.type = GFTYPE_LANGPACK; + gf.type = GFTYPE_PATCH; gf.gamename = game.gamename; - gf.updated = false; // language packs don't have "updated" flag - gf.id = langpack["id"].isInt() ? std::to_string(langpack["id"].asInt()) : langpack["id"].asString(); - gf.name = langpack["name"].asString(); - gf.path = langpack["link"].asString(); - gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL); - gf.size = langpack["size"].asString(); + gf.updated = patch["notificated"].isInt() ? patch["notificated"].asInt() : std::stoi(patch["notificated"].asString()); + gf.id = patch["id"].isInt() ? std::to_string(patch["id"].asInt()) : patch["id"].asString(); + gf.name = patch["name"].asString(); + gf.path = path; + gf.size = patch["size"].asString(); gf.language = GlobalConstants::LANGUAGES[i].id; + gf.platform = patches[j].platform; - game.languagepacks.push_back(gf); + game.patches.push_back(gf); } } + else // Patch is a single file + { + std::string path = patchnode["link"].asString(); + path = (std::string)curl_easy_unescape(curlhandle, path.c_str(), path.size(), NULL); + + // Check for duplicate patches in different languages and add languageId of duplicate patch to the original patch + if (useDuplicateHandler) + { + bool bDuplicate = false; + for (unsigned int k = 0; k < game.patches.size(); ++k) + { + if (game.patches[k].path == path) + { + game.patches[k].language |= GlobalConstants::LANGUAGES[i].id; // Add language code to patch + bDuplicate = true; + break; + } + } + if (bDuplicate) + continue; + } + + gameFile gf; + gf.type = GFTYPE_PATCH; + gf.gamename = game.gamename; + gf.updated = patchnode["notificated"].isInt() ? patchnode["notificated"].asInt() : std::stoi(patchnode["notificated"].asString()); + gf.id = patchnode["id"].isInt() ? std::to_string(patchnode["id"].asInt()) : patchnode["id"].asString(); + gf.name = patchnode["name"].asString(); + gf.path = path; + gf.size = patchnode["size"].asString(); + gf.language = GlobalConstants::LANGUAGES[i].id; + gf.platform = patches[j].platform; + + game.patches.push_back(gf); + } } } } - else - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getGameDetails)" << std::endl << json << std::endl; - #endif - this->setError(jsonparser->getFormattedErrorMessages()); - } - delete jsonparser; } - else - { - this->setError("Found nothing in " + url); + + // Language pack details + for (unsigned int i = 0; i < GlobalConstants::LANGUAGES.size(); ++i) + { // Check against the specified languages + if (lang & GlobalConstants::LANGUAGES[i].id) + { + // Try to find a language pack + _regex_namespace_::regex re(GlobalConstants::LANGUAGES[i].code + "\\d+langpack\\d+", _regex_namespace_::regex_constants::icase); // regex for language pack node names + std::vector langpacknames; + for (unsigned int j = 0; j < membernames.size(); ++j) + { + if (_regex_namespace_::regex_match(membernames[j], re)) + langpacknames.push_back(membernames[j]); + } + + if (!langpacknames.empty()) // found at least one language pack + { + for (unsigned int j = 0; j < langpacknames.size(); ++j) + { + Json::Value langpack = root["game"][langpacknames[j]]; + + gameFile gf; + gf.type = GFTYPE_LANGPACK; + gf.gamename = game.gamename; + gf.updated = false; // language packs don't have "updated" flag + gf.id = langpack["id"].isInt() ? std::to_string(langpack["id"].asInt()) : langpack["id"].asString(); + gf.name = langpack["name"].asString(); + gf.path = langpack["link"].asString(); + gf.path = (std::string)curl_easy_unescape(curlhandle, gf.path.c_str(), gf.path.size(), NULL); + gf.size = langpack["size"].asString(); + gf.language = GlobalConstants::LANGUAGES[i].id; + + game.languagepacks.push_back(gf); + } + } + } } return game; @@ -584,33 +568,31 @@ std::string API::getInstallerLink(const std::string& game_name, const std::strin url = this->config.get_installer_link + game_name + "/" + id + "/"; std::string json = this->getResponseOAuth(url); - if (!json.empty()) - { - Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << root << std::endl; - #endif - int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString()); - if (available) - link = root["file"]["link"].asString(); - } - else - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << json << std::endl; - #endif - this->setError(jsonparser->getFormattedErrorMessages()); - } - delete jsonparser; - } - else - { + if (json.empty()) { this->setError("Found nothing in " + url); + return link; } + Json::Value root; + std::istringstream json_stream(json); + + try { + json_stream >> root; + } catch (const Json::Exception& exc) { + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << json << std::endl; + #endif + this->setError(exc.what()); + return link; + } + + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getInstallerLink)" << std::endl << root << std::endl; + #endif + int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString()); + if (available) + link = root["file"]["link"].asString(); + return link; } @@ -620,33 +602,31 @@ std::string API::getExtraLink(const std::string& game_name, const std::string& i url = this->config.get_extra_link + game_name + "/" + id + "/"; std::string json = this->getResponseOAuth(url); - if (!json.empty()) - { - Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << root << std::endl; - #endif - int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString()); - if (available) - link = root["file"]["link"].asString(); - } - else - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << json << std::endl; - #endif - this->setError(jsonparser->getFormattedErrorMessages()); - } - delete jsonparser; - } - else - { + if (json.empty()) { this->setError("Found nothing in " + url); + return link; } + Json::Value root; + std::istringstream json_stream(json); + + try { + json_stream >> root; + } catch (const Json::Exception& exc) { + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << json << std::endl; + #endif + this->setError(exc.what()); + return link; + } + + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getExtraLink)" << std::endl << root << std::endl; + #endif + int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString()); + if (available) + link = root["file"]["link"].asString(); + return link; } @@ -666,34 +646,30 @@ std::string API::getXML(const std::string& game_name, const std::string& id) url = this->config.get_installer_link + game_name + "/" + id + "/crc/"; std::string json = this->getResponseOAuth(url); - if (!json.empty()) - { - Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getXML)" << std::endl << root << std::endl; - #endif - int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString()); - if (available) - { - url = root["file"]["link"].asString(); - XML = this->getResponse(url); - } - } - else - { - #ifdef DEBUG - std::cerr << "DEBUG INFO (API::getXML)" << std::endl << json << std::endl; - #endif - this->setError(jsonparser->getFormattedErrorMessages()); - } - delete jsonparser; - } - else - { + if (json.empty()) { this->setError("Found nothing in " + url); + return XML; + } + + try { + std::istringstream iss(json); + Json::Value root; + iss >> root; + + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getXML)" << std::endl << root << std::endl; + #endif + int available = root["file"]["available"].isInt() ? root["file"]["available"].asInt() : std::stoi(root["file"]["available"].asString()); + if (available) + { + url = root["file"]["link"].asString(); + XML = this->getResponse(url); + } + } catch (const Json::Exception& exc) { + #ifdef DEBUG + std::cerr << "DEBUG INFO (API::getXML)" << std::endl << json << std::endl; + #endif + this->setError(exc.what()); } return XML; diff --git a/src/downloader.cpp b/src/downloader.cpp index fb04402..c593a7c 100644 --- a/src/downloader.cpp +++ b/src/downloader.cpp @@ -121,9 +121,8 @@ Downloader::Downloader() { std::ifstream ifs(Globals::galaxyConf.getFilepath(), std::ifstream::binary); Json::Value json; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(ifs, json)) - { + try { + ifs >> json; if (!json.isMember("expires_at")) { std::time_t last_modified = boost::filesystem::last_write_time(Globals::galaxyConf.getFilepath()); @@ -132,13 +131,10 @@ Downloader::Downloader() } Globals::galaxyConf.setJSON(json); - } - else - { + } catch (const Json::Exception& exc) { std::cerr << "Failed to parse " << Globals::galaxyConf.getFilepath() << std::endl; - std::cerr << jsonparser->getFormattedErrorMessages() << std::endl; - } - delete jsonparser; + std::cerr << exc.what() << std::endl; + } if (ifs) ifs.close(); @@ -739,8 +735,6 @@ void Downloader::repair() if (this->games.empty()) this->getGameDetails(); - Json::Reader *jsonparser = new Json::Reader; - // Create a vector containing all game files std::vector vGameFiles; for (unsigned int i = 0; i < games.size(); ++i) @@ -793,8 +787,14 @@ void Downloader::repair() std::cerr << "Found nothing in " << vGameFiles[i].galaxy_downlink_json_url << ", skipping file" << std::endl; continue; } - jsonparser->parse(response, downlinkJson); - + try { + std::istringstream iss(response); + iss >> downlinkJson; + } catch (const Json::Exception& exc) { + std::cerr << "Could not parse JSON response, skipping file" << std::endl; + continue; + } + if (!downlinkJson.isMember("downlink")) { std::cerr << "Invalid JSON response, skipping file" << std::endl; @@ -827,8 +827,6 @@ void Downloader::repair() std::cout << std::endl; } } - - delete jsonparser; } void Downloader::download() @@ -2237,53 +2235,40 @@ int Downloader::loadGameDetailsCache() std::ifstream json(cachepath, std::ifstream::binary); Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) - { - if (root.isMember("date")) - { - cachedate = bptime::from_iso_string(root["date"].asString()); - if ((now - cachedate) > bptime::minutes(Globals::globalConfig.iCacheValid)) - { - // cache is too old - delete jsonparser; - json.close(); - return res = 3; - } - } - - int iCacheVersion = 0; - if (root.isMember("gamedetails-cache-version")) - iCacheVersion = root["gamedetails-cache-version"].asInt(); - - if (iCacheVersion != GlobalConstants::GAMEDETAILS_CACHE_VERSION) - { - res = 5; - } - else - { - if (root.isMember("games")) - { - this->games = getGameDetailsFromJsonNode(root["games"]); - res = 0; - } - else - { - res = 4; - } - } - } - else - { - res = 2; + try { + json >> root; + } catch (const Json::Exception& exc) { std::cout << "Failed to parse cache" << std::endl; - std::cout << jsonparser->getFormattedErrorMessages() << std::endl; + std::cout << exc.what() << std::endl; + return 2; } - delete jsonparser; - if (json) - json.close(); - return res; + if (root.isMember("date")) + { + cachedate = bptime::from_iso_string(root["date"].asString()); + if ((now - cachedate) > bptime::minutes(Globals::globalConfig.iCacheValid)) + { + // cache is too old + return 3; + } + } + + int iCacheVersion = 0; + if (root.isMember("gamedetails-cache-version")) + iCacheVersion = root["gamedetails-cache-version"].asInt(); + + if (iCacheVersion != GlobalConstants::GAMEDETAILS_CACHE_VERSION) + { + return 5; + } + + if (root.isMember("games")) + { + this->games = getGameDetailsFromJsonNode(root["games"]); + return 0; + } + + return 4; } /* Save game details to cache file returns 0 if successful @@ -2638,8 +2623,6 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid) } } - Json::Reader *jsonparser = new Json::Reader; - CURL* dlhandle = curl_easy_init(); curl_easy_setopt(dlhandle, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(dlhandle, CURLOPT_USERAGENT, conf.curlConf.sUserAgent.c_str()); @@ -2736,7 +2719,6 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid) { msgQueue.push(Message("Galaxy API failed to refresh login", MSGTYPE_ERROR, msg_prefix)); vDownloadInfo[tid].setStatus(DLSTATUS_FINISHED); - delete jsonparser; delete galaxy; return; } @@ -2751,7 +2733,14 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid) msgQueue.push(Message("Found nothing in " + gf.galaxy_downlink_json_url + ", skipping file", MSGTYPE_WARNING, msg_prefix)); continue; } - jsonparser->parse(response, downlinkJson); + + try { + std::istringstream iss(response); + iss >> downlinkJson; + } catch (const Json::Exception& exc) { + msgQueue.push(Message("Could not parse JSON response, skipping file", MSGTYPE_WARNING, msg_prefix)); + continue; + } if (!downlinkJson.isMember("downlink")) { @@ -2962,7 +2951,6 @@ void Downloader::processDownloadQueue(Config conf, const unsigned int& tid) } curl_easy_cleanup(dlhandle); - delete jsonparser; delete galaxy; vDownloadInfo[tid].setStatus(DLSTATUS_FINISHED); diff --git a/src/galaxyapi.cpp b/src/galaxyapi.cpp index 4462e73..261f1eb 100644 --- a/src/galaxyapi.cpp +++ b/src/galaxyapi.cpp @@ -10,6 +10,7 @@ #include #include #include +#include GalaxyConfig Globals::galaxyConf; @@ -78,19 +79,19 @@ bool galaxyAPI::refreshLogin() + "&refresh_token=" + Globals::galaxyConf.getRefreshToken(); std::string json = this->getResponse(refresh_url); - if (!json.empty()) - { - Json::Value token_json; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, token_json)) - { - Globals::galaxyConf.setJSON(token_json); - res = true; - } - delete jsonparser; + if (json.empty()) + return false; + + Json::Value token_json; + std::istringstream json_stream(json); + try { + json_stream >> token_json; + Globals::galaxyConf.setJSON(token_json); + } catch (const Json::Exception& exc) { + return false; } - return res; + return true; } bool galaxyAPI::isTokenExpired() @@ -145,59 +146,47 @@ std::string galaxyAPI::getResponse(const std::string& url, const bool& zlib_deco Json::Value galaxyAPI::getProductBuilds(const std::string& product_id, const std::string& platform, const std::string& generation) { + std::string url = "https://content-system.gog.com/products/" + product_id + "/os/" + platform + "/builds?generation=" + generation; + std::istringstream response(this->getResponse(url)); Json::Value json; - std::string url = "https://content-system.gog.com/products/" + product_id + "/os/" + platform + "/builds?generation=" + generation; - std::string response = this->getResponse(url); - - Json::Reader *jsonparser = new Json::Reader; - jsonparser->parse(response, json); - delete jsonparser; + response >> json; return json; } Json::Value galaxyAPI::getManifestV1(const std::string& product_id, const std::string& build_id, const std::string& manifest_id, const std::string& platform) { + std::string url = "https://cdn.gog.com/content-system/v1/manifests/" + product_id + "/" + platform + "/" + build_id + "/" + manifest_id + ".json"; + std::istringstream response(this->getResponse(url)); Json::Value json; - std::string url = "https://cdn.gog.com/content-system/v1/manifests/" + product_id + "/" + platform + "/" + build_id + "/" + manifest_id + ".json"; - std::string response = this->getResponse(url); - - Json::Reader *jsonparser = new Json::Reader; - jsonparser->parse(response, json); - delete jsonparser; + response >> json; return json; } Json::Value galaxyAPI::getManifestV2(std::string manifest_hash) { - Json::Value json; - if (!manifest_hash.empty() && manifest_hash.find("/") == std::string::npos) manifest_hash = this->hashToGalaxyPath(manifest_hash); std::string url = "https://cdn.gog.com/content-system/v2/meta/" + manifest_hash; - std::string response = this->getResponse(url, true); + std::istringstream response(this->getResponse(url, true)); + Json::Value json; - Json::Reader *jsonparser = new Json::Reader; - jsonparser->parse(response, json); - delete jsonparser; + response >> json; return json; } Json::Value galaxyAPI::getSecureLink(const std::string& product_id, const std::string& path) { + std::string url = "https://content-system.gog.com/products/" + product_id + "/secure_link?generation=2&path=" + path + "&_version=2"; + std::istringstream response(this->getResponse(url)); Json::Value json; - std::string url = "https://content-system.gog.com/products/" + product_id + "/secure_link?generation=2&path=" + path + "&_version=2"; - std::string response = this->getResponse(url); - - Json::Reader *jsonparser = new Json::Reader; - jsonparser->parse(response, json); - delete jsonparser; + response >>json; return json; } @@ -257,14 +246,11 @@ std::vector galaxyAPI::getDepotItemsVector(const std::string& h Json::Value galaxyAPI::getProductInfo(const std::string& product_id) { + std::string url = "https://api.gog.com/products/" + product_id + "?expand=downloads,expanded_dlcs,description,screenshots,videos,related_products,changelog&locale=en-US"; + std::istringstream response(this->getResponse(url)); Json::Value json; - std::string url = "https://api.gog.com/products/" + product_id + "?expand=downloads,expanded_dlcs,description,screenshots,videos,related_products,changelog&locale=en-US"; - std::string response = this->getResponse(url); - - Json::Reader *jsonparser = new Json::Reader; - jsonparser->parse(response, json); - delete jsonparser; + response >> json; return json; } @@ -384,9 +370,10 @@ std::vector galaxyAPI::fileJsonNodeToGameFileVector(const std::string& continue; Json::Value downlinkJson; - Json::Reader *jsonparser = new Json::Reader; - jsonparser->parse(downlinkResponse, downlinkJson); - delete jsonparser; + Json::CharReaderBuilder builder; + std::istringstream downlink_stream(downlinkResponse); + JSONCPP_STRING errs; + Json::parseFromStream(builder, downlink_stream, &downlinkJson, &errs); std::string downlink_url = downlinkJson["downlink"].asString(); std::string downlink_url_unescaped = (std::string)curl_easy_unescape(curlhandle, downlink_url.c_str(), downlink_url.size(), NULL); diff --git a/src/util.cpp b/src/util.cpp index f23a80c..ebf06f5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -235,89 +235,84 @@ int Util::getGameSpecificConfig(std::string gamename, gameSpecificConfig* conf, std::ifstream json(filepath, std::ifstream::binary); Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, root)) - { - if (root.isMember("language")) - { - if (root["language"].isInt()) - conf->dlConf.iInstallerLanguage = root["language"].asUInt(); - else - { - Util::parseOptionString(root["language"].asString(), conf->dlConf.vLanguagePriority, conf->dlConf.iInstallerLanguage, GlobalConstants::LANGUAGES); - } - res++; - } - if (root.isMember("platform")) - { - if (root["platform"].isInt()) - conf->dlConf.iInstallerPlatform = root["platform"].asUInt(); - else - { - Util::parseOptionString(root["platform"].asString(), conf->dlConf.vPlatformPriority, conf->dlConf.iInstallerPlatform, GlobalConstants::PLATFORMS); - } - res++; - } - if (root.isMember("dlc")) - { - conf->dlConf.bDLC = root["dlc"].asBool(); - res++; - } - if (root.isMember("ignore-dlc-count")) - { - conf->dlConf.bIgnoreDLCCount = root["ignore-dlc-count"].asBool(); - res++; - } - if (root.isMember("subdirectories")) - { - conf->dirConf.bSubDirectories = root["subdirectories"].asBool(); - res++; - } - if (root.isMember("directory")) - { - conf->dirConf.sDirectory = root["directory"].asString(); - res++; - } - if (root.isMember("subdir-game")) - { - conf->dirConf.sGameSubdir = root["subdir-game"].asString(); - res++; - } - if (root.isMember("subdir-installers")) - { - conf->dirConf.sInstallersSubdir = root["subdir-installers"].asString(); - res++; - } - if (root.isMember("subdir-extras")) - { - conf->dirConf.sExtrasSubdir = root["subdir-extras"].asString(); - res++; - } - if (root.isMember("subdir-patches")) - { - conf->dirConf.sPatchesSubdir = root["subdir-patches"].asString(); - res++; - } - if (root.isMember("subdir-language-packs")) - { - conf->dirConf.sLanguagePackSubdir = root["subdir-language-packs"].asString(); - res++; - } - if (root.isMember("subdir-dlc")) - { - conf->dirConf.sDLCSubdir = root["subdir-dlc"].asString(); - res++; - } - } - else - { + try { + json >> root; + } catch (const Json::Exception& exc) { std::cerr << "Failed to parse game specific config " << filepath << std::endl; - std::cerr << jsonparser->getFormattedErrorMessages() << std::endl; + std::cerr << exc.what() << std::endl; + return res; } - delete jsonparser; - if (json) - json.close(); + if (root.isMember("language")) + { + if (root["language"].isInt()) + conf->dlConf.iInstallerLanguage = root["language"].asUInt(); + else + { + Util::parseOptionString(root["language"].asString(), conf->dlConf.vLanguagePriority, conf->dlConf.iInstallerLanguage, GlobalConstants::LANGUAGES); + } + res++; + } + if (root.isMember("platform")) + { + if (root["platform"].isInt()) + conf->dlConf.iInstallerPlatform = root["platform"].asUInt(); + else + { + Util::parseOptionString(root["platform"].asString(), conf->dlConf.vPlatformPriority, conf->dlConf.iInstallerPlatform, GlobalConstants::PLATFORMS); + } + res++; + } + if (root.isMember("dlc")) + { + conf->dlConf.bDLC = root["dlc"].asBool(); + res++; + } + if (root.isMember("ignore-dlc-count")) + { + conf->dlConf.bIgnoreDLCCount = root["ignore-dlc-count"].asBool(); + res++; + } + if (root.isMember("subdirectories")) + { + conf->dirConf.bSubDirectories = root["subdirectories"].asBool(); + res++; + } + if (root.isMember("directory")) + { + conf->dirConf.sDirectory = root["directory"].asString(); + res++; + } + if (root.isMember("subdir-game")) + { + conf->dirConf.sGameSubdir = root["subdir-game"].asString(); + res++; + } + if (root.isMember("subdir-installers")) + { + conf->dirConf.sInstallersSubdir = root["subdir-installers"].asString(); + res++; + } + if (root.isMember("subdir-extras")) + { + conf->dirConf.sExtrasSubdir = root["subdir-extras"].asString(); + res++; + } + if (root.isMember("subdir-patches")) + { + conf->dirConf.sPatchesSubdir = root["subdir-patches"].asString(); + res++; + } + if (root.isMember("subdir-language-packs")) + { + conf->dirConf.sLanguagePackSubdir = root["subdir-language-packs"].asString(); + res++; + } + if (root.isMember("subdir-dlc")) + { + conf->dirConf.sDLCSubdir = root["subdir-dlc"].asString(); + res++; + } return res; } diff --git a/src/website.cpp b/src/website.cpp index 6fe6d5f..88c73e3 100644 --- a/src/website.cpp +++ b/src/website.cpp @@ -99,20 +99,20 @@ Json::Value Website::getGameDetailsJSON(const std::string& gameid) // Parse JSON Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - if (!jsonparser->parse(json, root)) - { + std::istringstream json_stream(json); + + try { + json_stream >> root; + } catch(const Json::Exception& exc) { #ifdef DEBUG std::cerr << "DEBUG INFO (Website::getGameDetailsJSON)" << std::endl << json << std::endl; #endif - std::cout << jsonparser->getFormattedErrorMessages(); - delete jsonparser; + std::cout << exc.what(); exit(1); } #ifdef DEBUG std::cerr << "DEBUG INFO (Website::getGameDetailsJSON)" << std::endl << root << std::endl; #endif - delete jsonparser; return root; } @@ -122,22 +122,22 @@ std::vector Website::getGames() { std::vector games; Json::Value root; - Json::Reader *jsonparser = new Json::Reader; int i = 1; bool bAllPagesParsed = false; do { std::string response = this->getResponse("https://www.gog.com/account/getFilteredProducts?hasHiddenProducts=false&hiddenFlag=0&isUpdated=0&mediaType=1&sortBy=title&system=&page=" + std::to_string(i)); + std::istringstream json_stream(response); - // Parse JSON - if (!jsonparser->parse(response, root)) - { + try { + // Parse JSON + json_stream >> root; + } catch (const Json::Exception& exc) { #ifdef DEBUG std::cerr << "DEBUG INFO (Website::getGames)" << std::endl << response << std::endl; #endif - std::cout << jsonparser->getFormattedErrorMessages(); - delete jsonparser; + std::cout << exc.what(); if (!response.empty()) { if(response[0] != '{') @@ -269,8 +269,6 @@ std::vector Website::getGames() } while (!bAllPagesParsed); std::cerr << std::endl; - delete jsonparser; - return games; } @@ -278,20 +276,21 @@ std::vector Website::getGames() std::vector Website::getFreeGames() { Json::Value root; - Json::Reader *jsonparser = new Json::Reader; std::vector games; std::string json = this->getResponse("https://www.gog.com/games/ajax/filtered?mediaType=game&page=1&price=free&sort=title"); + std::istringstream json_stream(json); - // Parse JSON - if (!jsonparser->parse(json, root)) - { + try { + // Parse JSON + json_stream >> root; + } catch (const Json::Exception& exc) { #ifdef DEBUG std::cerr << "DEBUG INFO (Website::getFreeGames)" << std::endl << json << std::endl; #endif - std::cout << jsonparser->getFormattedErrorMessages(); - delete jsonparser; + std::cout << exc.what(); exit(1); } + #ifdef DEBUG std::cerr << "DEBUG INFO (Website::getFreeGames)" << std::endl << root << std::endl; #endif @@ -304,7 +303,6 @@ std::vector Website::getFreeGames() game.id = products[i]["id"].isInt() ? std::to_string(products[i]["id"].asInt()) : products[i]["id"].asString(); games.push_back(game); } - delete jsonparser; return games; } @@ -506,18 +504,16 @@ int Website::Login(const std::string& email, const std::string& password) if (!json.empty()) { Json::Value token_json; - Json::Reader *jsonparser = new Json::Reader; - if (jsonparser->parse(json, token_json)) - { + std::istringstream json_stream(json); + try { + json_stream >> token_json; + Globals::galaxyConf.setJSON(token_json); res = 2; - } - else - { + } catch (const Json::Exception& exc) { std::cerr << "Failed to parse json" << std::endl << json << std::endl; - std::cerr << jsonparser->getFormattedErrorMessages() << std::endl; + std::cerr << exc.what() << std::endl; } - delete jsonparser; } } @@ -608,23 +604,24 @@ bool Website::IsloggedInSimple() std::vector Website::getWishlistItems() { Json::Value root; - Json::Reader *jsonparser = new Json::Reader; + Json::CharReaderBuilder builder; int i = 1; bool bAllPagesParsed = false; std::vector wishlistItems; do { - std::string response = this->getResponse("https://www.gog.com/account/wishlist/search?hasHiddenProducts=false&hiddenFlag=0&isUpdated=0&mediaType=0&sortBy=title&system=&page=" + std::to_string(i)); + std::string response(this->getResponse("https://www.gog.com/account/wishlist/search?hasHiddenProducts=false&hiddenFlag=0&isUpdated=0&mediaType=0&sortBy=title&system=&page=" + std::to_string(i))); + std::istringstream response_stream(response); - // Parse JSON - if (!jsonparser->parse(response, root)) - { + try { + // Parse JSON + response_stream >> root; + } catch(const Json::Exception exc) { #ifdef DEBUG std::cerr << "DEBUG INFO (Website::getWishlistItems)" << std::endl << response << std::endl; #endif - std::cout << jsonparser->getFormattedErrorMessages(); - delete jsonparser; + std::cout << exc.what(); exit(1); } #ifdef DEBUG @@ -712,7 +709,5 @@ std::vector Website::getWishlistItems() i++; } while (!bAllPagesParsed); - delete jsonparser; - return wishlistItems; }