KD SOAP API Documentation: KDSoapServerSocket.cpp Source File

| KD SOAP API Documentation 2.2

Loading...
Searching...
No Matches
KDSoapServerSocket.cpp
Go to the documentation of this file.
1/****************************************************************************
2**
3** This file is part of the KD Soap project.
4**
5** SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10#include "KDSoapServer.h"
11#include "KDSoapServerAuthInterface.h"
12#include "KDSoapServerCustomVerbRequestInterface.h"
13#include "KDSoapServerObjectInterface.h"
14#include "KDSoapServerRawXMLInterface.h"
15#include "KDSoapServerSocket_p.h"
16#include "KDSoapSocketList_p.h"
17#include <KDSoapClient/KDSoapMessage.h>
18#include <KDSoapClient/KDSoapMessageReader_p.h>
19#include <KDSoapClient/KDSoapMessageWriter_p.h>
20#include <KDSoapClient/KDSoapNamespaceManager.h>
21#include <QBuffer>
22#include <QDir>
23#include <QFile>
24#include <QFileInfo>
25#include <QMetaMethod>
26#include <QThread>
27#include <QVarLengthArray>
28
29 static const char s_forbidden[] = "HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n";
30
31KDSoapServerSocket::KDSoapServerSocket(KDSoapSocketList *owner, QObject *serverObject)
32#ifndef QT_NO_SSL
33 : QSslSocket()
34 ,
35#else
36 : QTcpSocket()
37 ,
38#endif
39 m_owner(owner)
40 , m_serverObject(serverObject)
41 , m_delayedResponse(false)
42 , m_socketEnabled(true)
43 , m_receivedData(false)
44 , m_useRawXML(false)
45 , m_bytesReceived(0)
46 , m_chunkStart(0)
47{
48 connect(this, &QIODevice::readyRead, this, &KDSoapServerSocket::slotReadyRead);
49 m_doDebug = qEnvironmentVariableIsSet("KDSOAP_DEBUG");
50}
51
52// The socket is deleted when it emits disconnected() (see KDSoapSocketList::handleIncomingConnection).
53KDSoapServerSocket::~KDSoapServerSocket()
54{
55 // same as m_owner->socketDeleted, but safe in case m_owner is deleted first
56 emit socketDeleted(this);
57}
58
59 typedef QMap<QByteArray, QByteArray> HeadersMap;
60 static HeadersMap parseHeaders(const QByteArray &headerData)
61{
62 HeadersMap headersMap;
63 QBuffer sourceBuffer;
64 sourceBuffer.setData(headerData);
65 sourceBuffer.open(QIODevice::ReadOnly);
66 // The first line is special, it's the GET or POST line
67 const QList<QByteArray> firstLine = sourceBuffer.readLine().split(' ');
68 if (firstLine.count() < 3) {
69 qDebug() << "Malformed HTTP request:" << firstLine;
70 return headersMap;
71 }
72 const QByteArray &requestType = firstLine.at(0);
73 headersMap.insert("_requestType", requestType);
74
75 // Grammar from https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1
76 // origin-form = absolute-path [ "?" query ]
77 // and https://datatracker.ietf.org/doc/html/rfc3986#section-3.3
78 // says the path ends at the first '?' or '#' character
79 const QByteArray arg1 = firstLine.at(1);
80 const int queryPos = arg1.indexOf('?');
81 const QByteArray path = queryPos >= 0 ? arg1.left(queryPos) : arg1;
82 const QByteArray query = queryPos >= 0 ? arg1.mid(queryPos) : QByteArray();
83 // Unfortunately QDir::cleanPath works with QString
84 const QByteArray cleanedPath = QDir::cleanPath(QString::fromUtf8(path)).toUtf8();
85 headersMap.insert("_path", cleanedPath + query);
86
87 const QByteArray &httpVersion = firstLine.at(2);
88 headersMap.insert("_httpVersion", httpVersion);
89
90 while (!sourceBuffer.atEnd()) {
91 const QByteArray line = sourceBuffer.readLine();
92 const int pos = line.indexOf(':');
93 if (pos == -1) {
94 qDebug() << "Malformed HTTP header:" << line;
95 }
96 const QByteArray header = line.left(pos).toLower(); // RFC2616 section 4.2 "Field names are case-insensitive"
97 const QByteArray value = line.mid(pos + 1).trimmed(); // remove space before and \r\n after
98 // qDebug() << "HEADER" << header << "VALUE" << value;
99 headersMap.insert(header, value);
100 }
101 return headersMap;
102}
103
104// We could parse headers as we go along looking for \r\n, and stop at empty header line, to avoid all this memory copying
105// But in practice XML parsing (and writing) is far, far slower anyway.
106 static bool splitHeadersAndData(const QByteArray &request, QByteArray &header, QByteArray &data)
107{
108 const int sep = request.indexOf("\r\n\r\n");
109 if (sep <= 0) {
110 return false;
111 }
112 header = request.left(sep);
113 data = request.mid(sep + 4);
114 return true;
115}
116
117 static QByteArray stripQuotes(const QByteArray &bar)
118{
119 if (bar.startsWith('\"') && bar.endsWith('\"')) {
120 return bar.mid(1, bar.length() - 2);
121 }
122
123 return bar;
124}
125
126 static QByteArray httpResponseHeaders(bool fault, const QByteArray &contentType, int responseDataSize, QObject *serverObject)
127{
128 QByteArray httpResponse;
129 httpResponse.reserve(50);
130 if (fault) {
131 // https://www.w3.org/TR/2007/REC-soap12-part0-20070427 and look for 500
132 httpResponse += "HTTP/1.1 500 Internal Server Error\r\n";
133 } else if (responseDataSize == 0) {
134 httpResponse += "HTTP/1.1 204 No Content\r\n";
135 } else {
136 httpResponse += "HTTP/1.1 200 OK\r\n";
137 }
138
139 httpResponse += "Content-Type: ";
140 httpResponse += contentType;
141 httpResponse += "\r\nContent-Length: ";
142 httpResponse += QByteArray::number(responseDataSize);
143 httpResponse += "\r\n";
144
145 KDSoapServerObjectInterface *serverObjectInterface = qobject_cast<KDSoapServerObjectInterface *>(serverObject);
146 if (serverObjectInterface) {
147 const KDSoapServerObjectInterface::HttpResponseHeaderItems &additionalItems = serverObjectInterface->additionalHttpResponseHeaderItems();
148 for (const KDSoapServerObjectInterface::HttpResponseHeaderItem &headerItem : qAsConst(additionalItems)) {
149 httpResponse += headerItem.m_name;
150 httpResponse += ": ";
151 httpResponse += headerItem.m_value;
152 httpResponse += "\r\n";
153 }
154 }
155
156 httpResponse += "\r\n"; // end of headers
157 return httpResponse;
158}
159
160void KDSoapServerSocket::slotReadyRead()
161{
162 if (!m_socketEnabled) {
163 return;
164 }
165
166 // QNAM in Qt 5.x tends to connect additional sockets in advance and not use them
167 // So only count the sockets which actually sent us data (for the servertest unittest).
168 if (!m_receivedData) {
169 m_receivedData = true;
170 m_owner->increaseConnectionCount();
171 }
172
173 // qDebug() << this << QThread::currentThread() << "slotReadyRead!";
174
175 QByteArray buf(2048, ' ');
176 qint64 nread = -1;
177 while (nread != 0) {
178 nread = read(buf.data(), buf.size());
179 if (nread < 0) {
180 qDebug() << "Error reading from server socket:" << errorString();
181 return;
182 }
183 m_requestBuffer += buf.left(nread);
184 m_bytesReceived += nread;
185 }
186
187 KDSoapServerRawXMLInterface *rawXmlInterface = qobject_cast<KDSoapServerRawXMLInterface *>(m_serverObject);
188
189 if (m_httpHeaders.isEmpty()) {
190 // New request: see if we can parse headers
191 QByteArray receivedHttpHeaders, receivedData;
192 const bool splitOK = splitHeadersAndData(m_requestBuffer, receivedHttpHeaders, receivedData);
193 if (!splitOK) {
194 // qDebug() << "Incomplete SOAP request, wait for more data";
195 // incomplete request, wait for more data
196 return;
197 }
198 m_httpHeaders = parseHeaders(receivedHttpHeaders);
199 // Leave only the actual data in the buffer
200 m_requestBuffer = receivedData;
201 m_bytesReceived = receivedData.size();
202 m_useRawXML = false;
203 if (rawXmlInterface) {
204 KDSoapServerObjectInterface *serverObjectInterface = qobject_cast<KDSoapServerObjectInterface *>(m_serverObject);
205 serverObjectInterface->setServerSocket(this);
206 m_useRawXML = rawXmlInterface->newRequest(m_httpHeaders.value("_requestType"), m_httpHeaders);
207 }
208 }
209
210 if (m_doDebug) {
211 qDebug() << "headers:" << m_httpHeaders;
212 qDebug() << "data received:" << m_requestBuffer;
213 }
214
215 if (m_httpHeaders.value("transfer-encoding") != "chunked") {
216 if (m_useRawXML) {
217 rawXmlInterface->processXML(m_requestBuffer);
218 m_requestBuffer.clear();
219 }
220
221 const QByteArray contentLength = m_httpHeaders.value("content-length");
222 if (m_bytesReceived < contentLength.toInt()) {
223 return; // incomplete request, wait for more data
224 }
225
226 if (m_useRawXML) {
227 rawXmlInterface->endRequest();
228 } else {
229 handleRequest(m_httpHeaders, m_requestBuffer);
230 }
231 } else {
232 // qDebug() << "requestBuffer has " << m_requestBuffer.size() << "bytes, starting at" << m_chunkStart;
233 while (m_chunkStart >= 0) {
234 const int nextEOL = m_requestBuffer.indexOf("\r\n", m_chunkStart);
235 if (nextEOL == -1) {
236 return;
237 }
238 const QByteArray chunkSizeStr = m_requestBuffer.mid(m_chunkStart, nextEOL - m_chunkStart);
239 // qDebug() << m_chunkStart << nextEOL << "chunkSizeStr=" << chunkSizeStr;
240 bool ok;
241 int chunkSize = chunkSizeStr.toInt(&ok, 16);
242 if (!ok) {
243 const QByteArray badRequest = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n";
244 write(badRequest);
245 return;
246 }
247 if (chunkSize == 0) { // done!
248 m_requestBuffer = m_requestBuffer.mid(nextEOL);
249 m_chunkStart = -1;
250 break;
251 }
252 if (nextEOL + 2 + chunkSize + 2 >= m_requestBuffer.size()) {
253 return; // not enough data, chunk is incomplete
254 }
255 const QByteArray chunk = m_requestBuffer.mid(nextEOL + 2, chunkSize);
256 if (m_useRawXML) {
257 rawXmlInterface->processXML(chunk);
258 } else {
259 m_decodedRequestBuffer += chunk;
260 }
261 m_chunkStart = nextEOL + 2 + chunkSize + 2;
262 }
263 // We have the full data, now ensure we read trailers
264 if (!m_requestBuffer.contains("\r\n\r\n")) {
265 return;
266 }
267 if (m_useRawXML) {
268 rawXmlInterface->endRequest();
269 } else {
270 handleRequest(m_httpHeaders, m_decodedRequestBuffer);
271 }
272 m_decodedRequestBuffer.clear();
273 m_chunkStart = 0;
274 }
275 m_requestBuffer.clear();
276 m_httpHeaders.clear();
277 m_receivedData = false;
278}
279
280void KDSoapServerSocket::handleRequest(const QMap<QByteArray, QByteArray> &httpHeaders, const QByteArray &receivedData)
281{
282 const QByteArray requestType = httpHeaders.value("_requestType");
283 const QString path = QString::fromLatin1(httpHeaders.value("_path").constData());
284
285 if (!path.startsWith(QLatin1String("/"))) {
286 // denied for security reasons (ex: path starting with "..")
287 write(s_forbidden);
288 return;
289 }
290
291 KDSoapServerAuthInterface *serverAuthInterface = qobject_cast<KDSoapServerAuthInterface *>(m_serverObject);
292 if (serverAuthInterface) {
293 const QByteArray authValue = httpHeaders.value("authorization");
294 if (!serverAuthInterface->handleHttpAuth(authValue, path)) {
295 // send auth request (Qt supports basic, ntlm and digest)
296 const QByteArray unauthorized =
297 "HTTP/1.1 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"example\"\r\nContent-Length: 0\r\n\r\n";
298 write(unauthorized);
299 return;
300 }
301 }
302
303 if (requestType != "GET" && requestType != "POST") {
304 KDSoapServerCustomVerbRequestInterface *serverCustomRequest = qobject_cast<KDSoapServerCustomVerbRequestInterface *>(m_serverObject);
305 QByteArray customVerbRequestAnswer;
306 if (serverCustomRequest && serverCustomRequest->processCustomVerbRequest(requestType, receivedData, httpHeaders, customVerbRequestAnswer)) {
307 write(customVerbRequestAnswer);
308 return;
309 } else {
310 qWarning() << "Unknown HTTP request:" << requestType;
311 // handleError(replyMsg, "Client.Data", QString::fromLatin1("Invalid request type '%1', should be GET or
312 // POST").arg(QString::fromLatin1(requestType.constData()))); sendReply(0, replyMsg);
313 const QByteArray methodNotAllowed = "HTTP/1.1 405 Method Not Allowed\r\nAllow: GET POST\r\nContent-Length: 0\r\n\r\n";
314 write(methodNotAllowed);
315 return;
316 }
317 }
318
319 KDSoapServer *server = m_owner->server();
320 KDSoapMessage replyMsg;
321 replyMsg.setUse(server->use());
322
323 KDSoapServerObjectInterface *serverObjectInterface = qobject_cast<KDSoapServerObjectInterface *>(m_serverObject);
324 if (!serverObjectInterface) {
325 const QString error = QString::fromLatin1("Server object %1 does not implement KDSoapServerObjectInterface!")
326 .arg(QString::fromLatin1(m_serverObject->metaObject()->className()));
327 handleError(replyMsg, "Server.ImplementationError", error);
328 sendReply(nullptr, replyMsg);
329 return;
330 } else {
331 serverObjectInterface->setServerSocket(this);
332 }
333
334 if (requestType == "GET") {
335 if (path == server->wsdlPathInUrl() && handleWsdlDownload()) {
336 return;
337 } else if (handleFileDownload(serverObjectInterface, path)) {
338 return;
339 }
340
341 // See https://www.ibm.com/developerworks/xml/library/x-tipgetr/
342 // We could implement it, but there's no SOAP request, just a query in the URL,
343 // which we'd have to pass to a different virtual than processRequest.
344 handleError(replyMsg, "Client.Data", QString::fromLatin1("Support for GET requests not implemented yet."));
345 sendReply(nullptr, replyMsg);
346 return;
347 }
348
349 // parse message
350 KDSoapMessage requestMsg;
351 KDSoapHeaders requestHeaders;
352 KDSoapMessageReader reader;
353 KDSoapMessageReader::XmlError err = reader.xmlToMessage(receivedData, &requestMsg, &m_messageNamespace, &requestHeaders, KDSoap::SOAP1_1);
354 if (err == KDSoapMessageReader::PrematureEndOfDocumentError) {
355 // qDebug() << "Incomplete SOAP message, wait for more data";
356 // This should never happen, since we check for content-size above.
357 return;
358 } // TODO handle parse errors?
359
360 // check soap version and extract soapAction header
361 QByteArray soapAction;
362 const QByteArray contentType = httpHeaders.value("content-type");
363 if (contentType.startsWith("text/xml")) { // krazy:exclude=strings
364 // SOAP 1.1
365 soapAction = httpHeaders.value("soapaction");
366 // The SOAP standard allows quotation marks around the SoapAction, so we have to get rid of these.
367 soapAction = stripQuotes(soapAction);
368
369 } else if (contentType.startsWith("application/soap+xml")) { // krazy:exclude=strings
370 // SOAP 1.2
371 // Example: application/soap+xml;charset=utf-8;action=ActionHex
372 const QList<QByteArray> parts = contentType.split(';');
373 for (const QByteArray &part : qAsConst(parts)) {
374 if (part.trimmed().startsWith("action=")) { // krazy:exclude=strings
375 soapAction = stripQuotes(part.mid(part.indexOf('=') + 1));
376 }
377 }
378 }
379
380 m_method = requestMsg.name();
381
382 if (!replyMsg.isFault()) {
383 makeCall(serverObjectInterface, requestMsg, replyMsg, requestHeaders, soapAction, path);
384 }
385
386 if (serverObjectInterface && m_delayedResponse) {
387 // Delayed response. Disable the socket to make sure we don't handle another call at the same time.
388 setSocketEnabled(false);
389 } else {
390 sendReply(serverObjectInterface, replyMsg);
391 }
392}
393
394bool KDSoapServerSocket::handleWsdlDownload()
395{
396 KDSoapServer *server = m_owner->server();
397 const QString wsdlFile = server->wsdlFile();
398 QFile wf(wsdlFile);
399 if (wf.open(QIODevice::ReadOnly)) {
400 // qDebug() << "Returning wsdl file contents";
401 const QByteArray responseText = wf.readAll();
402 const QByteArray response = httpResponseHeaders(false, "application/xml", responseText.size(), m_serverObject);
403 write(response);
404 write(responseText);
405 return true;
406 }
407 return false;
408}
409
410bool KDSoapServerSocket::handleFileDownload(KDSoapServerObjectInterface *serverObjectInterface, const QString &path)
411{
412 QByteArray contentType;
413 QIODevice *device = serverObjectInterface->processFileRequest(path, contentType);
414 if (!device) {
415 const QByteArray notFound = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
416 write(notFound);
417 return true;
418 }
419 if (!device->open(QIODevice::ReadOnly)) {
420 write(s_forbidden);
421 delete device;
422 return true; // handled!
423 }
424 const QByteArray response = httpResponseHeaders(false, contentType, device->size(), m_serverObject);
425 if (m_doDebug) {
426 qDebug() << "KDSoapServerSocket: file download response" << response;
427 }
428 qint64 written = write(response);
429 Q_ASSERT(written == response.size()); // Please report a bug if you hit this.
430 Q_UNUSED(written);
431
432 char block[4096] = {0};
433 // qint64 totalRead = 0;
434 while (!device->atEnd()) {
435 const qint64 in = device->read(block, sizeof(block));
436 if (in <= 0) {
437 break;
438 }
439 // totalRead += in;
440 if (in != write(block, in)) {
441 // error = true;
442 break;
443 }
444 }
445 // if (totalRead != device->size()) {
446 // // Unable to read from the source.
447 // error = true;
448 //}
449
450 delete device;
451 // TODO log the file request, if logging is enabled?
452 return true;
453}
454
455void KDSoapServerSocket::writeXML(const QByteArray &xmlResponse, bool isFault)
456{
457 const QByteArray httpHeaders = httpResponseHeaders(isFault, "text/xml", xmlResponse.size(),
458 m_serverObject); // TODO return application/soap+xml;charset=utf-8 instead for SOAP 1.2
459 if (m_doDebug) {
460 qDebug() << "KDSoapServerSocket: writing" << httpHeaders << xmlResponse;
461 }
462 qint64 written = write(httpHeaders);
463 if (written != httpHeaders.size()) {
464 qWarning() << "Only wrote" << written << "out of" << httpHeaders.size() << "bytes of HTTP headers. Error:" << errorString();
465 }
466 written = write(xmlResponse);
467 if (written != xmlResponse.size()) {
468 qWarning() << "Only wrote" << written << "out of" << xmlResponse.size() << "bytes of response. Error:" << errorString();
469 }
470}
471
472 void KDSoapServerSocket::sendReply(KDSoapServerObjectInterface *serverObjectInterface, const KDSoapMessage &replyMsg)
473{
474 const bool isFault = replyMsg.isFault();
475
476 QByteArray xmlResponse;
477 if (!replyMsg.isNil()) {
478 KDSoapMessageWriter msgWriter;
479 // Note that the kdsoap client parsing code doesn't care for the name (except if it's fault), even in
480 // Document mode. Other implementations do, though.
481 QString responseName = isFault ? QString::fromLatin1("Fault") : replyMsg.name();
482 if (responseName.isEmpty()) {
483 responseName = m_method;
484 }
485 QString responseNamespace = m_messageNamespace;
486 KDSoapHeaders responseHeaders;
487 if (serverObjectInterface) {
488 responseHeaders = serverObjectInterface->responseHeaders();
489 if (!serverObjectInterface->responseNamespace().isEmpty()) {
490 responseNamespace = serverObjectInterface->responseNamespace();
491 }
492 }
493 msgWriter.setMessageNamespace(responseNamespace);
494 xmlResponse = msgWriter.messageToXml(replyMsg, responseName, responseHeaders, QMap<QString, KDSoapMessage>());
495 }
496
497 writeXML(xmlResponse, isFault);
498
499 // All done, check if we should log this
500 KDSoapServer *server = m_owner->server();
501 const KDSoapServer::LogLevel logLevel =
502 server->logLevel(); // we do this here in order to support dynamic settings changes (at the price of a mutex)
503 if (logLevel != KDSoapServer::LogNothing) {
504 if (logLevel == KDSoapServer::LogEveryCall || (logLevel == KDSoapServer::LogFaults && isFault)) {
505
506 if (isFault) {
507 server->log("FAULT " + m_method.toLatin1() + " -- " + replyMsg.faultAsString().toUtf8() + '\n');
508 } else {
509 server->log("CALL " + m_method.toLatin1() + '\n');
510 }
511 }
512 }
513}
514
515 void KDSoapServerSocket::sendDelayedReply(KDSoapServerObjectInterface *serverObjectInterface, const KDSoapMessage &replyMsg)
516{
517 sendReply(serverObjectInterface, replyMsg);
518 m_delayedResponse = false;
519 setSocketEnabled(true);
520}
521
522 void KDSoapServerSocket::setResponseDelayed()
523{
524 m_delayedResponse = true;
525}
526
527void KDSoapServerSocket::handleError(KDSoapMessage &replyMsg, const char *errorCode, const QString &error)
528{
529 qWarning("%s", qPrintable(error));
530 const KDSoap::SoapVersion soapVersion = KDSoap::SOAP1_1; // TODO version selection on the server side
531 replyMsg.createFaultMessage(QString::fromLatin1(errorCode), error, soapVersion);
532}
533
534void KDSoapServerSocket::makeCall(KDSoapServerObjectInterface *serverObjectInterface, const KDSoapMessage &requestMsg, KDSoapMessage &replyMsg,
535 const KDSoapHeaders &requestHeaders, const QByteArray &soapAction, const QString &path)
536{
537 Q_ASSERT(serverObjectInterface);
538
539 if (requestMsg.isFault()) {
540 // Can this happen? Getting a fault as a request !? Doesn't make sense...
541 // reply with a fault, but we don't even know what main element name to use
542 // Oh well, just use the incoming fault :-)
543 replyMsg = requestMsg;
544 handleError(replyMsg, "Client.Data", QString::fromLatin1("Request was a fault"));
545 } else {
546
547 // Call method on m_serverObject
548 serverObjectInterface->setRequestHeaders(requestHeaders, soapAction);
549
550 KDSoapServer *server = m_owner->server();
551 if (path != server->path()) {
552 serverObjectInterface->processRequestWithPath(requestMsg, replyMsg, soapAction, path);
553 } else {
554 serverObjectInterface->processRequest(requestMsg, replyMsg, soapAction);
555 }
556 if (serverObjectInterface->hasFault()) {
557 // qDebug() << "Got fault!";
558 replyMsg.setFault(true);
559 serverObjectInterface->storeFaultAttributes(replyMsg);
560 }
561 }
562}
563
564// Prevention against concurrent requests without waiting for a (delayed) reply,
565// but untestable with QNAM on the client side, since it doesn't do that.
566void KDSoapServerSocket::setSocketEnabled(bool enabled)
567{
568 if (m_socketEnabled == enabled) {
569 return;
570 }
571
572 m_socketEnabled = enabled;
573 if (enabled) {
574 slotReadyRead();
575 }
576}
577
578#include "moc_KDSoapServerSocket_p.cpp"
KDSoapMessageReader_p.h
KDSoapMessageWriter_p.h
KDSoapMessage.h
KDSoapNamespaceManager.h
KDSoapServerAuthInterface.h
KDSoapServerCustomVerbRequestInterface.h
KDSoapServerObjectInterface.h
KDSoapServerRawXMLInterface.h
s_forbidden
static const char s_forbidden[]
Definition KDSoapServerSocket.cpp:29
httpResponseHeaders
static QByteArray httpResponseHeaders(bool fault, const QByteArray &contentType, int responseDataSize, QObject *serverObject)
Definition KDSoapServerSocket.cpp:126
parseHeaders
static HeadersMap parseHeaders(const QByteArray &headerData)
Definition KDSoapServerSocket.cpp:60
HeadersMap
QMap< QByteArray, QByteArray > HeadersMap
Definition KDSoapServerSocket.cpp:59
stripQuotes
static QByteArray stripQuotes(const QByteArray &bar)
Definition KDSoapServerSocket.cpp:117
splitHeadersAndData
static bool splitHeadersAndData(const QByteArray &request, QByteArray &header, QByteArray &data)
Definition KDSoapServerSocket.cpp:106
KDSoapServerSocket_p.h
KDSoapServer.h
KDSoapSocketList_p.h
KDSoapHeaders
Definition KDSoapMessage.h:185
KDSoapMessageReader
Definition KDSoapMessageReader_p.h:18
KDSoapMessageReader::xmlToMessage
XmlError xmlToMessage(const QByteArray &data, KDSoapMessage *pParsedMessage, QString *pMessageNamespace, KDSoapHeaders *pRequestHeaders, KDSoap::SoapVersion soapVersion) const
Definition KDSoapMessageReader.cpp:188
KDSoapMessageReader::XmlError
XmlError
Definition KDSoapMessageReader_p.h:21
KDSoapMessageReader::PrematureEndOfDocumentError
@ PrematureEndOfDocumentError
Definition KDSoapMessageReader_p.h:24
KDSoapMessageWriter
Definition KDSoapMessageWriter_p.h:31
KDSoapMessage
Definition KDSoapMessage.h:29
KDSoapMessage::setUse
void setUse(Use use)
Definition KDSoapMessage.cpp:195
KDSoapServerAuthInterface
Definition KDSoapServerAuthInterface.h:30
KDSoapServerCustomVerbRequestInterface
Definition KDSoapServerCustomVerbRequestInterface.h:31
KDSoapServerObjectInterface
Definition KDSoapServerObjectInterface.h:60
KDSoapServerObjectInterface::additionalHttpResponseHeaderItems
virtual HttpResponseHeaderItems additionalHttpResponseHeaderItems() const
Definition KDSoapServerObjectInterface.cpp:85
KDSoapServerRawXMLInterface
Definition KDSoapServerRawXMLInterface.h:41
KDSoapServerSocket::sendDelayedReply
void sendDelayedReply(KDSoapServerObjectInterface *serverObjectInterface, const KDSoapMessage &replyMsg)
Definition KDSoapServerSocket.cpp:515
KDSoapServerSocket::socketDeleted
void socketDeleted(KDSoapServerSocket *)
KDSoapServerSocket::~KDSoapServerSocket
~KDSoapServerSocket()
Definition KDSoapServerSocket.cpp:53
KDSoapServerSocket::KDSoapServerSocket
KDSoapServerSocket(KDSoapSocketList *owner, QObject *serverObject)
Definition KDSoapServerSocket.cpp:31
KDSoapServerSocket::sendReply
void sendReply(KDSoapServerObjectInterface *serverObjectInterface, const KDSoapMessage &replyMsg)
Definition KDSoapServerSocket.cpp:472
KDSoapServerSocket::setResponseDelayed
void setResponseDelayed()
Definition KDSoapServerSocket.cpp:522
KDSoapServer
Definition KDSoapServer.h:30
KDSoapServer::use
KDSoapMessage::Use use() const
Definition KDSoapServer.cpp:157
KDSoapServer::LogLevel
LogLevel
Definition KDSoapServer.h:125
KDSoapServer::LogFaults
@ LogFaults
Definition KDSoapServer.h:127
KDSoapServer::LogEveryCall
@ LogEveryCall
Definition KDSoapServer.h:128
KDSoapServer::LogNothing
@ LogNothing
Definition KDSoapServer.h:126
KDSoapServer::wsdlFile
QString wsdlFile() const
Definition KDSoapServer.cpp:304
KDSoapServer::wsdlPathInUrl
QString wsdlPathInUrl() const
Definition KDSoapServer.cpp:310
KDSoapServer::logLevel
LogLevel logLevel() const
Definition KDSoapServer.cpp:168
KDSoapServer::path
QString path() const
Definition KDSoapServer.cpp:322
KDSoapSocketList
Definition KDSoapSocketList_p.h:23
KDSoapSocketList::server
KDSoapServer * server() const
Definition KDSoapSocketList_p.h:38
KDSoapSocketList::increaseConnectionCount
void increaseConnectionCount()
Definition KDSoapSocketList.cpp:74
KDSoap::SoapVersion
SoapVersion
Definition KDSoapValue.h:40
KDSoap::SOAP1_1
@ SOAP1_1
Definition KDSoapValue.h:42
QAbstractSocket::error
QAbstractSocket::SocketError error() const const
QBuffer
QBuffer::atEnd
virtual bool atEnd() const const override
QBuffer::open
virtual bool open(QIODevice::OpenMode flags) override
QBuffer::setData
void setData(const QByteArray &data)
QByteArray
QByteArray::clear
void clear()
QByteArray::contains
bool contains(char ch) const const
QByteArray::endsWith
bool endsWith(const QByteArray &ba) const const
QByteArray::indexOf
int indexOf(char ch, int from) const const
QByteArray::left
QByteArray left(int len) const const
QByteArray::length
int length() const const
QByteArray::mid
QByteArray mid(int pos, int len) const const
QByteArray::number
QByteArray number(int n, int base)
QByteArray::reserve
void reserve(int size)
QByteArray::size
int size() const const
QByteArray::startsWith
bool startsWith(const QByteArray &ba) const const
QByteArray::toInt
int toInt(bool *ok, int base) const const
QByteArray::toLower
QByteArray toLower() const const
QByteArray::trimmed
QByteArray trimmed() const const
QDir::cleanPath
QString cleanPath(const QString &path)
QFile
QIODevice
QIODevice::ReadOnly
ReadOnly
QIODevice::atEnd
virtual bool atEnd() const const
QIODevice::errorString
QString errorString() const const
QIODevice::open
virtual bool open(QIODevice::OpenMode mode)
QIODevice::read
qint64 read(char *data, qint64 maxSize)
QIODevice::readLine
qint64 readLine(char *data, qint64 maxSize)
QIODevice::readyRead
void readyRead()
QIODevice::size
virtual qint64 size() const const
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
QLatin1String
QList
QList::at
const T & at(int i) const const
QList::count
int count(const T &value) const const
QMap
QMap::clear
void clear()
QMap::insert
QMap::iterator insert(const Key &key, const T &value)
QMap::isEmpty
bool isEmpty() const const
QMap::value
const T value(const Key &key, const T &defaultValue) const const
QMetaObject::className
const char * className() const const
QObject
QObject::metaObject
virtual const QMetaObject * metaObject() const const
QObject::qobject_cast
T qobject_cast(QObject *object)
QSslSocket
QString
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QString::fromUtf8
QString fromUtf8(const char *str, int size)
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString::toLatin1
QByteArray toLatin1() const const
QString::toUtf8
QByteArray toUtf8() const const
QTcpSocket
QVector
KDSoapServerObjectInterface::HttpResponseHeaderItem
Definition KDSoapServerObjectInterface.h:124

© 2010-2024 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-soap/
Generated on Sun Jan 7 2024 11:47:36 for KD SOAP API Documentation by doxygen 1.9.8