Bug Summary

File:src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/system_method.c
Location:line 267, column 14
Description:Access to field 'introspectionEnabled' results in a dereference of a null pointer (loaded from variable 'registryP')

Annotated Source Code

1/* Copyright information is at end of file */
2
3#include "xmlrpc_config.h"
4
5#include <assert.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "xmlrpc-c/base_int.h"
10#include "xmlrpc-c/string_int.h"
11#include "xmlrpc-c/base.h"
12#include "xmlrpc-c/server.h"
13#include "version.h"
14#include "registry.h"
15#include "method.h"
16
17#include "system_method.h"
18
19
20struct systemMethodReg {
21/*----------------------------------------------------------------------------
22 Information needed to register a system method
23-----------------------------------------------------------------------------*/
24 const char * const methodName;
25 xmlrpc_method2 const methodFunction;
26 const char * const signatureString;
27 const char * const helpText;
28};
29
30
31
32void
33xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP) {
34
35 XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed(
"../../../../libs/xmlrpc-c/src/system_method.c", 35); while (
0)
;
36
37 registryP->introspectionEnabled = false;
38}
39
40
41
42/*=========================================================================
43 system.multicall
44=========================================================================*/
45
46static void
47callOneMethod(xmlrpc_env * const envP,
48 xmlrpc_registry * const registryP,
49 xmlrpc_value * const rpcDescP,
50 void * const callInfo,
51 xmlrpc_value ** const resultPP) {
52
53 const char * methodName;
54 xmlrpc_value * paramArrayP;
55
56 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 56); while (
0)
;
57
58 if (xmlrpc_value_type(rpcDescP) != XMLRPC_TYPE_STRUCT)
59 xmlrpc_env_set_fault_formatted(
60 envP, XMLRPC_TYPE_ERROR(-501),
61 "An element of the multicall array is type %u, but should "
62 "be a struct (with members 'methodName' and 'params')",
63 xmlrpc_value_type(rpcDescP));
64 else {
65 xmlrpc_decompose_value(envP, rpcDescP, "{s:s,s:A,*}",
66 "methodName", &methodName,
67 "params", &paramArrayP);
68 if (!envP->fault_occurred) {
69 /* Watch out for a deep recursion attack. */
70 if (xmlrpc_streq(methodName, "system.multicall"))
71 xmlrpc_env_set_fault_formatted(
72 envP,
73 XMLRPC_REQUEST_REFUSED_ERROR(-507),
74 "Recursive system.multicall forbidden");
75 else {
76 xmlrpc_env env;
77 xmlrpc_value * resultValP;
78
79 xmlrpc_env_init(&env);
80 xmlrpc_dispatchCall(&env, registryP, methodName, paramArrayP,
81 callInfo,
82 &resultValP);
83 if (env.fault_occurred) {
84 /* Method failed, so result is a fault structure */
85 *resultPP =
86 xmlrpc_build_value(
87 envP, "{s:i,s:s}",
88 "faultCode", (xmlrpc_int32) env.fault_code,
89 "faultString", env.fault_string);
90 } else {
91 *resultPP = xmlrpc_build_value(envP, "(V)", resultValP);
92
93 xmlrpc_DECREF(resultValP);
94 }
95 xmlrpc_env_clean(&env);
96 }
97 xmlrpc_DECREF(paramArrayP);
98 xmlrpc_strfree(methodName);
99 }
100 }
101}
102
103
104
105static void
106getMethListFromMulticallPlist(xmlrpc_env * const envP,
107 xmlrpc_value * const paramArrayP,
108 xmlrpc_value ** const methlistPP) {
109
110 if (xmlrpc_array_size(envP, paramArrayP) != 1)
111 xmlrpc_env_set_fault_formatted(
112 envP, XMLRPC_PARSE_ERROR(-503),
113 "system.multicall takes one parameter, which is an "
114 "array, each element describing one RPC. You "
115 "supplied %u arguments",
116 xmlrpc_array_size(envP, paramArrayP));
117 else {
118 xmlrpc_value * methlistP;
119
120 xmlrpc_array_read_item(envP, paramArrayP, 0, &methlistP);
121
122 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 122); while
(0)
;
123
124 if (xmlrpc_value_type(methlistP) != XMLRPC_TYPE_ARRAY)
125 xmlrpc_env_set_fault_formatted(
126 envP, XMLRPC_TYPE_ERROR(-501),
127 "system.multicall's parameter should be an array, "
128 "each element describing one RPC. But it is type "
129 "%u instead.", xmlrpc_value_type(methlistP));
130 else
131 *methlistPP = methlistP;
132
133 if (envP->fault_occurred)
134 xmlrpc_DECREF(methlistP);
135 }
136}
137
138
139
140static xmlrpc_value *
141system_multicall(xmlrpc_env * const envP,
142 xmlrpc_value * const paramArrayP,
143 void * const serverInfo,
144 void * const callInfo) {
145
146 xmlrpc_registry * registryP;
147 xmlrpc_value * resultsP;
148 xmlrpc_value * methlistP;
149
150 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 150); while
(0)
;
151 XMLRPC_ASSERT_ARRAY_OK(paramArrayP)xmlrpc_abort_if_array_bad(paramArrayP);
152 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 152); while
(0)
;
153
154 resultsP = NULL((void*)0); /* defeat compiler warning */
155
156 /* Turn our arguments into something more useful. */
157 registryP = (xmlrpc_registry*) serverInfo;
158
159 getMethListFromMulticallPlist(envP, paramArrayP, &methlistP);
160 if (!envP->fault_occurred) {
161 /* Create an initially empty result list. */
162 resultsP = xmlrpc_array_new(envP);
163 if (!envP->fault_occurred) {
164 /* Loop over our input list, calling each method in turn. */
165 unsigned int const methodCount =
166 xmlrpc_array_size(envP, methlistP);
167 unsigned int i;
168 for (i = 0; i < methodCount && !envP->fault_occurred; ++i) {
169 xmlrpc_value * const methinfoP =
170 xmlrpc_array_get_item(envP, methlistP, i);
171
172 xmlrpc_value * resultP;
173
174 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 174); while
(0)
;
175
176 callOneMethod(envP, registryP, methinfoP, callInfo, &resultP);
177
178 if (!envP->fault_occurred) {
179 /* Append this method result to our master array. */
180 xmlrpc_array_append_item(envP, resultsP, resultP);
181 xmlrpc_DECREF(resultP);
182 }
183 }
184 if (envP->fault_occurred)
185 xmlrpc_DECREF(resultsP);
186 xmlrpc_DECREF(methlistP);
187 }
188 }
189 return resultsP;
190}
191
192
193
194static struct systemMethodReg const methodMulticall = {
195 "system.multicall",
196 &system_multicall,
197 "A:A",
198 "Process an array of calls, and return an array of results. Calls should "
199 "be structs of the form {'methodName': string, 'params': array}. Each "
200 "result will either be a single-item array containg the result value, or "
201 "a struct of the form {'faultCode': int, 'faultString': string}. This "
202 "is useful when you need to make lots of small calls without lots of "
203 "round trips.",
204};
205
206
207/*=========================================================================
208 system.listMethods
209=========================================================================*/
210
211
212static void
213createMethodListArray(xmlrpc_env * const envP,
214 xmlrpc_registry * const registryP,
215 xmlrpc_value ** const methodListPP) {
216/*----------------------------------------------------------------------------
217 Create as an XML-RPC array value a list of names of methods registered
218 in registry 'registryP'.
219
220 This is the type of value that the system.listMethods method is supposed
221 to return.
222-----------------------------------------------------------------------------*/
223 xmlrpc_value * methodListP;
224
225 methodListP = xmlrpc_array_new(envP);
226
227 if (!envP->fault_occurred) {
228 xmlrpc_methodNode * methodNodeP;
229 for (methodNodeP = registryP->methodListP->firstMethodP;
230 methodNodeP && !envP->fault_occurred;
231 methodNodeP = methodNodeP->nextP) {
232
233 xmlrpc_value * methodNameVP;
234
235 methodNameVP = xmlrpc_string_new(envP, methodNodeP->methodName);
236
237 if (!envP->fault_occurred) {
238 xmlrpc_array_append_item(envP, methodListP, methodNameVP);
239
240 xmlrpc_DECREF(methodNameVP);
241 }
242 }
243 if (envP->fault_occurred)
244 xmlrpc_DECREF(methodListP);
245 }
246 *methodListPP = methodListP;
247}
248
249
250
251static xmlrpc_value *
252system_listMethods(xmlrpc_env * const envP,
253 xmlrpc_value * const paramArrayP,
254 void * const serverInfo,
255 void * const callInfo ATTR_UNUSED__attribute__((__unused__))) {
256
257 xmlrpc_registry * const registryP = serverInfo;
1
'registryP' initialized here
258
259 xmlrpc_value * retvalP;
260
261 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 261); while
(0)
;
262 XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP)
->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/system_method.c"
, 262); while (0)
;
263 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 263); while
(0)
;
2
Within the expansion of the macro 'XMLRPC_ASSERT_PTR_OK':
a
Assuming 'serverInfo' is equal to null
264
265 xmlrpc_decompose_value(envP, paramArrayP, "()");
266 if (!envP->fault_occurred) {
3
Taking true branch
267 if (!registryP->introspectionEnabled)
4
Access to field 'introspectionEnabled' results in a dereference of a null pointer (loaded from variable 'registryP')
268 xmlrpc_env_set_fault_formatted(
269 envP, XMLRPC_INTROSPECTION_DISABLED_ERROR(-508),
270 "Introspection is disabled in this server "
271 "for security reasons");
272 else
273 createMethodListArray(envP, registryP, &retvalP);
274 }
275 return retvalP;
276}
277
278
279
280static struct systemMethodReg const methodListMethods = {
281 "system.listMethods",
282 &system_listMethods,
283 "A:",
284 "Return an array of all available XML-RPC methods on this server.",
285};
286
287
288
289/*=========================================================================
290 system.methodExist
291==========================================================================*/
292
293static void
294determineMethodExistence(xmlrpc_env * const envP,
295 const char * const methodName,
296 xmlrpc_registry * const registryP,
297 xmlrpc_value ** const existsPP) {
298
299 xmlrpc_methodInfo * methodP;
300
301 xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
302 &methodP);
303
304 *existsPP = xmlrpc_bool_new(envP, !!methodP);
305}
306
307
308
309static xmlrpc_value *
310system_methodExist(xmlrpc_env * const envP,
311 xmlrpc_value * const paramArrayP,
312 void * const serverInfo,
313 void * const callInfo ATTR_UNUSED__attribute__((__unused__))) {
314
315 xmlrpc_registry * const registryP = serverInfo;
316
317 xmlrpc_value * retvalP;
318
319 const char * methodName;
320
321 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 321); while
(0)
;
322 XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP)
->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/system_method.c"
, 322); while (0)
;
323 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 323); while
(0)
;
324
325 xmlrpc_decompose_value(envP, paramArrayP, "(s)", &methodName);
326
327 if (!envP->fault_occurred) {
328 determineMethodExistence(envP, methodName, registryP, &retvalP);
329
330 xmlrpc_strfree(methodName);
331 }
332
333 return retvalP;
334}
335
336
337
338static struct systemMethodReg const methodMethodExist = {
339 "system.methodExist",
340 &system_methodExist,
341 "s:b",
342 "Tell whether a method by a specified name exists on this server",
343};
344
345
346
347/*=========================================================================
348 system.methodHelp
349=========================================================================*/
350
351
352static void
353getHelpString(xmlrpc_env * const envP,
354 const char * const methodName,
355 xmlrpc_registry * const registryP,
356 xmlrpc_value ** const helpStringPP) {
357
358 xmlrpc_methodInfo * methodP;
359
360 xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
361 &methodP);
362
363 if (!methodP)
364 xmlrpc_env_set_fault_formatted(
365 envP, XMLRPC_NO_SUCH_METHOD_ERROR(-506),
366 "Method '%s' does not exist", methodName);
367 else
368 *helpStringPP = xmlrpc_string_new(envP, methodP->helpText);
369}
370
371
372
373static xmlrpc_value *
374system_methodHelp(xmlrpc_env * const envP,
375 xmlrpc_value * const paramArrayP,
376 void * const serverInfo,
377 void * const callInfo ATTR_UNUSED__attribute__((__unused__))) {
378
379 xmlrpc_registry * const registryP = serverInfo;
380
381 xmlrpc_value * retvalP;
382
383 const char * methodName;
384
385 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 385); while
(0)
;
386 XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP)
->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/system_method.c"
, 386); while (0)
;
387 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 387); while
(0)
;
388
389 xmlrpc_decompose_value(envP, paramArrayP, "(s)", &methodName);
390
391 if (!envP->fault_occurred) {
392 if (!registryP->introspectionEnabled)
393 xmlrpc_env_set_fault_formatted(
394 envP, XMLRPC_INTROSPECTION_DISABLED_ERROR(-508),
395 "Introspection is disabled in this server "
396 "for security reasons");
397 else
398 getHelpString(envP, methodName, registryP, &retvalP);
399
400 xmlrpc_strfree(methodName);
401 }
402
403 return retvalP;
404}
405
406
407static struct systemMethodReg const methodMethodHelp = {
408 "system.methodHelp",
409 &system_methodHelp,
410 "s:s",
411 "Given the name of a method, return a help string.",
412};
413
414
415
416/*=========================================================================
417 system.methodSignature
418==========================================================================*/
419
420static void
421buildNoSigSuppliedResult(xmlrpc_env * const envP,
422 xmlrpc_value ** const resultPP) {
423
424 xmlrpc_env env;
425
426 xmlrpc_env_init(&env);
427
428 *resultPP = xmlrpc_string_new(&env, "undef");
429 if (env.fault_occurred)
430 xmlrpc_faultf(envP, "Unable to construct 'undef'. %s",
431 env.fault_string);
432
433 xmlrpc_env_clean(&env);
434}
435
436
437
438static void
439buildSignatureValue(xmlrpc_env * const envP,
440 struct xmlrpc_signature * const signatureP,
441 xmlrpc_value ** const sigValuePP) {
442
443 xmlrpc_value * sigValueP;
444 unsigned int i;
445
446 sigValueP = xmlrpc_array_new(envP);
447
448 {
449 xmlrpc_value * retTypeVP;
450
451 retTypeVP = xmlrpc_string_new(envP, signatureP->retType);
452
453 xmlrpc_array_append_item(envP, sigValueP, retTypeVP);
454
455 xmlrpc_DECREF(retTypeVP);
456 }
457 for (i = 0; i < signatureP->argCount && !envP->fault_occurred; ++i) {
458 xmlrpc_value * argTypeVP;
459
460 argTypeVP = xmlrpc_string_new(envP, signatureP->argList[i]);
461 if (!envP->fault_occurred) {
462 xmlrpc_array_append_item(envP, sigValueP, argTypeVP);
463
464 xmlrpc_DECREF(argTypeVP);
465 }
466 }
467
468 if (envP->fault_occurred)
469 xmlrpc_DECREF(sigValueP);
470
471 *sigValuePP = sigValueP;
472}
473
474
475
476static void
477getSignatureList(xmlrpc_env * const envP,
478 xmlrpc_registry * const registryP,
479 const char * const methodName,
480 xmlrpc_value ** const signatureListPP) {
481/*----------------------------------------------------------------------------
482 Get the signature list array for method named 'methodName' from registry
483 'registryP'.
484
485 If there is no signature information for the method in the registry,
486 return *signatureListPP == NULL.
487
488 Nonexistent method is considered a failure.
489-----------------------------------------------------------------------------*/
490 xmlrpc_methodInfo * methodP;
491
492 xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
493 &methodP);
494
495 if (!methodP)
496 xmlrpc_env_set_fault_formatted(
497 envP, XMLRPC_NO_SUCH_METHOD_ERROR(-506),
498 "Method '%s' does not exist", methodName);
499 else {
500 if (!methodP->signatureListP->firstSignatureP)
501 *signatureListPP = NULL((void*)0);
502 else {
503 xmlrpc_value * signatureListP;
504
505 signatureListP = xmlrpc_array_new(envP);
506
507 if (!envP->fault_occurred) {
508 struct xmlrpc_signature * signatureP;
509 for (signatureP = methodP->signatureListP->firstSignatureP;
510 signatureP && !envP->fault_occurred;
511 signatureP = signatureP->nextP) {
512
513 xmlrpc_value * signatureVP = NULL((void*)0);
514
515 buildSignatureValue(envP, signatureP, &signatureVP);
516
517 xmlrpc_array_append_item(envP,
518 signatureListP, signatureVP);
519
520 xmlrpc_DECREF(signatureVP);
521 }
522 if (envP->fault_occurred)
523 xmlrpc_DECREF(signatureListP);
524 }
525 *signatureListPP = signatureListP;
526 }
527 }
528}
529
530
531
532/* Microsoft Visual C in debug mode produces code that complains about
533 returning an undefined value from system_methodSignature(). It's a bogus
534 complaint, because this function is defined to return nothing meaningful
535 those cases. So we disable the check.
536*/
537#pragma runtime_checks("u", off)
538
539
540
541static xmlrpc_value *
542system_methodSignature(xmlrpc_env * const envP,
543 xmlrpc_value * const paramArrayP,
544 void * const serverInfo,
545 void * const callInfo ATTR_UNUSED__attribute__((__unused__))) {
546
547 xmlrpc_registry * const registryP = (xmlrpc_registry *) serverInfo;
548
549 xmlrpc_value * retvalP;
550 const char * methodName;
551 xmlrpc_env env;
552
553 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 553); while
(0)
;
554 XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP)
->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/system_method.c"
, 554); while (0)
;
555 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 555); while
(0)
;
556
557 xmlrpc_env_init(&env);
558
559 /* Turn our arguments into something more useful. */
560 xmlrpc_decompose_value(&env, paramArrayP, "(s)", &methodName);
561 if (env.fault_occurred)
562 xmlrpc_env_set_fault_formatted(
563 envP, env.fault_code,
564 "Invalid parameter list. %s", env.fault_string);
565 else {
566 if (!registryP->introspectionEnabled)
567 xmlrpc_env_set_fault(envP, XMLRPC_INTROSPECTION_DISABLED_ERROR(-508),
568 "Introspection disabled on this server");
569 else {
570 xmlrpc_value * signatureListP;
571
572 getSignatureList(envP, registryP, methodName, &signatureListP);
573
574 if (!envP->fault_occurred) {
575 if (signatureListP)
576 retvalP = signatureListP;
577 else
578 buildNoSigSuppliedResult(envP, &retvalP);
579 }
580 }
581 xmlrpc_strfree(methodName);
582 }
583 xmlrpc_env_clean(&env);
584
585 return retvalP;
586}
587
588
589
590#pragma runtime_checks("u", restore)
591
592
593
594static struct systemMethodReg const methodMethodSignature = {
595 "system.methodSignature",
596 &system_methodSignature,
597 "A:s",
598 "Given the name of a method, return an array of legal signatures. "
599 "Each signature is an array of strings. The first item of each signature "
600 "is the return type, and any others items are parameter types.",
601};
602
603
604
605
606/*=========================================================================
607 system.shutdown
608==========================================================================*/
609
610static xmlrpc_value *
611system_shutdown(xmlrpc_env * const envP,
612 xmlrpc_value * const paramArrayP,
613 void * const serverInfo,
614 void * const callInfo) {
615
616 xmlrpc_registry * const registryP = (xmlrpc_registry *) serverInfo;
617
618 xmlrpc_value * retvalP;
619 const char * comment;
620 xmlrpc_env env;
621
622 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 622); while
(0)
;
623 XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP)
->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/system_method.c"
, 623); while (0)
;
624 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 624); while
(0)
;
625
626 xmlrpc_env_init(&env);
627
628 /* Turn our arguments into something more useful. */
629 xmlrpc_decompose_value(&env, paramArrayP, "(s)", &comment);
630 if (env.fault_occurred)
631 xmlrpc_env_set_fault_formatted(
632 envP, env.fault_code,
633 "Invalid parameter list. %s", env.fault_string);
634 else {
635 if (!registryP->shutdownServerFn)
636 xmlrpc_env_set_fault(
637 envP, 0, "This server program is not capable of "
638 "shutting down");
639 else {
640 registryP->shutdownServerFn(
641 &env, registryP->shutdownContext, comment, callInfo);
642
643 if (env.fault_occurred)
644 xmlrpc_env_set_fault(envP, env.fault_code, env.fault_string);
645 else {
646 retvalP = xmlrpc_int_new(&env, 0);
647
648 if (env.fault_occurred)
649 xmlrpc_faultf(envP,
650 "Failed to construct return value. %s",
651 env.fault_string);
652 }
653 }
654 xmlrpc_strfree(comment);
655 }
656 xmlrpc_env_clean(&env);
657
658 return retvalP;
659}
660
661
662
663static struct systemMethodReg const methodShutdown = {
664 "system.shutdown",
665 &system_shutdown,
666 "i:s",
667 "Shut down the server. Return code is always zero.",
668};
669
670
671
672/*=========================================================================
673 system.capabilities
674=========================================================================*/
675
676static void
677constructCapabilities(xmlrpc_env * const envP,
678 xmlrpc_registry * const registryP ATTR_UNUSED__attribute__((__unused__)),
679 xmlrpc_value ** const capabilitiesPP) {
680
681 *capabilitiesPP =
682 xmlrpc_build_value(
683 envP, "{s:s,s:i,s:i,s:i,s:i}",
684 "facility", "xmlrpc-c",
685 "version_major", XMLRPC_VERSION_MAJOR1,
686 "version_minor", XMLRPC_VERSION_MINOR26,
687 "version_point", XMLRPC_VERSION_POINT0,
688 "protocol_version", 2
689 );
690
691}
692
693
694
695static xmlrpc_value *
696system_capabilities(xmlrpc_env * const envP,
697 xmlrpc_value * const paramArrayP,
698 void * const serverInfo,
699 void * const callInfo ATTR_UNUSED__attribute__((__unused__))) {
700
701 xmlrpc_registry * const registryP = serverInfo;
702
703 xmlrpc_value * retvalP;
704
705 unsigned int paramCount;
706
707 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 707); while
(0)
;
708 XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP)
->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/system_method.c"
, 708); while (0)
;
709 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 709); while
(0)
;
710
711 paramCount = xmlrpc_array_size(envP, paramArrayP);
712
713 if (paramCount > 0)
714 xmlrpc_env_set_fault_formatted(
715 envP, XMLRPC_INDEX_ERROR(-502),
716 "There are no parameters. You supplied %u", paramCount);
717 else
718 constructCapabilities(envP, registryP, &retvalP);
719
720 return retvalP;
721}
722
723
724
725static struct systemMethodReg const methodCapabilities = {
726 "system.capabilities",
727 &system_capabilities,
728 "S:",
729 "Return the capabilities of XML-RPC server. This includes the "
730 "version number of the XML-RPC For C/C++ software"
731};
732
733
734
735/*=========================================================================
736 system.getCapabilities
737=========================================================================*/
738
739/* This implements a standard.
740 See http://tech.groups.yahoo.com/group/xml-rpc/message/2897 .
741*/
742
743static void
744listCapabilities(xmlrpc_env * const envP,
745 xmlrpc_registry * const registryP ATTR_UNUSED__attribute__((__unused__)),
746 xmlrpc_value ** const capabilitiesPP) {
747
748 *capabilitiesPP =
749 xmlrpc_build_value(
750 envP, "{s:{s:s,s:i}}",
751 "introspect",
752 "specUrl",
753 "http://xmlrpc-c.sourceforge.net/xmlrpc-c/introspection.html",
754 "specVersion",
755 1
756 );
757}
758
759
760
761static xmlrpc_value *
762system_getCapabilities(xmlrpc_env * const envP,
763 xmlrpc_value * const paramArrayP,
764 void * const serverInfo,
765 void * const callInfo ATTR_UNUSED__attribute__((__unused__))) {
766
767 xmlrpc_registry * const registryP = serverInfo;
768
769 xmlrpc_value * retvalP;
770
771 unsigned int paramCount;
772
773 XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string
== ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 773); while
(0)
;
774 XMLRPC_ASSERT_VALUE_OK(paramArrayP)do if (!((paramArrayP) != ((void*)0) && (paramArrayP)
->_type != XMLRPC_TYPE_DEAD)) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/system_method.c"
, 774); while (0)
;
775 XMLRPC_ASSERT_PTR_OK(serverInfo)do if (!((serverInfo) != ((void*)0))) xmlrpc_assertion_failed
("../../../../libs/xmlrpc-c/src/system_method.c", 775); while
(0)
;
776
777 paramCount = xmlrpc_array_size(envP, paramArrayP);
778
779 if (paramCount > 0)
780 xmlrpc_env_set_fault_formatted(
781 envP, XMLRPC_INDEX_ERROR(-502),
782 "There are no parameters. You supplied %u", paramCount);
783 else
784 listCapabilities(envP, registryP, &retvalP);
785
786 return retvalP;
787}
788
789
790
791static struct systemMethodReg const methodGetCapabilities = {
792 "system.getCapabilities",
793 &system_getCapabilities,
794 "S:",
795 "Return the list of standard capabilities of XML-RPC server. "
796 "See http://tech.groups.yahoo.com/group/xml-rpc/message/2897"
797};
798
799
800
801/*============================================================================
802 Installer of system methods
803============================================================================*/
804
805static void
806registerSystemMethod(xmlrpc_env * const envP,
807 xmlrpc_registry * const registryP,
808 struct systemMethodReg const methodReg) {
809
810 xmlrpc_env env;
811 xmlrpc_env_init(&env);
812
813 xmlrpc_registry_add_method2(
814 &env, registryP, methodReg.methodName,
815 methodReg.methodFunction,
816 methodReg.signatureString, methodReg.helpText, registryP);
817
818 if (env.fault_occurred)
819 xmlrpc_faultf(envP, "Failed to register '%s' system method. %s",
820 methodReg.methodName, env.fault_string);
821
822 xmlrpc_env_clean(&env);
823}
824
825
826
827void
828xmlrpc_installSystemMethods(xmlrpc_env * const envP,
829 xmlrpc_registry * const registryP) {
830/*----------------------------------------------------------------------------
831 Install the built-in methods (system.*) into registry 'registryP'.
832-----------------------------------------------------------------------------*/
833 if (!envP->fault_occurred)
834 registerSystemMethod(envP, registryP, methodListMethods);
835
836 if (!envP->fault_occurred)
837 registerSystemMethod(envP, registryP, methodMethodExist);
838
839 if (!envP->fault_occurred)
840 registerSystemMethod(envP, registryP, methodMethodHelp);
841
842 if (!envP->fault_occurred)
843 registerSystemMethod(envP, registryP, methodMethodSignature);
844
845 if (!envP->fault_occurred)
846 registerSystemMethod(envP, registryP, methodMulticall);
847
848 if (!envP->fault_occurred)
849 registerSystemMethod(envP, registryP, methodShutdown);
850
851 if (!envP->fault_occurred)
852 registerSystemMethod(envP, registryP, methodCapabilities);
853
854 if (!envP->fault_occurred)
855 registerSystemMethod(envP, registryP, methodGetCapabilities);
856}
857
858
859
860/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
861** Copyright (C) 2001 by Eric Kidd. All rights reserved.
862** Copyright (C) 2001 by Luke Howard. All rights reserved.
863**
864** Redistribution and use in source and binary forms, with or without
865** modification, are permitted provided that the following conditions
866** are met:
867** 1. Redistributions of source code must retain the above copyright
868** notice, this list of conditions and the following disclaimer.
869** 2. Redistributions in binary form must reproduce the above copyright
870** notice, this list of conditions and the following disclaimer in the
871** documentation and/or other materials provided with the distribution.
872** 3. The name of the author may not be used to endorse or promote products
873** derived from this software without specific prior written permission.
874**
875** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
876** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
877** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
878** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
879** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
880** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
881** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
882** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
883** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
884** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
885** SUCH DAMAGE. */
886