24 #include <klocalizedstring.h>
27 #include <QtCore/QDateTime>
28 #include <QtCore/QVariant>
29 #include <QtXml/QDomDocument>
31 using namespace KXmlRpc;
52 friend class Query::Private;
78 int errorCode()
const;
101 KXmlRpc::Result::Result()
105 KXmlRpc::Result::~Result()
109 bool KXmlRpc::Result::success()
const
114 int KXmlRpc::Result::errorCode()
const
119 QString KXmlRpc::Result::errorString()
const
137 bool isMessageResponse(
const QDomDocument &doc )
const;
140 Result parseMessageResponse(
const QDomDocument &doc )
const;
141 Result parseFaultResponse(
const QDomDocument &doc )
const;
147 void slotData( KIO::Job *job,
const QByteArray &data );
148 void slotResult( KJob *job );
156 bool Query::Private::isMessageResponse(
const QDomDocument &doc )
const
162 bool Query::Private::isFaultResponse(
const QDomDocument &doc )
const
168 Result Query::Private::parseMessageResponse(
const QDomDocument &doc )
const
171 response.mSuccess =
true;
174 while ( !paramNode.
isNull() ) {
182 Result Query::Private::parseFaultResponse(
const QDomDocument &doc )
const
185 response.mSuccess =
false;
189 response.mErrorCode = errorVariant.
toMap() [
"faultCode" ].toInt();
190 response.mErrorString = errorVariant.
toMap() [
"faultString" ].toString();
198 QString markup =
"<?xml version=\"1.0\" ?>\r\n<methodCall>\r\n";
200 markup +=
"<methodName>" + cmd +
"</methodName>\r\n";
204 markup +=
"<params>\r\n";
207 for ( ; it != end; ++it ) {
208 markup +=
"<param>\r\n" + marshal( *it ) +
"</param>\r\n";
210 markup +=
"</params>\r\n";
213 markup +=
"</methodCall>\r\n";
220 switch ( arg.
type() ) {
222 case QVariant::String:
223 return "<value><string><![CDATA[" + arg.
toString() +
"]]></string></value>\r\n";
224 case QVariant::StringList:
227 QStringListIterator dataIterator( data );
229 markup +=
"<value><array><data>";
230 while ( dataIterator.hasNext() ) {
231 markup +=
"<value><string><![CDATA[" + dataIterator.next() +
"]]></string></value>\r\n";
233 markup +=
"</data></array></value>";
238 case QVariant::Double:
242 QString markup =
"<value><boolean>";
243 markup += arg.
toBool() ?
"1" :
"0";
244 markup +=
"</boolean></value>\r\n";
247 case QVariant::ByteArray:
249 case QVariant::DateTime:
251 return "<value><dateTime.iso8601>" +
253 "</dateTime.iso8601></value>\r\n";
257 QString markup =
"<value><array><data>\r\n";
261 for ( ; it != end; ++it ) {
262 markup += marshal( *it );
264 markup +=
"</data></array></value>\r\n";
269 QString markup =
"<value><struct>\r\n";
273 for ( ; it != end; ++it ) {
274 markup +=
"<member>\r\n";
275 markup +=
"<name>" + it.
key() +
"</name>\r\n";
276 markup += marshal( it.
value() );
277 markup +=
"</member>\r\n";
279 markup +=
"</struct></value>\r\n";
283 kWarning() <<
"Failed to marshal unknown variant type:" << arg.
type();
296 if ( typeName ==
"string" ) {
297 return QVariant( typeElement.text() );
298 }
else if ( typeName ==
"i4" || typeName ==
"int" ) {
299 return QVariant( typeElement.text().toInt() );
300 }
else if ( typeName ==
"double" ) {
301 return QVariant( typeElement.text().toDouble() );
302 }
else if ( typeName ==
"boolean" ) {
304 if ( typeElement.text().toLower() ==
"true" || typeElement.text() ==
"1" ) {
309 }
else if ( typeName ==
"base64" ) {
311 }
else if ( typeName ==
"datetime" || typeName ==
"datetime.iso8601" ) {
313 QString dateText = typeElement.text();
315 if ( 17 <= dateText.
length() && dateText.
length() <= 18 &&
316 dateText.
at( 4 ) !=
'-' && dateText.
at( 11 ) ==
':' ) {
326 }
else if ( typeName ==
"array" ) {
329 while ( !valueNode.
isNull() ) {
330 values << demarshal( valueNode.
toElement() );
334 }
else if ( typeName ==
"struct" ) {
338 while ( !memberNode.
isNull() ) {
348 kWarning() <<
"Cannot demarshal unknown type" << typeName;
353 void Query::Private::slotData( KIO::Job *,
const QByteArray &data )
355 unsigned int oldSize = mBuffer.size();
356 mBuffer.resize( oldSize + data.
size() );
357 memcpy( mBuffer.data() + oldSize, data.
data(), data.
size() );
360 void Query::Private::slotResult( KJob *job )
362 mPendingJobs.removeAll( job );
364 if ( job->error() != 0 ) {
365 emit mParent->fault( job->error(), job->errorString(), mId );
366 emit mParent->finished( mParent );
373 if ( !doc.
setContent( mBuffer,
false, &errMsg, &errLine, &errCol ) ) {
374 emit mParent->fault( -1, i18n(
"Received invalid XML markup: %1 at %2:%3",
375 errMsg, errLine, errCol ), mId );
376 emit mParent->finished( mParent );
382 if ( isMessageResponse( doc ) ) {
383 emit mParent->message( parseMessageResponse( doc ).data(), mId );
384 }
else if ( isFaultResponse( doc ) ) {
385 emit mParent->fault( parseFaultResponse( doc ).errorCode(),
386 parseFaultResponse( doc ).errorString(), mId );
388 emit mParent->fault( 1, i18n(
"Unknown type of XML markup received" ),
392 emit mParent->finished( mParent );
397 return new Query(
id, parent );
406 const QString xmlMarkup = d->markupCall( method, args );
410 QDataStream stream( &postData, QIODevice::WriteOnly );
413 KIO::TransferJob *job = KIO::http_post( KUrl( server ), postData, KIO::HideProgressInfo );
416 kWarning() <<
"Unable to create KIO job for" << server;
420 job->addMetaData(
"content-type",
"Content-Type: text/xml; charset=utf-8" );
421 job->addMetaData(
"ConnectTimeout",
"50" );
423 for ( mapIter = jobMetaData.
begin(); mapIter != jobMetaData.
end(); ++mapIter ) {
424 job->addMetaData( mapIter.key(), mapIter.value() );
429 connect( job, SIGNAL(result(KJob*)),
430 this, SLOT(slotResult(KJob*)) );
432 d->mPendingJobs.append( job );
436 :
QObject( parent ), d( new Private( this ) )
444 for ( it = d->mPendingJobs.begin(); it != d->mPendingJobs.end(); ++it ) {
450 #include "moc_query.cpp"
QDomNodeList elementsByTagName(const QString &tagname) const
QString toString(Qt::DateFormat format) const
QByteArray toByteArray() const
QDomNode item(int index) const
void truncate(int position)
QList< QVariant > toList() const
QDateTime toDateTime() const
const_iterator constBegin() const
QDomElement documentElement() const
QDomNode nextSibling() const
This file is part of KXmlRpc and defines our internal classes.
QDomElement toElement() const
Query is a class that represents an individual XML-RPC call.
QString number(int n, int base)
int toInt(bool *ok) const
const_iterator constEnd() const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QFuture< void > map(Sequence &sequence, MapFunction function)
void call(const QString &server, const QString &method, const QList< QVariant > &args, const QMap< QString, QString > &jobMetaData)
Calls the specified method on the specified server with the given argument list.
QDateTime fromString(const QString &string, Qt::DateFormat format)
const Key key(const T &value) const
QDomNode firstChild() const
QMap< QString, QVariant > toMap() const
QStringList toStringList() const
QByteArray fromBase64(const QByteArray &base64)
const QChar at(int position) const
int writeRawData(const char *s, int len)
double toDouble(bool *ok) const
QByteArray toBase64() const
static Query * create(const QVariant &id=QVariant(), QObject *parent=0)
Constructs a query.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
const T value(const Key &key) const
QByteArray toUtf8() const