File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/system_method.c |
Location: | line 37, column 37 |
Description: | Access to field 'introspectionEnabled' results in a dereference of a null pointer (loaded from variable 'registryP') |
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 | ||||||
20 | struct 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 | ||||||
32 | void | |||||
33 | xmlrpc_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 | ||||||
46 | static void | |||||
47 | callOneMethod(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", ¶mArrayP); | |||||
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 | ||||||
105 | static void | |||||
106 | getMethListFromMulticallPlist(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 | ||||||
140 | static xmlrpc_value * | |||||
141 | system_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 | ||||||
194 | static 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 | ||||||
212 | static void | |||||
213 | createMethodListArray(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 | ||||||
251 | static xmlrpc_value * | |||||
252 | system_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; | |||||
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); | |||||
264 | ||||||
265 | xmlrpc_decompose_value(envP, paramArrayP, "()"); | |||||
266 | if (!envP->fault_occurred) { | |||||
267 | if (!registryP->introspectionEnabled) | |||||
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 | ||||||
280 | static 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 | ||||||
293 | static void | |||||
294 | determineMethodExistence(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 | ||||||
309 | static xmlrpc_value * | |||||
310 | system_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 | ||||||
338 | static 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 | ||||||
352 | static void | |||||
353 | getHelpString(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 | ||||||
373 | static xmlrpc_value * | |||||
374 | system_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 | ||||||
407 | static 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 | ||||||
420 | static void | |||||
421 | buildNoSigSuppliedResult(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 | ||||||
438 | static void | |||||
439 | buildSignatureValue(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 | ||||||
476 | static void | |||||
477 | getSignatureList(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 | ||||||
541 | static xmlrpc_value * | |||||
542 | system_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 | ||||||
594 | static 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 | ||||||
610 | static xmlrpc_value * | |||||
611 | system_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 | ||||||
663 | static 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 | ||||||
676 | static void | |||||
677 | constructCapabilities(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 | ||||||
695 | static xmlrpc_value * | |||||
696 | system_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 | ||||||
725 | static 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 | ||||||
743 | static void | |||||
744 | listCapabilities(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 | ||||||
761 | static xmlrpc_value * | |||||
762 | system_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 | ||||||
791 | static 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 | ||||||
805 | static void | |||||
806 | registerSystemMethod(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 | ||||||
827 | void | |||||
828 | xmlrpc_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 |