1 /****************************************************************************
2 ** Copyright (C) 2010-2020 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com.
3 ** All rights reserved.
4 **
5 ** This file is part of the KD Soap library.
6 **
7 ** Licensees holding valid commercial KD Soap licenses may use this file in
8 ** accordance with the KD Soap Commercial License Agreement provided with
9 ** the Software.
10 **
11 **
12 ** This file may be distributed and/or modified under the terms of the
13 ** GNU Lesser General Public License version 2.1 and version 3 as published by the
14 ** Free Software Foundation and appearing in the file LICENSE.LGPL.txt included.
15 **
16 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
17 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 **
19 ** Contact info@kdab.com if any conditions of this licensing are not
20 ** clear to you.
21 **
22 **********************************************************************/
23 #include "KDSoapServerObjectInterface.h"
24 #include "KDSoapServerSocket_p.h"
25 #include "KDSoapClient/KDSoapValue.h"
26 #include <QDebug>
27 #include <QPointer>
28 
29 class KDSoapServerObjectInterface::Private
30 {
31 public:
Private()32     Private() :
33         m_serverSocket(nullptr)
34     {
35     }
36 
37     KDSoapHeaders m_requestHeaders;
38     KDSoapHeaders m_responseHeaders;
39     QString m_faultCode;
40     QString m_faultString;
41     QString m_faultActor;
42     QString m_detail;
43     KDSoapValue m_detailValue;
44     QString m_responseNamespace;
45     QByteArray m_soapAction;
46     // QPointer in case the client disconnects during a delayed response
47     QPointer<KDSoapServerSocket> m_serverSocket;
48 };
49 
HttpResponseHeaderItem(const QByteArray & name,const QByteArray & value)50 KDSoapServerObjectInterface::HttpResponseHeaderItem::HttpResponseHeaderItem(const QByteArray &name, const QByteArray &value)
51     : m_value(value), m_name(name)
52 {
53 }
54 
HttpResponseHeaderItem()55 KDSoapServerObjectInterface::HttpResponseHeaderItem::HttpResponseHeaderItem()
56 {
57 }
58 
KDSoapServerObjectInterface()59 KDSoapServerObjectInterface::KDSoapServerObjectInterface()
60     : d(new Private)
61 {
62 }
63 
~KDSoapServerObjectInterface()64 KDSoapServerObjectInterface::~KDSoapServerObjectInterface()
65 {
66     delete d;
67 }
68 
processRequest(const KDSoapMessage & request,KDSoapMessage & response,const QByteArray & soapAction)69 void KDSoapServerObjectInterface::processRequest(const KDSoapMessage &request, KDSoapMessage &response, const QByteArray &soapAction)
70 {
71     const QString method = request.name();
72     qDebug() << "Slot not found:" << method << "[soapAction =" << soapAction << "]" /* << "in" << metaObject()->className()*/;
73     const KDSoap::SoapVersion soapVersion = KDSoap::SOAP1_1; // TODO version selection on the server side
74     response.createFaultMessage(QString::fromLatin1("Server.MethodNotFound"), QString::fromLatin1("%1 not found").arg(method), soapVersion);
75 }
76 
processFileRequest(const QString & path,QByteArray & contentType)77 QIODevice *KDSoapServerObjectInterface::processFileRequest(const QString &path, QByteArray &contentType)
78 {
79     Q_UNUSED(path);
80     Q_UNUSED(contentType);
81     return nullptr;
82 }
83 
processRequestWithPath(const KDSoapMessage & request,KDSoapMessage & response,const QByteArray & soapAction,const QString & path)84 void KDSoapServerObjectInterface::processRequestWithPath(const KDSoapMessage &request, KDSoapMessage &response, const QByteArray &soapAction, const QString &path)
85 {
86     Q_UNUSED(soapAction);
87     const QString method = request.name();
88     qWarning("Invalid path: \"%s\"", qPrintable(path));
89     //qWarning() << "Invalid path:" << path << "[method =" << method << "; soapAction =" << soapAction << "]" /* << "in" << metaObject()->className()*/;
90     const KDSoap::SoapVersion soapVersion = KDSoap::SOAP1_1; // TODO version selection on the server side
91     response.createFaultMessage(QString::fromLatin1("Client.Data"), QString::fromLatin1("Method %1 not found in path %2").arg(method, path), soapVersion);
92 }
93 
additionalHttpResponseHeaderItems() const94 KDSoapServerObjectInterface::HttpResponseHeaderItems KDSoapServerObjectInterface::additionalHttpResponseHeaderItems() const
95 {
96     return HttpResponseHeaderItems();
97 }
98 
doneProcessingRequestWithPath(const KDSoapServerObjectInterface & otherInterface)99 void KDSoapServerObjectInterface::doneProcessingRequestWithPath(const KDSoapServerObjectInterface &otherInterface)
100 {
101     d->m_faultCode = otherInterface.d->m_faultCode;
102     d->m_faultString = otherInterface.d->m_faultString;
103     d->m_faultActor = otherInterface.d->m_faultActor;
104     d->m_detail = otherInterface.d->m_detail;
105     d->m_detailValue = otherInterface.d->m_detailValue;
106     d->m_responseHeaders = otherInterface.d->m_responseHeaders;
107     d->m_responseNamespace = otherInterface.d->m_responseNamespace;
108 }
109 
setFault(const QString & faultCode,const QString & faultString,const QString & faultActor,const QString & detail)110 void KDSoapServerObjectInterface::setFault(const QString &faultCode, const QString &faultString, const QString &faultActor, const QString &detail)
111 {
112     Q_ASSERT(!faultCode.isEmpty());
113     d->m_faultCode = faultCode;
114     d->m_faultString = faultString;
115     d->m_faultActor = faultActor;
116     d->m_detail = detail;
117 }
118 
setFault(const QString & faultCode,const QString & faultString,const QString & faultActor,const KDSoapValue & detail)119 void KDSoapServerObjectInterface::setFault(const QString &faultCode, const QString &faultString, const QString &faultActor, const KDSoapValue &detail)
120 {
121     Q_ASSERT(!faultCode.isEmpty());
122     d->m_faultCode = faultCode;
123     d->m_faultString = faultString;
124     d->m_faultActor = faultActor;
125     d->m_detailValue = detail;
126 }
127 
storeFaultAttributes(KDSoapMessage & message) const128 void KDSoapServerObjectInterface::storeFaultAttributes(KDSoapMessage &message) const
129 {
130     // SOAP 1.1  <faultcode>, <faultstring>, <faultfactor>, <detail>
131     message.addArgument(QString::fromLatin1("faultcode"), d->m_faultCode);
132     message.addArgument(QString::fromLatin1("faultstring"), d->m_faultString);
133     message.addArgument(QString::fromLatin1("faultactor"), d->m_faultActor);
134     if (d->m_detailValue.isNil() || d->m_detailValue.isNull()) {
135         message.addArgument(QString::fromLatin1("detail"), d->m_detail);
136     } else {
137         KDSoapValueList detailAsList;
138         detailAsList.append(d->m_detailValue);
139         message.addArgument(QString::fromLatin1("detail"), detailAsList);
140     }
141     // TODO  : Answer SOAP 1.2  <Code> , <Reason> , <Node> , <Role> , <Detail>
142 }
143 
hasFault() const144 bool KDSoapServerObjectInterface::hasFault() const
145 {
146     return !d->m_faultCode.isEmpty();
147 }
148 
serverSocket() const149 QAbstractSocket *KDSoapServerObjectInterface::serverSocket() const
150 {
151     return d->m_serverSocket;
152 }
153 
requestHeaders() const154 KDSoapHeaders KDSoapServerObjectInterface::requestHeaders() const
155 {
156     return d->m_requestHeaders;
157 }
158 
setRequestHeaders(const KDSoapHeaders & headers,const QByteArray & soapAction)159 void KDSoapServerObjectInterface::setRequestHeaders(const KDSoapHeaders &headers, const QByteArray &soapAction)
160 {
161     d->m_requestHeaders = headers;
162     d->m_soapAction = soapAction;
163     // Prepare for a new request to be handled
164     d->m_faultCode.clear();
165     d->m_responseHeaders.clear();
166 }
167 
setResponseHeaders(const KDSoapHeaders & headers)168 void KDSoapServerObjectInterface::setResponseHeaders(const KDSoapHeaders &headers)
169 {
170     d->m_responseHeaders = headers;
171 }
172 
responseHeaders() const173 KDSoapHeaders KDSoapServerObjectInterface::responseHeaders() const
174 {
175     return d->m_responseHeaders;
176 }
177 
soapAction() const178 QByteArray KDSoapServerObjectInterface::soapAction() const
179 {
180     return d->m_soapAction;
181 }
182 
prepareDelayedResponse()183 KDSoapDelayedResponseHandle KDSoapServerObjectInterface::prepareDelayedResponse()
184 {
185     return KDSoapDelayedResponseHandle(d->m_serverSocket);
186 }
187 
setServerSocket(KDSoapServerSocket * serverSocket)188 void KDSoapServerObjectInterface::setServerSocket(KDSoapServerSocket *serverSocket)
189 {
190     d->m_serverSocket = serverSocket;
191 }
192 
sendDelayedResponse(const KDSoapDelayedResponseHandle & responseHandle,const KDSoapMessage & response)193 void KDSoapServerObjectInterface::sendDelayedResponse(const KDSoapDelayedResponseHandle &responseHandle, const KDSoapMessage &response)
194 {
195     KDSoapServerSocket *socket = responseHandle.serverSocket();
196     if (socket) {
197         socket->sendDelayedReply(this, response);
198     }
199 }
200 
writeHTTP(const QByteArray & httpReply)201 void KDSoapServerObjectInterface::writeHTTP(const QByteArray &httpReply)
202 {
203     const qint64 written = d->m_serverSocket->write(httpReply);
204     Q_ASSERT(written == httpReply.size()); // Please report a bug if you hit this.
205     Q_UNUSED(written);
206 }
207 
writeXML(const QByteArray & reply,bool isFault)208 void KDSoapServerObjectInterface::writeXML(const QByteArray &reply, bool isFault)
209 {
210     d->m_serverSocket->writeXML(reply, isFault);
211 }
212 
setResponseNamespace(const QString & ns)213 void KDSoapServerObjectInterface::setResponseNamespace(const QString &ns)
214 {
215     d->m_responseNamespace = ns;
216 }
217 
responseNamespace() const218 QString KDSoapServerObjectInterface::responseNamespace() const
219 {
220     return d->m_responseNamespace;
221 }
222