From af9a8dbd8625334350b5ea27ebc0045b7d813074 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Sat, 16 Apr 2022 03:37:38 +0300 Subject: [PATCH] kio: implement EPUB meta information extractor via ebook-tools Signed-off-by: Ivailo Monev --- CMakeLists.txt | 8 ++ appveyor.yml | 2 +- kio/kio/kfilemetainfo.cpp | 4 +- kio/metadata/CMakeLists.txt | 22 +++ kio/metadata/kfilemetadata_epub.cpp | 176 ++++++++++++++++++++++++ kio/metadata/kfilemetadata_epub.desktop | 7 + kio/metadata/kfilemetadata_epub.h | 37 +++++ 7 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 kio/metadata/kfilemetadata_epub.cpp create mode 100644 kio/metadata/kfilemetadata_epub.desktop create mode 100644 kio/metadata/kfilemetadata_epub.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 41be3a4a..af38ffe6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,6 +223,14 @@ set_package_properties(Taglib PROPERTIES PURPOSE "Audio metadata extraction" ) +macro_optional_find_package(EPub) +set_package_properties(EPub PROPERTIES + DESCRIPTION "A library for reading EPub documents" + URL "https://sourceforge.net/projects/ebook-tools/" + TYPE RECOMMENDED + PURPOSE "eBook metadata extraction" +) + macro_optional_find_package(OpenSSL) set_package_properties(OpenSSL PROPERTIES DESCRIPTION "Robust, commercial-grade, full-featured toolkit for general-purpose cryptography and secure communication" diff --git a/appveyor.yml b/appveyor.yml index e5e40664..7aab983f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,7 +24,7 @@ build_script: libexiv2-dev libcdio-dev libssl-dev libcurl4-openssl-dev \ libdbusmenu-katie libavcodec-dev libavutil-dev libavformat-dev \ libtag1-dev media-player-info shared-mime-info media-player-info \ - xdg-utils ccache + libepub-dev xdg-utils ccache export PATH="/usr/lib/ccache/:$PATH" diff --git a/kio/kio/kfilemetainfo.cpp b/kio/kio/kfilemetainfo.cpp index ccdca9e4..f28a3579 100644 --- a/kio/kio/kfilemetainfo.cpp +++ b/kio/kio/kfilemetainfo.cpp @@ -277,6 +277,8 @@ QString KFileMetaInfo::name(const QString& key) { "http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#originalReleaseYear", i18nc("@label", "Original Release Year") }, { "http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#uniqueFileIdentifier", i18nc("@label", "URI") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#publisher", i18nc("@label", "Publisher") }, + { "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#creator", i18nc("@label", "Creator") }, + { "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#contributor", i18nc("@label", "Contributor") }, { "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#make", i18nc("@label EXIF", "Manufacturer") }, { "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#model", i18nc("@label EXIF", "Model") }, { "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#orientation", i18nc("@label EXIF", "Orientation") }, @@ -295,7 +297,6 @@ QString KFileMetaInfo::name(const QString& key) { "http://www.semanticdesktop.org/ontologies/2007/05/10/nexif#whiteBalance", i18nc("@label EXIF", "White Balance") }, // to be used by plugins { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#pageCount", i18nc("@label", "Page Count") }, - { "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#creator", i18nc("@label", "Creator") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nmo#Email", i18nc("@label", "Creator E-Mail") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#hashValue", i18nc("@label", "Hash Value") }, { "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#hashAlgorithm", i18nc("@label", "Hash Algorithm") }, @@ -310,7 +311,6 @@ QString KFileMetaInfo::name(const QString& key) { "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#Contact", i18nc("@label", "Contact") }, { "http://www.semanticdesktop.org/ontologies/2007/01/19/nie#disclaimer", i18nc("@label", "Disclaimer") }, { "http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#textWriter", i18nc("@label", "Text Writer") }, - { "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#contributor", i18nc("@label", "Contributor") }, { "http://www.semanticdesktop.org/ontologies/2009/02/19/nmm#director", i18nc("@label video director", "Director") }, { "http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#conductor", i18nc("@label", "Conductor") }, { "http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#interpretedBy", i18nc("@label", "Interpreted By") }, diff --git a/kio/metadata/CMakeLists.txt b/kio/metadata/CMakeLists.txt index 384f05fb..1a89c9c8 100644 --- a/kio/metadata/CMakeLists.txt +++ b/kio/metadata/CMakeLists.txt @@ -59,3 +59,25 @@ if (TAGLIB_FOUND) DESTINATION ${KDE4_SERVICES_INSTALL_DIR} ) endif() + +if (EPUB_FOUND) + include_directories(${EPUB_INCLUDE_DIR}) + + set(kfilemetadata_epub_SRCS kfilemetadata_epub.cpp) + + kde4_add_plugin(kfilemetadata_epub ${kfilemetadata_epub_SRCS}) + target_link_libraries(kfilemetadata_epub + ${KDE4_KIO_LIBS} + ${EPUB_LIBRARIES} + ) + + install( + TARGETS kfilemetadata_epub + DESTINATION ${KDE4_PLUGIN_INSTALL_DIR} + ) + + install( + FILES kfilemetadata_epub.desktop + DESTINATION ${KDE4_SERVICES_INSTALL_DIR} + ) +endif() diff --git a/kio/metadata/kfilemetadata_epub.cpp b/kio/metadata/kfilemetadata_epub.cpp new file mode 100644 index 00000000..cfd9af49 --- /dev/null +++ b/kio/metadata/kfilemetadata_epub.cpp @@ -0,0 +1,176 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kfilemetadata_epub.h" +#include "kpluginfactory.h" +#include "kdebug.h" + +#include + +static QString getEPubMetadata(struct epub *epubdocument, enum epub_metadata epubmetadata) +{ + QString result; + int epubdatasize = 0; + uchar **epubdata = epub_get_metadata(epubdocument, epubmetadata, &epubdatasize); + if (!epubdata) { + return result; + } + for (int i = 0; i < epubdatasize; i++) { + if (i == 0) { + result = QString::fromUtf8(reinterpret_cast(epubdata[i])); + } else { + result.append(QLatin1String(", ")); + result.append(QString::fromUtf8(reinterpret_cast(epubdata[i]))); + } + ::free(epubdata[i]); + } + ::free(epubdata); + return result; +} + +KFileMetaDataEPubPlugin::KFileMetaDataEPubPlugin(QObject* parent, const QVariantList &args) + : KFileMetaDataPlugin(parent) +{ + Q_UNUSED(args); +} + +KFileMetaDataEPubPlugin::~KFileMetaDataEPubPlugin() +{ +} + +QStringList KFileMetaDataEPubPlugin::keys() const +{ + static const QStringList result = QStringList() + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#uniqueFileIdentifier") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#title") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#creator") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#contributor") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#subject") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#publisher") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#description") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentCreated") + << QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#copyright"); + return result; +} + +QStringList KFileMetaDataEPubPlugin::mimeTypes() const +{ + static const QStringList result = QStringList() + << QString::fromLatin1("application/epub+zip"); + return result; +} + +QList KFileMetaDataEPubPlugin::metaData(const KUrl &url, const KFileMetaInfo::WhatFlags flags) +{ + Q_UNUSED(flags); + QList result; + const QByteArray urlpath = url.toLocalFile().toLocal8Bit(); + struct epub *epubdocument = epub_open(urlpath.constData(), 1); + if (!epubdocument) { + kWarning() << "Could not open" << urlpath; + return result; + } + const QString epubid = getEPubMetadata(epubdocument, EPUB_ID); + if (!epubid.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#uniqueFileIdentifier"), + epubid + ) + ); + } + const QString epubtitle = getEPubMetadata(epubdocument, EPUB_TITLE); + if (!epubtitle.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#title"), + epubtitle + ) + ); + } + const QString epubcreator = getEPubMetadata(epubdocument, EPUB_CREATOR); + if (!epubcreator.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#creator"), + epubcreator + ) + ); + } + const QString epubcontrib = getEPubMetadata(epubdocument, EPUB_CONTRIB); + if (!epubcontrib.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#contributor"), + epubcontrib + ) + ); + } + const QString epubsubject = getEPubMetadata(epubdocument, EPUB_SUBJECT); + if (!epubsubject.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#subject"), + epubsubject + ) + ); + } + const QString epubpublisher = getEPubMetadata(epubdocument, EPUB_PUBLISHER); + if (!epubpublisher.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#publisher"), + epubpublisher + ) + ); + } + const QString epubdescription = getEPubMetadata(epubdocument, EPUB_DESCRIPTION); + if (!epubdescription.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#description"), + epubdescription + ) + ); + } + const QString epubdate = getEPubMetadata(epubdocument, EPUB_DATE); + if (!epubdate.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentCreated"), + epubdate + ) + ); + } + const QString epubrights = getEPubMetadata(epubdocument, EPUB_RIGHTS); + if (!epubrights.isEmpty()) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#copyright"), + epubrights + ) + ); + } + epub_close(epubdocument); + return result; +} + +K_PLUGIN_FACTORY(KFileMetaDataEPubPluginFactory, registerPlugin();) +K_EXPORT_PLUGIN(KFileMetaDataEPubPluginFactory("kfilemetadata_epub")) + +#include "moc_kfilemetadata_epub.cpp" diff --git a/kio/metadata/kfilemetadata_epub.desktop b/kio/metadata/kfilemetadata_epub.desktop new file mode 100644 index 00000000..7f50f224 --- /dev/null +++ b/kio/metadata/kfilemetadata_epub.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Service +Name=KFileMetaDataEPubPlugin +GenericName=EPUB metadata extractor +X-KDE-Library=kfilemetadata_epub +X-KDE-ServiceTypes=KFileMetaData/Plugin +InitialPreference=1 diff --git a/kio/metadata/kfilemetadata_epub.h b/kio/metadata/kfilemetadata_epub.h new file mode 100644 index 00000000..560739b3 --- /dev/null +++ b/kio/metadata/kfilemetadata_epub.h @@ -0,0 +1,37 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KFILEMETADATA_EPUB_H +#define KFILEMETADATA_EPUB_H + +#include "kfilemetadata.h" + +class KFileMetaDataEPubPlugin : public KFileMetaDataPlugin +{ + Q_OBJECT +public: + KFileMetaDataEPubPlugin(QObject* parent, const QVariantList &args); + ~KFileMetaDataEPubPlugin(); + + QStringList keys() const final; + QStringList mimeTypes() const final; + + QList metaData(const KUrl &url, const KFileMetaInfo::WhatFlags flags) final; +}; + +#endif // KFILEMETADATA_EPUB_H