diff --git a/main.cpp b/main.cpp index dcfd856..ccc3520 100644 --- a/main.cpp +++ b/main.cpp @@ -33,24 +33,24 @@ int main(int argc, char *argv[]) config.sConfigFilePath = config.sHome + "/.gogdownloader/config.cfg"; config.sXMLDirectory = config.sHome + "/.gogdownloader/xml"; - // Create gogdownloader directories - boost::filesystem::path path = config.sXMLDirectory; - if (!boost::filesystem::exists(path)) - { - if (!boost::filesystem::create_directories(path)) - { - std::cout << "Failed to create directory: " << path << std::endl; - return 1; - } - } + // Create gogdownloader directories + boost::filesystem::path path = config.sXMLDirectory; + if (!boost::filesystem::exists(path)) + { + if (!boost::filesystem::create_directories(path)) + { + std::cout << "Failed to create directory: " << path << std::endl; + return 1; + } + } // Create help text for --platform option - std::string platform_text = "Select which installers are downloaded\n" + std::string platform_text = "Select which installers are downloaded\n" + std::to_string(INSTALLER_WINDOWS) + " = Windows\n" + std::to_string(INSTALLER_MAC) + " = Mac\n" + std::to_string(INSTALLER_WINDOWS | INSTALLER_MAC) + " = Both"; // Create help text for --language option - std::string language_text = "Select which language installers are downloaded\n" + std::string language_text = "Select which language installers are downloaded\n" + std::to_string(LANGUAGE_EN) + " = English\n" + std::to_string(LANGUAGE_DE) + " = German\n" + std::to_string(LANGUAGE_FR) + " = French\n" @@ -165,7 +165,7 @@ int main(int argc, char *argv[]) // Make sure that directory has trailing slash if (!config.sDirectory.empty()) if (config.sDirectory.at(config.sDirectory.length()-1)!='/') - config.sDirectory += "/"; + config.sDirectory += "/"; Downloader downloader(config); int result = downloader.init(); diff --git a/src/api.cpp b/src/api.cpp index 9117241..a328713 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -159,7 +159,7 @@ int API::login(const std::string& email, const std::string& password) url = oauth_sign_url2(url.c_str(), NULL, OA_HMAC, NULL, CONSUMER_KEY, CONSUMER_SECRET, token.c_str(), secret.c_str()); std::string token_resp = this->getResponse(url); - rc = oauth_split_url_parameters(token_resp.c_str(), &rv); + 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; diff --git a/src/downloader.cpp b/src/downloader.cpp index 98c54ae..a067cf7 100644 --- a/src/downloader.cpp +++ b/src/downloader.cpp @@ -482,70 +482,70 @@ CURLcode Downloader::downloadFile(std::string url, std::string filepath) { CURLcode res = CURLE_RECV_ERROR; // assume network error bool bResume = false; - FILE *outfile; - size_t offset=0; + FILE *outfile; + size_t offset=0; // Get directory from filepath - boost::filesystem::path pathname = filepath; - std::string directory = pathname.parent_path().string(); + 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 res; - } - } - else - { - if (!boost::filesystem::create_directories(path)) - { - std::cout << "Failed to create directory: " << path << std::endl; - return res; - } - } + // 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 res; + } + } + else + { + if (!boost::filesystem::create_directories(path)) + { + std::cout << "Failed to create directory: " << path << std::endl; + return res; + } + } - // Check if file exists - if ((outfile=fopen(filepath.c_str(), "r"))!=NULL) - { - // File exists, resume - if ((outfile = freopen(filepath.c_str(), "r+", outfile))!=NULL ) - { - bResume = true; - fseek(outfile, 0, SEEK_END); - offset = ftell(outfile); - curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM, offset); - this->resume_position = offset; - } - else - { - std::cout << "Failed to reopen " << filepath << std::endl; - return res; - } - } - else - { + // Check if file exists + if ((outfile=fopen(filepath.c_str(), "r"))!=NULL) + { + // File exists, resume + if ((outfile = freopen(filepath.c_str(), "r+", outfile))!=NULL ) + { + bResume = true; + fseek(outfile, 0, SEEK_END); + offset = ftell(outfile); + curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM, offset); + this->resume_position = offset; + } + else + { + std::cout << "Failed to reopen " << filepath << std::endl; + return res; + } + } + else + { // File doesn't exist, create new file if ((outfile=fopen(filepath.c_str(), "w"))!=NULL) { curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM, offset); // start downloading from the beginning of file - this->resume_position = 0; + this->resume_position = 0; } else { std::cout << "Failed to create " << filepath << std::endl; return res; } - } + } curl_easy_setopt(curlhandle, CURLOPT_URL, url.c_str()); curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, outfile); res = this->beginDownload(); - fclose(outfile); + fclose(outfile); // Download failed and was not a resume attempt so delete the file if (res != CURLE_OK && !bResume) @@ -556,16 +556,16 @@ CURLcode Downloader::downloadFile(std::string url, std::string filepath) std::cout << "Failed to delete " << path << std::endl; } - return res; + return res; } // Repair file int Downloader::repairFile(std::string url, std::string filepath, std::string xml_data, std::string xml_dir) { int res = 0; - FILE *outfile; - size_t offset=0; - if (xml_dir.empty()) + FILE *outfile; + size_t offset=0; + if (xml_dir.empty()) xml_dir = config.sHome + "/.gogdownloader/xml"; size_t from_offset, to_offset; @@ -584,11 +584,11 @@ int Downloader::repairFile(std::string url, std::string filepath, std::string xm boost::filesystem::path pathname = filepath; std::string filename = pathname.filename().string(); - TiXmlDocument xml; - if (!xml_data.empty()) { - std::cout << "XML: Using remote file" << std::endl; - xml.Parse(xml_data.c_str()); - } + TiXmlDocument xml; + if (!xml_data.empty()) { + std::cout << "XML: Using remote file" << std::endl; + xml.Parse(xml_data.c_str()); + } else { std::string xml_file = xml_dir + "/" + filename + ".xml"; @@ -596,34 +596,34 @@ int Downloader::repairFile(std::string url, std::string filepath, std::string xm xml.LoadFile(xml_file); } - TiXmlNode *fileNode = xml.FirstChild("file"); - if (!fileNode) - { - std::cout << "XML: Parsing failed / not valid XML" << std::endl; - return res; - } - else - { - std::cout << "XML: Valid XML" << std::endl; - TiXmlElement *fileElem = fileNode->ToElement(); - info.filename = fileElem->Attribute("name"); - info.hash = fileElem->Attribute("md5"); - std::stringstream(fileElem->Attribute("chunks")) >> info.chunks; - std::stringstream(fileElem->Attribute("total_size")) >> info.size; + TiXmlNode *fileNode = xml.FirstChild("file"); + if (!fileNode) + { + std::cout << "XML: Parsing failed / not valid XML" << std::endl; + return res; + } + else + { + std::cout << "XML: Valid XML" << std::endl; + TiXmlElement *fileElem = fileNode->ToElement(); + info.filename = fileElem->Attribute("name"); + info.hash = fileElem->Attribute("md5"); + std::stringstream(fileElem->Attribute("chunks")) >> info.chunks; + std::stringstream(fileElem->Attribute("total_size")) >> info.size; - //Iterate through all chunk nodes - TiXmlNode *chunkNode = fileNode->FirstChild(); - while (chunkNode) - { - TiXmlElement *chunkElem = chunkNode->ToElement(); - std::stringstream(chunkElem->Attribute("from")) >> from_offset; - std::stringstream(chunkElem->Attribute("to")) >> to_offset; - info.chunk_from.push_back(from_offset); - info.chunk_to.push_back(to_offset); - info.chunk_hash.push_back(chunkElem->GetText()); - chunkNode = fileNode->IterateChildren(chunkNode); - } - } + //Iterate through all chunk nodes + TiXmlNode *chunkNode = fileNode->FirstChild(); + while (chunkNode) + { + TiXmlElement *chunkElem = chunkNode->ToElement(); + std::stringstream(chunkElem->Attribute("from")) >> from_offset; + std::stringstream(chunkElem->Attribute("to")) >> to_offset; + info.chunk_from.push_back(from_offset); + info.chunk_to.push_back(to_offset); + info.chunk_hash.push_back(chunkElem->GetText()); + chunkNode = fileNode->IterateChildren(chunkNode); + } + } std::cout << "XML: Parsing finished" << std::endl << std::endl << info.filename << std::endl @@ -631,33 +631,33 @@ int Downloader::repairFile(std::string url, std::string filepath, std::string xm << "\tChunks:\t" << info.chunks << std::endl << "\tSize:\t" << info.size << " bytes" << std::endl << std::endl; - // Check if file exists - if ((outfile=fopen(filepath.c_str(), "r"))!=NULL) - { - // File exists - if ((outfile = freopen(filepath.c_str(), "r+", outfile))!=NULL ) - { - fseek(outfile, 0, SEEK_END); - offset = ftell(outfile); - } + // Check if file exists + if ((outfile=fopen(filepath.c_str(), "r"))!=NULL) + { + // File exists + if ((outfile = freopen(filepath.c_str(), "r+", outfile))!=NULL ) + { + fseek(outfile, 0, SEEK_END); + offset = ftell(outfile); + } else { - std::cout << "Failed to reopen " << filepath << std::endl; - return res; - } - } - else - { + std::cout << "Failed to reopen " << filepath << std::endl; + return res; + } + } + else + { std::cout << "File doesn't exist " << filepath << std::endl; return res; - } + } - if (offset != info.size) - { - std::cout << "Filesizes don't match" << std::endl + if (offset != info.size) + { + std::cout << "Filesizes don't match" << std::endl << "Incomplete download or different version" << std::endl; - return res; - } + return res; + } for (int i=0; iFirstChild(); - while (gameNode) - { - TiXmlElement *gameElem = gameNode->ToElement(); - std::string game_name = gameElem->Attribute("name"); + xml.Parse(cover_xml_data.c_str()); + TiXmlElement *rootNode = xml.RootElement(); + if (!rootNode) + { + std::cout << "Not valid XML" << std::endl; + return res; + } + else + { + TiXmlNode *gameNode = rootNode->FirstChild(); + while (gameNode) + { + TiXmlElement *gameElem = gameNode->ToElement(); + std::string game_name = gameElem->Attribute("name"); - if (game_name == gamename) - { - boost::match_results what; - TiXmlNode *coverNode = gameNode->FirstChild(); - while (coverNode) - { - TiXmlElement *coverElem = coverNode->ToElement(); - std::string cover_url = coverElem->GetText(); - // Get file extension for the image - boost::regex e1(".*(\\.\\w+)$", boost::regex::perl | boost::regex::icase); - boost::regex_search(cover_url, what, e1); - std::string file_extension = what[1]; - std::string cover_name = std::string("cover_") + coverElem->Attribute("id") + file_extension; - std::string filepath = directory + "/" + cover_name; + if (game_name == gamename) + { + boost::match_results what; + TiXmlNode *coverNode = gameNode->FirstChild(); + while (coverNode) + { + TiXmlElement *coverElem = coverNode->ToElement(); + std::string cover_url = coverElem->GetText(); + // Get file extension for the image + boost::regex e1(".*(\\.\\w+)$", boost::regex::perl | boost::regex::icase); + boost::regex_search(cover_url, what, e1); + std::string file_extension = what[1]; + std::string cover_name = std::string("cover_") + coverElem->Attribute("id") + file_extension; + std::string filepath = directory + "/" + cover_name; std::cout << "Downloading cover " << filepath << std::endl; CURLcode result = this->downloadFile(cover_url, filepath); @@ -789,15 +789,15 @@ int Downloader::downloadCovers(std::string gamename, std::string directory, std: std::cout << "failed to get error code: " << curl_easy_strerror(result) << std::endl; } - coverNode = gameNode->IterateChildren(coverNode); - } + coverNode = gameNode->IterateChildren(coverNode); + } break; // Found cover for game, no need to go through rest of the game nodes - } - gameNode = rootNode->IterateChildren(gameNode); - } - } + } + gameNode = rootNode->IterateChildren(gameNode); + } + } - return res; + return res; } CURLcode Downloader::beginDownload() @@ -928,31 +928,31 @@ size_t Downloader::getResumePosition() int Downloader::HTTP_Login(const std::string& email, const std::string& password) { int res = 0; - std::string postdata; - std::ostringstream memory; - std::string buk; + std::string postdata; + std::ostringstream memory; + std::string buk; - // Get "buk" for login form - std::string json = this->getResponse("http://www.gog.com/user/ajax/?a=get"); + // Get "buk" for login form + std::string json = this->getResponse("http://www.gog.com/user/ajax/?a=get"); - Json::Value root; - Json::Reader *jsonparser = new Json::Reader; - bool parsingSuccessful = jsonparser->parse(json, root); - if (!parsingSuccessful) - { + Json::Value root; + Json::Reader *jsonparser = new Json::Reader; + bool parsingSuccessful = jsonparser->parse(json, root); + if (!parsingSuccessful) + { #ifdef DEBUG std::cerr << "DEBUG INFO (Downloader::HTTP_Login)" << std::endl << json << std::endl; #endif - std::cout << jsonparser->getFormatedErrorMessages(); - return res = 0; - } + std::cout << jsonparser->getFormatedErrorMessages(); + return res = 0; + } #ifdef DEBUG std::cerr << "DEBUG INFO (Downloader::HTTP_Login)" << std::endl << root << std::endl; #endif - buk = root["buk"].asString(); + buk = root["buk"].asString(); - //Create postdata - escape characters in email/password to support special characters - postdata = "log_email=" + (std::string)curl_easy_escape(curlhandle, email.c_str(),email.size()) + //Create postdata - escape characters in email/password to support special characters + postdata = "log_email=" + (std::string)curl_easy_escape(curlhandle, email.c_str(),email.size()) + "&log_password=" + (std::string)curl_easy_escape(curlhandle, password.c_str(), password.size()) + "&buk=" + (std::string)curl_easy_escape(curlhandle, buk.c_str(), buk.size()); curl_easy_setopt(curlhandle, CURLOPT_URL, "https://secure.gog.com/login"); @@ -968,27 +968,27 @@ int Downloader::HTTP_Login(const std::string& email, const std::string& password curl_easy_setopt(curlhandle, CURLOPT_MAXREDIRS, -1); json = this->getResponse("http://www.gog.com/user/ajax/?a=get"); - parsingSuccessful = jsonparser->parse(json, root); - if (!parsingSuccessful) - { + parsingSuccessful = jsonparser->parse(json, root); + if (!parsingSuccessful) + { #ifdef DEBUG std::cerr << "DEBUG INFO (Downloader::HTTP_Login)" << std::endl << json << std::endl; #endif - std::cout << jsonparser->getFormatedErrorMessages(); - return res = 0; - } + std::cout << jsonparser->getFormatedErrorMessages(); + return res = 0; + } #ifdef DEBUG std::cerr << "DEBUG INFO (Downloader::HTTP_Login)" << std::endl << root << std::endl; #endif - if (root["user"]["email"].asString() == email) - res = 1; // Login successful - else - res = 0; // Login failed + if (root["user"]["email"].asString() == email) + res = 1; // Login successful + else + res = 0; // Login failed - delete jsonparser; + delete jsonparser; - return res; + return res; } // Get list of games from account page @@ -1026,25 +1026,25 @@ std::vector Downloader::getGames() delete jsonparser; // Parse HTML to get game names - htmlcxx::HTML::ParserDom parser; - tree dom = parser.parseTree(html); - tree::iterator it = dom.begin(); - tree::iterator end = dom.end(); - for (; it != end; ++it) - { - if (it->tagName()=="div") - { - it->parseAttributes(); - std::string classname = it->attribute("class").second; - if (classname=="shelf_game") - { - // Game name is contained in data-gameindex attribute - std::string game = it->attribute("data-gameindex").second; - if (!game.empty()) + htmlcxx::HTML::ParserDom parser; + tree dom = parser.parseTree(html); + tree::iterator it = dom.begin(); + tree::iterator end = dom.end(); + for (; it != end; ++it) + { + if (it->tagName()=="div") + { + it->parseAttributes(); + std::string classname = it->attribute("class").second; + if (classname=="shelf_game") + { + // Game name is contained in data-gameindex attribute + std::string game = it->attribute("data-gameindex").second; + if (!game.empty()) games.push_back(game); - } - } - } + } + } + } return games; } @@ -1056,25 +1056,25 @@ std::vector Downloader::getFreeGames() std::string html = this->getResponse("https://secure.gog.com/catalogue/ajax?a=getGames&tab=all_genres&genre=all_genres&price=0&order=alph&publisher=&releaseDate=&availability=&gameMode=&rating=&search=&sort=vote&system=&language=&mixPage=1"); // Parse HTML to get game names - htmlcxx::HTML::ParserDom parser; - tree dom = parser.parseTree(html); - tree::iterator it = dom.begin(); - tree::iterator end = dom.end(); - for (; it != end; ++it) - { - if (it->tagName()=="a") - { - it->parseAttributes(); - std::string classname = it->attribute("class").second; - if (classname=="game-title-link") - { - std::string game = it->attribute("href").second; - game.assign(game.begin()+game.find_last_of("/")+1,game.end()); - if (!game.empty()) + htmlcxx::HTML::ParserDom parser; + tree dom = parser.parseTree(html); + tree::iterator it = dom.begin(); + tree::iterator end = dom.end(); + for (; it != end; ++it) + { + if (it->tagName()=="a") + { + it->parseAttributes(); + std::string classname = it->attribute("class").second; + if (classname=="game-title-link") + { + std::string game = it->attribute("href").second; + game.assign(game.begin()+game.find_last_of("/")+1,game.end()); + if (!game.empty()) games.push_back(game); - } - } - } + } + } + } return games; } diff --git a/src/util.cpp b/src/util.cpp index eb7a642..af9e8fa 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -47,134 +47,134 @@ std::string Util::makeFilepath(const std::string& directory, const std::string& std::string Util::getFileHash(const std::string& filename, unsigned hash_id) { - unsigned char digest[rhash_get_digest_size(hash_id)]; - char result[rhash_get_hash_length(hash_id)]; + unsigned char digest[rhash_get_digest_size(hash_id)]; + char result[rhash_get_hash_length(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; - else - rhash_print_bytes(result, digest, rhash_get_digest_size(hash_id), RHPR_HEX); + rhash_library_init(); + int i = rhash_file(hash_id, filename.c_str(), digest); + if (i < 0) + std::cout << "LibRHash error: " << strerror(errno) << std::endl; + else + rhash_print_bytes(result, digest, rhash_get_digest_size(hash_id), RHPR_HEX); - return result; + return result; } std::string Util::getChunkHash(unsigned char *chunk, size_t chunk_size, unsigned hash_id) { - unsigned char digest[rhash_get_digest_size(hash_id)]; - char result[rhash_get_hash_length(hash_id)]; + unsigned char digest[rhash_get_digest_size(hash_id)]; + char result[rhash_get_hash_length(hash_id)]; - rhash_library_init(); - int i = rhash_msg(hash_id, chunk, chunk_size, digest); - if (i < 0) - std::cout << "LibRHash error: " << strerror(errno) << std::endl; - else - rhash_print_bytes(result, digest, rhash_get_digest_size(hash_id), RHPR_HEX); + rhash_library_init(); + int i = rhash_msg(hash_id, chunk, chunk_size, digest); + if (i < 0) + std::cout << "LibRHash error: " << strerror(errno) << std::endl; + else + rhash_print_bytes(result, digest, rhash_get_digest_size(hash_id), RHPR_HEX); - return result; + return result; } // Create GOG XML int Util::createXML(std::string filepath, size_t chunk_size, std::string xml_dir) { int res = 0; - FILE *infile; - FILE *xmlfile; - size_t filesize, size; - int chunks, i; - std::string home = (std::string)getenv("HOME"); - if (xml_dir.empty()) + FILE *infile; + FILE *xmlfile; + size_t filesize, size; + int chunks, i; + std::string home = (std::string)getenv("HOME"); + if (xml_dir.empty()) xml_dir = home + "/.gogdownloader/xml"; - // Make sure directory exists - 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; - return res; - } - } + // Make sure directory exists + 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; + return res; + } + } - if ((infile=fopen(filepath.c_str(), "r"))!=NULL) { - //File exists - fseek(infile, 0, SEEK_END); - filesize = ftell(infile); - rewind(infile); - } else { - std::cout << filepath << " doesn't exist" << std::endl; - return res; - } + if ((infile=fopen(filepath.c_str(), "r"))!=NULL) { + //File exists + fseek(infile, 0, SEEK_END); + filesize = ftell(infile); + rewind(infile); + } else { + std::cout << filepath << " doesn't exist" << std::endl; + return res; + } // Get filename boost::filesystem::path pathname = filepath; std::string filename = pathname.filename().string(); - std::string filenameXML = xml_dir + "/" + filename + ".xml"; + std::string filenameXML = xml_dir + "/" + filename + ".xml"; - std::cout << filename << std::endl; - //Determine number of chunks - int remaining = filesize % chunk_size; - chunks = (remaining == 0) ? filesize/chunk_size : (filesize/chunk_size)+1; - std::cout << "Filesize: " << filesize << " bytes" << std::endl + std::cout << filename << std::endl; + //Determine number of chunks + int remaining = filesize % chunk_size; + chunks = (remaining == 0) ? filesize/chunk_size : (filesize/chunk_size)+1; + std::cout << "Filesize: " << filesize << " bytes" << std::endl << "Chunks: " << chunks << std::endl << "Chunk size: " << (chunk_size >> 20) << " MB" << std::endl << "MD5: " << std::flush; - std::string file_md5 = Util::getFileHash(filepath.c_str(), RHASH_MD5); - std::cout << file_md5 << std::endl; + std::string file_md5 = Util::getFileHash(filepath.c_str(), RHASH_MD5); + std::cout << file_md5 << std::endl; - TiXmlDocument xml; - TiXmlElement *fileElem = new TiXmlElement("file"); - fileElem->SetAttribute("name", filename); - fileElem->SetAttribute("md5", file_md5); - fileElem->SetAttribute("chunks", chunks); - fileElem->SetAttribute("total_size", filesize); + TiXmlDocument xml; + TiXmlElement *fileElem = new TiXmlElement("file"); + fileElem->SetAttribute("name", filename); + fileElem->SetAttribute("md5", file_md5); + fileElem->SetAttribute("chunks", chunks); + fileElem->SetAttribute("total_size", filesize); - std::cout << "Getting MD5 for chunks" << std::endl; - for (i = 0; i < chunks; i++) { - size_t range_begin = i*chunk_size; - fseek(infile, range_begin, SEEK_SET); - if ((i == chunks-1) && (remaining != 0)) - chunk_size = remaining; - size_t range_end = range_begin + chunk_size - 1; - unsigned char *chunk = (unsigned char *) malloc(chunk_size * sizeof(unsigned char *)); - if (chunk == NULL) - { - std::cout << "Memory error" << std::endl; - return res; - } - size = fread(chunk, 1, chunk_size, infile); - if (size != chunk_size) - { - std::cout << "Read error" << std::endl; - free(chunk); - return res; - } - std::string hash = Util::getChunkHash(chunk, chunk_size, RHASH_MD5); - free(chunk); + std::cout << "Getting MD5 for chunks" << std::endl; + for (i = 0; i < chunks; i++) { + size_t range_begin = i*chunk_size; + fseek(infile, range_begin, SEEK_SET); + if ((i == chunks-1) && (remaining != 0)) + chunk_size = remaining; + size_t range_end = range_begin + chunk_size - 1; + unsigned char *chunk = (unsigned char *) malloc(chunk_size * sizeof(unsigned char *)); + if (chunk == NULL) + { + std::cout << "Memory error" << std::endl; + return res; + } + size = fread(chunk, 1, chunk_size, infile); + if (size != chunk_size) + { + std::cout << "Read error" << std::endl; + free(chunk); + return res; + } + std::string hash = Util::getChunkHash(chunk, chunk_size, RHASH_MD5); + free(chunk); - TiXmlElement *chunkElem = new TiXmlElement("chunk"); - chunkElem->SetAttribute("id", i); - chunkElem->SetAttribute("from", range_begin); - chunkElem->SetAttribute("to", range_end); - chunkElem->SetAttribute("method", "md5"); - TiXmlText *text = new TiXmlText(hash); - chunkElem->LinkEndChild(text); - fileElem->LinkEndChild(chunkElem); + TiXmlElement *chunkElem = new TiXmlElement("chunk"); + chunkElem->SetAttribute("id", i); + chunkElem->SetAttribute("from", range_begin); + chunkElem->SetAttribute("to", range_end); + chunkElem->SetAttribute("method", "md5"); + TiXmlText *text = new TiXmlText(hash); + chunkElem->LinkEndChild(text); + fileElem->LinkEndChild(chunkElem); - std::cout << "Chunks hashed " << (i+1) << " / " << chunks << "\r" << std::flush; - } - fclose(infile); - xml.LinkEndChild(fileElem); + std::cout << "Chunks hashed " << (i+1) << " / " << chunks << "\r" << std::flush; + } + fclose(infile); + xml.LinkEndChild(fileElem); - std::cout << std::endl << "Writing XML: " << filenameXML << std::endl; - if ((xmlfile=fopen(filenameXML.c_str(), "w"))!=NULL) { - xml.Print(xmlfile); - fclose(xmlfile); - res = 1; - } else { - std::cout << "Can't create " << filenameXML << std::endl; - return res; - } + std::cout << std::endl << "Writing XML: " << filenameXML << std::endl; + if ((xmlfile=fopen(filenameXML.c_str(), "w"))!=NULL) { + xml.Print(xmlfile); + fclose(xmlfile); + res = 1; + } else { + std::cout << "Can't create " << filenameXML << std::endl; + return res; + } - return res; + return res; }