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; }
void xmlrpc_methodCreate(xmlrpc_env * const envP, xmlrpc_method1 methodFnType1, xmlrpc_method2 methodFnType2, void * const userData, const char * const signatureString, const char * const helpText, xmlrpc_methodInfo ** const methodPP) { xmlrpc_methodInfo * methodP; XMLRPC_ASSERT_ENV_OK(envP); MALLOCVAR(methodP); if (methodP == NULL) xmlrpc_faultf(envP, "Unable to allocate storage for a method " "descriptor"); else { methodP->methodFnType1 = methodFnType1; methodP->methodFnType2 = methodFnType2; methodP->userData = userData; methodP->helpText = strdup(helpText); makeSignatureList(envP, signatureString, &methodP->signatureListP); if (envP->fault_occurred) free(methodP); *methodPP = methodP; } }
static void parseBase64(xmlrpc_env * const envP, const char * const str, size_t const strLength, xmlrpc_value ** const valuePP) { /*---------------------------------------------------------------------------- Parse the content of a <base64> XML-RPC XML element, e.g. "FD32YY". 'str' is that content. -----------------------------------------------------------------------------*/ xmlrpc_mem_block * decoded; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(str); decoded = xmlrpc_base64_decode(envP, str, strLength); if (!envP->fault_occurred) { unsigned char * const bytes = XMLRPC_MEMBLOCK_CONTENTS(unsigned char, decoded); size_t const byteCount = XMLRPC_MEMBLOCK_SIZE(unsigned char, decoded); *valuePP = xmlrpc_base64_new(envP, byteCount, bytes); XMLRPC_MEMBLOCK_FREE(unsigned char, decoded); }
void xmlrpc_authcookie_set(xmlrpc_env *const envP, const char *const username, const char *const password) { char *unencoded; xmlrpc_mem_block *token; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(username); XMLRPC_ASSERT_PTR_OK(password); /* Create unencoded string/hash. */ MALLOCARRAY(unencoded, (strlen(username) + strlen(password) + 1 + 1)); sprintf(unencoded, "%s:%s", username, password); /* Create encoded string. */ token = xmlrpc_base64_encode_without_newlines( envP, (unsigned char *) unencoded, strlen(unencoded)); if (!envP->fault_occurred) { /* Set HTTP_COOKIE_AUTH to the character representation of the encoded string. */ #if HAVE_SETENV setenv("HTTP_COOKIE_AUTH", XMLRPC_MEMBLOCK_CONTENTS(char, token), 1); #endif xmlrpc_mem_block_free(token); }
static void parseResponse(xmlrpc_env * const envP, xmlrpc_mem_block * const respXmlP, xmlrpc_value ** const resultPP, int * const faultCodeP, const char ** const faultStringP) { xmlrpc_env respEnv; XMLRPC_ASSERT_ENV_OK(envP); xmlrpc_env_init(&respEnv); xmlrpc_parse_response2( &respEnv, XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP), XMLRPC_MEMBLOCK_SIZE(char, respXmlP), resultPP, faultCodeP, faultStringP); if (respEnv.fault_occurred) xmlrpc_env_set_fault_formatted( envP, respEnv.fault_code, "Unable to make sense of XML-RPC response from server. " "%s. Use XMLRPC_TRACE_XML to see for yourself", respEnv.fault_string); xmlrpc_env_clean(&respEnv); }
int xmlrpc_struct_size(xmlrpc_env * const envP, xmlrpc_value * const structP) { int retval; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_VALUE_OK(structP); if (structP->_type != XMLRPC_TYPE_STRUCT) { xmlrpc_env_set_fault_formatted( envP, XMLRPC_TYPE_ERROR, "Value is not a struct. It is type #%d", structP->_type); retval = -1; } else { size_t const size = XMLRPC_MEMBLOCK_SIZE(_struct_member, &structP->_block); assert((size_t)(int)size == size); /* Because structs are defined to have few enough members */ retval = (int)size; } return retval; }
xmlrpc_server_info * xmlrpc_server_info_new(xmlrpc_env * const envP, const char * const serverUrl) { xmlrpc_server_info * serverInfoP; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(serverUrl); MALLOCVAR(serverInfoP); if (serverInfoP == NULL) xmlrpc_faultf(envP, "Couldn't allocate memory for xmlrpc_server_info"); else { serverInfoP->serverUrl = strdup(serverUrl); if (serverInfoP->serverUrl == NULL) xmlrpc_faultf(envP, "Couldn't allocate memory for server URL"); else { serverInfoP->allowedAuth.basic = false; serverInfoP->allowedAuth.digest = false; serverInfoP->allowedAuth.gssnegotiate = false; serverInfoP->allowedAuth.ntlm = false; serverInfoP->userNamePw = NULL; serverInfoP->basicAuthHdrValue = NULL; if (envP->fault_occurred) xmlrpc_strfree(serverInfoP->serverUrl); } if (envP->fault_occurred) free(serverInfoP); } return serverInfoP; }
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); } }
void xmlrpc_registry_add_method_w_doc(xmlrpc_env *env, xmlrpc_registry *registry, const char *host, const char *method_name, xmlrpc_method method, void *user_data, const char *signature, const char *help) { xmlrpc_value *method_info; XMLRPC_ASSERT_ENV_OK(env); XMLRPC_ASSERT_PTR_OK(registry); XMLRPC_ASSERT(host == NULL); XMLRPC_ASSERT_PTR_OK(method_name); XMLRPC_ASSERT_PTR_OK(method); /* Error-handling preconditions. */ method_info = NULL; /* Store our method and user data into our hash table. */ method_info = xmlrpc_build_value(env, "(ppss)", (void*) method, user_data, signature, help); XMLRPC_FAIL_IF_FAULT(env); xmlrpc_struct_set_value(env, registry->_methods, method_name, method_info); XMLRPC_FAIL_IF_FAULT(env); cleanup: if (method_info) xmlrpc_DECREF(method_info); }
void xmlrpc_registry_set_preinvoke_method(xmlrpc_env *env, xmlrpc_registry *registry, xmlrpc_preinvoke_method handler, void *user_data) { xmlrpc_value *method_info; XMLRPC_ASSERT_ENV_OK(env); XMLRPC_ASSERT_PTR_OK(registry); XMLRPC_ASSERT_PTR_OK(handler); /* Error-handling preconditions. */ method_info = NULL; /* Store our method and user data into our hash table. */ method_info = xmlrpc_build_value(env, "(pp)", (void*) handler, user_data); XMLRPC_FAIL_IF_FAULT(env); /* Dispose of any pre-existing preinvoke method and install ours. */ if (registry->_preinvoke_method) xmlrpc_DECREF(registry->_preinvoke_method); registry->_preinvoke_method = method_info; cleanup: if (env->fault_occurred) { if (method_info) xmlrpc_DECREF(method_info); } }
void xmlrpc_parse_response2(xmlrpc_env * const envP, const char * const xmlData, size_t const xmlDataLen, xmlrpc_value ** const resultPP, int * const faultCodeP, const char ** const faultStringP) { /*---------------------------------------------------------------------------- Given some XML text, attempt to parse it as an XML-RPC response. If the response is a regular, valid response, return a new reference to the appropriate value as *resultP and return NULL as *faultStringP and nothing as *faultCodeP. If the response is valid, but indicates a failure of the RPC, return the fault string in newly malloc'ed space as *faultStringP and the fault code as *faultCodeP and nothing as *resultP. If the XML text is not a valid response or something prevents us from parsing it, return a description of the error as *envP and nothing else. -----------------------------------------------------------------------------*/ xml_element * response; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT(xmlData != NULL); /* SECURITY: Last-ditch attempt to make sure our content length is legal. ** XXX - This check occurs too late to prevent an attacker from creating ** an enormous memory block, so you should try to enforce it ** *before* reading any data off the network. */ if (xmlDataLen > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) xmlrpc_env_set_fault_formatted( envP, XMLRPC_LIMIT_EXCEEDED_ERROR, "XML-RPC response too large. Our limit is %u characters. " "We got %u characters", xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID), xmlDataLen); else { xmlrpc_env env; xmlrpc_env_init(&env); xml_parse(&env, xmlData, xmlDataLen, &response); if (env.fault_occurred) setParseFault(envP, "Not valid XML. %s", env.fault_string); else { /* Pick apart and verify our structure. */ if (xmlrpc_streq(xml_element_name(response), "methodResponse")) { parseMethodResponseElt(envP, response, resultPP, faultCodeP, faultStringP); } else setParseFault(envP, "XML-RPC response must consist of a " "<methodResponse> element. " "This has a <%s> instead.", xml_element_name(response)); xml_element_free(response); } xmlrpc_env_clean(&env); } }
/* set cookie function */ void xmlrpc_authcookie_set ( xmlrpc_env *env, const char *username, const char *password ) { char *unencoded; xmlrpc_mem_block *token; static char env_buffer[1024]; const char* block; /* Check asserts. */ XMLRPC_ASSERT_ENV_OK(env); XMLRPC_ASSERT_PTR_OK(username); XMLRPC_ASSERT_PTR_OK(password); /* Clear out memory. */ unencoded = (char *) malloc ( sizeof ( char * ) ); /* Create unencoded string/hash. */ sprintf(unencoded, "%s:%s", username, password); /* Create encoded string. */ token = xmlrpc_base64_encode_without_newlines(env, (unsigned char*)unencoded, strlen(unencoded)); XMLRPC_FAIL_IF_FAULT(env); /* Set HTTP_COOKIE_AUTH to the character representation of the ** encoded string. */ block = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, token); sprintf(env_buffer, "HTTP_COOKIE_AUTH=%s", block); putenv(env_buffer); cleanup: if (token) xmlrpc_mem_block_free(token); }
static void format_out(xmlrpc_env *env, xmlrpc_mem_block *output, char *format_string, ...) { va_list args; char buffer[SMALL_BUFFER_SZ]; int count; XMLRPC_ASSERT_ENV_OK(env); va_start(args, format_string); /* We assume that this function is present and works correctly. Right. */ count = vsnprintf(buffer, SMALL_BUFFER_SZ, format_string, args); /* Old C libraries return -1 if vsnprintf overflows its buffer. ** New C libraries return the number of characters which *would* have ** been printed if the error did not occur. This is impressively vile. ** Thank the C99 committee for this bright idea. But wait! We also ** need to keep track of the trailing NULL. */ if (count < 0 || count >= (SMALL_BUFFER_SZ - 1)) XMLRPC_FAIL(env, XMLRPC_INTERNAL_ERROR, "format_out overflowed internal buffer"); /* Append our new data to our output. */ XMLRPC_TYPED_MEM_BLOCK_APPEND(char, env, output, buffer, count); XMLRPC_FAIL_IF_FAULT(env); cleanup: va_end(args); }
static xmlrpc_value * convert_params(xmlrpc_env * const envP, const xml_element * const elemP) { /*---------------------------------------------------------------------------- Convert an XML element representing a list of parameters (i.e. a <params> element) to an xmlrpc_value of type array. Note that an array is normally represented in XML by a <value> element. We use type xmlrpc_value to represent the parameter list just for convenience. -----------------------------------------------------------------------------*/ xmlrpc_value *array, *item; int size, i; xml_element **params, *param, *value; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT(elemP != NULL); /* Set up our error-handling preconditions. */ array = item = NULL; /* Allocate an array to hold our parameters. */ array = xmlrpc_build_value(envP, "()"); XMLRPC_FAIL_IF_FAULT(envP); /* We're responsible for checking our own element name. */ CHECK_NAME(envP, elemP, "params"); /* Iterate over our children. */ size = xml_element_children_size(elemP); params = xml_element_children(elemP); for (i = 0; i < size; ++i) { unsigned int const maxNest = xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID); param = params[i]; CHECK_NAME(envP, param, "param"); CHECK_CHILD_COUNT(envP, param, 1); value = xml_element_children(param)[0]; CHECK_NAME(envP, value, "value"); xmlrpc_parseValue(envP, maxNest, value, &item); XMLRPC_FAIL_IF_FAULT(envP); xmlrpc_array_append_item(envP, array, item); xmlrpc_DECREF(item); item = NULL; XMLRPC_FAIL_IF_FAULT(envP); } cleanup: if (envP->fault_occurred) { if (array) xmlrpc_DECREF(array); if (item) xmlrpc_DECREF(item); return NULL; } return array; }
static xml_element * xmlElementNew(xmlrpc_env * const envP, const char * const name) { /*---------------------------------------------------------------------------- Create a new xml_element. This routine isn't exported, because the arguments are implementation-dependent. -----------------------------------------------------------------------------*/ xml_element * retval; bool nameIsValid; bool cdataIsValid; bool childrenAreValid; XMLRPC_ASSERT_ENV_OK(envP); assert(name != NULL); /* Set up our error-handling preconditions. */ retval = NULL; nameIsValid = cdataIsValid = childrenAreValid = false; MALLOCVAR(retval); XMLRPC_FAIL_IF_NULL(retval, envP, XMLRPC_INTERNAL_ERROR, "Couldn't allocate memory for XML element"); retval->parentP = NULL; /* Copy over the element name. */ retval->name = strdup(name); XMLRPC_FAIL_IF_NULL(retval->name, envP, XMLRPC_INTERNAL_ERROR, "Couldn't allocate memory for XML element"); nameIsValid = true; /* Initialize a block to hold our CDATA. */ XMLRPC_TYPED_MEM_BLOCK_INIT(char, envP, &retval->cdata, 0); XMLRPC_FAIL_IF_FAULT(envP); cdataIsValid = true; /* Initialize a block to hold our child elements. */ XMLRPC_TYPED_MEM_BLOCK_INIT(xml_element *, envP, &retval->children, 0); XMLRPC_FAIL_IF_FAULT(envP); childrenAreValid = true; cleanup: if (envP->fault_occurred) { if (retval) { if (nameIsValid) xmlrpc_strfree(retval->name); if (cdataIsValid) xmlrpc_mem_block_clean(&retval->cdata); if (childrenAreValid) xmlrpc_mem_block_clean(&retval->children); free(retval); } retval = NULL; } return retval; }
static void parseInt(xmlrpc_env * const envP, const char * const str, xmlrpc_value ** const valuePP) { /*---------------------------------------------------------------------------- Parse the content of a <int> XML-RPC XML element, e.g. "34". 'str' is that content. -----------------------------------------------------------------------------*/ XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(str); if (str[0] == '\0') setParseFault(envP, "<int> XML element content is empty"); else if (isspace(str[0])) setParseFault(envP, "<int> content '%s' starts with white space", str); else { long i; char * tail; errno = 0; i = strtol(str, &tail, 10); /* Look for ERANGE. */ if (errno == ERANGE) setParseFault(envP, "<int> XML element value '%s' represents a " "number beyond the range that " "XML-RPC allows (%d - %d)", str, XMLRPC_INT32_MIN, XMLRPC_INT32_MAX); else if (errno != 0) setParseFault(envP, "unexpected error parsing <int> XML element " "value '%s'. strtol() failed with errno %d (%s)", str, errno, strerror(errno)); else { /* Look for out-of-range errors which didn't produce ERANGE. */ if (i < XMLRPC_INT32_MIN) setParseFault(envP, "<int> value %ld is below the range allowed " "by XML-RPC (minimum is %d)", i, XMLRPC_INT32_MIN); else if (i > XMLRPC_INT32_MAX) setParseFault(envP, "<int> value %ld is above the range allowed " "by XML-RPC (maximum is %d)", i, XMLRPC_INT32_MAX); else { if (tail[0] != '\0') setParseFault(envP, "<int> value '%s' contains non-numerical " "junk: '%s'", str, tail); else *valuePP = xmlrpc_int_new(envP, i); } } } }
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 xmlElementAppendCdata(xmlrpc_env * const envP, xml_element * const elemP, const char * const cdata, size_t const size) { XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_ELEM_OK(elemP); XMLRPC_TYPED_MEM_BLOCK_APPEND(char, envP, &elemP->cdata, cdata, size); }
void xmlrpc_client_create(xmlrpc_env * const envP, int const flags, const char * const appname, const char * const appversion, const struct xmlrpc_clientparms * const clientparmsP, unsigned int const parmSize, xmlrpc_client ** const clientPP) { XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(clientPP); if (constSetupCount == 0) { xmlrpc_faultf(envP, "You have not called " "xmlrpc_client_setup_global_const()."); /* Impl note: We can't just call it now because it isn't thread-safe. */ } else { const char * transportName; struct xportParms transportparms; const struct xmlrpc_client_transport_ops * transportOpsP; xmlrpc_client_transport * transportP; xmlrpc_dialect dialect; xmlrpc_progress_fn * progressFn; getTransportInfo(envP, clientparmsP, parmSize, &transportName, &transportparms, &transportOpsP, &transportP); getDialectFromClientParms(clientparmsP, parmSize, &dialect); progressFn = parmSize >= XMLRPC_CPSIZE(progressFn) ? clientparmsP->progressFn : NULL; if (!envP->fault_occurred) { if (transportName) createTransportAndClient(envP, transportName, transportparms.parmsP, transportparms.size, flags, appname, appversion, dialect, progressFn, clientPP); else { bool myTransportFalse = false; clientCreate(envP, myTransportFalse, transportOpsP, transportP, dialect, progressFn, clientPP); } } } }
void xml_init(xmlrpc_env * const envP) { XMLRPC_ASSERT_ENV_OK(envP); /* N.B. xmlInitParser() does not stack. Calling it twice is the same as calling it once. Consequently, the same is true of xml_init(). N.B. xmlInitParser() is necessary for form only, because every libxml2 subroutine that needs it to be called just calls it itself. */ xmlInitParser(); }
void xmlrpc_server_abyss_global_init(xmlrpc_env * const envP) { /* Note that this is specified as not thread safe; user calls it at the beginning of his program, when it is only one thread. */ XMLRPC_ASSERT_ENV_OK(envP); if (globallyInitialized == 0) initAbyss(envP); ++globallyInitialized; }
static void parseStruct(xmlrpc_env * const envP, unsigned int const maxRecursion, xml_element * const elemP, xmlrpc_value ** const structPP) { /*---------------------------------------------------------------------------- Parse the <struct> element 'elemP'. -----------------------------------------------------------------------------*/ xmlrpc_value * structP; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT(elemP != NULL); structP = xmlrpc_struct_new(envP); if (!envP->fault_occurred) { /* Iterate over our children, extracting key/value pairs. */ xml_element ** const members = xml_element_children(elemP); unsigned int const size = xml_element_children_size(elemP); unsigned int i; for (i = 0; i < size && !envP->fault_occurred; ++i) { const char * const elemName = xml_element_name(members[i]); if (!xmlrpc_streq(elemName, "member")) setParseFault(envP, "<%s> element found where only <member> " "makes sense", elemName); else { xmlrpc_value * keyP; xmlrpc_value * valueP; parseMember(envP, members[i], maxRecursion, &keyP, &valueP); if (!envP->fault_occurred) { xmlrpc_struct_set_value_v(envP, structP, keyP, valueP); xmlrpc_DECREF(keyP); xmlrpc_DECREF(valueP); } } } if (envP->fault_occurred) xmlrpc_DECREF(structP); else *structPP = structP; } }
void xmlrpc_parse_value_xml(xmlrpc_env * const envP, const char * const xmlData, size_t const xmlDataLen, xmlrpc_value ** const valuePP) { /*---------------------------------------------------------------------------- Compute the xmlrpc_value represented by the XML document 'xmlData' (of length 'xmlDataLen' characters), which must consist of a single <value> element. Return that xmlrpc_value. We call convert_array() and convert_struct(), which may ultimately call us recursively. Don't recurse any more than 'maxRecursion' times. This isn't generally useful in XML-RPC programs, because such programs parse a whole XML-RPC call or response document, and never see the XML text of just a <value> element. But a program may do some weird form of XML-RPC processing or just borrow Xmlrpc-c's value serialization facilities for something unrelated to XML-RPC. In any case, it makes sense to have an inverse of xmlrpc_serialize_value2(), which generates XML text from an xmlrpc_value. -----------------------------------------------------------------------------*/ xmlrpc_env env; xml_element * valueEltP; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT(xmlData != NULL); xmlrpc_env_init(&env); xml_parse(&env, xmlData, xmlDataLen, &valueEltP); if (env.fault_occurred) { setParseFault(envP, "Not valid XML. %s", env.fault_string); } else { if (xmlrpc_streq(xml_element_name(valueEltP), "value")) { unsigned int const maxRecursion = (unsigned int) xmlrpc_limit_get(XMLRPC_NESTING_LIMIT_ID); xmlrpc_parseValue(envP, maxRecursion, valueEltP, valuePP); } else setParseFault(envP, "XML-RPC value XML document must consist of " "a <value> element. This has a <%s> instead.", xml_element_name(valueEltP)); xml_element_free(valueEltP); } xmlrpc_env_clean(&env); }
void xmlrpc_mem_block_append(xmlrpc_env * const envP, xmlrpc_mem_block * const blockP, const void * const data, size_t const len) { size_t const originalSize = blockP->_size; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT(blockP != NULL); xmlrpc_mem_block_resize(envP, blockP, originalSize + len); if (!envP->fault_occurred) { memcpy(((unsigned char*) blockP->_block) + originalSize, data, len); } }
void xmlrpc_server_info_set_user(xmlrpc_env * const envP, xmlrpc_server_info * const serverInfoP, const char * const username, const char * const password) { const char * userNamePw; xmlrpc_mem_block * userNamePw64; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(serverInfoP); XMLRPC_ASSERT_PTR_OK(username); XMLRPC_ASSERT_PTR_OK(password); xmlrpc_asprintf(&userNamePw, "%s:%s", username, password); userNamePw64 = xmlrpc_base64_encode_without_newlines(envP, (unsigned char*) userNamePw, strlen(userNamePw)); if (!envP->fault_occurred) { const char * const data = XMLRPC_MEMBLOCK_CONTENTS(char, userNamePw64); size_t const len = XMLRPC_MEMBLOCK_SIZE(char, userNamePw64); const char * const authType = "Basic "; char * hdrValue; hdrValue = malloc(strlen(authType) + len + 1); if (hdrValue == NULL) xmlrpc_faultf(envP, "Could not allocate memory to store " "authorization header value."); else { strcpy(hdrValue, authType); strncat(hdrValue, data, len); if (serverInfoP->basicAuthHdrValue) xmlrpc_strfree(serverInfoP->basicAuthHdrValue); serverInfoP->basicAuthHdrValue = hdrValue; } XMLRPC_MEMBLOCK_FREE(char, userNamePw64); } if (serverInfoP->userNamePw) xmlrpc_strfree(serverInfoP->userNamePw); serverInfoP->userNamePw = userNamePw; }
void xmlrpc_client_call2(xmlrpc_env * const envP, struct xmlrpc_client * const clientP, const xmlrpc_server_info * const serverInfoP, const char * const methodName, xmlrpc_value * const paramArrayP, xmlrpc_value ** const resultPP) { xmlrpc_mem_block * callXmlP; XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(clientP); XMLRPC_ASSERT_PTR_OK(serverInfoP); XMLRPC_ASSERT_PTR_OK(paramArrayP); makeCallXml(envP, methodName, paramArrayP, clientP->dialect, &callXmlP); if (!envP->fault_occurred) { xmlrpc_mem_block * respXmlP; xmlrpc_traceXml("XML-RPC CALL", XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP), XMLRPC_MEMBLOCK_SIZE(char, callXmlP)); clientP->transportOps.call( envP, clientP->transportP, serverInfoP, callXmlP, &respXmlP); if (!envP->fault_occurred) { int faultCode; const char * faultString; xmlrpc_traceXml("XML-RPC RESPONSE", XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP), XMLRPC_MEMBLOCK_SIZE(char, respXmlP)); parseResponse(envP, respXmlP, resultPP, &faultCode, &faultString); if (!envP->fault_occurred) { if (faultString) { xmlrpc_env_set_fault_formatted( envP, faultCode, "RPC failed at server. %s", faultString); xmlrpc_strfree(faultString); } else XMLRPC_ASSERT_VALUE_OK(*resultPP); } XMLRPC_MEMBLOCK_FREE(char, respXmlP); }
xmlrpc_registry * xmlrpc_registry_new(xmlrpc_env *env) { xmlrpc_value *methods; xmlrpc_registry *registry; int registry_valid; XMLRPC_ASSERT_ENV_OK(env); /* Error-handling preconditions. */ methods = NULL; registry = NULL; registry_valid = 0; /* Allocate our memory. */ methods = xmlrpc_struct_new(env); XMLRPC_FAIL_IF_FAULT(env); registry = (xmlrpc_registry*) malloc(sizeof(xmlrpc_registry)); XMLRPC_FAIL_IF_NULL(registry, env, XMLRPC_INTERNAL_ERROR, "Could not allocate memory for registry"); /* Set everything up. */ registry->_introspection_enabled = 1; registry->_methods = methods; registry->_default_method = NULL; registry->_preinvoke_method = NULL; registry_valid = 1; /* Install our system methods. */ install_system_methods(env, registry); XMLRPC_FAIL_IF_FAULT(env); cleanup: if (env->fault_occurred) { if (registry_valid) { xmlrpc_registry_free(registry); } else { if (methods) xmlrpc_DECREF(methods); if (registry) free(registry); } return NULL; } return registry; }
xmlrpc_value * xmlrpc_struct_new(xmlrpc_env * const envP) { xmlrpc_value * valP; XMLRPC_ASSERT_ENV_OK(envP); xmlrpc_createXmlrpcValue(envP, &valP); if (!envP->fault_occurred) { valP->_type = XMLRPC_TYPE_STRUCT; XMLRPC_MEMBLOCK_INIT(_struct_member, envP, &valP->_block, 0); if (envP->fault_occurred) free(valP); } return valP; }
void xmlrpc_client_transport_call2( xmlrpc_env * const envP, xmlrpc_client * const clientP, const xmlrpc_server_info * const serverP, xmlrpc_mem_block * const callXmlP, xmlrpc_mem_block ** const respXmlPP) { XMLRPC_ASSERT_ENV_OK(envP); XMLRPC_ASSERT_PTR_OK(clientP); XMLRPC_ASSERT_PTR_OK(serverP); XMLRPC_ASSERT_PTR_OK(callXmlP); XMLRPC_ASSERT_PTR_OK(respXmlPP); clientP->transportOps.call( envP, clientP->transportP, serverP, callXmlP, respXmlPP); }
void xmlrpc_client_setup_global_const(xmlrpc_env * const envP) { /*---------------------------------------------------------------------------- Set up pseudo-constant global variables (they'd be constant, except that the library loader doesn't set them. An explicit call from the loaded program does). This function is not thread-safe. The user is supposed to call it (perhaps cascaded down from a multitude of higher level libraries) as part of early program setup, when the program is only one thread. -----------------------------------------------------------------------------*/ XMLRPC_ASSERT_ENV_OK(envP); if (constSetupCount == 0) setupTransportGlobalConst(envP); ++constSetupCount; }