Qt 4.8
qdbusutil.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdbusutil_p.h"
43 
44 #include "qdbus_symbols_p.h"
45 
46 #include <QtCore/qstringlist.h>
47 
48 #include "qdbusargument.h"
50 
51 #ifndef QT_NO_DBUS
52 
54 
55 static inline bool isValidCharacterNoDash(const QChar &c)
56 {
57  register ushort u = c.unicode();
58  return (u >= 'a' && u <= 'z')
59  || (u >= 'A' && u <= 'Z')
60  || (u >= '0' && u <= '9')
61  || (u == '_');
62 }
63 
64 static inline bool isValidCharacter(const QChar &c)
65 {
66  register ushort u = c.unicode();
67  return (u >= 'a' && u <= 'z')
68  || (u >= 'A' && u <= 'Z')
69  || (u >= '0' && u <= '9')
70  || (u == '_') || (u == '-');
71 }
72 
73 static inline bool isValidNumber(const QChar &c)
74 {
75  register ushort u = c.unicode();
76  return (u >= '0' && u <= '9');
77 }
78 
79 static bool argToString(const QDBusArgument &arg, QString &out);
80 
81 static bool variantToString(const QVariant &arg, QString &out)
82 {
83  int argType = arg.userType();
84 
85  if (argType == QVariant::StringList) {
86  out += QLatin1Char('{');
87  QStringList list = arg.toStringList();
88  foreach (QString item, list)
89  out += QLatin1Char('\"') + item + QLatin1String("\", ");
90  if (!list.isEmpty())
91  out.chop(2);
92  out += QLatin1Char('}');
93  } else if (argType == QVariant::ByteArray) {
94  out += QLatin1Char('{');
95  QByteArray list = arg.toByteArray();
96  for (int i = 0; i < list.count(); ++i) {
97  out += QString::number(list.at(i));
98  out += QLatin1String(", ");
99  }
100  if (!list.isEmpty())
101  out.chop(2);
102  out += QLatin1Char('}');
103  } else if (argType == QVariant::List) {
104  out += QLatin1Char('{');
105  QList<QVariant> list = arg.toList();
106  foreach (QVariant item, list) {
107  if (!variantToString(item, out))
108  return false;
109  out += QLatin1String(", ");
110  }
111  if (!list.isEmpty())
112  out.chop(2);
113  out += QLatin1Char('}');
114  } else if (argType == QMetaType::Char || argType == QMetaType::Short || argType == QMetaType::Int
115  || argType == QMetaType::Long || argType == QMetaType::LongLong) {
116  out += QString::number(arg.toLongLong());
117  } else if (argType == QMetaType::UChar || argType == QMetaType::UShort || argType == QMetaType::UInt
118  || argType == QMetaType::ULong || argType == QMetaType::ULongLong) {
119  out += QString::number(arg.toULongLong());
120  } else if (argType == QMetaType::Double) {
121  out += QString::number(arg.toDouble());
122  } else if (argType == QMetaType::Bool) {
123  out += QLatin1String(arg.toBool() ? "true" : "false");
124  } else if (argType == qMetaTypeId<QDBusArgument>()) {
125  argToString(qvariant_cast<QDBusArgument>(arg), out);
126  } else if (argType == qMetaTypeId<QDBusObjectPath>()) {
127  const QString path = qvariant_cast<QDBusObjectPath>(arg).path();
128  out += QLatin1String("[ObjectPath: ");
129  out += path;
130  out += QLatin1Char(']');
131  } else if (argType == qMetaTypeId<QDBusSignature>()) {
132  out += QLatin1String("[Signature: ") + qvariant_cast<QDBusSignature>(arg).signature();
133  out += QLatin1Char(']');
134  } else if (argType == qMetaTypeId<QDBusUnixFileDescriptor>()) {
135  out += QLatin1String("[Unix FD: ");
136  out += QLatin1String(qvariant_cast<QDBusUnixFileDescriptor>(arg).isValid() ? "valid" : "not valid");
137  out += QLatin1Char(']');
138  } else if (argType == qMetaTypeId<QDBusVariant>()) {
139  const QVariant v = qvariant_cast<QDBusVariant>(arg).variant();
140  out += QLatin1String("[Variant");
141  int vUserType = v.userType();
142  if (vUserType != qMetaTypeId<QDBusVariant>()
143  && vUserType != qMetaTypeId<QDBusSignature>()
144  && vUserType != qMetaTypeId<QDBusObjectPath>()
145  && vUserType != qMetaTypeId<QDBusArgument>())
146  out += QLatin1Char('(') + QLatin1String(v.typeName()) + QLatin1Char(')');
147  out += QLatin1String(": ");
148  if (!variantToString(v, out))
149  return false;
150  out += QLatin1Char(']');
151  } else if (arg.canConvert(QVariant::String)) {
152  out += QLatin1Char('\"') + arg.toString() + QLatin1Char('\"');
153  } else {
154  out += QLatin1Char('[');
155  out += QLatin1String(arg.typeName());
156  out += QLatin1Char(']');
157  }
158 
159  return true;
160 }
161 
162 bool argToString(const QDBusArgument &busArg, QString &out)
163 {
164  QString busSig = busArg.currentSignature();
165  bool doIterate = false;
166  QDBusArgument::ElementType elementType = busArg.currentType();
167 
168  if (elementType != QDBusArgument::BasicType && elementType != QDBusArgument::VariantType
169  && elementType != QDBusArgument::MapEntryType)
170  out += QLatin1String("[Argument: ") + busSig + QLatin1Char(' ');
171 
172  switch (elementType) {
175  if (!variantToString(busArg.asVariant(), out))
176  return false;
177  break;
179  busArg.beginStructure();
180  doIterate = true;
181  break;
183  busArg.beginArray();
184  out += QLatin1Char('{');
185  doIterate = true;
186  break;
188  busArg.beginMap();
189  out += QLatin1Char('{');
190  doIterate = true;
191  break;
193  busArg.beginMapEntry();
194  if (!variantToString(busArg.asVariant(), out))
195  return false;
196  out += QLatin1String(" = ");
197  if (!argToString(busArg, out))
198  return false;
199  busArg.endMapEntry();
200  break;
202  default:
203  out += QLatin1String("<ERROR - Unknown Type>");
204  return false;
205  }
206  if (doIterate && !busArg.atEnd()) {
207  while (!busArg.atEnd()) {
208  if (!argToString(busArg, out))
209  return false;
210  out += QLatin1String(", ");
211  }
212  out.chop(2);
213  }
214  switch (elementType) {
219  // nothing to do
220  break;
222  busArg.endStructure();
223  break;
225  out += QLatin1Char('}');
226  busArg.endArray();
227  break;
229  out += QLatin1Char('}');
230  busArg.endMap();
231  break;
232  }
233 
234  if (elementType != QDBusArgument::BasicType && elementType != QDBusArgument::VariantType
235  && elementType != QDBusArgument::MapEntryType)
236  out += QLatin1Char(']');
237 
238  return true;
239 }
240 
241 //------- D-Bus Types --------
242 static const char oneLetterTypes[] = "vsogybnqiuxtdh";
243 static const char basicTypes[] = "sogybnqiuxtdh";
244 static const char fixedTypes[] = "ybnqiuxtdh";
245 
246 static bool isBasicType(int c)
247 {
248  return c != DBUS_TYPE_INVALID && strchr(basicTypes, c) != NULL;
249 }
250 
251 static bool isFixedType(int c)
252 {
253  return c != DBUS_TYPE_INVALID && strchr(fixedTypes, c) != NULL;
254 }
255 
256 // Returns a pointer to one-past-end of this type if it's valid;
257 // returns NULL if it isn't valid.
258 static const char *validateSingleType(const char *signature)
259 {
260  register char c = *signature;
261  if (c == DBUS_TYPE_INVALID)
262  return 0;
263 
264  // is it one of the one-letter types?
265  if (strchr(oneLetterTypes, c) != NULL)
266  return signature + 1;
267 
268  // is it an array?
269  if (c == DBUS_TYPE_ARRAY) {
270  // then it's valid if the next type is valid
271  // or if it's a dict-entry
272  c = *++signature;
273  if (c == DBUS_DICT_ENTRY_BEGIN_CHAR) {
274  // beginning of a dictionary entry
275  // a dictionary entry has a key which is of basic types
276  // and a free value
277  c = *++signature;
278  if (!isBasicType(c))
279  return 0;
280  signature = validateSingleType(signature + 1);
281  return signature && *signature == DBUS_DICT_ENTRY_END_CHAR ? signature + 1 : 0;
282  }
283 
284  return validateSingleType(signature);
285  }
286 
287  if (c == DBUS_STRUCT_BEGIN_CHAR) {
288  // beginning of a struct
289  ++signature;
290  while (true) {
291  signature = validateSingleType(signature);
292  if (!signature)
293  return 0;
294  if (*signature == DBUS_STRUCT_END_CHAR)
295  return signature + 1;
296  }
297  }
298 
299  // invalid/unknown type
300  return 0;
301 }
302 
314 namespace QDBusUtil
315 {
325  {
326  QString out;
327 
328  variantToString(arg, out);
329 
330  return out;
331  }
332 
339  {
340  if (part.isEmpty())
341  return false; // can't be valid if it's empty
342 
343  const QChar *c = part.unicode();
344  for (int i = 0; i < part.length(); ++i)
345  if (!isValidCharacterNoDash(c[i]))
346  return false;
347 
348  return true;
349  }
350 
367  bool isValidInterfaceName(const QString& ifaceName)
368  {
369  if (ifaceName.isEmpty() || ifaceName.length() > DBUS_MAXIMUM_NAME_LENGTH)
370  return false;
371 
372  QStringList parts = ifaceName.split(QLatin1Char('.'));
373  if (parts.count() < 2)
374  return false; // at least two parts
375 
376  for (int i = 0; i < parts.count(); ++i)
377  if (!isValidMemberName(parts.at(i)))
378  return false;
379 
380  return true;
381  }
382 
393  bool isValidUniqueConnectionName(const QString &connName)
394  {
395  if (connName.isEmpty() || connName.length() > DBUS_MAXIMUM_NAME_LENGTH ||
396  !connName.startsWith(QLatin1Char(':')))
397  return false;
398 
399  QStringList parts = connName.mid(1).split(QLatin1Char('.'));
400  if (parts.count() < 1)
401  return false;
402 
403  for (int i = 0; i < parts.count(); ++i) {
404  const QString &part = parts.at(i);
405  if (part.isEmpty())
406  return false;
407 
408  const QChar* c = part.unicode();
409  for (int j = 0; j < part.length(); ++j)
410  if (!isValidCharacter(c[j]))
411  return false;
412  }
413 
414  return true;
415  }
416 
435  bool isValidBusName(const QString &busName)
436  {
437  if (busName.isEmpty() || busName.length() > DBUS_MAXIMUM_NAME_LENGTH)
438  return false;
439 
440  if (busName.startsWith(QLatin1Char(':')))
441  return isValidUniqueConnectionName(busName);
442 
443  QStringList parts = busName.split(QLatin1Char('.'));
444  if (parts.count() < 1)
445  return false;
446 
447  for (int i = 0; i < parts.count(); ++i) {
448  const QString &part = parts.at(i);
449  if (part.isEmpty())
450  return false;
451 
452  const QChar *c = part.unicode();
453  if (isValidNumber(c[0]))
454  return false;
455  for (int j = 0; j < part.length(); ++j)
456  if (!isValidCharacter(c[j]))
457  return false;
458  }
459 
460  return true;
461  }
462 
473  {
474  if (memberName.isEmpty() || memberName.length() > DBUS_MAXIMUM_NAME_LENGTH)
475  return false;
476 
477  const QChar* c = memberName.unicode();
478  if (isValidNumber(c[0]))
479  return false;
480  for (int j = 0; j < memberName.length(); ++j)
481  if (!isValidCharacterNoDash(c[j]))
482  return false;
483  return true;
484  }
485 
494  bool isValidErrorName(const QString &errorName)
495  {
496  return isValidInterfaceName(errorName);
497  }
498 
515  bool isValidObjectPath(const QString &path)
516  {
517  if (path == QLatin1String("/"))
518  return true;
519 
520  if (!path.startsWith(QLatin1Char('/')) || path.indexOf(QLatin1String("//")) != -1 ||
521  path.endsWith(QLatin1Char('/')))
522  return false;
523 
524  QStringList parts = path.split(QLatin1Char('/'));
525  Q_ASSERT(parts.count() >= 1);
526  parts.removeFirst(); // it starts with /, so we get an empty first part
527 
528  for (int i = 0; i < parts.count(); ++i)
529  if (!isValidPartOfObjectPath(parts.at(i)))
530  return false;
531 
532  return true;
533  }
534 
542  bool isValidBasicType(int c)
543  {
544  return isBasicType(c);
545  }
546 
554  bool isValidFixedType(int c)
555  {
556  return isFixedType(c);
557  }
558 
559 
571  bool isValidSignature(const QString &signature)
572  {
573  QByteArray ba = signature.toLatin1();
574  const char *data = ba.constData();
575  while (true) {
576  data = validateSingleType(data);
577  if (!data)
578  return false;
579  if (*data == '\0')
580  return true;
581  }
582  }
583 
593  bool isValidSingleSignature(const QString &signature)
594  {
595  QByteArray ba = signature.toLatin1();
596  const char *data = validateSingleType(ba.constData());
597  return data && *data == '\0';
598  }
599 
600 } // namespace QDBusUtil
601 
603 
604 #endif // QT_NO_DBUS
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
void beginMapEntry()
Opens a D-Bus map entry suitable for appending the key and value entries.
void endArray()
Closes a D-Bus array opened with beginArray().
static bool isFixedType(int c)
Definition: qdbusutil.cpp:251
static bool isValidCharacter(const QChar &c)
Definition: qdbusutil.cpp:64
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool isValidObjectPath(const QString &path)
Returns true if path is valid object path.
Definition: qdbusutil.cpp:515
static bool argToString(const QDBusArgument &arg, QString &out)
Definition: qdbusutil.cpp:162
ushort unicode() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qchar.h:251
The QDBusArgument class is used to marshall and demarshall D-Bus arguments.
Definition: qdbusargument.h:69
void beginArray(int elementMetaTypeId)
Opens a new D-Bus array suitable for appending elements of meta-type id.
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void chop(int n)
Removes n characters from the end of the string.
Definition: qstring.cpp:4623
static const char * validateSingleType(const char *signature)
Definition: qdbusutil.cpp:258
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
QString currentSignature() const
Returns the type signature of the D-Bus type this QDBusArgument object is currently pointing to...
The QDBusSignature class enables the programmer to identify the SIGNATURE type provided by the D-Bus ...
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QList< QVariant > toList() const
Returns the variant as a QVariantList if the variant has type() List or StringList ; otherwise return...
Definition: qvariant.cpp:2751
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool toBool() const
Returns the variant as a bool if the variant has type() Bool.
Definition: qvariant.cpp:2691
quint16 u
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
void beginMap(int keyMetaTypeId, int valueMetaTypeId)
Opens a new D-Bus map suitable for appending elements.
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static const char basicTypes[]
Definition: qdbusutil.cpp:243
bool isValidInterfaceName(const QString &ifaceName)
Returns true if this is ifaceName is a valid interface name.
Definition: qdbusutil.cpp:367
static bool isValidNumber(const QChar &c)
Definition: qdbusutil.cpp:73
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has type() ByteArray or String (converted using QS...
Definition: qvariant.cpp:2383
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
static bool isValidCharacterNoDash(const QChar &c)
Definition: qdbusutil.cpp:55
QStringList toStringList() const
Returns the variant as a QStringList if the variant has type() StringList, String ...
Definition: qvariant.cpp:2259
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
qlonglong toLongLong(bool *ok=0) const
Returns the variant as a long long int if the variant has type() LongLong , Bool , ByteArray , Char , Double , Int , String , UInt , or ULongLong ; otherwise returns 0.
Definition: qvariant.cpp:2659
bool canConvert(Type t) const
Returns true if the variant&#39;s type can be cast to the requested type, t.
Definition: qvariant.cpp:2886
bool atEnd() const
Returns true if there are no more elements to be extracted from this QDBusArgument.
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static bool isBasicType(int c)
Definition: qdbusutil.cpp:246
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
qulonglong toULongLong(bool *ok=0) const
Returns the variant as as an unsigned long long int if the variant has type() ULongLong ...
Definition: qvariant.cpp:2675
bool isValidSignature(const QString &signature)
Returns true if signature is a valid D-Bus type signature for one or more types.
Definition: qdbusutil.cpp:571
static const char * data(const QByteArray &arr)
static bool variantToString(const QVariant &arg, QString &out)
Definition: qdbusutil.cpp:81
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
bool isValidMemberName(const QString &memberName)
Returns true if memberName is a valid member name.
Definition: qdbusutil.cpp:472
void removeFirst()
Removes the first item in the list.
Definition: qlist.h:286
bool isValidSingleSignature(const QString &signature)
Returns true if signature is a valid D-Bus type signature for exactly one full type.
Definition: qdbusutil.cpp:593
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
bool isValidErrorName(const QString &errorName)
Returns true if errorName is a valid error name.
Definition: qdbusutil.cpp:494
const char * typeName() const
Returns the name of the type stored in the variant.
Definition: qvariant.cpp:1984
bool isValidFixedType(int c)
Returns true if c is a valid, fixed D-Bus type.
Definition: qdbusutil.cpp:554
bool isValidUniqueConnectionName(const QString &connName)
Returns true if connName is a valid unique connection name.
Definition: qdbusutil.cpp:393
QVariant asVariant() const
Returns the current argument in the form of a QVariant.
ElementType
This enum describes the type of element held by the argument.
Definition: qdbusargument.h:72
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
static const char fixedTypes[]
Definition: qdbusutil.cpp:244
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
ElementType currentType() const
Returns the classification of the current element type.
bool isValidBasicType(int c)
Returns true if c is a valid, basic D-Bus type.
Definition: qdbusutil.cpp:542
void endMapEntry()
Closes a D-Bus map entry opened with beginMapEntry().
int userType() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1913
void endMap()
Closes a D-Bus map opened with beginMap().
int count(char c) const
Returns the number of occurrences of character ch in the byte array.
unsigned short ushort
Definition: qglobal.h:995
void endStructure()
Closes a D-Bus structure opened with beginStructure().
The QDBusObjectPath class enables the programmer to identify the OBJECT_PATH type provided by the D-B...
double toDouble(bool *ok=0) const
Returns the variant as a double if the variant has type() Double , QMetaType::Float ...
Definition: qvariant.cpp:2710
void beginStructure()
Opens a new D-Bus structure suitable for appending new arguments.
static QByteArray memberName(const QMetaMethod &member)
bool isValidPartOfObjectPath(const QString &part)
Definition: qdbusutil.cpp:338
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
const char * variant
The QDBusUtil namespace contains a few functions that are of general use when dealing with D-Bus stri...
char at(int i) const
Returns the character at index position i in the byte array.
Definition: qbytearray.h:413
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QString argumentToString(const QVariant &arg)
Dumps the contents of a QtDBus argument from arg into a string.
Definition: qdbusutil.cpp:324
The QDBusVariant class enables the programmer to identify the variant type provided by the D-Bus type...
static const char oneLetterTypes[]
Definition: qdbusutil.cpp:242
T qvariant_cast(const QVariant &value)
Returns the given value converted to the template type T.
Definition: qvariant.h:571
bool isValidBusName(const QString &busName)
Returns true if busName is a valid bus name.
Definition: qdbusutil.cpp:435