[lgogdownloader] 01/03: Imported Upstream version 2.21

Stephen Kitt skitt at moszumanska.debian.org
Fri Apr 10 21:30:10 UTC 2015


This is an automated email from the git hooks/post-receive script.

skitt pushed a commit to branch master
in repository lgogdownloader.

commit 82e26d762cf6818e771e19700518a36f120977e6
Author: Stephen Kitt <steve at sk2.org>
Date:   Fri Apr 10 21:20:21 2015 +0200

    Imported Upstream version 2.21
---
 Makefile              |   2 +-
 include/config.h      |   2 +
 include/downloader.h  |   7 +-
 include/gamedetails.h |   7 +-
 include/gamefile.h    |   2 +-
 main.cpp              |   7 +-
 src/api.cpp           |  20 ++++-
 src/downloader.cpp    | 239 +++++++++++++++++++++++++++++++++++++++++++++-----
 src/gamedetails.cpp   |   9 ++
 src/util.cpp          |   2 +-
 10 files changed, 262 insertions(+), 35 deletions(-)

diff --git a/Makefile b/Makefile
index 18c7845..ded437f 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ AR = ar
 LD = g++
 WINDRES = windres
 
-INC =  -Iinclude -I/usr/include/rhash
+INC =  -Iinclude -I/usr/include/rhash -I/usr/include/jsoncpp
 CFLAGS =  -std=c++11 -Wall -fexceptions -D_FILE_OFFSET_BITS=64
 RESINC = 
 LIBDIR = 
diff --git a/include/config.h b/include/config.h
index 01d2939..09a4e1e 100644
--- a/include/config.h
+++ b/include/config.h
@@ -42,6 +42,8 @@ class Config
         bool bSubDirectories;
         bool bUseCache;
         bool bUpdateCache;
+        bool bSaveSerials;
+        bool bPlatformDetection;
         std::string sGameRegex;
         std::string sDirectory;
         std::string sCacheDirectory;
diff --git a/include/downloader.h b/include/downloader.h
index 8154ce5..49cab87 100644
--- a/include/downloader.h
+++ b/include/downloader.h
@@ -25,7 +25,7 @@
 #include "api.h"
 #include "progressbar.h"
 #include <curl/curl.h>
-#include <jsoncpp/json/json.h>
+#include <json/json.h>
 #include <ctime>
 #include <fstream>
 
@@ -89,7 +89,10 @@ class Downloader
         int HTTP_Login(const std::string& email, const std::string& password);
         std::vector<gameItem> getGames();
         std::vector<gameItem> getFreeGames();
-        std::vector<gameFile> getExtras(const std::string& gamename, const std::string& gameid);
+        std::vector<gameFile> getExtrasFromHTML(const std::string& html, const std::string& gamename, const std::string& gameid);
+        std::string getGameDetailsHTML(const std::string& gamename, const std::string& gameid);
+        std::string getSerialsFromHTML(const std::string& html);
+        void saveSerials(const std::string& serials, const std::string& filepath);
 
         static int progressCallback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
         static size_t writeMemoryCallback(char *ptr, size_t size, size_t nmemb, void *userp);
diff --git a/include/gamedetails.h b/include/gamedetails.h
index 5e86cb9..4ef052a 100644
--- a/include/gamedetails.h
+++ b/include/gamedetails.h
@@ -7,7 +7,7 @@
 
 #include <iostream>
 #include <vector>
-#include <jsoncpp/json/json.h>
+#include <json/json.h>
 
 class gameDetails
 {
@@ -20,14 +20,17 @@ class gameDetails
         std::vector<gameDetails> dlcs;
         std::string gamename;
         std::string title;
-        std::string icon;;
+        std::string icon;
+        std::string serials;
         void filterWithPriorities(const Config& config);
         void makeFilepaths(const Config& config);
+        std::string getSerialsFilepath();
         Json::Value getDetailsAsJson();
         virtual ~gameDetails();
     protected:
         void filterListWithPriorities(std::vector<gameFile>& list, const Config& config);
     private:
+        std::string serialsFilepath;
 };
 
 #endif // GAMEDETAILS_H
diff --git a/include/gamefile.h b/include/gamefile.h
index f7d5c76..2c32100 100644
--- a/include/gamefile.h
+++ b/include/gamefile.h
@@ -5,7 +5,7 @@
 
 #include <iostream>
 #include <vector>
-#include <jsoncpp/json/json.h>
+#include <json/json.h>
 
 class gameFile
 {
diff --git a/main.cpp b/main.cpp
index bdaf253..ba908de 100644
--- a/main.cpp
+++ b/main.cpp
@@ -13,7 +13,7 @@
 #include <boost/filesystem.hpp>
 #include <boost/program_options.hpp>
 
-#define VERSION_NUMBER "2.20"
+#define VERSION_NUMBER "2.21"
 
 #ifndef VERSION_STRING
 #   define VERSION_STRING "LGOGDownloader " VERSION_NUMBER
@@ -128,6 +128,7 @@ int main(int argc, char *argv[])
         bool bNoDeb = false;
         bool bNoTarGz = false;
         bool bNoCover = false;
+        bool bNoPlatformDetection = false;
         config.bReport = false;
         // Commandline options (no config file)
         options_cli_no_cfg.add_options()
@@ -148,6 +149,7 @@ int main(int argc, char *argv[])
             ("report", bpo::value<std::string>(&config.sReportFilePath)->implicit_value("lgogdownloader-report.log"), "Save report of downloaded/repaired files to specified file\nDefault filename: lgogdownloader-report.log")
             ("no-cover", bpo::value<bool>(&bNoCover)->zero_tokens()->default_value(false), "Don't download cover images. Overrides --cover option.\nUseful for making exceptions when \"cover\" is set to true in config file.")
             ("update-cache", bpo::value<bool>(&config.bUpdateCache)->zero_tokens()->default_value(false), "Update game details cache")
+            ("no-platform-detection", bpo::value<bool>(&bNoPlatformDetection)->zero_tokens()->default_value(false), "Don't try to detect supported platforms from game shelf.\nSkips the initial fast platform detection and detects the supported platforms from game details which is slower but more accurate.\nUseful in case platform identifier is missing for some games in the game shelf.\nUsing --platform with --list doesn't work with this option.")
         ;
         // Commandline options (config file)
         options_cli_cfg.add_options()
@@ -186,7 +188,7 @@ int main(int argc, char *argv[])
             ("cache-valid", bpo::value<int>(&config.iCacheValid)->default_value(2880), ("Set how long cached game details are valid (in minutes)\nDefault: 2880 minutes (48 hours)"))
             ("language-priority", bpo::value<std::string>(&config.sLanguagePriority)->default_value(""), ("Set priority of systems" + priority_help_text + ", like \"4,1\" for French first, then English if no French version").c_str())
             ("platform-priority", bpo::value<std::string>(&config.sPlatformPriority)->default_value(""), ("Set priority of platforms" + priority_help_text + ", like \"4,1\" for Linux first, then Windows if no Linux version").c_str())
-
+            ("save-serials", bpo::value<bool>(&config.bSaveSerials)->zero_tokens()->default_value(false), "Save serial numbers when downloading")
         ;
         // Options read from config file
         options_cfg_only.add_options()
@@ -335,6 +337,7 @@ int main(int argc, char *argv[])
         config.bDLC = !bNoDLC;
         config.bRemoteXML = !bNoRemoteXML;
         config.bSubDirectories = !bNoSubDirectories;
+        config.bPlatformDetection = !bNoPlatformDetection;
 
         // Override cover option
         if (bNoCover)
diff --git a/src/api.cpp b/src/api.cpp
index 737d55b..d8b6eb8 100644
--- a/src/api.cpp
+++ b/src/api.cpp
@@ -10,7 +10,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <sstream>
-#include <jsoncpp/json/json.h>
+#include <json/json.h>
 
 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40900
 #   define _regex_namespace_ std
@@ -233,14 +233,28 @@ std::string API::getResponse(const std::string& url)
     CURLcode result = curl_easy_perform(curlhandle);
     std::string response = memory.str();
     memory.str(std::string());
+
     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));
+            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)));
+            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;
diff --git a/src/downloader.cpp b/src/downloader.cpp
index 5775d30..14d6c57 100644
--- a/src/downloader.cpp
+++ b/src/downloader.cpp
@@ -20,7 +20,7 @@
 #include <boost/regex.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <tinyxml.h>
-#include <jsoncpp/json/json.h>
+#include <json/json.h>
 #include <htmlcxx/html/ParserDom.h>
 #include <htmlcxx/html/Uri.h>
 #include <boost/algorithm/string/case_conv.hpp>
@@ -261,21 +261,37 @@ int Downloader::getGameDetails()
         if (!gogAPI->getError())
         {
             game.filterWithPriorities(config);
+            std::string gameDetailsHTML;
 
             if (game.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras
             {
-                game.extras = this->getExtras(gameItems[i].name, gameItems[i].id);
+                gameDetailsHTML = this->getGameDetailsHTML(gameItems[i].name, gameItems[i].id);
+                game.extras = this->getExtrasFromHTML(gameDetailsHTML, gameItems[i].name, gameItems[i].id);
+            }
+            if (config.bSaveSerials)
+            {
+                if (gameDetailsHTML.empty())
+                    gameDetailsHTML = this->getGameDetailsHTML(gameItems[i].name, gameItems[i].id);
+                game.serials = this->getSerialsFromHTML(gameDetailsHTML);
             }
             if (game.dlcs.empty() && bHasDLC && conf.bDLC)
             {
                 for (unsigned int j = 0; j < gameItems[i].dlcnames.size(); ++j)
                 {
                     gameDetails dlc;
+                    std::string gameDetailsHTML_dlc;
                     dlc = gogAPI->getGameDetails(gameItems[i].dlcnames[j], conf.iInstallerType, conf.iInstallerLanguage, config.bDuplicateHandler);
                     dlc.filterWithPriorities(config);
                     if (dlc.extras.empty() && config.bExtras) // Try to get extras from account page if API didn't return any extras
                     {
-                        dlc.extras = this->getExtras(gameItems[i].dlcnames[j], gameItems[i].id);
+                        gameDetailsHTML_dlc = this->getGameDetailsHTML(gameItems[i].dlcnames[j], gameItems[i].id);
+                        dlc.extras = this->getExtrasFromHTML(gameDetailsHTML_dlc, gameItems[i].dlcnames[j], gameItems[i].id);
+                    }
+                    if (config.bSaveSerials)
+                    {
+                        if (gameDetailsHTML_dlc.empty())
+                            gameDetailsHTML_dlc = this->getGameDetailsHTML(gameItems[i].dlcnames[j], gameItems[i].id);
+                        dlc.serials = this->getSerialsFromHTML(gameDetailsHTML_dlc);
                     }
                     game.dlcs.push_back(dlc);
                 }
@@ -326,6 +342,9 @@ void Downloader::listGames()
             std::cout   << "gamename: " << games[i].gamename << std::endl
                         << "title: " << games[i].title << std::endl
                         << "icon: " << "http://static.gog.com" << games[i].icon << std::endl;
+            if (!games[i].serials.empty())
+                std::cout << "serials:" << std::endl << games[i].serials << std::endl;
+
             // List installers
             if (config.bInstallers)
             {
@@ -436,6 +455,12 @@ void Downloader::listGames()
                 std::cout << "DLCs: " << std::endl;
                 for (unsigned int j = 0; j < games[i].dlcs.size(); ++j)
                 {
+                    if (!games[i].dlcs[j].serials.empty())
+                    {
+                        std::cout   << "\tDLC gamename: " << games[i].dlcs[j].gamename << std::endl
+                                    << "\tserials:" << games[i].dlcs[j].serials << std::endl;
+                    }
+
                     for (unsigned int k = 0; k < games[i].dlcs[j].installers.size(); ++k)
                     {
                         std::string filepath = games[i].dlcs[j].installers[k].getFilepath();
@@ -758,6 +783,12 @@ void Downloader::download()
 
     for (unsigned int i = 0; i < games.size(); ++i)
     {
+        if (config.bSaveSerials && !games[i].serials.empty())
+        {
+            std::string filepath = games[i].getSerialsFilepath();
+            this->saveSerials(games[i].serials, filepath);
+        }
+
         // Download covers
         if (config.bCover && !config.bUpdateCheck)
         {
@@ -806,7 +837,14 @@ void Downloader::download()
                 {
                     std::string XML;
                     if (config.bRemoteXML)
+                    {
                         XML = gogAPI->getXML(games[i].gamename, games[i].installers[j].id);
+                        if (gogAPI->getError())
+                        {
+                            std::cout << gogAPI->getErrorMessage() << std::endl;
+                            gogAPI->clearError();
+                        }
+                    }
                     if (!games[i].installers[j].name.empty())
                         std::cout << "Downloading: " << games[i].installers[j].name << std::endl;
                     std::cout << filepath << std::endl;
@@ -886,7 +924,14 @@ void Downloader::download()
                 {
                     std::string XML;
                     if (config.bRemoteXML)
+                    {
                         XML = gogAPI->getXML(games[i].gamename, games[i].patches[j].id);
+                        if (gogAPI->getError())
+                        {
+                            std::cout << gogAPI->getErrorMessage() << std::endl;
+                            gogAPI->clearError();
+                        }
+                    }
                     if (!games[i].patches[j].name.empty())
                         std::cout << "Downloading: " << games[i].patches[j].name << std::endl;
                     std::cout << filepath << std::endl;
@@ -922,7 +967,14 @@ void Downloader::download()
                 {
                     std::string XML;
                     if (config.bRemoteXML)
+                    {
                         XML = gogAPI->getXML(games[i].gamename, games[i].languagepacks[j].id);
+                        if (gogAPI->getError())
+                        {
+                            std::cout << gogAPI->getErrorMessage() << std::endl;
+                            gogAPI->clearError();
+                        }
+                    }
                     if (!games[i].languagepacks[j].name.empty())
                         std::cout << "Downloading: " << games[i].gamename << " " << games[i].languagepacks[j].name << std::endl;
                     std::cout << filepath << std::endl;
@@ -935,6 +987,12 @@ void Downloader::download()
         {
             for (unsigned int j = 0; j < games[i].dlcs.size(); ++j)
             {
+                if (config.bSaveSerials && !games[i].dlcs[j].serials.empty())
+                {
+                    std::string filepath = games[i].dlcs[j].getSerialsFilepath();
+                    this->saveSerials(games[i].dlcs[j].serials, filepath);
+                }
+
                 if (config.bInstallers)
                 {
                     for (unsigned int k = 0; k < games[i].dlcs[j].installers.size(); ++k)
@@ -961,7 +1019,14 @@ void Downloader::download()
                         {
                             std::string XML;
                             if (config.bRemoteXML)
+                            {
                                 XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id);
+                                if (gogAPI->getError())
+                                {
+                                    std::cout << gogAPI->getErrorMessage() << std::endl;
+                                    gogAPI->clearError();
+                                }
+                            }
                             if (!games[i].dlcs[j].installers[k].name.empty())
                                 std::cout << "Downloading: " << games[i].dlcs[j].installers[k].name << std::endl;
                             std::cout << filepath << std::endl;
@@ -996,7 +1061,14 @@ void Downloader::download()
                         {
                             std::string XML;
                             if (config.bRemoteXML)
+                            {
                                 XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id);
+                                if (gogAPI->getError())
+                                {
+                                    std::cout << gogAPI->getErrorMessage() << std::endl;
+                                    gogAPI->clearError();
+                                }
+                            }
                             if (!games[i].dlcs[j].patches[k].name.empty())
                                 std::cout << "Downloading: " << games[i].dlcs[j].patches[k].name << std::endl;
                             std::cout << filepath << std::endl;
@@ -1553,9 +1625,9 @@ int Downloader::downloadCovers(const std::string& gamename, const std::string& d
                         result = curl_easy_getinfo(curlhandle, CURLINFO_RESPONSE_CODE, &response_code);
                         std::cout << "HTTP ERROR: ";
                         if (result == CURLE_OK)
-                            std::cout << response_code << std::endl;
+                            std::cout << response_code << " (" << cover_url << ")" << std::endl;
                         else
-                            std::cout << "failed to get error code: " << curl_easy_strerror(result) << std::endl;
+                            std::cout << "failed to get error code: " << curl_easy_strerror(result) << " (" << cover_url << ")" << std::endl;
                     }
 
                     coverNode = gameNode->IterateChildren(coverNode);
@@ -1611,9 +1683,9 @@ std::string Downloader::getResponse(const std::string& url)
             result = curl_easy_getinfo(curlhandle, CURLINFO_RESPONSE_CODE, &response_code);
             std::cout << "HTTP ERROR: ";
             if (result == CURLE_OK)
-                std::cout << response_code << std::endl;
+                std::cout << response_code << " (" << url << ")" << std::endl;
             else
-                std::cout << "failed to get error code: " << curl_easy_strerror(result) << std::endl;
+                std::cout << "failed to get error code: " << curl_easy_strerror(result) << " (" << url << ")" << std::endl;
         }
     }
 
@@ -2023,7 +2095,7 @@ std::vector<gameItem> Downloader::getGames()
                     platform |= GlobalConstants::PLATFORM_MAC;
 
                 // Skip if platform doesn't match
-                if (!(platform & config.iInstallerType))
+                if (config.bPlatformDetection && !(platform & config.iInstallerType))
                     continue;
 
                 if (!game.name.empty() && !game.id.empty())
@@ -2180,30 +2252,36 @@ std::vector<gameItem> Downloader::getFreeGames()
     return games;
 }
 
-std::vector<gameFile> Downloader::getExtras(const std::string& gamename, const std::string& gameid)
+std::string Downloader::getGameDetailsHTML(const std::string& gamename, const std::string& gameid)
 {
-    Json::Value root;
-    Json::Reader *jsonparser = new Json::Reader;
-    std::vector<gameFile> extras;
-
     std::string gameDataUrl = "https://www.gog.com/account/ajax?a=gamesListDetails&g=" + gameid;
     std::string json = this->getResponse(gameDataUrl);
+
     // Parse JSON
+    Json::Value root;
+    Json::Reader *jsonparser = new Json::Reader;
     if (!jsonparser->parse(json, root))
     {
         #ifdef DEBUG
-            std::cerr << "DEBUG INFO (Downloader::getExtras)" << std::endl << json << std::endl;
+            std::cerr << "DEBUG INFO (Downloader::getGameDetailsHTML)" << std::endl << json << std::endl;
         #endif
         std::cout << jsonparser->getFormatedErrorMessages();
         delete jsonparser;
         exit(1);
     }
     #ifdef DEBUG
-        std::cerr << "DEBUG INFO (Downloader::getExtras)" << std::endl << root << std::endl;
+        std::cerr << "DEBUG INFO (Downloader::getGameDetailsHTML)" << std::endl << root << std::endl;
     #endif
     std::string html = root["details"]["html"].asString();
     delete jsonparser;
 
+    return html;
+}
+
+std::vector<gameFile> Downloader::getExtrasFromHTML(const std::string& html, const std::string& gamename, const std::string& gameid)
+{
+    std::vector<gameFile> extras;
+
     htmlcxx::HTML::ParserDom parser;
     tree<htmlcxx::HTML::Node> dom = parser.parseTree(html);
     tree<htmlcxx::HTML::Node>::iterator it = dom.begin();
@@ -2237,6 +2315,15 @@ std::vector<gameFile> Downloader::getExtras(const std::string& gamename, const s
                 // Get name from path
                 name.assign(path.begin()+path.find_last_of("/")+1,path.end());
 
+                if (name.empty())
+                {
+                    #ifdef DEBUG
+                        std::cerr << "DEBUG INFO (getExtrasFromHTML)" << std::endl;
+                        std::cerr << "Skipped file without a name (game: " << gamename << ", gameid: " << gameid << ", fileid: " << id << ")" << std::endl;
+                    #endif
+                    continue;
+                }
+
                 extras.push_back(
                                     gameFile (  false,
                                                 id,
@@ -2252,6 +2339,60 @@ std::vector<gameFile> Downloader::getExtras(const std::string& gamename, const s
     return extras;
 }
 
+
+std::string Downloader::getSerialsFromHTML(const std::string& html)
+{
+    std::ostringstream serials;
+
+    htmlcxx::HTML::ParserDom parser;
+    tree<htmlcxx::HTML::Node> dom = parser.parseTree(html);
+    tree<htmlcxx::HTML::Node>::iterator it = dom.begin();
+    tree<htmlcxx::HTML::Node>::iterator end = dom.end();
+    for (; it != end; ++it)
+    {
+        if (it->tagName() == "div")
+        {
+            it->parseAttributes();
+            std::string classname = it->attribute("class").second;
+            if (classname == "list_serial_h")
+            {
+                for (unsigned int i = 0; i < dom.number_of_children(it); ++i)
+                {
+                    tree<htmlcxx::HTML::Node>::iterator serials_it = dom.child(it, i);
+                    if (!serials_it->isComment())
+                    {
+                        std::string tag_text;
+                        if (!serials_it->isTag())
+                        {
+                            if (!serials_it->text().empty())
+                                tag_text = serials_it->text();
+                        }
+                        else if (serials_it->tagName() == "span")
+                        {
+                            for (unsigned int j = 0; j < dom.number_of_children(serials_it); ++j)
+                            {
+                                tree<htmlcxx::HTML::Node>::iterator serials_span_it = dom.child(serials_it, j);
+                                if (!serials_span_it->isTag() && !serials_span_it->isComment())
+                                    tag_text = serials_span_it->text();
+                            }
+                        }
+
+                        if (!tag_text.empty())
+                        {
+                            boost::regex expression("^\\h+|\\h+$");
+                            std::string text = boost::regex_replace(tag_text, expression, "");
+                            if (!text.empty())
+                                serials << text << std::endl;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return serials.str();
+}
+
 void Downloader::checkOrphans()
 {
     // Always check everything when checking for orphaned files
@@ -2461,7 +2602,7 @@ void Downloader::checkStatus()
                 localHash = this->getLocalFileHash(filepath.string(), games[i].gamename);
                 remoteHash = this->getRemoteFileHash(games[i].gamename, games[i].installers[j].id);
 
-                if (boost::filesystem::exists(filepath))
+                if (boost::filesystem::exists(filepath) && boost::filesystem::is_regular_file(filepath))
                 {
                     filesize = boost::filesystem::file_size(filepath);
 
@@ -2486,7 +2627,7 @@ void Downloader::checkStatus()
                 std::string localHash = this->getLocalFileHash(filepath.string(), games[i].gamename);
                 size_t filesize;
 
-                if (boost::filesystem::exists(filepath))
+                if (boost::filesystem::exists(filepath) && boost::filesystem::is_regular_file(filepath))
                 {
                     filesize = boost::filesystem::file_size(filepath);
                     std::cout << "OK " << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
@@ -2507,7 +2648,7 @@ void Downloader::checkStatus()
                 std::string localHash = this->getLocalFileHash(filepath.string(), games[i].gamename);
                 size_t filesize;
 
-                if (boost::filesystem::exists(filepath))
+                if (boost::filesystem::exists(filepath) && boost::filesystem::is_regular_file(filepath))
                 {
                     filesize = boost::filesystem::file_size(filepath);
                     std::cout << "OK " << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
@@ -2528,7 +2669,7 @@ void Downloader::checkStatus()
                 std::string localHash = this->getLocalFileHash(filepath.string(), games[i].gamename);
                 size_t filesize;
 
-                if (boost::filesystem::exists(filepath))
+                if (boost::filesystem::exists(filepath) && boost::filesystem::is_regular_file(filepath))
                 {
                     filesize = boost::filesystem::file_size(filepath);
                     std::cout << "OK " << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
@@ -2558,7 +2699,7 @@ void Downloader::checkStatus()
                         localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename);
                         remoteHash = this->getRemoteFileHash(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id);
 
-                        if (boost::filesystem::exists(filepath))
+                        if (boost::filesystem::exists(filepath) && boost::filesystem::is_regular_file(filepath))
                         {
                             filesize = boost::filesystem::file_size(filepath);
 
@@ -2583,7 +2724,7 @@ void Downloader::checkStatus()
                         std::string localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename);
                         size_t filesize;
 
-                        if (boost::filesystem::exists(filepath))
+                        if (boost::filesystem::exists(filepath) && boost::filesystem::is_regular_file(filepath))
                         {
                             filesize = boost::filesystem::file_size(filepath);
                             std::cout << "OK " << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
@@ -2604,7 +2745,7 @@ void Downloader::checkStatus()
                         std::string localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename);
                         size_t filesize;
 
-                        if (boost::filesystem::exists(filepath))
+                        if (boost::filesystem::exists(filepath) && boost::filesystem::is_regular_file(filepath))
                         {
                             filesize = boost::filesystem::file_size(filepath);
                             std::cout << "OK " << games[i].gamename << " " << filepath.filename().string() << " " << filesize << " " << localHash << std::endl;
@@ -2645,7 +2786,7 @@ std::string Downloader::getLocalFileHash(const std::string& filepath, const std:
     }
     else
     {
-        if (boost::filesystem::exists(path))
+        if (boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path))
         {
             localHash = Util::getFileHash(path.string(), RHASH_MD5);
         }
@@ -2657,6 +2798,11 @@ std::string Downloader::getRemoteFileHash(const std::string& gamename, const std
 {
     std::string remoteHash;
     std::string xml_data = gogAPI->getXML(gamename, id);
+    if (gogAPI->getError())
+    {
+        std::cout << gogAPI->getErrorMessage() << std::endl;
+        gogAPI->clearError();
+    }
     if (!xml_data.empty())
     {
         TiXmlDocument remote_xml;
@@ -2789,6 +2935,7 @@ std::vector<gameDetails> Downloader::getGameDetailsFromJsonNode(Json::Value root
         }
         game.title = gameDetailsNode["title"].asString();
         game.icon = gameDetailsNode["icon"].asString();
+        game.serials = gameDetailsNode["serials"].asString();
 
         // Make a vector of valid node names to make things easier
         std::vector<std::string> nodes;
@@ -2883,3 +3030,49 @@ void Downloader::updateCache()
 
     return;
 }
+
+// Save serials to file
+void Downloader::saveSerials(const std::string& serials, const std::string& filepath)
+{
+    bool bFileExists = boost::filesystem::exists(filepath);
+
+    if (bFileExists)
+        return;
+
+    // Get directory from filepath
+    boost::filesystem::path pathname = filepath;
+    std::string directory = pathname.parent_path().string();
+
+    // Check that directory exists and create subdirectories
+    boost::filesystem::path path = directory;
+    if (boost::filesystem::exists(path))
+    {
+        if (!boost::filesystem::is_directory(path))
+        {
+            std::cout << path << " is not directory" << std::endl;
+            return;
+        }
+    }
+    else
+    {
+        if (!boost::filesystem::create_directories(path))
+        {
+            std::cout << "Failed to create directory: " << path << std::endl;
+            return;
+        }
+    }
+
+    std::ofstream ofs(filepath);
+    if (ofs)
+    {
+        std::cout << "Saving serials: " << filepath << std::endl;
+        ofs << serials;
+        ofs.close();
+    }
+    else
+    {
+        std::cout << "Failed to create file: " << filepath << std::endl;
+    }
+
+    return;
+}
diff --git a/src/gamedetails.cpp b/src/gamedetails.cpp
index ae02b18..5e57777 100644
--- a/src/gamedetails.cpp
+++ b/src/gamedetails.cpp
@@ -71,6 +71,7 @@ void gameDetails::makeFilepaths(const Config& config)
     std::string filepath;
     std::string directory = config.sDirectory + "/" + config.sGameSubdir + "/";
     std::string subdir;
+    this->serialsFilepath = Util::makeFilepath(directory, "serials.txt", this->gamename, subdir, 0);
 
     for (unsigned int i = 0; i < this->installers.size(); ++i)
     {
@@ -102,6 +103,8 @@ void gameDetails::makeFilepaths(const Config& config)
 
     for (unsigned int i = 0; i < this->dlcs.size(); ++i)
     {
+        subdir = config.bSubDirectories ? config.sDLCSubdir + "/" + config.sInstallersSubdir : "";
+        this->dlcs[i].serialsFilepath = Util::makeFilepath(directory, "serials.txt", this->gamename, subdir, 0);
         for (unsigned int j = 0; j < this->dlcs[i].installers.size(); ++j)
         {
             subdir = config.bSubDirectories ? config.sDLCSubdir + "/" + config.sInstallersSubdir : "";
@@ -132,6 +135,7 @@ Json::Value gameDetails::getDetailsAsJson()
     json["gamename"] = this->gamename;
     json["title"] = this->title;
     json["icon"] = this->icon;
+    json["serials"] = this->serials;
 
     for (unsigned int i = 0; i < this->extras.size(); ++i)
         json["extras"].append(this->extras[i].getAsJson());
@@ -152,3 +156,8 @@ Json::Value gameDetails::getDetailsAsJson()
 
     return json;
 }
+
+std::string gameDetails::getSerialsFilepath()
+{
+    return this->serialsFilepath;
+}
diff --git a/src/util.cpp b/src/util.cpp
index 63fb0dd..e66da1e 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -9,7 +9,7 @@
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string/case_conv.hpp>
 #include <tinyxml.h>
-#include <jsoncpp/json/json.h>
+#include <json/json.h>
 #include <fstream>
 #include <sys/ioctl.h>
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/lgogdownloader.git



More information about the Pkg-games-commits mailing list