mirror of https://github.com/kiwix/libkiwix.git
commit
6777bfeecf
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Matthieu Gautier <mgautier@kymeria.fr>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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 KIWIX_BOOKMARK_H
|
||||||
|
#define KIWIX_BOOKMARK_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace pugi {
|
||||||
|
class xml_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace kiwix
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to store information about a bookmark (an article in a book)
|
||||||
|
*/
|
||||||
|
class Bookmark
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Bookmark();
|
||||||
|
~Bookmark();
|
||||||
|
|
||||||
|
void updateFromXml(const pugi::xml_node& node);
|
||||||
|
|
||||||
|
const std::string& getBookId() const { return m_bookId; }
|
||||||
|
const std::string& getBookTitle() const { return m_bookTitle; }
|
||||||
|
const std::string& getUrl() const { return m_url; }
|
||||||
|
const std::string& getTitle() const { return m_title; }
|
||||||
|
const std::string& getLanguage() const { return m_language; }
|
||||||
|
const std::string& getDate() const { return m_date; }
|
||||||
|
|
||||||
|
void setBookId(const std::string& bookId) { m_bookId = bookId; }
|
||||||
|
void setBookTitle(const std::string& bookTitle) { m_bookTitle = bookTitle; }
|
||||||
|
void setUrl(const std::string& url) { m_url = url; }
|
||||||
|
void setTitle(const std::string& title) { m_title = title; }
|
||||||
|
void setLanguage(const std::string& language) { m_language = language; }
|
||||||
|
void setDate(const std::string& date) { m_date = date; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string m_bookId;
|
||||||
|
std::string m_bookTitle;
|
||||||
|
std::string m_url;
|
||||||
|
std::string m_title;
|
||||||
|
std::string m_language;
|
||||||
|
std::string m_date;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -24,12 +24,14 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "book.h"
|
||||||
|
#include "bookmark.h"
|
||||||
|
|
||||||
#define KIWIX_LIBRARY_VERSION "20110515"
|
#define KIWIX_LIBRARY_VERSION "20110515"
|
||||||
|
|
||||||
namespace kiwix
|
namespace kiwix
|
||||||
{
|
{
|
||||||
|
|
||||||
class Book;
|
|
||||||
class OPDSDumper;
|
class OPDSDumper;
|
||||||
|
|
||||||
enum supportedListSortBy { UNSORTED, TITLE, SIZE, DATE, CREATOR, PUBLISHER };
|
enum supportedListSortBy { UNSORTED, TITLE, SIZE, DATE, CREATOR, PUBLISHER };
|
||||||
|
@ -47,12 +49,13 @@ enum supportedListMode {
|
||||||
*/
|
*/
|
||||||
class Library
|
class Library
|
||||||
{
|
{
|
||||||
std::map<std::string, kiwix::Book> books;
|
std::map<std::string, kiwix::Book> m_books;
|
||||||
|
std::vector<kiwix::Bookmark> m_bookmarks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Library();
|
Library();
|
||||||
~Library();
|
~Library();
|
||||||
|
|
||||||
std::string version;
|
|
||||||
/**
|
/**
|
||||||
* Add a book to the library.
|
* Add a book to the library.
|
||||||
*
|
*
|
||||||
|
@ -65,6 +68,22 @@ class Library
|
||||||
*/
|
*/
|
||||||
bool addBook(const Book& book);
|
bool addBook(const Book& book);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a bookmark to the library.
|
||||||
|
*
|
||||||
|
* @param bookmark the book to add.
|
||||||
|
*/
|
||||||
|
void addBookmark(const Bookmark& bookmark);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a bookmarkk
|
||||||
|
*
|
||||||
|
* @param zimId The zimId of the bookmark.
|
||||||
|
* @param url The url of the bookmark.
|
||||||
|
* @return True if the bookmark has been removed.
|
||||||
|
*/
|
||||||
|
bool removeBookmark(const std::string& zimId, const std::string& url);
|
||||||
|
|
||||||
Book& getBookById(const std::string& id);
|
Book& getBookById(const std::string& id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,10 +98,18 @@ class Library
|
||||||
* Write the library to a file.
|
* Write the library to a file.
|
||||||
*
|
*
|
||||||
* @param path the path of the file to write to.
|
* @param path the path of the file to write to.
|
||||||
* @return True if the library has been correctly save.
|
* @return True if the library has been correctly saved.
|
||||||
*/
|
*/
|
||||||
bool writeToFile(const std::string& path);
|
bool writeToFile(const std::string& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the library bookmarks to a file.
|
||||||
|
*
|
||||||
|
* @param path the path of the file to write to.
|
||||||
|
* @return True if the library has been correctly saved.
|
||||||
|
*/
|
||||||
|
bool writeBookmarksToFile(const std::string& path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of book in the library.
|
* Get the number of book in the library.
|
||||||
*
|
*
|
||||||
|
@ -113,6 +140,13 @@ class Library
|
||||||
*/
|
*/
|
||||||
std::vector<std::string> getBooksPublishers();
|
std::vector<std::string> getBooksPublishers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all bookmarks.
|
||||||
|
*
|
||||||
|
* @return A list of bookmarks
|
||||||
|
*/
|
||||||
|
const std::vector<kiwix::Bookmark>& getBookmarks() { return m_bookmarks; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all book ids of the books in the library.
|
* Get all book ids of the books in the library.
|
||||||
*
|
*
|
||||||
|
@ -163,6 +197,7 @@ class Library
|
||||||
size_t maxSize = 0);
|
size_t maxSize = 0);
|
||||||
|
|
||||||
friend class OPDSDumper;
|
friend class OPDSDumper;
|
||||||
|
friend class libXMLDumper;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Matthieu Gautier <mgautier@kymeria.fr>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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 KIWIX_LIBXML_DUMPER_H
|
||||||
|
#define KIWIX_LIBXML_DUMPER_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <pugixml.hpp>
|
||||||
|
|
||||||
|
#include "library.h"
|
||||||
|
|
||||||
|
namespace kiwix
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tool to dump a `Library` into a basic library.xml
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class LibXMLDumper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LibXMLDumper() = default;
|
||||||
|
LibXMLDumper(Library* library);
|
||||||
|
~LibXMLDumper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump the library.xml
|
||||||
|
*
|
||||||
|
* @param id The id of the library.
|
||||||
|
* @return The library.xml content.
|
||||||
|
*/
|
||||||
|
std::string dumpLibXMLContent(const std::vector<std::string>& bookIds);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump the bookmark of the library.
|
||||||
|
*
|
||||||
|
* @return The bookmark.xml content.
|
||||||
|
*/
|
||||||
|
std::string dumpLibXMLBookmark();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the base directory used.
|
||||||
|
*
|
||||||
|
* @param baseDir the base directory to use.
|
||||||
|
*/
|
||||||
|
void setBaseDir(const std::string& baseDir) { this->baseDir = baseDir; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the library to dump.
|
||||||
|
*
|
||||||
|
* @param library The library to dump.
|
||||||
|
*/
|
||||||
|
void setLibrary(Library* library) { this->library = library; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
kiwix::Library* library;
|
||||||
|
std::string baseDir;
|
||||||
|
private:
|
||||||
|
void handleBook(Book book, pugi::xml_node root_node);
|
||||||
|
void handleBookmark(Bookmark bookmark, pugi::xml_node root_node);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KIWIX_OPDS_DUMPER_H
|
|
@ -38,6 +38,7 @@ class LibraryManipulator {
|
||||||
public:
|
public:
|
||||||
virtual ~LibraryManipulator() {}
|
virtual ~LibraryManipulator() {}
|
||||||
virtual bool addBookToLibrary(Book book) = 0;
|
virtual bool addBookToLibrary(Book book) = 0;
|
||||||
|
virtual void addBookmarkToLibrary(Bookmark bookmark) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DefaultLibraryManipulator : public LibraryManipulator {
|
class DefaultLibraryManipulator : public LibraryManipulator {
|
||||||
|
@ -48,6 +49,9 @@ class DefaultLibraryManipulator : public LibraryManipulator {
|
||||||
bool addBookToLibrary(Book book) {
|
bool addBookToLibrary(Book book) {
|
||||||
return library->addBook(book);
|
return library->addBook(book);
|
||||||
}
|
}
|
||||||
|
void addBookmarkToLibrary(Bookmark bookmark) {
|
||||||
|
library->addBookmark(bookmark);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
kiwix::Library* library;
|
kiwix::Library* library;
|
||||||
};
|
};
|
||||||
|
@ -113,6 +117,15 @@ class Manager
|
||||||
*/
|
*/
|
||||||
bool readOpds(const std::string& content, const std::string& urlHost);
|
bool readOpds(const std::string& content, const std::string& urlHost);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a bookmark file.
|
||||||
|
*
|
||||||
|
* @param path The path of the file to read.
|
||||||
|
* @return True if the content has been properly parsed.
|
||||||
|
*/
|
||||||
|
bool readBookmarkFile(const std::string& path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a book to the library.
|
* Add a book to the library.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
headers = [
|
headers = [
|
||||||
'book.h',
|
'book.h',
|
||||||
|
'bookmark.h',
|
||||||
'common.h',
|
'common.h',
|
||||||
'library.h',
|
'library.h',
|
||||||
'manager.h',
|
'manager.h',
|
||||||
|
'libxml_dumper.h',
|
||||||
'opds_dumper.h',
|
'opds_dumper.h',
|
||||||
'downloader.h',
|
'downloader.h',
|
||||||
'reader.h',
|
'reader.h',
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Matthieu Gautier <mgautier@kymeria.fr>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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 "bookmark.h"
|
||||||
|
|
||||||
|
#include <pugixml.hpp>
|
||||||
|
|
||||||
|
namespace kiwix
|
||||||
|
{
|
||||||
|
/* Constructor */
|
||||||
|
Bookmark::Bookmark()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destructor */
|
||||||
|
Bookmark::~Bookmark()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bookmark::updateFromXml(const pugi::xml_node& node)
|
||||||
|
{
|
||||||
|
auto bookNode = node.child("book");
|
||||||
|
m_bookId = bookNode.child("id").child_value();
|
||||||
|
m_bookTitle = bookNode.child("title").child_value();
|
||||||
|
m_language = bookNode.child("language").child_value();
|
||||||
|
m_date = bookNode.child("date").child_value();
|
||||||
|
m_title = node.child("title").child_value();
|
||||||
|
m_url = node.child("url").child_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
130
src/library.cpp
130
src/library.cpp
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "book.h"
|
#include "book.h"
|
||||||
|
#include "libxml_dumper.h"
|
||||||
|
|
||||||
#include "common/base64.h"
|
#include "common/base64.h"
|
||||||
#include "common/regexTools.h"
|
#include "common/regexTools.h"
|
||||||
|
@ -30,7 +31,7 @@
|
||||||
namespace kiwix
|
namespace kiwix
|
||||||
{
|
{
|
||||||
/* Constructor */
|
/* Constructor */
|
||||||
Library::Library() : version(KIWIX_LIBRARY_VERSION)
|
Library::Library()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/* Destructor */
|
/* Destructor */
|
||||||
|
@ -43,31 +44,48 @@ bool Library::addBook(const Book& book)
|
||||||
{
|
{
|
||||||
/* Try to find it */
|
/* Try to find it */
|
||||||
try {
|
try {
|
||||||
auto& oldbook = books.at(book.getId());
|
auto& oldbook = m_books.at(book.getId());
|
||||||
oldbook.update(book);
|
oldbook.update(book);
|
||||||
return false;
|
return false;
|
||||||
} catch (std::out_of_range&) {
|
} catch (std::out_of_range&) {
|
||||||
books[book.getId()] = book;
|
m_books[book.getId()] = book;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Library::addBookmark(const Bookmark& bookmark)
|
||||||
|
{
|
||||||
|
m_bookmarks.push_back(bookmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Library::removeBookmark(const std::string& zimId, const std::string& url)
|
||||||
|
{
|
||||||
|
for(auto it=m_bookmarks.begin(); it!=m_bookmarks.end(); it++) {
|
||||||
|
if (it->getBookId() == zimId && it->getUrl() == url) {
|
||||||
|
m_bookmarks.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Library::removeBookById(const std::string& id)
|
bool Library::removeBookById(const std::string& id)
|
||||||
{
|
{
|
||||||
return books.erase(id) == 1;
|
return m_books.erase(id) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Book& Library::getBookById(const std::string& id)
|
Book& Library::getBookById(const std::string& id)
|
||||||
{
|
{
|
||||||
return books.at(id);
|
return m_books.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Library::getBookCount(const bool localBooks,
|
unsigned int Library::getBookCount(const bool localBooks,
|
||||||
const bool remoteBooks)
|
const bool remoteBooks)
|
||||||
{
|
{
|
||||||
unsigned int result = 0;
|
unsigned int result = 0;
|
||||||
for (auto& pair: books) {
|
for (auto& pair: m_books) {
|
||||||
auto& book = pair.second;
|
auto& book = pair.second;
|
||||||
if ((!book.getPath().empty() && localBooks)
|
if ((!book.getPath().empty() && localBooks)
|
||||||
|| (book.getPath().empty() && remoteBooks)) {
|
|| (book.getPath().empty() && remoteBooks)) {
|
||||||
|
@ -78,91 +96,15 @@ unsigned int Library::getBookCount(const bool localBooks,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Library::writeToFile(const std::string& path) {
|
bool Library::writeToFile(const std::string& path) {
|
||||||
pugi::xml_document doc;
|
|
||||||
auto baseDir = removeLastPathElement(path, true, false);
|
auto baseDir = removeLastPathElement(path, true, false);
|
||||||
|
LibXMLDumper dumper(this);
|
||||||
/* Add the library node */
|
dumper.setBaseDir(baseDir);
|
||||||
pugi::xml_node libraryNode = doc.append_child("library");
|
return writeTextFile(path, dumper.dumpLibXMLContent(getBooksIds()));
|
||||||
|
|
||||||
if (!version.empty())
|
|
||||||
libraryNode.append_attribute("version") = version.c_str();
|
|
||||||
|
|
||||||
/* Add each book */
|
|
||||||
for (auto& pair: books) {
|
|
||||||
auto& book = pair.second;
|
|
||||||
if (!book.readOnly()) {
|
|
||||||
pugi::xml_node bookNode = libraryNode.append_child("book");
|
|
||||||
bookNode.append_attribute("id") = book.getId().c_str();
|
|
||||||
|
|
||||||
if (!book.getPath().empty()) {
|
|
||||||
bookNode.append_attribute("path") = computeRelativePath(
|
|
||||||
baseDir, book.getPath()).c_str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!book.getIndexPath().empty()) {
|
bool Library::writeBookmarksToFile(const std::string& path) {
|
||||||
bookNode.append_attribute("indexPath") = computeRelativePath(
|
LibXMLDumper dumper(this);
|
||||||
baseDir, book.getIndexPath()).c_str();
|
return writeTextFile(path, dumper.dumpLibXMLBookmark());
|
||||||
bookNode.append_attribute("indexType") = "xapian";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (book.getOrigId().empty()) {
|
|
||||||
if (!book.getTitle().empty())
|
|
||||||
bookNode.append_attribute("title") = book.getTitle().c_str();
|
|
||||||
|
|
||||||
if (!book.getName().empty())
|
|
||||||
bookNode.append_attribute("name") = book.getName().c_str();
|
|
||||||
|
|
||||||
if (!book.getTags().empty())
|
|
||||||
bookNode.append_attribute("tags") = book.getTags().c_str();
|
|
||||||
|
|
||||||
if (!book.getDescription().empty())
|
|
||||||
bookNode.append_attribute("description") = book.getDescription().c_str();
|
|
||||||
|
|
||||||
if (!book.getLanguage().empty())
|
|
||||||
bookNode.append_attribute("language") = book.getLanguage().c_str();
|
|
||||||
|
|
||||||
if (!book.getCreator().empty())
|
|
||||||
bookNode.append_attribute("creator") = book.getCreator().c_str();
|
|
||||||
|
|
||||||
if (!book.getPublisher().empty())
|
|
||||||
bookNode.append_attribute("publisher") = book.getPublisher().c_str();
|
|
||||||
|
|
||||||
if (!book.getFavicon().empty())
|
|
||||||
bookNode.append_attribute("favicon") = base64_encode(book.getFavicon()).c_str();
|
|
||||||
|
|
||||||
if (!book.getFaviconMimeType().empty())
|
|
||||||
bookNode.append_attribute("faviconMimeType")
|
|
||||||
= book.getFaviconMimeType().c_str();
|
|
||||||
} else {
|
|
||||||
bookNode.append_attribute("origId") = book.getOrigId().c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!book.getDate().empty()) {
|
|
||||||
bookNode.append_attribute("date") = book.getDate().c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!book.getUrl().empty()) {
|
|
||||||
bookNode.append_attribute("url") = book.getUrl().c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (book.getArticleCount())
|
|
||||||
bookNode.append_attribute("articleCount") = to_string(book.getArticleCount()).c_str();
|
|
||||||
|
|
||||||
if (book.getMediaCount())
|
|
||||||
bookNode.append_attribute("mediaCount") = to_string(book.getMediaCount()).c_str();
|
|
||||||
|
|
||||||
if (book.getSize()) {
|
|
||||||
bookNode.append_attribute("size") = to_string(book.getSize()>>10).c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!book.getDownloadId().empty()) {
|
|
||||||
bookNode.append_attribute("downloadId") = book.getDownloadId().c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* saving file */
|
|
||||||
return doc.save_file(path.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Library::getBooksLanguages()
|
std::vector<std::string> Library::getBooksLanguages()
|
||||||
|
@ -170,7 +112,7 @@ std::vector<std::string> Library::getBooksLanguages()
|
||||||
std::vector<std::string> booksLanguages;
|
std::vector<std::string> booksLanguages;
|
||||||
std::map<std::string, bool> booksLanguagesMap;
|
std::map<std::string, bool> booksLanguagesMap;
|
||||||
|
|
||||||
for (auto& pair: books) {
|
for (auto& pair: m_books) {
|
||||||
auto& book = pair.second;
|
auto& book = pair.second;
|
||||||
auto& language = book.getLanguage();
|
auto& language = book.getLanguage();
|
||||||
if (booksLanguagesMap.find(language) == booksLanguagesMap.end()) {
|
if (booksLanguagesMap.find(language) == booksLanguagesMap.end()) {
|
||||||
|
@ -189,7 +131,7 @@ std::vector<std::string> Library::getBooksCreators()
|
||||||
std::vector<std::string> booksCreators;
|
std::vector<std::string> booksCreators;
|
||||||
std::map<std::string, bool> booksCreatorsMap;
|
std::map<std::string, bool> booksCreatorsMap;
|
||||||
|
|
||||||
for (auto& pair: books) {
|
for (auto& pair: m_books) {
|
||||||
auto& book = pair.second;
|
auto& book = pair.second;
|
||||||
auto& creator = book.getCreator();
|
auto& creator = book.getCreator();
|
||||||
if (booksCreatorsMap.find(creator) == booksCreatorsMap.end()) {
|
if (booksCreatorsMap.find(creator) == booksCreatorsMap.end()) {
|
||||||
|
@ -208,7 +150,7 @@ std::vector<std::string> Library::getBooksPublishers()
|
||||||
std::vector<std::string> booksPublishers;
|
std::vector<std::string> booksPublishers;
|
||||||
std::map<std::string, bool> booksPublishersMap;
|
std::map<std::string, bool> booksPublishersMap;
|
||||||
|
|
||||||
for (auto& pair:books) {
|
for (auto& pair:m_books) {
|
||||||
auto& book = pair.second;
|
auto& book = pair.second;
|
||||||
auto& publisher = book.getPublisher();
|
auto& publisher = book.getPublisher();
|
||||||
if (booksPublishersMap.find(publisher) == booksPublishersMap.end()) {
|
if (booksPublishersMap.find(publisher) == booksPublishersMap.end()) {
|
||||||
|
@ -226,7 +168,7 @@ std::vector<std::string> Library::getBooksIds()
|
||||||
{
|
{
|
||||||
std::vector<std::string> bookIds;
|
std::vector<std::string> bookIds;
|
||||||
|
|
||||||
for (auto& pair: books) {
|
for (auto& pair: m_books) {
|
||||||
bookIds.push_back(pair.first);
|
bookIds.push_back(pair.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +182,7 @@ std::vector<std::string> Library::filter(const std::string& search)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> bookIds;
|
std::vector<std::string> bookIds;
|
||||||
for(auto& pair:books) {
|
for(auto& pair:m_books) {
|
||||||
auto& book = pair.second;
|
auto& book = pair.second;
|
||||||
if (matchRegex(book.getTitle(), "\\Q" + search + "\\E")
|
if (matchRegex(book.getTitle(), "\\Q" + search + "\\E")
|
||||||
|| matchRegex(book.getDescription(), "\\Q" + search + "\\E")) {
|
|| matchRegex(book.getDescription(), "\\Q" + search + "\\E")) {
|
||||||
|
@ -311,7 +253,7 @@ std::vector<std::string> Library::listBooksIds(
|
||||||
size_t maxSize) {
|
size_t maxSize) {
|
||||||
|
|
||||||
std::vector<std::string> bookIds;
|
std::vector<std::string> bookIds;
|
||||||
for(auto& pair:books) {
|
for(auto& pair:m_books) {
|
||||||
auto& book = pair.second;
|
auto& book = pair.second;
|
||||||
auto local = !book.getPath().empty();
|
auto local = !book.getPath().empty();
|
||||||
if (mode & LOCAL && !local)
|
if (mode & LOCAL && !local)
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Matthieu Gautier <mgautier@kymeria.fr>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* 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 "libxml_dumper.h"
|
||||||
|
#include "book.h"
|
||||||
|
|
||||||
|
#include <common/base64.h>
|
||||||
|
#include <common/stringTools.h>
|
||||||
|
#include <common/otherTools.h>
|
||||||
|
|
||||||
|
namespace kiwix
|
||||||
|
{
|
||||||
|
/* Constructor */
|
||||||
|
LibXMLDumper::LibXMLDumper(Library* library)
|
||||||
|
: library(library)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/* Destructor */
|
||||||
|
LibXMLDumper::~LibXMLDumper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_ATTRIBUTE(node, name, value) { (node).append_attribute((name)) = (value).c_str(); }
|
||||||
|
#define ADD_ATTR_NOT_EMPTY(node, name, value) { if (!(value).empty()) ADD_ATTRIBUTE(node, name, value); }
|
||||||
|
|
||||||
|
void LibXMLDumper::handleBook(Book book, pugi::xml_node root_node) {
|
||||||
|
if (book.readOnly())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto entry_node = root_node.append_child("book");
|
||||||
|
ADD_ATTRIBUTE(entry_node, "id", book.getId());
|
||||||
|
|
||||||
|
if (!book.getPath().empty()) {
|
||||||
|
ADD_ATTRIBUTE(entry_node, "path", computeRelativePath(baseDir, book.getPath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!book.getIndexPath().empty()) {
|
||||||
|
ADD_ATTRIBUTE(entry_node, "indexPath", computeRelativePath(baseDir, book.getIndexPath()));
|
||||||
|
entry_node.append_attribute("indexType") = "xapian";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (book.getOrigId().empty()) {
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "title", book.getTitle());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "name", book.getName());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "tags", book.getTags());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "description", book.getDescription());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "language", book.getLanguage());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "creator", book.getCreator());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "publisher", book.getPublisher());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "faviconMimeType", book.getFaviconMimeType());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "language", book.getLanguage());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "language", book.getLanguage());
|
||||||
|
if (!book.getFavicon().empty())
|
||||||
|
ADD_ATTRIBUTE(entry_node, "favicon", base64_encode(book.getFavicon()));
|
||||||
|
} else {
|
||||||
|
ADD_ATTRIBUTE(entry_node, "origId", book.getOrigId());
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "date", book.getDate());
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "url", book.getUrl());
|
||||||
|
|
||||||
|
if (book.getArticleCount())
|
||||||
|
ADD_ATTRIBUTE(entry_node, "articleCount", to_string(book.getArticleCount()));
|
||||||
|
|
||||||
|
if (book.getMediaCount())
|
||||||
|
ADD_ATTRIBUTE(entry_node, "mediaCount", to_string(book.getMediaCount()));
|
||||||
|
|
||||||
|
if (book.getSize())
|
||||||
|
ADD_ATTRIBUTE(entry_node, "size", to_string(book.getSize()>>10));
|
||||||
|
|
||||||
|
ADD_ATTR_NOT_EMPTY(entry_node, "downloadId", book.getDownloadId());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_TEXT_ENTRY(node, child, value) (node).append_child((child)).append_child(pugi::node_pcdata).set_value((value).c_str())
|
||||||
|
|
||||||
|
void LibXMLDumper::handleBookmark(Bookmark bookmark, pugi::xml_node root_node) {
|
||||||
|
|
||||||
|
auto entry_node = root_node.append_child("bookmark");
|
||||||
|
auto book_node = entry_node.append_child("book");
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto book = library->getBookById(bookmark.getBookId());
|
||||||
|
ADD_TEXT_ENTRY(book_node, "id", book.getId());
|
||||||
|
ADD_TEXT_ENTRY(book_node, "title", book.getTitle());
|
||||||
|
ADD_TEXT_ENTRY(book_node, "language", book.getLanguage());
|
||||||
|
ADD_TEXT_ENTRY(book_node, "date", book.getDate());
|
||||||
|
} catch (...) {
|
||||||
|
ADD_TEXT_ENTRY(book_node, "id", bookmark.getBookId());
|
||||||
|
ADD_TEXT_ENTRY(book_node, "title", bookmark.getBookTitle());
|
||||||
|
ADD_TEXT_ENTRY(book_node, "language", bookmark.getLanguage());
|
||||||
|
ADD_TEXT_ENTRY(book_node, "date", bookmark.getDate());
|
||||||
|
}
|
||||||
|
ADD_TEXT_ENTRY(entry_node, "title", bookmark.getTitle());
|
||||||
|
ADD_TEXT_ENTRY(entry_node, "url", bookmark.getUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string LibXMLDumper::dumpLibXMLContent(const std::vector<std::string>& bookIds)
|
||||||
|
{
|
||||||
|
pugi::xml_document doc;
|
||||||
|
|
||||||
|
/* Add the library node */
|
||||||
|
pugi::xml_node libraryNode = doc.append_child("library");
|
||||||
|
|
||||||
|
libraryNode.append_attribute("version") = KIWIX_LIBRARY_VERSION;
|
||||||
|
|
||||||
|
if (library) {
|
||||||
|
for (auto& bookId: bookIds) {
|
||||||
|
handleBook(library->getBookById(bookId), libraryNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodeToString(libraryNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LibXMLDumper::dumpLibXMLBookmark()
|
||||||
|
{
|
||||||
|
pugi::xml_document doc;
|
||||||
|
|
||||||
|
/* Add the library node */
|
||||||
|
pugi::xml_node bookmarksNode = doc.append_child("bookmarks");
|
||||||
|
|
||||||
|
if (library) {
|
||||||
|
for (auto& bookmark: library->getBookmarks()) {
|
||||||
|
handleBookmark(bookmark, bookmarksNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodeToString(bookmarksNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -221,4 +221,27 @@ bool Manager::readBookFromPath(const std::string& path, kiwix::Book* book)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Manager::readBookmarkFile(const std::string& path)
|
||||||
|
{
|
||||||
|
pugi::xml_document doc;
|
||||||
|
pugi::xml_parse_result result = doc.load_file(path.c_str());
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pugi::xml_node libraryNode = doc.child("bookmarks");
|
||||||
|
|
||||||
|
for (pugi::xml_node node = libraryNode.child("bookmark"); node;
|
||||||
|
node = node.next_sibling("bookmark")) {
|
||||||
|
kiwix::Bookmark bookmark;
|
||||||
|
|
||||||
|
bookmark.updateFromXml(node);
|
||||||
|
|
||||||
|
manipulator->addBookmarkToLibrary(bookmark);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
kiwix_sources = [
|
kiwix_sources = [
|
||||||
'book.cpp',
|
'book.cpp',
|
||||||
|
'bookmark.cpp',
|
||||||
'library.cpp',
|
'library.cpp',
|
||||||
'manager.cpp',
|
'manager.cpp',
|
||||||
|
'libxml_dumper.cpp',
|
||||||
'opds_dumper.cpp',
|
'opds_dumper.cpp',
|
||||||
'downloader.cpp',
|
'downloader.cpp',
|
||||||
'reader.cpp',
|
'reader.cpp',
|
||||||
|
|
Loading…
Reference in New Issue