KFileMetaData

externalextractor.cpp
1/*
2 This file is part of the KFileMetaData project
3 SPDX-FileCopyrightText: 2016 Varun Joshi <varunj.1011@gmail.com>
4 SPDX-FileCopyrightText: 2015 Boudhayan Gupta <bgupta@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7*/
8
9#include "externalextractor.h"
10#include "kfilemetadata_debug.h"
11#include "properties.h"
12#include "propertyinfo.h"
13#include "typeinfo.h"
14
15#include <QDir>
16#include <QProcess>
17#include <QJsonDocument>
18#include <QJsonObject>
19#include <QJsonArray>
20
21namespace KFileMetaData
22{
23class ExternalExtractorPrivate
24{
25public:
26 QString path;
27 QStringList writeMimetypes;
28 QString mainPath;
29};
30}
31
32using namespace KFileMetaData;
33
34ExternalExtractor::ExternalExtractor(QObject* parent)
35 : ExtractorPlugin(parent),
36 d_ptr(new ExternalExtractorPrivate)
37{
38}
39
40ExternalExtractor::ExternalExtractor(const QString& pluginPath)
41 : ExtractorPlugin(nullptr),
42 d_ptr(new ExternalExtractorPrivate)
43{
44 Q_D(ExternalExtractor);
45
46 d->path = pluginPath;
47
48 QDir pluginDir(pluginPath);
49 QStringList pluginDirContents = pluginDir.entryList(QDir::Files | QDir::NoDotAndDotDot);
50
51 if (!pluginDirContents.contains(QStringLiteral("manifest.json"))) {
52 qCDebug(KFILEMETADATA_LOG) << pluginPath << "does not seem to contain a valid plugin";
53 return;
54 }
55
56 QFile manifest(pluginDir.filePath(QStringLiteral("manifest.json")));
57 manifest.open(QIODevice::ReadOnly);
58 QJsonDocument manifestDoc = QJsonDocument::fromJson(manifest.readAll());
59 if (!manifestDoc.isObject()) {
60 qCDebug(KFILEMETADATA_LOG) << "Manifest does not seem to be a valid JSON Object";
61 return;
62 }
63
64 QJsonObject rootObject = manifestDoc.object();
65 const QJsonArray mimetypesArray = rootObject.value(QStringLiteral("mimetypes")).toArray();
66 QStringList mimetypes;
67 mimetypes.reserve(mimetypesArray.count());
68
69 for (const QJsonValue &mimetype : mimetypesArray) {
70 mimetypes << mimetype.toString();
71 }
72
73 d->writeMimetypes.append(mimetypes);
74 d->mainPath = pluginDir.absoluteFilePath(rootObject[QStringLiteral("main")].toString());
75}
76
77ExternalExtractor::~ExternalExtractor() = default;
78
79QStringList ExternalExtractor::mimetypes() const
80{
81 Q_D(const ExternalExtractor);
82
83 return d->writeMimetypes;
84}
85
86void ExternalExtractor::extract(ExtractionResult* result)
87{
88 Q_D(ExternalExtractor);
89
90 QJsonDocument writeData;
91 QJsonObject writeRootObject;
92 QByteArray output;
93 QByteArray errorOutput;
94
95 writeRootObject[QStringLiteral("path")] = QJsonValue(result->inputUrl());
96 writeRootObject[QStringLiteral("mimetype")] = result->inputMimetype();
97 writeData.setObject(writeRootObject);
98
99 QProcess extractorProcess;
100 extractorProcess.start(d->mainPath, QStringList(), QIODevice::ReadWrite);
101 bool started = extractorProcess.waitForStarted();
102 if (!started) {
103 qCWarning(KFILEMETADATA_LOG) << "External extractor" << d->mainPath
104 << "failed to start:" << extractorProcess.errorString();
105 return;
106 }
107
108 extractorProcess.write(writeData.toJson());
109 extractorProcess.closeWriteChannel();
110 extractorProcess.waitForFinished();
111
112 output = extractorProcess.readAll();
113 errorOutput = extractorProcess.readAllStandardError();
114
115 if (extractorProcess.exitStatus()) {
116 qCWarning(KFILEMETADATA_LOG) << "External extractor" << d->mainPath
117 << "failed to index" << result->inputUrl() << "-" << errorOutput;
118 return;
119 }
120
121 // now we read in the output (which is a standard json format) into the
122 // ExtractionResult
123
124 QJsonDocument extractorData = QJsonDocument::fromJson(output);
125 if (!extractorData.isObject()) {
126 return;
127 }
128 QJsonObject rootObject = extractorData.object();
129 QJsonObject propertiesObject = rootObject[QStringLiteral("properties")].toObject();
130
131 const auto propertiesObjectEnd = propertiesObject.constEnd();
132 auto i = propertiesObject.constBegin();
133 for (; i != propertiesObjectEnd; ++i) {
134 if (i.key() == QStringLiteral("typeInfo")) {
135 TypeInfo info = TypeInfo::fromName(i.value().toString());
136 result->addType(info.type());
137 continue;
138 }
139
140 // for plaintext extraction
141 if (i.key() == QStringLiteral("text")) {
142 result->append(i.value().toString());
143 continue;
144 }
145
146 PropertyInfo info = PropertyInfo::fromName(i.key());
147 if (info.name() != i.key()) {
148 continue;
149 }
150 result->add(info.property(), i.value().toVariant());
151 }
152
153 if (rootObject[QStringLiteral("status")].toString() != QStringLiteral("OK")) {
154 qCDebug(KFILEMETADATA_LOG) << rootObject[QStringLiteral("error")].toString();
155 }
156}
157
158#include "moc_externalextractor.cpp"
The ExtractionResult class is where all the data extracted by the indexer is saved.
QString inputUrl() const
The input URL which the plugins will use to locate the file.
virtual void addType(Type::Type type)=0
This function is called by the plugins.
QString inputMimetype() const
The input MIME type.
virtual void add(Property::Property property, const QVariant &value)=0
This function is called by the plugins when they wish to add a key value pair which should be indexed...
virtual void append(const QString &text)=0
This function is called by plugins when they wish for some plain text to be indexed without any prope...
The ExtractorPlugin is the base class for all file metadata extractors.
The PropertyInfo class can be used to obtain extra information about any property.
QString name() const
The internal unique name used to refer to the property.
Property::Property property() const
The enumeration which represents this property.
static PropertyInfo fromName(const QString &name)
Construct a PropertyInfo from the internal property name.
The TypeInfo class can be used to obtain a rough type classification for a file.
Definition typeinfo.h:31
Type::Type type() const
The type identifier.
Definition typeinfo.cpp:109
static TypeInfo fromName(const QString &name)
Construct a TypeInfo from the internal type name.
Definition typeinfo.cpp:114
char * toString(const EngineQuery &query)
The KFileMetaData namespace.
KIOCORE_EXPORT MimetypeJob * mimetype(const QUrl &url, JobFlags flags=DefaultFlags)
QString errorString() const const
QByteArray readAll()
qint64 write(const QByteArray &data)
qsizetype count() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
bool isObject() const const
QJsonObject object() const const
void setObject(const QJsonObject &object)
QByteArray toJson(JsonFormat format) const const
const_iterator constBegin() const const
const_iterator constEnd() const const
QJsonValue value(QLatin1StringView key) const const
QJsonArray toArray() const const
void reserve(qsizetype size)
void closeWriteChannel()
QProcess::ExitStatus exitStatus() const const
QByteArray readAllStandardError()
void start(OpenMode mode)
bool waitForFinished(int msecs)
bool waitForStarted(int msecs)
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:49:15 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.