diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index bb64152407e56748222303fc31192d557dd3234d..c35799bbb91761845f1ca616a1c3e87ffefdc7a6 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 4a42241c4f2b5a10d058deee993085ae8940d249..b3e604f8e83f177c6a2285c524fea201b7e30bbb 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/llsingleton.h b/indra/llcommon/llsingleton.h
index 7aee1bb85fc3eb14e6e352a0afca4faf9c887b59..00757be27744c29f78b80aa72897500d0cff7553 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -100,12 +100,6 @@ class LLSingleton : private boost::noncopyable
 		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 @@ class LLSingleton : private boost::noncopyable
 
 		~SingletonInstanceData()
 		{
-			deleteSingleton();
+			SingletonInstanceData& data = getData();
+			if (data.mInitState != DELETED)
+			{
+				deleteSingleton();
+			}
 		}
 	};
 	
@@ -132,6 +130,14 @@ class LLSingleton : private boost::noncopyable
 		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/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index c5f82cf0527dd7c9c454d71d5345323e834ded07..0f40a670fad223de66193721b78c33f323ca5d69 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 1a86a69a045f685ce5a1bb1000df7042c75c0eea..bfdf49c74b520774e42090148bc181a5f3c80964 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 f7518c8e5c2f9c42116d0d5e44fdd24bf88de7d8..5ab4dc35b91e3ea65bf27166a95e22756ba199f8 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -187,6 +187,122 @@ class LLCurl
 	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 @@ class LLCurlEasyRequest
 	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 @@ class LLCurlEasyRequest
 	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 5a38b7fd9f41836a0b5216058d3f402597829957..2bca517e97ac9d4870703a8a2ec9772882f64eae 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 0e5206a520cb9d19cd42d33ed52cab5c7301d516..dd4e3a63007d56753fc8dd7b52df8a902a84951d 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 b717e321bfe9eef182eba707001dc171837c6c03..ee9379f20585f0d1407984a4620a770f8a92ae80 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 e0f6c1e34d0ea15be627cb718f64f171cf506491..be0f7dfcc655e1e47ac2ccdf8f967037ac4458a8 100644
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -145,13 +145,6 @@ class LLSocket
 	 */
 	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 @@ class LLSocket
 	 */
 	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 8999dec64a7793b6df21346b069e606b9994f8d7..7628984de4cc0c53b90c808b1c01b1935b6de5ea 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 e6409d20488270f0f6aff5cd636f119fd42fb6a4..7edcc834db83338ec72be7523a3607cb0e582a51 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 @@ class LLPacketRing
 
 	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 0000000000000000000000000000000000000000..3f4a6accbf625a0ab7b1c684afeeb916db8a6f4a
--- /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 0000000000000000000000000000000000000000..29e7e285679bc9f035e39cafb8b1588c65387b27
--- /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 e8e35d00a21aa5808c6e5b35047e007751fc66f1..d5400e41696c3e46002031564846e269edf5228e 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 97611c3b5198f4f8ee34b956d63afb724b834bd1..85aef5da003c2bfb3e40c4f567b73a3c2665fbf7 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 9f4f5c5821272ba5fde05c2932220a74cbd5c7c8..0f2437479df8bdd861091fd913a49705de931eef 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/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h
index 752c7df7eee8e52ff3d5392a35c99e2026c349bf..899cc3a326304e7aecd40c4e5dcd21b0ba59fe78 100644
--- a/indra/llui/llfunctorregistry.h
+++ b/indra/llui/llfunctorregistry.h
@@ -103,7 +103,7 @@ class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> >
 		}
 		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 @@ class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> >
 
 	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 7c0173128296cb8a6c506386dd489b686118a6a3..30e0b86a5a858dc6c01318d3531c81d1dd344329 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>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d12b971bde9c174be71bfff66a56efe9904fd3c9..9b29d69ccebe4d9e3fbd47c029b8e865f8b2aa65 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"
@@ -1840,6 +1841,8 @@ bool LLAppViewer::cleanup()
 		LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
 		llinfos << "File launched." << llendflush;
 	}
+	llinfos << "Cleaning up LLProxy." << llendl;
+	LLProxy::cleanupClass();
 
 	LLMainLoopRepeater::instance().stop();
 
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 5fd262a72019b550b898b38145b23c191b9215db..d65928e3859fc31ce650155d672db2249d4a8f1f 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 61f2c786401cc02331ba63ca556422835f7ebc7e..ef9bc2dd5322313ef4f4d7da940ba92527c63440 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -156,6 +156,7 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver
 	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 @@ class LLPanelPreferenceGraphics : public LLPanelPreference
 	
 };
 
+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 48be2516115fb94c25bfd765c0372f6161547992..9b4f146332e84b6ea35c3be88e31537d1fe696c6 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 b29b3af7ca753881de967a53903f0f41393852df..4078eedc774030fb78ce8ba2d69ceeb49bbc40e4 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -113,7 +113,4 @@ class LLPanelLogin:
 	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 8e4c2c56c6d50b23830db5de9d987d858ea4226d..0935a0005b4ed5907be5f7dd261377044580d2b2 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/llstartup.cpp b/indra/newview/llstartup.cpp
index 880b43740478d7c695c9172e1d42b4a238c7bde9..749acea6c106bc0bb50913af983298865a99ddd3 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.
@@ -2768,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 b3d9ef1dcc7805b9a3003ba87fe70c42d3f51c2f..99a644eb9cfa275ba49cf49cc1ec2497380cd70f 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -113,6 +113,8 @@ class LLStartUp
 	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 dd0989d608e9df61902c3be5ab93ab77d78169c8..fecc6d91bd81855e89f1f10361067ce19689ed0a 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/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index bd1d2ed7a7b7e325eb625a50048afcefc6239eee..f483ba5af8d5089c6d0ee3127dd30da9d64f0b48 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_preferences_proxy.xml b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..449731ab8906ad9c5811e3bb2e4e478163aa78f2
--- /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 c9ccd44b83166d24282898d31111ffb08ac37ee8..104bcaf7d035b3bde4f7f9c5ada2ae2d507e2c7f 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -7156,6 +7156,138 @@ Click and drag anywhere on the world to rotate your view
     </form>
   </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">
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 9e70706603cafe8f459d1a71445cf03b80097d33..beea53437a88254b521f235309bddf340eab2255 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 30be5bc8533560aad1e3560dbad97af38e78401e..47236c1a48b38bfb322d0e4e947bcfe8a020516f 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 e639f0dc9dd7abf1b66b391975591bfa1f7fe4e0..a7078ce2e106cf8ddd2d46a0da0cf86e0f9200c0 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>