--- /dev/null
+/* 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 */
+
+#define RETURN_IF_FAULT(env) \
+ do { \
+ if ((env)->fault_occurred) \
+ return NULL; \
+ } while (0)
+
+
+/*=========================================================================
+** validator1.arrayOfStructsTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+array_of_structs(xmlrpc_env * const envP,
+ xmlrpc_value * const param_array,
+ void * const user_data ATTR_UNUSED) {
+
+ xmlrpc_value * array;
+ xmlrpc_value * retval;
+
+ xmlrpc_decompose_value(envP, param_array, "(A)", &array);
+ if (envP->fault_occurred)
+ retval = NULL;
+ else {
+ /* Add up all the struct elements named "curly". */
+ size_t size;
+ size = xmlrpc_array_size(envP, array);
+ if (envP->fault_occurred)
+ retval = NULL;
+ else {
+ unsigned int sum;
+ unsigned int i;
+ sum = 0;
+ for (i = 0; i < size && !envP->fault_occurred; ++i) {
+ xmlrpc_value * strct;
+ strct = xmlrpc_array_get_item(envP, array, i);
+ if (!envP->fault_occurred) {
+ xmlrpc_int32 curly;
+ xmlrpc_decompose_value(envP, strct, "{s:i,*}",
+ "curly", &curly);
+ if (!envP->fault_occurred)
+ sum += curly;
+ }
+ }
+ xmlrpc_DECREF(array);
+ if (envP->fault_occurred)
+ retval = NULL;
+ else
+ retval = xmlrpc_build_value(envP, "i", sum);
+ }
+ }
+ return retval;
+}
+
+
+/*=========================================================================
+** validator1.countTheEntities
+**=========================================================================
+*/
+
+static xmlrpc_value *
+count_entities(xmlrpc_env * const env,
+ xmlrpc_value * const param_array,
+ void * const user_data ATTR_UNUSED) {
+ const char *str;
+ size_t len, i;
+ xmlrpc_int32 left, right, amp, apos, quote;
+
+ xmlrpc_decompose_value(env, param_array, "(s#)", &str, &len);
+ RETURN_IF_FAULT(env);
+
+ left = right = amp = apos = quote = 0;
+ for (i = 0; i < len; i++) {
+ switch (str[i]) {
+ case '<': left++; break;
+ case '>': right++; break;
+ case '&': amp++; break;
+ case '\'': apos++; break;
+ case '\"': quote++; break;
+ default: break;
+ }
+ }
+ free((void*)str);
+
+ return xmlrpc_build_value(env, "{s:i,s:i,s:i,s:i,s:i}",
+ "ctLeftAngleBrackets", left,
+ "ctRightAngleBrackets", right,
+ "ctAmpersands", amp,
+ "ctApostrophes", apos,
+ "ctQuotes", quote);
+}
+
+
+
+/*=========================================================================
+** validator1.easyStructTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+easy_struct(xmlrpc_env * const env,
+ xmlrpc_value * const param_array,
+ void * const user_data ATTR_UNUSED) {
+
+ xmlrpc_int32 larry, moe, curly;
+
+ /* Parse our argument array and get the stooges. */
+ xmlrpc_decompose_value(env, param_array, "({s:i,s:i,s:i,*})",
+ "larry", &larry,
+ "moe", &moe,
+ "curly", &curly);
+ RETURN_IF_FAULT(env);
+
+ /* Return our result. */
+ return xmlrpc_build_value(env, "i", larry + moe + curly);
+}
+
+
+/*=========================================================================
+** validator1.echoStructTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+echo_struct(xmlrpc_env * const env,
+ xmlrpc_value * const param_array,
+ void * const user_data ATTR_UNUSED) {
+ xmlrpc_value *s;
+
+ /* Parse our argument array. */
+ xmlrpc_decompose_value(env, param_array, "(S)", &s);
+ RETURN_IF_FAULT(env);
+
+ return s; /* We transfer our reference on 's' to Caller */
+}
+
+
+/*=========================================================================
+** 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;
+}
+
+
+/*=========================================================================
+** 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,
+ xmlrpc_value ** const resultP) {
+
+ /* 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);
+ *resultP = xmlrpc_build_value(envP, "s#",
+ buffer, str1_len + str2_len);
+ free(buffer);
+ }
+}
+
+
+
+static xmlrpc_value *
+moderate_array(xmlrpc_env * const envP,
+ xmlrpc_value * const param_array,
+ void * const user_data ATTR_UNUSED) {
+
+ xmlrpc_value * retval;
+ xmlrpc_value * arrayP;
+
+ /* Parse our argument array. */
+ xmlrpc_decompose_value(envP, param_array, "(A)", &arrayP);
+ if (!envP->fault_occurred) {
+ int const size = xmlrpc_array_size(envP, arrayP);
+ if (!envP->fault_occurred) {
+ /* Get our first string. */
+ xmlrpc_value * const firstItemP =
+ xmlrpc_array_get_item(envP, arrayP, 0);
+ if (!envP->fault_occurred) {
+ const char * str1;
+ size_t str1_len;
+ xmlrpc_read_string_lp(envP, firstItemP, &str1_len, &str1);
+ if (!envP->fault_occurred) {
+ /* Get our last string. */
+ xmlrpc_value * const lastItemP =
+ xmlrpc_array_get_item(envP, arrayP, size - 1);
+ if (!envP->fault_occurred) {
+ const char * str2;
+ size_t str2_len;
+ xmlrpc_read_string_lp(envP, lastItemP,
+ &str2_len, &str2);
+ if (!envP->fault_occurred) {
+ concatenate(envP, str1, str1_len, str2, str2_len,
+ &retval);
+ free((char*)str2);
+ }
+ }
+ free((char*)str1);
+ }
+ }
+ }
+ xmlrpc_DECREF(arrayP);
+ }
+ return retval;
+}
+
+
+/*=========================================================================
+** validator1.nestedStructTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+nested_struct(xmlrpc_env * const envP,
+ xmlrpc_value * const param_array,
+ void * const user_data ATTR_UNUSED) {
+
+ xmlrpc_value * yearsP;
+ xmlrpc_value * retval;
+
+ /* Parse our argument array. */
+ xmlrpc_decompose_value(envP, param_array, "(S)", &yearsP);
+ if (envP->fault_occurred)
+ retval = NULL;
+ else {
+ /* 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);
+ if (envP->fault_occurred)
+ retval = NULL;
+ else
+ retval = xmlrpc_build_value(envP, "i", larry + moe + curly);
+
+ xmlrpc_DECREF(yearsP);
+ }
+ return retval;
+}
+
+
+/*=========================================================================
+** validator1.simpleStructReturnTest
+**=========================================================================
+*/
+
+static xmlrpc_value *
+struct_return(xmlrpc_env * const env,
+ xmlrpc_value * const param_array,
+ void * const user_data ATTR_UNUSED) {
+
+ xmlrpc_int32 i;
+
+ xmlrpc_decompose_value(env, param_array, "(i)", &i);
+ RETURN_IF_FAULT(env);
+
+ return xmlrpc_build_value(env, "{s:i,s:i,s:i}",
+ "times10", (xmlrpc_int32) i * 10,
+ "times100", (xmlrpc_int32) i * 100,
+ "times1000", (xmlrpc_int32) i * 1000);
+}
+
+
+/*=========================================================================
+** 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;
+}