diff options
Diffstat (limited to 'fbreader/src/formats/oeb/OEBPlugin.cpp')
-rw-r--r-- | fbreader/src/formats/oeb/OEBPlugin.cpp | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/fbreader/src/formats/oeb/OEBPlugin.cpp b/fbreader/src/formats/oeb/OEBPlugin.cpp new file mode 100644 index 0000000..96970c1 --- /dev/null +++ b/fbreader/src/formats/oeb/OEBPlugin.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2004-2012 Geometer Plus <[email protected]> + * + * 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 <ZLFile.h> +#include <ZLImage.h> +#include <ZLStringUtil.h> +#include <ZLUnicodeUtil.h> +#include <ZLDir.h> +#include <ZLInputStream.h> +#include <ZLLogger.h> +#include <ZLMimeType.h> + +#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<ZLMimeType> 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<ZLDir> 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<ZLDir> zipDir = oebFile.directory(false); + if (zipDir.isNull()) { + ZLLogger::Instance().println("epub", "Couldn't open zip archive"); + return ZLFile::NO_FILE; + } + std::vector<std::string> fileNames; + zipDir->collectFiles(fileNames, false); + for (std::vector<std::string>::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<const ZLImage> OEBPlugin::coverImage(const ZLFile &file) const { + return OEBCoverReader().readCover(opfFile(file)); +} + +bool OEBPlugin::readLanguageAndEncoding(Book &book) const { + if (book.language().empty()) { + shared_ptr<ZLInputStream> oebStream = new OEBTextStream(opfFile(book.file())); + detectLanguage(book, *oebStream, book.encoding()); + } + return true; +} |