| File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/system_method.c |
| Location: | line 403, column 5 |
| Description: | Undefined or garbage value returned to caller |
| 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 |