qdbusxmlparser.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/dbus/qdbusxmlparser.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtDBus module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qdbusxmlparser_p.h"-
41#include "qdbusutil_p.h"-
42-
43#include <QtCore/qmap.h>-
44#include <QtCore/qvariant.h>-
45#include <QtCore/qtextstream.h>-
46#include <QtCore/qxmlstream.h>-
47#include <QtCore/qdebug.h>-
48-
49#ifndef QT_NO_DBUS-
50-
51//#define QDBUS_PARSER_DEBUG-
52#ifdef QDBUS_PARSER_DEBUG-
53# define qDBusParserError qDebug-
54#else-
55# define qDBusParserError if (true) {} else qDebug-
56#endif-
57-
58QT_BEGIN_NAMESPACE-
59-
60static bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection::Argument &argData,-
61 QDBusIntrospection::Interface *ifaceData)-
62{-
63 const QString argType = attributes.value(QLatin1String("type")).toString();-
64-
65 bool ok = QDBusUtil::isValidSingleSignature(argType);-
66 if (!ok) {-
67 qDBusParserError("Invalid D-BUS type signature '%s' found while parsing introspection",
dead code: QMessageLogger(__FILE__, 67, __PRETTY_FUNCTION__).debug("Invalid D-BUS type signature '%s' found while parsing introspection", QString(argType).toLocal8Bit().constData());
-
68 qPrintable(argType));
dead code: QMessageLogger(__FILE__, 67, __PRETTY_FUNCTION__).debug("Invalid D-BUS type signature '%s' found while parsing introspection", QString(argType).toLocal8Bit().constData());
-
69 }-
70-
71 argData.name = attributes.value(QLatin1String("name")).toString();-
72 argData.type = argType;-
73-
74 ifaceData->introspection += QLatin1String(" <arg");-
75 if (attributes.hasAttribute(QLatin1String("direction"))) {-
76 const QString direction = attributes.value(QLatin1String("direction")).toString();-
77 ifaceData->introspection += QLatin1String(" direction=\"") + direction + QLatin1String("\"");-
78 }-
79 ifaceData->introspection += QLatin1String(" type=\"") + argData.type + QLatin1String("\"");-
80 if (!argData.name.isEmpty())-
81 ifaceData->introspection += QLatin1String(" name=\"") + argData.name + QLatin1String("\"");-
82 ifaceData->introspection += QLatin1String("/>\n");-
83-
84 return ok;-
85}-
86-
87static bool parseAnnotation(const QXmlStreamReader &xml, QDBusIntrospection::Annotations &annotations,-
88 QDBusIntrospection::Interface *ifaceData, bool interfaceAnnotation = false)-
89{-
90 Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("annotation"));-
91-
92 const QXmlStreamAttributes attributes = xml.attributes();-
93 const QString name = attributes.value(QLatin1String("name")).toString();-
94-
95 if (!QDBusUtil::isValidInterfaceName(name)) {-
96 qDBusParserError("Invalid D-BUS annotation '%s' found while parsing introspection",
dead code: QMessageLogger(__FILE__, 96, __PRETTY_FUNCTION__).debug("Invalid D-BUS annotation '%s' found while parsing introspection", QString(name).toLocal8Bit().constData());
-
97 qPrintable(name));
dead code: QMessageLogger(__FILE__, 96, __PRETTY_FUNCTION__).debug("Invalid D-BUS annotation '%s' found while parsing introspection", QString(name).toLocal8Bit().constData());
-
98 return false;-
99 }-
100 const QString value = attributes.value(QLatin1String("value")).toString();-
101 annotations.insert(name, value);-
102 if (!interfaceAnnotation)-
103 ifaceData->introspection += QLatin1String(" ");-
104 ifaceData->introspection += QLatin1String(" <annotation value=\"") + value.toHtmlEscaped() + QLatin1String("\" name=\"") + name + QLatin1String("\"/>\n");-
105 return true;-
106}-
107-
108static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &propertyData,-
109 QDBusIntrospection::Interface *ifaceData)-
110{-
111 Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("property"));-
112-
113 QXmlStreamAttributes attributes = xml.attributes();-
114 const QString propertyName = attributes.value(QLatin1String("name")).toString();-
115 if (!QDBusUtil::isValidMemberName(propertyName)) {-
116 qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
dead code: QMessageLogger(__FILE__, 116, __PRETTY_FUNCTION__).debug("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", QString(propertyName).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData());
-
117 qPrintable(propertyName), qPrintable(ifaceData->name));
dead code: QMessageLogger(__FILE__, 116, __PRETTY_FUNCTION__).debug("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", QString(propertyName).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData());
-
118 xml.skipCurrentElement();-
119 return false;-
120 }-
121-
122 // parse data-
123 propertyData.name = propertyName;-
124 propertyData.type = attributes.value(QLatin1String("type")).toString();-
125-
126 if (!QDBusUtil::isValidSingleSignature(propertyData.type)) {-
127 // cannot be!-
128 qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection",
dead code: QMessageLogger(__FILE__, 128, __PRETTY_FUNCTION__).debug("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", QString(propertyData.type).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData(), QString(propertyName).toLocal8Bit().constData());
-
129 qPrintable(propertyData.type), qPrintable(ifaceData->name),
dead code: QMessageLogger(__FILE__, 128, __PRETTY_FUNCTION__).debug("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", QString(propertyData.type).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData(), QString(propertyName).toLocal8Bit().constData());
-
130 qPrintable(propertyName));
dead code: QMessageLogger(__FILE__, 128, __PRETTY_FUNCTION__).debug("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", QString(propertyData.type).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData(), QString(propertyName).toLocal8Bit().constData());
-
131 }-
132-
133 const QString access = attributes.value(QLatin1String("access")).toString();-
134 if (access == QLatin1String("read"))-
135 propertyData.access = QDBusIntrospection::Property::Read;-
136 else if (access == QLatin1String("write"))-
137 propertyData.access = QDBusIntrospection::Property::Write;-
138 else if (access == QLatin1String("readwrite"))-
139 propertyData.access = QDBusIntrospection::Property::ReadWrite;-
140 else {-
141 qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection",
dead code: QMessageLogger(__FILE__, 141, __PRETTY_FUNCTION__).debug("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", QString(access).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData(), QString(propertyName).toLocal8Bit().constData());
-
142 qPrintable(access), qPrintable(ifaceData->name),
dead code: QMessageLogger(__FILE__, 141, __PRETTY_FUNCTION__).debug("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", QString(access).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData(), QString(propertyName).toLocal8Bit().constData());
-
143 qPrintable(propertyName));
dead code: QMessageLogger(__FILE__, 141, __PRETTY_FUNCTION__).debug("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", QString(access).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData(), QString(propertyName).toLocal8Bit().constData());
-
144 return false; // invalid one!-
145 }-
146-
147 ifaceData->introspection += QLatin1String(" <property access=\"") + access + QLatin1String("\" type=\"") + propertyData.type + QLatin1String("\" name=\"") + propertyName + QLatin1String("\"");-
148-
149 if (!xml.readNextStartElement()) {-
150 ifaceData->introspection += QLatin1String("/>\n");-
151 } else {-
152 ifaceData->introspection += QLatin1String(">\n");-
153-
154 do {-
155 if (xml.name() == QLatin1String("annotation")) {-
156 parseAnnotation(xml, propertyData.annotations, ifaceData);-
157 } else if (xml.prefix().isEmpty()) {-
158 qDBusParserError() << "Unknown element" << xml.name() << "while checking for annotations";
dead code: QMessageLogger(__FILE__, 158, __PRETTY_FUNCTION__).debug() << "Unknown element" << xml.name() << "while checking for annotations";
-
159 }-
160 xml.skipCurrentElement();-
161 } while (xml.readNextStartElement());-
162-
163 ifaceData->introspection += QLatin1String(" </property>\n");-
164 }-
165-
166 if (!xml.isEndElement() || xml.name() != QLatin1String("property")) {-
167 qDBusParserError() << "Invalid property specification" << xml.tokenString() << xml.name();
dead code: QMessageLogger(__FILE__, 167, __PRETTY_FUNCTION__).debug() << "Invalid property specification" << xml.tokenString() << xml.name();
-
168 return false;-
169 }-
170-
171 return true;-
172}-
173-
174static bool parseMethod(QXmlStreamReader &xml, QDBusIntrospection::Method &methodData,-
175 QDBusIntrospection::Interface *ifaceData)-
176{-
177 Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("method"));-
178-
179 const QXmlStreamAttributes attributes = xml.attributes();-
180 const QString methodName = attributes.value(QLatin1String("name")).toString();-
181 if (!QDBusUtil::isValidMemberName(methodName)) {-
182 qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
dead code: QMessageLogger(__FILE__, 182, __PRETTY_FUNCTION__).debug("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", QString(methodName).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData());
-
183 qPrintable(methodName), qPrintable(ifaceData->name));
dead code: QMessageLogger(__FILE__, 182, __PRETTY_FUNCTION__).debug("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", QString(methodName).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData());
-
184 return false;-
185 }-
186-
187 methodData.name = methodName;-
188 ifaceData->introspection += QLatin1String(" <method name=\"") + methodName + QLatin1String("\"");-
189-
190 QDBusIntrospection::Arguments outArguments;-
191 QDBusIntrospection::Arguments inArguments;-
192 QDBusIntrospection::Annotations annotations;-
193-
194 if (!xml.readNextStartElement()) {-
195 ifaceData->introspection += QLatin1String("/>\n");-
196 } else {-
197 ifaceData->introspection += QLatin1String(">\n");-
198-
199 do {-
200 if (xml.name() == QLatin1String("annotation")) {-
201 parseAnnotation(xml, annotations, ifaceData);-
202 } else if (xml.name() == QLatin1String("arg")) {-
203 const QXmlStreamAttributes attributes = xml.attributes();-
204 const QString direction = attributes.value(QLatin1String("direction")).toString();-
205 QDBusIntrospection::Argument argument;-
206 if (!attributes.hasAttribute(QLatin1String("direction"))-
207 || direction == QLatin1String("in")) {-
208 parseArg(attributes, argument, ifaceData);-
209 inArguments << argument;-
210 } else if (direction == QLatin1String("out")) {-
211 parseArg(attributes, argument, ifaceData);-
212 outArguments << argument;-
213 }-
214 } else if (xml.prefix().isEmpty()) {-
215 qDBusParserError() << "Unknown element" << xml.name() << "while checking for method arguments";
dead code: QMessageLogger(__FILE__, 215, __PRETTY_FUNCTION__).debug() << "Unknown element" << xml.name() << "while checking for method arguments";
-
216 }-
217 xml.skipCurrentElement();-
218 } while (xml.readNextStartElement());-
219-
220 ifaceData->introspection += QLatin1String(" </method>\n");-
221 }-
222-
223 methodData.inputArgs = inArguments;-
224 methodData.outputArgs = outArguments;-
225 methodData.annotations = annotations;-
226-
227 return true;-
228}-
229-
230-
231static bool parseSignal(QXmlStreamReader &xml, QDBusIntrospection::Signal &signalData,-
232 QDBusIntrospection::Interface *ifaceData)-
233{-
234 Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("signal"));-
235-
236 const QXmlStreamAttributes attributes = xml.attributes();-
237 const QString signalName = attributes.value(QLatin1String("name")).toString();-
238-
239 if (!QDBusUtil::isValidMemberName(signalName)) {-
240 qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
dead code: QMessageLogger(__FILE__, 240, __PRETTY_FUNCTION__).debug("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", QString(signalName).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData());
-
241 qPrintable(signalName), qPrintable(ifaceData->name));
dead code: QMessageLogger(__FILE__, 240, __PRETTY_FUNCTION__).debug("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", QString(signalName).toLocal8Bit().constData(), QString(ifaceData->name).toLocal8Bit().constData());
-
242 return false;-
243 }-
244-
245 signalData.name = signalName;-
246 ifaceData->introspection += QLatin1String(" <signal name=\"") + signalName + QLatin1String("\"");-
247-
248 QDBusIntrospection::Arguments arguments;-
249 QDBusIntrospection::Annotations annotations;-
250-
251 if (!xml.readNextStartElement()) {-
252 ifaceData->introspection += QLatin1String("/>\n");-
253 } else {-
254 ifaceData->introspection += QLatin1String(">\n");-
255-
256 do {-
257 if (xml.name() == QLatin1String("annotation")) {-
258 parseAnnotation(xml, annotations, ifaceData);-
259 } else if (xml.name() == QLatin1String("arg")) {-
260 const QXmlStreamAttributes attributes = xml.attributes();-
261 QDBusIntrospection::Argument argument;-
262 if (!attributes.hasAttribute(QLatin1String("direction")) ||-
263 attributes.value(QLatin1String("direction")) == QLatin1String("out")) {-
264 parseArg(attributes, argument, ifaceData);-
265 arguments << argument;-
266 }-
267 } else {-
268 qDBusParserError() << "Unknown element" << xml.name() << "while checking for signal arguments";
dead code: QMessageLogger(__FILE__, 268, __PRETTY_FUNCTION__).debug() << "Unknown element" << xml.name() << "while checking for signal arguments";
-
269 }-
270 xml.skipCurrentElement();-
271 } while (xml.readNextStartElement());-
272-
273 ifaceData->introspection += QLatin1String(" </signal>\n");-
274 }-
275-
276 signalData.outputArgs = arguments;-
277 signalData.annotations = annotations;-
278-
279 return true;-
280}-
281-
282static void readInterface(QXmlStreamReader &xml, QDBusIntrospection::Object *objData,-
283 QDBusIntrospection::Interfaces *interfaces)-
284{-
285 const QString ifaceName = xml.attributes().value(QLatin1String("name")).toString();-
286 if (!QDBusUtil::isValidInterfaceName(ifaceName)) {-
287 qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection",
dead code: QMessageLogger(__FILE__, 287, __PRETTY_FUNCTION__).debug("Invalid D-BUS interface name '%s' found while parsing introspection", QString(ifaceName).toLocal8Bit().constData());
-
288 qPrintable(ifaceName));
dead code: QMessageLogger(__FILE__, 287, __PRETTY_FUNCTION__).debug("Invalid D-BUS interface name '%s' found while parsing introspection", QString(ifaceName).toLocal8Bit().constData());
-
289 return;-
290 }-
291-
292 objData->interfaces.append(ifaceName);-
293-
294 QDBusIntrospection::Interface *ifaceData = new QDBusIntrospection::Interface;-
295 ifaceData->name = ifaceName;-
296 ifaceData->introspection += QLatin1String(" <interface name=\"") + ifaceName + QLatin1String("\">\n");-
297-
298 while (xml.readNextStartElement()) {-
299 if (xml.name() == QLatin1String("method")) {-
300 QDBusIntrospection::Method methodData;-
301 if (parseMethod(xml, methodData, ifaceData))-
302 ifaceData->methods.insert(methodData.name, methodData);-
303 } else if (xml.name() == QLatin1String("signal")) {-
304 QDBusIntrospection::Signal signalData;-
305 if (parseSignal(xml, signalData, ifaceData))-
306 ifaceData->signals_.insert(signalData.name, signalData);-
307 } else if (xml.name() == QLatin1String("property")) {-
308 QDBusIntrospection::Property propertyData;-
309 if (parseProperty(xml, propertyData, ifaceData))-
310 ifaceData->properties.insert(propertyData.name, propertyData);-
311 } else if (xml.name() == QLatin1String("annotation")) {-
312 parseAnnotation(xml, ifaceData->annotations, ifaceData, true);-
313 xml.skipCurrentElement(); // skip over annotation object-
314 } else {-
315 if (xml.prefix().isEmpty()) {-
316 qDBusParserError() << "Unknown element while parsing interface" << xml.name();
dead code: QMessageLogger(__FILE__, 316, __PRETTY_FUNCTION__).debug() << "Unknown element while parsing interface" << xml.name();
-
317 }-
318 xml.skipCurrentElement();-
319 }-
320 }-
321-
322 ifaceData->introspection += QLatin1String(" </interface>");-
323-
324 interfaces->insert(ifaceName, QSharedDataPointer<QDBusIntrospection::Interface>(ifaceData));-
325-
326 if (!xml.isEndElement() || xml.name() != QLatin1String("interface")) {-
327 qDBusParserError() << "Invalid Interface specification";
dead code: QMessageLogger(__FILE__, 327, __PRETTY_FUNCTION__).debug() << "Invalid Interface specification";
-
328 }-
329}-
330-
331static void readNode(const QXmlStreamReader &xml, QDBusIntrospection::Object *objData, int nodeLevel)-
332{-
333 const QString objName = xml.attributes().value(QLatin1String("name")).toString();-
334 const QString fullName = objData->path.endsWith(QLatin1Char('/'))-
335 ? (objData->path + objName)-
336 : QString(objData->path + QLatin1Char('/') + objName);-
337 if (!QDBusUtil::isValidObjectPath(fullName)) {-
338 qDBusParserError("Invalid D-BUS object path '%s' found while parsing introspection",
dead code: QMessageLogger(__FILE__, 338, __PRETTY_FUNCTION__).debug("Invalid D-BUS object path '%s' found while parsing introspection", QString(fullName).toLocal8Bit().constData());
-
339 qPrintable(fullName));
dead code: QMessageLogger(__FILE__, 338, __PRETTY_FUNCTION__).debug("Invalid D-BUS object path '%s' found while parsing introspection", QString(fullName).toLocal8Bit().constData());
-
340 return;-
341 }-
342-
343 if (nodeLevel > 0)-
344 objData->childObjects.append(objName);-
345}-
346-
347QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path,-
348 const QString& xmlData)-
349 : m_service(service), m_path(path), m_object(new QDBusIntrospection::Object)-
350{-
351// qDBusParserError() << "parsing" << xmlData;-
352-
353 m_object->service = m_service;-
354 m_object->path = m_path;-
355-
356 QXmlStreamReader xml(xmlData);-
357-
358 int nodeLevel = -1;-
359-
360 while (!xml.atEnd()) {-
361 xml.readNext();-
362-
363 switch (xml.tokenType()) {-
364 case QXmlStreamReader::StartElement:-
365 if (xml.name() == QLatin1String("node")) {-
366 readNode(xml, m_object, ++nodeLevel);-
367 } else if (xml.name() == QLatin1String("interface")) {-
368 readInterface(xml, m_object, &m_interfaces);-
369 } else {-
370 if (xml.prefix().isEmpty()) {-
371 qDBusParserError() << "skipping unknown element" << xml.name();
dead code: QMessageLogger(__FILE__, 371, __PRETTY_FUNCTION__).debug() << "skipping unknown element" << xml.name();
-
372 }-
373 xml.skipCurrentElement();-
374 }-
375 break;-
376 case QXmlStreamReader::EndElement:-
377 if (xml.name() == QLatin1String("node")) {-
378 --nodeLevel;-
379 } else {-
380 qDBusParserError() << "Invalid Node declaration" << xml.name();
dead code: QMessageLogger(__FILE__, 380, __PRETTY_FUNCTION__).debug() << "Invalid Node declaration" << xml.name();
-
381 }-
382 break;-
383 case QXmlStreamReader::StartDocument:-
384 case QXmlStreamReader::EndDocument:-
385 case QXmlStreamReader::DTD:-
386 // not interested-
387 break;-
388 case QXmlStreamReader::Comment:-
389 // ignore comments and processing instructions-
390 break;-
391 default:-
392 qDBusParserError() << "unknown token" << xml.name() << xml.tokenString();
dead code: QMessageLogger(__FILE__, 392, __PRETTY_FUNCTION__).debug() << "unknown token" << xml.name() << xml.tokenString();
-
393 break;-
394 }-
395 }-
396-
397 if (xml.hasError()) {-
398 qDBusParserError() << "xml error" << xml.errorString() << "doc" << xmlData;
dead code: QMessageLogger(__FILE__, 398, __PRETTY_FUNCTION__).debug() << "xml error" << xml.errorString() << "doc" << xmlData;
-
399 }-
400}-
401-
402QT_END_NAMESPACE-
403-
404#endif // QT_NO_DBUS-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9