[fbreader] Read the path to the default OPF from container.xml

This commit is contained in:
Slava Monich 2015-08-21 14:41:34 +03:00
parent ba402d79ff
commit c9a7225138
3 changed files with 127 additions and 0 deletions

View file

@ -0,0 +1,62 @@
/*
* Copyright (C) 2015 Slava Monich <slava.monich@jolla.com>
*
* 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 "OCFContainerReader.h"
#include <string.h>
bool OCFContainerReader::readContainer(const ZLFile &file) {
myOpfFile = std::string();
myStateStack = std::stack<State>();
myStateStack.push(STATE_CONTAINER);
return readDocument(file);
}
void OCFContainerReader::startElementHandler(const char *tag, const char **attr) {
switch (myStateStack.top()) {
case STATE_CONTAINER:
myStateStack.push(strcmp(tag, "container") ? STATE_IGNORE : STATE_ROOTFILES);
break;
case STATE_ROOTFILES:
myStateStack.push(strcmp(tag, "rootfiles") ? STATE_IGNORE : STATE_ROOTFILE);
break;
case STATE_ROOTFILE:
// An OCF Processor must consider the first rootfile element
// within the rootfiles element to represent the Default
// Rendition for the contained EPUB Publication. Reading
// Systems are not required to use any Rendition except
// the default one.
if (myOpfFile.empty() && !strcmp(tag, "rootfile")) {
const char *mediaType = attributeValue(attr, "media-type");
if (mediaType && !strcmp(mediaType, "application/oebps-package+xml")) {
const char *fullPath = attributeValue(attr, "full-path");
if (fullPath) {
myOpfFile = fullPath;
}
}
}
/* no break */
default:
myStateStack.push(STATE_IGNORE);
break;
}
}
void OCFContainerReader::endElementHandler(const char *tag) {
myStateStack.pop();
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2015 Slava Monich <slava.monich@jolla.com>
*
* 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.
*/
#ifndef __OCFCONTANERREADER_H__
#define __OCFCONTANERREADER_H__
#include <ZLXMLReader.h>
#include <stack>
class OCFContainerReader : public ZLXMLReader {
public:
OCFContainerReader() {}
bool readContainer(const ZLFile &file);
const std::string &opfFile() const;
private:
void startElementHandler(const char *tag, const char **attr);
void endElementHandler(const char *tag);
private:
enum State {
STATE_CONTAINER,
STATE_ROOTFILES,
STATE_ROOTFILE,
STATE_IGNORE
};
std::stack<State> myStateStack;
std::string myOpfFile;
};
inline const std::string &OCFContainerReader::opfFile() const { return myOpfFile; }
#endif /* __OCFCONTANERREADER_H__ */

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 2004-2010 Geometer Plus <contact@geometerplus.com>
* Copyright (C) 2015 Slava Monich <slava.monich@jolla.com>
*
* 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
@ -25,6 +26,7 @@
#include <ZLLogger.h>
#include <ZLMimeType.h>
#include "OCFContainerReader.h"
#include "OEBPlugin.h"
#include "OEBMetaInfoReader.h"
#include "OEBBookReader.h"
@ -36,6 +38,7 @@
static const std::string OPF = "opf";
static const std::string OEBZIP = "oebzip";
static const std::string EPUB = "epub";
static const std::string CONTAINER_XML = "META-INF/container.xml";
OEBPlugin::~OEBPlugin() {
}
@ -68,6 +71,16 @@ ZLFile OEBPlugin::opfFile(const ZLFile &oebFile) {
ZLLogger::Instance().println("epub", "Couldn't open zip archive");
return ZLFile::NO_FILE;
}
OCFContainerReader ocfReader;
ZLFile containerXml(zipDir->itemPath(CONTAINER_XML));
if (ocfReader.readContainer(containerXml)) {
const std::string &opf = ocfReader.opfFile();
if (!opf.empty()) {
return ZLFile(zipDir->itemPath(opf));
}
}
std::vector<std::string> fileNames;
zipDir->collectFiles(fileNames, false);
for (std::vector<std::string>::const_iterator it = fileNames.begin(); it != fileNames.end(); ++it) {