1 // Copyright (C) 2001 by Eric Kidd. All rights reserved.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions
6 // 1. Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // 3. The name of the author may not be used to endorse or promote products
12 // derived from this software without specific prior written permission.
14 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include "XmlRpcCpp.h"
30 //=========================================================================
31 // XmlRpcFault Methods
32 //=========================================================================
34 XmlRpcFault::XmlRpcFault (const XmlRpcFault
&fault
) {
35 xmlrpc_env_init(&mFault
);
36 xmlrpc_env_set_fault(&mFault
,
37 fault
.mFault
.fault_code
,
38 fault
.mFault
.fault_string
);
41 XmlRpcFault::XmlRpcFault (const int faultCode
, const string faultString
) {
42 xmlrpc_env_init(&mFault
);
43 xmlrpc_env_set_fault(&mFault
, faultCode
,
44 const_cast<char*>(faultString
.c_str()));
47 XmlRpcFault::XmlRpcFault (const xmlrpc_env
*env
) {
48 if (!env
->fault_string
)
49 throw XmlRpcFault(XMLRPC_INTERNAL_ERROR
,
50 "Tried to create empty fault");
51 xmlrpc_env_init(&mFault
);
52 xmlrpc_env_set_fault(&mFault
, env
->fault_code
,
53 const_cast<char*>(env
->fault_string
));
56 XmlRpcFault::~XmlRpcFault (void) {
57 xmlrpc_env_clean(&mFault
);
60 string
XmlRpcFault::getFaultString (void) const {
61 XMLRPC_ASSERT(mFault
.fault_occurred
);
62 return string(mFault
.fault_string
);
66 //=========================================================================
68 //=========================================================================
70 XmlRpcEnv::XmlRpcEnv (const XmlRpcEnv
&env
) {
71 xmlrpc_env_init(&mEnv
);
72 if (env
.hasFaultOccurred())
73 xmlrpc_env_set_fault(&mEnv
,
75 env
.mEnv
.fault_string
);
78 XmlRpcFault
XmlRpcEnv::getFault (void) const {
79 return XmlRpcFault(&mEnv
);
82 void XmlRpcEnv::throwMe (void) const {
83 throw XmlRpcFault(&mEnv
);
87 //=========================================================================
88 // XmlRpcValue Methods
89 //=========================================================================
91 // If the user doesn't tell us what kind of value to create, use
92 // a false boolean value as the default.
93 XmlRpcValue::XmlRpcValue (void) {
95 mValue
= xmlrpc_build_value(env
, "b", (xmlrpc_bool
) 0);
96 env
.throwIfFaultOccurred();
99 XmlRpcValue
XmlRpcValue::makeInt (const XmlRpcValue::int32 i
) {
101 xmlrpc_value
*value
= xmlrpc_build_value(env
, "i", i
);
102 env
.throwIfFaultOccurred();
103 return XmlRpcValue(value
, CONSUME_REFERENCE
);
106 XmlRpcValue
XmlRpcValue::makeBool (const bool b
) {
108 xmlrpc_value
*value
= xmlrpc_build_value(env
, "b", (xmlrpc_bool
) b
);
109 env
.throwIfFaultOccurred();
110 return XmlRpcValue(value
, CONSUME_REFERENCE
);
113 XmlRpcValue
XmlRpcValue::makeDouble (const double d
) {
115 xmlrpc_value
*value
= xmlrpc_build_value(env
, "d", d
);
116 env
.throwIfFaultOccurred();
117 return XmlRpcValue(value
, CONSUME_REFERENCE
);
120 XmlRpcValue
XmlRpcValue::makeDateTime (const string
& dateTime
) {
123 const char *data
= dateTime
.c_str(); // Make sure we're not using wchar_t.
124 value
= xmlrpc_build_value(env
, "8", data
);
125 env
.throwIfFaultOccurred();
126 return XmlRpcValue(value
, CONSUME_REFERENCE
);
129 XmlRpcValue
XmlRpcValue::makeString (const string
& str
) {
131 const char *data
= str
.data(); // Make sure we're not using wchar_t.
132 size_t size
= str
.size();
133 xmlrpc_value
*value
= xmlrpc_build_value(env
, "s#", data
, size
);
134 env
.throwIfFaultOccurred();
135 return XmlRpcValue(value
, CONSUME_REFERENCE
);
138 XmlRpcValue
XmlRpcValue::makeString (const char *const str
) {
140 xmlrpc_value
*value
= xmlrpc_build_value(env
, "s", str
);
141 env
.throwIfFaultOccurred();
142 return XmlRpcValue(value
, CONSUME_REFERENCE
);
145 XmlRpcValue
XmlRpcValue::makeString (const char *const str
, size_t len
) {
147 xmlrpc_value
*value
= xmlrpc_build_value(env
, "s#", str
, len
);
148 env
.throwIfFaultOccurred();
149 return XmlRpcValue(value
, CONSUME_REFERENCE
);
152 XmlRpcValue
XmlRpcValue::makeArray (void) {
154 xmlrpc_value
*value
= xmlrpc_build_value(env
, "()");
155 env
.throwIfFaultOccurred();
156 return XmlRpcValue(value
, CONSUME_REFERENCE
);
159 XmlRpcValue
XmlRpcValue::makeStruct (void) {
161 xmlrpc_value
*value
= xmlrpc_struct_new(env
);
162 env
.throwIfFaultOccurred();
163 return XmlRpcValue(value
, CONSUME_REFERENCE
);
166 XmlRpcValue
XmlRpcValue::makeBase64 (const unsigned char *const data
,
170 xmlrpc_value
*value
= xmlrpc_build_value(env
, "6", data
, len
);
171 env
.throwIfFaultOccurred();
172 return XmlRpcValue(value
, CONSUME_REFERENCE
);
175 XmlRpcValue::int32
XmlRpcValue::getInt (void) const {
177 XmlRpcValue::int32 result
;
178 xmlrpc_parse_value(env
, mValue
, "i", &result
);
179 env
.throwIfFaultOccurred();
183 bool XmlRpcValue::getBool (void) const {
186 xmlrpc_parse_value(env
, mValue
, "b", &result
);
187 env
.throwIfFaultOccurred();
191 double XmlRpcValue::getDouble (void) const {
194 xmlrpc_parse_value(env
, mValue
, "d", &result
);
195 env
.throwIfFaultOccurred();
199 string
XmlRpcValue::getRawDateTime (void) const {
202 xmlrpc_parse_value(env
, mValue
, "8", &result
);
203 env
.throwIfFaultOccurred();
204 return string(result
);
207 string
XmlRpcValue::getString (void) const {
211 xmlrpc_parse_value(env
, mValue
, "s#", &result
, &result_len
);
212 env
.throwIfFaultOccurred();
213 return string(result
, result_len
);
217 XmlRpcValue
XmlRpcValue::getArray (void) const {
219 xmlrpc_value
*result
;
220 xmlrpc_parse_value(env
, mValue
, "A", &result
);
221 env
.throwIfFaultOccurred();
222 return XmlRpcValue(result
);
225 XmlRpcValue
XmlRpcValue::getStruct (void) const {
227 xmlrpc_value
*result
;
228 xmlrpc_parse_value(env
, mValue
, "S", &result
);
229 env
.throwIfFaultOccurred();
230 return XmlRpcValue(result
);
233 void XmlRpcValue::getBase64 (const unsigned char *& out_data
,
234 size_t& out_len
) const
237 xmlrpc_parse_value(env
, mValue
, "6", &out_data
, &out_len
);
238 env
.throwIfFaultOccurred();
241 size_t XmlRpcValue::arraySize (void) const {
243 size_t result
= xmlrpc_array_size(env
, mValue
);
244 env
.throwIfFaultOccurred();
248 void XmlRpcValue::arrayAppendItem (const XmlRpcValue
& value
) {
250 xmlrpc_array_append_item(env
, mValue
, value
.borrowReference());
251 env
.throwIfFaultOccurred();
254 XmlRpcValue
XmlRpcValue::arrayGetItem (int index
) const {
256 xmlrpc_value
*result
= xmlrpc_array_get_item(env
, mValue
, index
);
257 env
.throwIfFaultOccurred();
258 return XmlRpcValue(result
);
261 size_t XmlRpcValue::structSize (void) const {
263 size_t result
= xmlrpc_struct_size(env
, mValue
);
264 env
.throwIfFaultOccurred();
268 bool XmlRpcValue::structHasKey (const string
& key
) const {
270 const char *keystr
= key
.data();
271 size_t keylen
= key
.size();
272 bool result
= xmlrpc_struct_has_key_n(env
, mValue
,
273 const_cast<char*>(keystr
), keylen
);
274 env
.throwIfFaultOccurred();
278 XmlRpcValue
XmlRpcValue::structGetValue (const string
& key
) const {
280 const char *keystr
= key
.data();
281 size_t keylen
= key
.size();
282 xmlrpc_value
*result
=
283 xmlrpc_struct_get_value_n(env
, mValue
,
284 const_cast<char*>(keystr
), keylen
);
285 env
.throwIfFaultOccurred();
286 return XmlRpcValue(result
);
289 void XmlRpcValue::structSetValue (const string
& key
, const XmlRpcValue
& value
)
292 const char *keystr
= key
.data();
293 size_t keylen
= key
.size();
294 xmlrpc_struct_set_value_n(env
, mValue
, (char*) keystr
, keylen
,
295 value
.borrowReference());
296 env
.throwIfFaultOccurred();
299 void XmlRpcValue::structGetKeyAndValue (const int index
,
301 XmlRpcValue
& out_value
) const
305 xmlrpc_value
*key
, *value
;
306 xmlrpc_struct_get_key_and_value(env
, mValue
, index
, &key
, &value
);
307 env
.throwIfFaultOccurred();
309 out_key
= XmlRpcValue(key
).getString();
310 out_value
= XmlRpcValue(value
);
313 XmlRpcGenSrv
& XmlRpcGenSrv::addMethod (const string
& name
,
314 xmlrpc_method method
,
319 xmlrpc_registry_add_method (env
, mRegistry
, NULL
,
323 env
.throwIfFaultOccurred ();
327 XmlRpcGenSrv
& XmlRpcGenSrv::addMethod (const string
& name
,
328 xmlrpc_method method
,
330 const string
& signature
,
335 xmlrpc_registry_add_method_w_doc (env
, mRegistry
, NULL
,
341 env
.throwIfFaultOccurred ();
345 xmlrpc_mem_block
* XmlRpcGenSrv::alloc (XmlRpcEnv
& env
, const string
& body
) const
347 xmlrpc_mem_block
* result
= NULL
;
350 result
= xmlrpc_mem_block_new (env
, body
.length ());
351 env
.throwIfFaultOccurred ();
353 contents
= XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result
);
355 memcpy (contents
, body
.c_str (), body
.length ());
359 string
XmlRpcGenSrv::handle (const string
& body
) const
363 xmlrpc_mem_block
* input
= NULL
, * output
= NULL
;
364 char* input_data
, * output_data
;
365 size_t input_size
, output_size
;
367 if (body
.length () > xmlrpc_limit_get (XMLRPC_XML_SIZE_LIMIT_ID
))
368 throw XmlRpcFault (XMLRPC_LIMIT_EXCEEDED_ERROR
, "XML-RPC request too large");
370 input
= alloc (env
, body
);
371 input_data
= XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input
);
372 input_size
= XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input
);
374 output
= xmlrpc_registry_process_call (env
, mRegistry
, NULL
,
375 input_data
, input_size
);
379 output_data
= XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output
);
380 output_size
= XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output
);
382 result
.assign (output_data
, output_size
);
383 xmlrpc_mem_block_free (output
);
386 xmlrpc_mem_block_free (input
);
387 if (!result
.length ())
388 throw XmlRpcFault (env
);