Esempio n. 1
0
void FSData::startDownload()
{
	LLSD headers;
	headers.insert("User-Agent", LLViewerMedia::getCurrentUserAgent());
	headers.insert("viewer-version", versionid);
	LL_INFOS("Data") << "Downloading data.xml" << LL_ENDL;
	LLHTTPClient::get(fsdata_url,new FSDownloader(fsdata_url),headers);
}
	void SDTestObject::test<10>()
		// map operations
	{
		SDCleanupCheck check;
		
		LLSD v;
		ensure("undefined has no members", !v.has("amy"));
		ensure("undefined get() is undefined", v.get("bob").isUndefined());
		
		v = LLSD::emptyMap();
		ensure("empty map is a map", v.isMap());
		ensure("empty map has no members", !v.has("cam"));
		ensure("empty map get() is undefined", v.get("don").isUndefined());
		
		v.clear();
		v.insert("eli", 43);
		ensure("insert converts to map", v.isMap());
		ensure("inserted key is present", v.has("eli"));
		ensureTypeAndValue("inserted value", v.get("eli"), 43);
		
		v.insert("fra", false);
		ensure("first key still present", v.has("eli"));
		ensure("second key is present", v.has("fra"));
		ensureTypeAndValue("first value", v.get("eli"), 43);
		ensureTypeAndValue("second value", v.get("fra"), false);
		
		v.erase("eli");
		ensure("first key now gone", !v.has("eli"));
		ensure("second key still present", v.has("fra"));
		ensure("first value gone", v.get("eli").isUndefined());
		ensureTypeAndValue("second value sill there", v.get("fra"), false);
		
		v.erase("fra");
		ensure("second key now gone", !v.has("fra"));
		ensure("second value gone", v.get("fra").isUndefined());
		
		v["gil"] = (std::string)"good morning";
		ensure("third key present", v.has("gil"));
		ensureTypeAndValue("third key value", v.get("gil"), "good morning");
		
		const LLSD& cv = v;	// FIX ME IF POSSIBLE
		ensure("missing key", cv["ham"].isUndefined());
		ensure("key not present", !v.has("ham"));
	
		LLSD w = 43;
		const LLSD& cw = w;	// FIX ME IF POSSIBLE
		int i = cw["ian"];
		ensureTypeAndValue("other missing value", i, 0);
		ensure("other missing key", !w.has("ian"));
		ensure("no conversion", w.isInteger());
		
		LLSD x;
		x = v;
		ensure("copy map type", x.isMap());
		ensureTypeAndValue("copy map value gil", x.get("gil"), "good morning");
	}
Esempio n. 3
0
S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
{
	// map: { string:object, string:object }
	map = LLSD::emptyMap();
	S32 parse_count = 0;
	char c = get(istr);
	if(c == '{')
	{
		// eat commas, white
		bool found_name = false;
		std::string name;
		c = get(istr);
		while(c != '}' && istr.good())
		{
			if(!found_name)
			{
				if((c == '\"') || (c == '\'') || (c == 's'))
				{
					putback(istr, c);
					found_name = true;
					int count = deserialize_string(istr, name, mMaxBytesLeft);
					if(PARSE_FAILURE == count) return PARSE_FAILURE;
					account(count);
				}
				c = get(istr);
			}
			else
			{
				if(isspace(c) || (c == ':'))
				{
					c = get(istr);
					continue;
				}
				putback(istr, c);
				LLSD child;
				S32 count = doParse(istr, child);
				if(count > 0)
				{
					// There must be a value for every key, thus
					// child_count must be greater than 0.
					parse_count += count;
					map.insert(name, child);
				}
				else
				{
					return PARSE_FAILURE;
				}
				found_name = false;
				c = get(istr);
			}
		}
		if(c != '}')
		{
			map.clear();
			return PARSE_FAILURE;
		}
	}
	return parse_count;
}
// static
LLSD LLWLParamManager::createSkyMap(std::map<LLWLParamKey, LLWLParamSet> refs)
{
	LLSD skies = LLSD::emptyMap();
	for(std::map<LLWLParamKey, LLWLParamSet>::iterator iter = refs.begin(); iter != refs.end(); ++iter)
	{
		skies.insert(iter->first.name, iter->second.getAll());
	}
	return skies;
}
Esempio n. 5
0
LLSD LLSavedLogins::asLLSD() const
{
	LLSD output;
	for (LLSavedLoginsList::const_iterator i = mEntries.begin();
		 i != mEntries.end(); ++i)
	{
		output.insert(0, i->asLLSD());
	}
	return output;
}
Esempio n. 6
0
void PhoenixViewerLink::start_download()
{
	//cmdline_printchat("requesting msdata");
	// This has all the database about the developers and what versions are available etc.
	std::string url = "http://luna.nexisonline.net/app/msdata/";
	LLSD headers;
	headers.insert("Accept", "*/*");
	headers.insert("User-Agent", LLViewerMedia::getCurrentUserAgent());
	headers.insert("viewer-version", versionid);

	LLHTTPClient::get(url,new ModularSystemsDownloader( PhoenixViewerLink::msdata ),headers);
	
	url = "http://phoenixviewer.com/app/blacklist/versionquery.php?v=" + gSavedSettings.getString("PhoenixAssetBlacklistVersion");

	LL_INFOS("MSBlacklist") << "Checking for blacklist updates..." << LL_ENDL;
	LLHTTPClient::get(url,new ModularSystemsDownloader( PhoenixViewerLink::msblacklistquery ),headers);

	downloadClientTags();
}
Esempio n. 7
0
void PhoenixViewerLink::start_download()
{
	//cmdline_printchat("requesting msdata");
	std::string url = "http://phoenixviewer.com/app/msdata/";
	LLSD headers;
	headers.insert("Accept", "*/*");
	headers.insert("User-Agent", LLViewerMedia::getCurrentUserAgent());
	headers.insert("viewer-version", versionid);

	LL_INFOS("Data") << "Downloading msdata." << LL_ENDL;
	LLHTTPClient::get(url,new ModularSystemsDownloader( PhoenixViewerLink::msdata ),headers);
	
	url = "http://phoenixviewer.com/app/blacklist/blacklist.xml";

	LL_INFOS("Blacklist") << "Downloading blacklist.xml" << LL_ENDL;
	LLHTTPClient::get(url,new ModularSystemsDownloader( PhoenixViewerLink::msblacklist ),headers);

	downloadClientTags();
}
Esempio n. 8
0
// static
void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder)
{
	static const float REQUEST_TIMEOUT = 5;
	static LLSD sHeader;

	if (!sHeader.size())
	{
	    std::string user_agent = llformat("%s %d.%d.%d (%d)",
			LLVersionInfo::getChannel().c_str(),
			LLVersionInfo::getMajor(),
			LLVersionInfo::getMinor(),
			LLVersionInfo::getPatch(),
			LLVersionInfo::getBuild());

		sHeader.insert("Accept", "text/plain");
		sHeader.insert("User-Agent", user_agent);
	}

	LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT);
}
Esempio n. 9
0
S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
{
	map = LLSD::emptyMap();
	U32 value_nbo = 0;
	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
	S32 size = (S32)ntohl(value_nbo);
	S32 parse_count = 0;
	S32 count = 0;
	char c = get(istr);
	while(c != '}' && (count < size) && istr.good())
	{
		std::string name;
		switch(c)
		{
		case 'k':
			if(!parseString(istr, name))
			{
				return PARSE_FAILURE;
			}
			break;
		case '\'':
		case '"':
		{
			int cnt = deserialize_string_delim(istr, name, c);
			if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
			account(cnt);
			break;
		}
		}
		LLSD child;
		S32 child_count = doParse(istr, child);
		if(child_count > 0)
		{
			// There must be a value for every key, thus child_count
			// must be greater than 0.
			parse_count += child_count;
			map.insert(name, child);
		}
		else
		{
			return PARSE_FAILURE;
		}
		++count;
		c = get(istr);
	}
	if((c != '}') || (count < size))
	{
		// Make sure it is correctly terminated and we parsed as many
		// as were said to be there.
		return PARSE_FAILURE;
	}
	return parse_count;
}
Esempio n. 10
0
void PhoenixViewerLink::msblacklistquery(U32 status,std::string body)
{
	if(body != "0")
	{	
		// *Sigh*.
		// Just leave this in.  I'm not going to f**k with it for now.
		//update with a list of known malicious assets.
		std::string url = "http://phoenixviewer.com/app/blacklist/" + body + ".xml.gz";
		LLSD headers;
		headers.insert("Accept", "application/octet-stream");
		headers.insert("User-Agent", LLViewerMedia::getCurrentUserAgent());
		headers.insert("viewer-version", versionid);

		LL_INFOS("MSBlacklist") << "Downloading asset blacklist update " << url << LL_ENDL;

		LLHTTPClient::get(url,new ModularSystemsDownloader( PhoenixViewerLink::msblacklist ),headers);
		blacklist_version = body;
	}
	else
		LL_INFOS("MSBlacklist") << "Blacklist is up to date." << LL_ENDL;
}
	void SDTestObject::test<11>()
		// array operations
	{
		SDCleanupCheck check;
		
		LLSD v;
		ensure_equals("undefined has no size", v.size(), 0);
		ensure("undefined get() is undefined", v.get(0).isUndefined());
		
		v = LLSD::emptyArray();
		ensure("empty array is an array", v.isArray());
		ensure_equals("empty array has no size", v.size(), 0);
		ensure("empty map get() is undefined", v.get(0).isUndefined());
		
		v.clear();
		v.append(88);
		v.append("noodle");
		v.append(true);
		ensure_equals("appened array size", v.size(), 3);
		ensure("append array is an array", v.isArray());
		ensureTypeAndValue("append 0", v[0], 88);
		ensureTypeAndValue("append 1", v[1], "noodle");
		ensureTypeAndValue("append 2", v[2], true);
		
		v.insert(0, 77);
		v.insert(2, "soba");
		v.insert(4, false);
		ensure_equals("inserted array size", v.size(), 6);
		ensureTypeAndValue("post insert 0", v[0], 77);
		ensureTypeAndValue("post insert 1", v[1], 88);
		ensureTypeAndValue("post insert 2", v[2], "soba");
		ensureTypeAndValue("post insert 3", v[3], "noodle");
		ensureTypeAndValue("post insert 4", v[4], false);
		ensureTypeAndValue("post insert 5", v[5], true);
		
		ensureTypeAndValue("get 1", v.get(1), 88);
		v.set(1, "hot");
		ensureTypeAndValue("set 1", v.get(1), "hot");
		
		v.erase(3);
		ensure_equals("post erase array size", v.size(), 5);
		ensureTypeAndValue("post erase 0", v[0], 77);
		ensureTypeAndValue("post erase 1", v[1], "hot");
		ensureTypeAndValue("post erase 2", v[2], "soba");
		ensureTypeAndValue("post erase 3", v[3], false);
		ensureTypeAndValue("post erase 4", v[4], true);
		
		v.append(34);
		ensure_equals("size after append", v.size(), 6);
		ensureTypeAndValue("post append 5", v[5], 34);

		LLSD w;
		w = v;
		ensure("copy array type", w.isArray());
		ensure_equals("copy array size", w.size(), 6);
		ensureTypeAndValue("copy array 0", w[0], 77);
		ensureTypeAndValue("copy array 1", w[1], "hot");
		ensureTypeAndValue("copy array 2", w[2], "soba");
		ensureTypeAndValue("copy array 3", w[3], false);
		ensureTypeAndValue("copy array 4", w[4], true);
		ensureTypeAndValue("copy array 5", w[5], 34);
	}
    void llsdutil_object::test<9>()
    {
        set_test_name("llsd_matches");

        // for this test, construct a map of all possible LLSD types
        LLSD map;
        map.insert("empty",     LLSD());
        map.insert("Boolean",   LLSD::Boolean());
        map.insert("Integer",   LLSD::Integer(0));
        map.insert("Real",      LLSD::Real(0.0));
        map.insert("String",    LLSD::String("bah"));
        map.insert("NumString", LLSD::String("1"));
        map.insert("UUID",      LLSD::UUID());
        map.insert("Date",      LLSD::Date());
        map.insert("URI",       LLSD::URI());
        map.insert("Binary",    LLSD::Binary());
        map.insert("Map",       LLSD().with("foo", LLSD()));
        // Only an empty array can be constructed on the fly
        LLSD array;
        array.append(LLSD());
        map.insert("Array",     array);

        // These iterators are declared outside our various for loops to avoid
        // fatal MSVC warning: "I used to be broken, but I'm all better now!"
        LLSD::map_const_iterator mi, mend(map.endMap());

        /*-------------------------- llsd_matches --------------------------*/

        // empty prototype matches anything
        for (mi = map.beginMap(); mi != mend; ++mi)
        {
            ensure_equals(std::string("empty matches ") + mi->first, llsd_matches(LLSD(), mi->second), "");
        }

        LLSD proto_array, data_array;
        for (int i = 0; i < 3; ++i)
        {
            proto_array.append(LLSD());
            data_array.append(LLSD());
        }

        // prototype array matches only array
        for (mi = map.beginMap(); mi != mend; ++mi)
        {
            ensure(std::string("array doesn't match ") + mi->first,
                   ! llsd_matches(proto_array, mi->second).empty());
        }

        // data array must be at least as long as prototype array
        proto_array.append(LLSD());
        ensure_equals("data array too short", llsd_matches(proto_array, data_array),
                      "Array size 4 required instead of Array size 3");
        data_array.append(LLSD());
        ensure_equals("data array just right", llsd_matches(proto_array, data_array), "");
        data_array.append(LLSD());
        ensure_equals("data array longer", llsd_matches(proto_array, data_array), "");

        // array element matching
        data_array[0] = LLSD::String();
        ensure_equals("undefined prototype array entry", llsd_matches(proto_array, data_array), "");
        proto_array[0] = LLSD::Binary();
        ensure_equals("scalar prototype array entry", llsd_matches(proto_array, data_array),
                      "[0]: Binary required instead of String");
        data_array[0] = LLSD::Binary();
        ensure_equals("matching prototype array entry", llsd_matches(proto_array, data_array), "");

        // build a coupla maps
        LLSD proto_map, data_map;
        data_map["got"] = LLSD();
        data_map["found"] = LLSD();
        for (LLSD::map_const_iterator dmi(data_map.beginMap()), dmend(data_map.endMap());
             dmi != dmend; ++dmi)
        {
            proto_map[dmi->first] = dmi->second;
        }
        proto_map["foo"] = LLSD();
        proto_map["bar"] = LLSD();

        // prototype map matches only map
        for (mi = map.beginMap(); mi != mend; ++mi)
        {
            ensure(std::string("map doesn't match ") + mi->first,
                   ! llsd_matches(proto_map, mi->second).empty());
        }

        // data map must contain all keys in prototype map
        std::string error(llsd_matches(proto_map, data_map));
        ensure_contains("missing keys", error, "missing keys");
        ensure_contains("missing foo", error, "foo");
        ensure_contains("missing bar", error, "bar");
        ensure_does_not_contain("found found", error, "found");
        ensure_does_not_contain("got got", error, "got");
        data_map["bar"] = LLSD();
        error = llsd_matches(proto_map, data_map);
        ensure_contains("missing foo", error, "foo");
        ensure_does_not_contain("got bar", error, "bar");
        data_map["foo"] = LLSD();
        ensure_equals("data map just right", llsd_matches(proto_map, data_map), "");
        data_map["extra"] = LLSD();
        ensure_equals("data map with extra", llsd_matches(proto_map, data_map), "");

        // map element matching
        data_map["foo"] = LLSD::String();
        ensure_equals("undefined prototype map entry", llsd_matches(proto_map, data_map), "");
        proto_map["foo"] = LLSD::Binary();
        ensure_equals("scalar prototype map entry", llsd_matches(proto_map, data_map),
                      "['foo']: Binary required instead of String");
        data_map["foo"] = LLSD::Binary();
        ensure_equals("matching prototype map entry", llsd_matches(proto_map, data_map), "");

        // String
        {
            static const char* matches[] = { "String", "NumString", "Boolean", "Integer",
                                             "Real", "UUID", "Date", "URI" };
            test_matches("String", map, boost::begin(matches), boost::end(matches));
        }

        // Boolean, Integer, Real
        static const char* numerics[] = { "Boolean", "Integer", "Real" };
        for (const char **ni = boost::begin(numerics), **nend = boost::end(numerics);
             ni != nend; ++ni)
        {
            static const char* matches[] = { "Boolean", "Integer", "Real", "String", "NumString" };
            test_matches(*ni, map, boost::begin(matches), boost::end(matches));
        }

        // UUID
        {
            static const char* matches[] = { "UUID", "String", "NumString" };
            test_matches("UUID", map, boost::begin(matches), boost::end(matches));
        }

        // Date
        {
            static const char* matches[] = { "Date", "String", "NumString" };
            test_matches("Date", map, boost::begin(matches), boost::end(matches));
        }

        // URI
        {
            static const char* matches[] = { "URI", "String", "NumString" };
            test_matches("URI", map, boost::begin(matches), boost::end(matches));
        }

        // Binary
        {
            static const char* matches[] = { "Binary" };
            test_matches("Binary", map, boost::begin(matches), boost::end(matches));
        }

        /*-------------------------- llsd_equals ---------------------------*/

        // Cross-product of each LLSD type with every other
        for (LLSD::map_const_iterator lmi(map.beginMap()), lmend(map.endMap());
             lmi != lmend; ++lmi)
        {
            for (LLSD::map_const_iterator rmi(map.beginMap()), rmend(map.endMap());
                 rmi != rmend; ++rmi)
            {
                // Name this test based on the map keys naming the types of
                // interest, e.g "String::Integer".
                // We expect the values (xmi->second) to be equal if and only
                // if the type names (xmi->first) are equal.
                ensure(STRINGIZE(lmi->first << "::" << rmi->first),
                       bool(lmi->first == rmi->first) ==
                       bool(llsd_equals(lmi->second, rmi->second)));
            }
        }

        // Array cases
        LLSD rarray;
        rarray.append(1.0);
        rarray.append(2);
        rarray.append("3");
        LLSD larray(rarray);
        ensure("llsd_equals(equal arrays)", llsd_equals(larray, rarray));
        rarray[2] = "4";
        ensure("llsd_equals(different [2])", ! llsd_equals(larray, rarray));
        rarray = larray;
        rarray.append(LLSD::Date());
        ensure("llsd_equals(longer right array)", ! llsd_equals(larray, rarray));
        rarray = larray;
        rarray.erase(2);
        ensure("llsd_equals(shorter right array)", ! llsd_equals(larray, rarray));

        // Map cases
        LLSD rmap;
        rmap["San Francisco"] = 65;
        rmap["Phoenix"] = 92;
        rmap["Boston"] = 77;
        LLSD lmap(rmap);
        ensure("llsd_equals(equal maps)", llsd_equals(lmap, rmap));
        rmap["Boston"] = 80;
        ensure("llsd_equals(different [\"Boston\"])", ! llsd_equals(lmap, rmap));
        rmap = lmap;
        rmap["Atlanta"] = 95;
        ensure("llsd_equals(superset right map)", ! llsd_equals(lmap, rmap));
        rmap = lmap;
        lmap["Seattle"] = 72;
        ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
    }
Esempio n. 13
0
void FSData::processData(const LLSD& fsData)
{
	// Set Message Of The Day if present
	if(fsData.has("MOTD"))
	{
		gAgent.mMOTD.assign(fsData["MOTD"]);
	}

	bool local_file = false;
	if (!(fsData["Releases"].asInteger() == 0))
	{
		const std::string releases_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "releases.xml");
		llifstream releases_file(releases_filename);
		LLSD releases;
		if(releases_file.is_open())
		{
			if(LLSDSerialize::fromXML(releases, releases_file) >= 1)
			{
				if(releases.has("ReleaseVersion"))
				{
					if (fsData["Releases"].asInteger() <= releases["ReleaseVersion"].asInteger())
					{
						processReleasesLLSD(releases);
						local_file = true;
					}
				}
			}
			releases_file.close();
		}
	}

	if (!local_file)
	{
		LL_INFOS("Data") << "Downloading " << releases_url << LL_ENDL;
		LLHTTPClient::get(releases_url,new FSDownloader(releases_url));
	}


	local_file = false;
	if (!(fsData["Agents"].asInteger() == 0))
	{
		const std::string agents_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "agents.xml");
		llifstream agents_file(agents_filename);
		LLSD agents;
		if(agents_file.is_open())
		{
			if(LLSDSerialize::fromXML(agents, agents_file) >= 1)
			{
				if(agents.has("AgentsVersion"))
				{
					if (fsData["Agents"].asInteger() <= agents["AgentsVersion"].asInteger())
					{
						processAgentsLLSD(agents);
						local_file = true;
					}
				}
			}
			agents_file.close();
		}
	}

	if (!local_file)
	{
		LL_INFOS("Data") << "Downloading " << agents_url << LL_ENDL;
		LLHTTPClient::get(agents_url,new FSDownloader(agents_url));
	}

	//TODO: add blacklist support
// 	LL_INFOS("Blacklist") << "Downloading blacklist.xml" << LL_ENDL;
// 	LLHTTPClient::get(url,new FSDownloader( FSData::msblacklist ),headers);

	// FSUseLegacyClienttags: 0=Off, 1=Local Clienttags, 2=Download Clienttags
	if(gSavedSettings.getU32("FSUseLegacyClienttags") > 1)
	{
		LLSD headers;
		headers.insert("User-Agent", LLViewerMedia::getCurrentUserAgent());
		headers.insert("viewer-version", versionid);
		LLHTTPClient::get(legacy_client_list,new FSDownloader(legacy_client_list),headers);
		LL_INFOS("CLIENTTAGS DOWNLOADER") << "Getting new tags" << LL_ENDL;
	}
	else if(gSavedSettings.getU32("FSUseLegacyClienttags") > 0)
	{
		updateClientTagsLocal();
	}
}
Esempio n. 14
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;
}