File indexing completed on 2024-04-14 05:44:32

0001 /***************************************************************************
0002                       odfplugin.cpp  -  description
0003                              -------------------
0004     begin                : Wed June 20th 2018
0005     copyright            : (C) 2018 by Friedrich W. H. Kossebau
0006     email                : kossebau@kde.org
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *                                                                         *
0016  ***************************************************************************/
0017 
0018 #include "odfplugin.h"
0019 
0020 #include "batchrenamer.h"
0021 #include "tokenhelpdialog.h"
0022 // KF
0023 #include <KZip>
0024 // Qt
0025 #include <QDomDocument>
0026 #include <QDebug>
0027 
0028 namespace {
0029 inline QString dcNS()     { return QStringLiteral("http://purl.org/dc/elements/1.1/"); }
0030 inline QString metaNS()   { return QStringLiteral("urn:oasis:names:tc:opendocument:xmlns:meta:1.0"); }
0031 inline QString officeNS() { return QStringLiteral("urn:oasis:names:tc:opendocument:xmlns:office:1.0"); }
0032 
0033 QString createHelpString(const QString &tokenId, const QString &description)
0034 {
0035     return QLatin1Char('[') + tokenId + QLatin1Char(']') + TokenHelpDialog::getTokenSeparator() + description;
0036 }
0037 
0038 QDomElement namedItemNS(const QDomNode &node, const QString &nsURI, const QString &localName)
0039 {
0040     for (auto n = node.firstChildElement(); !n.isNull(); n = n.nextSiblingElement()) {
0041         if (n.localName() == localName && n.namespaceURI() == nsURI) {
0042             return n;
0043         }
0044     }
0045 
0046     return QDomElement();
0047 }
0048 }
0049 
0050 
0051 OdfPlugin::OdfPlugin(PluginLoader *loader)
0052     : FilePlugin(loader)
0053     , m_creatorToken("odfCreator")
0054     , m_keywordsToken("odfKeywords")
0055     , m_subjectToken("odfSubject")
0056     , m_titleToken("odfTitle")
0057     , m_generatorToken("odfGenerator")
0058     , m_languageToken("odfLanguage")
0059     , m_pageCountToken("odfPageCount")
0060     , m_wordCountToken("odfWordCount")
0061 {
0062     m_name = i18n("OpenDocument Format (ODT, ODS, ODP) Plugin");
0063     m_comment = i18n("<qt>This plugin supports reading metadata from "
0064                      "files in an OpenDocument format.</qt>");
0065 
0066     // there is no generic ODF icon, so use the text one for now
0067     m_icon = "application-vnd.oasis.opendocument.text";
0068 
0069     addSupportedToken(m_creatorToken);
0070     addSupportedToken(m_keywordsToken);
0071     addSupportedToken(m_subjectToken);
0072     addSupportedToken(m_titleToken);
0073     addSupportedToken(m_generatorToken);
0074     addSupportedToken(m_languageToken);
0075     addSupportedToken(m_pageCountToken);
0076     addSupportedToken(m_wordCountToken);
0077 
0078     m_help = QStringList {
0079         createHelpString(m_creatorToken, i18n("Creator of the ODF file")),
0080         createHelpString(m_keywordsToken, i18n("Keywords of the ODF file")),
0081         createHelpString(m_subjectToken, i18n("Subject of the ODF file")),
0082         createHelpString(m_titleToken, i18n("Title of the ODF file")),
0083         createHelpString(m_generatorToken, i18n("Generator of the ODF file")),
0084         createHelpString(m_languageToken, i18n("Language of the ODF file")),
0085         createHelpString(m_pageCountToken, i18n("Number of pages in the ODF file")),
0086         createHelpString(m_wordCountToken, i18n("Number of words in the ODF file")),
0087     };
0088 
0089     // prepare for case-insensitive comparison
0090     m_creatorToken = m_creatorToken.toLower();
0091     m_keywordsToken = m_keywordsToken.toLower();
0092     m_subjectToken = m_subjectToken.toLower();
0093     m_titleToken = m_titleToken.toLower();
0094     m_generatorToken = m_generatorToken.toLower();
0095     m_languageToken = m_languageToken.toLower();
0096     m_pageCountToken = m_pageCountToken.toLower();
0097     m_wordCountToken = m_wordCountToken.toLower();
0098 }
0099 
0100 
0101 QString OdfPlugin::processFile(BatchRenamer *b, int index, const QString &filenameOrToken, EPluginType)
0102 {
0103     const QString token = filenameOrToken.toLower();
0104 
0105     if (!supports(token)) {
0106         return QString("");
0107     }
0108 
0109     const QString filename = (*b->files())[index].srcUrl().path();
0110     KZip zip(filename);
0111     if (!zip.open(QIODevice::ReadOnly)) {
0112         return QString("");
0113     }
0114 
0115     const KArchiveDirectory* directory = zip.directory();
0116     if (!directory) {
0117         return QString("");
0118     }
0119 
0120     // we need a meta xml file in the archive!
0121     const auto metaXml = directory->entry(QStringLiteral("meta.xml"));
0122     if (!metaXml || !metaXml->isFile()) {
0123         return QString("");
0124     }
0125 
0126     QDomDocument metaDataDocument(QStringLiteral("metaData"));
0127     bool success = metaDataDocument.setContent(static_cast<const KArchiveFile*>(metaXml)->data(), true);
0128     if (!success)  {
0129         return QString("");
0130     }
0131 
0132     // parse metadata ..
0133     QDomElement meta = namedItemNS(namedItemNS(metaDataDocument,
0134                                                officeNS(), QStringLiteral("document-meta")),
0135                                                officeNS(), QStringLiteral("meta"));
0136 
0137     // Dublin Core
0138     if (token == m_subjectToken) {
0139         return namedItemNS(meta, dcNS(), QStringLiteral("subject")).text();
0140     }
0141     if (token == m_titleToken) {
0142         return namedItemNS(meta, dcNS(), QStringLiteral("title")).text();
0143     }
0144     if (token == m_creatorToken) {
0145         return namedItemNS(meta, dcNS(), QStringLiteral("creator")).text();
0146     }
0147     if (token == m_languageToken) {
0148         return namedItemNS(meta, dcNS(), QStringLiteral("language")).text();
0149     }
0150 
0151     // Meta Properties
0152     if (token == m_keywordsToken) {
0153         return namedItemNS(meta, metaNS(), QStringLiteral("keyword")).text();
0154     }
0155     if (token == m_generatorToken) {
0156         return namedItemNS(meta, metaNS(), QStringLiteral("generator")).text();
0157     }
0158 
0159     const QString attributeName =
0160         (token == m_pageCountToken) ? QStringLiteral("page-count") :
0161         (token == m_wordCountToken) ? QStringLiteral("word-count") :
0162         /* else */                    QString();
0163 
0164     if (!attributeName.isEmpty()) {
0165         return namedItemNS(meta, metaNS(), QStringLiteral("document-statistic")).attributeNS(metaNS(), attributeName);
0166     }
0167 
0168     return QString("");
0169 }
0170 
0171 const QStringList & OdfPlugin::help() const
0172 {
0173     return m_help;
0174 }