Make the member of the book protected.

It is up to the book to manage its attribute.

Also remove the `absolutePath` (and `indexAbsolutePath`). The `Book::path` is always stored
absolute.
The fact that the path can be stored absolute or relative in the
`library.xml` is not relevant for the book.
This commit is contained in:
Matthieu Gautier 2018-09-03 15:35:22 +02:00
parent 57ac6f0305
commit bba3c252e4
4 changed files with 248 additions and 236 deletions

View File

@ -58,29 +58,72 @@ class Book
static bool sortByLanguage(const Book& a, const Book& b);
string getHumanReadableIdFromPath();
string id;
string path;
string pathAbsolute;
string last;
string indexPath;
string indexPathAbsolute;
supportedIndexType indexType;
string title;
string description;
string language;
string creator;
string publisher;
string date;
string url;
string name;
string tags;
string origId;
string articleCount;
string mediaCount;
bool readOnly;
string size;
string favicon;
string faviconMimeType;
bool readOnly() const { return m_readOnly; }
const string& id() const { return m_id; }
const string& path() const { return m_path; }
const string& last() const { return m_last; }
const string& indexPath() const { return m_indexPath; }
const supportedIndexType& indexType() const { return m_indexType; }
const string& title() const { return m_title; }
const string& description() const { return m_description; }
const string& language() const { return m_language; }
const string& creator() const { return m_creator; }
const string& publisher() const { return m_publisher; }
const string& date() const { return m_date; }
const string& url() const { return m_url; }
const string& name() const { return m_name; }
const string& tags() const { return m_tags; }
const string& origId() const { return m_origId; }
const uint64_t& articleCount() const { return m_articleCount; }
const uint64_t& mediaCount() const { return m_mediaCount; }
const uint64_t& size() const { return m_size; }
const string& favicon() const { return m_favicon; }
const string& faviconMimeType() const { return m_faviconMimeType; }
void setReadOnly(bool readOnly) { m_readOnly = readOnly; }
void setId(const std::string& id) { m_id = id; }
void setPath(const std::string& path);
void setLast(const std::string& last) { m_last = last; }
void setIndexPath(const std::string& indexPath);
void setIndexType(supportedIndexType indexType) { m_indexType = indexType;}
void setTitle(const std::string& title) { m_title = title; }
void setDescription(const std::string& description) { m_description = description; }
void setLanguage(const std::string& language) { m_language = language; }
void setCreator(const std::string& creator) { m_creator = creator; }
void setPublisher(const std::string& publisher) { m_publisher = publisher; }
void setDate(const std::string& date) { m_date = date; }
void setUrl(const std::string& url) { m_url = url; }
void setName(const std::string& name) { m_name = name; }
void setTags(const std::string& tags) { m_tags = tags; }
void setOrigId(const std::string& origId) { m_origId = origId; }
void setArticleCount(uint64_t articleCount) { m_articleCount = articleCount; }
void setMediaCount(uint64_t mediaCount) { m_mediaCount = mediaCount; }
void setSize(uint64_t size) { m_size = size; }
void setFavicon(const std::string& favicon) { m_favicon = favicon; }
void setFaviconMimeType(const std::string& faviconMimeType) { m_faviconMimeType = faviconMimeType; }
protected:
string m_id;
string m_path;
string m_last;
string m_indexPath;
supportedIndexType m_indexType;
string m_title;
string m_description;
string m_language;
string m_creator;
string m_publisher;
string m_date;
string m_url;
string m_name;
string m_tags;
string m_origId;
uint64_t m_articleCount;
uint64_t m_mediaCount;
bool m_readOnly;
uint64_t m_size;
string m_favicon;
string m_faviconMimeType;
};
/**

View File

@ -24,7 +24,7 @@
namespace kiwix
{
/* Constructor */
Book::Book() : readOnly(false)
Book::Book() : m_readOnly(false)
{
}
/* Destructor */
@ -36,84 +36,74 @@ bool Book::sortByLastOpen(const kiwix::Book& a, const kiwix::Book& b)
{
return atoi(a.last.c_str()) > atoi(b.last.c_str());
}
bool Book::sortByTitle(const kiwix::Book& a, const kiwix::Book& b)
{
return strcmp(a.title.c_str(), b.title.c_str()) < 0;
return a.m_title < b.m_title;
}
bool Book::sortByDate(const kiwix::Book& a, const kiwix::Book& b)
{
return strcmp(a.date.c_str(), b.date.c_str()) > 0;
return a.m_date < b.m_date;
}
bool Book::sortBySize(const kiwix::Book& a, const kiwix::Book& b)
{
return atoi(a.size.c_str()) < atoi(b.size.c_str());
return a.m_size < b.m_size;
}
bool Book::sortByPublisher(const kiwix::Book& a, const kiwix::Book& b)
{
return strcmp(a.publisher.c_str(), b.publisher.c_str()) < 0;
return a.m_publisher < b.m_publisher;
}
bool Book::sortByCreator(const kiwix::Book& a, const kiwix::Book& b)
{
return strcmp(a.creator.c_str(), b.creator.c_str()) < 0;
return a.m_creator < b.m_creator;
}
bool Book::sortByLanguage(const kiwix::Book& a, const kiwix::Book& b)
{
return strcmp(a.language.c_str(), b.language.c_str()) < 0;
return a.m_language < b.m_language;
}
bool Book::update(const kiwix::Book& other)
{
if (readOnly)
if (m_readOnly)
return false;
readOnly = other.readOnly;
m_readOnly = other.m_readOnly;
if (path.empty()) {
path = other.path;
if (m_path.empty()) {
m_path = other.m_path;
}
if (pathAbsolute.empty()) {
pathAbsolute = other.pathAbsolute;
if (m_url.empty()) {
m_url = other.m_url;
}
if (url.empty()) {
url = other.url;
if (m_tags.empty()) {
m_tags = other.m_tags;
}
if (tags.empty()) {
tags = other.tags;
if (m_name.empty()) {
m_name = other.m_name;
}
if (name.empty()) {
name = other.name;
if (m_indexPath.empty()) {
m_indexPath = other.m_indexPath;
m_indexType = other.m_indexType;
}
if (indexPath.empty()) {
indexPath = other.indexPath;
indexType = other.indexType;
}
if (indexPathAbsolute.empty()) {
indexPathAbsolute = other.indexPathAbsolute;
indexType = other.indexType;
}
if (faviconMimeType.empty()) {
favicon = other.favicon;
faviconMimeType = other.faviconMimeType;
if (m_faviconMimeType.empty()) {
m_favicon = other.m_favicon;
m_faviconMimeType = other.m_faviconMimeType;
}
return true;
}
std::string Book::getHumanReadableIdFromPath()
{
std::string id = pathAbsolute;
std::string id = m_path;
if (!id.empty()) {
kiwix::removeAccents(id);
@ -130,6 +120,20 @@ std::string Book::getHumanReadableIdFromPath()
return id;
}
void Book::setPath(const std::string& path)
{
m_path = isRelativePath(path)
? computeAbsolutePath(getCurrentDirectory(), path)
: path;
}
void Book::setIndexPath(const std::string& indexPath)
{
m_indexPath = isRelativePath(indexPath)
? computeAbsolutePath(getCurrentDirectory(), indexPath)
: indexPath;
}
/* Constructor */
Library::Library() : version(KIWIX_LIBRARY_VERSION)
{
@ -145,11 +149,11 @@ bool Library::addBook(const Book& book)
/* Try to find it */
std::vector<kiwix::Book>::iterator itr;
try {
auto& oldbook = books.at(book.id);
auto& oldbook = books.at(book.id());
oldbook.update(book);
return false;
} catch (std::out_of_range&) {
books[book.id] = book;
books[book.id()] = book;
return true;
}
}
@ -171,8 +175,8 @@ unsigned int Library::getBookCount(const bool localBooks,
unsigned int result = 0;
for (auto& pair: books) {
auto& book = pair.second;
if ((!book.path.empty() && localBooks)
|| (book.path.empty() && remoteBooks)) {
if ((!book.path().empty() && localBooks)
|| (book.path().empty() && remoteBooks)) {
result++;
}
}
@ -188,8 +192,8 @@ Library Library::filter(const std::string& search) {
for(auto& pair:books) {
auto& book = pair.second;
if (matchRegex(book.title, "\\Q" + search + "\\E")
|| matchRegex(book.description, "\\Q" + search + "\\E")) {
if (matchRegex(book.title(), "\\Q" + search + "\\E")
|| matchRegex(book.description(), "\\Q" + search + "\\E")) {
library.addBook(book);
}
}
@ -209,76 +213,69 @@ bool Library::writeToFile(const std::string& path) {
/* Add each book */
for (auto& pair: books) {
auto& book = pair.second;
if (!book.readOnly) {
if (!book.readOnly()) {
pugi::xml_node bookNode = libraryNode.append_child("book");
bookNode.append_attribute("id") = book.id.c_str();
bookNode.append_attribute("id") = book.id().c_str();
if (!book.path.empty()) {
bookNode.append_attribute("path") = book.path.c_str();
if (!book.path().empty()) {
bookNode.append_attribute("path") = computeRelativePath(
removeLastPathElement(path, true, false), book.path()).c_str();
}
if (!book.last.empty() && book.last != "undefined") {
bookNode.append_attribute("last") = book.last.c_str();
if (!book.indexPath().empty()) {
bookNode.append_attribute("indexPath") = computeRelativePath(
removeLastPathElement(path, true, false), book.indexPath()).c_str();
bookNode.append_attribute("indexType") = "xapian";
}
if (!book.indexPath.empty())
bookNode.append_attribute("indexPath") = book.indexPath.c_str();
if (book.origId().empty()) {
if (!book.title().empty())
bookNode.append_attribute("title") = book.title().c_str();
if (!book.indexPath.empty() || !book.indexPathAbsolute.empty()) {
if (book.indexType == XAPIAN) {
bookNode.append_attribute("indexType") = "xapian";
}
}
if (!book.name().empty())
bookNode.append_attribute("name") = book.name().c_str();
if (book.origId.empty()) {
if (!book.title.empty())
bookNode.append_attribute("title") = book.title.c_str();
if (!book.tags().empty())
bookNode.append_attribute("tags") = book.tags().c_str();
if (!book.name.empty())
bookNode.append_attribute("name") = book.name.c_str();
if (!book.description().empty())
bookNode.append_attribute("description") = book.description().c_str();
if (!book.tags.empty())
bookNode.append_attribute("tags") = book.tags.c_str();
if (!book.language().empty())
bookNode.append_attribute("language") = book.language().c_str();
if (!book.description.empty())
bookNode.append_attribute("description") = book.description.c_str();
if (!book.creator().empty())
bookNode.append_attribute("creator") = book.creator().c_str();
if (!book.language.empty())
bookNode.append_attribute("language") = book.language.c_str();
if (!book.publisher().empty())
bookNode.append_attribute("publisher") = book.publisher().c_str();
if (!book.creator.empty())
bookNode.append_attribute("creator") = book.creator.c_str();
if (!book.favicon().empty())
bookNode.append_attribute("favicon") = book.favicon().c_str();
if (!book.publisher.empty())
bookNode.append_attribute("publisher") = book.publisher.c_str();
if (!book.favicon.empty())
bookNode.append_attribute("favicon") = book.favicon.c_str();
if (!book.faviconMimeType.empty())
if (!book.faviconMimeType().empty())
bookNode.append_attribute("faviconMimeType")
= book.faviconMimeType.c_str();
= book.faviconMimeType().c_str();
} else {
bookNode.append_attribute("origId") = book.origId().c_str();
}
if (!book.date.empty()) {
bookNode.append_attribute("date") = book.date.c_str();
if (!book.date().empty()) {
bookNode.append_attribute("date") = book.date().c_str();
}
if (!book.url.empty()) {
bookNode.append_attribute("url") = book.url.c_str();
if (!book.url().empty()) {
bookNode.append_attribute("url") = book.url().c_str();
}
if (!book.origId.empty())
bookNode.append_attribute("origId") = book.origId.c_str();
if (!book.articleCount())
bookNode.append_attribute("articleCount") = to_string(book.articleCount()).c_str();
if (!book.articleCount.empty())
bookNode.append_attribute("articleCount") = book.articleCount.c_str();
if (!book.mediaCount())
bookNode.append_attribute("mediaCount") = to_string(book.mediaCount()).c_str();
if (!book.mediaCount.empty())
bookNode.append_attribute("mediaCount") = book.mediaCount.c_str();
if (!book.size.empty()) {
bookNode.append_attribute("size") = book.size.c_str();
if (!book.size()) {
bookNode.append_attribute("size") = to_string(book.size()).c_str();
}
}
}
@ -294,12 +291,13 @@ std::vector<std::string> Library::getBooksLanguages()
for (auto& pair: books) {
auto& book = pair.second;
if (booksLanguagesMap.find(book.language) == booksLanguagesMap.end()) {
if (book.origId.empty()) {
booksLanguagesMap[book.language] = true;
booksLanguages.push_back(book.language);
}
}
auto& language = book.language();
if (booksLanguagesMap.find(language) == booksLanguagesMap.end()) {
if (book.origId().empty()) {
booksLanguagesMap[language] = true;
booksLanguages.push_back(language);
}
}
}
return booksLanguages;
@ -312,10 +310,11 @@ std::vector<std::string> Library::getBooksCreators()
for (auto& pair: books) {
auto& book = pair.second;
if (booksCreatorsMap.find(book.creator) == booksCreatorsMap.end()) {
if (book.origId.empty()) {
booksCreatorsMap[book.creator] = true;
booksCreators.push_back(book.creator);
auto& creator = book.creator();
if (booksCreatorsMap.find(creator) == booksCreatorsMap.end()) {
if (book.origId().empty()) {
booksCreatorsMap[creator] = true;
booksCreators.push_back(creator);
}
}
}
@ -341,10 +340,11 @@ std::vector<std::string> Library::getBooksPublishers()
for (auto& pair:books) {
auto& book = pair.second;
if (booksPublishersMap.find(book.publisher) == booksPublishersMap.end()) {
if (book.origId.empty()) {
booksPublishersMap[book.publisher] = true;
booksPublishers.push_back(book.publisher);
auto& publisher = book.publisher();
if (booksPublishersMap.find(publisher) == booksPublishersMap.end()) {
if (book.origId().empty()) {
booksPublishersMap[publisher] = true;
booksPublishers.push_back(publisher);
}
}
}

View File

@ -43,38 +43,46 @@ bool Manager::parseXmlDom(const pugi::xml_document& doc,
bool ok = true;
kiwix::Book book;
book.readOnly = readOnly;
book.id = bookNode.attribute("id").value();
book.path = bookNode.attribute("path").value();
book.last = (std::string(bookNode.attribute("last").value()) != "undefined"
book.setReadOnly(readOnly);
book.setId(bookNode.attribute("id").value());
std::string path = bookNode.attribute("path").value();
if (isRelativePath(path)) {
path = computeAbsolutePath(
removeLastPathElement(libraryPath, true, false), path);
}
book.setPath(path);
book.setLast(std::string(bookNode.attribute("last").value()) != "undefined"
? bookNode.attribute("last").value()
: "");
book.indexPath = bookNode.attribute("indexPath").value();
book.indexType = XAPIAN;
book.title = bookNode.attribute("title").value();
book.name = bookNode.attribute("name").value();
book.tags = bookNode.attribute("tags").value();
book.description = bookNode.attribute("description").value();
book.language = bookNode.attribute("language").value();
book.date = bookNode.attribute("date").value();
book.creator = bookNode.attribute("creator").value();
book.publisher = bookNode.attribute("publisher").value();
book.url = bookNode.attribute("url").value();
book.origId = bookNode.attribute("origId").value();
book.articleCount = bookNode.attribute("articleCount").value();
book.mediaCount = bookNode.attribute("mediaCount").value();
book.size = bookNode.attribute("size").value();
book.favicon = bookNode.attribute("favicon").value();
book.faviconMimeType = bookNode.attribute("faviconMimeType").value();
/* Check absolute and relative paths */
this->checkAndCleanBookPaths(book, libraryPath);
std::string indexPath = bookNode.attribute("indexPath").value();
if (isRelativePath(indexPath)) {
indexPath = computeAbsolutePath(
removeLastPathElement(libraryPath, true, false), indexPath);
}
book.setIndexPath(indexPath);
book.setIndexType(XAPIAN);
book.setTitle(bookNode.attribute("title").value());
book.setName(bookNode.attribute("name").value());
book.setTags(bookNode.attribute("tags").value());
book.setDescription(bookNode.attribute("description").value());
book.setLanguage(bookNode.attribute("language").value());
book.setDate(bookNode.attribute("date").value());
book.setCreator(bookNode.attribute("creator").value());
book.setPublisher(bookNode.attribute("publisher").value());
book.setUrl(bookNode.attribute("url").value());
book.setOrigId(bookNode.attribute("origId").value());
book.setArticleCount(strtoull(bookNode.attribute("articleCount").value(), 0, 0));
book.setMediaCount(strtoull(bookNode.attribute("mediaCount").value(), 0, 0));
book.setSize(strtoull(bookNode.attribute("size").value(), 0, 0));
book.setFavicon(bookNode.attribute("favicon").value());
book.setFaviconMimeType(bookNode.attribute("faviconMimeType").value());
/* Update the book properties with the new importer */
if (libraryVersion.empty()
|| atoi(libraryVersion.c_str()) <= atoi(KIWIX_LIBRARY_VERSION)) {
if (!book.path.empty()) {
ok = this->readBookFromPath(book.pathAbsolute);
ok = false;
if (!book.path().empty()) {
ok = this->readBookFromPath(book.path());
}
}
@ -111,13 +119,13 @@ bool Manager::parseOpdsDom(const pugi::xml_document& doc, const std::string& url
entryNode = entryNode.next_sibling("entry")) {
kiwix::Book book;
book.readOnly = false;
book.id = entryNode.child("id").child_value();
book.title = entryNode.child("title").child_value();
book.description = entryNode.child("summary").child_value();
book.language = entryNode.child("language").child_value();
book.date = entryNode.child("updated").child_value();
book.creator = entryNode.child("author").child("name").child_value();
book.setReadOnly(false);
book.setId(entryNode.child("id").child_value());
book.setTitle(entryNode.child("title").child_value());
book.setDescription(entryNode.child("summary").child_value());
book.setLanguage(entryNode.child("language").child_value());
book.setDate(entryNode.child("updated").child_value());
book.setCreator(entryNode.child("author").child("name").child_value());
for(pugi::xml_node linkNode = entryNode.child("link"); linkNode;
linkNode = linkNode.next_sibling("link")) {
std::string rel = linkNode.attribute("rel").value();
@ -128,14 +136,14 @@ bool Manager::parseOpdsDom(const pugi::xml_document& doc, const std::string& url
auto fileHandle = downloader.download(faviconUrl);
if (fileHandle.success) {
auto content = getFileContent(fileHandle.path);
book.favicon = base64_encode((const unsigned char*)content.data(), content.size());
book.faviconMimeType = linkNode.attribute("type").value();
book.setFavicon(base64_encode((const unsigned char*)content.data(), content.size()));
book.setFaviconMimeType(linkNode.attribute("type").value());
} else {
std::cerr << "Cannot get favicon content from " << faviconUrl << std::endl;
}
} else if (rel == "http://opds-spec.org/acquisition/open-access") {
book.url = linkNode.attribute("href").value();
book.setUrl(linkNode.attribute("href").value());
}
}
@ -203,21 +211,19 @@ string Manager::addBookFromPathAndGetId(const string pathToOpen,
if (this->readBookFromPath(pathToOpen, &book)) {
if (pathToSave != pathToOpen) {
book.path = pathToSave;
book.pathAbsolute
= isRelativePath(pathToSave)
book.setPath(isRelativePath(pathToSave)
? computeAbsolutePath(
removeLastPathElement(writableLibraryPath, true, false),
pathToSave)
: pathToSave;
: pathToSave);
}
if (!checkMetaData
|| (checkMetaData && !book.title.empty() && !book.language.empty()
&& !book.date.empty())) {
book.url = url;
library.addBook(book);
return book.id;
|| (checkMetaData && !book.title().empty() && !book.language().empty()
&& !book.date().empty())) {
book.setUrl(url);
library->addBook(book);
return book.id();
}
}
@ -242,37 +248,28 @@ bool Manager::readBookFromPath(const string path, kiwix::Book* book)
kiwix::Reader* reader = new kiwix::Reader(path);
if (book != NULL) {
book->path = path;
book->pathAbsolute = path;
book->id = reader->getId();
book->description = reader->getDescription();
book->language = reader->getLanguage();
book->date = reader->getDate();
book->creator = reader->getCreator();
book->publisher = reader->getPublisher();
book->title = reader->getTitle();
book->name = reader->getName();
book->tags = reader->getTags();
book->origId = reader->getOrigId();
std::ostringstream articleCountStream;
articleCountStream << reader->getArticleCount();
book->articleCount = articleCountStream.str();
std::ostringstream mediaCountStream;
mediaCountStream << reader->getMediaCount();
book->mediaCount = mediaCountStream.str();
ostringstream convert;
convert << reader->getFileSize();
book->size = convert.str();
book->setPath(path);
book->setId(reader->getId());
book->setDescription(reader->getDescription());
book->setLanguage(reader->getLanguage());
book->setDate(reader->getDate());
book->setCreator(reader->getCreator());
book->setPublisher(reader->getPublisher());
book->setTitle(reader->getTitle());
book->setName(reader->getName());
book->setTags(reader->getTags());
book->setOrigId(reader->getOrigId());
book->setArticleCount(reader->getArticleCount());
book->setMediaCount(reader->getMediaCount());
book->setSize(reader->getFileSize());
string favicon;
string faviconMimeType;
if (reader->getFavicon(favicon, faviconMimeType)) {
book->favicon = base64_encode(
book->setFavicon(base64_encode(
reinterpret_cast<const unsigned char*>(favicon.c_str()),
favicon.length());
book->faviconMimeType = faviconMimeType;
favicon.length()));
book->setFaviconMimeType(faviconMimeType);
}
}
@ -306,13 +303,12 @@ bool Manager::setBookIndex(const string id,
const supportedIndexType type)
try {
auto book = library.getBookById(id);
book.indexPath = path;
book.indexPathAbsolute = isRelativePath(path)
book.setIndexPath(isRelativePath(path)
? computeAbsolutePath(
removeLastPathElement(writableLibraryPath, true, false),
path)
: path;
book.indexType = type;
: path);
book.setIndexType(type);
return true;
} catch (...) {
return false;
@ -321,41 +317,14 @@ try {
bool Manager::setBookPath(const string id, const string path)
try {
auto book = library.getBookById(id);
book.path = path;
book.pathAbsolute = isRelativePath(path)
book.setPath(isRelativePath(path)
? computeAbsolutePath(
removeLastPathElement(writableLibraryPath, true, false),
path)
: path;
: path);
return true;
} catch(...) {
return false;
}
void Manager::checkAndCleanBookPaths(Book& book, const string& libraryPath)
{
if (!book.path.empty()) {
if (isRelativePath(book.path)) {
book.pathAbsolute = computeAbsolutePath(
removeLastPathElement(libraryPath, true, false), book.path);
} else {
book.pathAbsolute = book.path;
book.path = computeRelativePath(
removeLastPathElement(libraryPath, true, false), book.pathAbsolute);
}
}
if (!book.indexPath.empty()) {
if (isRelativePath(book.indexPath)) {
book.indexPathAbsolute = computeAbsolutePath(
removeLastPathElement(libraryPath, true, false), book.indexPath);
} else {
book.indexPathAbsolute = book.indexPath;
book.indexPath
= computeRelativePath(removeLastPathElement(libraryPath, true, false),
book.indexPathAbsolute);
}
}
}
}

View File

@ -54,30 +54,30 @@ std::string gen_date_str()
pugi::xml_node OPDSDumper::handleBook(Book book, pugi::xml_node root_node) {
auto entry_node = root_node.append_child("entry");
ADD_TEXT_ENTRY(entry_node, "title", book.title);
ADD_TEXT_ENTRY(entry_node, "id", "urn:uuid:"+book.id);
ADD_TEXT_ENTRY(entry_node, "title", book.title());
ADD_TEXT_ENTRY(entry_node, "id", "urn:uuid:"+book.id());
ADD_TEXT_ENTRY(entry_node, "icon", rootLocation + "/meta?name=favicon&content=" + book.getHumanReadableIdFromPath());
ADD_TEXT_ENTRY(entry_node, "updated", date);
ADD_TEXT_ENTRY(entry_node, "summary", book.description);
ADD_TEXT_ENTRY(entry_node, "summary", book.description());
auto content_node = entry_node.append_child("link");
content_node.append_attribute("type") = "text/html";
content_node.append_attribute("href") = (rootLocation + "/" + book.getHumanReadableIdFromPath()).c_str();
auto author_node = entry_node.append_child("author");
ADD_TEXT_ENTRY(author_node, "name", book.creator);
ADD_TEXT_ENTRY(author_node, "name", book.creator());
if (! book.url.empty()) {
if (! book.url().empty()) {
auto acquisition_link = entry_node.append_child("link");
acquisition_link.append_attribute("rel") = "http://opds-spec.org/acquisition/open-access";
acquisition_link.append_attribute("type") = "application/x-zim";
acquisition_link.append_attribute("href") = book.url.c_str();
acquisition_link.append_attribute("href") = book.url().c_str();
}
if (! book.faviconMimeType.empty() ) {
if (! book.faviconMimeType().empty() ) {
auto image_link = entry_node.append_child("link");
image_link.append_attribute("rel") = "http://opds-spec.org/image/thumbnail";
image_link.append_attribute("type") = book.faviconMimeType.c_str();
image_link.append_attribute("type") = book.faviconMimeType().c_str();
image_link.append_attribute("href") = (rootLocation + "/meta?name=favicon&content=" + book.getHumanReadableIdFromPath()).c_str();
}
return entry_node;