#include #include #include #include "xmlrpcinterface.h" XmlRpcInterface::XmlRpcInterface(const QUrl& endpoint, QObject *parent) : QObject(parent), _endpoint(endpoint), _manager(new QNetworkAccessManager(this)) { } XmlRpcPendingCall *XmlRpcInterface::asyncCallWithArgumentList(const QString &method, const QList &args) { QNetworkRequest request(_endpoint); QByteArray data = encodeCall(method, args); request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml"); request.setRawHeader("User-Agent", "Tapasboard/1.0"); #if XML_RPC_DEBUG qDebug() << "Request:" << data; #endif QNetworkReply *reply = _manager->post(request, data); return new XmlRpcPendingCall(reply, this); } QByteArray XmlRpcInterface::encodeCall(const QString &method, const QList &args) { QByteArray buffer; QXmlStreamWriter writer(&buffer); writer.writeStartDocument(); writer.writeStartElement("methodCall"); writer.writeTextElement("methodName", method); if (!args.isEmpty()) { writer.writeStartElement("params"); foreach (const QVariant& arg, args) { writer.writeStartElement("param"); encodeValue(&writer, arg); writer.writeEndElement(); // param } writer.writeEndElement(); // params } writer.writeEndElement(); // methodCall writer.writeEndDocument(); return buffer; } void XmlRpcInterface::encodeValue(QXmlStreamWriter *w, const QVariant &value) { w->writeStartElement("value"); switch (value.type()) { case QVariant::String: w->writeTextElement("string", value.toString()); break; case QVariant::Int: w->writeTextElement("int", value.toString()); break; case QVariant::Bool: w->writeTextElement("boolean", value.toBool() ? "1" : "0"); break; case QVariant::Double: w->writeTextElement("double", value.toString()); break; case QVariant::DateTime: w->writeTextElement("dateTime.iso8601", value.toDateTime().toString(Qt::ISODate)); break; case QVariant::ByteArray: w->writeTextElement("base64", value.toByteArray().toBase64()); break; case QVariant::List: w->writeStartElement("array"); w->writeStartElement("data"); { QVariantList list = value.toList(); foreach (const QVariant& v, list) { encodeValue(w, v); } } w->writeEndElement(); // data w->writeEndElement(); // array break; case QVariant::Map: w->writeStartElement("struct"); { QVariantMap map = value.toMap(); for (QVariantMap::Iterator i = map.begin(); i != map.end(); i++) { w->writeStartElement("member"); w->writeTextElement("name", i.key()); encodeValue(w, i.value()); w->writeEndElement(); // member } } w->writeEndElement(); // struct break; default: qWarning() << "Unhandled value type:" << value.typeName(); break; } w->writeEndElement(); // value }