/* 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 DOWNLOADER_H #define DOWNLOADER_H #if __GNUC__ # if !(__x86_64__ || __ppc64__ || __LP64__) # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE # endif # ifndef _LARGEFILE64_SOURCE # define _LARGEFILE64_SOURCE # endif # if !defined(_FILE_OFFSET_BITS) || (_FILE_OFFSET_BITS == 32) # define _FILE_OFFSET_BITS 64 # endif # endif #endif #include "config.h" #include "progressbar.h" #include "website.h" #include "threadsafequeue.h" #include "galaxyapi.h" #include "globals.h" #include "util.h" #include #include #include #include #include class Timer { public: Timer() { this->reset(); }; void reset() { gettimeofday(&(this->last_update), NULL); }; double getTimeBetweenUpdates() { // Returns time elapsed between updates in milliseconds struct timeval time_now; gettimeofday(&time_now, NULL); double time_between = ( (time_now.tv_sec+(time_now.tv_usec/1000000.0))*1000.0 - (this->last_update.tv_sec+(this->last_update.tv_usec/1000000.0))*1000.0 ); return time_between; }; ~Timer() {}; private: struct timeval last_update; }; struct xferInfo { unsigned int tid; CURL* curlhandle; Timer timer; std::deque< std::pair > TimeAndSize; curl_off_t offset; }; typedef struct { std::string filepath; off_t comp_size; off_t uncomp_size; off_t start_offset_zip; off_t start_offset_mojosetup; off_t end_offset; uint16_t file_attributes; uint32_t crc32; time_t timestamp; std::string installer_url; // For split file handling bool isSplitFile = false; std::string splitFileBasePath; std::string splitFilePartExt; off_t splitFileStartOffset; off_t splitFileEndOffset; } zipFileEntry; typedef std::map> splitFilesMap; class Downloader { public: Downloader(); virtual ~Downloader(); bool isLoggedIn(); int init(); int login(); int listGames(); void checkNotifications(); void clearUpdateNotifications(); void repair(); void download(); void checkOrphans(); void checkStatus(); void updateCache(); int downloadFileWithId(const std::string& fileid_string, const std::string& output_filepath); void showWishlist(); CURL* curlhandle; Timer timer; ProgressBar* progressbar; std::deque< std::pair > TimeAndSize; void saveGalaxyJSON(); void galaxyInstallGame(const std::string& product_id, int build_index = -1, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64); void galaxyInstallGameById(const std::string& product_id, int build_index = -1, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64); void galaxyShowBuilds(const std::string& product_id, int build_index = -1); void galaxyShowBuildsById(const std::string& product_id, int build_index = -1); protected: private: CURLcode downloadFile(const std::string& url, const std::string& filepath, const std::string& xml_data = std::string(), const std::string& gamename = std::string()); int repairFile(const std::string& url, const std::string& filepath, const std::string& xml_data = std::string(), const std::string& gamename = std::string()); int getGameDetails(); void getGameList(); uintmax_t getResumePosition(); CURLcode beginDownload(); std::string getResponse(const std::string& url); std::string getLocalFileHash(const std::string& filepath, const std::string& gamename = std::string()); std::string getRemoteFileHash(const gameFile& gf); int loadGameDetailsCache(); int saveGameDetailsCache(); std::vector getGameDetailsFromJsonNode(Json::Value root, const int& recursion_level = 0); 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); void saveChangelog(const std::string& changelog, const std::string& filepath); static void processDownloadQueue(Config conf, const unsigned int& tid); static int progressCallbackForThread(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); template void printProgress(const ThreadSafeQueue& download_queue); static void getGameDetailsThread(Config config, const unsigned int& tid); static int progressCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); static size_t writeData(void *ptr, size_t size, size_t nmemb, FILE *stream); static size_t readData(void *ptr, size_t size, size_t nmemb, FILE *stream); std::vector galaxyGetOrphanedFiles(const std::vector& items, const std::string& install_path); static void processGalaxyDownloadQueue(const std::string& install_path, Config conf, const unsigned int& tid); void galaxyInstallGame_MojoSetupHack(const std::string& product_id); void galaxyInstallGame_MojoSetupHack_CombineSplitFiles(const splitFilesMap& mSplitFiles, const bool& bAppendtoFirst = false); static void processGalaxyDownloadQueue_MojoSetupHack(Config conf, const unsigned int& tid); int mojoSetupGetFileVector(const gameFile& gf, std::vector& vFiles); std::string getGalaxyInstallDirectory(galaxyAPI *galaxyHandle, const Json::Value& manifest); bool galaxySelectProductIdHelper(const std::string& product_id, std::string& selected_product); std::vector galaxyGetDepotItemVectorFromJson(const Json::Value& json, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64); Website *gogWebsite; galaxyAPI *gogGalaxy; std::vector gameItems; std::vector games; off_t resume_position; int retries; std::ofstream report_ofs; }; #endif // DOWNLOADER_H