static void validateUtf16(xmlrpc_env *const envP, wchar_t const wc) { /*---------------------------------------------------------------------------- Validate that the string is a legal UTF16 encoding of a Unicode character. Actually, we validate that it is UCS-2. The set of UCS-2 encodings is a subset of the set of UTF16 encodings. In particular, it is the set of UTF16 encodings that are 16 bits. UCS-2 is a fixed-length encoding, with 16 bits per character, whereas UTF16 is variable length, with 1 or more 16 bit units per character. The name of the subroutine reflects the fact that in concept, we _should_ accept any UTF16, but we haven't taken the time yet to figure out how to do that (in the big picture, not just this subroutine). The user will notice only if he uses those really arcane 3.1% of the Unicode characters that take more than 16 bits to represent in UTF16. -----------------------------------------------------------------------------*/ if (wc > UCS2_MAX_LEGAL_CHARACTER) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INVALID_UTF8_ERROR, "Xmlrpc-c is not capable of handling UTF16 character encodings " "longer than 16 bits, which means you can't have a code point " "> U+FFFD. " "This string contains 0x%04x", (unsigned) wc); else if (UTF16_FIRST_SURROGATE <= wc && wc <= UTF16_LAST_SURROGATE) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INVALID_UTF8_ERROR, "UTF-16 surrogates may not appear in UTF-8 data. " "String contains %04x", (unsigned) wc); }
// Return open index for given key or 0 Index *open_index(xmlrpc_env *env, int key) { try { ServerConfig config; if (!get_config(env, config)) return 0; stdString index_name; if (!config.find(key, index_name)) { xmlrpc_env_set_fault_formatted(env, ARCH_DAT_NO_INDEX, "Invalid key %d", key); return 0; } LOG_MSG("Open index, key %d = '%s'\n", key, index_name.c_str()); AutoPtr<Index> index(new AutoIndex()); if (!index) { xmlrpc_env_set_fault_formatted(env, ARCH_DAT_NO_INDEX, "Cannot allocate index"); return 0; } index->open(index_name); return index.release(); } catch (GenericException &e) { LOG_MSG("Error: %s\n", e.what()); xmlrpc_env_set_fault_formatted(env, ARCH_DAT_NO_INDEX, "%s", e.what()); } return 0; }
static void validateFractionalSeconds(xmlrpc_env * const envP, const char * const dt) { /*---------------------------------------------------------------------------- Validate the fractional seconds part of the XML-RPC datetime string 'dt', if any. That's the decimal point and everything following it. -----------------------------------------------------------------------------*/ if (strlen(dt) > 17) { if (dt[17] != '.') { xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "'%c' where only a period is valid", dt[17]); } else { if (dt[18] == '\0') xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Nothing after decimal point"); else { unsigned int i; for (i = 18; dt[i] != '\0' && !envP->fault_occurred; ++i) { if (!isdigit(dt[i])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Non-digit in fractional seconds: '%c'", dt[i]); } } } } }
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 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 xmlrpc_value * service_set_url (xmlrpc_env *env, xmlrpc_value *param_array, void *user_data) { char *service_identifier; char *old_url, *new_url; RCWorldService *service; xmlrpc_parse_value (env, param_array, "(ss)", &service_identifier, &new_url); XMLRPC_FAIL_IF_FAULT (env); service = service_lookup (service_identifier); if (!service) { xmlrpc_env_set_fault_formatted (env, RCD_RPC_FAULT_INVALID_SERVICE, "Unable to unmount service for '%s'", service_identifier); goto cleanup; } old_url = service->url; service->url = g_strdup (new_url); /* FIXME: This is wrong. rc_world_refresh () returns pending only if refresh has not completed yet. Pending needs to be unref'ed when we're done with it as well. It's not a big deal right now as nothing actually calls this anymore. */ if (!rc_world_refresh (RC_WORLD (service))) { xmlrpc_env_set_fault_formatted (env, RCD_RPC_FAULT_INVALID_SERVICE, "Unable to change mirrors for '%s'", service->name); g_free (service->url); service->url = old_url; goto cleanup; } g_free (old_url); rcd_services_save (); cleanup: if (env->fault_occurred) return NULL; return xmlrpc_build_value (env, "i", 0); }
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_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); }
static xmlrpc_value * service_remove (xmlrpc_env *env, xmlrpc_value *param_array, void *user_data) { char *service_identifier; RCWorldService *service; xmlrpc_parse_value (env, param_array, "(s)", &service_identifier); XMLRPC_FAIL_IF_FAULT (env); service = service_lookup (service_identifier); if (!service) { xmlrpc_env_set_fault_formatted (env, RCD_RPC_FAULT_INVALID_SERVICE, "Unable to unmount service for '%s'", service_identifier); goto cleanup; } rc_world_multi_remove_subworld (RC_WORLD_MULTI (rc_get_world ()), RC_WORLD (service)); rcd_services_save (); cleanup: if (env->fault_occurred) return NULL; return xmlrpc_build_value (env, "i", 0); }
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; }
static void writeFile(xmlrpc_env * const envP, FILE * const ofP, xmlrpc_mem_block * const fileContentsP) { size_t totalWritten; totalWritten = 0; while (!envP->fault_occurred && totalWritten < XMLRPC_MEMBLOCK_SIZE(char, fileContentsP)) { size_t bytesWritten; bytesWritten = fwrite( XMLRPC_MEMBLOCK_CONTENTS(char, fileContentsP) + totalWritten, 1, XMLRPC_MEMBLOCK_SIZE(char, fileContentsP) - totalWritten, ofP); if (bytesWritten < 1) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INTERNAL_ERROR, "Error writing output"); totalWritten -= bytesWritten; } }
static void setParseErr(xmlrpc_env * const envP, Tokenizer * const tokP, const char * const format, ...) { struct docPosition const pos = currentDocumentPosition(tokP); va_list args; const char * msg; XMLRPC_ASSERT(envP != NULL); XMLRPC_ASSERT(format != NULL); va_start(args, format); xmlrpc_vasprintf(&msg, format, args); xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "JSON parse error at Line %u, Column %u: %s", pos.lineNum, pos.colNum, msg); xmlrpc_strfree(msg); va_end(args); }
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); } }
void xmlrpc_read_base64(xmlrpc_env * const envP, const xmlrpc_value * const valueP, size_t * const lengthP, const unsigned char ** const byteStringValueP) { validateType(envP, valueP, XMLRPC_TYPE_BASE64); if (!envP->fault_occurred) { size_t const size = XMLRPC_MEMBLOCK_SIZE(char, &valueP->_block); const char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); char * byteStringValue; byteStringValue = calloc(1,size); if (byteStringValue == NULL) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate %u bytes " "for byte string.", size); else { memcpy(byteStringValue, contents, size); *byteStringValueP = (const unsigned char *)byteStringValue; *lengthP = size; } }
static void parseCallXml(xmlrpc_env * const envP, const char * const xmlData, size_t const xmlDataLen, xml_element ** const callElemPP) { /*---------------------------------------------------------------------------- Parse the XML of an XML-RPC call. -----------------------------------------------------------------------------*/ xml_element * callElemP; xmlrpc_env env; xmlrpc_env_init(&env); xml_parse(&env, xmlData, xmlDataLen, &callElemP); if (env.fault_occurred) xmlrpc_env_set_fault_formatted( envP, env.fault_code, "Call is not valid XML. %s", env.fault_string); else { if (!xmlrpc_streq(xml_element_name(callElemP), "methodCall")) setParseFault(envP, "XML-RPC call should be a <methodCall> element. " "Instead, we have a <%s> element.", xml_element_name(callElemP)); if (envP->fault_occurred) xml_element_free(callElemP); } *callElemPP = callElemP; xmlrpc_env_clean(&env); }
static xmlrpc_value * service_add (xmlrpc_env *env, xmlrpc_value *param_array, void *user_data) { char *service_url, *mangled_url; GError *err = NULL; xmlrpc_parse_value (env, param_array, "(s)", &service_url); XMLRPC_FAIL_IF_FAULT (env); /* We always want to download data from the site */ mangled_url = g_strconcat (service_url, "?remote_only=1", NULL); if (!rc_world_multi_mount_service (RC_WORLD_MULTI (rc_get_world ()), mangled_url, &err)) { xmlrpc_env_set_fault_formatted (env, RCD_RPC_FAULT_INVALID_SERVICE, "Unable to mount service for '%s': %s", service_url, err->message); } else rcd_services_save (); g_free (mangled_url); cleanup: if (env->fault_occurred) return NULL; return xmlrpc_build_value (env, "i", 0); }
static void test_env(void) { xmlrpc_env env, env2; char *s; /* Test xmlrpc_env_init. */ xmlrpc_env_init(&env); TEST(!env.fault_occurred); TEST(env.fault_code == 0); TEST(env.fault_string == NULL); /* Test xmlrpc_set_fault. */ xmlrpc_env_set_fault(&env, 1, test_string_1); TEST(env.fault_occurred); TEST(env.fault_code == 1); TEST(env.fault_string != test_string_1); TEST(strcmp(env.fault_string, test_string_1) == 0); /* Change an existing fault. */ xmlrpc_env_set_fault(&env, 2, test_string_2); TEST(env.fault_occurred); TEST(env.fault_code == 2); TEST(strcmp(env.fault_string, test_string_2) == 0); /* Set a fault with a format string. */ xmlrpc_env_set_fault_formatted(&env, 3, "a%s%d", "bar", 9); TEST(env.fault_occurred); TEST(env.fault_code == 3); TEST(strcmp(env.fault_string, "abar9") == 0); /* Set a fault with an oversized string. */ s = "12345678901234567890123456789012345678901234567890"; xmlrpc_env_set_fault_formatted(&env, 4, "%s%s%s%s%s%s", s, s, s, s, s, s); TEST(env.fault_occurred); TEST(env.fault_code == 4); TEST(strlen(env.fault_string) == 255); /* Test cleanup code (with help from memprof). */ xmlrpc_env_clean(&env); /* Test cleanup code on in absence of xmlrpc_env_set_fault. */ xmlrpc_env_init(&env2); xmlrpc_env_clean(&env2); }
static void validateFirst17(xmlrpc_env * const envP, const char * const dt) { /*---------------------------------------------------------------------------- Assuming 'dt' is at least 17 characters long, validate that the first 17 characters are a valid XML-RPC datetime, e.g. "20080628T16:35:02" -----------------------------------------------------------------------------*/ unsigned int i; for (i = 0; i < 8 && !envP->fault_occurred; ++i) if (!isdigit(dt[i])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[i]); if (dt[8] != 'T') xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "9th character is '%c', not 'T'", dt[8]); if (!isdigit(dt[9])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[9]); if (!isdigit(dt[10])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[10]); if (dt[11] != ':') xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a colon: '%c'", dt[11]); if (!isdigit(dt[12])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[12]); if (!isdigit(dt[13])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[13]); if (dt[14] != ':') xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a colon: '%c'", dt[14]); if (!isdigit(dt[15])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[15]); if (!isdigit(dt[16])) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Not a digit: '%c'", dt[16]); }
static void validateContinuation(xmlrpc_env *const envP, char const c) { if (!IS_CONTINUATION(c)) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INVALID_UTF8_ERROR, "UTF-8 multibyte sequence contains character 0x%02x, " "which does not indicate continuation.", c); }
// Return name of configuration file from environment or 0 const char *get_config_name(xmlrpc_env *env) { const char *name = getenv("SERVERCONFIG"); if (!name) { xmlrpc_env_set_fault_formatted(env, ARCH_DAT_NO_INDEX, "SERVERCONFIG is undefined"); return 0; } return name; }
static void validateStringType(xmlrpc_env * const envP, const xmlrpc_value * const valueP) { if (valueP->_type != XMLRPC_TYPE_STRING) { xmlrpc_env_set_fault_formatted( envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where " "string type was expected.", xmlrpc_type_name(valueP->_type)); } }
static void processCall(TSession * const abyssSessionP, size_t const contentSize, xmlrpc_call_processor xmlProcessor, void * const xmlProcessorArg, bool const wantChunk, ResponseAccessCtl const accessControl, const char * const trace) { /*---------------------------------------------------------------------------- Handle an RPC request. This is an HTTP request that has the proper form to be an XML-RPC call. The text of the call is available through the Abyss session 'abyssSessionP'. Its content length is 'contentSize' bytes. -----------------------------------------------------------------------------*/ xmlrpc_env env; if (trace) fprintf(stderr, "xmlrpc_server_abyss URI path handler processing RPC.\n"); xmlrpc_env_init(&env); if (contentSize > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID)) xmlrpc_env_set_fault_formatted( &env, XMLRPC_LIMIT_EXCEEDED_ERROR, "XML-RPC request too large (%u bytes)", (unsigned)contentSize); else { xmlrpc_mem_block * body; /* Read XML data off the wire. */ getBody(&env, abyssSessionP, contentSize, trace, &body); if (!env.fault_occurred) { xmlrpc_mem_block * output; /* Process the RPC. */ xmlProcessor( &env, xmlProcessorArg, XMLRPC_MEMBLOCK_CONTENTS(char, body), XMLRPC_MEMBLOCK_SIZE(char, body), abyssSessionP, &output); if (!env.fault_occurred) { /* Send out the result. */ sendResponse(&env, abyssSessionP, XMLRPC_MEMBLOCK_CONTENTS(char, output), XMLRPC_MEMBLOCK_SIZE(char, output), wantChunk, accessControl); XMLRPC_MEMBLOCK_FREE(char, output); } XMLRPC_MEMBLOCK_FREE(char, body); }
static void validateDatetimeType(xmlrpc_env *const envP, const xmlrpc_value *const valueP) { if (valueP->_type != XMLRPC_TYPE_DATETIME) { xmlrpc_env_set_fault_formatted( envP, XMLRPC_TYPE_ERROR, "Value of type %s supplied where " "type %s was expected.", xmlrpc_type_name(valueP->_type), xmlrpc_type_name(XMLRPC_TYPE_DATETIME)); } }
static void validateArraySize(xmlrpc_env * const envP, const xmlrpc_value * const arrayP, struct arrayDecomp const arrayDecomp) { unsigned int size; size = xmlrpc_array_size(envP, arrayP); if (!envP->fault_occurred) { if (arrayDecomp.itemCnt > size) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INDEX_ERROR, "Format string requests %u items from array, but array " "has only %u items.", arrayDecomp.itemCnt, size); else if (arrayDecomp.itemCnt < size && !arrayDecomp.ignoreExcess) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INDEX_ERROR, "Format string requests exactly %u items from array, " "but array has %u items. (A '*' at the end would avoid " "this failure)", arrayDecomp.itemCnt, size); } }
bool get_config(xmlrpc_env *env, ServerConfig &config) { const char *config_name = get_config_name(env); if (env->fault_occurred) return false; if (!config.read(config_name)) { xmlrpc_env_set_fault_formatted(env, ARCH_DAT_NO_INDEX, "Cannot open config '%s'", config_name); return false; } return true; }
void xmlrpc_read_datetime_usec(xmlrpc_env *const envP, const xmlrpc_value *const valueP, time_t *const secsP, unsigned int *const usecsP) { validateDatetimeType(envP, valueP); if (!envP->fault_occurred) { if (valueP->_value.dt.Y < 1970) xmlrpc_faultf(envP, "Year (%u) is too early to represent as " "a standard Unix time", valueP->_value.dt.Y); else { struct tm brokenTime; const char *error; brokenTime.tm_sec = valueP->_value.dt.s; brokenTime.tm_min = valueP->_value.dt.m; brokenTime.tm_hour = valueP->_value.dt.h; brokenTime.tm_mday = valueP->_value.dt.D; brokenTime.tm_mon = valueP->_value.dt.M - 1; brokenTime.tm_year = valueP->_value.dt.Y - 1900; xmlrpc_timegm(&brokenTime, secsP, &error); if (error) { /* Ideally, this wouldn't be possible - it wouldn't be possible to create an xmlrpc_value that doesn't actually represent a real datetime. But today, we're lazy and don't fully validate incoming XML-RPC <dateTime.iso8601> elements, and we also have the legacy xmlrpc_datetime_new_str() constructor to which the user may feed garbage. We should tighten that up and then simply assert here that xmlrpc_timegm() succeeded. */ xmlrpc_env_set_fault_formatted(envP, XMLRPC_PARSE_ERROR, "A datetime received in an XML-RPC message " "or generated with legacy Xmlrpc-c facilities " "does not validly describe a datetime. %s", error); xmlrpc_strfree(error); } else *usecsP = valueP->_value.dt.u; } } }
static void verifyNoNullsW(xmlrpc_env * const envP, const wchar_t * const contents, unsigned int const len) { /*---------------------------------------------------------------------------- Same as verifyNoNulls(), but for wide characters. -----------------------------------------------------------------------------*/ unsigned int i; for (i = 0; i < len && !envP->fault_occurred; i++) if (contents[i] == '\0') xmlrpc_env_set_fault_formatted( envP, XMLRPC_TYPE_ERROR, "String must not contain NUL characters"); }
static void parseDtRegex(xmlrpc_env * const envP, const char * const datetimeString, xmlrpc_datetime * const dtP) { unsigned int i; const struct regexParser * parserP; /* The parser that matches 'datetimeString'. Null if no match yet found. */ regmatch_t matches[1024]; for (i = 0, parserP = NULL; iso8601Regex[i].regex && !parserP; ++i) { const struct regexParser * const thisParserP = &iso8601Regex[i]; regex_t re; int status; status = regcomp(&re, thisParserP->regex, REG_ICASE | REG_EXTENDED); /* Our regex is valid, so it must have compiled: */ assert(status == 0); { int status; status = regexec(&re, datetimeString, ARRAY_SIZE(matches), matches, 0); if (status == 0) { assert(matches[0].rm_so != -1); /* Match of whole regex */ parserP = thisParserP; } regfree(&re); } } if (parserP) { parserP->func(matches, datetimeString, dtP); } else { xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "value '%s' is not of any form we recognize " "for a <dateTime.iso8601> element", datetimeString); } }
void xmlrpc_read_datetime_str(xmlrpc_env * const envP, const xmlrpc_value * const valueP, const char ** const stringValueP) { validateDatetimeType(envP, valueP); if (!envP->fault_occurred) { const char * const contents = XMLRPC_MEMBLOCK_CONTENTS(char, &valueP->_block); *stringValueP = strdup(contents); if (*stringValueP == NULL) xmlrpc_env_set_fault_formatted( envP, XMLRPC_INTERNAL_ERROR, "Unable to allocate space " "for datetime string"); } }
static __inline__ void validateFormatNoRegex(xmlrpc_env * const envP, const char * const dt) { if (strlen(dt) < 17) xmlrpc_env_set_fault_formatted( envP, XMLRPC_PARSE_ERROR, "Invalid length of %u of datetime. " "Must be at least 17 characters", (unsigned)strlen(dt)); else { validateFirst17(envP, dt); validateFractionalSeconds(envP, dt); } }
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); }