コード例 #1
0
LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
	const LLChannelDescriptors& channels,
	buffer_ptr_t& buffer,
	bool& eos,
	LLSD& context,
	LLPumpIO* pump)
{
	LLFastTimer t(FTM_PROCESS_XMLRPC2LLSD_REQUEST);
	PUMP_DEBUG;
	if(!eos) return STATUS_BREAK;
	if(!buffer) return STATUS_ERROR;

	PUMP_DEBUG;
	// *FIX: This technique for reading data is far from optimal. We
	// need to have some kind of istream interface into the xml
	// parser...
	S32 bytes = buffer->countAfter(channels.in(), NULL);
	if(!bytes) return STATUS_ERROR;
	char* buf = new char[bytes + 1];
	buf[bytes] = '\0';
	buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);

	//lldebugs << "xmlrpc request: " << buf << llendl;
	
	// Check the value in the buffer. XMLRPC_REQUEST_FromXML will report a error code 4 if 
	// values that are less than 0x20 are passed to it, except
	// 0x09: Horizontal tab; 0x0a: New Line; 0x0d: Carriage
	U8* cur_pBuf = (U8*)buf;
    U8 cur_char;
	for (S32 i=0; i<bytes; i++) 
	{
        cur_char = *cur_pBuf;
		if (   cur_char < 0x20
            && 0x09 != cur_char
            && 0x0a != cur_char
            && 0x0d != cur_char )
        {
			*cur_pBuf = '?';
        }
		++cur_pBuf;
	}

	PUMP_DEBUG;
	XMLRPC_REQUEST request = XMLRPC_REQUEST_FromXML(
		buf,
		bytes,
		NULL);
	if(!request)
	{
		llwarns << "XML -> SD Request process parse error." << llendl;
		delete[] buf;
		return STATUS_ERROR;
	}

	PUMP_DEBUG;
	LLBufferStream stream(channels, buffer.get());
	stream.precision(DEFAULT_PRECISION);
	const char* name = XMLRPC_RequestGetMethodName(request);
	stream << LLSDRPC_REQUEST_HEADER_1 << (name ? name : "")
		   << LLSDRPC_REQUEST_HEADER_2;
	XMLRPC_VALUE param = XMLRPC_RequestGetData(request);
	if(param)
	{
		PUMP_DEBUG;
		S32 size = XMLRPC_VectorSize(param);
		if(size > 1)
		{
			// if there are multiple parameters, stuff the values into
			// an array so that the next step in the chain can read them.
			stream << "[";
		}
 		XMLRPC_VALUE current = XMLRPC_VectorRewind(param);
		bool needs_comma = false;
 		while(current)
 		{
			if(needs_comma)
			{
				stream << ",";
			}
			needs_comma = true;
 			stream_out(stream, current);
 			current = XMLRPC_VectorNext(param);
 		}
		if(size > 1)
		{
			// close the array
			stream << "]";
		}
	}
	stream << LLSDRPC_REQUEST_FOOTER << std::flush;
	XMLRPC_RequestFree(request, 1);
	delete[] buf;
	PUMP_DEBUG;
	return STATUS_DONE;
}
コード例 #2
0
ファイル: xml_to_soap.c プロジェクト: browniebraun/php-src
/* translates data structures to soap/xml. recursive */
xml_element* SOAP_to_xml_element_worker(XMLRPC_REQUEST request, XMLRPC_VALUE node) {
#define BUF_SIZE 128
	xml_element* elem_val = NULL;
	if (node) {
		int bFreeNode = 0;  /* sometimes we may need to free 'node' variable */
		char buf[BUF_SIZE];
		XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(node);
		char* pName = NULL, *pAttrType = NULL;

		/* create our return value element */
		elem_val = xml_elem_new();

		switch (type) {
		case xmlrpc_type_struct:
		case xmlrpc_type_mixed:
		case xmlrpc_type_array:
			if (type == xmlrpc_type_array) {
				/* array's are _very_ special in soap.
				   TODO: Should handle sparse/partial arrays here. */

				/* determine soap array type. */
				const char* type = get_array_soap_type(node);
				xml_element_attr* attr_array_type = NULL;

				/* specify array kids type and array size. */
				snprintf(buf, sizeof(buf), "%s[%i]", type, XMLRPC_VectorSize(node));
				attr_array_type = new_attr(TOKEN_ARRAY_TYPE, buf);

				Q_PushTail(&elem_val->attrs, attr_array_type);

				pAttrType = TOKEN_ARRAY;
			}
			/* check for fault, which is a rather special case. 
			   (can't these people design anything consistent/simple/elegant?) */
			else if (type == xmlrpc_type_struct) {
				int fault_type = get_fault_type(node);
				if (fault_type) {
					if (fault_type == 1) {
						/* gen fault from xmlrpc style fault codes              
						    notice that we get a new node, which must be freed herein. */
						node = gen_fault_xmlrpc(node, elem_val);
						bFreeNode = 1;
					}
					pName = TOKEN_FAULT;
				}
			}

			{
				/* recurse through sub-elements */
				XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node);
				while ( xIter ) {
					xml_element* next_el = SOAP_to_xml_element_worker(request, xIter);
					if (next_el) {
						Q_PushTail(&elem_val->children, next_el);
					}
					xIter = XMLRPC_VectorNext(node);
				}
			}

			break;

			/* handle scalar types */
		case xmlrpc_type_empty:
			pAttrType = TOKEN_NULL;
			break;
		case xmlrpc_type_string:
			pAttrType = TOKEN_STRING;
			simplestring_addn(&elem_val->text, XMLRPC_GetValueString(node), XMLRPC_GetValueStringLen(node));
			break;
		case xmlrpc_type_int:
			pAttrType = TOKEN_INT;
			snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueInt(node));
			simplestring_add(&elem_val->text, buf);
			break;
		case xmlrpc_type_boolean:
			pAttrType = TOKEN_BOOLEAN;
			snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueBoolean(node));
			simplestring_add(&elem_val->text, buf);
			break;
		case xmlrpc_type_double:
			pAttrType = TOKEN_DOUBLE;
			snprintf(buf, BUF_SIZE, "%f", XMLRPC_GetValueDouble(node));
			simplestring_add(&elem_val->text, buf);
			break;
		case xmlrpc_type_datetime:
			{
				time_t tt = XMLRPC_GetValueDateTime(node);
				struct tm *tm = localtime (&tt);
				pAttrType = TOKEN_DATETIME;
				if(strftime (buf, BUF_SIZE, "%Y-%m-%dT%H:%M:%SZ", tm)) {
					simplestring_add(&elem_val->text, buf);
				}
			}
			break;
		case xmlrpc_type_base64:
			{
				struct buffer_st buf;
				pAttrType = TOKEN_BASE64;
				base64_encode_xmlrpc(&buf, XMLRPC_GetValueBase64(node), XMLRPC_GetValueStringLen(node));
				simplestring_addn(&elem_val->text, buf.data, buf.offset );
				buffer_delete(&buf);
			}
			break;
			break;
		default:
			break;
		}

		/* determining element's name is a bit tricky, due to soap semantics. */
		if (!pName) {
			/* if the value's type is known... */
			if (pAttrType) {
				/* see if it has an id (key). If so, use that as name, and type as an attribute. */
				pName = (char*)XMLRPC_GetValueID(node);
				if (pName) {
					Q_PushTail(&elem_val->attrs, new_attr(TOKEN_TYPE, pAttrType));
				}

				/* otherwise, use the type as the name. */
				else {
					pName = pAttrType;
				}
			}
			/* if the value's type is not known... (a rare case?) */
			else {
				/* see if it has an id (key). otherwise, default to generic "item" */
				pName = (char*)XMLRPC_GetValueID(node);
				if (!pName) {
					pName = "item";
				}
			}
		}
		elem_val->name = strdup(pName);

		/* cleanup */
		if (bFreeNode) {
			XMLRPC_CleanupValue(node);
		}
	}
	return elem_val;
}