diff options
Diffstat (limited to 'indra')
50 files changed, 2344 insertions, 464 deletions
| diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index bb64152407..c35799bbb9 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -379,7 +379,7 @@ namespace  	{  		/* This pattern, of returning a reference to a static function  		   variable, is to ensure that this global is constructed before -		   it is used, no matter what the global initializeation sequence +		   it is used, no matter what the global initialization sequence  		   is.  		   See C++ FAQ Lite, sections 10.12 through 10.14  		*/ diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 4a42241c4f..b3e604f8e8 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -39,7 +39,7 @@  	Information for most users: -	Code can log messages with constuctions like this: +	Code can log messages with constructions like this:  		LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id  			<< " denied due to timeout" << LL_ENDL; @@ -47,9 +47,9 @@  	Messages can be logged to one of four increasing levels of concern,  	using one of four "streams": -		LL_DEBUGS("StringTag")	- debug messages that are normally supressed -		LL_INFOS("StringTag")	- informational messages that are normall shown -		LL_WARNS("StringTag")	- warning messages that singal a problem +		LL_DEBUGS("StringTag")	- debug messages that are normally suppressed +		LL_INFOS("StringTag")	- informational messages that are normal shown +		LL_WARNS("StringTag")	- warning messages that signal a problem  		LL_ERRS("StringTag")	- error messages that are major, unrecoverable failures  	The later (LL_ERRS("StringTag")) automatically crashes the process after the message @@ -90,7 +90,7 @@  		WARN: LLFoo::doSomething: called with a big value for i: 283 -	Which messages are logged and which are supressed can be controled at run +	Which messages are logged and which are suppressed can be controlled at run  	time from the live file logcontrol.xml based on function, class and/or   	source file.  See etc/logcontrol-dev.xml for details. @@ -106,7 +106,7 @@ namespace LLError  	enum ELevel  	{  		LEVEL_ALL = 0, -			// used to indicate that all messagess should be logged +			// used to indicate that all messages should be logged  		LEVEL_DEBUG = 0,  		LEVEL_INFO = 1, @@ -220,7 +220,7 @@ namespace LLError  	// See top of file for example of how to use this  typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; -	// Outside a class declartion, or in class without LOG_CLASS(), this +	// Outside a class declaration, or in class without LOG_CLASS(), this  	// typedef causes the messages to not be associated with any class. diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index b4891eba67..afb714c71c 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -92,7 +92,7 @@ public:  	public:  		typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t; -		key_iter(typename InstanceMap::iterator& it) +		key_iter(typename InstanceMap::iterator it)  			:	mIterator(it)  		{  			++sIterationNestDepth; diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 7aee1bb85f..00757be277 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -100,12 +100,6 @@ private:  		DELETED  	} EInitState; -	static void deleteSingleton() -	{ -		delete getData().mSingletonInstance; -		getData().mSingletonInstance = NULL; -	} -	  	// stores pointer to singleton instance  	// and tracks initialization state of singleton  	struct SingletonInstanceData @@ -120,7 +114,11 @@ private:  		~SingletonInstanceData()  		{ -			deleteSingleton(); +			SingletonInstanceData& data = getData(); +			if (data.mInitState != DELETED) +			{ +				deleteSingleton(); +			}  		}  	}; @@ -132,6 +130,14 @@ public:  		data.mInitState = DELETED;  	} +	// Can be used to control when the singleton is deleted.  Not normally needed. +	static void deleteSingleton() +	{ +		delete getData().mSingletonInstance; +		getData().mSingletonInstance = NULL; +		getData().mInitState = DELETED; +	} +  	static SingletonInstanceData& getData()  	{  		// this is static to cache the lookup results diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index 3caf49aa6e..80b35bbdc3 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -90,79 +90,79 @@ namespace tut          ensure_equals(Keyed::instanceCount(), 0);      } -  //  template<> template<> -  //  void object::test<2>() -  //  { -  //      ensure_equals(Unkeyed::instanceCount(), 0); -  //      { -  //          Unkeyed one; -  //          ensure_equals(Unkeyed::instanceCount(), 1); -  //          Unkeyed* found = Unkeyed::getInstance(&one); -  //          ensure_equals(found, &one); -  //          { -  //              boost::scoped_ptr<Unkeyed> two(new Unkeyed); -  //              ensure_equals(Unkeyed::instanceCount(), 2); -  //              Unkeyed* found = Unkeyed::getInstance(two.get()); -  //              ensure_equals(found, two.get()); -  //          } -  //          ensure_equals(Unkeyed::instanceCount(), 1); -  //      } -  //      ensure_equals(Unkeyed::instanceCount(), 0); -  //  } +    template<> template<> +    void object::test<2>() +    { +        ensure_equals(Unkeyed::instanceCount(), 0); +        { +            Unkeyed one; +            ensure_equals(Unkeyed::instanceCount(), 1); +            Unkeyed* found = Unkeyed::getInstance(&one); +            ensure_equals(found, &one); +            { +                boost::scoped_ptr<Unkeyed> two(new Unkeyed); +                ensure_equals(Unkeyed::instanceCount(), 2); +                Unkeyed* found = Unkeyed::getInstance(two.get()); +                ensure_equals(found, two.get()); +            } +            ensure_equals(Unkeyed::instanceCount(), 1); +        } +        ensure_equals(Unkeyed::instanceCount(), 0); +    } -  //  template<> template<> -  //  void object::test<3>() -  //  { -  //      Keyed one("one"), two("two"), three("three"); -  //      // We don't want to rely on the underlying container delivering keys -  //      // in any particular order. That allows us the flexibility to -  //      // reimplement LLInstanceTracker using, say, a hash map instead of a -  //      // std::map. We DO insist that every key appear exactly once. -  //      typedef std::vector<std::string> StringVector; -  //      StringVector keys(Keyed::beginKeys(), Keyed::endKeys()); -  //      std::sort(keys.begin(), keys.end()); -  //      StringVector::const_iterator ki(keys.begin()); -  //      ensure_equals(*ki++, "one"); -  //      ensure_equals(*ki++, "three"); -  //      ensure_equals(*ki++, "two"); -  //      // Use ensure() here because ensure_equals would want to display -  //      // mismatched values, and frankly that wouldn't help much. -  //      ensure("didn't reach end", ki == keys.end()); +    template<> template<> +    void object::test<3>() +    { +        Keyed one("one"), two("two"), three("three"); +        // We don't want to rely on the underlying container delivering keys +        // in any particular order. That allows us the flexibility to +        // reimplement LLInstanceTracker using, say, a hash map instead of a +        // std::map. We DO insist that every key appear exactly once. +        typedef std::vector<std::string> StringVector; +        StringVector keys(Keyed::beginKeys(), Keyed::endKeys()); +        std::sort(keys.begin(), keys.end()); +        StringVector::const_iterator ki(keys.begin()); +        ensure_equals(*ki++, "one"); +        ensure_equals(*ki++, "three"); +        ensure_equals(*ki++, "two"); +        // Use ensure() here because ensure_equals would want to display +        // mismatched values, and frankly that wouldn't help much. +        ensure("didn't reach end", ki == keys.end()); -  //      // Use a somewhat different approach to order independence with -  //      // beginInstances(): explicitly capture the instances we know in a -  //      // set, and delete them as we iterate through. -  //      typedef std::set<Keyed*> InstanceSet; -  //      InstanceSet instances; -  //      instances.insert(&one); -  //      instances.insert(&two); -  //      instances.insert(&three); -  //      for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances()); -  //           ii != iend; ++ii) -  //      { -  //          Keyed& ref = *ii; -  //          ensure_equals("spurious instance", instances.erase(&ref), 1); -  //      } -  //      ensure_equals("unreported instance", instances.size(), 0); -  //  } +        // Use a somewhat different approach to order independence with +        // beginInstances(): explicitly capture the instances we know in a +        // set, and delete them as we iterate through. +        typedef std::set<Keyed*> InstanceSet; +        InstanceSet instances; +        instances.insert(&one); +        instances.insert(&two); +        instances.insert(&three); +        for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances()); +             ii != iend; ++ii) +        { +            Keyed& ref = *ii; +            ensure_equals("spurious instance", instances.erase(&ref), 1); +        } +        ensure_equals("unreported instance", instances.size(), 0); +    } + +    template<> template<> +    void object::test<4>() +    { +        Unkeyed one, two, three; +        typedef std::set<Unkeyed*> KeySet; +     +        KeySet instances; +        instances.insert(&one); +        instances.insert(&two); +        instances.insert(&three); -  //  template<> template<> -  //  void object::test<4>() -  //  { -  //      Unkeyed one, two, three; -  //      typedef std::set<Unkeyed*> KeySet; -  //   -  //      KeySet instances; -  //      instances.insert(&one); -  //      instances.insert(&two); -  //      instances.insert(&three); -	 -		//for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); ii != iend; ++ii) -		//{ -		//	Unkeyed& ref = *ii; -		//	ensure_equals("spurious instance", instances.erase(&ref), 1); -		//} -	 -  //      ensure_equals("unreported instance", instances.size(), 0); -  //  } +		for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); ii != iend; ++ii) +		{ +			Unkeyed& ref = *ii; +			ensure_equals("spurious instance", instances.erase(&ref), 1); +		} + +        ensure_equals("unreported instance", instances.size(), 0); +    }  } // namespace tut diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index c5f82cf052..0f40a670fa 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -65,6 +65,7 @@ set(llmessage_SOURCE_FILES      llpacketbuffer.cpp      llpacketring.cpp      llpartdata.cpp +    llproxy.cpp      llpumpio.cpp      llregionpresenceverifier.cpp      llsdappservices.cpp @@ -161,6 +162,7 @@ set(llmessage_HEADER_FILES      llpacketring.h      llpartdata.h      llpumpio.h +    llproxy.h      llqueryflags.h      llregionflags.h      llregionhandle.h diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 1a86a69a04..bfdf49c74b 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1,5 +1,5 @@  /** - * @file llcurl.h + * @file llcurl.cpp   * @author Zero / Donovan   * @date 2006-10-15   * @brief Implementation of wrapper around libcurl. @@ -26,7 +26,6 @@   * $/LicenseInfo$   */ -  #if LL_WINDOWS  #define SAFE_SSL 1  #elif LL_DARWIN @@ -47,8 +46,9 @@  #endif  #include "llbufferstream.h" -#include "llstl.h" +#include "llproxy.h"  #include "llsdserialize.h" +#include "llstl.h"  #include "llthread.h"  #include "lltimer.h" @@ -209,7 +209,7 @@ namespace boost  	void intrusive_ptr_release(LLCurl::Responder* p)  	{ -		if(p && 0 == --p->mReferenceCount) +		if (p && 0 == --p->mReferenceCount)  		{  			delete p;  		} @@ -219,73 +219,6 @@ namespace boost  ////////////////////////////////////////////////////////////////////////////// - -class LLCurl::Easy -{ -	LOG_CLASS(Easy); - -private: -	Easy(); -	 -public: -	static Easy* getEasy(); -	~Easy(); - -	CURL* getCurlHandle() const { return mCurlEasyHandle; } - -	void setErrorBuffer(); -	void setCA(); -	 -	void setopt(CURLoption option, S32 value); -	// These assume the setter does not free value! -	void setopt(CURLoption option, void* value); -	void setopt(CURLoption option, char* value); -	// Copies the string so that it is gauranteed to stick around -	void setoptString(CURLoption option, const std::string& value); -	 -	void slist_append(const char* str); -	void setHeaders(); -	 -	U32 report(CURLcode); -	void getTransferInfo(LLCurl::TransferInfo* info); - -	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false); -	 -	const char* getErrorBuffer(); - -	std::stringstream& getInput() { return mInput; } -	std::stringstream& getHeaderOutput() { return mHeaderOutput; } -	LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } -	const LLChannelDescriptors& getChannels() { return mChannels; } -	 -	void resetState(); - -	static CURL* allocEasyHandle(); -	static void releaseEasyHandle(CURL* handle); - -private:	 -	friend class LLCurl; - -	CURL*				mCurlEasyHandle; -	struct curl_slist*	mHeaders; -	 -	std::stringstream	mRequest; -	LLChannelDescriptors mChannels; -	LLIOPipe::buffer_ptr_t mOutput; -	std::stringstream	mInput; -	std::stringstream	mHeaderOutput; -	char				mErrorBuffer[CURL_ERROR_SIZE]; - -	// Note: char*'s not strings since we pass pointers to curl -	std::vector<char*>	mStrings; -	 -	ResponderPtr		mResponder; - -	static std::set<CURL*> sFreeHandles; -	static std::set<CURL*> sActiveHandles; -	static LLMutex* sHandleMutex; -}; -  std::set<CURL*> LLCurl::Easy::sFreeHandles;  std::set<CURL*> LLCurl::Easy::sActiveHandles;  LLMutex* LLCurl::Easy::sHandleMutex = NULL; @@ -409,11 +342,11 @@ const char* LLCurl::Easy::getErrorBuffer()  void LLCurl::Easy::setCA()  { -	if(!sCAPath.empty()) +	if (!sCAPath.empty())  	{  		setoptString(CURLOPT_CAPATH, sCAPath);  	} -	if(!sCAFile.empty()) +	if (!sCAFile.empty())  	{  		setoptString(CURLOPT_CAINFO, sCAFile);  	} @@ -536,9 +469,12 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	if (post) setoptString(CURLOPT_ENCODING, ""); -	//setopt(CURLOPT_VERBOSE, 1); // usefull for debugging +	//setopt(CURLOPT_VERBOSE, 1); // useful for debugging  	setopt(CURLOPT_NOSIGNAL, 1); +	// Set the CURL options for either Socks or HTTP proxy +	LLProxy::getInstance()->applyProxySettings(this); +  	mOutput.reset(new LLBufferArray);  	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback);  	setopt(CURLOPT_WRITEDATA, (void*)this); @@ -550,7 +486,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	setopt(CURLOPT_HEADERDATA, (void*)this);  	// Allow up to five redirects -	if(responder && responder->followRedir()) +	if (responder && responder->followRedir())  	{  		setopt(CURLOPT_FOLLOWLOCATION, 1);  		setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS); @@ -563,7 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	//don't verify host name so urls with scrubbed host names will work (improves DNS performance)  	setopt(CURLOPT_SSL_VERIFYHOST, 0); -	setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT)); +	setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);  	setoptString(CURLOPT_URL, url); @@ -584,56 +520,6 @@ void LLCurl::Easy::prepRequest(const std::string& url,  //////////////////////////////////////////////////////////////////////////// -class LLCurl::Multi : public LLThread -{ -	LOG_CLASS(Multi); -public: - -	typedef enum -	{ -		PERFORM_STATE_READY=0, -		PERFORM_STATE_PERFORMING=1, -		PERFORM_STATE_COMPLETED=2 -	} ePerformState; - -	Multi(); -	~Multi(); - -	Easy* allocEasy(); -	bool addEasy(Easy* easy); -	 -	void removeEasy(Easy* easy); - -	S32 process(); -	void perform(); -	void doPerform(); -	 -	virtual void run(); - -	CURLMsg* info_read(S32* msgs_in_queue); - -	S32 mQueued; -	S32 mErrorCount; -	 -	S32 mPerformState; - -	LLCondition* mSignal; -	bool mQuitting; -	bool mThreaded; - -private: -	void easyFree(Easy*); -	 -	CURLM* mCurlMultiHandle; - -	typedef std::set<Easy*> easy_active_list_t; -	easy_active_list_t mEasyActiveList; -	typedef std::map<CURL*, Easy*> easy_active_map_t; -	easy_active_map_t mEasyActiveMap; -	typedef std::set<Easy*> easy_free_list_t; -	easy_free_list_t mEasyFreeList; -}; -  LLCurl::Multi::Multi()  	: LLThread("Curl Multi"),  	  mQueued(0), @@ -1071,6 +957,8 @@ LLCurlEasyRequest::LLCurlEasyRequest()  	{  		mEasy->setErrorBuffer();  		mEasy->setCA(); +		// Set proxy settings if configured to do so. +		LLProxy::getInstance()->applyProxySettings(mEasy);  	}  } diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index f7518c8e5c..5ab4dc35b9 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -187,6 +187,122 @@ private:  	static const unsigned int MAX_REDIRECTS;  }; +class LLCurl::Easy +{ +	LOG_CLASS(Easy); + +private: +	Easy(); + +public: +	static Easy* getEasy(); +	~Easy(); + +	CURL* getCurlHandle() const { return mCurlEasyHandle; } + +	void setErrorBuffer(); +	void setCA(); + +	void setopt(CURLoption option, S32 value); +	// These assume the setter does not free value! +	void setopt(CURLoption option, void* value); +	void setopt(CURLoption option, char* value); +	// Copies the string so that it is guaranteed to stick around +	void setoptString(CURLoption option, const std::string& value); + +	void slist_append(const char* str); +	void setHeaders(); + +	U32 report(CURLcode); +	void getTransferInfo(LLCurl::TransferInfo* info); + +	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false); + +	const char* getErrorBuffer(); + +	std::stringstream& getInput() { return mInput; } +	std::stringstream& getHeaderOutput() { return mHeaderOutput; } +	LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } +	const LLChannelDescriptors& getChannels() { return mChannels; } + +	void resetState(); + +	static CURL* allocEasyHandle(); +	static void releaseEasyHandle(CURL* handle); + +private: +	friend class LLCurl; + +	CURL*				mCurlEasyHandle; +	struct curl_slist*	mHeaders; + +	std::stringstream	mRequest; +	LLChannelDescriptors mChannels; +	LLIOPipe::buffer_ptr_t mOutput; +	std::stringstream	mInput; +	std::stringstream	mHeaderOutput; +	char				mErrorBuffer[CURL_ERROR_SIZE]; + +	// Note: char*'s not strings since we pass pointers to curl +	std::vector<char*>	mStrings; + +	ResponderPtr		mResponder; + +	static std::set<CURL*> sFreeHandles; +	static std::set<CURL*> sActiveHandles; +	static LLMutex* sHandleMutex; +}; + +class LLCurl::Multi : public LLThread +{ +	LOG_CLASS(Multi); +public: + +	typedef enum +	{ +		PERFORM_STATE_READY=0, +		PERFORM_STATE_PERFORMING=1, +		PERFORM_STATE_COMPLETED=2 +	} ePerformState; + +	Multi(); +	~Multi(); + +	Easy* allocEasy(); +	bool addEasy(Easy* easy); +	 +	void removeEasy(Easy* easy); + +	S32 process(); +	void perform(); +	void doPerform(); +	 +	virtual void run(); + +	CURLMsg* info_read(S32* msgs_in_queue); + +	S32 mQueued; +	S32 mErrorCount; +	 +	S32 mPerformState; + +	LLCondition* mSignal; +	bool mQuitting; +	bool mThreaded; + +private: +	void easyFree(Easy*); +	 +	CURLM* mCurlMultiHandle; + +	typedef std::set<Easy*> easy_active_list_t; +	easy_active_list_t mEasyActiveList; +	typedef std::map<CURL*, Easy*> easy_active_map_t; +	easy_active_map_t mEasyActiveMap; +	typedef std::set<Easy*> easy_free_list_t; +	easy_free_list_t mEasyFreeList; +}; +  namespace boost  {  	void intrusive_ptr_add_ref(LLCurl::Responder* p); @@ -243,6 +359,8 @@ public:  	bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);  	std::string getErrorString(); +	LLCurl::Easy* getEasy() const { return mEasy; } +  private:  	CURLMsg* info_read(S32* queue, LLCurl::TransferInfo* info); @@ -253,4 +371,7 @@ private:  	bool mResultReturned;  }; +void check_curl_code(CURLcode code); +void check_curl_multi_code(CURLMcode code); +  #endif // LL_LLCURL_H diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 5a38b7fd9f..2bca517e97 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -33,6 +33,7 @@  #include "indra_constants.h"  #include "message.h" +#include "llproxy.h"  #include "llvfile.h"  #include "llvfs.h" @@ -232,6 +233,10 @@ void LLHTTPAssetRequest::setupCurlHandle()  {  	// *NOTE: Similar code exists in mapserver/llcurlutil.cpp  JC  	mCurlHandle = curl_easy_init(); + +	// Apply proxy settings if configured to do so +	LLProxy::getInstance()->applyProxySettings(mCurlHandle); +  	curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);  	curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);  	curl_easy_setopt(mCurlHandle, CURLOPT_URL, mURLBuffer.c_str()); diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 0e5206a520..dd4e3a6300 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -428,6 +428,9 @@ static LLSD blocking_request(  	std::string body_str;  	// other request method checks root cert first, we skip? + +	// Apply configured proxy settings +	LLProxy::getInstance()->applyProxySettings(curlp);  	// * Set curl handle options  	curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1);	// don't use SIGALRM for timeouts @@ -436,7 +439,7 @@ static LLSD blocking_request(  	curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer);  	curl_easy_setopt(curlp, CURLOPT_URL, url.c_str());  	curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); -	 +  	// * Setup headers (don't forget to free them after the call!)  	curl_slist* headers_list = NULL;  	if (headers.isMap()) diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index b717e321bf..ee9379f205 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -251,10 +251,12 @@ LLSocket::~LLSocket()  	{  		ll_debug_socket("Destroying socket", mSocket);  		apr_socket_close(mSocket); +		mSocket = NULL;  	}  	if(mPool)  	{  		apr_pool_destroy(mPool); +		mPool = NULL;  	}  } diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index e0f6c1e34d..be0f7dfcc6 100644 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -145,13 +145,6 @@ public:  	 */  	apr_socket_t* getSocket() const { return mSocket; } -protected: -	/**  -	 * @brief Protected constructor since should only make sockets -	 * with one of the two <code>create()</code> calls. -	 */ -	LLSocket(apr_socket_t* socket, apr_pool_t* pool); -  	/**   	 * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.  	 * @param timeout Number of microseconds to wait on this socket. Any @@ -164,6 +157,13 @@ protected:  	 */  	void setNonBlocking(); +protected: +	/** +	 * @brief Protected constructor since should only make sockets +	 * with one of the two <code>create()</code> calls. +	 */ +	LLSocket(apr_socket_t* socket, apr_pool_t* pool); +  public:  	/**   	 * @brief Do not call this directly. diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index 8999dec64a..7628984de4 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -28,11 +28,20 @@  #include "llpacketring.h" +#if LL_WINDOWS +	#include <winsock2.h> +#else +	#include <sys/socket.h> +	#include <netinet/in.h> +#endif +  // linden library includes  #include "llerror.h"  #include "lltimer.h" -#include "timing.h" +#include "llproxy.h"  #include "llrand.h" +#include "message.h" +#include "timing.h"  #include "u64.h"  /////////////////////////////////////////////////////////// @@ -216,8 +225,32 @@ S32 LLPacketRing::receivePacket (S32 socket, char *datap)  	else  	{  		// no delay, pull straight from net -		packet_size = receive_packet(socket, datap);		 -		mLastSender = ::get_sender(); +		if (LLProxy::isSOCKSProxyEnabled()) +		{ +			U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; +			packet_size = receive_packet(socket, reinterpret_cast<char *>(buffer)); +			 +			if (packet_size > SOCKS_HEADER_SIZE) +			{ +				// *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6) +				memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE); +				proxywrap_t * header = reinterpret_cast<proxywrap_t *>(buffer); +				mLastSender.setAddress(header->addr); +				mLastSender.setPort(ntohs(header->port)); + +				packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size +			} +			else +			{ +				packet_size = 0; +			} +		} +		else +		{ +			packet_size = receive_packet(socket, datap); +			mLastSender = ::get_sender(); +		} +  		mLastReceivingIF = ::get_receiving_interface();  		if (packet_size)  // did we actually get a packet? @@ -243,7 +276,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  	BOOL status = TRUE;  	if (!mUseOutThrottle)  	{ -		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); +		return sendPacketImpl(h_socket, send_buffer, buf_size, host );  	}  	else  	{ @@ -264,7 +297,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  				mOutBufferLength -= packetp->getSize();  				packet_size = packetp->getSize(); -				status = send_packet(h_socket, packetp->getData(), packet_size, packetp->getHost().getAddress(), packetp->getHost().getPort()); +				status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost());  				delete packetp;  				// Update the throttle @@ -273,7 +306,7 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  			else  			{  				// If the queue's empty, we can just send this packet right away. -				status = send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort() ); +				status =  sendPacketImpl(h_socket, send_buffer, buf_size, host );  				packet_size = buf_size;  				// Update the throttle @@ -311,3 +344,23 @@ BOOL LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LL  	return status;  } + +BOOL LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host) +{ +	 +	if (!LLProxy::isSOCKSProxyEnabled()) +	{ +		return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort()); +	} + +	proxywrap_t *socks_header = reinterpret_cast<proxywrap_t *>(&mProxyWrappedSendBuffer); +	socks_header->rsv   = 0; +	socks_header->addr  = host.getAddress(); +	socks_header->port  = htons(host.getPort()); +	socks_header->atype = ADDRESS_IPV4; +	socks_header->frag  = 0; + +	memcpy(mProxyWrappedSendBuffer + SOCKS_HEADER_SIZE, send_buffer, buf_size); + +	return send_packet(h_socket, (const char*) mProxyWrappedSendBuffer, buf_size + 10, LLProxy::getInstance()->getUDPProxy().getAddress(), LLProxy::getInstance()->getUDPProxy().getPort()); +} diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index e6409d2048..7edcc834db 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -30,11 +30,11 @@  #include <queue> -#include "llpacketbuffer.h"  #include "llhost.h" -#include "net.h" +#include "llpacketbuffer.h" +#include "llproxy.h"  #include "llthrottle.h" - +#include "net.h"  class LLPacketRing  { @@ -82,6 +82,12 @@ protected:  	LLHost mLastSender;  	LLHost mLastReceivingIF; + + +	U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE]; + +private: +	BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);  }; diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp new file mode 100644 index 0000000000..3f4a6accbf --- /dev/null +++ b/indra/llmessage/llproxy.cpp @@ -0,0 +1,551 @@ +/** + * @file llproxy.cpp + * @brief UDP and HTTP proxy communications + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llproxy.h" + +#include <string> +#include <curl/curl.h> + +#include "llapr.h" +#include "llcurl.h" +#include "llhost.h" + +// Static class variable instances + +// We want this to be static to avoid excessive indirection on every +// incoming packet just to do a simple bool test. The getter for this +// member is also static +bool LLProxy::sUDPProxyEnabled = false; + +// Some helpful TCP static functions. +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host); // Open a TCP channel to a given host +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel + +LLProxy::LLProxy(): +		mHTTPProxyEnabled(false), +		mProxyMutex(0), +		mUDPProxy(), +		mTCPProxy(), +		mPool(gAPRPoolp), +		mHTTPProxy(), +		mProxyType(LLPROXY_SOCKS), +		mAuthMethodSelected(METHOD_NOAUTH), +		mSocksUsername(), +		mSocksPassword() +{ +} + +LLProxy::~LLProxy() +{ +	stopSOCKSProxy(); +	sUDPProxyEnabled  = false; +	mHTTPProxyEnabled = false; +} + +/** + * @brief Open the SOCKS 5 TCP control channel. + * + * Perform a SOCKS 5 authentication and UDP association to the proxy server. + * + * @param proxy The SOCKS 5 server to connect to. + * @return SOCKS_OK if successful, otherwise a socks error code from llproxy.h. + */ +S32 LLProxy::proxyHandshake(LLHost proxy) +{ +	S32 result; + +	/* SOCKS 5 Auth request */ +	socks_auth_request_t  socks_auth_request; +	socks_auth_response_t socks_auth_response; + +	socks_auth_request.version     = SOCKS_VERSION;       // SOCKS version 5 +	socks_auth_request.num_methods = 1;                   // Sending 1 method. +	socks_auth_request.methods     = getSelectedAuthMethod(); // Send only the selected method. + +	result = tcp_handshake(mProxyControlChannel, (char*)&socks_auth_request, sizeof(socks_auth_request), (char*)&socks_auth_response, sizeof(socks_auth_response)); +	if (result != APR_SUCCESS) +	{ +		LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL; +		stopSOCKSProxy(); +		return SOCKS_CONNECT_ERROR; +	} + +	if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE) +	{ +		LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods" << LL_ENDL; +		stopSOCKSProxy(); +		return SOCKS_NOT_ACCEPTABLE; +	} + +	// SOCKS 5 USERNAME/PASSWORD authentication +	if (socks_auth_response.method == METHOD_PASSWORD) +	{ +		// The server has requested a username/password combination +		std::string socks_username(getSocksUser()); +		std::string socks_password(getSocksPwd()); +		U32 request_size = socks_username.size() + socks_password.size() + 3; +		char * password_auth = new char[request_size]; +		password_auth[0] = 0x01; +		password_auth[1] = socks_username.size(); +		memcpy(&password_auth[2], socks_username.c_str(), socks_username.size()); +		password_auth[socks_username.size() + 2] = socks_password.size(); +		memcpy(&password_auth[socks_username.size()+3], socks_password.c_str(), socks_password.size()); + +		authmethod_password_reply_t password_reply; + +		result = tcp_handshake(mProxyControlChannel, password_auth, request_size, (char*)&password_reply, sizeof(password_reply)); +		delete[] password_auth; + +		if (result != APR_SUCCESS) +		{ +			LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL; +			stopSOCKSProxy(); +			return SOCKS_CONNECT_ERROR; +		} + +		if (password_reply.status != AUTH_SUCCESS) +		{ +			LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL; +			stopSOCKSProxy(); +			return SOCKS_AUTH_FAIL; +		} +	} + +	/* SOCKS5 connect request */ + +	socks_command_request_t  connect_request; +	socks_command_response_t connect_reply; + +	connect_request.version		= SOCKS_VERSION;         // SOCKS V5 +	connect_request.command		= COMMAND_UDP_ASSOCIATE; // Associate UDP +	connect_request.reserved	= FIELD_RESERVED; +	connect_request.atype		= ADDRESS_IPV4; +	connect_request.address		= htonl(0); // 0.0.0.0 +	connect_request.port		= htons(0); // 0 +	// "If the client is not in possession of the information at the time of the UDP ASSOCIATE, +	//  the client MUST use a port number and address of all zeros. RFC 1928" + +	result = tcp_handshake(mProxyControlChannel, (char*)&connect_request, sizeof(connect_request), (char*)&connect_reply, sizeof(connect_reply)); +	if (result != APR_SUCCESS) +	{ +		LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL; +		stopSOCKSProxy(); +		return SOCKS_CONNECT_ERROR; +	} + +	if (connect_reply.reply != REPLY_REQUEST_GRANTED) +	{ +		LL_WARNS("Proxy") << "Connection to SOCKS 5 server failed, UDP forward request not granted" << LL_ENDL; +		stopSOCKSProxy(); +		return SOCKS_UDP_FWD_NOT_GRANTED; +	} + +	mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order +	mUDPProxy.setAddress(proxy.getAddress()); +	// The connection was successful. We now have the UDP port to send requests that need forwarding to. +	LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL; +	return SOCKS_OK; +} + +/** + * @brief Initiates a SOCKS 5 proxy session. + * + * Performs basic checks on host to verify that it is a valid address. Opens the control channel + * and then negotiates the proxy connection with the server. + * + * + * @param host Socks server to connect to. + * @return SOCKS_OK if successful, otherwise a SOCKS error code defined in llproxy.h. + */ +S32 LLProxy::startSOCKSProxy(LLHost host) +{ +	S32 status = SOCKS_OK; + +	if (host.isOk()) +	{ +		mTCPProxy = host; +	} +	else +	{ +		status = SOCKS_INVALID_HOST; +	} + +	if (mProxyControlChannel && status == SOCKS_OK) +	{ +		tcp_close_channel(&mProxyControlChannel); +	} + +	if (status == SOCKS_OK) +	{ +		mProxyControlChannel = tcp_open_channel(mPool, mTCPProxy); +		if (!mProxyControlChannel) +		{ +			status = SOCKS_HOST_CONNECT_FAILED; +		} +	} + +	if (status == SOCKS_OK) +	{ +		status = proxyHandshake(mTCPProxy); +	} +	if (status == SOCKS_OK) +	{ +		sUDPProxyEnabled = true; +	} +	else +	{ +		stopSOCKSProxy(); +	} +	return status; +} + +/** + * @brief Stop using the SOCKS 5 proxy. + * + * This will stop sending UDP packets through the SOCKS 5 proxy + * and will also stop the HTTP proxy if it is configured to use SOCKS. + * The proxy control channel will also be disconnected. + */ +void LLProxy::stopSOCKSProxy() +{ +	sUDPProxyEnabled = false; + +	// If the SOCKS proxy is requested to stop and we are using that for HTTP as well +	// then we must shut down any HTTP proxy operations. But it is allowable if web +	// proxy is being used to continue proxying HTTP. + +	if (LLPROXY_SOCKS == getHTTPProxyType()) +	{ +		void disableHTTPProxy(); +	} + +	if (mProxyControlChannel) +	{ +		tcp_close_channel(&mProxyControlChannel); +	} +} + +/** + * @brief Set the proxy's SOCKS authentication method to none. + */ +void LLProxy::setAuthNone() +{ +	LLMutexLock lock(&mProxyMutex); + +	mAuthMethodSelected = METHOD_NOAUTH; +} + +/** + * @brief Set the proxy's SOCKS authentication method to password. + * + * Check whether the lengths of the supplied username + * and password conform to the lengths allowed by the + * SOCKS protocol. + * + * @param 	username The SOCKS username to send. + * @param 	password The SOCKS password to send. + * @return  Return true if applying the settings was successful. No changes are made if false. + * + */ +bool LLProxy::setAuthPassword(const std::string &username, const std::string &password) +{ +	if (username.length() > SOCKSMAXUSERNAMELEN || password.length() > SOCKSMAXPASSWORDLEN || +			username.length() < SOCKSMINUSERNAMELEN || password.length() < SOCKSMINPASSWORDLEN) +	{ +		LL_WARNS("Proxy") << "Invalid SOCKS 5 password or username length." << LL_ENDL; +		return false; +	} + +	LLMutexLock lock(&mProxyMutex); + +	mAuthMethodSelected = METHOD_PASSWORD; +	mSocksUsername      = username; +	mSocksPassword      = password; + +	return true; +} + +/** + * @brief Enable the HTTP proxy for either SOCKS or HTTP. + * + * Check the supplied host to see if it is a valid IP and port. + * + * @param httpHost Proxy server to connect to. + * @param type Is the host a SOCKS or HTTP proxy. + * @return Return true if applying the setting was successful. No changes are made if false. + */ +bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type) +{ +	if (!httpHost.isOk()) +	{ +		LL_WARNS("Proxy") << "Invalid SOCKS 5 Server" << LL_ENDL; +		return false; +	} + +	LLMutexLock lock(&mProxyMutex); + +	mHTTPProxy        = httpHost; +	mProxyType        = type; + +	mHTTPProxyEnabled = true; + +	return true; +} + +/** + * @brief Enable the HTTP proxy without changing the proxy settings. + * + * This should not be called unless the proxy has already been set up. + * + * @return Return true only if the current settings are valid and the proxy was enabled. + */ +bool LLProxy::enableHTTPProxy() +{ +	bool ok; + +	LLMutexLock lock(&mProxyMutex); + +	ok = (mHTTPProxy.isOk()); +	if (ok) +	{ +		mHTTPProxyEnabled = true; +	} + +	return ok; +} + +/** + * @brief Disable the HTTP proxy. + */ +void LLProxy::disableHTTPProxy() +{ +	LLMutexLock lock(&mProxyMutex); + +	mHTTPProxyEnabled = false; +} + +/** + * @brief Get the HTTP proxy address and port + */ +// +LLHost LLProxy::getHTTPProxy() const +{ +	LLMutexLock lock(&mProxyMutex); +	return mHTTPProxy; +} + +/** + * @brief Get the currently selected HTTP proxy type + */ +LLHttpProxyType LLProxy::getHTTPProxyType() const +{ +	LLMutexLock lock(&mProxyMutex); +	return mProxyType; +} + +/** + * @brief Get the SOCKS 5 password. + */ +std::string LLProxy::getSocksPwd() const +{ +	LLMutexLock lock(&mProxyMutex); +	return mSocksPassword; +} + +/** + * @brief Get the SOCKS 5 username. + */ +std::string LLProxy::getSocksUser() const +{ +	LLMutexLock lock(&mProxyMutex); +	return mSocksUsername; +} + +/** + * @brief Get the currently selected SOCKS 5 authentication method. + * + * @return Returns either none or password. + */ +LLSocks5AuthType LLProxy::getSelectedAuthMethod() const +{ +	LLMutexLock lock(&mProxyMutex); +	return mAuthMethodSelected; +} + +/** + * @brief Stop the LLProxy and make certain that any APR pools and classes are deleted before terminating APR. + * + * Deletes the LLProxy singleton, destroying the APR pool used by the control channel as well as . + */ +//static +void LLProxy::cleanupClass() +{ +	getInstance()->stopSOCKSProxy(); +	deleteSingleton(); +} + +void LLProxy::applyProxySettings(LLCurlEasyRequest* handle) +{ +	applyProxySettings(handle->getEasy()); +} + +void LLProxy::applyProxySettings(LLCurl::Easy* handle) +{ +	applyProxySettings(handle->getCurlHandle()); +} + +/** + * @brief Apply proxy settings to a CuRL request if an HTTP proxy is enabled. + * + * This method has been designed to be safe to call from + * any thread in the viewer.  This allows requests in the + * texture fetch thread to be aware of the proxy settings. + * When the HTTP proxy is enabled, the proxy mutex will + * be locked every time this method is called. + * + * @param handle A pointer to a valid CURL request, before it has been performed. + */ +void LLProxy::applyProxySettings(CURL* handle) +{ +	// Do a faster unlocked check to see if we are supposed to proxy. +	if (mHTTPProxyEnabled) +	{ +		// We think we should proxy, lock the proxy mutex. +		LLMutexLock lock(&mProxyMutex); +		// Now test again to verify that the proxy wasn't disabled between the first check and the lock. +		if (mHTTPProxyEnabled) +		{ +			check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str())); +			check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort())); + +			if (mProxyType == LLPROXY_SOCKS) +			{ +				check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5)); +				if (mAuthMethodSelected == METHOD_PASSWORD) +				{ +					std::string auth_string = mSocksUsername + ":" + mSocksPassword; +					check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str())); +				} +			} +			else +			{ +				check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP)); +			} +		} +	} +} + +/** + * @brief Send one TCP packet and receive one in return. + * + * This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking + * operation would impact the operation of the viewer. + * + * @param handle_ptr 	Pointer to a connected LLSocket of type STREAM_TCP. + * @param dataout		Data to send. + * @param outlen		Length of dataout. + * @param datain		Buffer for received data. Undefined if return value is not APR_SUCCESS. + * @param maxinlen		Maximum possible length of received data.  Short reads are allowed. + * @return 				Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received. + */ +static S32 tcp_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen) +{ +	apr_socket_t* apr_socket = handle->getSocket(); +	apr_status_t rv = APR_SUCCESS; + +	apr_size_t expected_len = outlen; + +	handle->setBlocking(1000); + +  	rv = apr_socket_send(apr_socket, dataout, &outlen); +	if (APR_SUCCESS != rv) +	{ +		LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << LL_ENDL; +		ll_apr_warn_status(rv); +	} +	else if (expected_len != outlen) +	{ +		LL_WARNS("Proxy") << "Incorrect data length sent. Expected: " << expected_len << +				" Sent: " << outlen << LL_ENDL; +		rv = -1; +	} + +	if (APR_SUCCESS == rv) +	{ +		expected_len = maxinlen; +		rv = apr_socket_recv(apr_socket, datain, &maxinlen); +		if (rv != APR_SUCCESS) +		{ +			LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << LL_ENDL; +			ll_apr_warn_status(rv); +		} +		else if (expected_len < maxinlen) +		{ +			LL_WARNS("Proxy") << "Incorrect data length received. Expected: " << expected_len << +					" Received: " << maxinlen << LL_ENDL; +			rv = -1; +		} +	} + +	handle->setNonBlocking(); + +	return rv; +} + +/** + * @brief Open a LLSocket and do a blocking connect to the chosen host. + * + * Checks for a successful connection, and makes sure the connection is closed if it fails. + * + * @param pool		APR pool to pass into the LLSocket. + * @param host		The host to open the connection to. + * @return			The created socket.  Will evaluate as NULL if the connection is unsuccessful. + */ +static LLSocket::ptr_t tcp_open_channel(apr_pool_t* pool, LLHost host) +{ +	LLSocket::ptr_t socket = LLSocket::create(pool, LLSocket::STREAM_TCP); +	bool connected = socket->blockingConnect(host); +	if (!connected) +	{ +		tcp_close_channel(&socket); +	} + +	return socket; +} + +/** + * @brief Close the socket. + * + * @param handle_ptr A pointer-to-pointer to avoid increasing the use count. + */ +static void tcp_close_channel(LLSocket::ptr_t* handle_ptr) +{ +	LL_DEBUGS("Proxy") << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << LL_ENDL; +	handle_ptr->reset(); +} diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h new file mode 100644 index 0000000000..29e7e28567 --- /dev/null +++ b/indra/llmessage/llproxy.h @@ -0,0 +1,342 @@ +/** + * @file llproxy.h + * @brief UDP and HTTP proxy communications + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_PROXY_H +#define LL_PROXY_H + +#include "llcurl.h" +#include "llhost.h" +#include "lliosocket.h" +#include "llmemory.h" +#include "llsingleton.h" +#include "llthread.h" +#include <string> + +// SOCKS error codes returned from the StartProxy method + +#define SOCKS_OK 0 +#define SOCKS_CONNECT_ERROR (-1) +#define SOCKS_NOT_PERMITTED (-2) +#define SOCKS_NOT_ACCEPTABLE (-3) +#define SOCKS_AUTH_FAIL (-4) +#define SOCKS_UDP_FWD_NOT_GRANTED (-5) +#define SOCKS_HOST_CONNECT_FAILED (-6) +#define SOCKS_INVALID_HOST (-7) + + +#ifndef MAXHOSTNAMELEN +#define	MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */ +#endif + +#define SOCKSMAXUSERNAMELEN 255 +#define SOCKSMAXPASSWORDLEN 255 + +#define SOCKSMINUSERNAMELEN 1 +#define SOCKSMINPASSWORDLEN 1 + +#define SOCKS_VERSION 0x05 // we are using SOCKS 5 + +#define SOCKS_HEADER_SIZE 10 + +// SOCKS 5 address/hostname types +#define ADDRESS_IPV4     0x01 +#define ADDRESS_HOSTNAME 0x03 +#define ADDRESS_IPV6     0x04 + +// Lets just use our own ipv4 struct rather than dragging in system +// specific headers +union ipv4_address_t { +	U8		octets[4]; +	U32		addr32; +}; + +// SOCKS 5 control channel commands +#define COMMAND_TCP_STREAM    0x01 +#define COMMAND_TCP_BIND      0x02 +#define COMMAND_UDP_ASSOCIATE 0x03 + +// SOCKS 5 command replies +#define REPLY_REQUEST_GRANTED     0x00 +#define REPLY_GENERAL_FAIL        0x01 +#define REPLY_RULESET_FAIL        0x02 +#define REPLY_NETWORK_UNREACHABLE 0x03 +#define REPLY_HOST_UNREACHABLE    0x04 +#define REPLY_CONNECTION_REFUSED  0x05 +#define REPLY_TTL_EXPIRED         0x06 +#define REPLY_PROTOCOL_ERROR      0x07 +#define REPLY_TYPE_NOT_SUPPORTED  0x08 + +#define FIELD_RESERVED 0x00 + +// The standard SOCKS 5 request packet +// Push current alignment to stack and set alignment to 1 byte boundary +// This enabled us to use structs directly to set up and receive network packets +// into the correct fields, without fear of boundary alignment causing issues +#pragma pack(push,1) + +// SOCKS 5 command packet +struct socks_command_request_t { +	U8		version; +	U8		command; +	U8		reserved; +	U8		atype; +	U32		address; +	U16		port; +}; + +// Standard SOCKS 5 reply packet +struct socks_command_response_t { +	U8		version; +	U8		reply; +	U8		reserved; +	U8		atype; +	U8		add_bytes[4]; +	U16		port; +}; + +#define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available +#define AUTH_SUCCESS        0x00 // reply if authentication successful + +// SOCKS 5 authentication request, stating which methods the client supports +struct socks_auth_request_t { +	U8		version; +	U8		num_methods; +	U8		methods; // We are only using a single method currently +}; + +// SOCKS 5 authentication response packet, stating server preferred method +struct socks_auth_response_t { +	U8		version; +	U8		method; +}; + +// SOCKS 5 password reply packet +struct authmethod_password_reply_t { +	U8		version; +	U8		status; +}; + +// SOCKS 5 UDP packet header +struct proxywrap_t { +	U16		rsv; +	U8		frag; +	U8		atype; +	U32		addr; +	U16		port; +}; + +#pragma pack(pop) /* restore original alignment from stack */ + + +// Currently selected HTTP proxy type +enum LLHttpProxyType +{ +	LLPROXY_SOCKS = 0, +	LLPROXY_HTTP  = 1 +}; + +// Auth types +enum LLSocks5AuthType +{ +	METHOD_NOAUTH   = 0x00,	// Client supports no auth +	METHOD_GSSAPI   = 0x01,	// Client supports GSSAPI (Not currently supported) +	METHOD_PASSWORD = 0x02 	// Client supports username/password +}; + +/** + * @brief Manage SOCKS 5 UDP proxy and HTTP proxy. + * + * This class is responsible for managing two interconnected tasks, + * connecting to a SOCKS 5 proxy for use by LLPacketRing to send UDP + * packets and managing proxy settings for HTTP requests. + * + * <h1>Threading:</h1> + * Because HTTP requests can be generated in threads outside the + * main thread, it is necessary for some of the information stored + * by this class to be available to other threads. The members that + * need to be read across threads are in a labeled section below. + * To protect those members, a mutex, mProxyMutex should be locked + * before reading or writing those members.  Methods that can lock + * mProxyMutex are in a labeled section below. Those methods should + * not be called while the mutex is already locked. + * + * There is also a LLAtomic type flag (mHTTPProxyEnabled) that is used + * to track whether the HTTP proxy is currently enabled. This allows + * for faster unlocked checks to see if the proxy is enabled.  This + * allows us to cut down on the performance hit when the proxy is + * disabled compared to before this class was introduced. + * + * <h1>UDP Proxying:</h1> + * UDP datagrams are proxied via a SOCKS 5 proxy with the UDP associate + * command.  To initiate the proxy, a TCP socket connection is opened + * to the SOCKS 5 host, and after a handshake exchange, the server + * returns a port and address to send the UDP traffic that is to be + * proxied to. The LLProxy class tracks this address and port after the + * exchange and provides it to LLPacketRing when required to. All UDP + * proxy management occurs in the main thread. + * + * <h1>HTTP Proxying:</h1> + * This class allows all viewer HTTP packets to be sent through a proxy. + * The user can select whether to send HTTP packets through a standard + * "web" HTTP proxy, through a SOCKS 5 proxy, or to not proxy HTTP + * communication. This class does not manage the integrated web browser + * proxy, which is handled in llviewermedia.cpp. + * + * The implementation of HTTP proxying is handled by libcurl. LLProxy + * is responsible for managing the HTTP proxy options and provides a + * thread-safe method to apply those options to a curl request + * (LLProxy::applyProxySettings()). This method is overloaded + * to accommodate the various abstraction libcurl layers that exist + * throughout the viewer (LLCurlEasyRequest, LLCurl::Easy, and CURL). + * + * If you are working with LLCurl or LLCurlEasyRequest objects, + * the configured proxy settings will be applied in the constructors + * of those request handles.  If you are working with CURL objects + * directly, you will need to pass the handle of the request to + * applyProxySettings() before issuing the request. + * + * To ensure thread safety, all LLProxy members that relate to the HTTP + * proxy require the LLProxyMutex to be locked before accessing. + */ +class LLProxy: public LLSingleton<LLProxy> +{ +	LOG_CLASS(LLProxy); +public: +	// METHODS THAT DO NOT LOCK mProxyMutex! + +	LLProxy(); + +	// static check for enabled status for UDP packets +	static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } + +	// check for enabled status for HTTP packets +	// mHTTPProxyEnabled is atomic, so no locking is required for thread safety. +	bool isHTTPProxyEnabled() const { return mHTTPProxyEnabled; } + +	// Get the UDP proxy address and port +	LLHost getUDPProxy() const { return mUDPProxy; } + +	// Get the SOCKS 5 TCP control channel address and port +	LLHost getTCPProxy() const { return mTCPProxy; } + +	// END OF NON-LOCKING METHODS + +	// METHODS THAT DO LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! + +	~LLProxy(); + +	// Start a connection to the SOCKS 5 proxy +	S32 startSOCKSProxy(LLHost host); + +	// Disconnect and clean up any connection to the SOCKS 5 proxy +	void stopSOCKSProxy(); + +	// Delete LLProxy singleton, destroying the APR pool used by the control channel. +	static void cleanupClass(); + +	// Set up to use Password auth when connecting to the SOCKS proxy +	bool setAuthPassword(const std::string &username, const std::string &password); + +	// Set up to use No Auth when connecting to the SOCKS proxy +	void setAuthNone(); + +	// Get the currently selected auth method. +	LLSocks5AuthType getSelectedAuthMethod() const; + +	// Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy +	// as specified in type +	bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type); +	bool enableHTTPProxy(); + +	// Stop proxying HTTP packets +	void disableHTTPProxy(); + +	// Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false. +	void applyProxySettings(CURL* handle); +	void applyProxySettings(LLCurl::Easy* handle); +	void applyProxySettings(LLCurlEasyRequest* handle); + +	// Get the HTTP proxy address and port +	LLHost getHTTPProxy() const; + +	// Get the currently selected HTTP proxy type +	LLHttpProxyType getHTTPProxyType() const; + +	std::string getSocksPwd() const; +	std::string getSocksUser() const; + +	// END OF LOCKING METHODS +private: +	// Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort +	S32 proxyHandshake(LLHost proxy); + +private: +	// Is the HTTP proxy enabled? +	// Safe to read in any thread, do not write directly, +	// use enableHTTPProxy() and disableHTTPProxy() instead. +	mutable LLAtomic32<bool> mHTTPProxyEnabled; + +	// Mutex to protect shared members in non-main thread calls to applyProxySettings() +	mutable LLMutex mProxyMutex; + +	// MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE! + +	// Is the UDP proxy enabled? +	static bool sUDPProxyEnabled; + +	// UDP proxy address and port +	LLHost mUDPProxy; +	// TCP proxy control channel address and port +	LLHost mTCPProxy; + +	// socket handle to proxy TCP control channel +	LLSocket::ptr_t mProxyControlChannel; + +	// APR pool for the socket +	apr_pool_t* mPool; + +	// END OF UNSHARED MEMBERS + +	// MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex! + +	// HTTP proxy address and port +	LLHost mHTTPProxy; + +	// Currently selected HTTP proxy type. Can be web or socks. +	LLHttpProxyType mProxyType; + +	// SOCKS 5 auth method selected +	LLSocks5AuthType mAuthMethodSelected; + +	// SOCKS 5 username +	std::string mSocksUsername; +	// SOCKS 5 password +	std::string mSocksPassword; + +	// END OF SHARED MEMBERS +}; + +#endif diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index e8e35d00a2..d5400e4169 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -35,6 +35,7 @@  #include "llcurl.h"  #include "llioutil.h"  #include "llmemtype.h" +#include "llproxy.h"  #include "llpumpio.h"  #include "llsd.h"  #include "llstring.h" @@ -227,8 +228,7 @@ void LLURLRequest::useProxy(bool use_proxy)          }      } - -    lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl; +    LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << LL_ENDL;      if (env_proxy && use_proxy)      { diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 97611c3b51..85aef5da00 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -50,7 +50,6 @@  #include "lltimer.h"  #include "indra_constants.h" -  // Globals  #if LL_WINDOWS @@ -174,7 +173,7 @@ U32 ip_string_to_u32(const char* ip_string)  	// use wildcard addresses. -Ambroff  	U32 ip = inet_addr(ip_string);  	if (ip == INADDR_NONE  -	    && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0) +			&& strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0)  	{  		llwarns << "ip_string_to_u32() failed, Error: Invalid IP string '" << ip_string << "'" << llendl;  		return INVALID_HOST_IP_ADDRESS; @@ -188,11 +187,11 @@ U32 ip_string_to_u32(const char* ip_string)  //////////////////////////////////////////////////////////////////////////////////////////  #if LL_WINDOWS -  +  S32 start_net(S32& socket_out, int& nPort)   {			  	// Create socket, make non-blocking -    // Init WinSock  +	// Init WinSock  	int nRet;  	int hSocket; @@ -201,7 +200,7 @@ S32 start_net(S32& socket_out, int& nPort)  	int buff_size = 4;  	// Initialize windows specific stuff -	if(WSAStartup(0x0202, &stWSAData)) +	if (WSAStartup(0x0202, &stWSAData))  	{  		S32 err = WSAGetLastError();  		WSACleanup(); @@ -210,8 +209,8 @@ S32 start_net(S32& socket_out, int& nPort)  	}  	// Get a datagram socket -    hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); -    if (hSocket == INVALID_SOCKET) +	hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0); +	if (hSocket == INVALID_SOCKET)  	{  		S32 err = WSAGetLastError();  		WSACleanup(); @@ -304,7 +303,7 @@ S32 start_net(S32& socket_out, int& nPort)  	//  Setup a destination address  	stDstAddr.sin_family =      AF_INET;  	stDstAddr.sin_addr.s_addr = INVALID_HOST_IP_ADDRESS; -    stDstAddr.sin_port =        htons(nPort); +	stDstAddr.sin_port =        htons(nPort);  	socket_out = hSocket;  	return 0; @@ -393,10 +392,10 @@ S32 start_net(S32& socket_out, int& nPort)  	int rec_size = RECEIVE_BUFFER_SIZE;  	socklen_t buff_size = 4; -     +  	//  Create socket -    hSocket = socket(AF_INET, SOCK_DGRAM, 0); -    if (hSocket < 0) +	hSocket = socket(AF_INET, SOCK_DGRAM, 0); +	if (hSocket < 0)  	{  		llwarns << "socket() failed" << llendl;  		return 1; @@ -429,7 +428,7 @@ S32 start_net(S32& socket_out, int& nPort)  	}  	else  	{ -	    // Name the socket (assign the local port number to receive on) +		// Name the socket (assign the local port number to receive on)  		stLclAddr.sin_family      = AF_INET;  		stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);  		stLclAddr.sin_port        = htons(nPort); @@ -474,7 +473,7 @@ S32 start_net(S32& socket_out, int& nPort)  		nPort = attempt_port;  	}  	// Set socket to be non-blocking - 	fcntl(hSocket, F_SETFL, O_NONBLOCK); +	fcntl(hSocket, F_SETFL, O_NONBLOCK);  	// set a large receive buffer  	nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);  	if (nRet) @@ -510,8 +509,8 @@ S32 start_net(S32& socket_out, int& nPort)  	//  Setup a destination address  	char achMCAddr[MAXADDRSTR] = "127.0.0.1";	/* Flawfinder: ignore */   	stDstAddr.sin_family =      AF_INET; -        stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); -        stDstAddr.sin_port =        htons(nPort); +	stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); +	stDstAddr.sin_port =        htons(nPort);  	socket_out = hSocket;  	return 0; @@ -537,7 +536,7 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro  	iov[0].iov_base = buf;  	iov[0].iov_len = len; -	memset( &msg, 0, sizeof msg ); +	memset(&msg, 0, sizeof msg);  	msg.msg_name = from;  	msg.msg_namelen = *fromlen;  	msg.msg_iov = iov; @@ -545,14 +544,14 @@ static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *fro  	msg.msg_control = &cmsg;  	msg.msg_controllen = sizeof(cmsg); -	size = recvmsg( socket, &msg, 0 ); +	size = recvmsg(socket, &msg, 0); -	if( size == -1 ) +	if (size == -1)  	{  		return -1;  	} -	for( cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr ) ) +	for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr))  	{  		if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO )  		{ @@ -650,7 +649,7 @@ BOOL send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient,  			}  		}  	} -	while ( resend && send_attempts < 3); +	while (resend && send_attempts < 3);  	if (send_attempts >= 3)  	{ diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h index 9f4f5c5821..0f2437479d 100644 --- a/indra/llmessage/net.h +++ b/indra/llmessage/net.h @@ -46,10 +46,10 @@ S32		receive_packet(int hSocket, char * receiveBuffer);  BOOL	send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort);	// Returns TRUE on success.  //void	get_sender(char * tmp); -LLHost  get_sender(); +LLHost	get_sender();  U32		get_sender_port();  U32		get_sender_ip(void); -LLHost  get_receiving_interface(); +LLHost	get_receiving_interface();  U32		get_receiving_interface_ip(void);  const char*	u32_to_ip_string(U32 ip);					// Returns pointer to internal string buffer, "(bad IP addr)" on failure, cannot nest calls  diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 9ca3a23d52..7188b0fa44 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1424,7 +1424,7 @@ void LLImageGL::deleteDeadTextures()  		{  			LLTexUnit* tex_unit = gGL.getTexUnit(i); -			if (tex_unit->getCurrTexture() == tex) +			if (tex_unit && tex_unit->getCurrTexture() == tex)  			{  				tex_unit->unbind(tex_unit->getCurrType());  				stop_glerror(); @@ -1887,6 +1887,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)  void LLImageGL::setCategory(S32 category)   { +#if 0 //turn this off temporarily because it is not in use now.  	if(!gAuditTexture)  	{  		return ; @@ -1907,6 +1908,7 @@ void LLImageGL::setCategory(S32 category)  			mCategory = -1 ;  		}  	} +#endif  }  //for debug use  diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 752c7df7ee..899cc3a326 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -103,7 +103,7 @@ public:  		}  		else  		{ -			llwarns << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl; +			lldebugs << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl;  			return mMap[LOGFUNCTOR];  		}  	} @@ -115,7 +115,7 @@ private:  	static void log_functor(const LLSD& notification, const LLSD& payload)  	{ -		llwarns << "log_functor called with payload: " << payload << llendl; +		lldebugs << "log_functor called with payload: " << payload << llendl;  	}  	static void do_nothing(const LLSD& notification, const LLSD& payload) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7c01731282..43aa67e949 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -798,6 +798,61 @@        <key>Value</key>        <integer>5</integer>      </map> +    <key>Socks5ProxyEnabled</key> +    <map> +      <key>Comment</key> +      <string>Use Socks5 Proxy</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map> +    <key>HttpProxyType</key> +    <map> +      <key>Comment</key> +      <string>Proxy type to use for HTTP operations</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>Socks</string> +    </map> +    <key>Socks5ProxyHost</key> +    <map> +      <key>Comment</key> +      <string>Socks 5 Proxy Host</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string></string> +    </map> +    <key>Socks5ProxyPort</key> +    <map> +      <key>Comment</key> +      <string>Socks 5 Proxy Port</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>U32</string> +      <key>Value</key> +      <integer>1080</integer> +    </map> +    <key>Socks5AuthType</key> +    <map> +      <key>Comment</key> +      <string>Selected Auth mechanism for Socks5</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string>None</string> +    </map>      <key>BuildAxisDeadZone0</key>      <map>        <key>Comment</key> @@ -3993,7 +4048,7 @@        <key>Type</key>        <string>String</string>        <key>Value</key> -      <string>http://search-beta.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]</string> +      <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]</string>      </map>      <key>WebProfileURL</key>      <map> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index d12b971bde..6a808b5daf 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -137,6 +137,7 @@  #include "lltoolmgr.h"  #include "llassetstorage.h"  #include "llpolymesh.h" +#include "llproxy.h"  #include "llaudioengine.h"  #include "llstreamingaudio.h"  #include "llviewermenu.h" @@ -321,6 +322,41 @@ static std::string gLaunchFileOnQuit;  // Used on Win32 for other apps to identify our window (eg, win_setup)  const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; +//-- LLDeferredTaskList ------------------------------------------------------ + +/** + * A list of deferred tasks. + * + * We sometimes need to defer execution of some code until the viewer gets idle, + * e.g. removing an inventory item from within notifyObservers() may not work out. + * + * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration. + * All tasks are executed only once. + */ +class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList> +{ +	LOG_CLASS(LLDeferredTaskList); + +	friend class LLAppViewer; +	typedef boost::signals2::signal<void()> signal_t; + +	void addTask(const signal_t::slot_type& cb) +	{ +		mSignal.connect(cb); +	} + +	void run() +	{ +		if (!mSignal.empty()) +		{ +			mSignal(); +			mSignal.disconnect_all_slots(); +		} +	} + +	signal_t mSignal; +}; +  //----------------------------------------------------------------------------  // List of entries from strings.xml to always replace @@ -731,6 +767,23 @@ bool LLAppViewer::init()      initThreads();  	LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; +	// Initialize settings early so that the defaults for ignorable dialogs are +	// picked up and then correctly re-saved after launching the updater (STORM-1268). +	LLUI::settings_map_t settings_map; +	settings_map["config"] = &gSavedSettings; +	settings_map["ignores"] = &gWarningSettings; +	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file +	settings_map["account"] = &gSavedPerAccountSettings; + +	LLUI::initClass(settings_map, +		LLUIImageList::getInstance(), +		ui_audio_callback, +		&LLUI::sGLScaleFactor); +	LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; + +	LLNotifications::instance(); +	LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; +      writeSystemInfo();  	// Initialize updater service (now that we have an io pump) @@ -772,19 +825,8 @@ bool LLAppViewer::init()  	{  		LLError::setPrintLocation(true);  	} -	 -	// Widget construction depends on LLUI being initialized -	LLUI::settings_map_t settings_map; -	settings_map["config"] = &gSavedSettings; -	settings_map["ignores"] = &gWarningSettings; -	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file -	settings_map["account"] = &gSavedPerAccountSettings; -	LLUI::initClass(settings_map, -		LLUIImageList::getInstance(), -		ui_audio_callback, -		&LLUI::sGLScaleFactor); -	 +  	// Setup paths and LLTrans after LLUI::initClass has been called  	LLUI::setupPaths();  	LLTransUtil::parseStrings("strings.xml", default_trans_args);		 @@ -1840,6 +1882,8 @@ bool LLAppViewer::cleanup()  		LLWeb::loadURLExternal( gLaunchFileOnQuit, false );  		llinfos << "File launched." << llendflush;  	} +	llinfos << "Cleaning up LLProxy." << llendl; +	LLProxy::cleanupClass();  	LLMainLoopRepeater::instance().stop(); @@ -3820,6 +3864,11 @@ bool LLAppViewer::initCache()  	}  } +void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb) +{ +	LLDeferredTaskList::instance().addTask(cb); +} +  void LLAppViewer::purgeCache()  {  	LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; @@ -4413,6 +4462,9 @@ void LLAppViewer::idle()  			gAudiop->idle(max_audio_decode_time);  		}  	} + +	// Execute deferred tasks. +	LLDeferredTaskList::instance().run();  	// Handle shutdown process, for example,   	// wait for floaters to close, send quit message, diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 61ee6a7cf1..32115e0e7b 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -164,6 +164,8 @@ public:  	login_completed_signal_t mOnLoginCompleted;  	boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); }  +	void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle +  	void purgeCache(); // Clear the local cache.   	// mute/unmute the system's master audio diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 6f71c54f79..0742250b0b 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -155,6 +155,7 @@ void LLStandardBumpmap::addstandard()  			LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id));	  		gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;  		gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); +		gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ;  		LLStandardBumpmap::sStandardBumpmapCount++;  	} @@ -1078,6 +1079,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText  			{  				src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;  				src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); +				src_image->forceToSaveRawImage(0) ;  			}  		}  	} diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index dd0b1d999c..3bcbb987f7 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -137,9 +137,9 @@ void LLFloaterPostcard::draw()  		// first set the max extents of our preview  		rect.translate(-rect.mLeft, -rect.mBottom); -		rect.mLeft += 280; +		rect.mLeft += 320;  		rect.mRight -= 10; -		rect.mTop -= 20; +		rect.mTop -= 27;  		rect.mBottom = rect.mTop - 130;  		// then fix the aspect ratio diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5fd262a720..d65928e385 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -105,6 +105,7 @@  #include "llviewermedia.h"  #include "llpluginclassmedia.h"  #include "llteleporthistorystorage.h" +#include "llproxy.h"  #include "lllogininstance.h"        // to check if logged in yet  #include "llsdserialize.h" @@ -158,7 +159,7 @@ BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask)  {  	BOOL result = TRUE; -	if(key == 'Q' && mask == MASK_CONTROL) +	if (key == 'Q' && mask == MASK_CONTROL)  	{  		result = FALSE;  	} @@ -333,16 +334,17 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)  	mCommitCallbackRegistrar.add("Pref.ClickEnablePopup",		boost::bind(&LLFloaterPreference::onClickEnablePopup, this));  	mCommitCallbackRegistrar.add("Pref.ClickDisablePopup",		boost::bind(&LLFloaterPreference::onClickDisablePopup, this));	  	mCommitCallbackRegistrar.add("Pref.LogPath",				boost::bind(&LLFloaterPreference::onClickLogPath, this)); -	mCommitCallbackRegistrar.add("Pref.HardwareSettings",       boost::bind(&LLFloaterPreference::onOpenHardwareSettings, this));	 -	mCommitCallbackRegistrar.add("Pref.HardwareDefaults",       boost::bind(&LLFloaterPreference::setHardwareDefaults, this));	 -	mCommitCallbackRegistrar.add("Pref.VertexShaderEnable",     boost::bind(&LLFloaterPreference::onVertexShaderEnable, this));	 -	mCommitCallbackRegistrar.add("Pref.WindowedMod",            boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));	 -	mCommitCallbackRegistrar.add("Pref.UpdateSliderText",       boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2));	 -	mCommitCallbackRegistrar.add("Pref.QualityPerformance",     boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));	 +	mCommitCallbackRegistrar.add("Pref.HardwareSettings",		boost::bind(&LLFloaterPreference::onOpenHardwareSettings, this)); +	mCommitCallbackRegistrar.add("Pref.HardwareDefaults",		boost::bind(&LLFloaterPreference::setHardwareDefaults, this)); +	mCommitCallbackRegistrar.add("Pref.VertexShaderEnable",		boost::bind(&LLFloaterPreference::onVertexShaderEnable, this)); +	mCommitCallbackRegistrar.add("Pref.WindowedMod",			boost::bind(&LLFloaterPreference::onCommitWindowedMode, this)); +	mCommitCallbackRegistrar.add("Pref.UpdateSliderText",		boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2)); +	mCommitCallbackRegistrar.add("Pref.QualityPerformance",		boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));  	mCommitCallbackRegistrar.add("Pref.applyUIColor",			boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2));  	mCommitCallbackRegistrar.add("Pref.getUIColor",				boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));  	mCommitCallbackRegistrar.add("Pref.MaturitySettings",		boost::bind(&LLFloaterPreference::onChangeMaturity, this));  	mCommitCallbackRegistrar.add("Pref.BlockList",				boost::bind(&LLFloaterPreference::onClickBlockList, this)); +	mCommitCallbackRegistrar.add("Pref.Proxy",					boost::bind(&LLFloaterPreference::onClickProxySettings, this));  	sSkin = gSavedSettings.getString("SkinCurrent"); @@ -457,7 +459,7 @@ BOOL LLFloaterPreference::postBuild()  void LLFloaterPreference::onBusyResponseChanged()  {  	// set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise -	if(LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) +	if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString())  	{  		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE );  	} @@ -539,7 +541,7 @@ void LLFloaterPreference::apply()  	LLViewerMedia::setCookiesEnabled(getChild<LLUICtrl>("cookies_enabled")->getValue()); -	if(hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port")) +	if (hasChild("web_proxy_enabled") &&hasChild("web_proxy_editor") && hasChild("web_proxy_port"))  	{  		bool proxy_enable = getChild<LLUICtrl>("web_proxy_enabled")->getValue();  		std::string proxy_address = getChild<LLUICtrl>("web_proxy_editor")->getValue(); @@ -552,13 +554,13 @@ void LLFloaterPreference::apply()  	gSavedSettings.setBOOL("PlainTextChatHistory", getChild<LLUICtrl>("plain_text_chat_history")->getValue().asBoolean()); -	if(mGotPersonalInfo) +	if (mGotPersonalInfo)  	{   //		gSavedSettings.setString("BusyModeResponse2", std::string(wstring_to_utf8str(busy_response)));  		bool new_im_via_email = getChild<LLUICtrl>("send_im_to_email")->getValue().asBoolean();  		bool new_hide_online = getChild<LLUICtrl>("online_visibility")->getValue().asBoolean();		 -		if((new_im_via_email != mOriginalIMViaEmail) +		if ((new_im_via_email != mOriginalIMViaEmail)  			||(new_hide_online != mOriginalHideOnlineStatus))  		{  			// This hack is because we are representing several different 	  @@ -566,13 +568,13 @@ void LLFloaterPreference::apply()  			// can only select between 2 values, we represent it as a 	   			// checkbox. This breaks down a little bit for liaisons, but 	   			// works out in the end. 	  -			if(new_hide_online != mOriginalHideOnlineStatus) 	  -			{ 	  -				if(new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN; +			if (new_hide_online != mOriginalHideOnlineStatus) +			{ +				if (new_hide_online) mDirectoryVisibility = VISIBILITY_HIDDEN;  				else mDirectoryVisibility = VISIBILITY_DEFAULT;  			 //Update showonline value, otherwise multiple applys won't work  				mOriginalHideOnlineStatus = new_hide_online; -			} 	  +			}  			gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);  		}  	} @@ -616,6 +618,11 @@ void LLFloaterPreference::cancel()  		updateDoubleClickControls();  		mDoubleClickActionDirty = false;  	} +	LLFloaterPreferenceProxy * advanced_proxy_settings = LLFloaterReg::findTypedInstance<LLFloaterPreferenceProxy>("prefs_proxy"); +	if (advanced_proxy_settings) +	{ +		advanced_proxy_settings->cancel(); +	}  }  void LLFloaterPreference::onOpen(const LLSD& key) @@ -799,7 +806,7 @@ void LLFloaterPreference::onBtnCancel()  void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_via_email, const std::string& email)  {  	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); -	if(instance) +	if (instance)  	{  		instance->setPersonalInfo(visibility, im_via_email, email);	  	} @@ -809,7 +816,7 @@ void LLFloaterPreference::updateUserInfo(const std::string& visibility, bool im_  void LLFloaterPreference::refreshEnabledGraphics()  {  	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); -	if(instance) +	if (instance)  	{  		instance->refresh();  		//instance->refreshEnabledState(); @@ -1096,7 +1103,7 @@ void LLFloaterPreference::disableUnavailableSettings()  	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");  	// if vertex shaders off, disable all shader related products -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))  	{  		ctrl_shader_enable->setEnabled(FALSE);  		ctrl_shader_enable->setValue(FALSE); @@ -1127,7 +1134,7 @@ void LLFloaterPreference::disableUnavailableSettings()  	}  	// disabled windlight -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))  	{  		ctrl_wind_light->setEnabled(FALSE);  		ctrl_wind_light->setValue(FALSE); @@ -1164,28 +1171,28 @@ void LLFloaterPreference::disableUnavailableSettings()  	}  	// disabled deferred SSAO -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO"))  	{  		ctrl_ssao->setEnabled(FALSE);  		ctrl_ssao->setValue(FALSE);  	}  	// disabled deferred shadows -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderShadowDetail"))  	{  		ctrl_shadows->setEnabled(FALSE);  		ctrl_shadows->setValue(0);  	}  	// disabled reflections -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail"))  	{  		ctrl_reflections->setEnabled(FALSE);  		ctrl_reflections->setValue(FALSE);  	}  	// disabled av -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarVP"))  	{  		ctrl_avatar_vp->setEnabled(FALSE);  		ctrl_avatar_vp->setValue(FALSE); @@ -1208,14 +1215,14 @@ void LLFloaterPreference::disableUnavailableSettings()  	}  	// disabled cloth -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))  	{  		ctrl_avatar_cloth->setEnabled(FALSE);  		ctrl_avatar_cloth->setValue(FALSE);  	}  	// disabled impostors -	if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors")) +	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors"))  	{  		ctrl_avatar_impostors->setEnabled(FALSE);  		ctrl_avatar_impostors->setValue(FALSE); @@ -1381,12 +1388,12 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im  	mOriginalIMViaEmail = im_via_email;  	mDirectoryVisibility = visibility; -	if(visibility == VISIBILITY_DEFAULT) +	if (visibility == VISIBILITY_DEFAULT)  	{  		mOriginalHideOnlineStatus = false;  		getChildView("online_visibility")->setEnabled(TRUE); 	   	} -	else if(visibility == VISIBILITY_HIDDEN) +	else if (visibility == VISIBILITY_HIDDEN)  	{  		mOriginalHideOnlineStatus = true;  		getChildView("online_visibility")->setEnabled(TRUE); 	  @@ -1434,7 +1441,7 @@ void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name)  {  	std::string ctrl_name = name.asString(); -	if((ctrl_name =="" )|| !hasChild(ctrl_name, true)) +	if ((ctrl_name =="" )|| !hasChild(ctrl_name, true))  		return;  	LLTextBox* text_box = getChild<LLTextBox>(name.asString()); @@ -1444,7 +1451,7 @@ void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name)  void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box)  { -	if(text_box == NULL || ctrl== NULL) +	if (text_box == NULL || ctrl== NULL)  		return;  	// get range and points when text should change @@ -1457,7 +1464,7 @@ void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_b  	F32 highPoint = min + (2.0f * range / 3.0f);  	// choose the right text -	if(value < midPoint) +	if (value < midPoint)  	{  		text_box->setText(LLTrans::getString("GraphicsQualityLow"));  	}  @@ -1541,6 +1548,11 @@ void LLFloaterPreference::updateDoubleClickSettings()  	}  } +void LLFloaterPreference::onClickProxySettings() +{ +	LLFloaterReg::showInstance("prefs_proxy"); +} +  void LLFloaterPreference::updateDoubleClickControls()  {  	// check is one of double-click actions settings enabled @@ -1637,7 +1649,7 @@ BOOL LLPanelPreference::postBuild()  {  	////////////////////// PanelVoice /////////////////// -	if(hasChild("voice_unavailable")) +	if (hasChild("voice_unavailable"))  	{  		BOOL voice_disabled = gSavedSettings.getBOOL("CmdLineDisableVoice");  		getChildView("voice_unavailable")->setVisible( voice_disabled); @@ -1659,7 +1671,7 @@ BOOL LLPanelPreference::postBuild()  	} -	if(hasChild("online_visibility") && hasChild("send_im_to_email")) +	if (hasChild("online_visibility") && hasChild("send_im_to_email"))  	{  		getChild<LLUICtrl>("email_address")->setValue(getString("log_in_to_change") );  //		getChild<LLUICtrl>("busy_response")->setValue(getString("log_in_to_change"));		 @@ -1788,7 +1800,7 @@ void LLPanelPreference::cancel()  		 iter != mSavedColors.end(); ++iter)  	{  		LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>(iter->first); -		if(color_swatch) +		if (color_swatch)  		{  			color_swatch->set(iter->second);  			color_swatch->onCommit(); @@ -1832,7 +1844,7 @@ void LLPanelPreferenceGraphics::draw()  	LLButton* button_apply = findChild<LLButton>("Apply"); -	if(button_apply && button_apply->getVisible()) +	if (button_apply && button_apply->getVisible())  	{  		bool enable = hasDirtyChilds(); @@ -1852,7 +1864,7 @@ bool LLPanelPreferenceGraphics::hasDirtyChilds()  		LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview);  		if (ctrl)  		{ -			if(ctrl->isDirty()) +			if (ctrl->isDirty())  				return true;  		}  		// Push children onto the end of the work stack @@ -1908,3 +1920,188 @@ void LLPanelPreferenceGraphics::setHardwareDefaults()  	resetDirtyChilds();  	LLPanelPreference::setHardwareDefaults();  } + +LLFloaterPreferenceProxy::LLFloaterPreferenceProxy(const LLSD& key) +	: LLFloater(key), +	  mSocksSettingsDirty(false) +{ +	mCommitCallbackRegistrar.add("Proxy.OK",                boost::bind(&LLFloaterPreferenceProxy::onBtnOk, this)); +	mCommitCallbackRegistrar.add("Proxy.Cancel",            boost::bind(&LLFloaterPreferenceProxy::onBtnCancel, this)); +	mCommitCallbackRegistrar.add("Proxy.Change",            boost::bind(&LLFloaterPreferenceProxy::onChangeSocksSettings, this)); +} + +LLFloaterPreferenceProxy::~LLFloaterPreferenceProxy() +{ +} + +BOOL LLFloaterPreferenceProxy::postBuild() +{ +	LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); +	if (!socksAuth) +	{ +		return FALSE; +	} +	if (socksAuth->getSelectedValue().asString() == "None") +	{ +		getChild<LLLineEditor>("socks5_username")->setEnabled(false); +		getChild<LLLineEditor>("socks5_password")->setEnabled(false); +	} +	else +	{ +		// Populate the SOCKS 5 credential fields with protected values. +		LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); +		getChild<LLLineEditor>("socks5_username")->setValue(socks_cred->getIdentifier()["username"].asString()); +		getChild<LLLineEditor>("socks5_password")->setValue(socks_cred->getAuthenticator()["creds"].asString()); +	} + +	center(); +	return TRUE; +} + +void LLFloaterPreferenceProxy::onOpen(const LLSD& key) +{ +	saveSettings(); +} + +void LLFloaterPreferenceProxy::onClose(bool app_quitting) +{ +	if (mSocksSettingsDirty) +	{ + +		// If the user plays with the Socks proxy settings after login, it's only fair we let them know +		// it will not be updated until next restart. +		if (LLStartUp::getStartupState()>STATE_LOGIN_WAIT) +		{ +			LLNotifications::instance().add("ChangeProxySettings", LLSD(), LLSD()); +			mSocksSettingsDirty = false; // we have notified the user now be quiet again +		} +	} +} + +void LLFloaterPreferenceProxy::saveSettings() +{ +	// Save the value of all controls in the hierarchy +	mSavedValues.clear(); +	std::list<LLView*> view_stack; +	view_stack.push_back(this); +	while(!view_stack.empty()) +	{ +		// Process view on top of the stack +		LLView* curview = view_stack.front(); +		view_stack.pop_front(); + +		LLUICtrl* ctrl = dynamic_cast<LLUICtrl*>(curview); +		if (ctrl) +		{ +			LLControlVariable* control = ctrl->getControlVariable(); +			if (control) +			{ +				mSavedValues[control] = control->getValue(); +			} +		} + +		// Push children onto the end of the work stack +		for (child_list_t::const_iterator iter = curview->getChildList()->begin(); +				iter != curview->getChildList()->end(); ++iter) +		{ +			view_stack.push_back(*iter); +		} +	} +} + +void LLFloaterPreferenceProxy::onBtnOk() +{ +	// commit any outstanding text entry +	if (hasFocus()) +	{ +		LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); +		if (cur_focus && cur_focus->acceptsTextInput()) +		{ +			cur_focus->onCommit(); +		} +	} + +	// Save SOCKS proxy credentials securely if password auth is enabled +	LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); +	if (socksAuth->getSelectedValue().asString() == "UserPass") +	{ +		LLSD socks_id = LLSD::emptyMap(); +		socks_id["type"] = "SOCKS5"; +		socks_id["username"] = getChild<LLLineEditor>("socks5_username")->getValue().asString(); + +		LLSD socks_authenticator = LLSD::emptyMap(); +		socks_authenticator["type"] = "SOCKS5"; +		socks_authenticator["creds"] = getChild<LLLineEditor>("socks5_password")->getValue().asString(); + +		// Using "SOCKS5" as the "grid" argument since the same proxy +		// settings will be used for all grids and because there is no +		// way to specify the type of credential. +		LLPointer<LLCredential> socks_cred = gSecAPIHandler->createCredential("SOCKS5", socks_id, socks_authenticator); +		gSecAPIHandler->saveCredential(socks_cred, true); +	} +	else +	{ +		// Clear SOCKS5 credentials since they are no longer needed. +		LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5"); +		gSecAPIHandler->deleteCredential(socks_cred); +	} + +	closeFloater(false); +} + +void LLFloaterPreferenceProxy::onBtnCancel() +{ +	if (hasFocus()) +	{ +		LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); +		if (cur_focus && cur_focus->acceptsTextInput()) +		{ +			cur_focus->onCommit(); +		} +		refresh(); +	} + +	cancel(); +} + +void LLFloaterPreferenceProxy::cancel() +{ + +	for (control_values_map_t::iterator iter =  mSavedValues.begin(); +			iter !=  mSavedValues.end(); ++iter) +	{ +		LLControlVariable* control = iter->first; +		LLSD ctrl_value = iter->second; +		control->set(ctrl_value); +	} + +	closeFloater(); +} + +void LLFloaterPreferenceProxy::onChangeSocksSettings()  +{ +	mSocksSettingsDirty = true; + +	LLRadioGroup* socksAuth = getChild<LLRadioGroup>("socks5_auth_type"); +	if (socksAuth->getSelectedValue().asString() == "None") +	{ +		getChild<LLLineEditor>("socks5_username")->setEnabled(false); +		getChild<LLLineEditor>("socks5_password")->setEnabled(false); +	} +	else +	{ +		getChild<LLLineEditor>("socks5_username")->setEnabled(true); +		getChild<LLLineEditor>("socks5_password")->setEnabled(true); +	} + +	// Check for invalid states for the other HTTP proxy radio +	LLRadioGroup* otherHttpProxy = getChild<LLRadioGroup>("other_http_proxy_type"); +	if ((otherHttpProxy->getSelectedValue().asString() == "Socks" && +			getChild<LLCheckBoxCtrl>("socks_proxy_enabled")->get() == FALSE )||( +					otherHttpProxy->getSelectedValue().asString() == "Web" && +					getChild<LLCheckBoxCtrl>("web_proxy_enabled")->get() == FALSE ) ) +	{ +		otherHttpProxy->selectFirstItem(); +	} + +}; diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 61f2c78640..ef9bc2dd53 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -156,6 +156,7 @@ public:  	void applyResolution();  	void onChangeMaturity();  	void onClickBlockList(); +	void onClickProxySettings();  	void applyUIColor(LLUICtrl* ctrl, const LLSD& param);  	void getUIColor(LLUICtrl* ctrl, const LLSD& param); @@ -229,4 +230,33 @@ protected:  }; +class LLFloaterPreferenceProxy : public LLFloater +{ +public:  +	LLFloaterPreferenceProxy(const LLSD& key); +	~LLFloaterPreferenceProxy(); + +	/// show off our menu +	static void show(); +	void cancel(); +	 +protected: +	BOOL postBuild(); +	void onOpen(const LLSD& key); +	void onClose(bool app_quitting); +	void saveSettings(); +	void onBtnOk(); +	void onBtnCancel(); + +	void onChangeSocksSettings(); + +private: +	 +	bool mSocksSettingsDirty; +	typedef std::map<LLControlVariable*, LLSD> control_values_map_t; +	control_values_map_t mSavedValues; + +}; + +  #endif  // LL_LLPREFERENCEFLOATER_H diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp index 48be251611..9b4f146332 100644 --- a/indra/newview/llloginhandler.cpp +++ b/indra/newview/llloginhandler.cpp @@ -30,13 +30,13 @@  // viewer includes  #include "llsecapi.h" -#include "lllogininstance.h"        // to check if logged in yet -#include "llpanellogin.h"			// save_password_to_disk() +#include "lllogininstance.h"		// to check if logged in yet +#include "llpanellogin.h"  #include "llstartup.h"				// getStartupState()  #include "llslurl.h"  #include "llviewercontrol.h"		// gSavedSettings  #include "llviewernetwork.h"		// EGridInfo -#include "llviewerwindow.h"                    // getWindow() +#include "llviewerwindow.h"			// getWindow()  // library includes  #include "llmd5.h" diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index b29b3af7ca..4078eedc77 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -113,7 +113,4 @@ private:  	static BOOL		sCapslockDidNotification;  }; -std::string load_password_from_disk(void); -void save_password_to_disk(const char* hashed_password); -  #endif diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 8e4c2c56c6..0935a0005b 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -286,8 +286,8 @@ bool operator!=(const LLCertificateVector::iterator& _lhs, const LLCertificateVe  #define CRED_AUTHENTICATOR_TYPE_HASH   "hash"  //  // LLCredential - interface for credentials providing the following functionality: -// * persistance of credential information based on grid (for saving username/password) -// * serialization to an OGP identifier/authenticator pair +// * Persistence of credential information based on grid (for saving username/password) +// * Serialization to an OGP identifier/authenticator pair  //   class LLCredential  : public LLRefCount  { diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index e23b431457..fd17781a2e 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -523,6 +523,11 @@ void LLSpatialGroup::clearDrawMap()  	mDrawMap.clear();  } +BOOL LLSpatialGroup::isHUDGroup()  +{ +	return mSpatialPartition && mSpatialPartition->isHUDPartition() ;  +} +  BOOL LLSpatialGroup::isRecentlyVisible() const  {  	return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ; @@ -4155,6 +4160,10 @@ void LLSpatialGroup::drawObjectBox(LLColor4 col)  	drawBox(mObjectBounds[0], size);  } +bool LLSpatialPartition::isHUDPartition()  +{  +	return mPartitionType == LLViewerRegion::PARTITION_HUD ; +}   BOOL LLSpatialPartition::isVisible(const LLVector3& v)  { diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 54d5d36f6e..11955540c6 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -282,6 +282,7 @@ public:  	LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); +	BOOL isHUDGroup() ;  	BOOL isDead()							{ return isState(DEAD); }  	BOOL isState(U32 state) const;	  	BOOL isOcclusionState(U32 state) const	{ return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; } @@ -470,6 +471,7 @@ public:  	S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum  	BOOL isVisible(const LLVector3& v); +	bool isHUDPartition() ;  	virtual LLSpatialBridge* asBridge() { return NULL; }  	virtual BOOL isBridge() { return asBridge() != NULL; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7991233ace..749acea6c1 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -126,6 +126,7 @@  #include "llpanelgroupnotices.h"  #include "llpreview.h"  #include "llpreviewscript.h" +#include "llproxy.h"  #include "llproductinforequest.h"  #include "llsecondlifeurls.h"  #include "llselectmgr.h" @@ -386,6 +387,14 @@ bool idle_startup()  			LLNotificationsUtil::add(gViewerWindow->getInitAlert());  		} +		//------------------------------------------------- +		// Init the SOCKS 5 proxy if the user has configured +		// one. We need to do this early in case the user +		// is using SOCKS for HTTP so we get the login +		// screen and HTTP tables via SOCKS. +		//------------------------------------------------- +		LLStartUp::startLLProxy(); +  		gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());  		gSavedSettings.setS32("LastGPUClass", LLFeatureManager::getInstance()->getGPUClass()); @@ -591,7 +600,7 @@ bool idle_startup()  		}  		LL_INFOS("AppInit") << "Message System Initialized." << LL_ENDL; -		 +  		//-------------------------------------------------  		// Init audio, which may be needed for prefs dialog  		// or audio cues in connection UI. @@ -800,7 +809,21 @@ bool idle_startup()  	if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())  	{ -		//reset the values that could have come in from a slurl +		// Post login screen, we should see if any settings have changed that may +		// require us to either start/stop or change the socks proxy. As various communications +		// past this point may require the proxy to be up. +		if (!LLStartUp::startLLProxy()) +		{ +			// Proxy start up failed, we should now bail the state machine +			// startLLProxy() will have reported an error to the user +			// already, so we just go back to the login screen. The user +			// could then change the preferences to fix the issue. + +			LLStartUp::setStartupState(STATE_LOGIN_SHOW); +			return FALSE; +		} + +		// reset the values that could have come in from a slurl  		// DEV-42215: Make sure they're not empty -- gUserCredential  		// might already have been set from gSavedSettings, and it's too bad  		// to overwrite valid values with empty strings. @@ -2556,22 +2579,32 @@ void init_start_screen(S32 location_id)  	else if(!start_image_bmp->load(temp_str) )  	{  		LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL; -		return; +		gStartTexture = NULL;  	} +	else +	{ +		gStartImageWidth = start_image_bmp->getWidth(); +		gStartImageHeight = start_image_bmp->getHeight(); -	gStartImageWidth = start_image_bmp->getWidth(); -	gStartImageHeight = start_image_bmp->getHeight(); +		LLPointer<LLImageRaw> raw = new LLImageRaw; +		if (!start_image_bmp->decode(raw, 0.0f)) +		{ +			LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL; +			gStartTexture = NULL; +		} +		else +		{ +			raw->expandToPowerOfTwo(); +			gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ; +		} +	} -	LLPointer<LLImageRaw> raw = new LLImageRaw; -	if (!start_image_bmp->decode(raw, 0.0f)) +	if(gStartTexture.isNull())  	{ -		LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL; -		gStartTexture = NULL; -		return; +		gStartTexture = LLViewerTexture::sBlackImagep ; +		gStartImageWidth = gStartTexture->getWidth() ; +		gStartImageHeight = gStartTexture->getHeight() ;  	} - -	raw->expandToPowerOfTwo(); -	gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ;  } @@ -2758,6 +2791,171 @@ void LLStartUp::setStartSLURL(const LLSLURL& slurl)      }  } +/** + * Read all proxy configuration settings and set up both the HTTP proxy and + * SOCKS proxy as needed. + * + * Any errors that are encountered will result in showing the user a notification. + * When an error is encountered, + * + * @return Returns true if setup was successful, false if an error was encountered. + */ +bool LLStartUp::startLLProxy() +{ +	bool proxy_ok = true; +	std::string httpProxyType = gSavedSettings.getString("HttpProxyType"); + +	// Set up SOCKS proxy (if needed) +	if (gSavedSettings.getBOOL("Socks5ProxyEnabled")) +	{	 +		// Determine and update LLProxy with the saved authentication system +		std::string auth_type = gSavedSettings.getString("Socks5AuthType"); + +		if (auth_type.compare("UserPass") == 0) +		{ +			LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5"); +			std::string socks_user = socks_cred->getIdentifier()["username"].asString(); +			std::string socks_password = socks_cred->getAuthenticator()["creds"].asString(); + +			bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password); + +			if (!ok) +			{ +				LLNotificationsUtil::add("SOCKS_BAD_CREDS"); +				proxy_ok = false; +			} +		} +		else if (auth_type.compare("None") == 0) +		{ +			LLProxy::getInstance()->setAuthNone(); +		} +		else +		{ +			LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL; + +			// Unknown or missing setting. +			gSavedSettings.setString("Socks5AuthType", "None"); + +			// Clear the SOCKS credentials. +			LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5"); +			gSecAPIHandler->deleteCredential(socks_cred); + +			LLProxy::getInstance()->setAuthNone(); +		} + +		if (proxy_ok) +		{ +			// Start the proxy and check for errors +			// If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns. +			LLHost socks_host; +			socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); +			socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); +			int status = LLProxy::getInstance()->startSOCKSProxy(socks_host); + +			if (status != SOCKS_OK) +			{ +				LLSD subs; +				subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost"); +				subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort"); + +				std::string error_string; + +				switch(status) +				{ +					case SOCKS_CONNECT_ERROR: // TCP Fail +						error_string = "SOCKS_CONNECT_ERROR"; +						break; + +					case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection +						error_string = "SOCKS_NOT_PERMITTED"; +						break; + +					case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server +						error_string = "SOCKS_NOT_ACCEPTABLE"; +						break; + +					case SOCKS_AUTH_FAIL: // Authentication failed +						error_string = "SOCKS_AUTH_FAIL"; +						break; + +					case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed +						error_string = "SOCKS_UDP_FWD_NOT_GRANTED"; +						break; + +					case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server +						error_string = "SOCKS_HOST_CONNECT_FAILED"; +						break; + +					case SOCKS_INVALID_HOST: // Improperly formatted host address or port. +						error_string = "SOCKS_INVALID_HOST"; +						break; + +					default: +						error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened, +						LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL; +						break; +				} + +				LLNotificationsUtil::add(error_string, subs); +				proxy_ok = false; +			} +		} +	} +	else +	{ +		LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up +	} + +	if (proxy_ok) +	{ +		// Determine the HTTP proxy type (if any) +		if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled")) +		{ +			LLHost http_host; +			http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress")); +			http_host.setPort(gSavedSettings.getS32("BrowserProxyPort")); +			if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP)) +			{ +				LLSD subs; +				subs["HOST"] = http_host.getIPString(); +				subs["PORT"] = (S32)http_host.getPort(); +				LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs); +				proxy_ok = false; +			} +		} +		else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled")) +		{ +			LLHost socks_host; +			socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost")); +			socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort")); +			if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS)) +			{ +				LLSD subs; +				subs["HOST"] = socks_host.getIPString(); +				subs["PORT"] = (S32)socks_host.getPort(); +				LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs); +				proxy_ok = false; +			} +		} +		else if (httpProxyType.compare("None") == 0) +		{ +			LLProxy::getInstance()->disableHTTPProxy(); +		} +		else +		{ +			LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration."<< LL_ENDL; + +			// Set the missing or wrong configuration back to something valid. +			gSavedSettings.setString("HttpProxyType", "None"); +			LLProxy::getInstance()->disableHTTPProxy(); + +			// Leave proxy_ok alone, since this isn't necessarily fatal. +		} +	} + +	return proxy_ok; +} +  bool login_alert_done(const LLSD& notification, const LLSD& response)  {  	LLPanelLogin::giveFocus(); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index b3d9ef1dcc..99a644eb9c 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -113,6 +113,8 @@ public:  	static void setStartSLURL(const LLSLURL& slurl);   	static LLSLURL& getStartSLURL() { return sStartSLURL; }  +	static bool startLLProxy(); // Initialize the SOCKS 5 proxy +  private:  	static LLSLURL sStartSLURL; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index dd0989d608..fecc6d91bd 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -232,6 +232,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>);  	LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); +	LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>);  	LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>);  	LLFloaterReg::add("perm_prefs", "floater_perm_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPerms>);  	LLFloaterReg::add("pref_joystick", "floater_joystick.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterJoystick>); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 321d02aaf1..64aeb750c6 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1049,48 +1049,26 @@ void start_new_inventory_observer()  class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver  {  	LOG_CLASS(LLDiscardAgentOffer); +  public:  	LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) :  		LLInventoryFetchItemsObserver(object_id),  		mFolderID(folder_id),  		mObjectID(object_id) {} -	virtual ~LLDiscardAgentOffer() {} +  	virtual void done()  	{  		LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL; -		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); -		bool notify = false; -		if(trash_id.notNull() && mObjectID.notNull()) -		{ -			LLInventoryModel::update_list_t update; -			LLInventoryModel::LLCategoryUpdate old_folder(mFolderID, -1); -			update.push_back(old_folder); -			LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1); -			update.push_back(new_folder); -			gInventory.accountForUpdate(update); -			gInventory.moveObject(mObjectID, trash_id); -			LLInventoryObject* obj = gInventory.getObject(mObjectID); -			if(obj) -			{ -				// no need to restamp since this is already a freshly -				// stamped item. -				obj->updateParentOnServer(FALSE); -				notify = true; -			} -		} -		else -		{ -			LL_WARNS("Messaging") << "DiscardAgentOffer unable to find: " -					<< (trash_id.isNull() ? "trash " : "") -					<< (mObjectID.isNull() ? "object" : "") << LL_ENDL; -		} + +		// We're invoked from LLInventoryModel::notifyObservers(). +		// If we now try to remove the inventory item, it will cause a nested +		// notifyObservers() call, which won't work. +		// So defer moving the item to trash until viewer gets idle (in a moment). +		LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID));  		gInventory.removeObserver(this); -		if(notify) -		{ -			gInventory.notifyObservers(); -		}  		delete this;  	} +  protected:  	LLUUID mFolderID;  	LLUUID mObjectID; @@ -1495,7 +1473,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	LLChat chat;  	std::string log_message;  	S32 button = LLNotificationsUtil::getSelectedOption(notification, response); -	 +  	LLInventoryObserver* opener = NULL;  	LLViewerInventoryCategory* catp = NULL;  	catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID); @@ -1527,7 +1505,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	// TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:  	from_string = chatHistory_string = mFromName; -	bool busy=FALSE; +	bool busy = gAgent.getBusy();  	switch(button)  	{ @@ -1586,9 +1564,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  		}  		break; -	case IOR_BUSY: -		//Busy falls through to decline.  Says to make busy message. -		busy=TRUE;  	case IOR_MUTE:  		// MUTE falls through to decline  	case IOR_DECLINE: @@ -1734,7 +1709,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const  		from_string = chatHistory_string = mFromName;  	} -	bool busy=FALSE; +	bool busy = gAgent.getBusy();  	switch(button)  	{ @@ -1780,9 +1755,6 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const  		}	// end switch (mIM)  			break; -		case IOR_BUSY: -			//Busy falls through to decline.  Says to make busy message. -			busy=TRUE;  		case IOR_MUTE:  			// MUTE falls through to decline  		case IOR_DECLINE: @@ -2667,7 +2639,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			{  				// Until throttling is implemented, busy mode should reject inventory instead of silently  				// accepting it.  SEE SL-39554 -				info->forceResponse(IOR_BUSY); +				info->forceResponse(IOR_DECLINE);  			}  			else  			{ diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 9d09d9c01a..d8acd99953 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -57,7 +57,6 @@ enum InventoryOfferResponse  	IOR_ACCEPT,  	IOR_DECLINE,  	IOR_MUTE, -	IOR_BUSY,  	IOR_SHOW  }; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index db2dc531db..17f908d73f 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1193,6 +1193,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec  	eCacheUpdateResult result = CACHE_UPDATE_ADDED;  	if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)  	{ +		delete mImpl->mCacheMap.begin()->second ;  		mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());  		result = CACHE_UPDATE_REPLACED; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5fcc57bc91..70509f9a9f 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -66,6 +66,7 @@  // statics  LLPointer<LLViewerTexture>        LLViewerTexture::sNullImagep = NULL; +LLPointer<LLViewerTexture>        LLViewerTexture::sBlackImagep = NULL;  LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL;  LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;  LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL; @@ -295,17 +296,23 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const  void LLViewerTextureManager::init()  { -	LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); -	raw->clear(0x77, 0x77, 0x77, 0xFF); -	LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ; - -#if 1 -	LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT); -	LLViewerFetchedTexture::sDefaultImagep = imagep; +	{ +		LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3); +		raw->clear(0x77, 0x77, 0x77, 0xFF); +		LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ; +	}  	const S32 dim = 128;  	LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);  	U8* data = image_raw->getData(); +	 +	memset(data, 0, dim * dim * 3) ; +	LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE) ; + +#if 1 +	LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT); +	LLViewerFetchedTexture::sDefaultImagep = imagep; +	  	for (S32 i = 0; i<dim; i++)  	{  		for (S32 j = 0; j<dim; j++) @@ -359,6 +366,7 @@ void LLViewerTextureManager::cleanup()  	LLImageGL::sDefaultGLTexture = NULL ;  	LLViewerTexture::sNullImagep = NULL; +	LLViewerTexture::sBlackImagep = NULL;  	LLViewerFetchedTexture::sDefaultImagep = NULL;	  	LLViewerFetchedTexture::sSmokeImagep = NULL;  	LLViewerFetchedTexture::sMissingAssetImagep = NULL; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index c5b8c8923a..de528927b4 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -330,6 +330,7 @@ public:  	static BOOL sUseTextureAtlas ;  	static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects. +	static LLPointer<LLViewerTexture> sBlackImagep;	// Texture to show NOTHING (pure black)  }; diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index f0b5b50feb..6d457434b5 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -621,16 +621,20 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca  				S32 num_entries;  				success = check_read(&apr_file, &num_entries, sizeof(S32)) ; -				for (S32 i = 0; success && i < num_entries; i++) +				if(success)  				{ -					LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); -					if (!entry->getLocalID()) +					for (S32 i = 0; i < num_entries; i++)  					{ -						llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; -						delete entry ; -						success = false ; +						LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); +						if (!entry->getLocalID()) +						{ +							llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; +							delete entry ; +							success = false ; +							break ; +						} +						cache_entry_map[entry->getLocalID()] = entry;  					} -					cache_entry_map[entry->getLocalID()] = entry;  				}  			}  		}		 diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index eb3ed3c379..528c7acbc8 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4490,6 +4490,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater());  	} +	bool hud_group = group->isHUDGroup() ;  	std::vector<LLFace*>::iterator face_iter = faces.begin();  	LLSpatialGroup::buffer_map_t buffer_map; @@ -4760,7 +4761,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  					registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY);  					registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);  				} -				else if (LLPipeline::sRenderDeferred) +				else if (LLPipeline::sRenderDeferred && !hud_group)  				{ //deferred rendering  					if (te->getFullbright())  					{ //register in post deferred fullbright shiny pass @@ -4798,7 +4799,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  				else if (fullbright || bake_sunlight)  				{ //fullbright  					registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); -					if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) +					if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && te->getBumpmap())  					{ //if this is the deferred render and a bump map is present, register in post deferred bump  						registerFace(group, facep, LLRenderPass::PASS_POST_BUMP);  					} @@ -4824,7 +4825,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  			}  			//not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 -			if (!is_alpha && !LLPipeline::sRenderDeferred) +			if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred))  			{  				llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright);  				facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index bd1d2ed7a7..f483ba5af8 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -306,19 +306,8 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)  		mCurlRequest = new LLCurlEasyRequest();  	}  	mErrorCert = NULL; -	 -	if (gSavedSettings.getBOOL("BrowserProxyEnabled")) -	{ -		mProxyAddress = gSavedSettings.getString("BrowserProxyAddress"); -		S32 port = gSavedSettings.getS32 ( "BrowserProxyPort" ); - -		// tell curl about the settings -		mCurlRequest->setoptString(CURLOPT_PROXY, mProxyAddress); -		mCurlRequest->setopt(CURLOPT_PROXYPORT, port); -		mCurlRequest->setopt(CURLOPT_PROXYTYPE, CURLPROXY_HTTP); -	} -//	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging +//	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging  	mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);  	mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);  	BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert"); diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml index 8da35e9d7f..c756661ffc 100644 --- a/indra/newview/skins/default/xui/en/floater_postcard.xml +++ b/indra/newview/skins/default/xui/en/floater_postcard.xml @@ -7,11 +7,11 @@   height="380"   layout="topleft"   min_height="380" - min_width="450" + min_width="490"   name="Postcard"   help_topic="postcard"   title="EMAIL SNAPSHOT" - width="450"> + width="490">      <floater.string       name="default_subject">          Postcard from [SECOND_LIFE]. @@ -40,7 +40,7 @@       follows="left|top"       height="20"       layout="topleft" -     left_delta="108" +     left_delta="148"       name="to_form"       top_delta="-4"       width="150" /> @@ -59,7 +59,7 @@       follows="left|top"       height="20"       layout="topleft" -     left_delta="108" +     left_delta="148"       name="from_form"       top_delta="-4"       width="150" /> @@ -78,7 +78,7 @@       follows="left|top"       height="20"       layout="topleft" -     left_delta="108" +     left_delta="148"       max_length_bytes="100"       name="name_form"       top_delta="-4" @@ -99,7 +99,7 @@       height="20"       label="Type your subject here."       layout="topleft" -     left_delta="108" +     left_delta="148"       max_length_bytes="100"       name="subject_form"       top_delta="-4" diff --git a/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml new file mode 100644 index 0000000000..449731ab89 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml @@ -0,0 +1,273 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + height="500" + layout="topleft" + name="Proxy Settings Floater" + help_topic="proxysettings" + title="Proxy Settings" + width="500"> +	<check_box +	 control_name="BrowserProxyEnabled" +	 top="38" +	 enabled="true" +	 follows="left|top" +	 height="14" +	 initial_value="false" +	 commit_callback.function="Proxy.Change" +	 label="Use HTTP Proxy for Web pages" +	 left="22" +	 mouse_opaque="true" +	 name="web_proxy_enabled" +	 radio_style="false" +	 width="400" +	 top_pad="5" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 left_delta="23" +	 layout="topleft" +	 name="Proxy location" +	 top_pad="10" +	 width="300"> +	    HTTP Proxy: +	</text> +	<line_editor +	 control_name="BrowserProxyAddress" +	 enabled_control="BrowserProxyEnabled" +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left_delta="0" +	 name="web_proxy_editor" +	 tool_tip="The DNS name or IP address of the HTTP proxy you would like to use." +	 top_pad="4" +	 width="200" /> +	<spinner +	 control_name="BrowserProxyPort" +	 enabled_control="BrowserProxyEnabled" +     decimal_digits="0" +	 follows="left|top" +	 height="23" +	 increment="1" +	 initial_value="80" +	 label="Port number:" +	 label_width="95" +	 layout="topleft" +	 left_delta="210" +	 max_val="12000" +	 min_val="10" +	 name="web_proxy_port" +	 top_delta="0" +	 tool_tip="The port of the HTTP proxy you would like to use." +	 width="145" /> +	<check_box +	 control_name="Socks5ProxyEnabled" +	 height="16" +	 label="Use SOCKS 5 Proxy for UDP traffic" +	 layout="topleft" +	 left="22" +	 name="socks_proxy_enabled" +	 top_pad="32" +	 width="256" +	 commit_callback.function="Proxy.Change" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left_delta="23" +	 name="Proxy location" +	 top_pad="10" +	 width="300"> +	    SOCKS 5 Proxy: +	</text> +	<line_editor +	 control_name="Socks5ProxyHost" +	 enabled_control="Socks5ProxyEnabled" +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left_delta="0" +	 name="socks_proxy_editor" +	 tool_tip="The DNS name or IP address of the SOCKS 5 proxy you would like to use." +	 top_pad="4" +	 width="200" +	 commit_callback.function="Proxy.Change" /> +	<spinner +	 control_name="Socks5ProxyPort" +	 enabled_control="Socks5ProxyEnabled" +	 decimal_digits="0" +	 follows="left|top" +	 height="23" +	 increment="1" +	 initial_value="80" +	 label="Port number:" +	 label_width="95" +	 layout="topleft" +	 left_delta="210" +	 max_val="12000" +	 min_val="10" +	 name="socks_proxy_port" +	 top_delta="0" +	 width="145" +	 tool_tip="The port of the SOCKS 5 proxy you would like to use." +	 commit_callback.function="Proxy.Change" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left="40" +	 name="Proxy location" +	 top_pad="15" +	 width="300"> +	    SOCKS Authentication: +	</text> +	<radio_group +	 control_name="Socks5AuthType" +	 enabled_control="Socks5ProxyEnabled" +	 height="50" +	 layout="topleft" +	 name="socks5_auth_type" +	 top_pad="10" +	 width="120" +	 commit_callback.function="Proxy.Change" > +		<radio_item +		 height="16" +		 label="No Authentication" +		 layout="topleft" +		 name="Socks5NoAuth" +		 value="None" +		 tool_tip="Socks5 proxy requires no authentication." +		 width="120" /> +		<radio_item +		 height="16" +		 label="Username/Password" +		 layout="topleft" +		 name="Socks5UserPass" +		 value="UserPass" +		 tool_tip="Socks5 proxy requires username/password authentication." +		 width="120" /> +	</radio_group> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left_delta="20" +	 top_delta="50" +	 width="200"> +	    Username: +	</text> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 left_pad="15" +	 layout="topleft" +	 width="200"> +	    Password: +	</text> +	<line_editor +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left="60" +	 name="socks5_username" +	 tool_tip="The username used to authenticate with your SOCKS 5 server" +	 top_pad="4" +	 width="200" +	 commit_callback.function="Proxy.Change" /> +	<line_editor +	 follows="left|top" +	 font="SansSerif" +	 height="23" +	 layout="topleft" +	 left_pad="15" +	 name="socks5_password" +	 tool_tip="The password used to authenticate with your SOCKS 5 server" +	 top_delta="0" +	 width="200" +	 is_password="true" +	 commit_callback.function="Proxy.Change" /> +	<text +	 type="string" +	 length="1" +	 follows="left|top" +	 height="10" +	 layout="topleft" +	 left="25" +	 name="Proxy location" +	 top_pad="18" +	 width="300"> +	   Other HTTP traffic proxy: +	</text> +	<radio_group +	 control_name="HttpProxyType" +	 name="other_http_proxy_type" +	 height="60" +	 layout="topleft" +	 top_pad="9" +	 width="120" +	 left_delta="15"  +	 commit_callback.function="Proxy.Change" > +		<radio_item +		 height="16" +		 label="Do not proxy" +		 layout="topleft" +		 name="OtherNoProxy" +		 value="None" +		 width="120" +		 tool_tip="Non-web HTTP traffic will NOT be sent to any proxy."/> +		<radio_item +		 height="16" +		 label="Use HTTP Proxy" +		 layout="topleft" +		 name="OtherHTTPProxy" +		 value="Web" +		 width="120" +		 enabled_control="BrowserProxyEnabled" +		 tool_tip="Non-web HTTP will be sent through the configured Web proxy." /> +		<radio_item +		 height="16" +		 label="Use SOCKS 5 Proxy" +		 layout="topleft" +		 name="OtherSocksProxy" +		 value="Socks" +		 width="120" +		 enabled_control="Socks5ProxyEnabled" +		 tool_tip="Non-web HTTP traffic will be sent through the configured Socks 5 proxy."/> +	</radio_group> +	<button +	 follows="left|top" +	 height="22" +	 label="OK" +	 label_selected="OK" +	 layout="topleft" +	 left="282" +	 name="OK" +	 top_pad="36" +	 width="90" +	 commit_callback.function="Proxy.OK" /> +	<button +	 follows="left|top" +	 height="22" +	 label="Cancel" +	 label_selected="Cancel" +	 layout="topleft" +	 left_pad="10" +	 name="Cancel" +	 top_delta="0" +	 width="90" +	 commit_callback.function="Proxy.Cancel" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c9ccd44b83..104bcaf7d0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -7157,6 +7157,138 @@ Click and drag anywhere on the world to rotate your view    </notification>    <notification +   icon="alertmodal.tga" +   name="SOCKS_NOT_PERMITTED" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the connection, not allowed by rule set. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_CONNECT_ERROR" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the connection, could not open TCP channel. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/>	  +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_NOT_ACCEPTABLE" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the selected authentication system. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_AUTH_FAIL" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" reported your credentials are invalid. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_UDP_FWD_NOT_GRANTED" +   type="alertmodal"> +	The SOCKS 5 proxy "[HOST]:[PORT]" refused the UDP associate request. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="SOCKS_HOST_CONNECT_FAILED" +   type="alertmodal"> +	Could not connect to SOCKS 5 proxy server "[HOST]:[PORT]". +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> +   +  <notification +   icon="alertmodal.tga" +   name="SOCKS_UNKNOWN_STATUS" +   type="alertmodal"> +	Unknown proxy error with server "[HOST]:[PORT]". +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> +   +  <notification +   icon="alertmodal.tga" +   name="SOCKS_INVALID_HOST" +   type="alertmodal"> +	Invalid SOCKS proxy address or port "[HOST]:[PORT]". +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> +   +  <notification +   icon="alertmodal.tga" +   name="SOCKS_BAD_CREDS" +   type="alertmodal"> +	Invalid SOCKS 5 username or password. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> +   +  <notification +   icon="alertmodal.tga" +   name="PROXY_INVALID_HTTP_HOST" +   type="alertmodal"> +    Invalid HTTP proxy address or port "[HOST]:[PORT]". +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="PROXY_INVALID_SOCKS_HOST" +   type="alertmodal"> +	Invalid SOCKS proxy address or port "[HOST]:[PORT]". +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification +   icon="alertmodal.tga" +   name="ChangeProxySettings" +   type="alert"> +	Proxy settings take effect after you restart [APP_NAME]. +	<tag>fail</tag> +   <usetemplate +     name="okbutton" +     yestext="OK"/> +  </notification> + +  <notification    name="AuthRequest"    type="browser">  The site at '<nolink>[HOST_NAME]</nolink>' in realm '[REALM]' requires a user name and password. diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index 9e70706603..beea53437a 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -52,7 +52,7 @@               multi_select="true"               name="list_attachments"               top="0" -             width="311"/> +			 width="311" />          </accordion_tab>          <accordion_tab           layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 30be5bc853..47236c1a48 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -139,7 +139,7 @@       height="16"       label="Add datestamp to log file name."       layout="topleft" -     left_detla="5" +     left_delta="5"       name="logfile_name_datestamp"       top_pad="10"       width="350"/> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index e639f0dc9d..a7078ce2e1 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -70,7 +70,7 @@     layout="topleft"     left="77"     name="connection_port_enabled" -   top_pad="20" +   top_pad="10"     width="256">      <check_box.commit_callback       function="Notification.Show" @@ -79,7 +79,7 @@    <spinner     control_name="ConnectionPort"     enabled_control="ConnectionPortEnabled" - decimal_digits="0" +   decimal_digits="0"     follows="left|top"     height="23"     increment="1" @@ -195,60 +195,6 @@      name="media_popup_enabled"      width="400"                 top_pad="5"/> -  <check_box -    top_delta="4" -    enabled="true" -    follows="left|top" -    height="14" -    initial_value="false" -    control_name="BrowserProxyEnabled" -    label="Enable Web Proxy" -    left_delta="0" -    mouse_opaque="true" -    name="web_proxy_enabled" -    radio_style="false" -    width="400"           top_pad="5"/> -  <text -   type="string" -   length="1" -   follows="left|top" -   height="10" -   layout="topleft" -   left_delta="20" -   name="Proxy location" -   top_delta="16" -   width="300"> -    Proxy location: -  </text> -  <line_editor -   control_name="BrowserProxyAddress" -   enabled_control="BrowserProxyEnabled" - follows="left|top" -   font="SansSerif" -   height="23" -   layout="topleft" -   left_delta="0" -   name="web_proxy_editor" -   tool_tip="The name or IP address of the proxy you would like to use" -   top_pad="4" -   width="200" /> -  <spinner -   control_name="BrowserProxyPort" -   enabled_control="BrowserProxyEnabled" - decimal_digits="0" -   follows="left|top" -   height="23" -   increment="1" -   initial_value="80" -   label="Port number:" -   label_width="95" -   layout="topleft" -   left_delta="210" -   max_val="12000" -   min_val="10" -   name="web_proxy_port" -   top_delta="0" -   width="145" />    <text       type="string"       length="1" @@ -286,4 +232,31 @@           name="Install_manual"           value="0" />    </combo_box> +  <text +     type="string" +     length="1" +     follows="left|top" +     height="10" +     layout="topleft" +     left="30" +     name="Proxy Settings:" +     mouse_opaque="false" +     top_pad="5" +     width="300"> +		Proxy Settings: +  </text> +  <button +	label="Adjust proxy settings" +    follows="left|top" +    height="23" +	width="140"  +    label_selected="Browse" +    layout="topleft" +    left_delta="50" +    name="set_proxy" +    top_pad="5" +    > +		<button.commit_callback +		  function="Pref.Proxy" /> +  </button>  </panel> | 
