Ejemplo n.º 1
0
         bool XMLRPC::setBuffer(dBuffer & _buffer)
         {
            XMLRPC_REQUEST temp_request;

            t_uint buffSize = _buffer.size();

            char *s=new char[buffSize+1];
            _buffer.getBytes(reinterpret_cast<t_byteP>(s), buffSize);
            s[buffSize] = 0;

            /* in xml_element.c:695 fprintf(stderr...) is used on
               error conditions.. Might wan't to remove that */
#if BTG_EXTERNALIZATION_DEBUG
            BTG_NOTICE(logWrapper(), "Deserializing command from " << s << " of size " << buffSize);
#endif // BTG_EXTERNALIZATION_DEBUG
            temp_request = XMLRPC_REQUEST_FromXML(s, buffSize, NULL);

            delete[] s;

            if(!temp_request)
               {
                  return false;
               }

            if (XMLRPC_RequestGetError(temp_request))
               {
                  XMLRPC_RequestFree(temp_request, 1);
                  return false;
               }

            /* Parsed OK, free the current request */
            XMLRPC_RequestFree(xmlrpc_request, 1);
            xmlrpc_request = temp_request;
            doRewind = true;
            return true;
         }
Ejemplo n.º 2
0
void LLXMLRPCTransaction::Impl::curlEasyRequestCallback(bool success)
{
	llassert(mStatus == LLXMLRPCTransaction::StatusStarted || mStatus == LLXMLRPCTransaction::StatusDownloading);

	AICurlEasyRequestStateMachine* state_machine = mCurlEasyRequestStateMachinePtr;
	// We're done with the statemachine, one way or another.
	// Set mCurlEasyRequestStateMachinePtr to NULL so we won't call mCurlEasyRequestStateMachinePtr->running() in the destructor.
	// Note that the state machine auto-cleaning: it will be deleted by the main-thread after this function returns.
	mCurlEasyRequestStateMachinePtr = NULL;

	if (!success)
	{
		// AICurlEasyRequestStateMachine did abort.
		// This currently only happens when libcurl didn't finish before the timer expired.
		std::ostringstream msg;
		F32 timeout_value = gSavedSettings.getF32("CurlRequestTimeOut");
		msg << "Connection to " << mURI << " timed out (" << timeout_value << " s)!";
		if (timeout_value < 40)
		{
			msg << "\nTry increasing CurlRequestTimeOut in Debug Settings.";
		}
		setStatus(LLXMLRPCTransaction::StatusOtherError, msg.str());
		return;
	}

	AICurlEasyRequest_wat curlEasyRequest_w(*state_machine->mCurlEasyRequest);
	CURLcode result;
	curlEasyRequest_w->getResult(&result, &mTransferInfo);

	if (result != CURLE_OK)
	{
		setCurlStatus(result);
		llwarns << "LLXMLRPCTransaction CURL error "
				<< mCurlCode << ": " << curlEasyRequest_w->getErrorString() << llendl;
		llwarns << "LLXMLRPCTransaction request URI: "
				<< mURI << llendl;
			
		return;
	}
	
	setStatus(LLXMLRPCTransaction::StatusComplete);

	mResponse = XMLRPC_REQUEST_FromXML(
			mResponseText.data(), mResponseText.size(), NULL);

	bool		hasError = false;
	bool		hasFault = false;
	int			faultCode = 0;
	std::string	faultString;

	LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse));
	if (error.isValid())
	{
		hasError = true;
		faultCode = error["faultCode"].asInt();
		faultString = error["faultString"].asString();
	}
	else if (XMLRPC_ResponseIsFault(mResponse))
	{
		hasFault = true;
		faultCode = XMLRPC_GetResponseFaultCode(mResponse);
		faultString = XMLRPC_GetResponseFaultString(mResponse);
	}

	if (hasError || hasFault)
	{
		setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
		
		llwarns << "LLXMLRPCTransaction XMLRPC "
				<< (hasError ? "error " : "fault ")
				<< faultCode << ": "
				<< faultString << llendl;
		llwarns << "LLXMLRPCTransaction request URI: "
				<< mURI << llendl;
	}
}
Ejemplo n.º 3
0
bool LLXMLRPCTransaction::Impl::process()
{
	switch(mStatus)
	{
		case LLXMLRPCTransaction::StatusComplete:
		case LLXMLRPCTransaction::StatusCURLError:
		case LLXMLRPCTransaction::StatusXMLRPCError:
		case LLXMLRPCTransaction::StatusOtherError:
		{
			return true;
		}
		
		case LLXMLRPCTransaction::StatusNotStarted:
		{
			setStatus(LLXMLRPCTransaction::StatusStarted);
			break;
		}
		
		default:
		{
			// continue onward
		}
	}
	
	const F32 MAX_PROCESSING_TIME = 0.05f;
	LLTimer timer;
	int count;
	
	while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(mCurlMulti, &count))
	{
		if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME)
		{
			return false;
		}
	}
			 
	while(CURLMsg* curl_msg = curl_multi_info_read(mCurlMulti, &count))
	{
		if (CURLMSG_DONE == curl_msg->msg)
		{
			if (curl_msg->data.result != CURLE_OK)
			{
				setCurlStatus(curl_msg->data.result);
				llwarns << "LLXMLRPCTransaction CURL error "
					<< mCurlCode << ": " << mCurlErrorBuffer << llendl;
				llwarns << "LLXMLRPCTransaction request URI: "
					<< mURI << llendl;
					
				return true;
			}
			
			setStatus(LLXMLRPCTransaction::StatusComplete);

			mResponse = XMLRPC_REQUEST_FromXML(
				mResponseText.data(), mResponseText.size(), NULL);

			bool		hasError = false;
			bool		hasFault = false;
			int			faultCode = 0;
			std::string	faultString;

			LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse));
			if (error.isValid())
			{
				hasError = true;
				faultCode = error["faultCode"].asInt();
				faultString = error["faultString"].asString();
			}
			else if (XMLRPC_ResponseIsFault(mResponse))
			{
				hasFault = true;
				faultCode = XMLRPC_GetResponseFaultCode(mResponse);
				faultString = XMLRPC_GetResponseFaultString(mResponse);
			}

			if (hasError || hasFault)
			{
				setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
				
				llwarns << "LLXMLRPCTransaction XMLRPC "
					<< (hasError ? "error " : "fault ")
					<< faultCode << ": "
					<< faultString << llendl;
				llwarns << "LLXMLRPCTransaction request URI: "
					<< mURI << llendl;
			}
			
			return true;
		}
	}
	
	return false;
}
bool LLXMLRPCTransaction::Impl::process()
{
	if(!mCurlRequest || !mCurlRequest->isValid())
	{
		llwarns << "transaction failed." << llendl ;

		delete mCurlRequest ;
		mCurlRequest = NULL ;
		return true ; //failed, quit.
	}

	switch(mStatus)
	{
		case LLXMLRPCTransaction::StatusComplete:
		case LLXMLRPCTransaction::StatusCURLError:
		case LLXMLRPCTransaction::StatusXMLRPCError:
		case LLXMLRPCTransaction::StatusOtherError:
		{
			return true;
		}
		
		case LLXMLRPCTransaction::StatusNotStarted:
		{
			setStatus(LLXMLRPCTransaction::StatusStarted);
			break;
		}
		
		default:
		{
			// continue onward
		}
	}
		
	if(!mCurlRequest->wait())
	{
		return false ;
	}

	while(1)
	{
		CURLcode result;
		bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo);
		if (newmsg)
		{
			if (result != CURLE_OK)
			{
				if ((result != CURLE_SSL_PEER_CERTIFICATE) &&
					(result != CURLE_SSL_CACERT))
				{
					// if we have a curl error that's not already been handled
					// (a non cert error), then generate the error message as
					// appropriate
					setCurlStatus(result);
				
					llwarns << "LLXMLRPCTransaction CURL error "
					<< mCurlCode << ": " << mCurlRequest->getErrorString() << llendl;
					llwarns << "LLXMLRPCTransaction request URI: "
					<< mURI << llendl;
				}
					
				return true;
			}
			
			setStatus(LLXMLRPCTransaction::StatusComplete);

			mResponse = XMLRPC_REQUEST_FromXML(
					mResponseText.data(), mResponseText.size(), NULL);

			bool		hasError = false;
			bool		hasFault = false;
			int			faultCode = 0;
			std::string	faultString;

			LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse));
			if (error.isValid())
			{
				hasError = true;
				faultCode = error["faultCode"].asInt();
				faultString = error["faultString"].asString();
			}
			else if (XMLRPC_ResponseIsFault(mResponse))
			{
				hasFault = true;
				faultCode = XMLRPC_GetResponseFaultCode(mResponse);
				faultString = XMLRPC_GetResponseFaultString(mResponse);
			}

			if (hasError || hasFault)
			{
				setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
				
				llwarns << "LLXMLRPCTransaction XMLRPC "
						<< (hasError ? "error " : "fault ")
						<< faultCode << ": "
						<< faultString << llendl;
				llwarns << "LLXMLRPCTransaction request URI: "
						<< mURI << llendl;
			}
			
			return true;
		}
		else
		{
			break; // done
		}
	}
	
	return false;
}
Ejemplo n.º 5
0
bool LLXMLRPCTransaction::Impl::process()
{
	switch(mStatus)
	{
		case LLXMLRPCTransaction::StatusComplete:
		case LLXMLRPCTransaction::StatusCURLError:
		case LLXMLRPCTransaction::StatusXMLRPCError:
		case LLXMLRPCTransaction::StatusOtherError:
		{
			return true;
		}
		
		case LLXMLRPCTransaction::StatusNotStarted:
		{
			setStatus(LLXMLRPCTransaction::StatusStarted);
			break;
		}
		
		default:
		{
			// continue onward
		}
	}
	
	const F32 MAX_PROCESSING_TIME = 0.05f;
	LLTimer timer;

	while (mCurlRequest->perform() > 0)
	{
		if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME)
		{
			return false;
		}
	}

	while(1)
	{
		CURLcode result;
		bool newmsg = mCurlRequest->getResult(&result, &mTransferInfo);
		if (newmsg)
		{
			if (result != CURLE_OK)
			{
				setCurlStatus(result);
				llwarns << "LLXMLRPCTransaction CURL error "
						<< mCurlCode << ": " << mCurlRequest->getErrorString() << llendl;
				llwarns << "LLXMLRPCTransaction request URI: "
						<< mURI << llendl;
					
				return true;
			}
			
			setStatus(LLXMLRPCTransaction::StatusComplete);

			mResponse = XMLRPC_REQUEST_FromXML(
					mResponseText.data(), mResponseText.size(), NULL);

			bool		hasError = false;
			bool		hasFault = false;
			int			faultCode = 0;
			std::string	faultString;

			LLXMLRPCValue error(XMLRPC_RequestGetError(mResponse));
			if (error.isValid())
			{
				hasError = true;
				faultCode = error["faultCode"].asInt();
				faultString = error["faultString"].asString();
			}
			else if (XMLRPC_ResponseIsFault(mResponse))
			{
				hasFault = true;
				faultCode = XMLRPC_GetResponseFaultCode(mResponse);
				faultString = XMLRPC_GetResponseFaultString(mResponse);
			}

			if (hasError || hasFault)
			{
				setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
				
				llwarns << "LLXMLRPCTransaction XMLRPC "
						<< (hasError ? "error " : "fault ")
						<< faultCode << ": "
						<< faultString << llendl;
				llwarns << "LLXMLRPCTransaction request URI: "
						<< mURI << llendl;
			}
			
			return true;
		}
		else
		{
			break; // done
		}
	}
	
	return false;
}
Ejemplo n.º 6
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;
}