2006-12-20 22:57:49 -05:00
|
|
|
/* Copyright (C) 2001 by First Peer, Inc. 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. */
|
|
|
|
|
|
|
|
|
|
|
|
/*============================================================================
|
|
|
|
xmlrpc_server_validatee
|
|
|
|
==============================================================================
|
|
|
|
|
|
|
|
This program runs an XMLRPC server, using the Xmlrpc-c libraries.
|
|
|
|
|
|
|
|
The server implements the methods that the Userland Validator1 test suite
|
|
|
|
invokes, which are supposed to exercise a broad range of XMLRPC server
|
|
|
|
function.
|
|
|
|
|
|
|
|
Coments here used to say you could get information about Validator1
|
|
|
|
from <http://validator.xmlrpc.com/>, but as of 2004.09.25, there's nothing
|
|
|
|
there (there's a web server, but it is not configured to serve that
|
|
|
|
particular URL).
|
|
|
|
|
|
|
|
============================================================================*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <xmlrpc-c/base.h>
|
|
|
|
#include <xmlrpc-c/server.h>
|
|
|
|
#include <xmlrpc-c/server_abyss.h>
|
|
|
|
|
|
|
|
#include "config.h" /* information about this build environment */
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
#define RETURN_IF_FAULT(envP) \
|
2006-12-20 22:57:49 -05:00
|
|
|
do { \
|
2008-05-23 16:56:24 -04:00
|
|
|
if ((envP)->fault_occurred) \
|
2006-12-20 22:57:49 -05:00
|
|
|
return NULL; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** validator1.arrayOfStructsTest
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
|
|
array_of_structs(xmlrpc_env * const envP,
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value * const paramArrayP,
|
2006-12-20 22:57:49 -05:00
|
|
|
void * const user_data ATTR_UNUSED) {
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value * arrayP;
|
2006-12-20 22:57:49 -05:00
|
|
|
xmlrpc_value * retval;
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(A)", &arrayP);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (envP->fault_occurred)
|
|
|
|
retval = NULL;
|
|
|
|
else {
|
|
|
|
/* Add up all the struct elements named "curly". */
|
|
|
|
size_t size;
|
2008-05-23 16:56:24 -04:00
|
|
|
size = xmlrpc_array_size(envP, arrayP);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (envP->fault_occurred)
|
|
|
|
retval = NULL;
|
|
|
|
else {
|
|
|
|
unsigned int sum;
|
|
|
|
unsigned int i;
|
|
|
|
sum = 0;
|
|
|
|
for (i = 0; i < size && !envP->fault_occurred; ++i) {
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value * strctP;
|
|
|
|
strctP = xmlrpc_array_get_item(envP, arrayP, i);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (!envP->fault_occurred) {
|
|
|
|
xmlrpc_int32 curly;
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, strctP, "{s:i,*}",
|
2006-12-20 22:57:49 -05:00
|
|
|
"curly", &curly);
|
|
|
|
if (!envP->fault_occurred)
|
|
|
|
sum += curly;
|
|
|
|
}
|
|
|
|
}
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_DECREF(arrayP);
|
|
|
|
if (envP->fault_occurred)
|
|
|
|
retval = NULL;
|
|
|
|
else
|
2006-12-20 22:57:49 -05:00
|
|
|
retval = xmlrpc_build_value(envP, "i", sum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** validator1.countTheEntities
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
2008-05-23 16:56:24 -04:00
|
|
|
count_entities(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const paramArrayP,
|
2006-12-20 22:57:49 -05:00
|
|
|
void * const user_data ATTR_UNUSED) {
|
2008-05-23 16:56:24 -04:00
|
|
|
|
|
|
|
const char * str;
|
2006-12-20 22:57:49 -05:00
|
|
|
size_t len, i;
|
|
|
|
xmlrpc_int32 left, right, amp, apos, quote;
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(s#)", &str, &len);
|
|
|
|
RETURN_IF_FAULT(envP);
|
2006-12-20 22:57:49 -05:00
|
|
|
|
|
|
|
left = right = amp = apos = quote = 0;
|
2008-05-23 16:56:24 -04:00
|
|
|
for (i = 0; i < len; ++i) {
|
2006-12-20 22:57:49 -05:00
|
|
|
switch (str[i]) {
|
2008-05-23 16:56:24 -04:00
|
|
|
case '<': ++left; break;
|
|
|
|
case '>': ++right; break;
|
|
|
|
case '&': ++amp; break;
|
|
|
|
case '\'': ++apos; break;
|
|
|
|
case '\"': ++quote; break;
|
2006-12-20 22:57:49 -05:00
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free((void*)str);
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
return xmlrpc_build_value(envP, "{s:i,s:i,s:i,s:i,s:i}",
|
2006-12-20 22:57:49 -05:00
|
|
|
"ctLeftAngleBrackets", left,
|
|
|
|
"ctRightAngleBrackets", right,
|
|
|
|
"ctAmpersands", amp,
|
|
|
|
"ctApostrophes", apos,
|
|
|
|
"ctQuotes", quote);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*=========================================================================
|
|
|
|
** validator1.easyStructTest
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
2008-05-23 16:56:24 -04:00
|
|
|
easy_struct(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const paramArrayP,
|
2006-12-20 22:57:49 -05:00
|
|
|
void * const user_data ATTR_UNUSED) {
|
|
|
|
|
|
|
|
xmlrpc_int32 larry, moe, curly;
|
|
|
|
|
|
|
|
/* Parse our argument array and get the stooges. */
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "({s:i,s:i,s:i,*})",
|
2006-12-20 22:57:49 -05:00
|
|
|
"larry", &larry,
|
|
|
|
"moe", &moe,
|
|
|
|
"curly", &curly);
|
2008-05-23 16:56:24 -04:00
|
|
|
RETURN_IF_FAULT(envP);
|
2006-12-20 22:57:49 -05:00
|
|
|
|
|
|
|
/* Return our result. */
|
2008-05-23 16:56:24 -04:00
|
|
|
return xmlrpc_build_value(envP, "i", larry + moe + curly);
|
2006-12-20 22:57:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
|
2006-12-20 22:57:49 -05:00
|
|
|
/*=========================================================================
|
|
|
|
** validator1.echoStructTest
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
2008-05-23 16:56:24 -04:00
|
|
|
echo_struct(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const paramArrayP,
|
2006-12-20 22:57:49 -05:00
|
|
|
void * const user_data ATTR_UNUSED) {
|
2008-05-23 16:56:24 -04:00
|
|
|
|
|
|
|
xmlrpc_value * sP;
|
2006-12-20 22:57:49 -05:00
|
|
|
|
|
|
|
/* Parse our argument array. */
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(S)", &sP);
|
|
|
|
RETURN_IF_FAULT(envP);
|
2006-12-20 22:57:49 -05:00
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
return sP; /* We transfer our reference on '*sP' to Caller */
|
2006-12-20 22:57:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
|
2006-12-20 22:57:49 -05:00
|
|
|
/*=========================================================================
|
|
|
|
** validator1.manyTypesTest
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
|
|
many_types(xmlrpc_env * const env ATTR_UNUSED,
|
|
|
|
xmlrpc_value * const param_array,
|
|
|
|
void * const user_data ATTR_UNUSED) {
|
|
|
|
|
|
|
|
/* Create another reference to our argument array and return it as is. */
|
|
|
|
xmlrpc_INCREF(param_array);
|
|
|
|
return param_array;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
|
2006-12-20 22:57:49 -05:00
|
|
|
/*=========================================================================
|
|
|
|
** validator1.moderateSizeArrayCheck
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
concatenate(xmlrpc_env * const envP,
|
|
|
|
const char * const str1,
|
|
|
|
size_t const str1_len,
|
|
|
|
const char * const str2,
|
|
|
|
size_t const str2_len,
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value ** const resultPP) {
|
2006-12-20 22:57:49 -05:00
|
|
|
|
|
|
|
/* Concatenate the two strings. */
|
|
|
|
|
|
|
|
char * buffer;
|
|
|
|
|
|
|
|
buffer = (char*) malloc(str1_len + str2_len);
|
|
|
|
if (!buffer) {
|
|
|
|
xmlrpc_env_set_fault(envP, 1,
|
|
|
|
"Couldn't allocate concatenated string");
|
|
|
|
} else {
|
|
|
|
memcpy(buffer, str1, str1_len);
|
|
|
|
memcpy(&buffer[str1_len], str2, str2_len);
|
2008-05-23 16:56:24 -04:00
|
|
|
*resultPP = xmlrpc_build_value(envP, "s#",
|
|
|
|
buffer, str1_len + str2_len);
|
2006-12-20 22:57:49 -05:00
|
|
|
free(buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
2008-05-23 16:56:24 -04:00
|
|
|
moderate_array(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const paramArrayP,
|
2006-12-20 22:57:49 -05:00
|
|
|
void * const user_data ATTR_UNUSED) {
|
|
|
|
|
|
|
|
xmlrpc_value * retval;
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value * arrayP;
|
2006-12-20 22:57:49 -05:00
|
|
|
|
|
|
|
/* Parse our argument array. */
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(A)", &arrayP);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (!envP->fault_occurred) {
|
2008-05-23 16:56:24 -04:00
|
|
|
int const size = xmlrpc_array_size(envP, arrayP);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (!envP->fault_occurred) {
|
|
|
|
/* Get our first string. */
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value * const firstItemP =
|
|
|
|
xmlrpc_array_get_item(envP, arrayP, 0);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (!envP->fault_occurred) {
|
2008-05-23 16:56:24 -04:00
|
|
|
const char * str1;
|
|
|
|
size_t str1_len;
|
|
|
|
xmlrpc_read_string_lp(envP, firstItemP, &str1_len, &str1);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (!envP->fault_occurred) {
|
|
|
|
/* Get our last string. */
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value * const lastItemP =
|
|
|
|
xmlrpc_array_get_item(envP, arrayP, size - 1);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (!envP->fault_occurred) {
|
2008-05-23 16:56:24 -04:00
|
|
|
const char * str2;
|
|
|
|
size_t str2_len;
|
|
|
|
xmlrpc_read_string_lp(envP, lastItemP,
|
|
|
|
&str2_len, &str2);
|
2006-12-20 22:57:49 -05:00
|
|
|
if (!envP->fault_occurred) {
|
|
|
|
concatenate(envP, str1, str1_len, str2, str2_len,
|
|
|
|
&retval);
|
|
|
|
free((char*)str2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free((char*)str1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_DECREF(arrayP);
|
2006-12-20 22:57:49 -05:00
|
|
|
}
|
2008-05-23 16:56:24 -04:00
|
|
|
return retval;
|
2006-12-20 22:57:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
|
2006-12-20 22:57:49 -05:00
|
|
|
/*=========================================================================
|
|
|
|
** validator1.nestedStructTest
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
|
|
|
nested_struct(xmlrpc_env * const envP,
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_value * const paramArrayP,
|
2006-12-20 22:57:49 -05:00
|
|
|
void * const user_data ATTR_UNUSED) {
|
|
|
|
|
|
|
|
xmlrpc_value * yearsP;
|
|
|
|
xmlrpc_value * retval;
|
|
|
|
|
|
|
|
/* Parse our argument array. */
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(S)", &yearsP);
|
|
|
|
if (envP->fault_occurred)
|
|
|
|
retval = NULL;
|
|
|
|
else {
|
2006-12-20 22:57:49 -05:00
|
|
|
/* Get values of larry, moe and curly for 2000-04-01. */
|
|
|
|
xmlrpc_int32 larry, moe, curly;
|
|
|
|
xmlrpc_decompose_value(envP, yearsP,
|
|
|
|
"{s:{s:{s:{s:i,s:i,s:i,*},*},*},*}",
|
|
|
|
"2000", "04", "01",
|
|
|
|
"larry", &larry,
|
|
|
|
"moe", &moe,
|
|
|
|
"curly", &curly);
|
2008-05-23 16:56:24 -04:00
|
|
|
if (envP->fault_occurred)
|
|
|
|
retval = NULL;
|
|
|
|
else
|
2006-12-20 22:57:49 -05:00
|
|
|
retval = xmlrpc_build_value(envP, "i", larry + moe + curly);
|
2008-05-23 16:56:24 -04:00
|
|
|
|
2006-12-20 22:57:49 -05:00
|
|
|
xmlrpc_DECREF(yearsP);
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
|
2006-12-20 22:57:49 -05:00
|
|
|
/*=========================================================================
|
|
|
|
** validator1.simpleStructReturnTest
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
static xmlrpc_value *
|
2008-05-23 16:56:24 -04:00
|
|
|
struct_return(xmlrpc_env * const envP,
|
|
|
|
xmlrpc_value * const paramArrayP,
|
2006-12-20 22:57:49 -05:00
|
|
|
void * const user_data ATTR_UNUSED) {
|
|
|
|
|
|
|
|
xmlrpc_int32 i;
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(i)", &i);
|
|
|
|
RETURN_IF_FAULT(envP);
|
2006-12-20 22:57:49 -05:00
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
return xmlrpc_build_value(envP, "{s:i,s:i,s:i}",
|
2006-12-20 22:57:49 -05:00
|
|
|
"times10", (xmlrpc_int32) i * 10,
|
|
|
|
"times100", (xmlrpc_int32) i * 100,
|
|
|
|
"times1000", (xmlrpc_int32) i * 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-23 16:56:24 -04:00
|
|
|
|
2006-12-20 22:57:49 -05:00
|
|
|
/*=========================================================================
|
|
|
|
** main
|
|
|
|
**=========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
int main(int const argc,
|
|
|
|
const char ** const argv) {
|
|
|
|
|
|
|
|
xmlrpc_server_abyss_parms serverparm;
|
|
|
|
xmlrpc_registry * registryP;
|
|
|
|
xmlrpc_env env;
|
|
|
|
|
|
|
|
if (argc-1 != 1) {
|
|
|
|
fprintf(stderr, "You must specify 1 argument: The TCP port "
|
|
|
|
"number on which the server will accept connections "
|
|
|
|
"for RPCs. You specified %d arguments.\n", argc-1);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlrpc_env_init(&env);
|
|
|
|
|
|
|
|
registryP = xmlrpc_registry_new(&env);
|
|
|
|
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.arrayOfStructsTest",
|
|
|
|
&array_of_structs, NULL);
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.countTheEntities",
|
|
|
|
&count_entities, NULL);
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.easyStructTest",
|
|
|
|
&easy_struct, NULL);
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.echoStructTest",
|
|
|
|
&echo_struct, NULL);
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.manyTypesTest",
|
|
|
|
&many_types, NULL);
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.moderateSizeArrayCheck",
|
|
|
|
&moderate_array, NULL);
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.nestedStructTest",
|
|
|
|
&nested_struct, NULL);
|
|
|
|
xmlrpc_registry_add_method(
|
|
|
|
&env, registryP, NULL, "validator1.simpleStructReturnTest",
|
|
|
|
&struct_return, NULL);
|
|
|
|
|
|
|
|
serverparm.config_file_name = NULL;
|
|
|
|
serverparm.registryP = registryP;
|
|
|
|
serverparm.port_number = atoi(argv[1]);
|
|
|
|
serverparm.log_file_name = NULL;
|
|
|
|
|
|
|
|
printf("Running XML-RPC server...\n");
|
|
|
|
|
|
|
|
xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(log_file_name));
|
|
|
|
|
|
|
|
/* This never gets executed. */
|
|
|
|
return 0;
|
|
|
|
}
|