Initial commit.
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmxmlrpc / XmlRpcCpp.cpp
blob119b6951d22103378115d16d972090bf8d60c156
1 // Copyright (C) 2001 by Eric Kidd. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions
5 // are met:
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.
13 //
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
24 // SUCH DAMAGE.
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 //=========================================================================
67 // XmlRpcEnv Methods
68 //=========================================================================
70 XmlRpcEnv::XmlRpcEnv (const XmlRpcEnv &env) {
71 xmlrpc_env_init(&mEnv);
72 if (env.hasFaultOccurred())
73 xmlrpc_env_set_fault(&mEnv,
74 env.mEnv.fault_code,
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) {
94 XmlRpcEnv env;
95 mValue = xmlrpc_build_value(env, "b", (xmlrpc_bool) 0);
96 env.throwIfFaultOccurred();
99 XmlRpcValue XmlRpcValue::makeInt (const XmlRpcValue::int32 i) {
100 XmlRpcEnv env;
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) {
107 XmlRpcEnv env;
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) {
114 XmlRpcEnv env;
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) {
121 XmlRpcEnv env;
122 xmlrpc_value *value;
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) {
130 XmlRpcEnv env;
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) {
139 XmlRpcEnv env;
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) {
146 XmlRpcEnv env;
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) {
153 XmlRpcEnv env;
154 xmlrpc_value *value = xmlrpc_build_value(env, "()");
155 env.throwIfFaultOccurred();
156 return XmlRpcValue(value, CONSUME_REFERENCE);
159 XmlRpcValue XmlRpcValue::makeStruct (void) {
160 XmlRpcEnv env;
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,
167 size_t len)
169 XmlRpcEnv env;
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 {
176 XmlRpcEnv env;
177 XmlRpcValue::int32 result;
178 xmlrpc_parse_value(env, mValue, "i", &result);
179 env.throwIfFaultOccurred();
180 return result;
183 bool XmlRpcValue::getBool (void) const {
184 XmlRpcEnv env;
185 xmlrpc_bool result;
186 xmlrpc_parse_value(env, mValue, "b", &result);
187 env.throwIfFaultOccurred();
188 return result;
191 double XmlRpcValue::getDouble (void) const {
192 XmlRpcEnv env;
193 double result;
194 xmlrpc_parse_value(env, mValue, "d", &result);
195 env.throwIfFaultOccurred();
196 return result;
199 string XmlRpcValue::getRawDateTime (void) const {
200 XmlRpcEnv env;
201 char *result;
202 xmlrpc_parse_value(env, mValue, "8", &result);
203 env.throwIfFaultOccurred();
204 return string(result);
207 string XmlRpcValue::getString (void) const {
208 XmlRpcEnv env;
209 char *result;
210 size_t result_len;
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 {
218 XmlRpcEnv env;
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 {
226 XmlRpcEnv env;
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
236 XmlRpcEnv env;
237 xmlrpc_parse_value(env, mValue, "6", &out_data, &out_len);
238 env.throwIfFaultOccurred();
241 size_t XmlRpcValue::arraySize (void) const {
242 XmlRpcEnv env;
243 size_t result = xmlrpc_array_size(env, mValue);
244 env.throwIfFaultOccurred();
245 return result;
248 void XmlRpcValue::arrayAppendItem (const XmlRpcValue& value) {
249 XmlRpcEnv env;
250 xmlrpc_array_append_item(env, mValue, value.borrowReference());
251 env.throwIfFaultOccurred();
254 XmlRpcValue XmlRpcValue::arrayGetItem (int index) const {
255 XmlRpcEnv env;
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 {
262 XmlRpcEnv env;
263 size_t result = xmlrpc_struct_size(env, mValue);
264 env.throwIfFaultOccurred();
265 return result;
268 bool XmlRpcValue::structHasKey (const string& key) const {
269 XmlRpcEnv env;
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();
275 return result;
278 XmlRpcValue XmlRpcValue::structGetValue (const string& key) const {
279 XmlRpcEnv env;
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)
291 XmlRpcEnv env;
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,
300 string& out_key,
301 XmlRpcValue& out_value) const
303 XmlRpcEnv env;
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,
315 void *data)
317 XmlRpcEnv env;
319 xmlrpc_registry_add_method (env, mRegistry, NULL,
320 name.c_str (),
321 method, data);
323 env.throwIfFaultOccurred ();
324 return (*this);
327 XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
328 xmlrpc_method method,
329 void* data,
330 const string& signature,
331 const string& help)
333 XmlRpcEnv env;
335 xmlrpc_registry_add_method_w_doc (env, mRegistry, NULL,
336 name.c_str (),
337 method, data,
338 signature.c_str (),
339 help.c_str ());
341 env.throwIfFaultOccurred ();
342 return (*this);
345 xmlrpc_mem_block* XmlRpcGenSrv::alloc (XmlRpcEnv& env, const string& body) const
347 xmlrpc_mem_block* result = NULL;
348 char* contents;
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 ());
356 return result;
359 string XmlRpcGenSrv::handle (const string& body) const
361 XmlRpcEnv env;
362 string result;
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);
377 if (output)
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);
390 return result;