6 * Portable Windows Library
8 * Copyright (c) 2002 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
27 * Revision 1.6 2003/02/19 01:51:18 robertj
28 * Change to make it easier to set a fault from the server function handler.
30 * Revision 1.5 2002/11/06 22:47:25 robertj
31 * Fixed header comment (copyright etc)
33 * Revision 1.4 2002/10/23 15:57:28 craigs
34 * Fixed problem where no params specified
36 * Revision 1.3 2002/10/17 12:51:01 rogerh
37 * Add a newline at the of the file to silence a gcc compiler warning.
39 * Revision 1.2 2002/10/10 04:43:44 robertj
40 * VxWorks port, thanks Martijn Roest
42 * Revision 1.1 2002/10/02 08:54:01 craigs
43 * Added support for XMLRPC server
47 // This depends on the expat XML library by Jim Clark
48 // See http://www.jclark.com/xml/expat.html for more information
53 #pragma implementation "pxmlrpcs.h"
56 #define DEFAULT_XMPRPC_URL "/RPC2"
58 #include <ptclib/pxmlrpcs.h>
62 PXMLRPCServerResource::PXMLRPCServerResource()
63 : PHTTPResource(DEFAULT_XMPRPC_URL
)
67 PXMLRPCServerResource::PXMLRPCServerResource(
68 const PHTTPAuthority
& auth
) // Authorisation for the resource.
69 : PHTTPResource(DEFAULT_XMPRPC_URL
, auth
)
72 PXMLRPCServerResource::PXMLRPCServerResource(
73 const PURL
& url
) // Name of the resource in URL space.
78 PXMLRPCServerResource::PXMLRPCServerResource(
79 const PURL
& url
, // Name of the resource in URL space.
80 const PHTTPAuthority
& auth
// Authorisation for the resource.
82 : PHTTPResource(url
, auth
)
86 BOOL
PXMLRPCServerResource::SetMethod(const PString
& methodName
, const PNotifier
& func
)
88 PWaitAndSignal
m(methodMutex
);
90 // find the method, or create a new one
91 PXMLRPCServerMethod
* methodInfo
;
92 PINDEX pos
= methodList
.GetValuesIndex(methodName
);
93 if (pos
!= P_MAX_INDEX
)
94 methodInfo
= (PXMLRPCServerMethod
*)methodList
.GetAt(pos
);
96 methodInfo
= new PXMLRPCServerMethod(methodName
);
97 methodList
.Append(methodInfo
);
101 methodInfo
->methodFunc
= func
;
106 BOOL
PXMLRPCServerResource::LoadHeaders(PHTTPRequest
& /*request*/) // Information on this request.
111 BOOL
PXMLRPCServerResource::OnPOSTData(PHTTPRequest
& request
,
112 const PStringToString
& /*data*/)
116 OnXMLRPCRequest(request
.entityBody
, reply
);
118 request
.code
= PHTTP::RequestOK
;
119 request
.outMIME
.SetAt(PHTTP::ContentTypeTag
, "text/xml");
121 PINDEX len
= reply
.GetLength();
122 request
.server
.StartResponse(request
.code
, request
.outMIME
, len
);
123 return request
.server
.Write((const char *)reply
, len
);
127 void PXMLRPCServerResource::OnXMLRPCRequest(const PString
& body
, PString
& reply
)
129 // get body of message here
130 PXMLRPCBlock request
;
131 BOOL ok
= request
.Load(body
);
133 // if cannot parse XML, set return
135 reply
= FormatFault(PXMLRPC::CannotParseRequestXML
, "XML error:" + request
.GetErrorString());
139 // make sure methodCall is specified as top level
140 if ((request
.GetDocumentType() != "methodCall") || (request
.GetNumElements() < 1)) {
141 reply
= FormatFault(PXMLRPC::RequestHasWrongDocumentType
, "document type is not methodCall");
145 // make sure methodName is speciified
146 PXMLElement
* methodName
= request
.GetElement("methodName");
147 if (methodName
== NULL
) {
148 reply
= FormatFault(PXMLRPC::RequestHasNoMethodName
, "methodCall has no methodName");
152 // extract method name
153 if ((methodName
->GetSize() != 1) || (methodName
->GetElement(0)->IsElement())) {
154 reply
= FormatFault(PXMLRPC::MethodNameIsEmpty
, "methodName is empty");
157 PString method
= ((PXMLData
*)methodName
->GetElement(0))->GetString();
160 PTRACE(3, "XMLRPC\tReceived XMLRPC request for method " << method
);
162 OnXMLRPCRequest(method
, request
, reply
);
165 void PXMLRPCServerResource::OnXMLRPCRequest(const PString
& methodName
,
166 PXMLRPCBlock
& request
,
171 // find the method information
172 PINDEX pos
= methodList
.GetValuesIndex(methodName
);
173 if (pos
== P_MAX_INDEX
) {
174 reply
= FormatFault(PXMLRPC::UnknownMethod
, "unknown method " + methodName
);
177 PXMLRPCServerMethod
* methodInfo
= (PXMLRPCServerMethod
*)methodList
.GetAt(pos
);
178 PNotifier notifier
= methodInfo
->methodFunc
;
179 methodMutex
.Signal();
182 PXMLRPCServerParms
p(*this, request
);
188 if (request
.GetFaultCode() != P_MAX_INDEX
)
189 reply
= FormatFault(request
.GetFaultCode(), request
.GetFaultText());
191 PStringStream r
; r
<< p
.response
;
197 PString
PXMLRPCServerResource::FormatFault(PINDEX code
, const PString
& str
)
199 PTRACE(2, "XMLRPC\trequest failed: " << str
);
202 reply
<< "<?xml version=\"1.0\"?>\n"
208 "<name>faultCode</name>"
209 "<value><int>" << code
<< "</int></value>"
212 "<name>faultString</name>"
213 "<value><string>" << str
<< "</string></value>"