|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define WIN32_LEAN_AND_MEAN |
|
|
|
|
|
#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" |
|
|
|
|
|
#define RETURN_IF_FAULT(envP) \ |
|
|
do { \ |
|
|
if ((envP)->fault_occurred) \ |
|
|
return NULL; \ |
|
|
} while (0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
array_of_structs(xmlrpc_env * const envP, |
|
|
xmlrpc_value * const paramArrayP, |
|
|
void * const user_data) { |
|
|
|
|
|
xmlrpc_value * arrayP; |
|
|
xmlrpc_value * retval; |
|
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(A)", &arrayP); |
|
|
if (envP->fault_occurred) |
|
|
retval = NULL; |
|
|
else { |
|
|
|
|
|
size_t size; |
|
|
size = xmlrpc_array_size(envP, arrayP); |
|
|
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 * strctP; |
|
|
strctP = xmlrpc_array_get_item(envP, arrayP, i); |
|
|
if (!envP->fault_occurred) { |
|
|
xmlrpc_int32 curly; |
|
|
xmlrpc_decompose_value(envP, strctP, "{s:i,*}", |
|
|
"curly", &curly); |
|
|
if (!envP->fault_occurred) |
|
|
sum += curly; |
|
|
} |
|
|
} |
|
|
xmlrpc_DECREF(arrayP); |
|
|
if (envP->fault_occurred) |
|
|
retval = NULL; |
|
|
else |
|
|
retval = xmlrpc_build_value(envP, "i", sum); |
|
|
} |
|
|
} |
|
|
return retval; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
count_entities(xmlrpc_env * const envP, |
|
|
xmlrpc_value * const paramArrayP, |
|
|
void * const user_data) { |
|
|
|
|
|
const char * str; |
|
|
size_t len, i; |
|
|
xmlrpc_int32 left, right, amp, apos, quote; |
|
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(s#)", &str, &len); |
|
|
RETURN_IF_FAULT(envP); |
|
|
|
|
|
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(envP, "{s:i,s:i,s:i,s:i,s:i}", |
|
|
"ctLeftAngleBrackets", left, |
|
|
"ctRightAngleBrackets", right, |
|
|
"ctAmpersands", amp, |
|
|
"ctApostrophes", apos, |
|
|
"ctQuotes", quote); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
easy_struct(xmlrpc_env * const envP, |
|
|
xmlrpc_value * const paramArrayP, |
|
|
void * const user_data) { |
|
|
|
|
|
xmlrpc_int32 larry, moe, curly; |
|
|
|
|
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "({s:i,s:i,s:i,*})", |
|
|
"larry", &larry, |
|
|
"moe", &moe, |
|
|
"curly", &curly); |
|
|
RETURN_IF_FAULT(envP); |
|
|
|
|
|
|
|
|
return xmlrpc_build_value(envP, "i", larry + moe + curly); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
echo_struct(xmlrpc_env * const envP, |
|
|
xmlrpc_value * const paramArrayP, |
|
|
void * const user_data) { |
|
|
|
|
|
xmlrpc_value * sP; |
|
|
|
|
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(S)", &sP); |
|
|
RETURN_IF_FAULT(envP); |
|
|
|
|
|
return sP; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
many_types(xmlrpc_env * const env, |
|
|
xmlrpc_value * const param_array, |
|
|
void * const user_data) { |
|
|
|
|
|
|
|
|
xmlrpc_INCREF(param_array); |
|
|
return param_array; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 resultPP) { |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
*resultPP = xmlrpc_build_value(envP, "s#", |
|
|
buffer, str1_len + str2_len); |
|
|
free(buffer); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
moderate_array(xmlrpc_env * const envP, |
|
|
xmlrpc_value * const paramArrayP, |
|
|
void * const user_data) { |
|
|
|
|
|
xmlrpc_value * retval; |
|
|
xmlrpc_value * arrayP; |
|
|
|
|
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(A)", &arrayP); |
|
|
if (!envP->fault_occurred) { |
|
|
int const size = xmlrpc_array_size(envP, arrayP); |
|
|
if (!envP->fault_occurred) { |
|
|
|
|
|
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) { |
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
nested_struct(xmlrpc_env * const envP, |
|
|
xmlrpc_value * const paramArrayP, |
|
|
void * const user_data) { |
|
|
|
|
|
xmlrpc_value * yearsP; |
|
|
xmlrpc_value * retval; |
|
|
|
|
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(S)", &yearsP); |
|
|
if (envP->fault_occurred) |
|
|
retval = NULL; |
|
|
else { |
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static xmlrpc_value * |
|
|
struct_return(xmlrpc_env * const envP, |
|
|
xmlrpc_value * const paramArrayP, |
|
|
void * const user_data) { |
|
|
|
|
|
xmlrpc_int32 i; |
|
|
|
|
|
xmlrpc_decompose_value(envP, paramArrayP, "(i)", &i); |
|
|
RETURN_IF_FAULT(envP); |
|
|
|
|
|
return xmlrpc_build_value(envP, "{s:i,s:i,s:i}", |
|
|
"times10", (xmlrpc_int32) i * 10, |
|
|
"times100", (xmlrpc_int32) i * 100, |
|
|
"times1000", (xmlrpc_int32) i * 1000); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)); |
|
|
|
|
|
|
|
|
return 0; |
|
|
} |
|
|
|