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_faultf(envP, "Not a digit: '%c'", dt[i]); if (dt[8] != 'T') xmlrpc_faultf(envP, "9th character is '%c', not 'T'", dt[8]); if (!isdigit(dt[9])) xmlrpc_faultf(envP, "Not a digit: '%c'", dt[9]); if (!isdigit(dt[10])) xmlrpc_faultf(envP, "Not a digit: '%c'", dt[10]); if (dt[11] != ':') xmlrpc_faultf(envP, "Not a colon: '%c'", dt[11]); if (!isdigit(dt[12])) xmlrpc_faultf(envP, "Not a digit: '%c'", dt[12]); if (!isdigit(dt[13])) xmlrpc_faultf(envP, "Not a digit: '%c'", dt[13]); if (dt[14] != ':') xmlrpc_faultf(envP, "Not a colon: '%c'", dt[14]); if (!isdigit(dt[15])) xmlrpc_faultf(envP, "Not a digit: '%c'", dt[15]); if (!isdigit(dt[16])) xmlrpc_faultf(envP, "Not a digit: '%c'", dt[16]); }
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 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_faultf(envP, "'%c' where only a period is valid", dt[17]); } else { if (dt[18] == '\0') xmlrpc_faultf(envP, "Nothing after decimal point"); else { unsigned int i; for (i = 18; dt[i] != '\0' && !envP->fault_occurred; ++i) { if (!isdigit(dt[i])) xmlrpc_faultf(envP, "Non-digit in fractional seconds: '%c'", dt[i]); } } } } }
static void getTransportInfo( xmlrpc_env * const envP, const struct xmlrpc_clientparms * const clientparmsP, unsigned int const parmSize, const char ** const transportNameP, struct xportParms * const transportParmsP, const struct xmlrpc_client_transport_ops ** const transportOpsPP, xmlrpc_client_transport ** const transportPP) { const char * transportNameParm; xmlrpc_client_transport * transportP; const struct xmlrpc_client_transport_ops * transportOpsP; if (parmSize < XMLRPC_CPSIZE(transport)) transportNameParm = NULL; else transportNameParm = clientparmsP->transport; if (parmSize < XMLRPC_CPSIZE(transportP)) transportP = NULL; else transportP = clientparmsP->transportP; if (parmSize < XMLRPC_CPSIZE(transportOpsP)) transportOpsP = NULL; else transportOpsP = clientparmsP->transportOpsP; if ((transportOpsP && !transportP) || (transportP && ! transportOpsP)) xmlrpc_faultf(envP, "'transportOpsP' and 'transportP' go together. " "You must specify both or neither"); else if (transportNameParm && transportP) xmlrpc_faultf(envP, "You cannot specify both 'transport' and " "'transportP' transport parameters."); else if (transportP) *transportNameP = NULL; else if (transportNameParm) *transportNameP = transportNameParm; else *transportNameP = xmlrpc_client_get_default_transport(envP); *transportOpsPP = transportOpsP; *transportPP = transportP; if (!envP->fault_occurred) { getTransportParmsFromClientParms( envP, clientparmsP, parmSize, transportParmsP); if (!envP->fault_occurred) { if (transportParmsP->parmsP && !transportNameParm) xmlrpc_faultf( envP, "You specified transport parameters, but did not " "specify a transport type. Parameters are specific " "to a particular type."); } } }
static void extractSockAddrParms(xmlrpc_env * const envP, const xmlrpc_server_abyss_parms * const parmsP, unsigned int const parmSize, const struct sockaddr ** const sockAddrPP, socklen_t * const sockAddrLenP, unsigned int * const portNumberP) { /*---------------------------------------------------------------------------- Return the server parameters that affect the address on which the server socket shall listen. There are two ways the arguments can specify this: 1) user supplies a complete socket address, which specifies both a TCP port number and an IP address (which determines on which interface, ergo which network, if any, the server listens); and 2) just a TCP port number, which means he wants to listen on all IPv4 interfaces and networks. (2) is legacy. If the user specifies the 'sockaddrP' and 'sockaddrlen' arguments, he gets (1) and we ignore his 'port' argument. We return his 'sockaddrP' and 'sockaddrlen' values as *sockAddrPP and *sockAddrLenP and nothing as *portNumberP. If the user doesn't specify 'sockaddrP', he gets (2). We return NULL as *sockAddrP and his 'port_number' argument as *portNumberP. If he doesn't specify 'port' either, we default it to 8080. Specifying 'sockaddrP' and not 'sockaddrlen' is an error. Note that the user's socket address may indicate "any IP address." -----------------------------------------------------------------------------*/ if (parmSize >= XMLRPC_APSIZE(sockaddr_p)) { if (parmSize < XMLRPC_APSIZE(sockaddrlen)) xmlrpc_faultf(envP, "You must specify 'sockaddrlen' when you " "specify 'sockaddrP'"); else { *sockAddrPP = parmsP->sockaddr_p; *sockAddrLenP = parmsP->sockaddrlen; } } else *sockAddrPP = NULL; if (*sockAddrPP == NULL) { unsigned int portNumber; if (parmSize >= XMLRPC_APSIZE(port_number)) portNumber = parmsP->port_number; else portNumber = 8080; if (portNumber > 0xffff) xmlrpc_faultf(envP, "TCP port number %u exceeds the maximum possible " "TCP port number (65535)", portNumber); *portNumberP = portNumber; } }
void xmlrpc_server_abyss_set_handler3( xmlrpc_env * const envP, TServer * const srvP, const xmlrpc_server_abyss_handler_parms * const parmsP, unsigned int const parmSize) { struct uriHandlerXmlrpc * uriHandlerXmlrpcP; size_t xmlProcessorMaxStackSize; MALLOCVAR_NOFAIL(uriHandlerXmlrpcP); if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(xml_processor)) uriHandlerXmlrpcP->xmlProcessor = parmsP->xml_processor; else xmlrpc_faultf(envP, "Parameter too short to contain the required " "'xml_processor' member"); } if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(xml_processor_arg)) uriHandlerXmlrpcP->xmlProcessorArg = parmsP->xml_processor_arg; else xmlrpc_faultf(envP, "Parameter too short to contain the required " "'xml_processor_arg' member"); } if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(xml_processor_max_stack)) xmlProcessorMaxStackSize = parmsP->xml_processor_max_stack; else xmlrpc_faultf(envP, "Parameter too short to contain the required " "'xml_processor_max_stack' member"); } if (!envP->fault_occurred) { if (parmSize >= XMLRPC_AHPSIZE(uri_path) && parmsP->uri_path) uriHandlerXmlrpcP->uriPath = xmlrpc_strdupsol(parmsP->uri_path); else uriHandlerXmlrpcP->uriPath = xmlrpc_strdupsol("/RPC2"); if (parmSize >= XMLRPC_AHPSIZE(chunk_response) && parmsP->chunk_response) uriHandlerXmlrpcP->chunkResponse = parmsP->chunk_response; else uriHandlerXmlrpcP->chunkResponse = false; interpretHttpAccessControl(parmsP, parmSize, &uriHandlerXmlrpcP->accessControl); if (envP->fault_occurred) xmlrpc_termAccessControl(&uriHandlerXmlrpcP->accessControl); } if (!envP->fault_occurred) setHandler(envP, srvP, uriHandlerXmlrpcP, xmlProcessorMaxStackSize); if (envP->fault_occurred) free(uriHandlerXmlrpcP); }
static void parseOneSignature(xmlrpc_env * const envP, const char * const startP, struct xmlrpc_signature ** const signaturePP, const char ** const nextPP) { /*---------------------------------------------------------------------------- Parse one signature from the signature string that starts at 'startP'. Return that signature as a signature object *signaturePP. Return as *nextP the location in the signature string of the next signature (i.e. right after the next comma). If there is no next signature (the string ends before any comma), make it point to the terminating NUL. -----------------------------------------------------------------------------*/ struct xmlrpc_signature * signatureP; MALLOCVAR(signatureP); if (signatureP == NULL) xmlrpc_faultf(envP, "Couldn't get memory for signature"); else { const char * cursorP; signatureP->argListSpace = 0; /* Start with no argument space */ signatureP->argList = NULL; /* Nothing allocated yet */ signatureP->argCount = 0; /* Start with no arguments */ cursorP = startP; /* start at the beginning */ if (*cursorP == ',' || *cursorP == '\0') xmlrpc_faultf(envP, "empty signature (a signature " "must have at least return value type)"); else { translateTypeSpecifierToName(envP, *cursorP, &signatureP->retType); ++cursorP; if (*cursorP != ':') xmlrpc_faultf(envP, "No colon (':') after " "the result type specifier"); else { ++cursorP; parseArgumentTypeSpecifiers(envP, cursorP, signatureP, nextPP); } } if (envP->fault_occurred) free(signatureP); else *signaturePP = signatureP; } }
static void setHandler(xmlrpc_env * const envP, TServer * const srvP, struct uriHandlerXmlrpc * const uriHandlerXmlrpcP, size_t const xmlProcessorMaxStackSize) { abyss_bool success; xmlrpc_abyss_handler_trace( getenv("XMLRPC_TRACE_ABYSS")); { size_t const stackSize = xmlrpc_abyss_handler_stacksize() + xmlProcessorMaxStackSize; struct ServerReqHandler3 const handlerDesc = { /* .term = */ &xmlrpc_termUriHandler, /* .handleReq = */ &xmlrpc_handleIfXmlrpcReq, /* .userdata = */ uriHandlerXmlrpcP, /* .handleReqStackSize = */ stackSize }; ServerAddHandler3(srvP, &handlerDesc, &success); } if (!success) xmlrpc_faultf(envP, "Abyss failed to register the Xmlrpc-c request " "handler. ServerAddHandler3() failed."); }
static void validateGlobalInit(xmlrpc_env * const envP) { if (!globallyInitialized) xmlrpc_faultf(envP, "libxmlrpc_server_abyss has not been globally " "initialized. See xmlrpc_server_abyss_init()"); }
static void copyServerInfoContent(xmlrpc_env * const envP, xmlrpc_server_info * const dstP, const xmlrpc_server_info * const srcP) { dstP->serverUrl = strdup(srcP->serverUrl); if (dstP->serverUrl == NULL) xmlrpc_faultf(envP, "Couldn't allocate memory for server URL"); else { copyUserNamePw(envP, srcP->userNamePw, &dstP->userNamePw); if (!envP->fault_occurred) { copyBasicAuthHdrValue(envP, srcP->basicAuthHdrValue, &dstP->basicAuthHdrValue); if (!envP->fault_occurred) { dstP->allowedAuth.basic = srcP->allowedAuth.basic; dstP->allowedAuth.digest = srcP->allowedAuth.digest; dstP->allowedAuth.gssnegotiate = srcP->allowedAuth.gssnegotiate; dstP->allowedAuth.ntlm = srcP->allowedAuth.ntlm; if (envP->fault_occurred) freeIfNonNull(dstP->basicAuthHdrValue); } if (envP->fault_occurred) freeIfNonNull(dstP->userNamePw); } if (envP->fault_occurred) xmlrpc_strfree(dstP->serverUrl); } }
void curlMulti_addHandle(xmlrpc_env * const envP, curlMulti * const curlMultiP, CURL * const curlSessionP) { CURLMcode rc; curlMultiP->lockP->acquire(curlMultiP->lockP); rc = curl_multi_add_handle(curlMultiP->curlMultiP, curlSessionP); curlMultiP->lockP->release(curlMultiP->lockP); /* Old libcurl (e.g. 7.12) actually returns CURLM_CALL_MULTI_PERFORM (by design) when it succeeds. Current libcurl returns CURLM_OK. */ if (rc != CURLM_OK && rc != CURLM_CALL_MULTI_PERFORM) { const char * reason; interpretCurlMultiError(&reason, rc); xmlrpc_faultf(envP, "Could not add Curl session to the " "curl multi manager. curl_multi_add_handle() " "failed: %s", reason); xmlrpc_strfree(reason); } }
xmlrpc_value * xmlrpc_datetime_new(xmlrpc_env *const envP, xmlrpc_datetime const dt) { xmlrpc_value *valP; const char **readBufferP; MALLOCVAR(readBufferP); if (!readBufferP) xmlrpc_faultf(envP, "Couldn't get memory for the cache part of the " "XML-RPC datetime value object"); else { *readBufferP = NULL; xmlrpc_createXmlrpcValue(envP, &valP); if (!envP->fault_occurred) { valP->_type = XMLRPC_TYPE_DATETIME; valP->_value.dt = dt; valP->_cache = readBufferP; } if (envP->fault_occurred) free(readBufferP); } return valP; }
xmlrpc_value * xmlrpc_datetime_new_usec(xmlrpc_env *const envP, time_t const secs, unsigned int const usecs) { xmlrpc_value *valueP; if (usecs >= 1000000) xmlrpc_faultf(envP, "Number of fractional microseconds must be less " "than one million. You specified %u", usecs); else { struct tm brokenTime; xmlrpc_datetime dt; xmlrpc_gmtime(secs, &brokenTime); dt.s = brokenTime.tm_sec; dt.m = brokenTime.tm_min; dt.h = brokenTime.tm_hour; dt.D = brokenTime.tm_mday; dt.M = brokenTime.tm_mon + 1; dt.Y = 1900 + brokenTime.tm_year; dt.u = usecs; valueP = xmlrpc_datetime_new(envP, dt); } return valueP; }
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; } }
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 = malloc(size); if (byteStringValue == NULL) xmlrpc_faultf(envP, "Unable to allocate %u bytes for byte string.", (unsigned)size); else { memcpy(byteStringValue, contents, size); *byteStringValueP = (const unsigned char *)byteStringValue; *lengthP = size; } }
static void createServer(xmlrpc_env * const envP, const xmlrpc_server_abyss_parms * const parmsP, unsigned int const parmSize, TServer * const abyssServerP, TChanSwitch ** const chanSwitchPP) { createServerBare(envP, parmsP, parmSize, abyssServerP, chanSwitchPP); if (!envP->fault_occurred) { const char * error; setAdditionalServerParms(parmsP, parmSize, abyssServerP); setHandlersRegistry(abyssServerP, uriPathParm(parmsP, parmSize), parmsP->registryP, chunkResponseParm(parmsP, parmSize), allowOriginParm(parmsP, parmSize), expiresParm(parmsP, parmSize), maxAgeParm(parmsP, parmSize)); ServerInit2(abyssServerP, &error); if (error) { xmlrpc_faultf(envP, error); xmlrpc_strfree(error); } } }
void xmlrpc_client_init2(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) { /*---------------------------------------------------------------------------- This function is not thread-safe. -----------------------------------------------------------------------------*/ if (globalClientExists) xmlrpc_faultf( envP, "Xmlrpc-c global client instance has already been created " "(need to call xmlrpc_client_cleanup() before you can " "reinitialize)."); else { /* The following call is not thread-safe */ xmlrpc_client_setup_global_const(envP); if (!envP->fault_occurred) { xmlrpc_client_create(envP, flags, appname, appversion, clientparmsP, parmSize, &globalClientP); if (!envP->fault_occurred) globalClientExists = true; if (envP->fault_occurred) xmlrpc_client_teardown_global_const(); } } }
static void makeCallXml(xmlrpc_env * const envP, const char * const methodName, xmlrpc_value * const paramArrayP, xmlrpc_dialect const dialect, xmlrpc_mem_block ** const callXmlPP) { XMLRPC_ASSERT_VALUE_OK(paramArrayP); XMLRPC_ASSERT_PTR_OK(callXmlPP); if (methodName == NULL) xmlrpc_faultf(envP, "method name argument is NULL pointer"); else { xmlrpc_mem_block * callXmlP; callXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0); if (!envP->fault_occurred) { xmlrpc_serialize_call2(envP, callXmlP, methodName, paramArrayP, dialect); *callXmlPP = callXmlP; if (envP->fault_occurred) XMLRPC_MEMBLOCK_FREE(char, callXmlP); } } }
static void createServerBare(xmlrpc_env * const envP, const xmlrpc_server_abyss_parms * const parmsP, unsigned int const parmSize, TServer * const serverP, TChanSwitch ** const chanSwitchPP) { /*---------------------------------------------------------------------------- Create a bare server. It will need further setup before it is ready to use. -----------------------------------------------------------------------------*/ bool socketBound; const struct sockaddr * sockAddrP; socklen_t sockAddrLen; unsigned int portNumber; TOsSocket socketFd; const char * logFileName; extractServerCreateParms(envP, parmsP, parmSize, &socketBound, &sockAddrP, &sockAddrLen, &portNumber, &socketFd, &logFileName); if (!envP->fault_occurred) { TChanSwitch * chanSwitchP; if (socketBound) createChanSwitchOsSocket(envP, socketFd, &chanSwitchP); else { if (sockAddrP) createChanSwitchSockAddr(envP, sockAddrP, sockAddrLen, &chanSwitchP); else createChanSwitchIpv4Port(envP, portNumber, &chanSwitchP); } if (!envP->fault_occurred) { const char * error; ServerCreateSwitch(serverP, chanSwitchP, &error); if (error) { xmlrpc_faultf(envP, "Abyss failed to create server. %s", error); xmlrpc_strfree(error); } else { *chanSwitchPP = chanSwitchP; ServerSetName(serverP, "XmlRpcServer"); if (logFileName) ServerSetLogFileName(serverP, logFileName); } if (envP->fault_occurred) ChanSwitchDestroy(chanSwitchP); } if (logFileName) xmlrpc_strfree(logFileName); } }
static void validateGlobalClientExists(xmlrpc_env * const envP) { if (!globalClientExists) xmlrpc_faultf(envP, "Xmlrpc-c global client instance " "has not been created " "(need to call xmlrpc_client_init2())."); }
void xmlrpc_read_datetime_8601(xmlrpc_env *const envP, const xmlrpc_value *const valueP, const char **const iso8601ValueP) { /*---------------------------------------------------------------------------- Get the datetime in ISO 8601 format. ISO 8601 allows a variety of representations for each datetime. The particular one we return is as in the following example. 19930214T131030,250000Z (13:10:30.25 on February 14, 1993) There are always 4 digits for the year. There are always 6 digits after the comma (microseconds). Midnight is hour 0, not 24. -----------------------------------------------------------------------------*/ validateDatetimeType(envP, valueP); if (!envP->fault_occurred) { xmlrpc_datetime dt; xmlrpc_read_datetime(envP, valueP, &dt); if (!envP->fault_occurred) { if (dt.Y > 9999) xmlrpc_faultf(envP, "Too far in future (year %u). " "ISO 8601 cannot " "represent years after AD 9999", dt.Y); else { xmlrpc_asprintf(iso8601ValueP, "%04u%02u%02uT%02u%02u%02u,%06uZ", dt.Y, dt.M, dt.D, dt.h, dt.m, dt.s, dt.u); if (xmlrpc_strnomem(*iso8601ValueP)) xmlrpc_faultf(envP, "Unable to allocate memory " "for datetime string"); if (envP->fault_occurred) xmlrpc_strfree(*iso8601ValueP); } } } }
void xmlrpc_server_info_allow_auth_basic(xmlrpc_env * const envP, xmlrpc_server_info * const sP) { if (sP->userNamePw == NULL) xmlrpc_faultf(envP, "You must set username/password with " "xmlrpc_server_info_set_user()"); else sP->allowedAuth.basic = true; }
static void sendResponse(xmlrpc_env * const envP, TSession * const abyssSessionP, const char * const body, size_t const len, bool const chunked, ResponseAccessCtl const accessControl) { /*---------------------------------------------------------------------------- Generate an HTTP response containing body 'body' of length 'len' characters. This is meant to run in the context of an Abyss URI handler for Abyss session 'abyssSessionP'. -----------------------------------------------------------------------------*/ const char * http_cookie = NULL; /* This used to set http_cookie to getenv("HTTP_COOKIE"), but that doesn't make any sense -- environment variables are not appropriate for this. So for now, cookie code is disabled. - Bryan 2004.10.03. */ /* Various bugs before Xmlrpc-c 1.05 caused the response to be not chunked in the most basic case, but chunked if the client explicitly requested keepalive. I think it's better not to chunk, because it's simpler, so I removed this in 1.05. I don't know what the purpose of chunking would be, and an original comment suggests the author wasn't sure chunking was a good idea. In 1.06 we added the user option to chunk. */ if (chunked) ResponseChunked(abyssSessionP); ResponseStatus(abyssSessionP, 200); if (http_cookie) /* There's an auth cookie, so pass it back in the response. */ addAuthCookie(envP, abyssSessionP, http_cookie); if ((size_t)(uint32_t)len != len) xmlrpc_faultf(envP, "XML-RPC method generated a response too " "large for Abyss to send"); else { uint32_t const abyssLen = (uint32_t)len; /* See discussion below of quotes around "utf-8" */ ResponseContentType(abyssSessionP, "text/xml; charset=utf-8"); ResponseContentLength(abyssSessionP, abyssLen); ResponseAccessControl(abyssSessionP, accessControl); ResponseWriteStart(abyssSessionP); ResponseWriteBody(abyssSessionP, body, abyssLen); ResponseWriteEnd(abyssSessionP); } }
static void initAbyss(xmlrpc_env * const envP) { const char * error; AbyssInit(&error); if (error) { xmlrpc_faultf(envP, "Failed to initialize the Abyss library. %s", error); xmlrpc_strfree(error); } }
static void formatOut(xmlrpc_env * const envP, xmlrpc_mem_block * const outputP, const char * const formatString, ...) { /*---------------------------------------------------------------------------- A lightweight print routine for use with various serialization functions. Use this routine only for printing small objects -- it uses a fixed-size internal buffer and returns an error on overflow. In particular, do NOT use this routine to print XML-RPC string values! -----------------------------------------------------------------------------*/ va_list args; char buffer[128]; int rc; XMLRPC_ASSERT_ENV_OK(envP); va_start(args, formatString); rc = XMLRPC_VSNPRINTF(buffer, sizeof(buffer), formatString, args); /* Old vsnprintf() (and Windows) fails with return value -1 if the full string doesn't fit in the buffer. New vsnprintf() puts whatever will fit in the buffer, and returns the length of the full string regardless. For us, this truncation is a failure. */ if (rc < 0) xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); else { unsigned int const formattedLen = rc; if (formattedLen + 1 >= (sizeof(buffer))) xmlrpc_faultf(envP, "formatOut() overflowed internal buffer"); else XMLRPC_MEMBLOCK_APPEND(char, envP, outputP, buffer, formattedLen); } va_end(args); }
static void clientCreate( xmlrpc_env * const envP, bool const myTransport, const struct xmlrpc_client_transport_ops * const transportOpsP, struct xmlrpc_client_transport * const transportP, xmlrpc_dialect const dialect, xmlrpc_progress_fn * const progressFn, xmlrpc_client ** const clientPP) { XMLRPC_ASSERT_PTR_OK(transportOpsP); XMLRPC_ASSERT_PTR_OK(transportP); 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 { xmlrpc_client * clientP; MALLOCVAR(clientP); if (clientP == NULL) xmlrpc_faultf(envP, "Unable to allocate memory for " "client descriptor."); else { clientP->myTransport = myTransport; clientP->transportOps = *transportOpsP; clientP->transportP = transportP; clientP->dialect = dialect; clientP->progressFn = progressFn; *clientPP = clientP; } } }
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); } } } }
static void copyUserNamePw(xmlrpc_env * const envP, const char * const src, const char ** const dstP) { if (src == NULL) *dstP = NULL; else { *dstP = strdup(src); if (*dstP == NULL) xmlrpc_faultf(envP, "Couldn't allocate memory for user name/pw"); } }
static void createWinInetHeaderList(xmlrpc_env * const envP, const xmlrpc_server_info * const serverP, char ** const headerListP) { const char * const szContentType = "Content-Type: text/xml\r\n"; char * szHeaderList; /* Send an authorization header if we need one. */ if (serverP->allowedAuth.basic) { /* Make the header with content type and authorization */ /* NOTE: A newline is required between each added header */ szHeaderList = malloc(strlen(szContentType) + 17 + strlen(serverP->basicAuthHdrValue) + 1); if (szHeaderList == NULL) xmlrpc_faultf(envP, "Couldn't allocate memory for authorization header"); else { memcpy(szHeaderList, szContentType, strlen(szContentType)); memcpy(szHeaderList + strlen(szContentType),"\r\nAuthorization: ", 17); memcpy(szHeaderList + strlen(szContentType) + 17, serverP->basicAuthHdrValue, strlen(serverP->basicAuthHdrValue) + 1); } } else { /* Just the content type header is needed */ szHeaderList = malloc(strlen(szContentType) + 1); if (szHeaderList == NULL) xmlrpc_faultf(envP, "Couldn't allocate memory for standard header"); else memcpy(szHeaderList, szContentType, strlen(szContentType) + 1); } *headerListP = szHeaderList; }
static void addHeader(xmlrpc_env * const envP, struct curl_slist ** const headerListP, const char * const headerText) { struct curl_slist * newHeaderList; newHeaderList = curl_slist_append(*headerListP, headerText); if (newHeaderList == NULL) xmlrpc_faultf(envP, "Could not add header '%s'. " "curl_slist_append() failed.", headerText); else *headerListP = newHeaderList; }