From 5ef8b38e55c1883224fe1f01f47aba45b7b42666 Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Mon, 1 Apr 2013 15:04:58 +0200 Subject: initial import --- xmlrpcpendingcall.cpp | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 xmlrpcpendingcall.cpp (limited to 'xmlrpcpendingcall.cpp') diff --git a/xmlrpcpendingcall.cpp b/xmlrpcpendingcall.cpp new file mode 100644 index 0000000..d94b76d --- /dev/null +++ b/xmlrpcpendingcall.cpp @@ -0,0 +1,187 @@ +#include +#include +#include + +#include "xmlrpcinterface.h" +#include "xmlrpcpendingcall.h" + +XmlRpcPendingCall::XmlRpcPendingCall(QNetworkReply *reply, XmlRpcInterface *parent) + : QObject(parent), _reply(reply), _state(StateWaitingReply) +{ + connect(_reply, SIGNAL(finished()), SLOT(handleRequestFinished())); + _reply->setParent(this); +} + +void XmlRpcPendingCall::waitForFinished() +{ + if (_state == StateWaitingReply) { + QEventLoop loop; + connect(this, SIGNAL(finished(XmlRpcPendingCall*)), &loop, SLOT(quit())); + loop.exec(); + } +} + +bool XmlRpcPendingCall::decodeMethodResponse(QXmlStreamReader *r) +{ + if (r->readNextStartElement()) { + if (r->name() == "fault") { + _state = StateFaultReceived; + if (r->readNextStartElement()) { + if (r->name() != "value") return false; + _value = decodeValue(r); + if (!_value.isValid()) return false; + } + return true; + } else if (r->name() == "params") { + _state = StateReplyReceived; + if (r->readNextStartElement()) { + if (r->name() != "param") return false; + if (r->readNextStartElement()) { + if (r->name() != "value") return false; + _value = decodeValue(r); + if (!_value.isValid()) return false; + } else { + return false; + } + } + return true; + } + } + + return false; +} + +QVariant XmlRpcPendingCall::decodeValue(QXmlStreamReader *r) +{ + Q_ASSERT(r->isStartElement() && r->name() == "value"); + QVariant value; + + if (r->readNextStartElement()) { + if (r->name() == "string") { + value = QVariant::fromValue(r->readElementText()); + } else if (r->name() == "int") { + bool ok; + value = QVariant::fromValue(r->readElementText().toInt(&ok)); + if (!ok) value.clear(); + } else if (r->name() == "boolean") { + bool ok; + value = QVariant::fromValue(r->readElementText().toInt(&ok)); + if (!ok) value.clear(); + } else if (r->name() == "double") { + bool ok; + value = QVariant::fromValue(r->readElementText().toDouble(&ok)); + if (!ok) value.clear(); + } else if (r->name() == "dateTime.iso8601") { + QString text = r->readElementText(); + QDateTime dateTime = QDateTime::fromString(text, Qt::ISODate); + if (!dateTime.isValid()) { + // Qt seems not be happy without dashes + text.insert(4, '-'); + text.insert(7, '-'); + dateTime = QDateTime::fromString(text, Qt::ISODate); + if (!dateTime.isValid()) { + qWarning() << "Invalid dateTime format" << text; + return QVariant(); + } + } + value = QVariant::fromValue(dateTime); + } else if (r->name() == "base64") { + QByteArray data = r->readElementText().toAscii(); + value = QVariant::fromValue(QByteArray::fromBase64(data)); + } else if (r->name() == "array") { + QList list; + if (!r->readNextStartElement() || r->name() != "data") { + qWarning() << "Unexpected element inside :" << r->name(); + return QVariant(); + } + while (r->readNextStartElement()) { + if (r->name() != "value") return QVariant(); + QVariant value = decodeValue(r); + if (!value.isValid()) return QVariant(); + list.append(value); + } + if (r->readNextStartElement()) { + // No other elements + qWarning() << "Unexpected element inside :" << r->name(); + return QVariant(); + } + value = QVariant::fromValue(list); + } else if (r->name() == "struct") { + QMap map; + while (r->readNextStartElement()) { + if (r->name() != "member") return QVariant(); + QString name; + if (r->readNextStartElement() && r->name() == "name") { + name = r->readElementText(); + } else { + qWarning() << "Malformed struct"; + return QVariant(); + } + if (r->readNextStartElement() && r->name() == "value") { + QVariant value = decodeValue(r); + if (!value.isValid()) return QVariant(); + map.insert(name, value); + } else { + qWarning() << "Malformed struct"; + return QVariant(); + } + if (r->readNextStartElement()) { + // No other elements + qWarning() << "Unexpected element inside " << r->name(); + return false; + } + } + value = QVariant::fromValue(map); + } else { + qWarning() << "Unknown value type:" << r->name(); + } + } + + if (r->readNextStartElement()) { + // There is more than one element inside this + qWarning() << "More than element inside "; + return QVariant(); + } else if (r->isEndElement() && r->name() == "value") { + // Everything OK + return value; + } else { + qWarning() << "Expected instead of" << r->name(); + return QVariant(); + } +} + +void XmlRpcPendingCall::handleRequestFinished() +{ + Q_ASSERT(_state == StateWaitingReply); + + QNetworkReply::NetworkError error = _reply->error(); + if (error == QNetworkReply::NoError) { + QByteArray data = _reply->readAll(); + QXmlStreamReader reader(data); + bool parse_ok = false; + if (reader.readNextStartElement()) { + if (reader.name() == "methodResponse") { + parse_ok = decodeMethodResponse(&reader); + } + } + if (parse_ok) { + Q_ASSERT(_state == StateReplyReceived || _state == StateFaultReceived); + } else { + qWarning() << "Parse error!"; + QVariantMap obj; + obj.insert("code", QVariant(reader.error())); + obj.insert("message", QVariant(reader.errorString())); + _value = obj; + _state = StateParseError; + } + } else { + qWarning() << "Network error!" << error; + QVariantMap obj; + obj.insert("code", QVariant(error)); + obj.insert("message", QVariant(_reply->errorString())); + _value = obj; + _state = StateNetworkError; + } + + emit finished(this); +} -- cgit v1.2.3