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