/* */ #include "metalink_helper.h" #include #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" #include "a2functional.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); std::array buf; ssize_t nread; int64_t offread = 0; bool retval = true; while ((nread = bs->readData(buf.data(), buf.size(), offread)) > 0) { if (ps.parseUpdate(reinterpret_cast(buf.data()), 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