/* */ #include "metalink_helper.h" #include "Option.h" #include "MetalinkEntry.h" #include "MetalinkParserStateMachine.h" #include "Metalinker.h" #include "XmlParser.h" #include "prefs.h" #include "DlAbortEx.h" #include "BinaryStream.h" #include "MetalinkMetaurl.h" namespace aria2 { namespace metalink { namespace { std::vector> query(const std::shared_ptr& metalinker, const Option* option) { return metalinker->queryEntry(option->get(PREF_METALINK_VERSION), option->get(PREF_METALINK_LANGUAGE), option->get(PREF_METALINK_OS)); } } // namespace std::vector> parseAndQuery (const std::string& filename, const Option* option, const std::string& baseUri) { return query(parseFile(filename, baseUri), option); } std::vector> parseAndQuery (BinaryStream* bs, const Option* option, const std::string& baseUri) { return query(parseBinaryStream(bs, baseUri), option); } std::vector>> groupEntryByMetaurlName (const std::vector>& entries) { std::vector>> result; for(auto& entry : entries) { if(entry->metaurls.empty()) { // std::pair> p; // p.second.push_back(entry.get()); result.push_back({"", {entry.get()}}); } else { auto i = std::begin(result); if(entry->metaurls[0]->name.empty() || !entry->sizeKnown) { i = std::end(result); } for(; i != std::end(result); ++i) { if((*i).first == entry->metaurls[0]->url && !(*i).second[0]->metaurls[0]->name.empty()) { (*i).second.push_back(entry.get()); break; } } if(i == std::end(result)) { result.push_back({entry->metaurls[0]->url, {entry.get()}}); } } } return result; } std::unique_ptr parseFile (const std::string& filename, const std::string& baseUri) { MetalinkParserStateMachine psm; psm.setBaseUri(baseUri); if(!xml::parseFile(filename, &psm)) { throw DL_ABORT_EX2("Could not parse Metalink XML document.", error_code::METALINK_PARSE_ERROR); } if(!psm.getErrors().empty()) { throw DL_ABORT_EX2(psm.getErrorString(), error_code::METALINK_PARSE_ERROR); } return psm.getResult(); } std::unique_ptr parseBinaryStream (BinaryStream* bs, const std::string& baseUri) { MetalinkParserStateMachine psm; psm.setBaseUri(baseUri); xml::XmlParser ps(&psm); unsigned char buf[4096]; ssize_t nread; int64_t offread = 0; bool retval = true; while((nread = bs->readData(buf, sizeof(buf), offread)) > 0) { if(ps.parseUpdate(reinterpret_cast(buf), nread) < 0) { retval = false; break; } offread += nread; } if(nread == 0 && retval) { if(ps.parseFinal(nullptr, 0) < 0) { retval = false; } } if(!retval) { throw DL_ABORT_EX2("Could not parse Metalink XML document.", error_code::METALINK_PARSE_ERROR); } if(!psm.getErrors().empty()) { throw DL_ABORT_EX2(psm.getErrorString(), error_code::METALINK_PARSE_ERROR); } return psm.getResult(); } } // namespace metalink } // namespace aria2