diff --git a/cmake/FindTinyxml.cmake b/cmake/FindTinyxml.cmake index 4764541..f399381 100644 --- a/cmake/FindTinyxml.cmake +++ b/cmake/FindTinyxml.cmake @@ -6,7 +6,7 @@ # Tinyxml_LIBRARIES - The libraries needed to use tinyxml find_package(PkgConfig) -pkg_check_modules(PC_TINYXML REQUIRED tinyxml) +pkg_check_modules(PC_TINYXML tinyxml) find_path(TINYXML_INCLUDE_DIR tinyxml.h HINTS @@ -26,8 +26,8 @@ find_library(TINYXML_LIBRARY tinyxml mark_as_advanced(TINYXML_INCLUDE_DIR TINYXML_LIBRARY) -if(PC_TINYXML_FOUND) +if(TINYXML_INCLUDE_DIR) set(Tinyxml_FOUND ON) set(Tinyxml_INCLUDE_DIRS ${TINYXML_INCLUDE_DIR}) set(Tinyxml_LIBRARIES ${TINYXML_LIBRARY}) -endif(PC_TINYXML_FOUND) +endif(TINYXML_INCLUDE_DIR) diff --git a/include/api.h b/include/api.h index 3104230..97abe45 100644 --- a/include/api.h +++ b/include/api.h @@ -72,7 +72,7 @@ class API std::string getErrorMessage() { return this->error_message; }; std::string getToken() { return this->config.oauth_token; }; std::string getSecret() { return this->config.oauth_secret; }; - template CURLcode curlSetOpt(CURLoption option, T value) { return curl_easy_setopt(this->curlhandle, option, value); }; + template CURLcode curlSetOpt(CURLoption option, T value) { return curl_easy_setopt(this->curlhandle, option, value); } virtual ~API(); protected: private: diff --git a/include/config.h b/include/config.h index 0bedfe6..1ef35d9 100644 --- a/include/config.h +++ b/include/config.h @@ -60,6 +60,7 @@ class Config std::string sCookiePath; std::string sConfigFilePath; std::string sBlacklistFilePath; + std::string sIgnorelistFilePath; std::string sOrphanRegex; std::string sCoverList; std::string sReportFilePath; @@ -87,6 +88,7 @@ class Config curl_off_t iDownloadRate; long int iTimeout; Blacklist blacklist; + Blacklist ignorelist; }; #endif // CONFIG_H__ diff --git a/include/globalconstants.h b/include/globalconstants.h index 47ada3a..2ae0f96 100644 --- a/include/globalconstants.h +++ b/include/globalconstants.h @@ -74,6 +74,6 @@ namespace GlobalConstants { PLATFORM_MAC, "mac", "Mac" , "m|mac|osx" }, { PLATFORM_LINUX, "linux", "Linux" , "l|lin|linux" } }; -}; +} #endif // GLOBALCONSTANTS_H_INCLUDED diff --git a/main.cpp b/main.cpp index 27ec91e..f0f044b 100644 --- a/main.cpp +++ b/main.cpp @@ -54,6 +54,7 @@ int main(int argc, char *argv[]) config.sCookiePath = config.sConfigDirectory + "/cookies.txt"; config.sConfigFilePath = config.sConfigDirectory + "/config.cfg"; config.sBlacklistFilePath = config.sConfigDirectory + "/blacklist.txt"; + config.sIgnorelistFilePath = config.sConfigDirectory + "/ignorelist.txt"; std::string priority_help_text = "Set priority by separating values with \",\"\nCombine values by separating with \"+\""; // Create help text for --platform option @@ -209,7 +210,7 @@ int main(int argc, char *argv[]) { if (!boost::filesystem::create_directories(path)) { - std::cout << "Failed to create directory: " << path << std::endl; + std::cerr << "Failed to create directory: " << path << std::endl; return 1; } } @@ -219,7 +220,7 @@ int main(int argc, char *argv[]) { if (!boost::filesystem::create_directories(path)) { - std::cout << "Failed to create directory: " << path << std::endl; + std::cerr << "Failed to create directory: " << path << std::endl; return 1; } } @@ -229,7 +230,7 @@ int main(int argc, char *argv[]) { if (!boost::filesystem::create_directories(path)) { - std::cout << "Failed to create directory: " << path << std::endl; + std::cerr << "Failed to create directory: " << path << std::endl; return 1; } } @@ -239,7 +240,7 @@ int main(int argc, char *argv[]) std::ifstream ifs(config.sConfigFilePath.c_str()); if (!ifs) { - std::cout << "Could not open config file: " << config.sConfigFilePath << std::endl; + std::cerr << "Could not open config file: " << config.sConfigFilePath << std::endl; return 1; } else @@ -256,7 +257,7 @@ int main(int argc, char *argv[]) std::ifstream ifs(config.sBlacklistFilePath.c_str()); if (!ifs) { - std::cout << "Could not open blacklist file: " << config.sBlacklistFilePath << std::endl; + std::cerr << "Could not open blacklist file: " << config.sBlacklistFilePath << std::endl; return 1; } else @@ -272,6 +273,27 @@ int main(int argc, char *argv[]) } } + if (boost::filesystem::exists(config.sIgnorelistFilePath)) + { + std::ifstream ifs(config.sIgnorelistFilePath.c_str()); + if (!ifs) + { + std::cerr << "Could not open ignorelist file: " << config.sIgnorelistFilePath << std::endl; + return 1; + } + else + { + std::string line; + std::vector lines; + while (!ifs.eof()) + { + std::getline(ifs, line); + lines.push_back(std::move(line)); + } + config.ignorelist.initialize(lines); + } + } + if (vm.count("chunk-size")) config.iChunkSize <<= 20; // Convert chunk size from bytes to megabytes @@ -363,13 +385,13 @@ int main(int argc, char *argv[]) if (config.iInstallerPlatform < GlobalConstants::PLATFORMS[0].id || config.iInstallerPlatform > platform_all) { - std::cout << "Invalid value for --platform" << std::endl; + std::cerr << "Invalid value for --platform" << std::endl; return 1; } if (config.iInstallerLanguage < GlobalConstants::LANGUAGES[0].id || config.iInstallerLanguage > language_all) { - std::cout << "Invalid value for --language" << std::endl; + std::cerr << "Invalid value for --language" << std::endl; return 1; } @@ -435,7 +457,7 @@ int main(int argc, char *argv[]) std::ofstream ofs(config.sConfigFilePath.c_str()); if (ofs) { - std::cout << "Saving config: " << config.sConfigFilePath << std::endl; + std::cerr << "Saving config: " << config.sConfigFilePath << std::endl; for (bpo::variables_map::iterator it = vm.begin(); it != vm.end(); ++it) { std::string option = it->first; @@ -486,7 +508,7 @@ int main(int argc, char *argv[]) } else { - std::cout << "Failed to create config: " << config.sConfigFilePath << std::endl; + std::cerr << "Failed to create config: " << config.sConfigFilePath << std::endl; return 1; } } @@ -506,7 +528,7 @@ int main(int argc, char *argv[]) } else { - std::cout << "Failed to create config: " << config.sConfigFilePath << std::endl; + std::cerr << "Failed to create config: " << config.sConfigFilePath << std::endl; return 1; } } @@ -535,7 +557,7 @@ int main(int argc, char *argv[]) downloader.checkStatus(); else { // Show help message - std::cout << config.sVersionString << std::endl + std::cerr << config.sVersionString << std::endl << options_cli_all << std::endl; } diff --git a/man/lgogdownloader.supplemental.groff b/man/lgogdownloader.supplemental.groff index e0eed30..a376412 100644 --- a/man/lgogdownloader.supplemental.groff +++ b/man/lgogdownloader.supplemental.groff @@ -62,7 +62,15 @@ If \fB$XDG_CACHE_HOME\fP is not set, it will use \fI$HOME/.cache/lgogdownloader/ .TP \fI$XDG_CONFIG_HOME/lgogdownloader/blacklist.txt\fP -Allows user to specify individual files that should not be downloaded or mentioned as orphans. +Allows user to specify individual files that should not be downloaded. +.br +It doesn't have to exist, but if it does exist, it must be readable to lgogdownloader. + +.TP +\fI$XDG_CONFIG_HOME/lgogdownloader/ignorelist.txt\fP +Allows user to specify individual files that should not be mentioned +as orphans. The file has the same format and interpretation as a +blacklist. .br It doesn't have to exist, but if it does exist, it must be readable to lgogdownloader. diff --git a/src/downloader.cpp b/src/downloader.cpp index 35162c3..419bab4 100644 --- a/src/downloader.cpp +++ b/src/downloader.cpp @@ -32,7 +32,7 @@ Downloader::Downloader(Config &conf) this->config = conf; if (config.bLoginHTTP && boost::filesystem::exists(config.sCookiePath)) if (!boost::filesystem::remove(config.sCookiePath)) - std::cout << "Failed to delete " << config.sCookiePath << std::endl; + std::cerr << "Failed to delete " << config.sCookiePath << std::endl; } Downloader::~Downloader() @@ -105,7 +105,7 @@ int Downloader::init() this->report_ofs.open(config.sReportFilePath); if (!this->report_ofs) { - std::cout << "Failed to create " << config.sReportFilePath << std::endl; + std::cerr << "Failed to create " << config.sReportFilePath << std::endl; return 1; } } @@ -122,16 +122,16 @@ int Downloader::login() char *pwd; std::string email; if (!isatty(STDIN_FILENO)) { - std::cout << "Unable to read email and password" << std::endl; + std::cerr << "Unable to read email and password" << std::endl; return 0; } - std::cout << "Email: "; + std::cerr << "Email: "; std::getline(std::cin,email); pwd = getpass("Password: "); std::string password = (std::string)pwd; if (email.empty() || password.empty()) { - std::cout << "Email and/or password empty" << std::endl; + std::cerr << "Email and/or password empty" << std::endl; return 0; } else @@ -141,12 +141,12 @@ int Downloader::login() { if (!HTTP_Login(email, password)) { - std::cout << "HTTP: Login failed" << std::endl; + std::cerr << "HTTP: Login failed" << std::endl; return 0; } else { - std::cout << "HTTP: Login successful" << std::endl; + std::cerr << "HTTP: Login successful" << std::endl; if (!config.bLoginAPI) return 1; } @@ -156,12 +156,12 @@ int Downloader::login() { if (!gogAPI->login(email, password)) { - std::cout << "API: Login failed" << std::endl; + std::cerr << "API: Login failed" << std::endl; return 0; } else { - std::cout << "API: Login successful" << std::endl; + std::cerr << "API: Login successful" << std::endl; config.sToken = gogAPI->getToken(); config.sSecret = gogAPI->getSecret(); return 1; @@ -227,7 +227,7 @@ int Downloader::getGameDetails() if (config.sGameRegex == "all") config.sGameRegex = ".*"; else if (config.sGameRegex == "free") - std::cout << "Warning: regex alias \"free\" doesn't work with cached details" << std::endl; + std::cerr << "Warning: regex alias \"free\" doesn't work with cached details" << std::endl; int result = this->loadGameDetailsCache(); if (result == 0) @@ -245,13 +245,13 @@ int Downloader::getGameDetails() { if (result == 1) { - std::cout << "Cache doesn't exist." << std::endl; - std::cout << "Create cache with --update-cache" << std::endl; + std::cerr << "Cache doesn't exist." << std::endl; + std::cerr << "Create cache with --update-cache" << std::endl; } else if (result == 3) { - std::cout << "Cache is too old." << std::endl; - std::cout << "Update cache with --update-cache or use bigger --cache-valid" << std::endl; + std::cerr << "Cache is too old." << std::endl; + std::cerr << "Update cache with --update-cache or use bigger --cache-valid" << std::endl; } return 1; } @@ -261,7 +261,7 @@ int Downloader::getGameDetails() int updated = 0; for (unsigned int i = 0; i < gameItems.size(); ++i) { - std::cout << "Getting game info " << i+1 << " / " << gameItems.size() << "\r" << std::flush; + std::cerr << "Getting game info " << i+1 << " / " << gameItems.size() << "\r" << std::flush; bool bHasDLC = !gameItems[i].dlcnames.empty(); gameSpecificConfig conf; @@ -277,31 +277,31 @@ int Downloader::getGameDetails() int iOptionsOverridden = Util::getGameSpecificConfig(gameItems[i].name, &conf); if (iOptionsOverridden > 0) { - std::cout << std::endl << gameItems[i].name << " - " << iOptionsOverridden << " options overridden with game specific options" << std::endl; + std::cerr << std::endl << gameItems[i].name << " - " << iOptionsOverridden << " options overridden with game specific options" << std::endl; if (config.bVerbose) { if (conf.bIgnoreDLCCount) - std::cout << "\tIgnore DLC count" << std::endl; + std::cerr << "\tIgnore DLC count" << std::endl; if (conf.bDLC != config.bDLC) - std::cout << "\tDLC: " << (conf.bDLC ? "true" : "false") << std::endl; + std::cerr << "\tDLC: " << (conf.bDLC ? "true" : "false") << std::endl; if (conf.iInstallerLanguage != config.iInstallerLanguage) - std::cout << "\tLanguage: " << Util::getOptionNameString(conf.iInstallerLanguage, GlobalConstants::LANGUAGES) << std::endl; + std::cerr << "\tLanguage: " << Util::getOptionNameString(conf.iInstallerLanguage, GlobalConstants::LANGUAGES) << std::endl; if (conf.vLanguagePriority != config.vLanguagePriority) { - std::cout << "\tLanguage priority:" << std::endl; + std::cerr << "\tLanguage priority:" << std::endl; for (unsigned int j = 0; j < conf.vLanguagePriority.size(); ++j) { - std::cout << "\t " << j << ": " << Util::getOptionNameString(conf.vLanguagePriority[j], GlobalConstants::LANGUAGES) << std::endl; + std::cerr << "\t " << j << ": " << Util::getOptionNameString(conf.vLanguagePriority[j], GlobalConstants::LANGUAGES) << std::endl; } } if (conf.iInstallerPlatform != config.iInstallerPlatform) - std::cout << "\tPlatform: " << Util::getOptionNameString(conf.iInstallerPlatform, GlobalConstants::PLATFORMS) << std::endl; + std::cerr << "\tPlatform: " << Util::getOptionNameString(conf.iInstallerPlatform, GlobalConstants::PLATFORMS) << std::endl; if (conf.vPlatformPriority != config.vPlatformPriority) { - std::cout << "\tPlatform priority:" << std::endl; + std::cerr << "\tPlatform priority:" << std::endl; for (unsigned int j = 0; j < conf.vPlatformPriority.size(); ++j) { - std::cout << "\t " << j << ": " << Util::getOptionNameString(conf.vPlatformPriority[j], GlobalConstants::PLATFORMS) << std::endl; + std::cerr << "\t " << j << ": " << Util::getOptionNameString(conf.vPlatformPriority[j], GlobalConstants::PLATFORMS) << std::endl; } } } @@ -411,19 +411,19 @@ int Downloader::getGameDetails() } if (updated >= gogAPI->user.notifications_games) { // Gone through all updated games. No need to go through the rest. - std::cout << std::endl << "Got info for all updated games. Moving on..." << std::endl; + std::cerr << std::endl << "Got info for all updated games. Moving on..." << std::endl; break; } } } else { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } } - std::cout << std::endl; + std::cerr << std::endl; return 0; } @@ -454,7 +454,7 @@ void Downloader::listGames() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -480,7 +480,7 @@ void Downloader::listGames() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -501,7 +501,7 @@ void Downloader::listGames() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -526,7 +526,7 @@ void Downloader::listGames() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -554,7 +554,7 @@ void Downloader::listGames() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -571,7 +571,7 @@ void Downloader::listGames() std::string filepath = games[i].dlcs[j].patches[k].getFilepath(); if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -587,7 +587,7 @@ void Downloader::listGames() std::string filepath = games[i].dlcs[j].extras[k].getFilepath(); if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -630,7 +630,7 @@ void Downloader::repair() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -641,7 +641,7 @@ void Downloader::repair() XML = gogAPI->getXML(games[i].gamename, games[i].installers[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -654,7 +654,7 @@ void Downloader::repair() std::string url = gogAPI->getInstallerLink(games[i].gamename, games[i].installers[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -674,14 +674,14 @@ void Downloader::repair() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } std::string url = gogAPI->getExtraLink(games[i].gamename, games[i].extras[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -700,7 +700,7 @@ void Downloader::repair() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -711,7 +711,7 @@ void Downloader::repair() XML = gogAPI->getXML(games[i].gamename, games[i].patches[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); } } @@ -719,7 +719,7 @@ void Downloader::repair() std::string url = gogAPI->getPatchLink(games[i].gamename, games[i].patches[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -738,14 +738,14 @@ void Downloader::repair() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } std::string url = gogAPI->getLanguagePackLink(games[i].gamename, games[i].languagepacks[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -766,7 +766,7 @@ void Downloader::repair() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -777,7 +777,7 @@ void Downloader::repair() XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -790,7 +790,7 @@ void Downloader::repair() std::string url = gogAPI->getInstallerLink(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -807,7 +807,7 @@ void Downloader::repair() std::string filepath = games[i].dlcs[j].patches[k].getFilepath(); if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -818,7 +818,7 @@ void Downloader::repair() XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); } } @@ -826,7 +826,7 @@ void Downloader::repair() std::string url = gogAPI->getPatchLink(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -842,14 +842,14 @@ void Downloader::repair() std::string filepath = games[i].dlcs[j].extras[k].getFilepath(); if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } std::string url = gogAPI->getExtraLink(games[i].dlcs[j].gamename, games[i].dlcs[j].extras[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -906,7 +906,7 @@ void Downloader::download() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -914,7 +914,7 @@ void Downloader::download() std::string url = gogAPI->getInstallerLink(games[i].gamename, games[i].installers[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -928,7 +928,7 @@ void Downloader::download() XML = gogAPI->getXML(games[i].gamename, games[i].installers[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); } } @@ -949,7 +949,7 @@ void Downloader::download() std::string url = gogAPI->getExtraLink(games[i].gamename, games[i].extras[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -958,7 +958,7 @@ void Downloader::download() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -993,7 +993,7 @@ void Downloader::download() std::string url = gogAPI->getPatchLink(games[i].gamename, games[i].patches[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -1002,7 +1002,7 @@ void Downloader::download() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -1015,7 +1015,7 @@ void Downloader::download() XML = gogAPI->getXML(games[i].gamename, games[i].patches[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); } } @@ -1036,7 +1036,7 @@ void Downloader::download() std::string url = gogAPI->getLanguagePackLink(games[i].gamename, games[i].languagepacks[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -1045,7 +1045,7 @@ void Downloader::download() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -1058,7 +1058,7 @@ void Downloader::download() XML = gogAPI->getXML(games[i].gamename, games[i].languagepacks[j].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); } } @@ -1088,7 +1088,7 @@ void Downloader::download() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -1096,7 +1096,7 @@ void Downloader::download() std::string url = gogAPI->getInstallerLink(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -1110,7 +1110,7 @@ void Downloader::download() XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].installers[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); } } @@ -1130,7 +1130,7 @@ void Downloader::download() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -1138,7 +1138,7 @@ void Downloader::download() std::string url = gogAPI->getPatchLink(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -1152,7 +1152,7 @@ void Downloader::download() XML = gogAPI->getXML(games[i].dlcs[j].gamename, games[i].dlcs[j].patches[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); } } @@ -1172,7 +1172,7 @@ void Downloader::download() if (config.blacklist.isBlacklisted(filepath)) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped blacklisted file " << filepath << std::endl; continue; } @@ -1180,7 +1180,7 @@ void Downloader::download() std::string url = gogAPI->getExtraLink(games[i].dlcs[j].gamename, games[i].dlcs[j].extras[k].id); if (gogAPI->getError()) { - std::cout << gogAPI->getErrorMessage() << std::endl; + std::cerr << gogAPI->getErrorMessage() << std::endl; gogAPI->clearError(); continue; } @@ -1258,7 +1258,7 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil { if (!boost::filesystem::is_directory(path)) { - std::cout << path << " is not directory" << std::endl; + std::cerr << path << " is not directory" << std::endl; return res; } } @@ -1266,7 +1266,7 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil { if (!boost::filesystem::create_directories(path)) { - std::cout << "Failed to create directory: " << path << std::endl; + std::cerr << "Failed to create directory: " << path << std::endl; return res; } } @@ -1288,22 +1288,22 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil } else { - std::cout << "Failed to reopen " << filepath << std::endl; + std::cerr << "Failed to reopen " << filepath << std::endl; return res; } } else { // File exists but is not the same version fclose(outfile); - std::cout << "Remote file is different, renaming local file" << std::endl; + std::cerr << "Remote file is different, renaming local file" << std::endl; std::string date_old = "." + bptime::to_iso_string(bptime::second_clock::local_time()) + ".old"; boost::filesystem::path new_name = filepath + date_old; // Rename old file by appending date and ".old" to filename boost::system::error_code ec; boost::filesystem::rename(pathname, new_name, ec); // Rename the file if (ec) { - std::cout << "Failed to rename " << filepath << " to " << new_name.string() << std::endl; - std::cout << "Skipping file" << std::endl; + std::cerr << "Failed to rename " << filepath << " to " << new_name.string() << std::endl; + std::cerr << "Skipping file" << std::endl; return res; } else @@ -1316,7 +1316,7 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil } else { - std::cout << "Failed to create " << filepath << std::endl; + std::cerr << "Failed to create " << filepath << std::endl; return res; } } @@ -1332,7 +1332,7 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil } else { - std::cout << "Failed to create " << filepath << std::endl; + std::cerr << "Failed to create " << filepath << std::endl; return res; } } @@ -1348,14 +1348,14 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil { if (!boost::filesystem::is_directory(path)) { - std::cout << path << " is not directory" << std::endl; + std::cerr << path << " is not directory" << std::endl; } } else { if (!boost::filesystem::create_directories(path)) { - std::cout << "Failed to create directory: " << path << std::endl; + std::cerr << "Failed to create directory: " << path << std::endl; } } std::ofstream ofs(local_xml_file.string().c_str()); @@ -1366,7 +1366,7 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil } else { - std::cout << "Can't create " << local_xml_file.string() << std::endl; + std::cerr << "Can't create " << local_xml_file.string() << std::endl; } } } @@ -1383,7 +1383,7 @@ CURLcode Downloader::downloadFile(const std::string& url, const std::string& fil boost::filesystem::path path = filepath; if (boost::filesystem::exists(path)) if (!boost::filesystem::remove(path)) - std::cout << "Failed to delete " << path << std::endl; + std::cerr << "Failed to delete " << path << std::endl; } if (config.bReport) @@ -2467,6 +2467,17 @@ std::string Downloader::getSerialsFromJSON(const Json::Value& json) return serials.str(); } +// Linear search. Good thing computers are fast and lists are small. +static int isPresent(std::vector& list, const boost::filesystem::path& path, Blacklist& blacklist) +{ + if(blacklist.isBlacklisted(path.native())) + return false; + for (unsigned int k = 0; k < list.size(); ++k) + if (list[k].getFilepath() == path.native()) + return true; + return false; +} + void Downloader::checkOrphans() { // Always check everything when checking for orphaned files @@ -2481,7 +2492,7 @@ void Downloader::checkOrphans() std::vector orphans; for (unsigned int i = 0; i < games.size(); ++i) { - std::cout << "Checking for orphaned files " << i+1 << " / " << games.size() << "\r" << std::flush; + std::cerr << "Checking for orphaned files " << i+1 << " / " << games.size() << "\r" << std::flush; std::vector filepath_vector; try @@ -2529,9 +2540,9 @@ void Downloader::checkOrphans() if (boost::filesystem::is_regular_file(dir_iter->status())) { std::string filepath = dir_iter->path().string(); - if (config.blacklist.isBlacklisted(filepath.substr(pathlen))) { + if (config.ignorelist.isBlacklisted(filepath.substr(pathlen))) { if (config.bVerbose) - std::cout << "skipped blacklisted file " << filepath << std::endl; + std::cerr << "skipped ignorelisted file " << filepath << std::endl; } else { boost::regex expression(config.sOrphanRegex); // Limit to files matching the regex boost::match_results what; @@ -2544,7 +2555,7 @@ void Downloader::checkOrphans() } } else - std::cout << paths[j] << " does not exist" << std::endl; + std::cerr << paths[j] << " does not exist" << std::endl; } } catch (const boost::filesystem::filesystem_error& ex) @@ -2556,80 +2567,20 @@ void Downloader::checkOrphans() { for (unsigned int j = 0; j < filepath_vector.size(); ++j) { - bool bFoundFile = false; // Assume that the file is orphaned + bool bFoundFile = isPresent(games[i].installers, filepath_vector[j], config.blacklist) + || isPresent(games[i].extras, filepath_vector[j], config.blacklist) + || isPresent(games[i].patches, filepath_vector[j], config.blacklist) + || isPresent(games[i].languagepacks, filepath_vector[j], config.blacklist); - // Check installers - for (unsigned int k = 0; k < games[i].installers.size(); ++k) - { - if (games[i].installers[k].path.find(filepath_vector[j].filename().string()) != std::string::npos) - { - bFoundFile = true; - break; - } - } - if (!bFoundFile) - { // Check extras - for (unsigned int k = 0; k < games[i].extras.size(); ++k) - { - if (games[i].extras[k].path.find(filepath_vector[j].filename().string()) != std::string::npos) - { - bFoundFile = true; - break; - } - } - } - if (!bFoundFile) - { // Check patches - for (unsigned int k = 0; k < games[i].patches.size(); ++k) - { - if (games[i].patches[k].path.find(filepath_vector[j].filename().string()) != std::string::npos) - { - bFoundFile = true; - break; - } - } - } - if (!bFoundFile) - { // Check language packs - for (unsigned int k = 0; k < games[i].languagepacks.size(); ++k) - { - if (games[i].languagepacks[k].path.find(filepath_vector[j].filename().string()) != std::string::npos) - { - bFoundFile = true; - break; - } - } - } if (!bFoundFile) { // Check dlcs for (unsigned int k = 0; k < games[i].dlcs.size(); ++k) { - for (unsigned int index = 0; index < games[i].dlcs[k].installers.size(); ++index) - { - if (games[i].dlcs[k].installers[index].path.find(filepath_vector[j].filename().string()) != std::string::npos) - { - bFoundFile = true; - break; - } - } - if (bFoundFile) break; - for (unsigned int index = 0; index < games[i].dlcs[k].patches.size(); ++index) - { - if (games[i].dlcs[k].patches[index].path.find(filepath_vector[j].filename().string()) != std::string::npos) - { - bFoundFile = true; - break; - } - } - for (unsigned int index = 0; index < games[i].dlcs[k].extras.size(); ++index) - { - if (games[i].dlcs[k].extras[index].path.find(filepath_vector[j].filename().string()) != std::string::npos) - { - bFoundFile = true; - break; - } - } - if (bFoundFile) break; + bFoundFile = isPresent(games[i].dlcs[k].installers, filepath_vector[j], config.blacklist) + || isPresent(games[i].dlcs[k].extras, filepath_vector[j], config.blacklist) + || isPresent(games[i].dlcs[k].patches, filepath_vector[j], config.blacklist); + if(bFoundFile) + break; } } if (!bFoundFile) @@ -2668,6 +2619,8 @@ void Downloader::checkStatus() { boost::filesystem::path filepath = games[i].installers[j].getFilepath(); + if (config.blacklist.isBlacklisted(filepath.native())) + continue; std::string remoteHash; std::string localHash; bool bHashOK = true; // assume hash OK @@ -2730,6 +2683,8 @@ void Downloader::checkStatus() { boost::filesystem::path filepath = games[i].extras[j].getFilepath(); + if (config.blacklist.isBlacklisted(filepath.native())) + continue; std::string localHash = this->getLocalFileHash(filepath.string(), games[i].gamename); uintmax_t filesize; @@ -2751,6 +2706,8 @@ void Downloader::checkStatus() { boost::filesystem::path filepath = games[i].patches[j].getFilepath(); + if (config.blacklist.isBlacklisted(filepath.native())) + continue; std::string localHash = this->getLocalFileHash(filepath.string(), games[i].gamename); uintmax_t filesize; @@ -2772,6 +2729,8 @@ void Downloader::checkStatus() { boost::filesystem::path filepath = games[i].languagepacks[j].getFilepath(); + if (config.blacklist.isBlacklisted(filepath.native())) + continue; std::string localHash = this->getLocalFileHash(filepath.string(), games[i].gamename); uintmax_t filesize; @@ -2797,6 +2756,8 @@ void Downloader::checkStatus() { boost::filesystem::path filepath = games[i].dlcs[j].installers[k].getFilepath(); + if (config.blacklist.isBlacklisted(filepath.native())) + continue; std::string remoteHash; std::string localHash; bool bHashOK = true; // assume hash OK @@ -2859,6 +2820,8 @@ void Downloader::checkStatus() { boost::filesystem::path filepath = games[i].dlcs[j].patches[k].getFilepath(); + if (config.blacklist.isBlacklisted(filepath.native())) + continue; std::string localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename); uintmax_t filesize; @@ -2880,6 +2843,8 @@ void Downloader::checkStatus() { boost::filesystem::path filepath = games[i].dlcs[j].extras[k].getFilepath(); + if (config.blacklist.isBlacklisted(filepath.native())) + continue; std::string localHash = this->getLocalFileHash(filepath.string(), games[i].dlcs[j].gamename); uintmax_t filesize; @@ -2911,23 +2876,35 @@ std::string Downloader::getLocalFileHash(const std::string& filepath, const std: else local_xml_file = config.sXMLDirectory + "/" + path.filename().string() + ".xml"; + if (config.bAutomaticXMLCreation && !boost::filesystem::exists(local_xml_file)) + { + std::string xml_directory = config.sXMLDirectory + "/" + gamename; + Util::createXML(filepath, config.iChunkSize, xml_directory); + } + if (boost::filesystem::exists(local_xml_file)) { TiXmlDocument local_xml; local_xml.LoadFile(local_xml_file.string()); TiXmlNode *fileNodeLocal = local_xml.FirstChild("file"); + if (!fileNodeLocal && config.bAutomaticXMLCreation) + { + std::string xml_directory = config.sXMLDirectory + "/" + gamename; + Util::createXML(filepath, config.iChunkSize, xml_directory); + local_xml.LoadFile(local_xml_file.string()); + fileNodeLocal = local_xml.FirstChild("file"); + } if (fileNodeLocal) { TiXmlElement *fileElemLocal = fileNodeLocal->ToElement(); localHash = fileElemLocal->Attribute("md5"); + return localHash; } } - else + + if (boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) { - if (boost::filesystem::exists(path) && boost::filesystem::is_regular_file(path)) - { - localHash = Util::getFileHash(path.string(), RHASH_MD5); - } + localHash = Util::getFileHash(path.string(), RHASH_MD5); } return localHash; } @@ -3092,7 +3069,7 @@ std::vector Downloader::getGameDetailsFromJsonNode(Json::Value root conf.vLanguagePriority = config.vLanguagePriority; conf.vPlatformPriority = config.vPlatformPriority; if (Util::getGameSpecificConfig(game.gamename, &conf) > 0) - std::cout << game.gamename << " - Language: " << conf.iInstallerLanguage << ", Platform: " << conf.iInstallerPlatform << ", DLC: " << (conf.bDLC ? "true" : "false") << std::endl; + std::cerr << game.gamename << " - Language: " << conf.iInstallerLanguage << ", Platform: " << conf.iInstallerPlatform << ", DLC: " << (conf.bDLC ? "true" : "false") << std::endl; for (unsigned int j = 0; j < nodes.size(); ++j) { diff --git a/src/util.cpp b/src/util.cpp index 5433650..4b98c45 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -64,7 +64,7 @@ std::string Util::getFileHash(const std::string& filename, unsigned hash_id) rhash_library_init(); int i = rhash_file(hash_id, filename.c_str(), digest); if (i < 0) - std::cout << "LibRHash error: " << strerror(errno) << std::endl; + std::cerr << "LibRHash error: " << strerror(errno) << std::endl; else rhash_print_bytes(result, digest, rhash_get_digest_size(hash_id), RHPR_HEX); @@ -79,7 +79,7 @@ std::string Util::getChunkHash(unsigned char *chunk, uintmax_t chunk_size, unsig rhash_library_init(); int i = rhash_msg(hash_id, chunk, chunk_size, digest); if (i < 0) - std::cout << "LibRHash error: " << strerror(errno) << std::endl; + std::cerr << "LibRHash error: " << strerror(errno) << std::endl; else rhash_print_bytes(result, digest, rhash_get_digest_size(hash_id), RHPR_HEX); @@ -104,7 +104,7 @@ int Util::createXML(std::string filepath, uintmax_t chunk_size, std::string xml_ boost::filesystem::path path = xml_dir; if (!boost::filesystem::exists(path)) { if (!boost::filesystem::create_directories(path)) { - std::cout << "Failed to create directory: " << path << std::endl; + std::cerr << "Failed to create directory: " << path << std::endl; return res; } } @@ -115,7 +115,7 @@ int Util::createXML(std::string filepath, uintmax_t chunk_size, std::string xml_ filesize = ftell(infile); rewind(infile); } else { - std::cout << filepath << " doesn't exist" << std::endl; + std::cerr << filepath << " doesn't exist" << std::endl; return res; } @@ -159,13 +159,13 @@ int Util::createXML(std::string filepath, uintmax_t chunk_size, std::string xml_ unsigned char *chunk = (unsigned char *) malloc(chunk_size * sizeof(unsigned char *)); if (chunk == NULL) { - std::cout << "Memory error" << std::endl; + std::cerr << "Memory error" << std::endl; return res; } size = fread(chunk, 1, chunk_size, infile); if (size != chunk_size) { - std::cout << "Read error" << std::endl; + std::cerr << "Read error" << std::endl; free(chunk); return res; } @@ -204,7 +204,7 @@ int Util::createXML(std::string filepath, uintmax_t chunk_size, std::string xml_ fclose(xmlfile); res = 1; } else { - std::cout << "Can't create " << filenameXML << std::endl; + std::cerr << "Can't create " << filenameXML << std::endl; return res; } @@ -311,8 +311,8 @@ int Util::getGameSpecificConfig(std::string gamename, gameSpecificConfig* conf, } else { - std::cout << "Failed to parse game specific config " << filepath << std::endl; - std::cout << jsonparser->getFormattedErrorMessages() << std::endl; + std::cerr << "Failed to parse game specific config " << filepath << std::endl; + std::cerr << jsonparser->getFormattedErrorMessages() << std::endl; } delete jsonparser; if (json) @@ -370,7 +370,7 @@ void Util::setFilePermissions(const boost::filesystem::path& path, const boost:: boost::filesystem::permissions(path, permissions, ec); if (ec) { - std::cout << "Failed to set file permissions for " << path.string() << std::endl; + std::cerr << "Failed to set file permissions for " << path.string() << std::endl; } } }