KNewStuff
soap.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "soap.h"
00020
00021 #include <QtXml/qdom.h>
00022 #include <QtNetwork/QTcpSocket>
00023 #include <QtCore/QRegExp>
00024
00025 #include <kio/job.h>
00026 #include <kurl.h>
00027 #include <kdebug.h>
00028
00029 #include <string.h>
00030
00031 using namespace KNS;
00032
00033 Soap::Soap(QObject* parent)
00034 : QObject(parent)
00035 {
00036
00037 m_model = soap;
00038 m_socket = NULL;
00039 m_lastjobid = 0;
00040
00041 }
00042
00043 Soap::~Soap()
00044 {
00045 }
00046
00047 int Soap::call(const QDomElement& element, const QString &endpoint)
00048 {
00049
00050
00051
00052
00053
00054
00055 if (m_model == canonicaltree) {
00056 call_tree(element, endpoint);
00057
00058 return -1;
00059 } else {
00060 return call_soap(element, endpoint);
00061 }
00062
00063
00064 }
00065
00066 void Soap::call_tree(const QDomElement& element, const QString &endpoint)
00067 {
00068 QString s;
00069
00070 s += localname(element);
00071 s += '(';
00072 QDomNodeList l = element.childNodes();
00073 for (int i = 0; i < l.count(); i++) {
00074 QDomNode tmp = l.item(i);
00075 s += localname(tmp);
00076 s += '(';
00077 s += xpath(tmp, "/");
00078 s += ')';
00079 s += '\n';
00080 }
00081 s += ")\n";
00082
00083
00084
00085 QByteArray data = s.toUtf8();
00086
00087
00088
00089 KUrl url(endpoint);
00090 QString hostname = url.host();
00091 int port = 30303;
00092
00093 m_socket = new QTcpSocket();
00094 m_socket->connectToHost(hostname, port);
00095
00096 m_socket->write(data, data.size());
00097
00098 connect(m_socket,
00099 SIGNAL(readyRead()),
00100 SLOT(slotSocket()));
00101 connect(m_socket,
00102 SIGNAL(error(QAbstractSocket::SocketError)),
00103 SLOT(slotSocketError(QAbstractSocket::SocketError)));
00104
00105 m_buffer = QByteArray();
00106 }
00107
00108 int Soap::call_soap(QDomElement element, const QString &endpoint)
00109 {
00110
00111 KUrl url(endpoint);
00112
00113 QDomDocument doc;
00114 QDomElement env = doc.createElement("SOAP-ENV:Envelope");
00115 env.setAttribute("xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
00116 doc.appendChild(env);
00117 QDomElement body = doc.createElement("SOAP-ENV:Body");
00118 env.appendChild(body);
00119 element.setAttribute("xmlns:ns", "urn:DXS");
00120 body.appendChild(element);
00121
00122 QString s = doc.toString();
00123 QByteArray data = s.toUtf8();
00124
00125
00126
00127
00128 KIO::TransferJob *job;
00129 job = KIO::http_post(url, data, KIO::HideProgressInfo);
00130 int thisjobid = ++m_lastjobid;
00131 m_jobids.insert(job, thisjobid);
00132 job->addMetaData("content-type", "Content-Type: text/xml");
00133
00134
00135
00136 connect(job,
00137 SIGNAL(data(KIO::Job*, const QByteArray&)),
00138 SLOT(slotData(KIO::Job*, const QByteArray&)));
00139 connect(job,
00140 SIGNAL(result(KJob*)),
00141 SLOT(slotResult(KJob*)));
00142
00143 m_buffer = QByteArray();
00144 return thisjobid;
00145 }
00146
00147 void Soap::slotData(KIO::Job *job, const QByteArray& data)
00148 {
00149 Q_UNUSED(job);
00150
00151
00152
00153
00154 int bufferlen = m_buffer.size();
00155 m_buffer.resize(bufferlen + data.size());
00156
00157
00158
00159 memcpy(m_buffer.data() + bufferlen, data.data(), data.size());
00160
00161
00162 }
00163
00164 void Soap::slotResult(KJob *job)
00165 {
00166
00167
00168 if ((job) && (job->error())) {
00169
00170
00171 emit signalError();
00172 return;
00173 }
00174
00175
00176
00177 int bufferlen = m_buffer.size();
00178 m_buffer.resize(bufferlen + 1);
00179 m_buffer.data()[bufferlen] = 0;
00180 m_data = QString::fromUtf8(m_buffer);
00181
00182
00183
00184 if (m_model == soap) {
00185 QDomDocument doc;
00186 doc.setContent(m_data);
00187
00188 QDomElement envelope = doc.documentElement();
00189 QDomNode bodynode = envelope.firstChild();
00190 QDomNode contentnode = bodynode.firstChild();
00191
00192
00193
00194
00195 emit signalResult(contentnode, m_jobids.value(job));
00196 m_jobids.remove(job);
00197 } else {
00198 QDomDocument doc;
00199
00200
00201
00202
00203
00204 m_data = m_data.simplified();
00205 doc = buildtree(doc, doc.documentElement(), m_data);
00206
00207 QDomElement root = doc.documentElement();
00208
00209
00210
00211
00212
00213 emit signalResult(root, -1);
00214 }
00215 }
00216
00217 QString Soap::localname(const QDomNode& node)
00218 {
00219 QDomElement el = node.toElement();
00220 QString s = el.tagName().section(':', -1);
00221 return s;
00222 }
00223
00224 QList<QDomNode> Soap::directChildNodes(const QDomNode& node, const QString &name)
00225 {
00226 QList<QDomNode> list;
00227 QDomNode n = node.firstChild();
00228 while (!n.isNull()) {
00229 if ((n.isElement()) && (n.toElement().tagName() == name)) {
00230 list.append(n);
00231 }
00232
00233 n = n.nextSibling();
00234 }
00235 return list;
00236 }
00237
00238 QString Soap::xpath(const QDomNode& node, const QString &expr)
00239 {
00240
00241
00242
00243
00244
00245
00246
00247
00248 QDomNode n = node;
00249 const QStringList explist = expr.split('/', QString::SkipEmptyParts);
00250 for (QStringList::const_iterator it = explist.begin(); it != explist.end(); ++it) {
00251 QDomElement el = n.toElement();
00252 QDomNodeList l = el.elementsByTagName((*it));
00253 if (!l.size()) {
00254 return QString();
00255 }
00256 n = l.item(0);
00257 }
00258 QString s = n.toElement().text();
00259 return s;
00260 }
00261
00262 void Soap::setModel(Model m)
00263 {
00264 m_model = m;
00265 }
00266
00267 void Soap::slotSocketError(QAbstractSocket::SocketError error)
00268 {
00269 Q_UNUSED(error);
00270
00271
00272
00273 delete m_socket;
00274 m_socket = NULL;
00275
00276
00277 }
00278
00279 void Soap::slotSocket()
00280 {
00281
00282
00283 QByteArray a;
00284 a.resize(m_socket->bytesAvailable());
00285 m_socket->read(a.data(), m_socket->bytesAvailable());
00286
00287
00288
00289 slotData(NULL, a);
00290
00291 if (m_socket->atEnd()) {
00292 m_socket->close();
00293
00294 m_socket = NULL;
00295
00296 slotResult(NULL);
00297 }
00298 }
00299
00300 QDomDocument Soap::buildtree(QDomDocument doc, QDomElement cur, const QString& data)
00301 {
00302 int start = -1, end = -1;
00303 int offset = 0;
00304 int stack = 0;
00305 bool quoted = false;
00306
00307 if (data.indexOf('(') == -1) {
00308 QDomText t = doc.createTextNode(data);
00309 cur.appendChild(t);
00310 return doc;
00311 }
00312
00313 for (int i = 0; i < data.length(); i++) {
00314 const QChar c = data.at(i);
00315 if (quoted) {
00316 quoted = false;
00317 continue;
00318 }
00319 if (c == '\\') {
00320 quoted = true;
00321 } else if (c == '(') {
00322 stack++;
00323 if (start == -1) {
00324 start = i;
00325 }
00326 } else if (c == ')') {
00327 stack--;
00328 if ((stack == 0) && (end == -1)) {
00329 end = i;
00330
00331 QString expression = data.mid(offset, start - offset);
00332 QString sub = data.mid(start + 1, end - start - 1);
00333 expression = expression.trimmed();
00334
00335
00336
00337 QDomElement elem;
00338 if (cur.isNull()) {
00339 elem = doc.createElement("ns:" + expression);
00340 doc.appendChild(elem);
00341 } else {
00342 elem = doc.createElement(expression);
00343 cur.appendChild(elem);
00344 }
00345
00346 buildtree(doc, elem, sub);
00347
00348 offset = end + 1;
00349 start = -1;
00350 end = -1;
00351 }
00352 }
00353 }
00354
00355 return doc;
00356 }
00357
00358 #include "soap.moc"