747 lines
23 KiB
C
747 lines
23 KiB
C
/* Copyright information is at end of file */
|
|
|
|
#include "xmlrpc_config.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "xmlrpc-c/base_int.h"
|
|
#include "xmlrpc-c/string_int.h"
|
|
#include "xmlrpc-c/base.h"
|
|
#include "xmlrpc-c/server.h"
|
|
#include "version.h"
|
|
#include "registry.h"
|
|
#include "method.h"
|
|
|
|
#include "system_method.h"
|
|
|
|
|
|
struct systemMethodReg {
|
|
/*----------------------------------------------------------------------------
|
|
Information needed to register a system method
|
|
-----------------------------------------------------------------------------*/
|
|
const char * const methodName;
|
|
xmlrpc_method2 const methodFunction;
|
|
const char * const signatureString;
|
|
const char * const helpText;
|
|
};
|
|
|
|
|
|
|
|
void
|
|
xmlrpc_registry_disable_introspection(xmlrpc_registry * const registryP) {
|
|
|
|
XMLRPC_ASSERT_PTR_OK(registryP);
|
|
|
|
registryP->introspectionEnabled = false;
|
|
}
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
system.multicall
|
|
=========================================================================*/
|
|
|
|
static void
|
|
callOneMethod(xmlrpc_env * const envP,
|
|
xmlrpc_registry * const registryP,
|
|
xmlrpc_value * const rpcDescP,
|
|
void * const callInfo,
|
|
xmlrpc_value ** const resultPP) {
|
|
|
|
const char * methodName;
|
|
xmlrpc_value * paramArrayP;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
|
|
if (xmlrpc_value_type(rpcDescP) != XMLRPC_TYPE_STRUCT)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_TYPE_ERROR,
|
|
"An element of the multicall array is type %u, but should "
|
|
"be a struct (with members 'methodName' and 'params')",
|
|
xmlrpc_value_type(rpcDescP));
|
|
else {
|
|
xmlrpc_decompose_value(envP, rpcDescP, "{s:s,s:A,*}",
|
|
"methodName", &methodName,
|
|
"params", ¶mArrayP);
|
|
if (!envP->fault_occurred) {
|
|
/* Watch out for a deep recursion attack. */
|
|
if (xmlrpc_streq(methodName, "system.multicall"))
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP,
|
|
XMLRPC_REQUEST_REFUSED_ERROR,
|
|
"Recursive system.multicall forbidden");
|
|
else {
|
|
xmlrpc_env env;
|
|
xmlrpc_value * resultValP;
|
|
|
|
xmlrpc_env_init(&env);
|
|
xmlrpc_dispatchCall(&env, registryP, methodName, paramArrayP,
|
|
callInfo,
|
|
&resultValP);
|
|
if (env.fault_occurred) {
|
|
/* Method failed, so result is a fault structure */
|
|
*resultPP =
|
|
xmlrpc_build_value(
|
|
envP, "{s:i,s:s}",
|
|
"faultCode", (xmlrpc_int32) env.fault_code,
|
|
"faultString", env.fault_string);
|
|
} else {
|
|
*resultPP = xmlrpc_build_value(envP, "(V)", resultValP);
|
|
|
|
xmlrpc_DECREF(resultValP);
|
|
}
|
|
xmlrpc_env_clean(&env);
|
|
}
|
|
xmlrpc_DECREF(paramArrayP);
|
|
xmlrpc_strfree(methodName);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
getMethListFromMulticallPlist(xmlrpc_env * const envP,
|
|
xmlrpc_value * const paramArrayP,
|
|
xmlrpc_value ** const methlistPP) {
|
|
|
|
if (xmlrpc_array_size(envP, paramArrayP) != 1)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_PARSE_ERROR,
|
|
"system.multicall takes one parameter, which is an "
|
|
"array, each element describing one RPC. You "
|
|
"supplied %u arguments",
|
|
xmlrpc_array_size(envP, paramArrayP));
|
|
else {
|
|
xmlrpc_value * methlistP;
|
|
|
|
xmlrpc_array_read_item(envP, paramArrayP, 0, &methlistP);
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
|
|
if (xmlrpc_value_type(methlistP) != XMLRPC_TYPE_ARRAY)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_TYPE_ERROR,
|
|
"system.multicall's parameter should be an array, "
|
|
"each element describing one RPC. But it is type "
|
|
"%u instead.", xmlrpc_value_type(methlistP));
|
|
else
|
|
*methlistPP = methlistP;
|
|
|
|
if (envP->fault_occurred)
|
|
xmlrpc_DECREF(methlistP);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
system_multicall(xmlrpc_env * const envP,
|
|
xmlrpc_value * const paramArrayP,
|
|
void * const serverInfo,
|
|
void * const callInfo) {
|
|
|
|
xmlrpc_registry * registryP;
|
|
xmlrpc_value * resultsP;
|
|
xmlrpc_value * methlistP;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
XMLRPC_ASSERT_ARRAY_OK(paramArrayP);
|
|
XMLRPC_ASSERT_PTR_OK(serverInfo);
|
|
|
|
resultsP = NULL; /* defeat compiler warning */
|
|
|
|
/* Turn our arguments into something more useful. */
|
|
registryP = (xmlrpc_registry*) serverInfo;
|
|
|
|
getMethListFromMulticallPlist(envP, paramArrayP, &methlistP);
|
|
if (!envP->fault_occurred) {
|
|
/* Create an initially empty result list. */
|
|
resultsP = xmlrpc_array_new(envP);
|
|
if (!envP->fault_occurred) {
|
|
/* Loop over our input list, calling each method in turn. */
|
|
unsigned int const methodCount =
|
|
xmlrpc_array_size(envP, methlistP);
|
|
unsigned int i;
|
|
for (i = 0; i < methodCount && !envP->fault_occurred; ++i) {
|
|
xmlrpc_value * const methinfoP =
|
|
xmlrpc_array_get_item(envP, methlistP, i);
|
|
|
|
xmlrpc_value * resultP;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
|
|
callOneMethod(envP, registryP, methinfoP, callInfo, &resultP);
|
|
|
|
if (!envP->fault_occurred) {
|
|
/* Append this method result to our master array. */
|
|
xmlrpc_array_append_item(envP, resultsP, resultP);
|
|
xmlrpc_DECREF(resultP);
|
|
}
|
|
}
|
|
if (envP->fault_occurred)
|
|
xmlrpc_DECREF(resultsP);
|
|
xmlrpc_DECREF(methlistP);
|
|
}
|
|
}
|
|
return resultsP;
|
|
}
|
|
|
|
|
|
|
|
static struct systemMethodReg const methodMulticall = {
|
|
"system.multicall",
|
|
&system_multicall,
|
|
"A:A",
|
|
"Process an array of calls, and return an array of results. Calls should "
|
|
"be structs of the form {'methodName': string, 'params': array}. Each "
|
|
"result will either be a single-item array containg the result value, or "
|
|
"a struct of the form {'faultCode': int, 'faultString': string}. This "
|
|
"is useful when you need to make lots of small calls without lots of "
|
|
"round trips.",
|
|
};
|
|
|
|
|
|
/*=========================================================================
|
|
system.listMethods
|
|
=========================================================================*/
|
|
|
|
|
|
static void
|
|
createMethodListArray(xmlrpc_env * const envP,
|
|
xmlrpc_registry * const registryP,
|
|
xmlrpc_value ** const methodListPP) {
|
|
/*----------------------------------------------------------------------------
|
|
Create as an XML-RPC array value a list of names of methods registered
|
|
in registry 'registryP'.
|
|
|
|
This is the type of value that the system.listMethods method is supposed
|
|
to return.
|
|
-----------------------------------------------------------------------------*/
|
|
xmlrpc_value * methodListP;
|
|
|
|
methodListP = xmlrpc_array_new(envP);
|
|
|
|
if (!envP->fault_occurred) {
|
|
xmlrpc_methodNode * methodNodeP;
|
|
for (methodNodeP = registryP->methodListP->firstMethodP;
|
|
methodNodeP && !envP->fault_occurred;
|
|
methodNodeP = methodNodeP->nextP) {
|
|
|
|
xmlrpc_value * methodNameVP;
|
|
|
|
methodNameVP = xmlrpc_string_new(envP, methodNodeP->methodName);
|
|
|
|
if (!envP->fault_occurred) {
|
|
xmlrpc_array_append_item(envP, methodListP, methodNameVP);
|
|
|
|
xmlrpc_DECREF(methodNameVP);
|
|
}
|
|
}
|
|
if (envP->fault_occurred)
|
|
xmlrpc_DECREF(methodListP);
|
|
}
|
|
*methodListPP = methodListP;
|
|
}
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
system_listMethods(xmlrpc_env * const envP,
|
|
xmlrpc_value * const paramArrayP,
|
|
void * const serverInfo,
|
|
void * const callInfo ATTR_UNUSED) {
|
|
|
|
xmlrpc_registry * const registryP = serverInfo;
|
|
|
|
xmlrpc_value * retvalP;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
XMLRPC_ASSERT_VALUE_OK(paramArrayP);
|
|
XMLRPC_ASSERT_PTR_OK(serverInfo);
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "()");
|
|
if (!envP->fault_occurred) {
|
|
if (!registryP->introspectionEnabled)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_INTROSPECTION_DISABLED_ERROR,
|
|
"Introspection is disabled in this server "
|
|
"for security reasons");
|
|
else
|
|
createMethodListArray(envP, registryP, &retvalP);
|
|
}
|
|
return retvalP;
|
|
}
|
|
|
|
|
|
|
|
static struct systemMethodReg const methodListMethods = {
|
|
"system.listMethods",
|
|
&system_listMethods,
|
|
"A:",
|
|
"Return an array of all available XML-RPC methods on this server.",
|
|
};
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
system.methodHelp
|
|
=========================================================================*/
|
|
|
|
|
|
static void
|
|
getHelpString(xmlrpc_env * const envP,
|
|
const char * const methodName,
|
|
xmlrpc_registry * const registryP,
|
|
xmlrpc_value ** const helpStringPP) {
|
|
|
|
xmlrpc_methodInfo * methodP;
|
|
|
|
xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
|
|
&methodP);
|
|
|
|
if (!methodP)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_NO_SUCH_METHOD_ERROR,
|
|
"Method '%s' does not exist", methodName);
|
|
else
|
|
*helpStringPP = xmlrpc_string_new(envP, methodP->helpText);
|
|
}
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
system_methodHelp(xmlrpc_env * const envP,
|
|
xmlrpc_value * const paramArrayP,
|
|
void * const serverInfo,
|
|
void * const callInfo ATTR_UNUSED) {
|
|
|
|
xmlrpc_registry * const registryP = serverInfo;
|
|
|
|
xmlrpc_value * retvalP;
|
|
|
|
const char * methodName;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
XMLRPC_ASSERT_VALUE_OK(paramArrayP);
|
|
XMLRPC_ASSERT_PTR_OK(serverInfo);
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(s)", &methodName);
|
|
|
|
if (!envP->fault_occurred) {
|
|
if (!registryP->introspectionEnabled)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_INTROSPECTION_DISABLED_ERROR,
|
|
"Introspection is disabled in this server "
|
|
"for security reasons");
|
|
else
|
|
getHelpString(envP, methodName, registryP, &retvalP);
|
|
}
|
|
|
|
xmlrpc_strfree(methodName);
|
|
|
|
return retvalP;
|
|
}
|
|
|
|
|
|
static struct systemMethodReg const methodMethodHelp = {
|
|
"system.methodHelp",
|
|
&system_methodHelp,
|
|
"s:s",
|
|
"Given the name of a method, return a help string.",
|
|
};
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
system.methodSignature
|
|
==========================================================================*/
|
|
|
|
static void
|
|
buildNoSigSuppliedResult(xmlrpc_env * const envP,
|
|
xmlrpc_value ** const resultPP) {
|
|
|
|
xmlrpc_env env;
|
|
|
|
xmlrpc_env_init(&env);
|
|
|
|
*resultPP = xmlrpc_string_new(&env, "undef");
|
|
if (env.fault_occurred)
|
|
xmlrpc_faultf(envP, "Unable to construct 'undef'. %s",
|
|
env.fault_string);
|
|
|
|
xmlrpc_env_clean(&env);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
buildSignatureValue(xmlrpc_env * const envP,
|
|
struct xmlrpc_signature * const signatureP,
|
|
xmlrpc_value ** const sigValuePP) {
|
|
|
|
xmlrpc_value * sigValueP;
|
|
unsigned int i;
|
|
|
|
sigValueP = xmlrpc_array_new(envP);
|
|
|
|
{
|
|
xmlrpc_value * retTypeVP;
|
|
|
|
retTypeVP = xmlrpc_string_new(envP, signatureP->retType);
|
|
|
|
xmlrpc_array_append_item(envP, sigValueP, retTypeVP);
|
|
|
|
xmlrpc_DECREF(retTypeVP);
|
|
}
|
|
for (i = 0; i < signatureP->argCount && !envP->fault_occurred; ++i) {
|
|
xmlrpc_value * argTypeVP;
|
|
|
|
argTypeVP = xmlrpc_string_new(envP, signatureP->argList[i]);
|
|
if (!envP->fault_occurred) {
|
|
xmlrpc_array_append_item(envP, sigValueP, argTypeVP);
|
|
|
|
xmlrpc_DECREF(argTypeVP);
|
|
}
|
|
}
|
|
|
|
if (envP->fault_occurred)
|
|
xmlrpc_DECREF(sigValueP);
|
|
else
|
|
*sigValuePP = sigValueP;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
getSignatureList(xmlrpc_env * const envP,
|
|
xmlrpc_registry * const registryP,
|
|
const char * const methodName,
|
|
xmlrpc_value ** const signatureListPP) {
|
|
/*----------------------------------------------------------------------------
|
|
Get the signature list array for method named 'methodName' from registry
|
|
'registryP'.
|
|
|
|
If there is no signature information for the method in the registry,
|
|
return *signatureListPP == NULL.
|
|
|
|
Nonexistent method is considered a failure.
|
|
-----------------------------------------------------------------------------*/
|
|
xmlrpc_methodInfo * methodP;
|
|
|
|
xmlrpc_methodListLookupByName(registryP->methodListP, methodName,
|
|
&methodP);
|
|
|
|
if (!methodP)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_NO_SUCH_METHOD_ERROR,
|
|
"Method '%s' does not exist", methodName);
|
|
else {
|
|
if (!methodP->signatureListP->firstSignatureP)
|
|
*signatureListPP = NULL;
|
|
else {
|
|
xmlrpc_value * signatureListP;
|
|
|
|
signatureListP = xmlrpc_array_new(envP);
|
|
|
|
if (!envP->fault_occurred) {
|
|
struct xmlrpc_signature * signatureP;
|
|
for (signatureP = methodP->signatureListP->firstSignatureP;
|
|
signatureP && !envP->fault_occurred;
|
|
signatureP = signatureP->nextP) {
|
|
|
|
xmlrpc_value * signatureVP;
|
|
|
|
buildSignatureValue(envP, signatureP, &signatureVP);
|
|
|
|
xmlrpc_array_append_item(envP,
|
|
signatureListP, signatureVP);
|
|
|
|
xmlrpc_DECREF(signatureVP);
|
|
}
|
|
if (envP->fault_occurred)
|
|
xmlrpc_DECREF(signatureListP);
|
|
}
|
|
*signatureListPP = signatureListP;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
system_methodSignature(xmlrpc_env * const envP,
|
|
xmlrpc_value * const paramArrayP,
|
|
void * const serverInfo,
|
|
void * const callInfo ATTR_UNUSED) {
|
|
|
|
xmlrpc_registry * const registryP = (xmlrpc_registry *) serverInfo;
|
|
|
|
xmlrpc_value * retvalP;
|
|
const char * methodName;
|
|
xmlrpc_env env;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
XMLRPC_ASSERT_VALUE_OK(paramArrayP);
|
|
XMLRPC_ASSERT_PTR_OK(serverInfo);
|
|
|
|
retvalP = NULL; /* quiet compiler unset variable warning */
|
|
|
|
xmlrpc_env_init(&env);
|
|
|
|
/* Turn our arguments into something more useful. */
|
|
xmlrpc_decompose_value(&env, paramArrayP, "(s)", &methodName);
|
|
if (env.fault_occurred)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, env.fault_code,
|
|
"Invalid parameter list. %s", env.fault_string);
|
|
else {
|
|
if (!registryP->introspectionEnabled)
|
|
xmlrpc_env_set_fault(envP, XMLRPC_INTROSPECTION_DISABLED_ERROR,
|
|
"Introspection disabled on this server");
|
|
else {
|
|
xmlrpc_value * signatureListP;
|
|
|
|
getSignatureList(envP, registryP, methodName, &signatureListP);
|
|
|
|
if (!envP->fault_occurred) {
|
|
if (signatureListP)
|
|
retvalP = signatureListP;
|
|
else
|
|
buildNoSigSuppliedResult(envP, &retvalP);
|
|
}
|
|
}
|
|
xmlrpc_strfree(methodName);
|
|
}
|
|
xmlrpc_env_clean(&env);
|
|
|
|
return retvalP;
|
|
}
|
|
|
|
|
|
|
|
static struct systemMethodReg const methodMethodSignature = {
|
|
"system.methodSignature",
|
|
&system_methodSignature,
|
|
"s:s",
|
|
"Given the name of a method, return an array of legal signatures. "
|
|
"Each signature is an array of strings. The first item of each signature "
|
|
"is the return type, and any others items are parameter types.",
|
|
};
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
system.shutdown
|
|
==========================================================================*/
|
|
|
|
static xmlrpc_value *
|
|
system_shutdown(xmlrpc_env * const envP,
|
|
xmlrpc_value * const paramArrayP,
|
|
void * const serverInfo,
|
|
void * const callInfo) {
|
|
|
|
xmlrpc_registry * const registryP = (xmlrpc_registry *) serverInfo;
|
|
|
|
xmlrpc_value * retvalP;
|
|
const char * comment;
|
|
xmlrpc_env env;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
XMLRPC_ASSERT_VALUE_OK(paramArrayP);
|
|
XMLRPC_ASSERT_PTR_OK(serverInfo);
|
|
|
|
xmlrpc_env_init(&env);
|
|
|
|
retvalP = NULL; /* quiet compiler warning */
|
|
|
|
/* Turn our arguments into something more useful. */
|
|
xmlrpc_decompose_value(&env, paramArrayP, "(s)", &comment);
|
|
if (env.fault_occurred)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, env.fault_code,
|
|
"Invalid parameter list. %s", env.fault_string);
|
|
else {
|
|
if (!registryP->shutdownServerFn)
|
|
xmlrpc_env_set_fault(
|
|
envP, 0, "This server program is not capable of "
|
|
"shutting down");
|
|
else {
|
|
registryP->shutdownServerFn(
|
|
&env, registryP->shutdownContext, comment, callInfo);
|
|
|
|
if (env.fault_occurred)
|
|
xmlrpc_env_set_fault(envP, env.fault_code, env.fault_string);
|
|
else {
|
|
retvalP = xmlrpc_int_new(&env, 0);
|
|
|
|
if (env.fault_occurred)
|
|
xmlrpc_faultf(envP,
|
|
"Failed to construct return value. %s",
|
|
env.fault_string);
|
|
}
|
|
}
|
|
xmlrpc_strfree(comment);
|
|
}
|
|
xmlrpc_env_clean(&env);
|
|
|
|
return retvalP;
|
|
}
|
|
|
|
|
|
|
|
static struct systemMethodReg const methodShutdown = {
|
|
"system.shutdown",
|
|
&system_shutdown,
|
|
"i:s",
|
|
"Shut down the server. Return code is always zero.",
|
|
};
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
system.capabilities
|
|
=========================================================================*/
|
|
|
|
static void
|
|
getCapabilities(xmlrpc_env * const envP,
|
|
xmlrpc_registry * const registryP ATTR_UNUSED,
|
|
xmlrpc_value ** const capabilitiesPP) {
|
|
|
|
*capabilitiesPP =
|
|
xmlrpc_build_value(
|
|
envP, "{s:s,s:i,s:i,s:i,s:i}",
|
|
"facility", "xmlrpc-c",
|
|
"version_major", XMLRPC_VERSION_MAJOR,
|
|
"version_minor", XMLRPC_VERSION_MINOR,
|
|
"version_point", XMLRPC_VERSION_POINT,
|
|
"protocol_version", 2
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
system_capabilities(xmlrpc_env * const envP,
|
|
xmlrpc_value * const paramArrayP,
|
|
void * const serverInfo,
|
|
void * const callInfo ATTR_UNUSED) {
|
|
|
|
xmlrpc_registry * const registryP = serverInfo;
|
|
|
|
xmlrpc_value * retvalP;
|
|
|
|
unsigned int paramCount;
|
|
|
|
XMLRPC_ASSERT_ENV_OK(envP);
|
|
XMLRPC_ASSERT_VALUE_OK(paramArrayP);
|
|
XMLRPC_ASSERT_PTR_OK(serverInfo);
|
|
|
|
paramCount = xmlrpc_array_size(envP, paramArrayP);
|
|
|
|
if (paramCount > 0)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_INDEX_ERROR,
|
|
"There are no parameters. You supplied %u", paramCount);
|
|
else
|
|
getCapabilities(envP, registryP, &retvalP);
|
|
|
|
return retvalP;
|
|
}
|
|
|
|
|
|
static struct systemMethodReg const methodCapabilities = {
|
|
"system.capabilities",
|
|
&system_capabilities,
|
|
"S:",
|
|
"Return the capabilities of XML-RPC server. This includes the "
|
|
"version number of the XML-RPC For C/C++ software"
|
|
};
|
|
|
|
|
|
|
|
/*============================================================================
|
|
Installer of system methods
|
|
============================================================================*/
|
|
|
|
static void
|
|
registerSystemMethod(xmlrpc_env * const envP,
|
|
xmlrpc_registry * const registryP,
|
|
struct systemMethodReg const methodReg) {
|
|
|
|
xmlrpc_env env;
|
|
xmlrpc_env_init(&env);
|
|
|
|
xmlrpc_registry_add_method2(
|
|
&env, registryP, methodReg.methodName,
|
|
methodReg.methodFunction,
|
|
methodReg.signatureString, methodReg.helpText, registryP);
|
|
|
|
if (env.fault_occurred)
|
|
xmlrpc_faultf(envP, "Failed to register '%s' system method. %s",
|
|
methodReg.methodName, env.fault_string);
|
|
|
|
xmlrpc_env_clean(&env);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
xmlrpc_installSystemMethods(xmlrpc_env * const envP,
|
|
xmlrpc_registry * const registryP) {
|
|
/*----------------------------------------------------------------------------
|
|
Install the built-in methods (system.*) into registry 'registryP'.
|
|
-----------------------------------------------------------------------------*/
|
|
if (!envP->fault_occurred)
|
|
registerSystemMethod(envP, registryP, methodListMethods);
|
|
|
|
if (!envP->fault_occurred)
|
|
registerSystemMethod(envP, registryP, methodMethodSignature);
|
|
|
|
if (!envP->fault_occurred)
|
|
registerSystemMethod(envP, registryP, methodMethodHelp);
|
|
|
|
if (!envP->fault_occurred)
|
|
registerSystemMethod(envP, registryP, methodMulticall);
|
|
|
|
if (!envP->fault_occurred)
|
|
registerSystemMethod(envP, registryP, methodShutdown);
|
|
|
|
if (!envP->fault_occurred)
|
|
registerSystemMethod(envP, registryP, methodCapabilities);
|
|
}
|
|
|
|
|
|
|
|
/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
|
|
** Copyright (C) 2001 by Eric Kidd. All rights reserved.
|
|
** Copyright (C) 2001 by Luke Howard. All rights reserved.
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions
|
|
** are met:
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
** notice, this list of conditions and the following disclaimer.
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
** documentation and/or other materials provided with the distribution.
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
** derived from this software without specific prior written permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
** SUCH DAMAGE. */
|
|
|