diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-10 08:07:35 +0000 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-10 08:07:35 +0000 |
| commit | 1d726c6fd2ac9a0e57fbc661c1d66273ff385ea1 (patch) | |
| tree | 61d73f5ef6b173c9798a3134fe20b8d962f00a08 /source | |
| parent | 1147c4f57591397a53bc045ae77106e337c2d940 (diff) | |
| download | qxmpp-1d726c6fd2ac9a0e57fbc661c1d66273ff385ea1.tar.gz | |
merge xmlrpc.cpp into QXmppRpcIq.cpp
Diffstat (limited to 'source')
| -rw-r--r-- | source/QXmppRpcIq.cpp | 249 | ||||
| -rw-r--r-- | source/QXmppRpcIq.h | 6 | ||||
| -rw-r--r-- | source/source.pro | 6 | ||||
| -rw-r--r-- | source/xmlrpc.cpp | 302 | ||||
| -rw-r--r-- | source/xmlrpc.h | 106 |
5 files changed, 239 insertions, 430 deletions
diff --git a/source/QXmppRpcIq.cpp b/source/QXmppRpcIq.cpp index e812cf4e..94848010 100644 --- a/source/QXmppRpcIq.cpp +++ b/source/QXmppRpcIq.cpp @@ -22,12 +22,169 @@ * */ +#include <QDebug> +#include <QDomElement> +#include <QMap> +#include <QVariant> +#include <QDateTime> +#include <QStringList> + #include "QXmppConstants.h" #include "QXmppRpcIq.h" #include "QXmppUtils.h" -#include "xmlrpc.h" -#include <QDomElement> +void XMLRPC::marshall(QXmlStreamWriter *writer, const QVariant &value) +{ + writer->writeStartElement("value"); + switch( value.type() ) + { + case QVariant::Int: + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + writer->writeTextElement("i4", value.toString()); + break; + case QVariant::Double: + writer->writeTextElement("double", value.toString()); + break; + case QVariant::Bool: + writer->writeTextElement("boolean", value.toBool() ? "1" : "0"); + break; + case QVariant::Date: + writer->writeTextElement("dateTime.iso8601", value.toDate().toString( Qt::ISODate ) ); + break; + case QVariant::DateTime: + writer->writeTextElement("dateTime.iso8601", value.toDateTime().toString( Qt::ISODate ) ); + break; + case QVariant::Time: + writer->writeTextElement("dateTime.iso8601", value.toTime().toString( Qt::ISODate ) ); + break; + case QVariant::StringList: + case QVariant::List: + { + writer->writeStartElement("array"); + writer->writeStartElement("data"); + foreach(const QVariant &item, value.toList()) + marshall(writer, item); + writer->writeEndElement(); + writer->writeEndElement(); + break; + } + case QVariant::Map: + { + writer->writeStartElement("struct"); + QMap<QString, QVariant> map = value.toMap(); + QMap<QString, QVariant>::ConstIterator index = map.begin(); + while( index != map.end() ) + { + writer->writeStartElement("member"); + writer->writeTextElement("name", index.key()); + marshall( writer, *index ); + writer->writeEndElement(); + ++index; + } + writer->writeEndElement(); + break; + } + case QVariant::ByteArray: + { + writer->writeTextElement("base64", value.toByteArray().toBase64() ); + break; + } + default: + { + if (value.isNull()) + writer->writeEmptyElement("nil"); + else if( value.canConvert(QVariant::String) ) + { + writer->writeTextElement("string", value.toString() ); + } + break; + } + } + writer->writeEndElement(); +} + +QVariant XMLRPC::demarshall(const QDomElement &elem, QStringList &errors) +{ + if ( elem.tagName().toLower() != "value" ) + { + errors << "Bad param value"; + return QVariant(); + } + + if ( !elem.firstChild().isElement() ) + { + return QVariant( elem.text() ); + } + + const QDomElement typeData = elem.firstChild().toElement(); + const QString typeName = typeData.tagName().toLower(); + + if (typeName == "nil") + { + return QVariant(); + } + if ( typeName == "string" ) + { + return QVariant( typeData.text() ); + } + else if (typeName == "int" || typeName == "i4" ) + { + bool ok = false; + QVariant val( typeData.text().toInt( &ok ) ); + if (ok) + return val; + errors << "I was looking for an integer but data was courupt"; + return QVariant(); + } + else if( typeName == "double" ) + { + bool ok = false; + QVariant val( typeData.text().toDouble( &ok ) ); + if (ok) + return val; + errors << "I was looking for an double but data was corrupt"; + } + else if( typeName == "boolean" ) + return QVariant( typeData.text() == "1" || typeData.text().toLower() == "true" ); + else if( typeName == "datetime" || typeName == "datetime.iso8601" ) + return QVariant( QDateTime::fromString( typeData.text(), Qt::ISODate ) ); + else if( typeName == "array" ) + { + QVariantList arr; + QDomElement valueNode = typeData.firstChildElement("data").firstChildElement(); + while (!valueNode.isNull() && errors.isEmpty()) + { + arr.append(demarshall(valueNode, errors)); + valueNode = valueNode.nextSiblingElement(); + } + return QVariant( arr ); + } + else if( typeName == "struct" ) + { + QMap<QString,QVariant> stct; + QDomNode valueNode = typeData.firstChild(); + while(!valueNode.isNull() && errors.isEmpty()) + { + const QDomElement memberNode = valueNode.toElement().elementsByTagName("name").item(0).toElement(); + const QDomElement dataNode = valueNode.toElement().elementsByTagName("value").item(0).toElement(); + stct[ memberNode.text() ] = demarshall(dataNode, errors); + valueNode = valueNode.nextSibling(); + } + return QVariant(stct); + } + else if( typeName == "base64" ) + { + QVariant returnVariant; + QByteArray dest; + QByteArray src = typeData.text().toLatin1(); + return QVariant(QByteArray::fromBase64(src)); + } + + errors << QString( "Cannot handle type %1").arg(typeName); + return QVariant(); +} QXmppRpcErrorIq::QXmppRpcErrorIq() : QXmppIq( QXmppIq::Error ) { @@ -91,9 +248,30 @@ void QXmppRpcResponseIq::parseElementFromChild(const QDomElement &element) QDomElement queryElement = element.firstChildElement("query"); QDomElement methodElement = queryElement.firstChildElement("methodResponse"); - XMLRPC::ResponseMessage message; - if (message.parse(methodElement)) - m_values = message.values(); + const QDomElement contents = methodElement.firstChildElement(); + if( contents.tagName().toLower() == "params") + { + QDomNode param = contents.firstChildElement("param"); + while (!param.isNull()) + { + QStringList errors; + const QVariant value = XMLRPC::demarshall(param.firstChildElement(), errors); + if (!errors.isEmpty()) + break; + m_values << value; + param = param.nextSiblingElement("param"); + } + } + else if( contents.tagName().toLower() == "fault") + { + QStringList errors; + const QDomElement errElement = contents.firstChildElement(); + const QVariant error = XMLRPC::demarshall(errElement, errors); + + qWarning() << QString("XMLRPC Fault %1: %2") + .arg(error.toMap()["faultCode"].toString() ) + .arg(error.toMap()["faultString"].toString() ); + } } void QXmppRpcResponseIq::toXmlElementFromChild(QXmlStreamWriter *writer) const @@ -101,9 +279,19 @@ void QXmppRpcResponseIq::toXmlElementFromChild(QXmlStreamWriter *writer) const writer->writeStartElement("query"); helperToXmlAddAttribute(writer, "xmlns", ns_rpc); - XMLRPC::ResponseMessage message; - message.setValues(m_values); - message.writeXml(writer); + writer->writeStartElement("methodResponse"); + if (!m_values.isEmpty()) + { + writer->writeStartElement("params"); + foreach (const QVariant &arg, m_values) + { + writer->writeStartElement("param"); + XMLRPC::marshall(writer, arg); + writer->writeEndElement(); + } + writer->writeEndElement(); + } + writer->writeEndElement(); writer->writeEndElement(); } @@ -154,12 +342,27 @@ void QXmppRpcInvokeIq::parseElementFromChild(const QDomElement &element) QDomElement queryElement = element.firstChildElement("query"); QDomElement methodElement = queryElement.firstChildElement("methodCall"); - XMLRPC::RequestMessage message; - if (message.parse(methodElement)) + const QString methodName = methodElement.firstChildElement("methodName").text(); + if (methodName.count('.') == 1) + { + m_interface = methodName.split('.').first(); + m_method = methodName.split('.').last(); + } + + const QDomElement methodParams = methodElement.firstChildElement("params"); + m_arguments.clear(); + if( !methodParams.isNull() ) { - m_interface = message.method().split('.').value(0); - m_method = message.method().split('.').value(1); - m_arguments = message.arguments(); + QDomNode param = methodParams.firstChildElement("param"); + while (!param.isNull()) + { + QStringList errors; + QVariant arg = XMLRPC::demarshall(param.firstChildElement(), errors); + if (!errors.isEmpty()) + break; + m_arguments << arg; + param = param.nextSiblingElement("param"); + } } } @@ -168,12 +371,22 @@ void QXmppRpcInvokeIq::toXmlElementFromChild(QXmlStreamWriter *writer) const writer->writeStartElement("query"); helperToXmlAddAttribute(writer, "xmlns", ns_rpc); - QString methodName = m_interface + "." + m_method; - XMLRPC::RequestMessage message; - message.setMethod(methodName.toLatin1()); - message.setArguments(m_arguments); - message.writeXml(writer); + writer->writeStartElement("methodCall"); + writer->writeTextElement("methodName", m_interface + "." + m_method); + if (!m_arguments.isEmpty()) + { + writer->writeStartElement("params"); + foreach(const QVariant &arg, m_arguments) + { + writer->writeStartElement("param"); + XMLRPC::marshall(writer, arg); + writer->writeEndElement(); + } + writer->writeEndElement(); + } + writer->writeEndElement(); writer->writeEndElement(); } + diff --git a/source/QXmppRpcIq.h b/source/QXmppRpcIq.h index 0594f27d..1f92f086 100644 --- a/source/QXmppRpcIq.h +++ b/source/QXmppRpcIq.h @@ -31,6 +31,12 @@ class QXmlStreamWriter; class QDomElement; +namespace XMLRPC +{ + void marshall( QXmlStreamWriter *writer, const QVariant &value); + QVariant demarshall(const QDomElement &elem, QStringList &errors); +} + class QXmppRpcResponseIq : public QXmppIq { public: diff --git a/source/source.pro b/source/source.pro index e7961bd5..a3bdcada 100644 --- a/source/source.pro +++ b/source/source.pro @@ -62,8 +62,7 @@ HEADERS += QXmppUtils.h \ QXmppRpcIq.h \ QXmppVCardManager.h \ QXmppVCard.h \ - QXmppVersionIq.h \ - xmlrpc.h + QXmppVersionIq.h # Source files SOURCES += QXmppUtils.cpp \ @@ -105,8 +104,7 @@ SOURCES += QXmppUtils.cpp \ QXmppRpcIq.cpp \ QXmppVCardManager.cpp \ QXmppVCard.cpp \ - QXmppVersionIq.cpp \ - xmlrpc.cpp + QXmppVersionIq.cpp # Installation PREFIX = /usr diff --git a/source/xmlrpc.cpp b/source/xmlrpc.cpp deleted file mode 100644 index 20ca2718..00000000 --- a/source/xmlrpc.cpp +++ /dev/null @@ -1,302 +0,0 @@ -#include "xmlrpc.h" -#include <QDebug> -#include <QMap> -#include <QVariant> -#include <QDateTime> -#include <QStringList> -#include <QTextStream> - -void XMLRPC::marshall( QXmlStreamWriter *writer, const QVariant &value) -{ - writer->writeStartElement("value"); - switch( value.type() ) - { - case QVariant::Int: - case QVariant::UInt: - case QVariant::LongLong: - case QVariant::ULongLong: - writer->writeTextElement("i4", value.toString()); - break; - case QVariant::Double: - writer->writeTextElement("double", value.toString()); - break; - case QVariant::Bool: - writer->writeTextElement("boolean", value.toBool() ? "1" : "0"); - break; - case QVariant::Date: - writer->writeTextElement("dateTime.iso8601", value.toDate().toString( Qt::ISODate ) ); - break; - case QVariant::DateTime: - writer->writeTextElement("dateTime.iso8601", value.toDateTime().toString( Qt::ISODate ) ); - break; - case QVariant::Time: - writer->writeTextElement("dateTime.iso8601", value.toTime().toString( Qt::ISODate ) ); - break; - case QVariant::StringList: - case QVariant::List: - { - writer->writeStartElement("array"); - writer->writeStartElement("data"); - foreach(const QVariant &item, value.toList()) - marshall(writer, item); - writer->writeEndElement(); - writer->writeEndElement(); - break; - } - case QVariant::Map: - { - writer->writeStartElement("struct"); - QMap<QString, QVariant> map = value.toMap(); - QMap<QString, QVariant>::ConstIterator index = map.begin(); - while( index != map.end() ) - { - writer->writeStartElement("member"); - writer->writeTextElement("name", index.key()); - marshall( writer, *index ); - writer->writeEndElement(); - ++index; - } - writer->writeEndElement(); - break; - } - case QVariant::ByteArray: - { - writer->writeTextElement("base64", value.toByteArray().toBase64() ); - break; - } - default: - { - if (value.isNull()) - writer->writeEmptyElement("nil"); - else if( value.canConvert(QVariant::String) ) - { - writer->writeTextElement("string", value.toString() ); - } - break; - } - } - writer->writeEndElement(); -} - -QVariant XMLRPC::demarshall(const QDomElement &elem, QStringList &errors) -{ - if ( elem.tagName().toLower() != "value" ) - { - errors << "Bad param value"; - return QVariant(); - } - - if ( !elem.firstChild().isElement() ) - { - return QVariant( elem.text() ); - } - - const QDomElement typeData = elem.firstChild().toElement(); - const QString typeName = typeData.tagName().toLower(); - - if (typeName == "nil") - { - return QVariant(); - } - if ( typeName == "string" ) - { - return QVariant( typeData.text() ); - } - else if (typeName == "int" || typeName == "i4" ) - { - bool ok = false; - QVariant val( typeData.text().toInt( &ok ) ); - if (ok) - return val; - errors << "I was looking for an integer but data was courupt"; - return QVariant(); - } - else if( typeName == "double" ) - { - bool ok = false; - QVariant val( typeData.text().toDouble( &ok ) ); - if (ok) - return val; - errors << "I was looking for an double but data was corrupt"; - } - else if( typeName == "boolean" ) - return QVariant( typeData.text() == "1" || typeData.text().toLower() == "true" ); - else if( typeName == "datetime" || typeName == "datetime.iso8601" ) - return QVariant( QDateTime::fromString( typeData.text(), Qt::ISODate ) ); - else if( typeName == "array" ) - { - QVariantList arr; - QDomElement valueNode = typeData.firstChildElement("data").firstChildElement(); - while (!valueNode.isNull() && errors.isEmpty()) - { - arr.append(demarshall(valueNode, errors)); - valueNode = valueNode.nextSiblingElement(); - } - return QVariant( arr ); - } - else if( typeName == "struct" ) - { - QMap<QString,QVariant> stct; - QDomNode valueNode = typeData.firstChild(); - while(!valueNode.isNull() && errors.isEmpty()) - { - const QDomElement memberNode = valueNode.toElement().elementsByTagName("name").item(0).toElement(); - const QDomElement dataNode = valueNode.toElement().elementsByTagName("value").item(0).toElement(); - stct[ memberNode.text() ] = demarshall(dataNode, errors); - valueNode = valueNode.nextSibling(); - } - return QVariant(stct); - } - else if( typeName == "base64" ) - { - QVariant returnVariant; - QByteArray dest; - QByteArray src = typeData.text().toLatin1(); - dest = QByteArray::fromBase64( src ); - QDataStream ds(&dest, QIODevice::ReadOnly); - ds.setVersion(QDataStream::Qt_4_0); - ds >> returnVariant; - if (returnVariant.isValid()) - return returnVariant; - else - return QVariant( dest ); - } - - errors << QString( "Cannot handle type %1").arg(typeName); - return QVariant(); -} - -bool XMLRPC::RequestMessage::parse(const QDomElement &element) -{ - QStringList errors; - - m_args.clear(); - m_method.clear(); - - const QDomElement methodName = element.firstChildElement("methodName"); - if( !methodName.isNull() ) - { - m_method = methodName.text().toLatin1(); - } - else - { - errors << "Missing methodName property"; - return false; - } - - const QDomElement methodParams = element.firstChildElement("params"); - if( !methodParams.isNull() ) - { - QDomNode param = methodParams.firstChildElement("param"); - while (!param.isNull()) - { - QVariant arg = demarshall(param.firstChild().toElement(), errors); - if (!errors.isEmpty()) - return false; - m_args << arg; - param = param.nextSiblingElement("param"); - } - } - return true; -} - -QVariantList XMLRPC::RequestMessage::arguments() const -{ - return m_args; -} - -void XMLRPC::RequestMessage::setArguments(const QVariantList &args) -{ - m_args = args; -} - -QByteArray XMLRPC::RequestMessage::method() const -{ - return m_method; -} - -void XMLRPC::RequestMessage::setMethod(const QByteArray &method) -{ - m_method = method; -} - -void XMLRPC::RequestMessage::writeXml( QXmlStreamWriter *writer ) const -{ - writer->writeStartElement("methodCall"); - writer->writeTextElement("methodName", m_method ); - if( !m_args.isEmpty() ) - { - writer->writeStartElement("params"); - foreach(const QVariant &arg, m_args) - { - writer->writeStartElement("param"); - marshall(writer, arg); - writer->writeEndElement(); - } - writer->writeEndElement(); - } - writer->writeEndElement(); -} - -bool XMLRPC::ResponseMessage::parse(const QDomElement &element) -{ - QStringList errors; - const QDomElement contents = element.firstChild().toElement(); - if( contents.tagName().toLower() == "params") - { - QDomNode param = contents.firstChildElement("param"); - while (!param.isNull()) - { - const QVariant value = demarshall(param.firstChildElement(), errors); - if (!errors.isEmpty()) - return false; - m_values << value; - param = param.nextSiblingElement("param"); - } - return true; - } - else if( contents.tagName().toLower() == "fault") - { - const QDomElement errElement = contents.firstChildElement(); - const QVariant error = demarshall(errElement, errors); - - qWarning() << QString("XMLRPC Fault %1: %2") - .arg(error.toMap()["faultCode"].toString() ) - .arg(error.toMap()["faultString"].toString() ); - return true; - } - else - { - qWarning("Bad XML response"); - return false; - } -} - -QVariantList XMLRPC::ResponseMessage::values() const -{ - return m_values; -} - -void XMLRPC::ResponseMessage::setValues(const QVariantList &values) -{ - m_values = values; -} - -void XMLRPC::ResponseMessage::writeXml( QXmlStreamWriter *writer ) const -{ - writer->writeStartElement("methodResponse"); - - if( !m_values.isEmpty() ) - { - writer->writeStartElement("params"); - foreach (const QVariant &arg, m_values) - { - writer->writeStartElement("param"); - marshall(writer, arg); - writer->writeEndElement(); - } - writer->writeEndElement(); - } - writer->writeEndElement(); -} - diff --git a/source/xmlrpc.h b/source/xmlrpc.h deleted file mode 100644 index e96a2ae3..00000000 --- a/source/xmlrpc.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef QXMPPXMLRPC_H -#define QXMPPXMLRPC_H - -#include <QDomElement> -#include <QVariant> -#include <QXmlStreamWriter> - -/** -* Packets are serialized QVariants that map to XMLRPC types. -* @li int -> int -* @li double -> double,float -* @li string -> QString, QCString, char *, QColor, QFont -* @li datetime.iso8601 -> QDateTime, QTime, QDate -* @li array -> QList<QVariant>, QStringList -* @li struct -> QMap<QVariant> -* @li base64 -> QByteArray -* -* An example of how to use the XML Packets is as follows: -* @code -* QList<QVariant> args; -* args << m_db << m_username << m_password << dbQuery; -* RequestMessage msg; -* msg.setMethod("data.query"); -* msg.setArguments(args); -* -* ResponseMessage resp; -* if (resp.parse(someDomElement)) -* { -* int rows = resp.values().first().toMap()["widgets"].toInt(); -* } -* else -* qWarning("Error: %s", resp.error().latin1() ); -* @endcode -* -* This example will construct invoke the data.query() method on the XMLRPC -* interface with the args. It will then check for the response to see if -* it was valid. If its valid the message contains a struct of values, one of -* which is "widgets" that is an integer. The struct is converted to a QVariant -* map and we can convert it as such from the QVariant. We can then get the -* QVariant for the "widgets" value and convert that to an integer. If there was -* an error, the packet is marked invalid and will have an error message in it. The -* error() message will return this message. The struct in the value will be a valid -* error structure so it can be dealt with accordingly. -*/ - -namespace XMLRPC -{ - -void marshall( QXmlStreamWriter *writer, const QVariant &value); -QVariant demarshall(const QDomElement &elem, QStringList &errors); - -/** -* Creates an XMLRPC message that will call a method with a series of -* QVariants that will be converted to XMLRPC types. -@author Ian Reinhart Geiser <geiseri@kde.org> -*/ -class RequestMessage -{ -public: - /** - * Parse an xml packet. - */ - bool parse(const QDomElement &element); - - /** - * Return the xml representation of the packet. - */ - void writeXml( QXmlStreamWriter *writer ) const; - - QByteArray method() const; - void setMethod(const QByteArray &method); - - QVariantList arguments() const; - void setArguments(const QVariantList &args); - -private: - QByteArray m_method; - QVariantList m_args; -}; - -/** -* Decodes an XMLRPC message from a server into a set of QVariants. -@author Ian Reinhart Geiser <geiseri@kde.org> -*/ -class ResponseMessage -{ -public: - /** - * Parse an xml packet. - */ - bool parse(const QDomElement &element); - - /** - * Return the xml representation of the packet. - */ - void writeXml( QXmlStreamWriter *writer ) const; - - QVariantList values() const; - void setValues(const QVariantList &values); - -private: - QList<QVariant> m_values; -}; - -} -#endif |
