Esempio n. 1
0
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;
}
Esempio n. 3
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_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]);
                }
            }
        }
    }
}
Esempio n. 4
0
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.");
        }
    }
}
Esempio n. 5
0
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;
    }        
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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;
    }
}
Esempio n. 8
0
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.");
}
Esempio n. 9
0
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);
    }
}
Esempio n. 11
0
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);
    }
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
    }
}
Esempio n. 15
0
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;
        }
    }
Esempio n. 16
0
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);
        }
    }
}
Esempio n. 17
0
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();
        }
    }
}
Esempio n. 18
0
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);
        }
    }    
}
Esempio n. 19
0
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);
    }
}
Esempio n. 20
0
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()).");
}
Esempio n. 21
0
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;
}
Esempio n. 23
0
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);
    }
}
Esempio n. 24
0
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);
    }
}
Esempio n. 25
0
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);
}
Esempio n. 26
0
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;
        }
    }
}
Esempio n. 27
0
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;
}
Esempio n. 30
0
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;
}