/****************************************************************************+ −
**+ −
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).+ −
** All rights reserved.+ −
** Contact: Nokia Corporation (qt-info@nokia.com)+ −
**+ −
** This file is part of the QtDBus module of the Qt Toolkit.+ −
**+ −
** $QT_BEGIN_LICENSE:LGPL$+ −
** No Commercial Usage+ −
** This file contains pre-release code and may not be distributed.+ −
** You may use this file in accordance with the terms and conditions+ −
** contained in the Technology Preview License Agreement accompanying+ −
** this package.+ −
**+ −
** GNU Lesser General Public License Usage+ −
** Alternatively, this file may be used under the terms of the GNU Lesser+ −
** General Public License version 2.1 as published by the Free Software+ −
** Foundation and appearing in the file LICENSE.LGPL included in the+ −
** packaging of this file. Please review the following information to+ −
** ensure the GNU Lesser General Public License version 2.1 requirements+ −
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.+ −
**+ −
** In addition, as a special exception, Nokia gives you certain additional+ −
** rights. These rights are described in the Nokia Qt LGPL Exception+ −
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.+ −
**+ −
** If you have questions regarding the use of this file, please contact+ −
** Nokia at qt-info@nokia.com.+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
** $QT_END_LICENSE$+ −
**+ −
****************************************************************************/+ −
+ −
#include "qdbusutil_p.h"+ −
+ −
#include "qdbus_symbols_p.h"+ −
+ −
#include <QtCore/qstringlist.h>+ −
+ −
#include "qdbusargument.h"+ −
+ −
#ifndef QT_NO_DBUS+ −
+ −
QT_BEGIN_NAMESPACE+ −
+ −
static inline bool isValidCharacterNoDash(const QChar &c)+ −
{+ −
register ushort u = c.unicode();+ −
return (u >= 'a' && u <= 'z')+ −
|| (u >= 'A' && u <= 'Z')+ −
|| (u >= '0' && u <= '9')+ −
|| (u == '_');+ −
}+ −
+ −
static inline bool isValidCharacter(const QChar &c)+ −
{+ −
register ushort u = c.unicode();+ −
return (u >= 'a' && u <= 'z')+ −
|| (u >= 'A' && u <= 'Z')+ −
|| (u >= '0' && u <= '9')+ −
|| (u == '_') || (u == '-');+ −
}+ −
+ −
static inline bool isValidNumber(const QChar &c)+ −
{+ −
register ushort u = c.unicode();+ −
return (u >= '0' && u <= '9');+ −
}+ −
+ −
static bool argToString(const QDBusArgument &arg, QString &out);+ −
+ −
static bool variantToString(const QVariant &arg, QString &out)+ −
{+ −
int argType = arg.userType();+ −
+ −
if (argType == QVariant::StringList) {+ −
out += QLatin1Char('{');+ −
QStringList list = arg.toStringList();+ −
foreach (QString item, list)+ −
out += QLatin1Char('\"') + item + QLatin1String("\", ");+ −
if (!list.isEmpty())+ −
out.chop(2);+ −
out += QLatin1Char('}');+ −
} else if (argType == QVariant::ByteArray) {+ −
out += QLatin1Char('{');+ −
QByteArray list = arg.toByteArray();+ −
for (int i = 0; i < list.count(); ++i) {+ −
out += QString::number(list.at(i));+ −
out += QLatin1String(", ");+ −
}+ −
if (!list.isEmpty())+ −
out.chop(2);+ −
out += QLatin1Char('}');+ −
} else if (argType == QVariant::List) {+ −
out += QLatin1Char('{');+ −
QList<QVariant> list = arg.toList();+ −
foreach (QVariant item, list) {+ −
if (!variantToString(item, out))+ −
return false;+ −
out += QLatin1String(", ");+ −
}+ −
if (!list.isEmpty())+ −
out.chop(2);+ −
out += QLatin1Char('}');+ −
} else if (argType == QMetaType::Char || argType == QMetaType::Short || argType == QMetaType::Int+ −
|| argType == QMetaType::Long || argType == QMetaType::LongLong) {+ −
out += QString::number(arg.toLongLong());+ −
} else if (argType == QMetaType::UChar || argType == QMetaType::UShort || argType == QMetaType::UInt+ −
|| argType == QMetaType::ULong || argType == QMetaType::ULongLong) {+ −
out += QString::number(arg.toULongLong());+ −
} else if (argType == QMetaType::Double) {+ −
out += QString::number(arg.toDouble());+ −
} else if (argType == QMetaType::Bool) {+ −
out += QLatin1String(arg.toBool() ? "true" : "false");+ −
} else if (argType == qMetaTypeId<QDBusArgument>()) {+ −
argToString(qvariant_cast<QDBusArgument>(arg), out);+ −
} else if (argType == qMetaTypeId<QDBusObjectPath>()) {+ −
const QString path = qvariant_cast<QDBusObjectPath>(arg).path();+ −
out += QLatin1String("[ObjectPath: ");+ −
out += path;+ −
out += QLatin1Char(']');+ −
} else if (argType == qMetaTypeId<QDBusSignature>()) {+ −
out += QLatin1String("[Signature: ") + qvariant_cast<QDBusSignature>(arg).signature();+ −
out += QLatin1Char(']');+ −
} else if (argType == qMetaTypeId<QDBusVariant>()) {+ −
const QVariant v = qvariant_cast<QDBusVariant>(arg).variant();+ −
out += QLatin1String("[Variant");+ −
int vUserType = v.userType();+ −
if (vUserType != qMetaTypeId<QDBusVariant>()+ −
&& vUserType != qMetaTypeId<QDBusSignature>()+ −
&& vUserType != qMetaTypeId<QDBusObjectPath>()+ −
&& vUserType != qMetaTypeId<QDBusArgument>())+ −
out += QLatin1Char('(') + QLatin1String(v.typeName()) + QLatin1Char(')');+ −
out += QLatin1String(": ");+ −
if (!variantToString(v, out))+ −
return false;+ −
out += QLatin1Char(']');+ −
} else if (arg.canConvert(QVariant::String)) {+ −
out += QLatin1Char('\"') + arg.toString() + QLatin1Char('\"');+ −
} else {+ −
out += QLatin1Char('[');+ −
out += QLatin1String(arg.typeName());+ −
out += QLatin1Char(']');+ −
}+ −
+ −
return true;+ −
}+ −
+ −
bool argToString(const QDBusArgument &busArg, QString &out)+ −
{+ −
QString busSig = busArg.currentSignature();+ −
bool doIterate = false;+ −
QDBusArgument::ElementType elementType = busArg.currentType();+ −
+ −
if (elementType != QDBusArgument::BasicType && elementType != QDBusArgument::VariantType+ −
&& elementType != QDBusArgument::MapEntryType)+ −
out += QLatin1String("[Argument: ") + busSig + QLatin1Char(' ');+ −
+ −
switch (elementType) {+ −
case QDBusArgument::BasicType:+ −
case QDBusArgument::VariantType:+ −
if (!variantToString(busArg.asVariant(), out))+ −
return false;+ −
break;+ −
case QDBusArgument::StructureType:+ −
busArg.beginStructure();+ −
doIterate = true;+ −
break;+ −
case QDBusArgument::ArrayType:+ −
busArg.beginArray();+ −
out += QLatin1Char('{');+ −
doIterate = true;+ −
break;+ −
case QDBusArgument::MapType:+ −
busArg.beginMap();+ −
out += QLatin1Char('{');+ −
doIterate = true;+ −
break;+ −
case QDBusArgument::MapEntryType:+ −
busArg.beginMapEntry();+ −
if (!variantToString(busArg.asVariant(), out))+ −
return false;+ −
out += QLatin1String(" = ");+ −
if (!argToString(busArg, out))+ −
return false;+ −
busArg.endMapEntry();+ −
break;+ −
case QDBusArgument::UnknownType:+ −
default:+ −
out += QLatin1String("<ERROR - Unknown Type>");+ −
return false;+ −
}+ −
if (doIterate && !busArg.atEnd()) {+ −
while (!busArg.atEnd()) {+ −
if (!argToString(busArg, out))+ −
return false;+ −
out += QLatin1String(", ");+ −
}+ −
out.chop(2);+ −
}+ −
switch (elementType) {+ −
case QDBusArgument::BasicType:+ −
case QDBusArgument::VariantType:+ −
case QDBusArgument::UnknownType:+ −
case QDBusArgument::MapEntryType:+ −
// nothing to do+ −
break;+ −
case QDBusArgument::StructureType:+ −
busArg.endStructure();+ −
break;+ −
case QDBusArgument::ArrayType:+ −
out += QLatin1Char('}');+ −
busArg.endArray();+ −
break;+ −
case QDBusArgument::MapType:+ −
out += QLatin1Char('}');+ −
busArg.endMap();+ −
break;+ −
}+ −
+ −
if (elementType != QDBusArgument::BasicType && elementType != QDBusArgument::VariantType+ −
&& elementType != QDBusArgument::MapEntryType)+ −
out += QLatin1Char(']');+ −
+ −
return true;+ −
}+ −
+ −
/*!+ −
\namespace QDBusUtil+ −
\inmodule QtDBus+ −
\internal+ −
+ −
\brief The QDBusUtil namespace contains a few functions that are of general use when+ −
dealing with D-Bus strings.+ −
*/+ −
namespace QDBusUtil+ −
{+ −
/*!+ −
\internal+ −
\since 4.5+ −
Dumps the contents of a QtDBus argument from \a arg into a string.+ −
*/+ −
QString argumentToString(const QVariant &arg)+ −
{+ −
QString out;+ −
+ −
variantToString(arg, out);+ −
+ −
return out;+ −
}+ −
+ −
/*!+ −
\internal+ −
\fn bool QDBusUtil::isValidPartOfObjectPath(const QString &part)+ −
See QDBusUtil::isValidObjectPath+ −
*/+ −
bool isValidPartOfObjectPath(const QString &part)+ −
{+ −
if (part.isEmpty())+ −
return false; // can't be valid if it's empty+ −
+ −
const QChar *c = part.unicode();+ −
for (int i = 0; i < part.length(); ++i)+ −
if (!isValidCharacterNoDash(c[i]))+ −
return false;+ −
+ −
return true;+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidInterfaceName(const QString &ifaceName)+ −
Returns true if this is \a ifaceName is a valid interface name.+ −
+ −
Valid interface names must:+ −
\list+ −
\o not be empty+ −
\o not exceed 255 characters in length+ −
\o be composed of dot-separated string components that contain only ASCII letters, digits+ −
and the underscore ("_") character+ −
\o contain at least two such components+ −
\endlist+ −
*/+ −
bool isValidInterfaceName(const QString& ifaceName)+ −
{+ −
if (ifaceName.isEmpty() || ifaceName.length() > DBUS_MAXIMUM_NAME_LENGTH)+ −
return false;+ −
+ −
QStringList parts = ifaceName.split(QLatin1Char('.'));+ −
if (parts.count() < 2)+ −
return false; // at least two parts+ −
+ −
for (int i = 0; i < parts.count(); ++i)+ −
if (!isValidMemberName(parts.at(i)))+ −
return false;+ −
+ −
return true;+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidUniqueConnectionName(const QString &connName)+ −
Returns true if \a connName is a valid unique connection name.+ −
+ −
Unique connection names start with a colon (":") and are followed by a list of dot-separated+ −
components composed of ASCII letters, digits, the hypen or the underscore ("_") character.+ −
*/+ −
bool isValidUniqueConnectionName(const QString &connName)+ −
{+ −
if (connName.isEmpty() || connName.length() > DBUS_MAXIMUM_NAME_LENGTH ||+ −
!connName.startsWith(QLatin1Char(':')))+ −
return false;+ −
+ −
QStringList parts = connName.mid(1).split(QLatin1Char('.'));+ −
if (parts.count() < 1)+ −
return false;+ −
+ −
for (int i = 0; i < parts.count(); ++i) {+ −
const QString &part = parts.at(i);+ −
if (part.isEmpty())+ −
return false;+ −
+ −
const QChar* c = part.unicode();+ −
for (int j = 0; j < part.length(); ++j)+ −
if (!isValidCharacter(c[j]))+ −
return false;+ −
}+ −
+ −
return true;+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidBusName(const QString &busName)+ −
Returns true if \a busName is a valid bus name.+ −
+ −
A valid bus name is either a valid unique connection name or follows the rules:+ −
\list+ −
\o is not empty+ −
\o does not exceed 255 characters in length+ −
\o be composed of dot-separated string components that contain only ASCII letters, digits,+ −
hyphens or underscores ("_"), but don't start with a digit+ −
\o contains at least two such elements+ −
\endlist+ −
+ −
\sa isValidUniqueConnectionName()+ −
*/+ −
bool isValidBusName(const QString &busName)+ −
{+ −
if (busName.isEmpty() || busName.length() > DBUS_MAXIMUM_NAME_LENGTH)+ −
return false;+ −
+ −
if (busName.startsWith(QLatin1Char(':')))+ −
return isValidUniqueConnectionName(busName);+ −
+ −
QStringList parts = busName.split(QLatin1Char('.'));+ −
if (parts.count() < 1)+ −
return false;+ −
+ −
for (int i = 0; i < parts.count(); ++i) {+ −
const QString &part = parts.at(i);+ −
if (part.isEmpty())+ −
return false;+ −
+ −
const QChar *c = part.unicode();+ −
if (isValidNumber(c[0]))+ −
return false;+ −
for (int j = 0; j < part.length(); ++j)+ −
if (!isValidCharacter(c[j]))+ −
return false;+ −
}+ −
+ −
return true;+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidMemberName(const QString &memberName)+ −
Returns true if \a memberName is a valid member name. A valid member name does not exceed+ −
255 characters in length, is not empty, is composed only of ASCII letters, digits and+ −
underscores, but does not start with a digit.+ −
*/+ −
bool isValidMemberName(const QString &memberName)+ −
{+ −
if (memberName.isEmpty() || memberName.length() > DBUS_MAXIMUM_NAME_LENGTH)+ −
return false;+ −
+ −
const QChar* c = memberName.unicode();+ −
if (isValidNumber(c[0]))+ −
return false;+ −
for (int j = 0; j < memberName.length(); ++j)+ −
if (!isValidCharacterNoDash(c[j]))+ −
return false;+ −
return true;+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidErrorName(const QString &errorName)+ −
Returns true if \a errorName is a valid error name. Valid error names are valid interface+ −
names and vice-versa, so this function is actually an alias for isValidInterfaceName.+ −
*/+ −
bool isValidErrorName(const QString &errorName)+ −
{+ −
return isValidInterfaceName(errorName);+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidObjectPath(const QString &path)+ −
Returns true if \a path is valid object path.+ −
+ −
Valid object paths follow the rules:+ −
\list+ −
\o start with the slash character ("/")+ −
\o do not end in a slash, unless the path is just the initial slash+ −
\o do not contain any two slashes in sequence+ −
\o contain slash-separated parts, each of which is composed of ASCII letters, digits and+ −
underscores ("_")+ −
\endlist+ −
*/+ −
bool isValidObjectPath(const QString &path)+ −
{+ −
if (path == QLatin1String("/"))+ −
return true;+ −
+ −
if (!path.startsWith(QLatin1Char('/')) || path.indexOf(QLatin1String("//")) != -1 ||+ −
path.endsWith(QLatin1Char('/')))+ −
return false;+ −
+ −
QStringList parts = path.split(QLatin1Char('/'));+ −
Q_ASSERT(parts.count() >= 1);+ −
parts.removeFirst(); // it starts with /, so we get an empty first part+ −
+ −
for (int i = 0; i < parts.count(); ++i)+ −
if (!isValidPartOfObjectPath(parts.at(i)))+ −
return false;+ −
+ −
return true;+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidSignature(const QString &signature)+ −
Returns true if \a signature is a valid D-Bus type signature for one or more types.+ −
This function returns true if it can all of \a signature into valid, individual types and no+ −
characters remain in \a signature.+ −
+ −
\sa isValidSingleSignature()+ −
*/+ −
bool isValidSignature(const QString &signature)+ −
{+ −
return q_dbus_signature_validate(signature.toUtf8(), 0);+ −
}+ −
+ −
/*!+ −
\fn bool QDBusUtil::isValidSingleSignature(const QString &signature)+ −
Returns true if \a signature is a valid D-Bus type signature for exactly one full type. This+ −
function tries to convert the type signature into a D-Bus type and, if it succeeds and no+ −
characters remain in the signature, it returns true.+ −
*/+ −
bool isValidSingleSignature(const QString &signature)+ −
{+ −
return q_dbus_signature_validate_single(signature.toUtf8(), 0);+ −
}+ −
+ −
} // namespace QDBusUtil+ −
+ −
QT_END_NAMESPACE+ −
+ −
#endif // QT_NO_DBUS+ −