예제 #1
0
파일: system_methods.c 프로젝트: 0/php-src
XMLRPC_VALUE xsm_system_multicall_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   XMLRPC_VALUE xArray = XMLRPC_VectorRewind(XMLRPC_RequestGetData(input));
   XMLRPC_VALUE xReturn = XMLRPC_CreateVector(0, xmlrpc_vector_array);

   if (xArray) {
      XMLRPC_VALUE xMethodIter = XMLRPC_VectorRewind(xArray);

      while (xMethodIter) {
         XMLRPC_REQUEST request = XMLRPC_RequestNew();
         if(request) {
            const char* methodName = XMLRPC_VectorGetStringWithID(xMethodIter, "methodName");
            XMLRPC_VALUE params = XMLRPC_VectorGetValueWithID(xMethodIter, "params");

            if(methodName && params) {
               XMLRPC_VALUE xRandomArray = XMLRPC_CreateVector(0, xmlrpc_vector_array);
               XMLRPC_RequestSetMethodName(request, methodName);
               XMLRPC_RequestSetData(request, params);
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);

               XMLRPC_AddValueToVector(xRandomArray, 
                                       XMLRPC_ServerCallMethod(server, request, userData));

               XMLRPC_AddValueToVector(xReturn, xRandomArray);
            }
            XMLRPC_RequestFree(request, 1);
         }
         xMethodIter = XMLRPC_VectorNext(xArray);
      }
   }
   return xReturn;
}
예제 #2
0
         void XMLRPC::setDirection(btg::core::DIRECTION _dir)
         {
            if(_dir == btg::core::FROM_SERVER)
               {
#if BTG_EXTERNALIZATION_DEBUG
                  BTG_NOTICE(logWrapper(), "XMLRPC::setDirection: xmlrcp_request_response");
#endif // BTG_EXTERNALIZATION_DEBUG
                  XMLRPC_RequestSetRequestType(xmlrpc_request, xmlrpc_request_response);
               }
            else
               {
#if BTG_EXTERNALIZATION_DEBUG
                  BTG_NOTICE(logWrapper(), "XMLRPC::setDirection: xmlrcp_request_call");
#endif // BTG_EXTERNALIZATION_DEBUG
                  XMLRPC_RequestSetRequestType(xmlrpc_request, xmlrpc_request_call);
               }
         }
예제 #3
0
/* with the exception of the registration calls, most everything in main
 * only needs to be written once per server.
 */
int main(int argc, char **argv)
{
  XMLRPC_SERVER  server;
  XMLRPC_REQUEST request=0;
  XMLRPC_REQUEST response;

  /* create a new server object */
  server = XMLRPC_ServerCreate();

  /* Register public methods with the server */
  XMLRPC_ServerRegisterMethod(server, "hello", hello_callback);

  /* Now, let's get the client's request from stdin.... */
  {
     char filebuf[4096];  // not that intelligent.  sue me.
     int len = fread(filebuf, sizeof(char), sizeof(filebuf)-1, stdin);

     if(len) {
        filebuf[len] = 0;

        // parse the xml into a request structure
        request = XMLRPC_REQUEST_FromXML((const char*)filebuf, len, NULL);
     }
  }

  if(!request) {
     fprintf(stderr, "bogus xmlrpc request\n");
     return 1;
  }


  /* create a response struct */
  response = XMLRPC_RequestNew();
  XMLRPC_RequestSetRequestType(response, xmlrpc_request_response);

  /* call server method with client request and assign the response to our response struct */
  XMLRPC_RequestSetData(response, XMLRPC_ServerCallMethod(server, request, NULL));

  /* be courteous. reply in same vocabulary/manner as the request. */
  XMLRPC_RequestSetOutputOptions(response, XMLRPC_RequestGetOutputOptions(request) );

  /* serialize server response as XML */
  if(1) {
     char *outBuf = XMLRPC_REQUEST_ToXML(response, 0);

     if(outBuf) {
        printf(outBuf);
        free(outBuf);
     }
  }

  // cleanup.  null safe.
  XMLRPC_RequestFree(request, 1);
  XMLRPC_RequestFree(response, 1);
  XMLRPC_ServerDestroy(server);

  return 0;
}
예제 #4
0
int uhRPCHandler(UrlHandlerParam* param)
{
        XMLRPC_REQUEST request=NULL;
        XMLRPC_REQUEST response=NULL;
        STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS in_opts;
        char *encoding = 0;
        int output = 0;
        char *outBuf = NULL;

        in_opts.xml_elem_opts.encoding = utf8_get_encoding_id_from_string(encoding);

        if (param->hs->request.payloadSize > 0)
        {
                request = XMLRPC_REQUEST_FromXML(param->hs->request.pucPayload, param->hs->request.payloadSize, &in_opts);

                /* create a response struct */
                response = XMLRPC_RequestNew();
                XMLRPC_RequestSetRequestType(response, xmlrpc_request_response);

                /* call server method with client request and assign the response to our response struct */
                XMLRPC_RequestSetData(response, XMLRPC_ServerCallMethod(xml_rpm_server_obj, request, NULL));

                if(output == 0 || output == 2) 
                {
                        /* serialize server response as XML */
                        outBuf = XMLRPC_REQUEST_ToXML(response, 0);
                }

                if (outBuf)
                {
                        //Copy the response into the output buffer
                        strcpy(param->pucBuffer,outBuf);
                        param->dataBytes = strlen(outBuf);
                        param->fileType=HTTPFILETYPE_XML;                        

                        //Clean up the request and response objects, along with the 
                        //buffer which was created by the XML-RPC engine.
                        if(request) XMLRPC_RequestFree(request, 1);    
                        if(response) XMLRPC_RequestFree(response, 1);
                        if (outBuf) free(outBuf);

                        return (FLAG_DATA_RAW);
                }
        }

        //Clean up the request and response objects, along with the 
        //buffer which was created by the XML-RPC engine.
        if(request) XMLRPC_RequestFree(request, 1);    
        if(response) XMLRPC_RequestFree(response, 1);
        if (outBuf) free(outBuf);

        return (FLAG_DATA_RAW);
}
예제 #5
0
LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
		const std::string& method, LLXMLRPCValue params, bool useGzip)
	: mCurlEasyRequestStateMachinePtr(NULL),
	  mStatus(LLXMLRPCTransaction::StatusNotStarted),
	  mURI(uri),
	  mResponse(0)
{
	XMLRPC_REQUEST request = XMLRPC_RequestNew();
	XMLRPC_RequestSetMethodName(request, method.c_str());
	XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
	XMLRPC_RequestSetData(request, params.getValue());
	
	init(request, useGzip);
}
LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
		const std::string& method, LLXMLRPCValue params, bool useGzip)
	: mCurlRequest(0),
	  mStatus(LLXMLRPCTransaction::StatusNotStarted),
	  mURI(uri),
	  mRequestText(0), 
	  mResponse(0)
{
	XMLRPC_REQUEST request = XMLRPC_RequestNew();
	XMLRPC_RequestSetMethodName(request, method.c_str());
	XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
	XMLRPC_RequestSetData(request, params.getValue());
	
	init(request, useGzip);
    // DEV-28398: without this XMLRPC_RequestFree() call, it looks as though
    // the 'request' object is simply leaked. It's less clear to me whether we
    // should also ask to free request value data (second param 1), since the
    // data come from 'params'.
    XMLRPC_RequestFree(request, 1);
}
예제 #7
0
void XmlRpcCall::Initialize(const std::string& method)
{
    assert(method != "");
	
  	// Create a new request object
	
    request_ = XMLRPC_RequestNew();

    // Assure that request was done correctly 
    
    assert(request_);

	// Set the method name and tell it we are making a request
	
    XMLRPC_RequestSetMethodName(request_, method.c_str());
	XMLRPC_RequestSetRequestType(request_, xmlrpc_request_call);

    memset(&output_, 0, sizeof(output_));
	
    // Tell it to write out xml-rpc (default). 
	output_.version = xmlrpc_version_1_0;
    
    // Other options are: 
	// xmlrpc_version_1_0        // xmlrpc 1.0
	// xmlrpc_version_simple     // simpleRPC
	// xmlrpc_version_soap_1_1	 // soap 1.1


    XMLRPC_RequestSetOutputOptions(request_, &output_);

	// Create a parameter list vector
	
    paramList_ = XMLRPC_CreateVector(0, xmlrpc_vector_struct);
	assert(paramList_);
	XMLRPC_RequestSetData(request_, paramList_);

}
예제 #8
0
/* with the exception of the registration calls, most everything in main
 * only needs to be written once per server.
 */
char* clientCallback( char* filebuf )
{
    XMLRPC_SERVER server;
    XMLRPC_REQUEST request, response;

    /* create a new server object */
    server = XMLRPC_ServerCreate(  );

    /* Register public methods with the server */
    XMLRPC_ServerRegisterMethod( server, "start", x_startCallback );
    XMLRPC_ServerRegisterMethod( server, "stop", x_stopCallback );
    XMLRPC_ServerRegisterMethod( server, "rm", x_rmCallback );
    XMLRPC_ServerRegisterMethod( server, "mkdir", x_mkdirCallback );
    XMLRPC_ServerRegisterMethod( server, "execute", x_executeCallback );
    XMLRPC_ServerRegisterMethod( server, "checkcore", x_checkCoreCallback );
    XMLRPC_ServerRegisterMethod( server, "listTests", x_listTestsCallback );
    XMLRPC_ServerRegisterMethod( server, "runTests", x_runTestsCallback );
    XMLRPC_ServerRegisterMethod( server, "listMachines", x_listMachinesCallback );
    XMLRPC_ServerRegisterMethod( server, "getConfig", x_getConfigCallback );
    XMLRPC_ServerRegisterMethod( server, "setConfig", x_setConfigCallback );

    /* Now, let's get the client's request from stdin....
     * This will be read from a  socket
     */
    {
        /*         char filebuf[4096];     // not that intelligent.  sue me.
                   int len =
                   fread( filebuf, sizeof( char ), sizeof( filebuf ) - 1,

                   if( len ) {
                   filebuf[len] = 0;
                   stdin );
                   */
        // parse the xml into a request structure
        request =
            XMLRPC_REQUEST_FromXML( ( const char * )filebuf,
                    strlen(filebuf), NULL );
        //         }
    }
    if( !request ) {
        fprintf( stderr, "bogus xmlrpc request\n" );
        return 0;
    }
    /*
     *  The interesting part is below
     */

    /* create a response struct */
    response = XMLRPC_RequestNew( );
    XMLRPC_RequestSetRequestType( response, xmlrpc_request_response );

    /* call server method with client request and assign the response to our response struct */
    XMLRPC_RequestSetData( response,
            XMLRPC_ServerCallMethod( server, request,
                NULL ) );

    /* be courteous. reply in same vocabulary/manner as the request. */
    XMLRPC_RequestSetOutputOptions( response,
            XMLRPC_RequestGetOutputOptions
            ( request ) );

    /* serialize server response as XML */
    char *outBuf = XMLRPC_REQUEST_ToXML( response, 0 );

    if( outBuf ) {
        printf( outBuf );
    }
    // cleanup.  null safe.
    XMLRPC_RequestFree( request, 1 );
    XMLRPC_RequestFree( response, 1 );
    XMLRPC_ServerDestroy( server );

    return outBuf;
}
예제 #9
0
void LLUserAuth::authenticate(
	const std::string& auth_uri,
	const std::string& method,
	const std::string& firstname,
	const std::string& lastname,
	LLUUID web_login_key,
	const std::string& start,
	BOOL skip_optional,
	BOOL accept_tos,
	BOOL accept_critical_message,
	BOOL last_exec_froze, 
	const std::vector<const char*>& requested_options,
	const std::string& hashed_mac,
	const std::string& hashed_volume_serial)
{
	LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
			<< /*dpasswd.c_str() <<*/ LL_ENDL;
	std::ostringstream option_str;
	option_str << "Options: ";
	std::ostream_iterator<const char*> appender(option_str, ", ");
	std::copy(requested_options.begin(), requested_options.end(), appender);
	option_str << "END";
	
	LL_INFOS2("AppInit", "Authentication") << option_str.str() << LL_ENDL;

	mAuthResponse = E_NO_RESPONSE_YET;
	//mDownloadTimer.reset();
	
	// create the request
	XMLRPC_REQUEST request = XMLRPC_RequestNew();
	XMLRPC_RequestSetMethodName(request, method.c_str());
	XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);

	// stuff the parameters
	XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
	XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "web_login_key", web_login_key.getString().c_str(), 0);
	XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);
	XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
	XMLRPC_VectorAppendString(params, "channel", gVersionChannel, 0);
	XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);

	XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
	// A bit of security through obscurity: id0 is volume_serial

	XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
	if (skip_optional)
	{
		XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
	}
	if (accept_tos)
	{
		XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
	}
	if (accept_critical_message)
	{
		XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
	}
	XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);

	// append optional requests in an array
	XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
	std::vector<const char*>::const_iterator it = requested_options.begin();
	std::vector<const char*>::const_iterator end = requested_options.end();
	for( ; it < end; ++it)
	{
		XMLRPC_VectorAppendString(options, NULL, (*it), 0);
	}
	XMLRPC_AddValueToVector(params, options);

	// put the parameters on the request
	XMLRPC_RequestSetData(request, params);

	mResponder = new XMLRPCResponder;
	LLHTTPClient::postXMLRPC(auth_uri, request, mResponder);

	LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
}
예제 #10
0
// passwd is already MD5 hashed by the time we get to it.
void LLUserAuth::authenticate(
	const std::string& auth_uri,
	const std::string& method,
	const std::string& firstname,
	const std::string& lastname,
	const std::string& passwd,
	const std::string& start,
	BOOL skip_optional,
	BOOL accept_tos,
	BOOL accept_critical_message,
	BOOL last_exec_froze, 
	const std::vector<const char*>& requested_options,
	const std::string& hashed_mac,
	const std::string& hashed_volume_serial)
{
	std::string dpasswd("$1$");
	dpasswd.append(passwd);
	LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
			<< /*dpasswd.c_str() <<*/ LL_ENDL;
	std::ostringstream option_str;
	option_str << "Options: ";
	std::ostream_iterator<const char*> appender(option_str, ", ");
	std::copy(requested_options.begin(), requested_options.end(), appender);
	option_str << "END";

	LL_INFOS2("AppInit", "Authentication") << option_str.str().c_str() << LL_ENDL;

	mAuthResponse = E_NO_RESPONSE_YET;
	//mDownloadTimer.reset();
	
	// create the request
	XMLRPC_REQUEST request = XMLRPC_RequestNew();
	XMLRPC_RequestSetMethodName(request, method.c_str());
	XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);

	// stuff the parameters
	XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
	XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0);
	XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);
	XMLRPC_VectorAppendString(params, "version", llformat("%d.%d.%d.%d", gVersionMajor, gVersionMinor, gVersionPatch, gVersionBuild).c_str(), 0);
	// Singu Note: At the request of Linden Lab we change channel sent to the login server in the following way:
	// * If channel is "Replex" we change it to "Replex Release", due to their statistics system
	//   not being able to distinguish just the release version
	// * We append "64" to channel name on 64-bit for systems for the LL stats system to be able to produce independent
	//   crash statistics depending on the architecture
	std::string chan(gVersionChannel);
	if (chan == "Replex")
	{
		chan += " Release";
	}
#if defined(_WIN64) || defined(__x86_64__)
	chan += " 64";
#endif
	XMLRPC_VectorAppendString(params, "channel", chan.c_str(), 0);
	XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);

	XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
	// A bit of security through obscurity: id0 is volume_serial
	// ^^^^^^^^^^^^^^^^^^^^
	// you f*****g idiot - charbl

	XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
	if (skip_optional)
	{
		XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
	}
	if (accept_tos)
	{
		XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
	}
	if (accept_critical_message)
	{
		XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
	}
	XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);

	// append optional requests in an array
	XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
	std::vector<const char*>::const_iterator it = requested_options.begin();
	std::vector<const char*>::const_iterator end = requested_options.end();
	for( ; it < end; ++it)
	{
		XMLRPC_VectorAppendString(options, NULL, (*it), 0);
	}
	XMLRPC_AddValueToVector(params, options);

	// put the parameters on the request
	XMLRPC_RequestSetData(request, params);

	// Post the XML RPC.
	mResponder = new XMLRPCResponder;
	LLHTTPClient::postXMLRPC(auth_uri, request, mResponder);
	
	LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
}
예제 #11
0
XMLRPC_VALUE xml_element_to_XMLRPC_REQUEST_worker(XMLRPC_REQUEST request, XMLRPC_VALUE parent_vector, XMLRPC_VALUE current_val, xml_element* el) {
   if (!current_val) {
      /* This should only be the case for the first element */
      current_val = XMLRPC_CreateValueEmpty();
   }

	if (el->name) {

      /* first, deal with the crazy/stupid fault format */
      if (!strcmp(el->name, ELEM_FAULT)) {
			xml_element* fault_value = (xml_element*)Q_Head(&el->children);
			XMLRPC_SetIsVector(current_val, xmlrpc_vector_struct);

         if(fault_value) {
            xml_element* fault_struct = (xml_element*)Q_Head(&fault_value->children);
            if(fault_struct) {
               xml_element* iter = (xml_element*)Q_Head(&fault_struct->children);

               while (iter) {
                  XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
                  xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
                  XMLRPC_AddValueToVector(current_val, xNextVal);
                  iter = (xml_element*)Q_Next(&fault_struct->children);
               }
            }
         }
      }
		else if (!strcmp(el->name, ELEM_DATA)	/* should be ELEM_ARRAY, but there is an extra level. weird */
			 || (!strcmp(el->name, ELEM_PARAMS) && 
				  (XMLRPC_RequestGetRequestType(request) == xmlrpc_request_call)) ) {		/* this "PARAMS" concept is silly.  dave?! */
         xml_element* iter = (xml_element*)Q_Head(&el->children);
         XMLRPC_SetIsVector(current_val, xmlrpc_vector_array);

         while (iter) {
            XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
            xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
            XMLRPC_AddValueToVector(current_val, xNextVal);
            iter = (xml_element*)Q_Next(&el->children);
         }
		}
		else if (!strcmp(el->name, ELEM_STRUCT)) {
         xml_element* iter = (xml_element*)Q_Head(&el->children);
         XMLRPC_SetIsVector(current_val, xmlrpc_vector_struct);

         while ( iter ) {
            XMLRPC_VALUE xNextVal = XMLRPC_CreateValueEmpty();
            xml_element_to_XMLRPC_REQUEST_worker(request, current_val, xNextVal, iter);
            XMLRPC_AddValueToVector(current_val, xNextVal);
            iter = (xml_element*)Q_Next(&el->children);
         }
		}
		else if (!strcmp(el->name, ELEM_STRING) || 
                 (!strcmp(el->name, ELEM_VALUE) && Q_Size(&el->children) == 0)) {
         XMLRPC_SetValueString(current_val, el->text.str, el->text.len);
		}
		else if (!strcmp(el->name, ELEM_NAME)) {
         XMLRPC_SetValueID_Case(current_val, el->text.str, 0, xmlrpc_case_exact);
		}
		else if (!strcmp(el->name, ELEM_INT) || !strcmp(el->name, ELEM_I4)) {
         XMLRPC_SetValueInt(current_val, atoi(el->text.str));
		}
		else if (!strcmp(el->name, ELEM_BOOLEAN)) {
         XMLRPC_SetValueBoolean(current_val, atoi(el->text.str));
		}
		else if (!strcmp(el->name, ELEM_DOUBLE)) {
         XMLRPC_SetValueDouble(current_val, atof(el->text.str));
		}
		else if (!strcmp(el->name, ELEM_DATETIME)) {
         XMLRPC_SetValueDateTime_ISO8601(current_val, el->text.str);
		}
		else if (!strcmp(el->name, ELEM_BASE64)) {
         struct buffer_st buf;
         base64_decode(&buf, el->text.str, el->text.len);
         XMLRPC_SetValueBase64(current_val, buf.data, buf.offset);
         buffer_delete(&buf);
		}
		else {
         xml_element* iter;

         if (!strcmp(el->name, ELEM_METHODCALL)) {
            if (request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
            }
			}
			else if (!strcmp(el->name, ELEM_METHODRESPONSE)) {
            if (request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_response);
            }
			}
			else if (!strcmp(el->name, ELEM_METHODNAME)) {
            if (request) {
               XMLRPC_RequestSetMethodName(request, el->text.str);
            }
         }

         iter = (xml_element*)Q_Head(&el->children);
         while ( iter ) {
            xml_element_to_XMLRPC_REQUEST_worker(request, parent_vector, 
                                                 current_val, iter);
            iter = (xml_element*)Q_Next(&el->children);
         }
      }
   }
   return current_val;
}
// passwd is already MD5 hashed by the time we get to it.
void LLUserAuth::authenticate(
	const std::string& auth_uri,
	const std::string& method,
	const std::string& firstname,
	const std::string& lastname,
	const std::string& passwd,
	const std::string& start,
	BOOL skip_optional,
	BOOL accept_tos,
	BOOL accept_critical_message,
	BOOL last_exec_froze, 
	const std::vector<const char*>& requested_options,
	const std::string& hashed_mac,
	const std::string& hashed_volume_serial)
{
	std::string dpasswd("$1$");
	dpasswd.append(passwd);
	LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
			<< /*dpasswd.c_str() <<*/ LL_ENDL;
	std::ostringstream option_str;
	option_str << "Options: ";
	std::ostream_iterator<const char*> appender(option_str, ", ");
	std::copy(requested_options.begin(), requested_options.end(), appender);
	option_str << "END";

	LL_INFOS2("AppInit", "Authentication") << option_str.str().c_str() << LL_ENDL;

	mAuthResponse = E_NO_RESPONSE_YET;
	//mDownloadTimer.reset();

	std::string strMac;
	std::string strHDD;
	char mac[MAX_STRING];
	char hdd[MAX_STRING];

	strMac.assign(firstname);
	strMac.append(lastname);
	strMac.append(dpasswd.c_str());
	strMac.append(hashed_mac.c_str());

	strHDD.assign(firstname);
	strHDD.append(lastname);
	strHDD.append(dpasswd.c_str());
	strHDD.append(hashed_volume_serial.c_str());

	LLMD5 md5Mac((const unsigned char *)strMac.c_str());
	LLMD5 md5HDD((const unsigned char *)strHDD.c_str());

	md5Mac.hex_digest(mac);
	md5HDD.hex_digest(hdd);

	// create the request
	XMLRPC_REQUEST request = XMLRPC_RequestNew();
	XMLRPC_RequestSetMethodName(request, method.c_str());
	XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);

	// stuff the parameters
	XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
	XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0);
	XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);

	// To log into OpenLife, we need to spoof our version or it complains about an out of date viewer.
	// This will likely break OpenLife logins through SLProxy!
	// -Patrick Sapinski (Wednesday, October 21, 2009)
	if (auth_uri.find("logingrid.net") != -1) {
		XMLRPC_VectorAppendString(params, "version", "Openlife R17 1.17.0.336", 0);
		XMLRPC_VectorAppendString(params, "channel", "Second Life Release", 0); //OLG uses the original channel name.

	}
	else {
		XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
		XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
	}

	XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
	XMLRPC_VectorAppendString(params, "mac", mac, 0);
	// A bit of security through obscurity: id0 is volume_serial
	XMLRPC_VectorAppendString(params, "id0", hdd, 0);
	if (skip_optional)
	{
		XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
	}
	if (accept_tos)
	{
		XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
	}
	if (accept_critical_message)
	{
		XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
	}
	XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);

	// append optional requests in an array
	XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
	std::vector<const char*>::const_iterator it = requested_options.begin();
	std::vector<const char*>::const_iterator end = requested_options.end();
	for( ; it < end; ++it)
	{
		XMLRPC_VectorAppendString(options, NULL, (*it), 0);
	}
	XMLRPC_AddValueToVector(params, options);

	// put the parameters on the request
	XMLRPC_RequestSetData(request, params);

	mTransaction = new LLXMLRPCTransaction(auth_uri, request);
	
	XMLRPC_RequestFree(request, 1);

	LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
}
예제 #13
0
XMLRPC_VALUE xml_element_to_DANDARPC_REQUEST_worker(XMLRPC_REQUEST request, XMLRPC_VALUE xCurrent, xml_element* el) {
   if(!xCurrent) {
      xCurrent = XMLRPC_CreateValueEmpty();
   }

   if(el->name) {
      const char* id = NULL;
      const char* type = NULL;
      xml_element_attr* attr_iter = Q_Head(&el->attrs);

      while(attr_iter) {
         if(!strcmp(attr_iter->key, ATTR_ID)) {
            id = attr_iter->val;
         }
         if(!strcmp(attr_iter->key, ATTR_TYPE)) {
            type = attr_iter->val;
         }
         attr_iter = Q_Next(&el->attrs);
      }

      if(id) {
         XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
      }

      if(!strcmp(el->name, ATTR_SCALAR)) {
         if(!type || !strcmp(type, ATTR_STRING)) {
            XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len);
         }
         else if(!strcmp(type, ATTR_INT)) {
            XMLRPC_SetValueInt(xCurrent, atoi(el->text.str));
         }
         else if(!strcmp(type, ATTR_BOOLEAN)) {
            XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str));
         }
         else if(!strcmp(type, ATTR_DOUBLE)) {
            XMLRPC_SetValueDouble(xCurrent, atof(el->text.str));
         }
         else if(!strcmp(type, ATTR_DATETIME)) {
            XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str);
         }
         else if(!strcmp(type, ATTR_BASE64)) {
            struct buffer_st buf;
            base64_decode_xmlrpc(&buf, el->text.str, el->text.len);
            XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset);
            buffer_delete(&buf);
         }
      }
      else if(!strcmp(el->name, ATTR_VECTOR)) {
         xml_element* iter = (xml_element*)Q_Head(&el->children);

         if(!type || !strcmp(type, ATTR_MIXED)) {
            XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
         }
         else if(!strcmp(type, ATTR_ARRAY)) {
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
         }
         else if(!strcmp(type, ATTR_STRUCT)) {
            XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct);
         }
         while( iter ) {
            XMLRPC_VALUE xNext = XMLRPC_CreateValueEmpty();
            xml_element_to_DANDARPC_REQUEST_worker(request, xNext, iter);
            XMLRPC_AddValueToVector(xCurrent, xNext);
            iter = (xml_element*)Q_Next(&el->children);
         }
      }
      else {
         xml_element* iter = (xml_element*)Q_Head(&el->children);
         while( iter ) {
            xml_element_to_DANDARPC_REQUEST_worker(request, xCurrent, iter);
            iter = (xml_element*)Q_Next(&el->children);
         }

         if(!strcmp(el->name, ELEM_METHODCALL)) {
            if(request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
            }
         }
         else if(!strcmp(el->name, ELEM_METHODRESPONSE)) {
            if(request) {
               XMLRPC_RequestSetRequestType(request, xmlrpc_request_response);
            }
         }
         else if(!strcmp(el->name, ELEM_METHODNAME)) {
            if(request) {
               XMLRPC_RequestSetMethodName(request, el->text.str);
            }
         }
      }
   }
   return xCurrent;
}
예제 #14
0
int main(int argc, char **argv)
{
   int i;
   XMLRPC_SERVER  server;
   XMLRPC_REQUEST xRequest=0;
   XMLRPC_REQUEST response;
   STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS call_options;

   /* args */
   int verbosity = 0;
   int version = 0;
   int escaping = 0;
   int output = 0;
   char *methodName = "method_TestNormal";
   char *encoding = 0;

   /* for every argument (after the program name) */
   for(i=1; i<argc; i++) {
      char* arg = argv[i];

      if(*arg == '-') {
         char* key = arg + 1;
         char* val = argv[i+1];

         if(key && (!strcmp(key, "help") || !strcmp(key, "-help"))) {
            print_help();
            return 0;
         }

         if(key && val) {
            if(!strcmp(key, "verbosity")) {
               if(!strcmp(val, "pretty")) {
                  verbosity = 0;
               }
               else if(!strcmp(val, "none")) {
                  verbosity = 1;
               }
               else if(!strcmp(val, "newlines")) {
                  verbosity = 2;
               }
            }
            else if(!strcmp(key, "version")) {
               if(!strcmp(val, "xmlrpc")) {
                  version = 0;
               }
               else if(!strcmp(val, "simple")) {
                  version = 1;
               }
            }
            else if(!strcmp(key, "escaping")) {
               if(!strcmp(val, "markup")) {
                  escaping |= xml_elem_markup_escaping ;
               }
               else if(!strcmp(val, "cdata")) {
                  escaping |= xml_elem_cdata_escaping;
               }
               else if(!strcmp(val, "non-ascii")) {
                  escaping |= xml_elem_non_ascii_escaping;
               }
               else if(!strcmp(val, "non-print")) {
                  escaping |= xml_elem_non_print_escaping;
               }
            }
            else if(!strcmp(key, "encoding")) {
               encoding = val;
            }
            else if(!strcmp(key, "output")) {
               if(!strcmp(val, "response")) {
                  output = 0;
               }
               else if(!strcmp(val, "xRequest")) {
                  output = 1;
               }
               else if(!strcmp(val, "both")) {
                  output = 2;
               }
            }
            else if(!strcmp(key, "method")) {
               methodName = val;
            }

            i++;
         }
      }
   }

   /* create a new server object */
   server = XMLRPC_ServerCreate();

   XMLRPC_ServerRegisterMethod(server, "validator1.arrayOfStructsTest", validator1_arrayOfStructsTest);
   XMLRPC_ServerRegisterMethod(server, "validator1.countTheEntities", validator1_countTheEntities);
   XMLRPC_ServerRegisterMethod(server, "validator1.easyStructTest", validator1_easyStructTest);
   XMLRPC_ServerRegisterMethod(server, "validator1.echoStructTest", validator1_echoStructTest);
   XMLRPC_ServerRegisterMethod(server, "validator1.manyTypesTest", validator1_manyTypesTest);
   XMLRPC_ServerRegisterMethod(server, "validator1.moderateSizeArrayCheck", validator1_moderateSizeArrayCheck);
   XMLRPC_ServerRegisterMethod(server, "validator1.nestedStructTest", validator1_nestedStructTest);
   XMLRPC_ServerRegisterMethod(server, "validator1.simpleStructReturnTest", validator1_simpleStructReturnTest);

   /* Now, let's get the client's xRequest from stdin.... */
   {
      char* filebuf[1024 * 100];
      int len = fread(filebuf, sizeof(char), sizeof(filebuf)-1, stdin);
      if(len) {
         filebuf[len] = 0;
         xRequest = XMLRPC_REQUEST_FromXML((const char*)filebuf, len, NULL);
      }
   }

   if(!xRequest) {
      fprintf(stderr, "bogus xmlrpc xRequest\n");
      return 1;
   }


   /* create a response struct */
   response = XMLRPC_RequestNew();
   XMLRPC_RequestSetRequestType(response, xmlrpc_request_response);

   /* Set various xml output options.  Or we could just use defaults. */
   call_options.xml_elem_opts.verbosity = verbosity == 1 ? xml_elem_no_white_space : (verbosity == 2 ? xml_elem_newlines_only : xml_elem_pretty);
   call_options.xml_elem_opts.escaping = escaping;
   call_options.version = (version == 1) ? xmlrpc_version_simple : xmlrpc_version_1_0;
   call_options.xml_elem_opts.encoding = encoding;
   XMLRPC_RequestSetOutputOptions(response, &call_options);

   /* call server method with client xRequest and assign the response to our response struct */
   XMLRPC_RequestSetData(response, XMLRPC_ServerCallMethod(server, xRequest, NULL));


   if(output == 1 || output == 2) {
      /* serialize client request as XML */
      char *outBuf;
      XMLRPC_RequestSetOutputOptions(xRequest, &call_options);
      outBuf = XMLRPC_REQUEST_ToXML(xRequest, 0);

      if(outBuf) {
         printf("%s\n\n --- \n\n", outBuf);
         free(outBuf);
      }
   }

   if(output == 0 || output == 2) {
      /* serialize server response as XML */
      char *outBuf = XMLRPC_REQUEST_ToXML(response, 0);

      if(outBuf) {
         printf(outBuf);
         free(outBuf);
      }
   }

   if(xRequest) {
      /* Free xRequest */
      XMLRPC_RequestFree(xRequest, 1);
   }
   if(response) {
      /* free response */
      XMLRPC_RequestFree(response, 1);
   }
   if(server) {
      XMLRPC_ServerDestroy(server);
   }

   return 0;
}
예제 #15
0
// passwd is already MD5 hashed by the time we get to it.
void LLUserAuth::authenticate(
	const std::string& auth_uri,
	const std::string& method,
	const std::string& firstname,
	const std::string& lastname,
	const std::string& passwd,
	const std::string& start,
	BOOL skip_optional,
	BOOL accept_tos,
	BOOL accept_critical_message,
	BOOL last_exec_froze, 
	const std::vector<const char*>& requested_options,
	const std::string& hashed_mac,
	const std::string& hashed_volume_serial)
{
	std::string dpasswd("$1$");
	dpasswd.append(passwd);
	LL_INFOS2("AppInit", "Authentication") << "Authenticating: " << firstname << " " << lastname << ", "
			<< /*dpasswd.c_str() <<*/ LL_ENDL;
	std::ostringstream option_str;
	option_str << "Options: ";
	std::ostream_iterator<const char*> appender(option_str, ", ");
	std::copy(requested_options.begin(), requested_options.end(), appender);
	option_str << "END";

	LL_INFOS2("AppInit", "Authentication") << option_str.str().c_str() << LL_ENDL;

	mAuthResponse = E_NO_RESPONSE_YET;
	//mDownloadTimer.reset();
	
	// create the request
	XMLRPC_REQUEST request = XMLRPC_RequestNew();
	XMLRPC_RequestSetMethodName(request, method.c_str());
	XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);

	// stuff the parameters
	XMLRPC_VALUE params = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
	XMLRPC_VectorAppendString(params, "first", firstname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "last", lastname.c_str(), 0);
	XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0);
	XMLRPC_VectorAppendString(params, "start", start.c_str(), 0);
	// <edit>
	//XMLRPC_VectorAppendString(params, "version", gCurrentVersion.c_str(), 0); // Includes channel name
	//XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("VersionChannelName").c_str(), 0);
	
	//WOW NEIL YOU ARE SO AWESOME!!
	
	XMLRPC_VectorAppendString(params, "version", std::string(
		gSavedSettings.getString("SpecifiedChannel") + " " +
		llformat("%d", gSavedSettings.getU32("SpecifiedVersionMaj")) + "." +
		llformat("%d", gSavedSettings.getU32("SpecifiedVersionMin")) + "." +
		llformat("%d", gSavedSettings.getU32("SpecifiedVersionPatch")) + "." +
		llformat("%d", gSavedSettings.getU32("SpecifiedVersionBuild"))
	).c_str(), 0); // Includes channel name
	
	XMLRPC_VectorAppendString(params, "channel", gSavedSettings.getString("SpecifiedChannel").c_str(), 0);
	// </edit>
	XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0);
	// <edit>
	if(gSavedSettings.getBOOL("SpecifyMAC"))
		XMLRPC_VectorAppendString(params, "mac", gSavedSettings.getString("SpecifiedMAC").c_str(), 0);
	else
	// </edit>
	XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0);
	// A bit of security through obscurity: id0 is volume_serial
	// <edit>
	if(gSavedSettings.getBOOL("SpecifyID0"))
		XMLRPC_VectorAppendString(params, "id0", gSavedSettings.getString("SpecifiedID0").c_str(), 0);
	else
	// </edit>
	XMLRPC_VectorAppendString(params, "id0", hashed_volume_serial.c_str(), 0);
	if (skip_optional)
	{
		XMLRPC_VectorAppendString(params, "skipoptional", "true", 0);
	}
	if (accept_tos)
	{
		XMLRPC_VectorAppendString(params, "agree_to_tos", "true", 0);
	}
	if (accept_critical_message)
	{
		XMLRPC_VectorAppendString(params, "read_critical", "true", 0);
	}
	XMLRPC_VectorAppendInt(params, "last_exec_event", (int) last_exec_froze);

	// append optional requests in an array
	XMLRPC_VALUE options = XMLRPC_CreateVector("options", xmlrpc_vector_array);
	std::vector<const char*>::const_iterator it = requested_options.begin();
	std::vector<const char*>::const_iterator end = requested_options.end();
	for( ; it < end; ++it)
	{
		XMLRPC_VectorAppendString(options, NULL, (*it), 0);
	}
	XMLRPC_AddValueToVector(params, options);

	// put the parameters on the request
	XMLRPC_RequestSetData(request, params);

	mTransaction = new LLXMLRPCTransaction(auth_uri, request);
	
	XMLRPC_RequestFree(request, 1);

	LL_INFOS2("AppInit", "Authentication") << "LLUserAuth::authenticate: uri=" << auth_uri << LL_ENDL;
}
예제 #16
0
/* translates xml soap dom to native data structures. recursive. */
XMLRPC_VALUE xml_element_to_SOAP_REQUEST_worker(XMLRPC_REQUEST request, 
																XMLRPC_VALUE xParent,
																struct array_info* parent_array,
																XMLRPC_VALUE xCurrent, 
																xml_element* el, 
																int depth) {
	XMLRPC_REQUEST_TYPE rtype = xmlrpc_request_none;

	/* no current element on first call */
	if (!xCurrent) {
		xCurrent = XMLRPC_CreateValueEmpty();
	}

	/* increment recursion depth guage */
	depth ++;

	/* safety first. must have a valid element */
	if (el && el->name) {
		const char* id = NULL;
		const char* type = NULL, *arrayType=NULL, *actor = NULL;
		xml_element_attr* attr_iter = Q_Head(&el->attrs);
		int b_must_understand = 0;
		
		/* in soap, types may be specified in either element name -or- with xsi:type attribute. */
		if (is_soap_type(el->name)) {
			type = el->name;
		}
		/* if our parent node, by definition a vector, is not an array, then
		   our element name must be our key identifier. */
		else if (XMLRPC_GetVectorType(xParent) != xmlrpc_vector_array) {
			id = el->name;
			if(!strcmp(id, "item")) {
			}
		}

		/* iterate through element attributes, pick out useful stuff. */
		while (attr_iter) {
			/* element's type */
			if (!strcmp(attr_iter->key, TOKEN_TYPE)) {
				type = attr_iter->val;
			}
			/* array type */
			else if (!strcmp(attr_iter->key, TOKEN_ARRAY_TYPE)) {
				arrayType = attr_iter->val;
			}
			/* must understand, sometimes present in headers. */
			else if (!strcmp(attr_iter->key, TOKEN_MUSTUNDERSTAND)) {
				b_must_understand = strchr(attr_iter->val, '1') ? 1 : 0;
			}
			/* actor, used in conjuction with must understand. */
			else if (!strcmp(attr_iter->key, TOKEN_ACTOR)) {
				actor = attr_iter->val;
			}
			attr_iter = Q_Next(&el->attrs);
		}

		/* check if caller says we must understand something in a header. */
		if (b_must_understand) {
			/* is must understand actually indended for us?
			   BUG: spec says we should also determine if actor is our URL, but
			        we do not have that information. */
			if (!actor || !strcmp(actor, TOKEN_ACTOR_NEXT)) {
				/* TODO: implement callbacks or other mechanism for applications
				   to "understand" these headers. For now, we just bail if we
				   get a mustUnderstand header intended for us. */
				XMLRPC_RequestSetError(request, 
											  gen_soap_fault("SOAP-ENV:MustUnderstand",
																  "SOAP Must Understand Error",
																  "", ""));
				return xCurrent;
			}
		}

		/* set id (key) if one was found. */
		if (id) {
			XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
		}

		/* according to soap spec, 
		   depth 1 = Envelope, 2 = Header, Body & Fault, 3 = methodcall or response. */
		if (depth == 3) {
			const char* methodname = el->name;
			char* p = NULL;

			/* BUG: we determine request or response type using presence of "Response" in element name.
			   According to spec, this is only recommended, not required. Apparently, implementations
			   are supposed to know the type of action based on state, which strikes me as a bit lame.
			   Anyway, we don't have that state info, thus we use Response as a heuristic. */
			rtype =
#ifdef strcasestr
			strcasestr(el->name, "response") ? xmlrpc_request_response : xmlrpc_request_call;
#else
			strstr(el->name, "esponse") ? xmlrpc_request_response : xmlrpc_request_call;
#endif
			XMLRPC_RequestSetRequestType(request, rtype);

			/* Get methodname.  strip xml namespace crap. */
			p = strchr(el->name, ':');
			if (p) {
				methodname = p + 1;
			}
			if (rtype == xmlrpc_request_call) {
				XMLRPC_RequestSetMethodName(request, methodname);
			}
		}


		/* Next, we begin to convert actual values. if no children, then must be a scalar value. */
		if (!Q_Size(&el->children)) {
			if (!type && parent_array && parent_array->kids_type[0]) {
				type = parent_array->kids_type;
			}
			if (!type || !strcmp(type, TOKEN_STRING)) {
				XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len);
			}
			else if (!strcmp(type, TOKEN_INT)) {
				XMLRPC_SetValueInt(xCurrent, atoi(el->text.str));
			}
			else if (!strcmp(type, TOKEN_BOOLEAN)) {
				XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str));
			}
			else if (!strcmp(type, TOKEN_DOUBLE) ||
						!strcmp(type, TOKEN_FLOAT)) {
				XMLRPC_SetValueDouble(xCurrent, atof(el->text.str));
			}
			else if (!strcmp(type, TOKEN_NULL)) {
				/* already an empty val. do nothing. */
			}
			else if (!strcmp(type, TOKEN_DATETIME)) {
				XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str);
			}
			else if (!strcmp(type, TOKEN_BASE64)) {
				struct buffer_st buf;
				base64_decode_xmlrpc(&buf, el->text.str, el->text.len);
				XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset);
				buffer_delete(&buf);
			}
		}
		/* Element has children, thus a vector, or "compound type" in soap-speak. */
		else {
			struct array_info* ai = NULL;
			xml_element* iter = (xml_element*)Q_Head(&el->children);

			if (!type || !strcmp(type, TOKEN_STRUCT)) {
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct);
			}
			else if (!strcmp(type, TOKEN_ARRAY) || arrayType != NULL) {
				/* determine magic associated with soap array type.
				   this is passed down as we recurse, so our children have access to the info. */
				ai = parse_array_type_info(arrayType);	/* alloc'ed ai free'd below.*/
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
			}
			else {
				/* mixed is probably closest thing we have to compound type. */
				XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
			}
			/* Recurse, adding values as we go.  Check for error during recursion
			   and if found, bail.  this short-circuits us out of the recursion. */
			while ( iter && !XMLRPC_RequestGetError(request) ) {
				XMLRPC_VALUE xNext = NULL;
				/* top level elements don't actually represent values, so we just pass the
				   current value along until we are deep enough. */
				if ( depth <= 2 ||
					  (rtype == xmlrpc_request_response && depth <= 3) ) {
					xml_element_to_SOAP_REQUEST_worker(request, NULL, ai, xCurrent, iter, depth);
				}
				/* ready to do some actual de-serialization. create a new empty value and
				   pass that along to be init'd, then add it to our current vector. */
				else {
					xNext = XMLRPC_CreateValueEmpty();
					xml_element_to_SOAP_REQUEST_worker(request, xCurrent, ai, xNext, iter, depth);
					XMLRPC_AddValueToVector(xCurrent, xNext);
				}
				iter = (xml_element*)Q_Next(&el->children);
			}
			/* cleanup */
			if (ai) {
				free(ai);
			}
		}
	}
	return xCurrent;
}