diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /src/dbus/qdbusutil.cpp | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'src/dbus/qdbusutil.cpp')
-rw-r--r-- | src/dbus/qdbusutil.cpp | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp new file mode 100644 index 0000000..471b899 --- /dev/null +++ b/src/dbus/qdbusutil.cpp @@ -0,0 +1,468 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdbusutil_p.h" + +#include <qdbus_symbols_p.h> + +#include <QtCore/qstringlist.h> + +#include "qdbusargument.h" + +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 += QLatin1String("{"); + QStringList list = arg.toStringList(); + foreach (QString item, list) + out += QLatin1Char('\"') + item + QLatin1String("\", "); + if (!list.isEmpty()) + out.chop(2); + out += QLatin1String("}"); + } else if (argType == QVariant::ByteArray) { + out += QLatin1String("{"); + 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 += QLatin1String("}"); + } else if (argType == QVariant::List) { + out += QLatin1String("{"); + QList<QVariant> list = arg.toList(); + foreach (QVariant item, list) { + if (!variantToString(item, out)) + return false; + out += QLatin1String(", "); + } + if (!list.isEmpty()) + out.chop(2); + out += QLatin1String("}"); + } 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 += QLatin1String("\"") + arg.toString() + QLatin1String("\""); + } 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 += QLatin1String("]"); + + 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 |