/* * Copyright (C) 2004-2012 Geometer Plus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include "OEBPlugin.h" #include "OEBMetaInfoReader.h" #include "OEBBookReader.h" #include "OEBCoverReader.h" #include "OEBTextStream.h" #include "../../bookmodel/BookModel.h" #include "../../library/Book.h" static const std::string OPF = "opf"; static const std::string OEBZIP = "oebzip"; static const std::string EPUB = "epub"; class ContainerFileReader : public ZLXMLReader { public: const std::string &rootPath() const; private: void startElementHandler(const char *tag, const char **attributes); private: std::string myRootPath; }; const std::string &ContainerFileReader::rootPath() const { return myRootPath; } void ContainerFileReader::startElementHandler(const char *tag, const char **attributes) { const std::string tagString = ZLUnicodeUtil::toLower(tag); if (tagString == "rootfile") { const char *path = attributeValue(attributes, "full-path"); if (path != 0) { myRootPath = path; interrupt(); } } } OEBPlugin::~OEBPlugin() { } bool OEBPlugin::providesMetaInfo() const { return true; } bool OEBPlugin::acceptsFile(const ZLFile &file) const { shared_ptr mimeType = file.mimeType(); const std::string &extension = file.extension(); if (!mimeType.isNull() && mimeType != ZLMimeType::EMPTY) { return mimeType == ZLMimeType::APPLICATION_EPUB_ZIP || (mimeType == ZLMimeType::APPLICATION_XML && extension == OPF) || (mimeType == ZLMimeType::APPLICATION_ZIP && extension == OEBZIP); } return extension == OPF || extension == OEBZIP || extension == EPUB; } ZLFile OEBPlugin::opfFile(const ZLFile &oebFile) { //ZLLogger::Instance().registerClass("epub"); if (oebFile.extension() == OPF) { return oebFile; } ZLLogger::Instance().println("epub", "Looking for opf file in " + oebFile.path()); shared_ptr oebDir = oebFile.directory(); if (!oebDir.isNull()) { const ZLFile containerInfoFile(oebDir->itemPath("META-INF/container.xml")); if (containerInfoFile.exists()) { ZLLogger::Instance().println("epub", "Found container file " + containerInfoFile.path()); ContainerFileReader reader; reader.readDocument(containerInfoFile); const std::string &opfPath = reader.rootPath(); ZLLogger::Instance().println("epub", "opf path = " + opfPath); if (!opfPath.empty()) { return ZLFile(oebDir->itemPath(opfPath)); } } } oebFile.forceArchiveType(ZLFile::ZIP); shared_ptr zipDir = oebFile.directory(false); if (zipDir.isNull()) { ZLLogger::Instance().println("epub", "Couldn't open zip archive"); return ZLFile::NO_FILE; } std::vector fileNames; zipDir->collectFiles(fileNames, false); for (std::vector::const_iterator it = fileNames.begin(); it != fileNames.end(); ++it) { ZLLogger::Instance().println("epub", "Item: " + *it); if (ZLStringUtil::stringEndsWith(*it, ".opf")) { return ZLFile(zipDir->itemPath(*it)); } } ZLLogger::Instance().println("epub", "Opf file not found"); return ZLFile::NO_FILE; } bool OEBPlugin::readMetaInfo(Book &book) const { const ZLFile &file = book.file(); return OEBMetaInfoReader(book).readMetaInfo(opfFile(file)); } bool OEBPlugin::readModel(BookModel &model) const { const ZLFile &file = model.book()->file(); return OEBBookReader(model).readBook(opfFile(file)); } shared_ptr OEBPlugin::coverImage(const ZLFile &file) const { return OEBCoverReader().readCover(opfFile(file)); } bool OEBPlugin::readLanguageAndEncoding(Book &book) const { if (book.language().empty()) { shared_ptr oebStream = new OEBTextStream(opfFile(book.file())); detectLanguage(book, *oebStream, book.encoding()); } return true; }