// this is a c function here since it's really an implementation
// detail that requires a header file just get the definition of the
// parameters.
LLIOPipe::EStatus stream_out(std::ostream& ostr, XMLRPC_VALUE value)
{
	XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(value);
	LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
	switch(type)
	{
	case xmlrpc_type_base64:
	{
		S32 len = XMLRPC_GetValueStringLen(value);
		const char* buf = XMLRPC_GetValueBase64(value);
		ostr << " b(";
		if((len > 0) && buf)
		{
			ostr << len << ")\"";
			ostr.write(buf, len);
			ostr << "\"";
		}
		else
		{
			ostr << "0)\"\"";
		}
		break;
	}
	case xmlrpc_type_boolean:
		//lldebugs << "stream_out() bool" << llendl;
		ostr << " " << (XMLRPC_GetValueBoolean(value) ? "true" : "false");
		break;
	case xmlrpc_type_datetime:
		ostr << " d\"" << XMLRPC_GetValueDateTime_ISO8601(value) << "\"";
		break;
	case xmlrpc_type_double:
		ostr << " r" << XMLRPC_GetValueDouble(value);
		//lldebugs << "stream_out() double" << XMLRPC_GetValueDouble(value)
		//		 << llendl;
		break;
	case xmlrpc_type_int:
		ostr << " i" << XMLRPC_GetValueInt(value);
		//lldebugs << "stream_out() integer:" << XMLRPC_GetValueInt(value)
		//		 << llendl;
		break;
	case xmlrpc_type_string:
		//lldebugs << "stream_out() string: " << str << llendl;
		ostr << " s(" << XMLRPC_GetValueStringLen(value) << ")'"
			<< XMLRPC_GetValueString(value) << "'";
		break;
	case xmlrpc_type_array: // vector
	case xmlrpc_type_mixed: // vector
	{
		//lldebugs << "stream_out() array" << llendl;
		ostr << " [";
		U32 needs_comma = 0;
		XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
		while(current && (LLIOPipe::STATUS_OK == status))
		{
			if(needs_comma++) ostr << ",";
			status = stream_out(ostr, current);
			current = XMLRPC_VectorNext(value);
		}
		ostr << "]";
		break;
	}
	case xmlrpc_type_struct: // still vector
	{
		//lldebugs << "stream_out() struct" << llendl;
		ostr << " {";
		std::string name;
		U32 needs_comma = 0;
		XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
		while(current && (LLIOPipe::STATUS_OK == status))
		{
			if(needs_comma++) ostr << ",";
			name.assign(XMLRPC_GetValueID(current));
			ostr << "'" << LLSDNotationFormatter::escapeString(name) << "':";
			status = stream_out(ostr, current);
			current = XMLRPC_VectorNext(value);
		}
		ostr << "}";
		break;
	}
	case xmlrpc_type_empty:
	case xmlrpc_type_none:
	default:
		status = LLIOPipe::STATUS_ERROR;
		llwarns << "Found an empty xmlrpc type.." << llendl;
		// not much we can do here...
		break;
	};
	return status;
}
LLUserAuth::UserAuthcode LLUserAuth::parseResponse()
{
	// The job of this function is to parse sCurlDownloadArea and
	// extract every member into either the mResponses or
	// mOptions. For now, we will only be looking at mResponses, which
	// will all be string => string pairs.
	UserAuthcode rv = E_UNHANDLED_ERROR;
	XMLRPC_REQUEST response = mTransaction->response();
	if(!response) return rv;

	// clear out any old parsing
	mResponses.clear();
	mOptions.clear();

	// Now, parse everything
	std::string key;
	std::string val;
	XMLRPC_VALUE param = NULL;
	XMLRPC_VALUE current = NULL;
	XMLRPC_VALUE_TYPE_EASY type;
	param = XMLRPC_RequestGetData(response);
	if(!param) goto exit;
	current = XMLRPC_VectorRewind(param);
	while(current)
	{
		key.assign(XMLRPC_GetValueID(current));
		lldebugs << "key: " << key << llendl;
		type = XMLRPC_GetValueTypeEasy(current);
		if(xmlrpc_type_string == type)
		{
			val.assign(XMLRPC_GetValueString(current));
			lldebugs << "val: " << val << llendl;
			mResponses.insert(response_t::value_type(key, val));
		}
		else if(xmlrpc_type_int == type)
		{
			val = llformat( "%d", XMLRPC_GetValueInt(current));
			lldebugs << "val: " << val << llendl;
			mResponses.insert(response_t::value_type(key, val));
		}
		else if(xmlrpc_type_array == type)
		{
			options_t options;
			parseOptionInto(key, current, options);
			mOptions.insert(all_options_t::value_type(key, options));
		}
		else
		{
			// whoops - bad response
			llwarns << "Unhandled xmlrpc type, key, value: " << type << " "
					<< key << " " << val << "." << llendl;
			rv = E_UNHANDLED_ERROR;
			break;
		}
		current = XMLRPC_VectorNext(param);
		rv = E_OK;
	}

 exit:
	return rv;
}
Exemple #3
0
LLSD LLUserAuth::parseValues(UserAuthcode &auth_code, const std::string& key_pfx, XMLRPC_VALUE param)
{
	auth_code = E_OK;
	LLSD responses;
	for(XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current;
		current = XMLRPC_VectorNext(param))
	{
		std::string key(XMLRPC_GetValueID(current));
		lldebugs << "key: " << key_pfx << key << llendl;
		XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current);
		if(xmlrpc_type_string == type)
		{
			LLSD::String val(XMLRPC_GetValueString(current));
			lldebugs << "val: " << val << llendl;
			responses.insert(key,val);
		}
		else if(xmlrpc_type_int == type)
		{
			LLSD::Integer val(XMLRPC_GetValueInt(current));
			lldebugs << "val: " << val << llendl;
			responses.insert(key,val);
		}
		else if (xmlrpc_type_double == type)
        {
			LLSD::Real val(XMLRPC_GetValueDouble(current));
            lldebugs << "val: " << val << llendl;
			responses.insert(key,val);
		}
		else if(xmlrpc_type_array == type)
		{
			// We expect this to be an array of submaps. Walk the array,
			// recursively parsing each submap and collecting them.
			LLSD array;
			int i = 0;          // for descriptive purposes
			for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row;
				row = XMLRPC_VectorNext(current), ++i)
			{
				// Recursive call. For the lower-level key_pfx, if 'key'
				// is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
				// nested call, a subkey "bar" will then be logged as
				// "foo[0]:bar", and so forth.
				// Parse the scalar subkey/value pairs from this array
				// entry into a temp submap. Collect such submaps in 'array'.
				std::string key_prefix = key_pfx;
				array.append(parseValues(auth_code,
									STRINGIZE(key_pfx << key << '[' << i << "]:"),
									row));
			}
			// Having collected an 'array' of 'submap's, insert that whole
			// 'array' as the value of this 'key'.
			responses.insert(key, array);
		}
		else if (xmlrpc_type_struct == type)
    	{
    		LLSD submap = parseValues(auth_code,
            						STRINGIZE(key_pfx << key << ':'),
            						current);
            responses.insert(key, submap);
        }
        else
        {
        	// whoops - unrecognized type
            llwarns << "Unhandled xmlrpc type " << type << " for key "
                                        << key_pfx << key << LL_ENDL;
            responses.insert(key, STRINGIZE("<bad XMLRPC type " << type << '>'));
            auth_code = E_UNHANDLED_ERROR;
        }
    }
    return responses;
}
Exemple #4
0
/* 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;
}