mirror of
https://github.com/Sude-/lgogdownloader.git
synced 2024-11-20 11:49:17 +01:00
Remove old GOG downloader API
Removed all remaining code related to old API. Removed dead or commented out code that I noticed while checking the code for references to old API.
This commit is contained in:
parent
a884e8c0a3
commit
42c71884a2
@ -50,7 +50,6 @@ find_package(ZLIB REQUIRED)
|
||||
|
||||
file(GLOB SRC_FILES
|
||||
main.cpp
|
||||
src/api.cpp
|
||||
src/website.cpp
|
||||
src/downloader.cpp
|
||||
src/progressbar.cpp
|
||||
|
@ -1,95 +0,0 @@
|
||||
/* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://www.wtfpl.net/ for more details. */
|
||||
|
||||
#ifndef API_H
|
||||
#define API_H
|
||||
|
||||
#include "globalconstants.h"
|
||||
#include "gamedetails.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <curl/curl.h>
|
||||
extern "C" {
|
||||
#include <oauth.h>
|
||||
}
|
||||
#include <cstring>
|
||||
#include <sys/time.h>
|
||||
|
||||
class userDetails {
|
||||
public:
|
||||
std::string avatar_small;
|
||||
std::string avatar_big;
|
||||
std::string username;
|
||||
std::string email;
|
||||
unsigned long long id;
|
||||
int notifications_forum;
|
||||
int notifications_games;
|
||||
int notifications_messages;
|
||||
};
|
||||
|
||||
class apiConfig {
|
||||
public:
|
||||
std::string oauth_authorize_temp_token;
|
||||
std::string oauth_get_temp_token;
|
||||
std::string oauth_get_token;
|
||||
std::string get_user_games;
|
||||
std::string get_user_details;
|
||||
std::string get_installer_link;
|
||||
std::string get_game_details;
|
||||
std::string get_extra_link;
|
||||
std::string set_app_status;
|
||||
std::string oauth_token;
|
||||
std::string oauth_secret;
|
||||
};
|
||||
|
||||
size_t writeMemoryCallback(char *ptr, size_t size, size_t nmemb, void *userp);
|
||||
|
||||
class API
|
||||
{
|
||||
public:
|
||||
userDetails user;
|
||||
|
||||
API(const std::string& token,const std::string& secret);
|
||||
int init();
|
||||
bool isLoggedIn();
|
||||
int login(const std::string& email, const std::string& password);
|
||||
int getAPIConfig();
|
||||
std::string getResponse(const std::string& url);
|
||||
std::string getResponseOAuth(const std::string& url);
|
||||
int getUserDetails();
|
||||
int getGames();
|
||||
gameDetails getGameDetails(const std::string& game_name, const unsigned int& platform = (GlobalConstants::PLATFORM_WINDOWS | GlobalConstants::PLATFORM_LINUX), const unsigned int& lang = GlobalConstants::LANGUAGE_EN, const bool& useDuplicateHandler = false);
|
||||
std::string getInstallerLink(const std::string& game_name, const std::string& id);
|
||||
std::string getExtraLink(const std::string& game_name, const std::string& id);
|
||||
std::string getPatchLink(const std::string& game_name, const std::string& id);
|
||||
std::string getLanguagePackLink(const std::string& game_name, const std::string& id);
|
||||
std::string getXML(const std::string& game_name, const std::string& id);
|
||||
void clearError();
|
||||
bool getError() { return this->error; };
|
||||
std::string getErrorMessage() { return this->error_message; };
|
||||
std::string getToken() { return this->config.oauth_token; };
|
||||
std::string getSecret() { return this->config.oauth_secret; };
|
||||
template <typename T> CURLcode curlSetOpt(CURLoption option, T value) { return curl_easy_setopt(this->curlhandle, option, value); }
|
||||
virtual ~API();
|
||||
protected:
|
||||
private:
|
||||
apiConfig config;
|
||||
CURL* curlhandle;
|
||||
void setError(const std::string& err);
|
||||
bool error;
|
||||
std::string error_message;
|
||||
|
||||
// API constants
|
||||
const std::string CONSUMER_KEY = "1f444d14ea8ec776585524a33f6ecc1c413ed4a5";
|
||||
const std::string CONSUMER_SECRET = "20d175147f9db9a10fc0584aa128090217b9cf88";
|
||||
const int OAUTH_VERIFIER_LENGTH = 14;
|
||||
const int OAUTH_TOKEN_LENGTH = 11;
|
||||
const int OAUTH_SECRET_LENGTH = 18;
|
||||
};
|
||||
|
||||
#endif // API_H
|
@ -211,8 +211,7 @@ class Config
|
||||
virtual ~Config() {};
|
||||
|
||||
// Booleans
|
||||
bool bLoginHTTP;
|
||||
bool bLoginAPI;
|
||||
bool bLogin;
|
||||
bool bSaveConfig;
|
||||
bool bResetConfig;
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "api.h"
|
||||
#include "progressbar.h"
|
||||
#include "website.h"
|
||||
#include "threadsafequeue.h"
|
||||
@ -124,7 +123,6 @@ class Downloader
|
||||
int loadGameDetailsCache();
|
||||
int saveGameDetailsCache();
|
||||
std::vector<gameDetails> getGameDetailsFromJsonNode(Json::Value root, const int& recursion_level = 0);
|
||||
static std::vector<gameFile> getExtrasFromJSON(const Json::Value& json, const std::string& gamename, const Config& config);
|
||||
static std::string getSerialsFromJSON(const Json::Value& json);
|
||||
void saveSerials(const std::string& serials, const std::string& filepath);
|
||||
static std::string getChangelogFromJSON(const Json::Value& json);
|
||||
@ -149,7 +147,6 @@ class Downloader
|
||||
std::vector<galaxyDepotItem> galaxyGetDepotItemVectorFromJson(const Json::Value& json, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64);
|
||||
|
||||
Website *gogWebsite;
|
||||
API *gogAPI;
|
||||
galaxyAPI *gogGalaxy;
|
||||
std::vector<gameItem> gameItems;
|
||||
std::vector<gameDetails> games;
|
||||
|
28
main.cpp
28
main.cpp
@ -167,7 +167,6 @@ int main(int argc, char *argv[])
|
||||
bool bNoRemoteXML = false;
|
||||
bool bNoSubDirectories = false;
|
||||
bool bNoPlatformDetection = false;
|
||||
bool bLogin = false;
|
||||
bool bNoGalaxyDependencies = false;
|
||||
std::string sInstallerPlatform;
|
||||
std::string sInstallerLanguage;
|
||||
@ -182,7 +181,7 @@ int main(int argc, char *argv[])
|
||||
options_cli_no_cfg.add_options()
|
||||
("help,h", "Print help message")
|
||||
("version", "Print version information")
|
||||
("login", bpo::value<bool>(&bLogin)->zero_tokens()->default_value(false), "Login")
|
||||
("login", bpo::value<bool>(&Globals::globalConfig.bLogin)->zero_tokens()->default_value(false), "Login")
|
||||
("list", bpo::value<bool>(&Globals::globalConfig.bList)->zero_tokens()->default_value(false), "List games")
|
||||
("list-details", bpo::value<bool>(&Globals::globalConfig.bListDetails)->zero_tokens()->default_value(false), "List games with detailed info")
|
||||
("download", bpo::value<bool>(&Globals::globalConfig.bDownload)->zero_tokens()->default_value(false), "Download")
|
||||
@ -202,8 +201,6 @@ int main(int argc, char *argv[])
|
||||
("download-file", bpo::value<std::string>(&Globals::globalConfig.sFileIdString)->default_value(""), "Download files using fileid\n\nFormat:\n\"gamename/fileid\"\nor: \"gogdownloader://gamename/fileid\"\n\nMultiple files:\n\"gamename1/fileid1,gamename2/fileid2\"\nor: \"gogdownloader://gamename1/fileid1,gamename2/fileid2\"\n\nThis option ignores all subdir options. The files are downloaded to directory specified with --directory option.")
|
||||
("output-file,o", bpo::value<std::string>(&Globals::globalConfig.sOutputFilename)->default_value(""), "Set filename of file downloaded with --download-file.")
|
||||
("wishlist", bpo::value<bool>(&Globals::globalConfig.bShowWishlist)->zero_tokens()->default_value(false), "Show wishlist")
|
||||
("login-api", bpo::value<bool>(&Globals::globalConfig.bLoginAPI)->zero_tokens()->default_value(false), "Login (API only)")
|
||||
("login-website", bpo::value<bool>(&Globals::globalConfig.bLoginHTTP)->zero_tokens()->default_value(false), "Login (website only)")
|
||||
("cacert", bpo::value<std::string>(&Globals::globalConfig.curlConf.sCACertPath)->default_value(""), "Path to CA certificate bundle in PEM format")
|
||||
("respect-umask", bpo::value<bool>(&Globals::globalConfig.bRespectUmask)->zero_tokens()->default_value(false), "Do not adjust permissions of sensitive files")
|
||||
("user-agent", bpo::value<std::string>(&Globals::globalConfig.curlConf.sUserAgent)->default_value(DEFAULT_USER_AGENT), "Set user agent")
|
||||
@ -410,7 +407,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (bLogin || Globals::globalConfig.bLoginAPI || Globals::globalConfig.bLoginHTTP)
|
||||
if (Globals::globalConfig.bLogin)
|
||||
{
|
||||
std::string login_conf = Globals::globalConfig.sConfigDirectory + "/login.txt";
|
||||
if (boost::filesystem::exists(login_conf))
|
||||
@ -491,12 +488,6 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bLogin)
|
||||
{
|
||||
Globals::globalConfig.bLoginAPI = true;
|
||||
Globals::globalConfig.bLoginHTTP = true;
|
||||
}
|
||||
|
||||
if (Globals::globalConfig.sXMLFile == "automatic")
|
||||
Globals::globalConfig.dlConf.bAutomaticXMLCreation = true;
|
||||
|
||||
@ -605,19 +596,13 @@ int main(int argc, char *argv[])
|
||||
ssl_thread_setup();
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
if (Globals::globalConfig.bLoginAPI)
|
||||
{
|
||||
Globals::globalConfig.apiConf.sToken = "";
|
||||
Globals::globalConfig.apiConf.sSecret = "";
|
||||
}
|
||||
|
||||
Downloader downloader;
|
||||
|
||||
int iLoginTries = 0;
|
||||
bool bLoginOK = false;
|
||||
|
||||
// Login because --login, --login-api or --login-website was used
|
||||
if (Globals::globalConfig.bLoginAPI || Globals::globalConfig.bLoginHTTP)
|
||||
if (Globals::globalConfig.bLogin)
|
||||
bLoginOK = downloader.login();
|
||||
|
||||
bool bIsLoggedin = downloader.isLoggedIn();
|
||||
@ -650,11 +635,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (Globals::globalConfig.bSaveConfig || bLoginOK)
|
||||
{
|
||||
if (bLoginOK)
|
||||
{
|
||||
set_vm_value(vm, "token", Globals::globalConfig.apiConf.sToken);
|
||||
set_vm_value(vm, "secret", Globals::globalConfig.apiConf.sSecret);
|
||||
}
|
||||
std::ofstream ofs(Globals::globalConfig.sConfigFilePath.c_str());
|
||||
if (ofs)
|
||||
{
|
||||
@ -803,7 +783,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(Globals::globalConfig.bLoginAPI || Globals::globalConfig.bLoginHTTP))
|
||||
if (!Globals::globalConfig.bLogin)
|
||||
{
|
||||
// Show help message
|
||||
std::cerr << Globals::globalConfig.sVersionString << std::endl
|
||||
|
706
src/api.cpp
706
src/api.cpp
@ -1,706 +0,0 @@
|
||||
/* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://www.wtfpl.net/ for more details. */
|
||||
|
||||
#include "api.h"
|
||||
#include "gamefile.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <json/json.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40900
|
||||
# define _regex_namespace_ std
|
||||
# include <regex>
|
||||
#else
|
||||
# define _regex_namespace_ boost
|
||||
# include <boost/regex.hpp>
|
||||
#endif
|
||||
|
||||
size_t writeMemoryCallback(char *ptr, size_t size, size_t nmemb, void *userp) {
|
||||
std::ostringstream *stream = (std::ostringstream*)userp;
|
||||
std::streamsize count = (std::streamsize) size * nmemb;
|
||||
stream->write(ptr, count);
|
||||
return count;
|
||||
}
|
||||
|
||||
API::API(const std::string& token, const std::string& secret)
|
||||
{
|
||||
curlhandle = curl_easy_init();
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_PROGRESSDATA, this);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FAILONERROR, true);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
this->error = false;
|
||||
this->config.oauth_token = token;
|
||||
this->config.oauth_secret = secret;
|
||||
}
|
||||
|
||||
/* Initialize the API
|
||||
returns 0 if failed
|
||||
returns 1 if successful
|
||||
*/
|
||||
int API::init()
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
this->getAPIConfig();
|
||||
|
||||
if (!this->getError())
|
||||
res = 1;
|
||||
else
|
||||
this->clearError();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Login check
|
||||
returns false if not logged in
|
||||
returns true if logged in
|
||||
*/
|
||||
bool API::isLoggedIn()
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
// Check if we already have token and secret
|
||||
if (!this->config.oauth_token.empty() && !this->config.oauth_secret.empty())
|
||||
{
|
||||
// Test authorization by getting user details
|
||||
res = this->getUserDetails(); // res = 1 if successful
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
std::string json = this->getResponse(url);
|
||||
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int res = 0;
|
||||
std::string url;
|
||||
|
||||
std::string token, secret;
|
||||
|
||||
// Get temporary request token
|
||||
url = oauth_sign_url2(this->config.oauth_get_temp_token.c_str(), NULL, OA_HMAC, NULL, CONSUMER_KEY.c_str(), CONSUMER_SECRET.c_str(), NULL /* token */, NULL /* secret */);
|
||||
|
||||
std::string request_token_resp = this->getResponse(url);
|
||||
|
||||
char **rv = NULL;
|
||||
int rc = oauth_split_url_parameters(request_token_resp.c_str(), &rv);
|
||||
qsort(rv, rc, sizeof(char *), oauth_cmpstringp);
|
||||
if (rc == 3 && !strncmp(rv[1], "oauth_token=", OAUTH_TOKEN_LENGTH) && !strncmp(rv[2], "oauth_token_secret=", OAUTH_SECRET_LENGTH)) {
|
||||
token = rv[1]+OAUTH_TOKEN_LENGTH+1;
|
||||
secret = rv[2]+OAUTH_SECRET_LENGTH+1;
|
||||
rv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
usleep(500); // Wait to avoid "429 Too Many Requests"
|
||||
|
||||
// Authorize temporary token and get verifier
|
||||
url = this->config.oauth_authorize_temp_token + "?username=" + oauth_url_escape(email.c_str()) + "&password=" + oauth_url_escape(password.c_str());
|
||||
url = oauth_sign_url2(url.c_str(), NULL, OA_HMAC, NULL, CONSUMER_KEY.c_str(), CONSUMER_SECRET.c_str(), token.c_str(), secret.c_str());
|
||||
std::string authorize_resp = this->getResponse(url);
|
||||
|
||||
std::string verifier;
|
||||
rc = oauth_split_url_parameters(authorize_resp.c_str(), &rv);
|
||||
qsort(rv, rc, sizeof(char *), oauth_cmpstringp);
|
||||
if (rc == 2 && !strncmp(rv[1], "oauth_verifier=", OAUTH_VERIFIER_LENGTH)) {
|
||||
verifier = rv[1]+OAUTH_VERIFIER_LENGTH+1;
|
||||
rv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
usleep(500); // Wait to avoid "429 Too Many Requests"
|
||||
|
||||
// Get final token and secret
|
||||
url = this->config.oauth_get_token + "?oauth_verifier=" + verifier;
|
||||
url = oauth_sign_url2(url.c_str(), NULL, OA_HMAC, NULL, CONSUMER_KEY.c_str(), CONSUMER_SECRET.c_str(), token.c_str(), secret.c_str());
|
||||
std::string token_resp = this->getResponse(url);
|
||||
|
||||
rc = oauth_split_url_parameters(token_resp.c_str(), &rv);
|
||||
qsort(rv, rc, sizeof(char *), oauth_cmpstringp);
|
||||
if (rc == 2 && !strncmp(rv[0], "oauth_token=", OAUTH_TOKEN_LENGTH) && !strncmp(rv[1], "oauth_token_secret=", OAUTH_SECRET_LENGTH)) {
|
||||
this->config.oauth_token = rv[0]+OAUTH_TOKEN_LENGTH+1;
|
||||
this->config.oauth_secret = rv[1]+OAUTH_SECRET_LENGTH+1;
|
||||
free(rv);
|
||||
res = 1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int API::getUserDetails()
|
||||
{
|
||||
std::string url;
|
||||
|
||||
url = this->config.get_user_details;
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
if (json.empty()) {
|
||||
this->setError("Found nothing in " + url);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int API::getGames()
|
||||
{
|
||||
// Not implemented on the server side currently
|
||||
|
||||
//std::string json = this->getResponseOAuth(this->config.get_user_games);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string API::getResponse(const std::string& url)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getResponse)" << std::endl << "URL: " << url << std::endl;
|
||||
#endif
|
||||
std::ostringstream memory;
|
||||
|
||||
curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, writeMemoryCallback);
|
||||
curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, &memory);
|
||||
|
||||
int retries = 0;
|
||||
CURLcode result;
|
||||
std::string response;
|
||||
do
|
||||
{
|
||||
if (Globals::globalConfig.iWait > 0)
|
||||
usleep(Globals::globalConfig.iWait); // Delay the request by specified time
|
||||
result = curl_easy_perform(curlhandle);
|
||||
response = memory.str();
|
||||
memory.str(std::string());
|
||||
}
|
||||
while ((result != CURLE_OK) && response.empty() && (retries++ < Globals::globalConfig.iRetries));
|
||||
|
||||
if (result == CURLE_HTTP_RETURNED_ERROR)
|
||||
{
|
||||
long int response_code = 0;
|
||||
result = curl_easy_getinfo(curlhandle, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
if (result == CURLE_OK)
|
||||
this->setError("HTTP ERROR: " + std::to_string(response_code) + " (" + url + ")");
|
||||
else
|
||||
this->setError("HTTP ERROR: failed to get error code: " + static_cast<std::string>(curl_easy_strerror(result)) + " (" + url + ")");
|
||||
|
||||
#ifdef DEBUG
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FAILONERROR, false);
|
||||
result = curl_easy_perform(curlhandle);
|
||||
std::string debug_response = memory.str();
|
||||
memory.str(std::string());
|
||||
std::cerr << "Response (CURLE_HTTP_RETURNED_ERROR):";
|
||||
if (debug_response.empty())
|
||||
std::cerr << " Response was empty" << std::endl;
|
||||
else
|
||||
std::cerr << std::endl << debug_response << std::endl;
|
||||
curl_easy_setopt(curlhandle, CURLOPT_FAILONERROR, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
std::string API::getResponseOAuth(const std::string& url)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (API::getResponseOAuth)" << std::endl << "URL: " << url << std::endl;
|
||||
#endif
|
||||
std::string url_oauth = oauth_sign_url2(url.c_str(), NULL, OA_HMAC, NULL, CONSUMER_KEY.c_str(), CONSUMER_SECRET.c_str(), this->config.oauth_token.c_str(), this->config.oauth_secret.c_str());
|
||||
std::string response = this->getResponse(url_oauth);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
gameDetails API::getGameDetails(const std::string& game_name, const unsigned int& platform, const unsigned int& lang, const bool& useDuplicateHandler)
|
||||
{
|
||||
std::string url;
|
||||
gameDetails game;
|
||||
struct gameFileInfo
|
||||
{
|
||||
Json::Value jsonNode;
|
||||
unsigned int platform;
|
||||
unsigned int language;
|
||||
};
|
||||
|
||||
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()) {
|
||||
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<std::string> membernames = root["game"].getMemberNames();
|
||||
|
||||
// Installer details
|
||||
// Create a list of installers from JSON
|
||||
std::vector<gameFileInfo> 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)
|
||||
{ // 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<gameFileInfo> 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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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<std::string> 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;
|
||||
}
|
||||
|
||||
|
||||
std::string API::getInstallerLink(const std::string& game_name, const std::string& id)
|
||||
{
|
||||
std::string url, link;
|
||||
url = this->config.get_installer_link + game_name + "/" + id + "/";
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::string API::getExtraLink(const std::string& game_name, const std::string& id)
|
||||
{
|
||||
std::string url, link;
|
||||
url = this->config.get_extra_link + game_name + "/" + id + "/";
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::string API::getPatchLink(const std::string& game_name, const std::string& id)
|
||||
{
|
||||
return this->getInstallerLink(game_name, id);
|
||||
}
|
||||
|
||||
std::string API::getLanguagePackLink(const std::string& game_name, const std::string& id)
|
||||
{
|
||||
return this->getInstallerLink(game_name, id);
|
||||
}
|
||||
|
||||
std::string API::getXML(const std::string& game_name, const std::string& id)
|
||||
{
|
||||
std::string url, XML;
|
||||
url = this->config.get_installer_link + game_name + "/" + id + "/crc/";
|
||||
std::string json = this->getResponseOAuth(url);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void API::clearError()
|
||||
{
|
||||
this->error = false;
|
||||
this->error_message = "";
|
||||
}
|
||||
|
||||
void API::setError(const std::string& err)
|
||||
{
|
||||
this->error = true;
|
||||
if (this->error_message.empty())
|
||||
this->error_message = err;
|
||||
else
|
||||
this->error_message += "\n" + err;
|
||||
}
|
||||
|
||||
API::~API()
|
||||
{
|
||||
curl_easy_cleanup(curlhandle);
|
||||
}
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "blacklist.h"
|
||||
#include "config.h"
|
||||
#include "api.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <iostream>
|
||||
|
@ -71,7 +71,7 @@ static curl_off_t WriteChunkMemoryCallback(void *contents, curl_off_t size, curl
|
||||
|
||||
Downloader::Downloader()
|
||||
{
|
||||
if (Globals::globalConfig.bLoginHTTP)
|
||||
if (Globals::globalConfig.bLogin)
|
||||
{
|
||||
if (boost::filesystem::exists(Globals::globalConfig.curlConf.sCookiePath))
|
||||
if (!boost::filesystem::remove(Globals::globalConfig.curlConf.sCookiePath))
|
||||
@ -110,16 +110,6 @@ Downloader::Downloader()
|
||||
// Create new GOG website handle
|
||||
gogWebsite = new Website();
|
||||
|
||||
// Create new API handle and set curl options for the API
|
||||
gogAPI = new API(Globals::globalConfig.apiConf.sToken, Globals::globalConfig.apiConf.sSecret);
|
||||
gogAPI->curlSetOpt(CURLOPT_VERBOSE, Globals::globalConfig.curlConf.bVerbose);
|
||||
gogAPI->curlSetOpt(CURLOPT_SSL_VERIFYPEER, Globals::globalConfig.curlConf.bVerifyPeer);
|
||||
gogAPI->curlSetOpt(CURLOPT_CONNECTTIMEOUT, Globals::globalConfig.curlConf.iTimeout);
|
||||
if (!Globals::globalConfig.curlConf.sCACertPath.empty())
|
||||
gogAPI->curlSetOpt(CURLOPT_CAINFO, Globals::globalConfig.curlConf.sCACertPath.c_str());
|
||||
|
||||
gogAPI->init();
|
||||
|
||||
progressbar = new ProgressBar(Globals::globalConfig.bUnicode, Globals::globalConfig.bColor);
|
||||
|
||||
if (boost::filesystem::exists(Globals::galaxyConf.getFilepath()))
|
||||
@ -159,7 +149,6 @@ Downloader::~Downloader()
|
||||
|
||||
delete progressbar;
|
||||
delete gogGalaxy;
|
||||
delete gogAPI;
|
||||
delete gogWebsite;
|
||||
curl_easy_cleanup(curlhandle);
|
||||
// Make sure that cookie file is only readable/writable by owner
|
||||
@ -176,12 +165,11 @@ Downloader::~Downloader()
|
||||
bool Downloader::isLoggedIn()
|
||||
{
|
||||
bool bIsLoggedIn = false;
|
||||
Globals::globalConfig.bLoginAPI = false;
|
||||
Globals::globalConfig.bLoginHTTP = false;
|
||||
Globals::globalConfig.bLogin= false;
|
||||
|
||||
bool bWebsiteIsLoggedIn = gogWebsite->IsLoggedIn();
|
||||
if (!bWebsiteIsLoggedIn)
|
||||
Globals::globalConfig.bLoginHTTP = true;
|
||||
Globals::globalConfig.bLogin = true;
|
||||
|
||||
bool bGalaxyIsLoggedIn = !gogGalaxy->isTokenExpired();
|
||||
if (!bGalaxyIsLoggedIn)
|
||||
@ -189,17 +177,9 @@ bool Downloader::isLoggedIn()
|
||||
if (gogGalaxy->refreshLogin())
|
||||
bGalaxyIsLoggedIn = true;
|
||||
else
|
||||
Globals::globalConfig.bLoginHTTP = true;
|
||||
Globals::globalConfig.bLogin = true;
|
||||
}
|
||||
|
||||
bool bIsLoggedInAPI = gogAPI->isLoggedIn();
|
||||
if (!bIsLoggedInAPI)
|
||||
Globals::globalConfig.bLoginAPI = true;
|
||||
|
||||
/* Check that website and Galaxy API are logged in.
|
||||
Allows users to use most of the functionality without having valid API login credentials.
|
||||
Globals::globalConfig.bLoginAPI can still be set to true at this point which means that if website is not logged in we still try to login to API.
|
||||
*/
|
||||
if (bWebsiteIsLoggedIn && bGalaxyIsLoggedIn)
|
||||
bIsLoggedIn = true;
|
||||
|
||||
@ -299,8 +279,8 @@ int Downloader::login()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Login to website
|
||||
if (Globals::globalConfig.bLoginHTTP)
|
||||
// Login to website and Galaxy API
|
||||
if (Globals::globalConfig.bLogin)
|
||||
{
|
||||
// Delete old cookies
|
||||
if (boost::filesystem::exists(Globals::globalConfig.curlConf.sCookiePath))
|
||||
@ -331,25 +311,6 @@ int Downloader::login()
|
||||
{
|
||||
this->saveGalaxyJSON();
|
||||
}
|
||||
|
||||
if (!Globals::globalConfig.bLoginAPI)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// Login to API
|
||||
if (Globals::globalConfig.bLoginAPI)
|
||||
{
|
||||
if (!gogAPI->login(email, password))
|
||||
{
|
||||
std::cerr << "API: Login failed (--download-file option will not work)" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "API: Login successful" << std::endl;
|
||||
Globals::globalConfig.apiConf.sToken = gogAPI->getToken();
|
||||
Globals::globalConfig.apiConf.sSecret = gogAPI->getSecret();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1690,91 +1651,6 @@ uintmax_t Downloader::getResumePosition()
|
||||
return this->resume_position;
|
||||
}
|
||||
|
||||
std::vector<gameFile> Downloader::getExtrasFromJSON(const Json::Value& json, const std::string& gamename, const Config& config)
|
||||
{
|
||||
std::vector<gameFile> extras;
|
||||
|
||||
// Create new API handle and set curl options for the API
|
||||
API* api = new API(config.apiConf.sToken, config.apiConf.sSecret);
|
||||
api->curlSetOpt(CURLOPT_VERBOSE, config.curlConf.bVerbose);
|
||||
api->curlSetOpt(CURLOPT_SSL_VERIFYPEER, config.curlConf.bVerifyPeer);
|
||||
api->curlSetOpt(CURLOPT_CONNECTTIMEOUT, config.curlConf.iTimeout);
|
||||
if (!config.curlConf.sCACertPath.empty())
|
||||
api->curlSetOpt(CURLOPT_CAINFO, config.curlConf.sCACertPath.c_str());
|
||||
|
||||
if (!api->init())
|
||||
{
|
||||
delete api;
|
||||
return extras;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < json["extras"].size(); ++i)
|
||||
{
|
||||
std::string id, name, path, downloaderUrl;
|
||||
name = json["extras"][i]["name"].asString();
|
||||
downloaderUrl = json["extras"][i]["downloaderUrl"].asString();
|
||||
id.assign(downloaderUrl.begin()+downloaderUrl.find_last_of("/")+1, downloaderUrl.end());
|
||||
|
||||
// Get path from download link
|
||||
std::string url = api->getExtraLink(gamename, id);
|
||||
if (api->getError())
|
||||
{
|
||||
api->clearError();
|
||||
continue;
|
||||
}
|
||||
url = htmlcxx::Uri::decode(url);
|
||||
if (url.find("/extras/") != std::string::npos)
|
||||
{
|
||||
path.assign(url.begin()+url.find("/extras/"), url.begin()+url.find_first_of("?"));
|
||||
path = "/" + gamename + path;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.assign(url.begin()+url.find_last_of("/")+1, url.begin()+url.find_first_of("?"));
|
||||
path = "/" + gamename + "/extras/" + path;
|
||||
}
|
||||
|
||||
// Get filename
|
||||
std::string filename;
|
||||
filename.assign(path.begin()+path.find_last_of("/")+1,path.end());
|
||||
|
||||
// Use filename if name was not specified
|
||||
if (name.empty())
|
||||
name = filename;
|
||||
|
||||
if (name.empty())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (getExtrasFromJSON)" << std::endl;
|
||||
std::cerr << "Skipped file without a name (game: " << gamename << ", fileid: " << id << ")" << std::endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filename.empty())
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DEBUG INFO (getExtrasFromJSON)" << std::endl;
|
||||
std::cerr << "Skipped file without a filename (game: " << gamename << ", fileid: " << id << ", name: " << name << ")" << std::endl;
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
gameFile gf;
|
||||
gf.type = GFTYPE_EXTRA;
|
||||
gf.gamename = gamename;
|
||||
gf.updated = false;
|
||||
gf.id = id;
|
||||
gf.name = name;
|
||||
gf.path = path;
|
||||
|
||||
extras.push_back(gf);
|
||||
}
|
||||
delete api;
|
||||
|
||||
return extras;
|
||||
}
|
||||
|
||||
std::string Downloader::getSerialsFromJSON(const Json::Value& json)
|
||||
{
|
||||
std::ostringstream serials;
|
||||
|
@ -578,7 +578,6 @@ int ZipUtil::extractStream(std::istream* input_stream, std::ostream* output_stre
|
||||
if (cd.compression_method == boost::iostreams::zlib::deflated)
|
||||
in.push(boost::iostreams::zlib_decompressor(p));
|
||||
|
||||
//in.push(compressed);
|
||||
in.push(*input_stream);
|
||||
try
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user