1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Volker Krause <volker.krause@kdab.com>
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the tools applications of the Qt Toolkit
8 **
9 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29
30 #include <QCommandLineParser>
31 #include <QCoreApplication>
32 #include <QDir>
33 #include <QFile>
34 #include <QJsonDocument>
35 #include <QJsonObject>
36 #include <QLibrary>
37 #include <QPluginLoader>
38 #include <QStringList>
39
40 #include <iostream>
41
42 enum PrintOption {
43 PrintIID = 0x01,
44 PrintClassName = 0x02,
45 PrintQtInfo = 0x04,
46 PrintUserData = 0x08
47 };
Q_DECLARE_FLAGS(PrintOptions,PrintOption)48 Q_DECLARE_FLAGS(PrintOptions, PrintOption)
49 Q_DECLARE_OPERATORS_FOR_FLAGS(PrintOptions)
50
51 int main(int argc, char** argv)
52 {
53 QCoreApplication app(argc, argv);
54 QCoreApplication::setApplicationName(QStringLiteral("qplugininfo"));
55 QCoreApplication::setApplicationVersion(QStringLiteral(QT_VERSION_STR));
56
57 QCommandLineParser parser;
58 parser.setApplicationDescription(QStringLiteral("Qt5 plugin meta-data dumper"));
59 QCommandLineOption jsonFormatOption(QStringList() << "f" << "json-format",
60 QStringLiteral("Print JSON data as: indented, compact"), QStringLiteral("format"));
61 QCommandLineOption fullJsonOption("full-json",
62 QStringLiteral("Print the plugin metadata in JSON format"));
63 QCommandLineOption printOption(QStringList() << "p" << QStringLiteral("print"),
64 QStringLiteral("Print detail (iid, classname, qtinfo, userdata)"), QStringLiteral("detail"));
65 jsonFormatOption.setDefaultValue(QStringLiteral("indented"));
66 printOption.setDefaultValues(QStringList() << QStringLiteral("iid") << QStringLiteral("qtinfo") << QStringLiteral("userdata"));
67
68 parser.addOption(fullJsonOption);
69 parser.addOption(jsonFormatOption);
70 parser.addOption(printOption);
71 parser.addHelpOption();
72 parser.addVersionOption();
73 parser.addPositionalArgument(QStringLiteral("plugin"), QStringLiteral("Plug-in of which to read the meta data."), QStringLiteral("<plugin>"));
74 parser.process(app);
75
76 if (parser.positionalArguments().isEmpty())
77 parser.showHelp(1);
78
79 bool fullJson = parser.isSet(fullJsonOption);
80 QJsonDocument::JsonFormat jsonFormat = parser.value(jsonFormatOption) == "indented" ? QJsonDocument::Indented : QJsonDocument::Compact;
81 QStringList printOptionList = parser.values(printOption);
82 PrintOptions print;
83 if (printOptionList.contains("iid"))
84 print |= PrintIID;
85 if (printOptionList.contains("classname"))
86 print |= PrintClassName;
87 if (printOptionList.contains("qtinfo"))
88 print |= PrintQtInfo;
89 if (printOptionList.contains("userdata"))
90 print |= PrintUserData;
91
92 int retval = 0;
93 const QStringList positionalArguments = parser.positionalArguments();
94 for (const QString &plugin : positionalArguments) {
95 QByteArray pluginNativeName = QFile::encodeName(QDir::toNativeSeparators(plugin));
96 if (!QFile::exists(plugin)) {
97 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No such file or directory." << std::endl;
98 retval = 1;
99 continue;
100 }
101 if (!QLibrary::isLibrary(plugin)) {
102 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": Not a plug-in." << std::endl;
103 retval = 1;
104 continue;
105 }
106
107 QPluginLoader loader(plugin);
108 QJsonObject metaData = loader.metaData();
109 if (metaData.isEmpty()) {
110 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": No plug-in meta-data found: "
111 << qPrintable(loader.errorString()) << std::endl;
112 retval = 1;
113 continue;
114 }
115
116 QString iid = metaData.value("IID").toString();
117 QString className = metaData.value("className").toString();
118 QJsonValue debug = metaData.value("debug");
119 int version = metaData.value("version").toInt();
120 QJsonValue userData = metaData.value("MetaData");
121
122 if ((version >> 16) != (QT_VERSION >> 16)) {
123 std::cerr << "qtplugininfo: " << pluginNativeName.constData()
124 << ": Qt version mismatch - got major version " << (version >> 16)
125 << ", expected " << (QT_VERSION >> 16) << std::endl;
126 retval = 1;
127 continue;
128 }
129 if (iid.isEmpty() || className.isEmpty() || debug.isNull()) {
130 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, missing required fields:";
131 if (iid.isEmpty())
132 std::cerr << " iid";
133 if (className.isEmpty())
134 std::cerr << " className";
135 if (debug.isNull())
136 std::cerr << " debug";
137 std::cerr << std::endl;
138 retval = 1;
139 continue;
140 }
141
142 if (parser.positionalArguments().size() != 1)
143 std::cout << pluginNativeName.constData() << ": ";
144 if (fullJson) {
145 std::cout << QJsonDocument(metaData).toJson(jsonFormat).constData();
146 if (jsonFormat == QJsonDocument::Compact)
147 std::cout << std::endl;
148 } else {
149 if (print & PrintIID)
150 std::cout << "IID \"" << qPrintable(iid) << "\" ";
151 if (print & PrintClassName)
152 std::cout << "class " << qPrintable(className) << ' ';
153 if (print & PrintQtInfo)
154 std::cout << "Qt " << (version >> 16) << '.' << ((version >> 8) & 0xFF) << '.' << (version & 0xFF)
155 << (debug.toBool() ? " (debug)" : " (release)");
156 std::cout << std::endl;
157 if (print & PrintUserData) {
158 if (userData.isObject())
159 std::cout << "User Data: " << QJsonDocument(userData.toObject()).toJson().constData();
160 else if (!userData.isNull()) {
161 std::cerr << "qtplugininfo: " << pluginNativeName.constData() << ": invalid metadata, user data is not a JSON object" << std::endl;
162 retval = 1;
163 }
164 }
165 }
166 }
167
168 return retval;
169 }
170