summaryrefslogtreecommitdiff
path: root/xmlrpcinterface.cpp
blob: acda0f68e800ba454562af26bc86fb1ffaae3c24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <QtCore/QDateTime>
#include <QtCore/QDebug>
#include <QtNetwork/QNetworkRequest>

#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<QVariant> &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<QVariant> &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
}