Container::Container(const std::string& path) : _archive(Archive::Open(path)) { if ( _archive == nullptr ) throw std::invalid_argument("Path does not point to a recognised archive file: '" + path + "'"); // TODO: Initialize lazily? Doing so would make initialization faster, but require // PackageLocations() to become non-const, like Packages(). ArchiveXmlReader reader(_archive->ReaderAtPath(gContainerFilePath)); _ocf = reader.xmlReadDocument(gContainerFilePath, nullptr, XML_PARSE_RECOVER|XML_PARSE_NOENT|XML_PARSE_DTDATTR); if ( _ocf == nullptr ) throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) + ": No container.xml in " + path); XPathWrangler xpath(_ocf, {{"ocf", "urn:oasis:names:tc:opendocument:xmlns:container"}}); xmlNodeSetPtr nodes = xpath.Nodes(reinterpret_cast<const xmlChar*>(gRootfilesXPath)); if ( nodes == nullptr || nodes->nodeNr == 0 ) throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) + ": No rootfiles in " + path); for ( int i = 0; i < nodes->nodeNr; i++ ) { xmlNodePtr n = nodes->nodeTab[i]; const xmlChar * _type = xmlGetProp(n, reinterpret_cast<const xmlChar*>("media-type")); std::string type((_type == nullptr ? "" : reinterpret_cast<const char*>(_type))); const xmlChar * _path = xmlGetProp(n, reinterpret_cast<const xmlChar*>("full-path")); if ( _path == nullptr ) continue; _packages.push_back(new Package(_archive, _path, type)); } LoadEncryption(); }
bool Container::Open(const string& path) { _archive = Archive::Open(path.stl_str()); if (_archive == nullptr) throw std::invalid_argument(_Str("Path does not point to a recognised archive file: '", path, "'")); _path = path; // TODO: Initialize lazily? Doing so would make initialization faster, but require // PackageLocations() to become non-const, like Packages(). ArchiveXmlReader reader(_archive->ReaderAtPath(gContainerFilePath)); if (!reader) { throw std::invalid_argument(_Str("Path does not point to a recognised archive file: '", path, "'")); } #if EPUB_USE(LIBXML2) _ocf = reader.xmlReadDocument(gContainerFilePath, nullptr, XML_PARSE_RECOVER|XML_PARSE_NOENT|XML_PARSE_DTDATTR); #else decltype(_ocf) __tmp(reader.ReadDocument(gContainerFilePath, nullptr, /*RESOLVE_EXTERNALS*/ 1)); _ocf = __tmp; #endif if (!((bool)_ocf)) return false; #if EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS) XPathWrangler xpath(_ocf, { { "ocf", "urn:oasis:names:tc:opendocument:xmlns:container" } }); #else XPathWrangler::NamespaceList __ns; __ns["ocf"] = OCFNamespaceURI; XPathWrangler xpath(_ocf, __ns); #endif xml::NodeSet nodes = xpath.Nodes(gRootfilesXPath); if (nodes.empty()) return false; LoadEncryption(); for (auto n : nodes) { string type = _getProp(n, "media-type"); string path = _getProp(n, "full-path"); if (path.empty()) continue; auto pkg = Package::New(Ptr(), type); if (pkg->Open(path)) _packages.push_back(pkg); } auto fm = FilterManager::Instance(); for (auto& pkg : _packages) { auto fc = fm->BuildFilterChainForPackage(pkg); pkg->SetFilterChain(fc); } return true; }
bool Container::Open(const string& path) { ContainerPtr sharedThis(shared_from_this()); _archive = std::move(Archive::Open(path.stl_str())); if ( _archive == nullptr ) throw std::invalid_argument(_Str("Path does not point to a recognised archive file: '", path, "'")); // TODO: Initialize lazily? Doing so would make initialization faster, but require // PackageLocations() to become non-const, like Packages(). ArchiveXmlReader reader(_archive->ReaderAtPath(gContainerFilePath)); _ocf = reader.xmlReadDocument(gContainerFilePath, nullptr, XML_PARSE_RECOVER|XML_PARSE_NOENT|XML_PARSE_DTDATTR); if ( _ocf == nullptr ) return false; #if EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS) XPathWrangler xpath(_ocf, {{"ocf", "urn:oasis:names:tc:opendocument:xmlns:container"}}); #else XPathWrangler::NamespaceList __ns; __ns["ocf"] = OCFNamespaceURI; XPathWrangler xpath(_ocf, __ns); #endif xmlNodeSetPtr nodes = xpath.Nodes(reinterpret_cast<const xmlChar*>(gRootfilesXPath)); if ( nodes == nullptr || nodes->nodeNr == 0 ) return false; for ( int i = 0; i < nodes->nodeNr; i++ ) { xmlNodePtr n = nodes->nodeTab[i]; const xmlChar * _type = xmlGetProp(n, reinterpret_cast<const xmlChar*>("media-type")); std::string type((_type == nullptr ? "" : reinterpret_cast<const char*>(_type))); const xmlChar * _path = xmlGetProp(n, reinterpret_cast<const xmlChar*>("full-path")); if ( _path == nullptr ) continue; auto pkg = std::make_shared<Package>(sharedThis, type); if ( pkg->Open(_path) ) _packages.push_back(pkg); } LoadEncryption(); return true; }