mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-02 01:25:11 +00:00
merged new xmlrpc-c revision 1472 from https://xmlrpc-c.svn.sourceforge.net/svnroot/xmlrpc-c/trunk
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8545 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
d2290cfa3a
commit
00654d880e
338 files changed
+55722
-19397
No files matched your search
@@ -0,0 +1,746 @@
|
||||
/* 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. */
|
||||
|
||||
Reference in new issue
Block a user