diff options
| -rw-r--r-- | etc/message.xml | 33 | ||||
| -rw-r--r-- | indra/llcommon/lluri.cpp | 35 | ||||
| -rw-r--r-- | indra/llcommon/lluri.h | 97 | ||||
| -rw-r--r-- | indra/llmessage/llhttpclient.cpp | 40 | ||||
| -rw-r--r-- | indra/llmessage/llhttpclient.h | 2 | ||||
| -rw-r--r-- | indra/llmessage/llmessageconfig.cpp | 16 | ||||
| -rw-r--r-- | indra/llmessage/llmessageconfig.h | 2 | ||||
| -rw-r--r-- | indra/llmessage/llservicebuilder.cpp | 19 | ||||
| -rw-r--r-- | indra/newview/llpanelavatar.cpp | 27 | ||||
| -rw-r--r-- | indra/newview/llpanelavatar.h | 18 | ||||
| -rw-r--r-- | indra/test/llservicebuilder_tut.cpp | 17 | 
11 files changed, 238 insertions, 68 deletions
| diff --git a/etc/message.xml b/etc/message.xml index ad2364a5c8..f8e627334f 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -243,7 +243,6 @@  					<key>trusted-sender</key>  					<boolean>false</boolean>  				</map> -  				<!-- Simulator to simulator unreliable messages -->  				<key>EdgeDataPacket</key>  				<map> @@ -324,6 +323,38 @@  					<key>trusted-sender</key>  					<boolean>true</boolean>  				</map> +				<key>avatarnotesrequest</key> +				<map> +                    <key>service_name</key><string>avatar-notes</string> +					<key>builder</key> +					<string>template</string> +					<key>trusted-sender</key> +					<boolean>false</boolean> +				</map> +				<key>avatarclassifiedsrequest</key> +				<map> +                    <key>service_name</key><string>avatar-classifieds</string> +					<key>builder</key> +					<string>template</string> +					<key>trusted-sender</key> +					<boolean>false</boolean> +				</map> +				<key>avatarpickrequest</key> +				<map> +                    <key>service_name</key><string>avatar-pick</string> +					<key>builder</key> +					<string>template</string> +					<key>trusted-sender</key> +					<boolean>false</boolean> +				</map> +				<key>pickinforequest</key> +				<map> +                    <key>service_name</key><string>pick-info</string> +					<key>builder</key> +					<string>template</string> +					<key>trusted-sender</key> +					<boolean>false</boolean> +				</map>  		  </map>    	  	<key>capBans</key>      	<map> diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 5cb6067990..22526c9a03 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -275,9 +275,10 @@ LLURI LLURI::buildHTTP(const std::string& prefix,  					   const LLSD& query)  {  	LLURI uri = buildHTTP(prefix, path); -	uri.mEscapedQuery = mapToQueryString(query);  	// break out and escape each query component -	uri.mEscapedOpaque += "?" + uri.mEscapedQuery ; +	uri.mEscapedQuery = mapToQueryString(query); +	uri.mEscapedOpaque += uri.mEscapedQuery ; +	uri.mEscapedQuery.erase(0,1); // trim the leading '?'  	return uri;  } @@ -581,20 +582,30 @@ LLSD LLURI::queryMap(std::string escaped_query_string)  std::string LLURI::mapToQueryString(const LLSD& queryMap)  {  	std::string query_string; -  	if (queryMap.isMap())  	{ -		for (LLSD::map_const_iterator iter = queryMap.beginMap(); -			 iter != queryMap.endMap(); -			 iter++) +		bool first_element = true; +		LLSD::map_const_iterator iter = queryMap.beginMap(); +		LLSD::map_const_iterator end = queryMap.endMap(); +		std::ostringstream ostr; +		for (; iter != end; ++iter)  		{ -			query_string += escapeQueryVariable(iter->first) + -				(iter->second.isUndefined() ? "" : "=" + escapeQueryValue(iter->second.asString())) + "&" ; +			if(first_element) +			{ +				ostr << "?"; +				first_element = false; +			} +			else +			{ +				ostr << "&"; +			} +			ostr << escapeQueryVariable(iter->first); +			if(iter->second.isDefined()) +			{ +				ostr << "=" <<  escapeQueryValue(iter->second.asString()); +			}  		} -		//if (queryMap.size() > 0) -		//{ -		//	query_string += "?" + query_string ; -		//} +		query_string = ostr.str();  	}  	return query_string;  } diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index 9ec51b4b1a..00eacf6536 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -38,34 +38,42 @@ public:    // construct from escaped string, as would be transmitted on the net -  ~LLURI(); +	~LLURI(); -  static LLURI buildHTTP(const std::string& prefix, -			 const LLSD& path); -  static LLURI buildHTTP(const std::string& prefix, -			 const LLSD& path, -			 const LLSD& query); -	// prefix is either a full URL prefix of the form "http://example.com:8080", -	// or it can be simply a host and optional port like "example.com" or  -	// "example.com:8080", in these cases, the "http://" will be added +	static LLURI buildHTTP( +		const std::string& prefix, +		const LLSD& path); -  static LLURI buildHTTP(const std::string& host, -			 const U32& port, -			 const LLSD& path); -  static LLURI buildHTTP(const std::string& host, -			 const U32& port, -			 const LLSD& path, -			 const LLSD& query); -  std::string asString() const; -  // the whole URI, escaped as needed +	static LLURI buildHTTP( +		const std::string& prefix, +		const LLSD& path, +		const LLSD& query); +	///< prefix is either a full URL prefix of the form +	/// "http://example.com:8080", or it can be simply a host and +	/// optional port like "example.com" or "example.com:8080", in +	/// these cases, the "http://" will be added + +	static LLURI buildHTTP( +		const std::string& host, +		const U32& port, +		const LLSD& path); +	static LLURI buildHTTP( +		const std::string& host, +		const U32& port, +		const LLSD& path, +		const LLSD& query); + +	std::string asString() const; +	///< the whole URI, escaped as needed -  // Parts of a URI -  // These functions return parts of the decoded URI.  The returned -  // strings are un-escaped as needed +	/** @name Parts of a URI */ +	//@{ +	// These functions return parts of the decoded URI.  The returned +	// strings are un-escaped as needed -  // for all schemes -  std::string scheme() const;		// ex.: "http", note lack of colon -  std::string opaque() const;		// everything after the colon +	// for all schemes +	std::string scheme() const;		///< ex.: "http", note lack of colon +	std::string opaque() const;		///< everything after the colon    // for schemes that follow path like syntax (http, https, ftp)    std::string authority() const;	// ex.: "host.com:80" @@ -81,27 +89,34 @@ public:    const std::string& escapedQuery() const { return mEscapedQuery; }    LLSD queryMap() const;			// above decoded into a map    static LLSD queryMap(std::string escaped_query_string); -  static std::string mapToQueryString(const LLSD& queryMap); -  // Escaping Utilities -  // Escape a string by urlencoding all the characters that aren't in the allowed string. -  static std::string escape(const std::string& str); -  static std::string escape(const std::string& str, const std::string & allowed);  -  static std::string unescape(const std::string& str); +	/** +	 * @brief given a name value map, return a serialized query string. +	 * + +	 * @param query_map a map of name value. every value must be +	 * representable as a string. +	 * @return Returns an url query string of '?n1=v1&n2=v2&...' +	 */ +	static std::string mapToQueryString(const LLSD& query_map); -	// Functions for building specific URIs for web services -	// *NOTE: DEPRECATED. use the service builder instead. -	//static LLURI buildBulkAgentNamesURI(LLApp* app); -	//static LLURI buildAgentSessionURI(const LLUUID& agent_id, LLApp* app); -	//static LLURI buildAgentLoginInfoURI(const LLUUID& agent_id, const std::string& dataserver); -	//static LLURI buildAgentNameURI(const LLUUID& agent_id, LLApp* app); +	/** @name Escaping Utilities */ +	//@{ +	// Escape a string by urlencoding all the characters that aren't +	// in the allowed string. +	static std::string escape(const std::string& str); +	static std::string escape( +		const std::string& str, +		const std::string & allowed);  +	static std::string unescape(const std::string& str); +	//@}  private: -  std::string mScheme; -  std::string mEscapedOpaque; -  std::string mEscapedAuthority; -  std::string mEscapedPath; -  std::string mEscapedQuery; +	std::string mScheme; +	std::string mEscapedOpaque; +	std::string mEscapedAuthority; +	std::string mEscapedPath; +	std::string mEscapedQuery;  };  #endif // LL_LLURI_H diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 1bc6d742f1..c798e6473c 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -232,6 +232,7 @@ static void request(  	LLURLRequest::ERequestAction method,  	Injector* body_injector,  	LLHTTPClient::ResponderPtr responder, +    const LLSD& headers,  	const F32 timeout=HTTP_REQUEST_EXPIRY_SECS)  {  	if (!LLHTTPClient::hasPump()) @@ -243,6 +244,19 @@ static void request(  	LLURLRequest *req = new LLURLRequest(method, url);  	req->requestEncoding(""); + +    if (headers.isMap()) +    { +        LLSD::map_const_iterator iter = headers.beginMap(); +        LLSD::map_const_iterator end  = headers.endMap(); + +        for (; iter != end; ++iter) +        { +            std::ostringstream header; +            header << iter->first << ": " << iter->second.asString() ; +            req->addHeader(header.str().c_str()); +        } +    }  	if (!gCABundle.empty())  	{  		req->checkRootCertificate(true, gCABundle.c_str()); @@ -267,17 +281,37 @@ static void request(  	theClientPump->addChain(chain, timeout);  } +static void request( +	const std::string& url, +	LLURLRequest::ERequestAction method, +	Injector* body_injector, +	LLHTTPClient::ResponderPtr responder, +	const F32 timeout=HTTP_REQUEST_EXPIRY_SECS) +{ +    request(url, method, body_injector, responder, LLSD(), timeout); +} + +void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const LLSD& headers, const F32 timeout) +{ +	request(url, LLURLRequest::HTTP_GET, NULL, responder, headers, timeout); +} +  void LLHTTPClient::get(const std::string& url, ResponderPtr responder, const F32 timeout)  { -	request(url, LLURLRequest::HTTP_GET, NULL, responder, timeout); +	get(url, responder, LLSD(), timeout);  } -void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const F32 timeout) +void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const LLSD& headers, const F32 timeout)  {  	LLURI uri;  	uri = LLURI::buildHTTP(url, LLSD::emptyArray(), query); -	get(uri.asString(), responder, timeout); +	get(uri.asString(), responder, headers, timeout); +} + +void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr responder, const F32 timeout) +{ +	get(url, query, responder, LLSD(), timeout);  }  // A simple class for managing data returned from a curl http request. diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index 447bd691ba..e3074ee707 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -59,7 +59,9 @@ public:  	typedef boost::intrusive_ptr<Responder>	ResponderPtr;  	static void get(const std::string& url, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); +	static void get(const std::string& url, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);  	static void get(const std::string& url, const LLSD& query, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); +	static void get(const std::string& url, const LLSD& query, ResponderPtr, const LLSD& headers, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);  	static void put(const std::string& url, const LLSD& body, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS);  		///< non-blocking  	static void post(const std::string& url, const LLSD& body, ResponderPtr, const F32 timeout=HTTP_REQUEST_EXPIRY_SECS); diff --git a/indra/llmessage/llmessageconfig.cpp b/indra/llmessage/llmessageconfig.cpp index dd2d725d32..25bdc9fb16 100644 --- a/indra/llmessage/llmessageconfig.cpp +++ b/indra/llmessage/llmessageconfig.cpp @@ -232,3 +232,19 @@ bool LLMessageConfig::isCapBanned(const std::string& cap_name)  {  	return LLMessageConfigFile::instance().isCapBanned(cap_name);  } + +// return the web-service path to use for a given +// message. This entry *should* match the entry +// in simulator.xml! +LLSD LLMessageConfig::getConfigForMessage(const std::string& msg_name) +{ +	if (sServerName.empty()) +	{ +		llerrs << "LLMessageConfig::isMessageTrusted(name) before" +				<< " LLMessageConfig::initClass()" << llendl; +	} +	LLMessageConfigFile& file = LLMessageConfigFile::instance(); +	// LLSD for the CamelCase message name +	LLSD config = file.mMessages[msg_name]; +	return config; +} diff --git a/indra/llmessage/llmessageconfig.h b/indra/llmessage/llmessageconfig.h index a99cdc46fa..9cc20fe98b 100644 --- a/indra/llmessage/llmessageconfig.h +++ b/indra/llmessage/llmessageconfig.h @@ -10,6 +10,7 @@  #define LL_MESSAGECONFIG_H  #include <string> +#include "llsd.h"  class LLSD; @@ -30,5 +31,6 @@ public:  	static SenderTrust getSenderTrustedness(const std::string& msg_name);  	static bool isValidMessage(const std::string& msg_name);  	static bool isCapBanned(const std::string& cap_name); +	static LLSD getConfigForMessage(const std::string& msg_name);  };  #endif // LL_MESSAGECONFIG_H diff --git a/indra/llmessage/llservicebuilder.cpp b/indra/llmessage/llservicebuilder.cpp index 8c34a506de..806a888b2b 100644 --- a/indra/llmessage/llservicebuilder.cpp +++ b/indra/llmessage/llservicebuilder.cpp @@ -89,7 +89,7 @@ std::string LLServiceBuilder::buildServiceURI(  	const LLSD& option_map)  {  	std::string service_url = buildServiceURI(service_name); - +      	// Find the Service Name  	if(!service_url.empty() && option_map.isMap())  	{ @@ -108,6 +108,23 @@ std::string LLServiceBuilder::buildServiceURI(  					find_pos,  					variable_name.length(),  					(*option_itr).second.asString()); +				continue; +			} +			variable_name.assign("{%"); +			variable_name.append((*option_itr).first); +			variable_name.append("}"); +			find_pos = service_url.find(variable_name); +			if(find_pos != std::string::npos) +			{ +				std::string query_str = LLURI::mapToQueryString( +					(*option_itr).second); +				if(!query_str.empty()) +				{ +					service_url.replace( +						find_pos, +						variable_name.length(), +						query_str); +				}  			}  		}  	} diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index daea084759..2567684fa9 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -71,6 +71,7 @@ BOOL LLPanelAvatar::sAllowFirstLife = FALSE;  // RN: move these to lldbstrings.h  static const S32 DB_USER_FAVORITES_STR_LEN = 254; +const char LOADING_MSG[] = "Loading...";  static const char IM_DISABLED_TOOLTIP[] = "Instant Message (IM).\nDisabled because you do not have their card.";  static const char IM_ENABLED_TOOLTIP[] = "Instant Message (IM)";  static const S32 LEFT = HPAD; @@ -810,7 +811,7 @@ void LLPanelAvatarNotes::refresh()  void LLPanelAvatarNotes::clearControls()  { -	childSetText("notes edit", "Loading..."); +	childSetText("notes edit", LOADING_MSG);  	childSetEnabled("notes edit", false);  } @@ -1251,6 +1252,8 @@ LLPanelAvatar::LLPanelAvatar(  	mAvatarID( LLUUID::null ),	// mAvatarID is set with 'setAvatar' or 'setAvatarID'  	mHaveProperties(FALSE),  	mHaveStatistics(FALSE), +	mHaveNotes(false), +	mLastNotes(),  	mAllowEdit(allow_edit)  { @@ -1440,6 +1443,8 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name,  		mPanelNotes->clearControls();  		mPanelNotes->setDataRequested(false); +		mHaveNotes = false; +		mLastNotes.clear();  		// Request just the first two pages of data.  The picks,  		// classifieds, and notes will be requested when that panel @@ -1451,8 +1456,8 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name,  			if (mAllowEdit)  			{  				// OK button disabled until properties data arrives -				childSetVisible("OK",TRUE); -				childSetEnabled("OK",TRUE); +				childSetVisible("OK", true); +				childSetEnabled("OK", false);  				childSetVisible("Cancel",TRUE);  				childSetEnabled("Cancel",TRUE);  			} @@ -1747,7 +1752,19 @@ void LLPanelAvatar::sendAvatarPropertiesRequest()  void LLPanelAvatar::sendAvatarNotesUpdate()  {  	std::string notes = mPanelNotes->childGetValue("notes edit").asString(); -	 + +	if (!mHaveNotes +		&& (notes.empty() || notes == LOADING_MSG)) +	{ +		// no notes from server and no user updates +		return; +	} +	if (notes == mLastNotes) +	{ +		// Avatar notes unchanged +		return; +	} +  	LLMessageSystem *msg = gMessageSystem;  	msg->newMessage("AvatarNotesUpdate"); @@ -2155,6 +2172,8 @@ void LLPanelAvatar::processAvatarNotesReply(LLMessageSystem *msg, void**)  		msg->getString("Data", "Notes", DB_USER_NOTE_SIZE, text);  		self->childSetValue("notes edit", text);  		self->childSetEnabled("notes edit", true); +		self->mHaveNotes = true; +		self->mLastNotes = text;  	}  } diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index cbc4c55b52..1469be2e9d 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -303,16 +303,15 @@ public:  	static void onClickCSR(		void *userdata);  	static void onClickMute(	void *userdata); +private: +	void enableOKIfReady(); +  	static void finishKick(S32 option, const LLString& text, void* userdata);  	static void finishFreeze(S32 option, const LLString& text, void* userdata);  	static void finishUnfreeze(S32 option, const LLString& text, void* userdata);  	static void showProfileCallback(S32 option, void *userdata); -	// Teen users are not allowed to see or enter data into the first life page, -	// or their own about/interests text entry fields. -	static BOOL sAllowFirstLife; -  	static	void*	createPanelAvatar(void*	data);  	static	void*	createFloaterAvatarInfo(void*	data);  	static	void*	createPanelAvatarSecondLife(void*	data); @@ -333,13 +332,20 @@ public:  	LLPanelAvatarWeb*			mPanelWeb;  	LLDropTarget* 				mDropTarget; + +	// Teen users are not allowed to see or enter data into the first life page, +	// or their own about/interests text entry fields. +	static BOOL sAllowFirstLife; -protected: -	void						enableOKIfReady(); +private:  	LLUUID						mAvatarID;			// for which avatar is this window?  	BOOL						mIsFriend;			// Are we friends?  	BOOL						mHaveProperties;  	BOOL						mHaveStatistics; +	// only update note if data received from database and +	// note is changed from database version +	bool						mHaveNotes; +	std::string					mLastNotes;  	LLTabContainerCommon*		mTab;  	BOOL						mAllowEdit; diff --git a/indra/test/llservicebuilder_tut.cpp b/indra/test/llservicebuilder_tut.cpp index b4a814ebb9..e782cfbb6f 100644 --- a/indra/test/llservicebuilder_tut.cpp +++ b/indra/test/llservicebuilder_tut.cpp @@ -72,5 +72,22 @@ namespace tut  		std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map);  		ensure_equals("Replacement URL Creation for Non-existant Service", test_url , "/agent/{$agent-id}/name");  	} + +	template<> template<> +	void ServiceBuilderTestObject::test<5>() +	{ +		LLSD test_block; +		test_block["service-builder"] = "/proc/{$proc}{%params}"; +		mServiceBuilder.createServiceDefinition("ServiceBuilderTest", test_block["service-builder"]);	 +		LLSD data_map; +		data_map["proc"] = "do/something/useful"; +		data_map["params"]["estate_id"] = 1; +		data_map["params"]["query"] = "public"; +		std::string test_url = mServiceBuilder.buildServiceURI("ServiceBuilderTest", data_map); +		ensure_equals( +			"two part URL Creation", +			test_url , +			"/proc/do/something/useful?estate_id=1&query=public"); +	}  } | 
