/* describe a value (param, return, type) */
static XMLRPC_VALUE describeValue_worker(const char* type, const char* id, const char* desc, int optional, const char* default_val, XMLRPC_VALUE sub_params) {
   XMLRPC_VALUE xParam = NULL;
   if(id || desc) {
      xParam = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
      XMLRPC_VectorAppendString(xParam, xi_token_name, id, 0);
      XMLRPC_VectorAppendString(xParam, xi_token_type, type, 0);
      XMLRPC_VectorAppendString(xParam, xi_token_description, desc, 0);
      if(optional != 2) {
         XMLRPC_VectorAppendInt(xParam, xi_token_optional, optional);
      }
      if(optional == 1 && default_val) {
         XMLRPC_VectorAppendString(xParam, xi_token_default, default_val, 0);
      }
      XMLRPC_AddValueToVector(xParam, sub_params);
   }
   return xParam;
}
示例#2
0
XMLRPC_VALUE xsm_system_get_capabilities_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   XMLRPC_VALUE xReturn = XMLRPC_CreateVector(0, xmlrpc_vector_struct);
   XMLRPC_VALUE xFaults = XMLRPC_CreateVector("faults_interop", xmlrpc_vector_struct);
   XMLRPC_VALUE xIntro = XMLRPC_CreateVector("introspection", xmlrpc_vector_struct);

   /* support for fault spec */
   XMLRPC_VectorAppendString(xFaults, "specURL", "http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php", 0);
   XMLRPC_VectorAppendInt(xFaults, "specVersion", 20010516);

   /* support for introspection spec */
   XMLRPC_VectorAppendString(xIntro, "specURL", "http://xmlrpc-epi.sourceforge.net/specs/rfc.introspection.php", 0);
   XMLRPC_VectorAppendInt(xIntro, "specVersion", 20010516);

   XMLRPC_AddValuesToVector(xReturn,
                            xFaults,
                            xIntro,
                            NULL);

   return xReturn;
                            
}
示例#3
0
/* this complies with system.listMethods as defined at http://xmlrpc.usefulinc.com/doc/reserved.html */
static XMLRPC_VALUE xi_system_list_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   XMLRPC_VALUE xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);

   q_iter qi = Q_Iter_Head_F(&server->methodlist);
   while( qi ) {
      server_method* sm = Q_Iter_Get_F(qi);
      if(sm) {
         XMLRPC_VectorAppendString(xResponse, 0, sm->name, 0);
      }
      qi = Q_Iter_Next_F(qi);
   }
   return xResponse;
}
示例#4
0
void XmlRpcCall::AddStringToArray(const std::string& name, const char *sstr)
{
    // Does this kind array exist in current xmlrpc-call?
    std::map<std::string, XMLRPC_VALUE>::iterator iter = mapArrays_.find(name);
    
    if ( iter != mapArrays_.end())
    {
        //There exist allready given array. Add string there. 
        XMLRPC_VectorAppendString(iter->second, 0, sstr, 0);
    }
    else
    {
        // Create new array into xmlrpc-call.
        mapArrays_[name] = XMLRPC_CreateVector(name.c_str(), xmlrpc_vector_array);
        
        // Note here paramList owns created vector (assumption) and paramList is owned by request_ object. 
	    XMLRPC_AddValueToVector(paramList_, mapArrays_[name]);
        
        // Add string there.
        XMLRPC_VectorAppendString(mapArrays_[name], 0, sstr, 0);

    }

}
示例#5
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;
}
示例#6
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;
}
// 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;
}
/* convert an xml tree conforming to spec <url tbd> to  XMLRPC_VALUE
 * suitable for use with XMLRPC_ServerAddIntrospectionData
 */
XMLRPC_VALUE xml_element_to_method_description(xml_element* el, XMLRPC_ERROR err) {
   XMLRPC_VALUE xReturn = NULL;

   if(el->name) {
      const char* name = NULL;
      const char* type = NULL;
      const char* basetype = NULL;
      const char* desc = NULL;
      const char* def = NULL;
      int optional = 0;
      xml_element_attr* attr_iter = Q_Head(&el->attrs);

      /* grab element attributes up front to save redundant while loops */
      while(attr_iter) {
         if(!strcmp(attr_iter->key, "name")) {
            name = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "type")) {
            type = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "basetype")) {
            basetype = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "desc")) {
            desc = attr_iter->val;
         }
         else if(!strcmp(attr_iter->key, "optional")) {
            if(attr_iter->val && !strcmp(attr_iter->val, "yes")) {
               optional = 1;
            }
         }
         else if(!strcmp(attr_iter->key, "default")) {
            def = attr_iter->val;
         }
         attr_iter = Q_Next(&el->attrs);
      }

      /* value and typeDescription behave about the same */
      if(!strcmp(el->name, "value") || !strcmp(el->name, "typeDescription")) {
         XMLRPC_VALUE xSubList = NULL;
         const char* ptype = !strcmp(el->name, "value") ? type : basetype;
         if(ptype) {
            if(Q_Size(&el->children) &&
               (!strcmp(ptype, "array") || !strcmp(ptype, "struct") || !strcmp(ptype, "mixed"))) {
               xSubList = XMLRPC_CreateVector("member", xmlrpc_vector_array);

               if(xSubList) {
                  xml_element* elem_iter = Q_Head(&el->children);
                  while(elem_iter) {
                     XMLRPC_AddValueToVector(xSubList, 
                                             xml_element_to_method_description(elem_iter, err));
                     elem_iter = Q_Next(&el->children);
                  }
               }
            }
            xReturn = describeValue_worker(ptype, name, (desc ? desc : (xSubList ? NULL : el->text.str)), optional, def, xSubList);
         }
      }

      /* these three kids are about equivalent */
      else if(!strcmp(el->name, "params") || 
              !strcmp(el->name, "returns") || 
              !strcmp(el->name, "signature")) {
         if(Q_Size(&el->children)) {
            xml_element* elem_iter = Q_Head(&el->children);
            xReturn = XMLRPC_CreateVector(!strcmp(el->name, "signature") ? NULL : el->name, xmlrpc_vector_struct);


            while(elem_iter) {
               XMLRPC_AddValueToVector(xReturn, 
                                       xml_element_to_method_description(elem_iter, err));
               elem_iter = Q_Next(&el->children);
            }
         }
      }


      else if(!strcmp(el->name, "methodDescription")) {
         xml_element* elem_iter = Q_Head(&el->children);
         xReturn = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);

         XMLRPC_VectorAppendString(xReturn, xi_token_name, name, 0);

         while(elem_iter) {
            XMLRPC_AddValueToVector(xReturn, 
                                    xml_element_to_method_description(elem_iter, err));
            elem_iter = Q_Next(&el->children);
         }
      }

      /* items are slightly special */
      else if(!strcmp(el->name, "item")) {
         xReturn = XMLRPC_CreateValueString(name, el->text.str, el->text.len);
      }

      /* sure.  we'll let any ol element with children through */
      else if(Q_Size(&el->children)) {
         xml_element* elem_iter = Q_Head(&el->children);
         xReturn = XMLRPC_CreateVector(el->name, xmlrpc_vector_mixed);

         while(elem_iter) {
            XMLRPC_AddValueToVector(xReturn, 
                                    xml_element_to_method_description(elem_iter, err));
            elem_iter = Q_Next(&el->children);
         }
      }

      /* or anything at all really, so long as its got some text. 
       * no reason being all snotty about a spec, right? 
       */
      else if(el->name && el->text.len) {
         xReturn = XMLRPC_CreateValueString(el->name, el->text.str, el->text.len);
      }
   }

   return xReturn;
}
示例#9
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;
}