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
30 #include "xmlrpc-c/oldcppwrapper.hpp"
34 //=========================================================================
35 // XmlRpcFault Methods
36 //=========================================================================
38 XmlRpcFault::XmlRpcFault (const XmlRpcFault &fault) {
39 xmlrpc_env_init(&mFault);
40 xmlrpc_env_set_fault(&mFault,
41 fault.mFault.fault_code,
42 fault.mFault.fault_string);
45 XmlRpcFault::XmlRpcFault (const int faultCode, const string faultString) {
46 xmlrpc_env_init(&mFault);
47 xmlrpc_env_set_fault(&mFault, faultCode,
48 const_cast<char*>(faultString.c_str()));
51 XmlRpcFault::XmlRpcFault (const xmlrpc_env *env) {
52 if (!env->fault_string)
53 throw XmlRpcFault(XMLRPC_INTERNAL_ERROR,
54 "Tried to create empty fault");
55 xmlrpc_env_init(&mFault);
56 xmlrpc_env_set_fault(&mFault, env->fault_code,
57 const_cast<char*>(env->fault_string));
60 XmlRpcFault::~XmlRpcFault (void) {
61 xmlrpc_env_clean(&mFault);
64 string XmlRpcFault::getFaultString (void) const {
65 XMLRPC_ASSERT(mFault.fault_occurred);
66 return string(mFault.fault_string);
70 //=========================================================================
72 //=========================================================================
74 XmlRpcEnv::XmlRpcEnv (const XmlRpcEnv &env) {
75 xmlrpc_env_init(&mEnv);
76 if (env.hasFaultOccurred())
77 xmlrpc_env_set_fault(&mEnv,
79 env.mEnv.fault_string);
82 XmlRpcFault XmlRpcEnv::getFault (void) const {
83 return XmlRpcFault(&mEnv);
86 void XmlRpcEnv::throwMe (void) const {
87 throw XmlRpcFault(&mEnv);
91 //=========================================================================
92 // XmlRpcValue Methods
93 //=========================================================================
95 // If the user doesn't tell us what kind of value to create, use
96 // a false boolean value as the default.
97 XmlRpcValue::XmlRpcValue (void) {
99 mValue = xmlrpc_build_value(env, "b", (xmlrpc_bool) 0);
100 env.throwIfFaultOccurred();
103 XmlRpcValue XmlRpcValue::makeInt (const XmlRpcValue::int32 i) {
105 xmlrpc_value *value = xmlrpc_build_value(env, "i", i);
106 env.throwIfFaultOccurred();
107 return XmlRpcValue(value, CONSUME_REFERENCE);
110 XmlRpcValue XmlRpcValue::makeBool (const bool b) {
112 xmlrpc_value *value = xmlrpc_build_value(env, "b", (xmlrpc_bool) b);
113 env.throwIfFaultOccurred();
114 return XmlRpcValue(value, CONSUME_REFERENCE);
117 XmlRpcValue XmlRpcValue::makeDouble (const double d) {
119 xmlrpc_value *value = xmlrpc_build_value(env, "d", d);
120 env.throwIfFaultOccurred();
121 return XmlRpcValue(value, CONSUME_REFERENCE);
124 XmlRpcValue XmlRpcValue::makeDateTime (const string& dateTime) {
127 const char *data = dateTime.c_str(); // Make sure we're not using wchar_t.
128 value = xmlrpc_build_value(env, "8", data);
129 env.throwIfFaultOccurred();
130 return XmlRpcValue(value, CONSUME_REFERENCE);
133 XmlRpcValue XmlRpcValue::makeString (const string& str) {
135 const char *data = str.data(); // Make sure we're not using wchar_t.
136 size_t size = str.size();
137 xmlrpc_value *value = xmlrpc_build_value(env, "s#", data, size);
138 env.throwIfFaultOccurred();
139 return XmlRpcValue(value, CONSUME_REFERENCE);
142 XmlRpcValue XmlRpcValue::makeString (const char *const str) {
144 xmlrpc_value *value = xmlrpc_build_value(env, "s", str);
145 env.throwIfFaultOccurred();
146 return XmlRpcValue(value, CONSUME_REFERENCE);
149 XmlRpcValue XmlRpcValue::makeString (const char *const str, size_t len) {
151 xmlrpc_value *value = xmlrpc_build_value(env, "s#", str, len);
152 env.throwIfFaultOccurred();
153 return XmlRpcValue(value, CONSUME_REFERENCE);
156 XmlRpcValue XmlRpcValue::makeArray (void) {
158 xmlrpc_value *value = xmlrpc_build_value(env, "()");
159 env.throwIfFaultOccurred();
160 return XmlRpcValue(value, CONSUME_REFERENCE);
163 XmlRpcValue XmlRpcValue::makeStruct (void) {
165 xmlrpc_value *value = xmlrpc_struct_new(env);
166 env.throwIfFaultOccurred();
167 return XmlRpcValue(value, CONSUME_REFERENCE);
170 XmlRpcValue XmlRpcValue::makeBase64 (const unsigned char *const data,
174 xmlrpc_value *value = xmlrpc_build_value(env, "6", data, len);
175 env.throwIfFaultOccurred();
176 return XmlRpcValue(value, CONSUME_REFERENCE);
179 XmlRpcValue::int32 XmlRpcValue::getInt (void) const {
181 XmlRpcValue::int32 result;
182 xmlrpc_parse_value(env, mValue, "i", &result);
183 env.throwIfFaultOccurred();
187 bool XmlRpcValue::getBool (void) const {
190 xmlrpc_parse_value(env, mValue, "b", &result);
191 env.throwIfFaultOccurred();
195 double XmlRpcValue::getDouble (void) const {
198 xmlrpc_parse_value(env, mValue, "d", &result);
199 env.throwIfFaultOccurred();
203 string XmlRpcValue::getRawDateTime (void) const {
206 xmlrpc_parse_value(env, mValue, "8", &result);
207 env.throwIfFaultOccurred();
208 return string(result);
211 string XmlRpcValue::getString (void) const {
215 xmlrpc_parse_value(env, mValue, "s#", &result, &result_len);
216 env.throwIfFaultOccurred();
217 return string(result, result_len);
221 XmlRpcValue XmlRpcValue::getArray (void) const {
223 xmlrpc_value *result;
224 xmlrpc_parse_value(env, mValue, "A", &result);
225 env.throwIfFaultOccurred();
226 return XmlRpcValue(result);
229 XmlRpcValue XmlRpcValue::getStruct (void) const {
231 xmlrpc_value *result;
232 xmlrpc_parse_value(env, mValue, "S", &result);
233 env.throwIfFaultOccurred();
234 return XmlRpcValue(result);
237 void XmlRpcValue::getBase64 (const unsigned char *& out_data,
238 size_t& out_len) const
241 xmlrpc_parse_value(env, mValue, "6", &out_data, &out_len);
242 env.throwIfFaultOccurred();
245 size_t XmlRpcValue::arraySize (void) const {
247 size_t result = xmlrpc_array_size(env, mValue);
248 env.throwIfFaultOccurred();
252 void XmlRpcValue::arrayAppendItem (const XmlRpcValue& value) {
254 xmlrpc_array_append_item(env, mValue, value.borrowReference());
255 env.throwIfFaultOccurred();
258 XmlRpcValue XmlRpcValue::arrayGetItem (int index) const {
260 xmlrpc_value *result = xmlrpc_array_get_item(env, mValue, index);
261 env.throwIfFaultOccurred();
262 return XmlRpcValue(result);
265 size_t XmlRpcValue::structSize (void) const {
267 size_t result = xmlrpc_struct_size(env, mValue);
268 env.throwIfFaultOccurred();
272 bool XmlRpcValue::structHasKey (const string& key) const {
274 const char *keystr = key.data();
275 size_t keylen = key.size();
276 bool result = xmlrpc_struct_has_key_n(env, mValue,
277 const_cast<char*>(keystr), keylen);
278 env.throwIfFaultOccurred();
282 XmlRpcValue XmlRpcValue::structGetValue (const string& key) const {
284 const char *keystr = key.data();
285 size_t keylen = key.size();
286 xmlrpc_value *result =
287 xmlrpc_struct_get_value_n(env, mValue,
288 const_cast<char*>(keystr), keylen);
289 env.throwIfFaultOccurred();
290 return XmlRpcValue(result);
293 void XmlRpcValue::structSetValue (const string& key, const XmlRpcValue& value)
296 const char *keystr = key.data();
297 size_t keylen = key.size();
298 xmlrpc_struct_set_value_n(env, mValue, (char*) keystr, keylen,
299 value.borrowReference());
300 env.throwIfFaultOccurred();
303 void XmlRpcValue::structGetKeyAndValue (const int index,
305 XmlRpcValue& out_value) const
309 xmlrpc_value *key, *value;
310 xmlrpc_struct_get_key_and_value(env, mValue, index, &key, &value);
311 env.throwIfFaultOccurred();
313 out_key = XmlRpcValue(key).getString();
314 out_value = XmlRpcValue(value);
317 XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
318 xmlrpc_method method,
323 xmlrpc_registry_add_method (env, mRegistry, NULL,
327 env.throwIfFaultOccurred ();
331 XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
332 xmlrpc_method method,
334 const string& signature,
339 xmlrpc_registry_add_method_w_doc (env, mRegistry, NULL,
345 env.throwIfFaultOccurred ();
349 xmlrpc_mem_block* XmlRpcGenSrv::alloc (XmlRpcEnv& env, const string& body) const
351 xmlrpc_mem_block* result = NULL;
354 result = xmlrpc_mem_block_new (env, body.length ());
355 env.throwIfFaultOccurred ();
357 contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result);
359 memcpy (contents, body.c_str (), body.length ());
363 string XmlRpcGenSrv::handle (const string& body) const
367 xmlrpc_mem_block* input = NULL, * output = NULL;
368 char* input_data, * output_data;
369 size_t input_size, output_size;
371 if (body.length () > xmlrpc_limit_get (XMLRPC_XML_SIZE_LIMIT_ID))
372 throw XmlRpcFault (XMLRPC_LIMIT_EXCEEDED_ERROR, "XML-RPC request too large");
374 input = alloc (env, body);
375 input_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input);
376 input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input);
378 output = xmlrpc_registry_process_call (env, mRegistry, NULL,
379 input_data, input_size);
383 output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
384 output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
386 result.assign (output_data, output_size);
387 xmlrpc_mem_block_free (output);
390 xmlrpc_mem_block_free (input);
391 if (!result.length ())
392 throw XmlRpcFault (env);