diff --git a/.hgtags b/.hgtags
index c25727650bf7ff2a2f783dcf6f027f3aa0634ea4..cc9e7fc2c79a159787b122088e2c882a68f31992 100644
--- a/.hgtags
+++ b/.hgtags
@@ -181,6 +181,13 @@ f2412ecd6740803ea9452f1d17fd872e263a0df7 3.0.2-start
 1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release
 42784bf50fa01974bada2a1af3892ee09c93fcda DRTVWR-83_3.0.2-beta1
 42784bf50fa01974bada2a1af3892ee09c93fcda 3.0.2-beta1
+e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e DRTVWR-86_3.0.2-beta2
+e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e 3.0.2-beta2
+b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
 1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-78_3.0.0-release
 0000000000000000000000000000000000000000 DRTVWR-78_3.0.0-release
 1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
+6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1
+6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 3.0.3-beta1
+61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2
+61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2
diff --git a/autobuild.xml b/autobuild.xml
index 6872af0661e80bb0f297a25de5d54c612de01867..e5c6b83037782ddffd1ac14a2c1ec297b188d304 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1110,9 +1110,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>0db10480362168f075c2af0ae302cb74</string>
+              <string>362654a472ef7368d4c803ae3fb89d95</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110707.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/238959/arch/Darwin/installer/llconvexdecomposition-0.1-darwin-20110819.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -1122,9 +1122,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>f3c667dc159c0537a9122ce6e72e16db</string>
+              <string>c7801d899daec5338fbe95053255b7e7</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110707.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/238959/arch/Linux/installer/llconvexdecomposition-0.1-linux-20110819.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -1134,9 +1134,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>46cac4d667446bbbc9b5023f2848a5ac</string>
+              <string>6ecf2f85f03c5ae87fe45769566a5660</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/234943/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110707.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-llconvexdecomposition/rev/238959/arch/CYGWIN/installer/llconvexdecomposition-0.1-windows-20110819.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1158,9 +1158,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>bc1388fc28dbb3bba1fe7cb8d09f49b4</string>
+              <string>a5f53e09f67271fd50f1131ffdda9d27</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/227399/arch/Darwin/installer/llconvexdecompositionstub-0.3-darwin-20110421.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/238958/arch/Darwin/installer/llconvexdecompositionstub-0.3-darwin-20110819.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -1170,9 +1170,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>3295bd4a0514b7c15dda9044f40c175e</string>
+              <string>0006a964f1497f55a5f181b7042d2d22</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/227399/arch/Linux/installer/llconvexdecompositionstub-0.3-linux-20110422.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/238958/arch/Linux/installer/llconvexdecompositionstub-0.3-linux-20110819.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -1182,9 +1182,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>92f1dff3249024c1534b55343ed79ea3</string>
+              <string>b859e7e3bb03ebb467f0309f46422995</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/227399/arch/CYGWIN/installer/llconvexdecompositionstub-0.3-windows-20110421.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llconvexdecompositionstub/rev/238958/arch/CYGWIN/installer/llconvexdecompositionstub-0.3-windows-20110819.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
@@ -1907,12 +1907,12 @@
             <map>
               <key>build</key>
               <map>
+                <key>command</key>
+                <string>xcodebuild</string>
                 <key>filters</key>
                 <array>
                   <string>setenv</string>
                 </array>
-                <key>command</key>
-                <string>xcodebuild</string>
                 <key>options</key>
                 <array>
                   <string>-configuration Debug</string>
@@ -1961,12 +1961,12 @@
             <map>
               <key>build</key>
               <map>
+                <key>command</key>
+                <string>xcodebuild</string>
                 <key>filters</key>
                 <array>
                   <string>setenv</string>
                 </array>
-                <key>command</key>
-                <string>xcodebuild</string>
                 <key>options</key>
                 <array>
                   <string>-configuration RelWithDebInfo</string>
@@ -2017,12 +2017,12 @@
             <map>
               <key>build</key>
               <map>
+                <key>command</key>
+                <string>xcodebuild</string>
                 <key>filters</key>
                 <array>
                   <string>setenv</string>
                 </array>
-                <key>command</key>
-                <string>xcodebuild</string>
                 <key>options</key>
                 <array>
                   <string>-configuration Release</string>
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 0368cd1ff0152f0eb8beaf565573ab05ceee2d28..55a3aaf1f464c94000c8921dc6ea0f6212966c84 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -563,6 +563,7 @@ Jonathan Yap
 	STORM-1313
 	STORM-899
 	STORM-1273
+	STORM-1276
 	STORM-1462
 	STORM-1459
 Kadah Coba
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/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index b4891eba67986985601e44dfa3bdaa38c8261456..afb714c71c5882ed742c5b6aa7b8aca1da3da80c 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -92,7 +92,7 @@ public:
 	public:
 		typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t;
 
-		key_iter(typename InstanceMap::iterator& it)
+		key_iter(typename InstanceMap::iterator it)
 			:	mIterator(it)
 		{
 			++sIterationNestDepth;
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 7aee1bb85fc3eb14e6e352a0afca4faf9c887b59..00757be27744c29f78b80aa72897500d0cff7553 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -100,12 +100,6 @@ private:
 		DELETED
 	} EInitState;
 	
-	static void deleteSingleton()
-	{
-		delete getData().mSingletonInstance;
-		getData().mSingletonInstance = NULL;
-	}
-	
 	// stores pointer to singleton instance
 	// and tracks initialization state of singleton
 	struct SingletonInstanceData
@@ -120,7 +114,11 @@ private:
 
 		~SingletonInstanceData()
 		{
-			deleteSingleton();
+			SingletonInstanceData& data = getData();
+			if (data.mInitState != DELETED)
+			{
+				deleteSingleton();
+			}
 		}
 	};
 	
@@ -132,6 +130,14 @@ public:
 		data.mInitState = DELETED;
 	}
 
+	// Can be used to control when the singleton is deleted.  Not normally needed.
+	static void deleteSingleton()
+	{
+		delete getData().mSingletonInstance;
+		getData().mSingletonInstance = NULL;
+		getData().mInitState = DELETED;
+	}
+
 	static SingletonInstanceData& getData()
 	{
 		// this is static to cache the lookup results
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index fa2b3bff361c6ed7b57637f829bcf5bc75360187..64225b859bc5473033605768a3145fad4fa61efa 100755
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -29,7 +29,7 @@
 
 const S32 LL_VERSION_MAJOR = 3;
 const S32 LL_VERSION_MINOR = 0;
-const S32 LL_VERSION_PATCH = 2;
+const S32 LL_VERSION_PATCH = 3;
 const S32 LL_VERSION_BUILD = 0;
 
 const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
index 3caf49aa6e2a71fa9ea8d7696dd637a279bb59ad..80b35bbdc38981ba3f4eb4670c35157d95031aed 100644
--- a/indra/llcommon/tests/llinstancetracker_test.cpp
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -90,79 +90,79 @@ namespace tut
         ensure_equals(Keyed::instanceCount(), 0);
     }
 
-  //  template<> template<>
-  //  void object::test<2>()
-  //  {
-  //      ensure_equals(Unkeyed::instanceCount(), 0);
-  //      {
-  //          Unkeyed one;
-  //          ensure_equals(Unkeyed::instanceCount(), 1);
-  //          Unkeyed* found = Unkeyed::getInstance(&one);
-  //          ensure_equals(found, &one);
-  //          {
-  //              boost::scoped_ptr<Unkeyed> two(new Unkeyed);
-  //              ensure_equals(Unkeyed::instanceCount(), 2);
-  //              Unkeyed* found = Unkeyed::getInstance(two.get());
-  //              ensure_equals(found, two.get());
-  //          }
-  //          ensure_equals(Unkeyed::instanceCount(), 1);
-  //      }
-  //      ensure_equals(Unkeyed::instanceCount(), 0);
-  //  }
+    template<> template<>
+    void object::test<2>()
+    {
+        ensure_equals(Unkeyed::instanceCount(), 0);
+        {
+            Unkeyed one;
+            ensure_equals(Unkeyed::instanceCount(), 1);
+            Unkeyed* found = Unkeyed::getInstance(&one);
+            ensure_equals(found, &one);
+            {
+                boost::scoped_ptr<Unkeyed> two(new Unkeyed);
+                ensure_equals(Unkeyed::instanceCount(), 2);
+                Unkeyed* found = Unkeyed::getInstance(two.get());
+                ensure_equals(found, two.get());
+            }
+            ensure_equals(Unkeyed::instanceCount(), 1);
+        }
+        ensure_equals(Unkeyed::instanceCount(), 0);
+    }
 
-  //  template<> template<>
-  //  void object::test<3>()
-  //  {
-  //      Keyed one("one"), two("two"), three("three");
-  //      // We don't want to rely on the underlying container delivering keys
-  //      // in any particular order. That allows us the flexibility to
-  //      // reimplement LLInstanceTracker using, say, a hash map instead of a
-  //      // std::map. We DO insist that every key appear exactly once.
-  //      typedef std::vector<std::string> StringVector;
-  //      StringVector keys(Keyed::beginKeys(), Keyed::endKeys());
-  //      std::sort(keys.begin(), keys.end());
-  //      StringVector::const_iterator ki(keys.begin());
-  //      ensure_equals(*ki++, "one");
-  //      ensure_equals(*ki++, "three");
-  //      ensure_equals(*ki++, "two");
-  //      // Use ensure() here because ensure_equals would want to display
-  //      // mismatched values, and frankly that wouldn't help much.
-  //      ensure("didn't reach end", ki == keys.end());
+    template<> template<>
+    void object::test<3>()
+    {
+        Keyed one("one"), two("two"), three("three");
+        // We don't want to rely on the underlying container delivering keys
+        // in any particular order. That allows us the flexibility to
+        // reimplement LLInstanceTracker using, say, a hash map instead of a
+        // std::map. We DO insist that every key appear exactly once.
+        typedef std::vector<std::string> StringVector;
+        StringVector keys(Keyed::beginKeys(), Keyed::endKeys());
+        std::sort(keys.begin(), keys.end());
+        StringVector::const_iterator ki(keys.begin());
+        ensure_equals(*ki++, "one");
+        ensure_equals(*ki++, "three");
+        ensure_equals(*ki++, "two");
+        // Use ensure() here because ensure_equals would want to display
+        // mismatched values, and frankly that wouldn't help much.
+        ensure("didn't reach end", ki == keys.end());
 
-  //      // Use a somewhat different approach to order independence with
-  //      // beginInstances(): explicitly capture the instances we know in a
-  //      // set, and delete them as we iterate through.
-  //      typedef std::set<Keyed*> InstanceSet;
-  //      InstanceSet instances;
-  //      instances.insert(&one);
-  //      instances.insert(&two);
-  //      instances.insert(&three);
-  //      for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances());
-  //           ii != iend; ++ii)
-  //      {
-  //          Keyed& ref = *ii;
-  //          ensure_equals("spurious instance", instances.erase(&ref), 1);
-  //      }
-  //      ensure_equals("unreported instance", instances.size(), 0);
-  //  }
+        // Use a somewhat different approach to order independence with
+        // beginInstances(): explicitly capture the instances we know in a
+        // set, and delete them as we iterate through.
+        typedef std::set<Keyed*> InstanceSet;
+        InstanceSet instances;
+        instances.insert(&one);
+        instances.insert(&two);
+        instances.insert(&three);
+        for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances());
+             ii != iend; ++ii)
+        {
+            Keyed& ref = *ii;
+            ensure_equals("spurious instance", instances.erase(&ref), 1);
+        }
+        ensure_equals("unreported instance", instances.size(), 0);
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        Unkeyed one, two, three;
+        typedef std::set<Unkeyed*> KeySet;
+    
+        KeySet instances;
+        instances.insert(&one);
+        instances.insert(&two);
+        instances.insert(&three);
 
-  //  template<> template<>
-  //  void object::test<4>()
-  //  {
-  //      Unkeyed one, two, three;
-  //      typedef std::set<Unkeyed*> KeySet;
-  //  
-  //      KeySet instances;
-  //      instances.insert(&one);
-  //      instances.insert(&two);
-  //      instances.insert(&three);
-	
-		//for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); ii != iend; ++ii)
-		//{
-		//	Unkeyed& ref = *ii;
-		//	ensure_equals("spurious instance", instances.erase(&ref), 1);
-		//}
-	
-  //      ensure_equals("unreported instance", instances.size(), 0);
-  //  }
+		for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); ii != iend; ++ii)
+		{
+			Unkeyed& ref = *ii;
+			ensure_equals("spurious instance", instances.erase(&ref), 1);
+		}
+
+        ensure_equals("unreported instance", instances.size(), 0);
+    }
 } // namespace tut
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 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 @@ private:
 	static const unsigned int MAX_REDIRECTS;
 };
 
+class LLCurl::Easy
+{
+	LOG_CLASS(Easy);
+
+private:
+	Easy();
+
+public:
+	static Easy* getEasy();
+	~Easy();
+
+	CURL* getCurlHandle() const { return mCurlEasyHandle; }
+
+	void setErrorBuffer();
+	void setCA();
+
+	void setopt(CURLoption option, S32 value);
+	// These assume the setter does not free value!
+	void setopt(CURLoption option, void* value);
+	void setopt(CURLoption option, char* value);
+	// Copies the string so that it is guaranteed to stick around
+	void setoptString(CURLoption option, const std::string& value);
+
+	void slist_append(const char* str);
+	void setHeaders();
+
+	U32 report(CURLcode);
+	void getTransferInfo(LLCurl::TransferInfo* info);
+
+	void prepRequest(const std::string& url, const std::vector<std::string>& headers, ResponderPtr, S32 time_out = 0, bool post = false);
+
+	const char* getErrorBuffer();
+
+	std::stringstream& getInput() { return mInput; }
+	std::stringstream& getHeaderOutput() { return mHeaderOutput; }
+	LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; }
+	const LLChannelDescriptors& getChannels() { return mChannels; }
+
+	void resetState();
+
+	static CURL* allocEasyHandle();
+	static void releaseEasyHandle(CURL* handle);
+
+private:
+	friend class LLCurl;
+
+	CURL*				mCurlEasyHandle;
+	struct curl_slist*	mHeaders;
+
+	std::stringstream	mRequest;
+	LLChannelDescriptors mChannels;
+	LLIOPipe::buffer_ptr_t mOutput;
+	std::stringstream	mInput;
+	std::stringstream	mHeaderOutput;
+	char				mErrorBuffer[CURL_ERROR_SIZE];
+
+	// Note: char*'s not strings since we pass pointers to curl
+	std::vector<char*>	mStrings;
+
+	ResponderPtr		mResponder;
+
+	static std::set<CURL*> sFreeHandles;
+	static std::set<CURL*> sActiveHandles;
+	static LLMutex* sHandleMutex;
+};
+
+class LLCurl::Multi : public LLThread
+{
+	LOG_CLASS(Multi);
+public:
+
+	typedef enum
+	{
+		PERFORM_STATE_READY=0,
+		PERFORM_STATE_PERFORMING=1,
+		PERFORM_STATE_COMPLETED=2
+	} ePerformState;
+
+	Multi();
+	~Multi();
+
+	Easy* allocEasy();
+	bool addEasy(Easy* easy);
+	
+	void removeEasy(Easy* easy);
+
+	S32 process();
+	void perform();
+	void doPerform();
+	
+	virtual void run();
+
+	CURLMsg* info_read(S32* msgs_in_queue);
+
+	S32 mQueued;
+	S32 mErrorCount;
+	
+	S32 mPerformState;
+
+	LLCondition* mSignal;
+	bool mQuitting;
+	bool mThreaded;
+
+private:
+	void easyFree(Easy*);
+	
+	CURLM* mCurlMultiHandle;
+
+	typedef std::set<Easy*> easy_active_list_t;
+	easy_active_list_t mEasyActiveList;
+	typedef std::map<CURL*, Easy*> easy_active_map_t;
+	easy_active_map_t mEasyActiveMap;
+	typedef std::set<Easy*> easy_free_list_t;
+	easy_free_list_t mEasyFreeList;
+};
+
 namespace boost
 {
 	void intrusive_ptr_add_ref(LLCurl::Responder* p);
@@ -243,6 +359,8 @@ public:
 	bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);
 	std::string getErrorString();
 
+	LLCurl::Easy* getEasy() const { return mEasy; }
+
 private:
 	CURLMsg* info_read(S32* queue, LLCurl::TransferInfo* info);
 	
@@ -253,4 +371,7 @@ private:
 	bool mResultReturned;
 };
 
+void check_curl_code(CURLcode code);
+void check_curl_multi_code(CURLMcode code);
+
 #endif // LL_LLCURL_H
diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp
index 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 @@ public:
 	 */
 	apr_socket_t* getSocket() const { return mSocket; }
 
-protected:
-	/** 
-	 * @brief Protected constructor since should only make sockets
-	 * with one of the two <code>create()</code> calls.
-	 */
-	LLSocket(apr_socket_t* socket, apr_pool_t* pool);
-
 	/** 
 	 * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.
 	 * @param timeout Number of microseconds to wait on this socket. Any
@@ -164,6 +157,13 @@ protected:
 	 */
 	void setNonBlocking();
 
+protected:
+	/**
+	 * @brief Protected constructor since should only make sockets
+	 * with one of the two <code>create()</code> calls.
+	 */
+	LLSocket(apr_socket_t* socket, apr_pool_t* pool);
+
 public:
 	/** 
 	 * @brief Do not call this directly.
diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp
index 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 @@ protected:
 
 	LLHost mLastSender;
 	LLHost mLastReceivingIF;
+
+
+	U8 mProxyWrappedSendBuffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
+
+private:
+	BOOL sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);
 };
 
 
diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp
new file mode 100644
index 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/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 9ca3a23d52cd4665e76c792b8c3158d65c45a1e5..7188b0fa440666cd39e62e0b0c58ae74d8d4ca4d 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1424,7 +1424,7 @@ void LLImageGL::deleteDeadTextures()
 		{
 			LLTexUnit* tex_unit = gGL.getTexUnit(i);
 
-			if (tex_unit->getCurrTexture() == tex)
+			if (tex_unit && tex_unit->getCurrTexture() == tex)
 			{
 				tex_unit->unbind(tex_unit->getCurrType());
 				stop_glerror();
@@ -1887,6 +1887,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)
 
 void LLImageGL::setCategory(S32 category) 
 {
+#if 0 //turn this off temporarily because it is not in use now.
 	if(!gAuditTexture)
 	{
 		return ;
@@ -1907,6 +1908,7 @@ void LLImageGL::setCategory(S32 category)
 			mCategory = -1 ;
 		}
 	}
+#endif
 }
 
 //for debug use 
diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h
index 752c7df7eee8e52ff3d5392a35c99e2026c349bf..899cc3a326304e7aecd40c4e5dcd21b0ba59fe78 100644
--- a/indra/llui/llfunctorregistry.h
+++ b/indra/llui/llfunctorregistry.h
@@ -103,7 +103,7 @@ public:
 		}
 		else
 		{
-			llwarns << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl;
+			lldebugs << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl;
 			return mMap[LOGFUNCTOR];
 		}
 	}
@@ -115,7 +115,7 @@ private:
 
 	static void log_functor(const LLSD& notification, const LLSD& payload)
 	{
-		llwarns << "log_functor called with payload: " << payload << llendl;
+		lldebugs << "log_functor called with payload: " << payload << llendl;
 	}
 
 	static void do_nothing(const LLSD& notification, const LLSD& payload)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 7c0173128296cb8a6c506386dd489b686118a6a3..ad9b3f63e3b86f641b9c8d50b90f94f85342d5f8 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>
@@ -1803,7 +1858,7 @@
     <key>Type</key>
     <string>Boolean</string>
     <key>Value</key>
-    <integer>0</integer>
+    <integer>1</integer>
   </map>
     <key>Cursor3D</key>
     <map>
@@ -3993,7 +4048,7 @@
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>http://search-beta.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]</string>
+      <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
     </map>
     <key>WebProfileURL</key>
     <map>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d12b971bde9c174be71bfff66a56efe9904fd3c9..6a808b5daf0aa7e94bb08040116acd95b03d2fa2 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -137,6 +137,7 @@
 #include "lltoolmgr.h"
 #include "llassetstorage.h"
 #include "llpolymesh.h"
+#include "llproxy.h"
 #include "llaudioengine.h"
 #include "llstreamingaudio.h"
 #include "llviewermenu.h"
@@ -321,6 +322,41 @@ static std::string gLaunchFileOnQuit;
 // Used on Win32 for other apps to identify our window (eg, win_setup)
 const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
 
+//-- LLDeferredTaskList ------------------------------------------------------
+
+/**
+ * A list of deferred tasks.
+ *
+ * We sometimes need to defer execution of some code until the viewer gets idle,
+ * e.g. removing an inventory item from within notifyObservers() may not work out.
+ *
+ * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration.
+ * All tasks are executed only once.
+ */
+class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList>
+{
+	LOG_CLASS(LLDeferredTaskList);
+
+	friend class LLAppViewer;
+	typedef boost::signals2::signal<void()> signal_t;
+
+	void addTask(const signal_t::slot_type& cb)
+	{
+		mSignal.connect(cb);
+	}
+
+	void run()
+	{
+		if (!mSignal.empty())
+		{
+			mSignal();
+			mSignal.disconnect_all_slots();
+		}
+	}
+
+	signal_t mSignal;
+};
+
 //----------------------------------------------------------------------------
 
 // List of entries from strings.xml to always replace
@@ -731,6 +767,23 @@ bool LLAppViewer::init()
     initThreads();
 	LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ;
 
+	// Initialize settings early so that the defaults for ignorable dialogs are
+	// picked up and then correctly re-saved after launching the updater (STORM-1268).
+	LLUI::settings_map_t settings_map;
+	settings_map["config"] = &gSavedSettings;
+	settings_map["ignores"] = &gWarningSettings;
+	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
+	settings_map["account"] = &gSavedPerAccountSettings;
+
+	LLUI::initClass(settings_map,
+		LLUIImageList::getInstance(),
+		ui_audio_callback,
+		&LLUI::sGLScaleFactor);
+	LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
+
+	LLNotifications::instance();
+	LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ;
+
     writeSystemInfo();
 
 	// Initialize updater service (now that we have an io pump)
@@ -772,19 +825,8 @@ bool LLAppViewer::init()
 	{
 		LLError::setPrintLocation(true);
 	}
-	
-	// Widget construction depends on LLUI being initialized
-	LLUI::settings_map_t settings_map;
-	settings_map["config"] = &gSavedSettings;
-	settings_map["ignores"] = &gWarningSettings;
-	settings_map["floater"] = &gSavedSettings; // *TODO: New settings file
-	settings_map["account"] = &gSavedPerAccountSettings;
 
-	LLUI::initClass(settings_map,
-		LLUIImageList::getInstance(),
-		ui_audio_callback,
-		&LLUI::sGLScaleFactor);
-	
+
 	// Setup paths and LLTrans after LLUI::initClass has been called
 	LLUI::setupPaths();
 	LLTransUtil::parseStrings("strings.xml", default_trans_args);		
@@ -1840,6 +1882,8 @@ bool LLAppViewer::cleanup()
 		LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
 		llinfos << "File launched." << llendflush;
 	}
+	llinfos << "Cleaning up LLProxy." << llendl;
+	LLProxy::cleanupClass();
 
 	LLMainLoopRepeater::instance().stop();
 
@@ -3820,6 +3864,11 @@ bool LLAppViewer::initCache()
 	}
 }
 
+void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)
+{
+	LLDeferredTaskList::instance().addTask(cb);
+}
+
 void LLAppViewer::purgeCache()
 {
 	LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
@@ -4413,6 +4462,9 @@ void LLAppViewer::idle()
 			gAudiop->idle(max_audio_decode_time);
 		}
 	}
+
+	// Execute deferred tasks.
+	LLDeferredTaskList::instance().run();
 	
 	// Handle shutdown process, for example, 
 	// wait for floaters to close, send quit message,
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 61ee6a7cf14072b2af6bf713c1eebb36832abfa0..32115e0e7b9418386f32e26e32c9453d6c2e6376 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -164,6 +164,8 @@ public:
 	login_completed_signal_t mOnLoginCompleted;
 	boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); } 
 
+	void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle
+
 	void purgeCache(); // Clear the local cache. 
 	
 	// mute/unmute the system's master audio
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 6f71c54f793202ae485cd443b846b145552e9af8..0742250b0b995b973cf0a5debad9eba4e139e9e4 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -155,6 +155,7 @@ void LLStandardBumpmap::addstandard()
 			LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id));	
 		gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
 		gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL );
+		gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ;
 		LLStandardBumpmap::sStandardBumpmapCount++;
 	}
 
@@ -1078,6 +1079,7 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
 			{
 				src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
 				src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
+				src_image->forceToSaveRawImage(0) ;
 			}
 		}
 	}
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index dd0b1d999c978ebe379ead3685cc4afdd1941d05..3bcbb987f750eec897a7aa6145fea62790452e45 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -137,9 +137,9 @@ void LLFloaterPostcard::draw()
 
 		// first set the max extents of our preview
 		rect.translate(-rect.mLeft, -rect.mBottom);
-		rect.mLeft += 280;
+		rect.mLeft += 320;
 		rect.mRight -= 10;
-		rect.mTop -= 20;
+		rect.mTop -= 27;
 		rect.mBottom = rect.mTop - 130;
 
 		// then fix the aspect ratio
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 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 @@ public:
 	void applyResolution();
 	void onChangeMaturity();
 	void onClickBlockList();
+	void onClickProxySettings();
 	void applyUIColor(LLUICtrl* ctrl, const LLSD& param);
 	void getUIColor(LLUICtrl* ctrl, const LLSD& param);
 	
@@ -229,4 +230,33 @@ protected:
 	
 };
 
+class LLFloaterPreferenceProxy : public LLFloater
+{
+public: 
+	LLFloaterPreferenceProxy(const LLSD& key);
+	~LLFloaterPreferenceProxy();
+
+	/// show off our menu
+	static void show();
+	void cancel();
+	
+protected:
+	BOOL postBuild();
+	void onOpen(const LLSD& key);
+	void onClose(bool app_quitting);
+	void saveSettings();
+	void onBtnOk();
+	void onBtnCancel();
+
+	void onChangeSocksSettings();
+
+private:
+	
+	bool mSocksSettingsDirty;
+	typedef std::map<LLControlVariable*, LLSD> control_values_map_t;
+	control_values_map_t mSavedValues;
+
+};
+
+
 #endif  // LL_LLPREFERENCEFLOATER_H
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 23cc23376f965e159bd869f60443990bbd67f6e7..2a946b1edfa06048dc610ae01cc7c940361149f5 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -27,26 +27,16 @@
 
 #include "llviewerprecompiledheaders.h"
 
-#include "llappviewer.h"
-#include "llbase64.h"
 #include "llcommandhandler.h"
 #include "llfloaterreg.h"
 #include "llfloatersearch.h"
 #include "llmediactrl.h"
 #include "llnotificationsutil.h"
-#include "llparcel.h"
-#include "llplugincookiestore.h"
 #include "lllogininstance.h"
 #include "lluri.h"
 #include "llagent.h"
-#include "llsdserialize.h"
 #include "llui.h"
 #include "llviewercontrol.h"
-#include "llviewerregion.h"
-#include "llversioninfo.h"
-#include "llviewermedia.h"
-#include "llviewernetwork.h"
-#include "llviewerparcelmgr.h"
 #include "llweb.h"
 
 // support secondlife:///app/search/{CATEGORY}/{QUERY} SLapps
@@ -178,14 +168,12 @@ void LLFloaterSearch::search(const SearchQuery &p)
 
 	// add the permissions token that login.cgi gave us
 	// We use "search_token", and fallback to "auth_token" if not present.
-	LLSD search_cookie;
-
 	LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token");
 	if (search_token.asString().empty())
 	{
 		search_token = LLLoginInstance::getInstance()->getResponse("auth_token");
 	}
-	search_cookie["AUTH_TOKEN"] = search_token.asString();
+	subs["AUTH_TOKEN"] = search_token.asString();
 
 	// add the user's preferred maturity (can be changed via prefs)
 	std::string maturity;
@@ -201,57 +189,10 @@ void LLFloaterSearch::search(const SearchQuery &p)
 	{
 		maturity = "13";  // PG
 	}
-	search_cookie["MATURITY"] = maturity;
+	subs["MATURITY"] = maturity;
 
 	// add the user's god status
-	search_cookie["GODLIKE"] = gAgent.isGodlike() ? "1" : "0";
-	search_cookie["VERSION"] = LLVersionInfo::getVersion();
-	search_cookie["VERSION_MAJOR"] = LLVersionInfo::getMajor();
-	search_cookie["VERSION_MINOR"] = LLVersionInfo::getMinor();
-	search_cookie["VERSION_PATCH"] = LLVersionInfo::getPatch();
-	search_cookie["VERSION_BUILD"] = LLVersionInfo::getBuild();
-	search_cookie["CHANNEL"] = LLVersionInfo::getChannel();
-	search_cookie["GRID"] = LLGridManager::getInstance()->getGridLabel();
-	search_cookie["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
-	search_cookie["SESSION_ID"] = gAgent.getSessionID();
-	search_cookie["FIRST_LOGIN"] = gAgent.isFirstLogin();
-
-	std::string lang = LLUI::getLanguage();
-	if (lang == "en-us")
-	{
-		lang = "en";
-	}
-	search_cookie["LANGUAGE"] = lang;
-
-	// find the region ID
-	LLUUID region_id;
-	LLViewerRegion *region = gAgent.getRegion();
-	if (region)
-	{
-		region_id = region->getRegionID();
-	}
-	search_cookie["REGION_ID"] = region_id;
-
-	// find the parcel local ID
-	S32 parcel_id = 0;
-	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	if (parcel)
-	{
-		parcel_id = parcel->getLocalID();
-	}
-	search_cookie["PARCEL_ID"] = llformat("%d", parcel_id);
-
-	std::stringstream cookie_string_stream;
-	LLSDSerialize::toXML(search_cookie, cookie_string_stream);
-	std::string cookie_string = cookie_string_stream.str();
-
-	U8* cookie_string_buffer = (U8*)cookie_string.c_str();
-	std::string cookie_value = LLBase64::encode(cookie_string_buffer, cookie_string.size());
-
-	// for staging services
-	LLViewerMedia::getCookieStore()->setCookiesFromHost(std::string("viewer_session_info=") + cookie_value, ".lindenlab.com");
-	// for live services
-	LLViewerMedia::getCookieStore()->setCookiesFromHost(std::string("viewer_session_info=") + cookie_value, ".secondlife.com");
+	subs["GODLIKE"] = gAgent.isGodlike() ? "1" : "0";
 
 	// get the search URL and expand all of the substitutions
 	// (also adds things like [LANGUAGE], [VERSION], [OS], etc.)
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 6461a5525e3eb52a80fa5b778b6a262c9a5496fe..ec162e00ebf731e4af0f032635aae77149ba8495 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -1912,9 +1912,20 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 
 	// when drop is not handled by child, it should be handled
 	// by the folder which is the hierarchy root.
-	if (!handled && getListener()->getUUID().notNull())
+	if (!handled)
 	{
-		LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+		if (getListener()->getUUID().notNull())
+		{
+			LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+		}
+		else
+		{
+			if (!mFolders.empty())
+			{
+				// dispatch to last folder as a hack to support "Contents" folder in object inventory
+				handled = mFolders.back()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+			}
+		}
 	}
 
 	if (handled)
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/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index b20f89aa7ca8251ae7c38778e30d1fd25b6ea6c2..f00d6087f9137e6afdd93fd616265e27c2a67b30 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -568,7 +568,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 	else
 	{
 		requested_options.append("basic-mode");
-		requested_options.append("inventory-basic");
+		//requested_options.append("inventory-basic");
 	}
 
 #endif
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 @@ private:
 	static BOOL		sCapslockDidNotification;
 };
 
-std::string load_password_from_disk(void);
-void save_password_to_disk(const char* hashed_password);
-
 #endif
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index 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/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index 904bb03270065573852bd41c975cc1d3241ba4b7..8d64c8c04f4bf2b3bd00dd29f482f024d0263923 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -1005,6 +1005,8 @@ void LLBasicCertificateStore::validate(int validation_policy,
 									   LLPointer<LLCertificateChain> cert_chain,
 									   const LLSD& validation_params)
 {
+	// If --no-verify-ssl-cert was passed on the command line, stop right now.
+	if (gSavedSettings.getBOOL("NoVerifySSLCert")) return;
 
 	if(cert_chain->size() < 1)
 	{
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index e23b431457470e1a3ef5fc699a8019b1486a9b55..fd17781a2e6f0eea8cf4f0be68594aa3822fcd2b 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -523,6 +523,11 @@ void LLSpatialGroup::clearDrawMap()
 	mDrawMap.clear();
 }
 
+BOOL LLSpatialGroup::isHUDGroup() 
+{
+	return mSpatialPartition && mSpatialPartition->isHUDPartition() ; 
+}
+
 BOOL LLSpatialGroup::isRecentlyVisible() const
 {
 	return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ;
@@ -4155,6 +4160,10 @@ void LLSpatialGroup::drawObjectBox(LLColor4 col)
 	drawBox(mObjectBounds[0], size);
 }
 
+bool LLSpatialPartition::isHUDPartition() 
+{ 
+	return mPartitionType == LLViewerRegion::PARTITION_HUD ;
+} 
 
 BOOL LLSpatialPartition::isVisible(const LLVector3& v)
 {
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 54d5d36f6ead74ab4525b768fa58c543eb181630..11955540c62a870493bac0d2db70743db5cb31bc 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -282,6 +282,7 @@ public:
 
 	LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part);
 
+	BOOL isHUDGroup() ;
 	BOOL isDead()							{ return isState(DEAD); }
 	BOOL isState(U32 state) const;	
 	BOOL isOcclusionState(U32 state) const	{ return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }
@@ -470,6 +471,7 @@ public:
 	S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum
 	
 	BOOL isVisible(const LLVector3& v);
+	bool isHUDPartition() ;
 	
 	virtual LLSpatialBridge* asBridge() { return NULL; }
 	virtual BOOL isBridge() { return asBridge() != NULL; }
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 7991233aceb41d51da3fba138240ffca156b6969..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.
@@ -2556,22 +2579,32 @@ void init_start_screen(S32 location_id)
 	else if(!start_image_bmp->load(temp_str) )
 	{
 		LL_WARNS("AppInit") << "Bitmap load failed" << LL_ENDL;
-		return;
+		gStartTexture = NULL;
 	}
+	else
+	{
+		gStartImageWidth = start_image_bmp->getWidth();
+		gStartImageHeight = start_image_bmp->getHeight();
 
-	gStartImageWidth = start_image_bmp->getWidth();
-	gStartImageHeight = start_image_bmp->getHeight();
+		LLPointer<LLImageRaw> raw = new LLImageRaw;
+		if (!start_image_bmp->decode(raw, 0.0f))
+		{
+			LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL;
+			gStartTexture = NULL;
+		}
+		else
+		{
+			raw->expandToPowerOfTwo();
+			gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ;
+		}
+	}
 
-	LLPointer<LLImageRaw> raw = new LLImageRaw;
-	if (!start_image_bmp->decode(raw, 0.0f))
+	if(gStartTexture.isNull())
 	{
-		LL_WARNS("AppInit") << "Bitmap decode failed" << LL_ENDL;
-		gStartTexture = NULL;
-		return;
+		gStartTexture = LLViewerTexture::sBlackImagep ;
+		gStartImageWidth = gStartTexture->getWidth() ;
+		gStartImageHeight = gStartTexture->getHeight() ;
 	}
-
-	raw->expandToPowerOfTwo();
-	gStartTexture = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE) ;
 }
 
 
@@ -2758,6 +2791,171 @@ void LLStartUp::setStartSLURL(const LLSLURL& slurl)
     }
 }
 
+/**
+ * Read all proxy configuration settings and set up both the HTTP proxy and
+ * SOCKS proxy as needed.
+ *
+ * Any errors that are encountered will result in showing the user a notification.
+ * When an error is encountered,
+ *
+ * @return Returns true if setup was successful, false if an error was encountered.
+ */
+bool LLStartUp::startLLProxy()
+{
+	bool proxy_ok = true;
+	std::string httpProxyType = gSavedSettings.getString("HttpProxyType");
+
+	// Set up SOCKS proxy (if needed)
+	if (gSavedSettings.getBOOL("Socks5ProxyEnabled"))
+	{	
+		// Determine and update LLProxy with the saved authentication system
+		std::string auth_type = gSavedSettings.getString("Socks5AuthType");
+
+		if (auth_type.compare("UserPass") == 0)
+		{
+			LLPointer<LLCredential> socks_cred = gSecAPIHandler->loadCredential("SOCKS5");
+			std::string socks_user = socks_cred->getIdentifier()["username"].asString();
+			std::string socks_password = socks_cred->getAuthenticator()["creds"].asString();
+
+			bool ok = LLProxy::getInstance()->setAuthPassword(socks_user, socks_password);
+
+			if (!ok)
+			{
+				LLNotificationsUtil::add("SOCKS_BAD_CREDS");
+				proxy_ok = false;
+			}
+		}
+		else if (auth_type.compare("None") == 0)
+		{
+			LLProxy::getInstance()->setAuthNone();
+		}
+		else
+		{
+			LL_WARNS("Proxy") << "Invalid SOCKS 5 authentication type."<< LL_ENDL;
+
+			// Unknown or missing setting.
+			gSavedSettings.setString("Socks5AuthType", "None");
+
+			// Clear the SOCKS credentials.
+			LLPointer<LLCredential> socks_cred = new LLCredential("SOCKS5");
+			gSecAPIHandler->deleteCredential(socks_cred);
+
+			LLProxy::getInstance()->setAuthNone();
+		}
+
+		if (proxy_ok)
+		{
+			// Start the proxy and check for errors
+			// If status != SOCKS_OK, stopSOCKSProxy() will already have been called when startSOCKSProxy() returns.
+			LLHost socks_host;
+			socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost"));
+			socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort"));
+			int status = LLProxy::getInstance()->startSOCKSProxy(socks_host);
+
+			if (status != SOCKS_OK)
+			{
+				LLSD subs;
+				subs["HOST"] = gSavedSettings.getString("Socks5ProxyHost");
+				subs["PORT"] = (S32)gSavedSettings.getU32("Socks5ProxyPort");
+
+				std::string error_string;
+
+				switch(status)
+				{
+					case SOCKS_CONNECT_ERROR: // TCP Fail
+						error_string = "SOCKS_CONNECT_ERROR";
+						break;
+
+					case SOCKS_NOT_PERMITTED: // SOCKS 5 server rule set refused connection
+						error_string = "SOCKS_NOT_PERMITTED";
+						break;
+
+					case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server
+						error_string = "SOCKS_NOT_ACCEPTABLE";
+						break;
+
+					case SOCKS_AUTH_FAIL: // Authentication failed
+						error_string = "SOCKS_AUTH_FAIL";
+						break;
+
+					case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed
+						error_string = "SOCKS_UDP_FWD_NOT_GRANTED";
+						break;
+
+					case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server
+						error_string = "SOCKS_HOST_CONNECT_FAILED";
+						break;
+
+					case SOCKS_INVALID_HOST: // Improperly formatted host address or port.
+						error_string = "SOCKS_INVALID_HOST";
+						break;
+
+					default:
+						error_string = "SOCKS_UNKNOWN_STATUS"; // Something strange happened,
+						LL_WARNS("Proxy") << "Unknown return from LLProxy::startProxy(): " << status << LL_ENDL;
+						break;
+				}
+
+				LLNotificationsUtil::add(error_string, subs);
+				proxy_ok = false;
+			}
+		}
+	}
+	else
+	{
+		LLProxy::getInstance()->stopSOCKSProxy(); // ensure no UDP proxy is running and it's all cleaned up
+	}
+
+	if (proxy_ok)
+	{
+		// Determine the HTTP proxy type (if any)
+		if ((httpProxyType.compare("Web") == 0) && gSavedSettings.getBOOL("BrowserProxyEnabled"))
+		{
+			LLHost http_host;
+			http_host.setHostByName(gSavedSettings.getString("BrowserProxyAddress"));
+			http_host.setPort(gSavedSettings.getS32("BrowserProxyPort"));
+			if (!LLProxy::getInstance()->enableHTTPProxy(http_host, LLPROXY_HTTP))
+			{
+				LLSD subs;
+				subs["HOST"] = http_host.getIPString();
+				subs["PORT"] = (S32)http_host.getPort();
+				LLNotificationsUtil::add("PROXY_INVALID_HTTP_HOST", subs);
+				proxy_ok = false;
+			}
+		}
+		else if ((httpProxyType.compare("Socks") == 0) && gSavedSettings.getBOOL("Socks5ProxyEnabled"))
+		{
+			LLHost socks_host;
+			socks_host.setHostByName(gSavedSettings.getString("Socks5ProxyHost"));
+			socks_host.setPort(gSavedSettings.getU32("Socks5ProxyPort"));
+			if (!LLProxy::getInstance()->enableHTTPProxy(socks_host, LLPROXY_SOCKS))
+			{
+				LLSD subs;
+				subs["HOST"] = socks_host.getIPString();
+				subs["PORT"] = (S32)socks_host.getPort();
+				LLNotificationsUtil::add("PROXY_INVALID_SOCKS_HOST", subs);
+				proxy_ok = false;
+			}
+		}
+		else if (httpProxyType.compare("None") == 0)
+		{
+			LLProxy::getInstance()->disableHTTPProxy();
+		}
+		else
+		{
+			LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration."<< LL_ENDL;
+
+			// Set the missing or wrong configuration back to something valid.
+			gSavedSettings.setString("HttpProxyType", "None");
+			LLProxy::getInstance()->disableHTTPProxy();
+
+			// Leave proxy_ok alone, since this isn't necessarily fatal.
+		}
+	}
+
+	return proxy_ok;
+}
+
 bool login_alert_done(const LLSD& notification, const LLSD& response)
 {
 	LLPanelLogin::giveFocus();
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index b3d9ef1dcc7805b9a3003ba87fe70c42d3f51c2f..99a644eb9cfa275ba49cf49cc1ec2497380cd70f 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -113,6 +113,8 @@ public:
 	static void setStartSLURL(const LLSLURL& slurl); 
 	static LLSLURL& getStartSLURL() { return sStartSLURL; } 
 
+	static bool startLLProxy(); // Initialize the SOCKS 5 proxy
+
 private:
 	static LLSLURL sStartSLURL;
 
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 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/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 321d02aaf13f74ea64aa310e1171ceacaa43a21a..64aeb750c60fddd7ac611cc80edd904b6261debc 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1049,48 +1049,26 @@ void start_new_inventory_observer()
 class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver
 {
 	LOG_CLASS(LLDiscardAgentOffer);
+
 public:
 	LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) :
 		LLInventoryFetchItemsObserver(object_id),
 		mFolderID(folder_id),
 		mObjectID(object_id) {}
-	virtual ~LLDiscardAgentOffer() {}
+
 	virtual void done()
 	{
 		LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL;
-		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
-		bool notify = false;
-		if(trash_id.notNull() && mObjectID.notNull())
-		{
-			LLInventoryModel::update_list_t update;
-			LLInventoryModel::LLCategoryUpdate old_folder(mFolderID, -1);
-			update.push_back(old_folder);
-			LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
-			update.push_back(new_folder);
-			gInventory.accountForUpdate(update);
-			gInventory.moveObject(mObjectID, trash_id);
-			LLInventoryObject* obj = gInventory.getObject(mObjectID);
-			if(obj)
-			{
-				// no need to restamp since this is already a freshly
-				// stamped item.
-				obj->updateParentOnServer(FALSE);
-				notify = true;
-			}
-		}
-		else
-		{
-			LL_WARNS("Messaging") << "DiscardAgentOffer unable to find: "
-					<< (trash_id.isNull() ? "trash " : "")
-					<< (mObjectID.isNull() ? "object" : "") << LL_ENDL;
-		}
+
+		// We're invoked from LLInventoryModel::notifyObservers().
+		// If we now try to remove the inventory item, it will cause a nested
+		// notifyObservers() call, which won't work.
+		// So defer moving the item to trash until viewer gets idle (in a moment).
+		LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID));
 		gInventory.removeObserver(this);
-		if(notify)
-		{
-			gInventory.notifyObservers();
-		}
 		delete this;
 	}
+
 protected:
 	LLUUID mFolderID;
 	LLUUID mObjectID;
@@ -1495,7 +1473,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 	LLChat chat;
 	std::string log_message;
 	S32 button = LLNotificationsUtil::getSelectedOption(notification, response);
-	
+
 	LLInventoryObserver* opener = NULL;
 	LLViewerInventoryCategory* catp = NULL;
 	catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID);
@@ -1527,7 +1505,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 	// TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:
 	from_string = chatHistory_string = mFromName;
 	
-	bool busy=FALSE;
+	bool busy = gAgent.getBusy();
 	
 	switch(button)
 	{
@@ -1586,9 +1564,6 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
 		}
 		break;
 
-	case IOR_BUSY:
-		//Busy falls through to decline.  Says to make busy message.
-		busy=TRUE;
 	case IOR_MUTE:
 		// MUTE falls through to decline
 	case IOR_DECLINE:
@@ -1734,7 +1709,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
 		from_string = chatHistory_string = mFromName;
 	}
 	
-	bool busy=FALSE;
+	bool busy = gAgent.getBusy();
 	
 	switch(button)
 	{
@@ -1780,9 +1755,6 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
 		}	// end switch (mIM)
 			break;
 			
-		case IOR_BUSY:
-			//Busy falls through to decline.  Says to make busy message.
-			busy=TRUE;
 		case IOR_MUTE:
 			// MUTE falls through to decline
 		case IOR_DECLINE:
@@ -2667,7 +2639,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
 			{
 				// Until throttling is implemented, busy mode should reject inventory instead of silently
 				// accepting it.  SEE SL-39554
-				info->forceResponse(IOR_BUSY);
+				info->forceResponse(IOR_DECLINE);
 			}
 			else
 			{
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index 9d09d9c01a8a204ed83ac4a689c8249a07fcbf33..d8acd99953844cb18ead8aca25b722a99e6ed67e 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -57,7 +57,6 @@ enum InventoryOfferResponse
 	IOR_ACCEPT,
 	IOR_DECLINE,
 	IOR_MUTE,
-	IOR_BUSY,
 	IOR_SHOW
 };
 
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index db2dc531db81a71e9500afcafd13a5e1337b3956..17f908d73f23f4c28bfccfa7672647d3eba914c5 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1193,6 +1193,7 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
 	eCacheUpdateResult result = CACHE_UPDATE_ADDED;
 	if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
 	{
+		delete mImpl->mCacheMap.begin()->second ;
 		mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());
 		result = CACHE_UPDATE_REPLACED;
 		
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 5fcc57bc91dc82841a5710e390a8516e64f57fd9..70509f9a9f409dbb59a0b848d6ef18e3b7f4ef89 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -66,6 +66,7 @@
 
 // statics
 LLPointer<LLViewerTexture>        LLViewerTexture::sNullImagep = NULL;
+LLPointer<LLViewerTexture>        LLViewerTexture::sBlackImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sMissingAssetImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sWhiteImagep = NULL;
 LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
@@ -295,17 +296,23 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const
 
 void LLViewerTextureManager::init()
 {
-	LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
-	raw->clear(0x77, 0x77, 0x77, 0xFF);
-	LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
-
-#if 1
-	LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
-	LLViewerFetchedTexture::sDefaultImagep = imagep;
+	{
+		LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,3);
+		raw->clear(0x77, 0x77, 0x77, 0xFF);
+		LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE) ;
+	}
 
 	const S32 dim = 128;
 	LLPointer<LLImageRaw> image_raw = new LLImageRaw(dim,dim,3);
 	U8* data = image_raw->getData();
+	
+	memset(data, 0, dim * dim * 3) ;
+	LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE) ;
+
+#if 1
+	LLPointer<LLViewerFetchedTexture> imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT);
+	LLViewerFetchedTexture::sDefaultImagep = imagep;
+	
 	for (S32 i = 0; i<dim; i++)
 	{
 		for (S32 j = 0; j<dim; j++)
@@ -359,6 +366,7 @@ void LLViewerTextureManager::cleanup()
 
 	LLImageGL::sDefaultGLTexture = NULL ;
 	LLViewerTexture::sNullImagep = NULL;
+	LLViewerTexture::sBlackImagep = NULL;
 	LLViewerFetchedTexture::sDefaultImagep = NULL;	
 	LLViewerFetchedTexture::sSmokeImagep = NULL;
 	LLViewerFetchedTexture::sMissingAssetImagep = NULL;
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index c5b8c8923ad52bf6b4eb16b363778221ee106e07..de528927b46fbe56a243fd07aafb4db7c1756907 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -330,6 +330,7 @@ public:
 	static BOOL sUseTextureAtlas ;
 
 	static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects.
+	static LLPointer<LLViewerTexture> sBlackImagep;	// Texture to show NOTHING (pure black)
 };
 
 
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index f0b5b50febbe2aecca2c36d3f5a587a806d5b330..6d457434b5f1cabedc4aa973e9e7d6ac198c2374 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -621,16 +621,20 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
 				S32 num_entries;
 				success = check_read(&apr_file, &num_entries, sizeof(S32)) ;
 	
-				for (S32 i = 0; success && i < num_entries; i++)
+				if(success)
 				{
-					LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file);
-					if (!entry->getLocalID())
+					for (S32 i = 0; i < num_entries; i++)
 					{
-						llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl;
-						delete entry ;
-						success = false ;
+						LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file);
+						if (!entry->getLocalID())
+						{
+							llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl;
+							delete entry ;
+							success = false ;
+							break ;
+						}
+						cache_entry_map[entry->getLocalID()] = entry;
 					}
-					cache_entry_map[entry->getLocalID()] = entry;
 				}
 			}
 		}		
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index eb3ed3c3795aaea3746f28c2902a2f0b4d9b3370..528c7acbc82ec76495b692ca3d1a4c07a37e0510 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4490,6 +4490,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 		std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater());
 	}
 				
+	bool hud_group = group->isHUDGroup() ;
 	std::vector<LLFace*>::iterator face_iter = faces.begin();
 	
 	LLSpatialGroup::buffer_map_t buffer_map;
@@ -4760,7 +4761,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 					registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY);
 					registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
 				}
-				else if (LLPipeline::sRenderDeferred)
+				else if (LLPipeline::sRenderDeferred && !hud_group)
 				{ //deferred rendering
 					if (te->getFullbright())
 					{ //register in post deferred fullbright shiny pass
@@ -4798,7 +4799,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 				else if (fullbright || bake_sunlight)
 				{ //fullbright
 					registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
-					if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap())
+					if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && te->getBumpmap())
 					{ //if this is the deferred render and a bump map is present, register in post deferred bump
 						registerFace(group, facep, LLRenderPass::PASS_POST_BUMP);
 					}
@@ -4824,7 +4825,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 			}
 			
 			//not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010
-			if (!is_alpha && !LLPipeline::sRenderDeferred)
+			if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred))
 			{
 				llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright);
 				facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE);
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 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_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml
index 8da35e9d7f73a7e60c7b1f3d31c976d756429cc3..c756661ffc38e80da6d33ef5704bcf27e2a280c9 100644
--- a/indra/newview/skins/default/xui/en/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/en/floater_postcard.xml
@@ -7,11 +7,11 @@
  height="380"
  layout="topleft"
  min_height="380"
- min_width="450"
+ min_width="490"
  name="Postcard"
  help_topic="postcard"
  title="EMAIL SNAPSHOT"
- width="450">
+ width="490">
     <floater.string
      name="default_subject">
         Postcard from [SECOND_LIFE].
@@ -40,7 +40,7 @@
      follows="left|top"
      height="20"
      layout="topleft"
-     left_delta="108"
+     left_delta="148"
      name="to_form"
      top_delta="-4"
      width="150" />
@@ -59,7 +59,7 @@
      follows="left|top"
      height="20"
      layout="topleft"
-     left_delta="108"
+     left_delta="148"
      name="from_form"
      top_delta="-4"
      width="150" />
@@ -78,7 +78,7 @@
      follows="left|top"
      height="20"
      layout="topleft"
-     left_delta="108"
+     left_delta="148"
      max_length_bytes="100"
      name="name_form"
      top_delta="-4"
@@ -99,7 +99,7 @@
      height="20"
      label="Type your subject here."
      layout="topleft"
-     left_delta="108"
+     left_delta="148"
      max_length_bytes="100"
      name="subject_form"
      top_delta="-4"
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml b/indra/newview/skins/default/xui/en/floater_preferences_proxy.xml
new file mode 100644
index 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..e3c649ab38fc7b86de955c512a5ceb10f3847f5e 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5928,7 +5928,7 @@ An object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; owned by [NAME_SLU
 [ITEM_SLURL]
     <form name="form">
       <button
-       index="4"
+       index="3"
        name="Show"
        text="Show"/>
       <button
@@ -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>
diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp
index daa10819fc036d8683ed445c7d750a162f6580d1..02354009760348c40dd7bc1b294d250a9ed0a449 100644
--- a/indra/newview/tests/llsechandler_basic_test.cpp
+++ b/indra/newview/tests/llsechandler_basic_test.cpp
@@ -86,6 +86,9 @@ std::string LLControlGroup::getString(const std::string& name)
 	return "";
 }
 
+// Stub for --no-verify-ssl-cert
+BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; }
+
 LLSD LLCredential::getLoginParams()
 {
 	LLSD result = LLSD::emptyMap();
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 0a21d8714cad316aa62c30ae501bf9898bfab775..f0bee2bfee3730dfc2eb1e87dfe4fa95715b470c 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -66,12 +66,14 @@ class ViewerManifest(LLManifest):
                 # include the extracted list of contributors
                 contributor_names = self.extract_names("../../doc/contributions.txt")
                 self.put_in_file(contributor_names, "contributors.txt")
+                self.file_list.append(["../../doc/contributions.txt",self.dst_path_of("contributors.txt")])
                 # include the extracted list of translators
                 translator_names = self.extract_names("../../doc/translations.txt")
                 self.put_in_file(translator_names, "translators.txt")
+                self.file_list.append(["../../doc/translations.txt",self.dst_path_of("translators.txt")])
                 # include the list of Lindens (if any)
                 #   see https://wiki.lindenlab.com/wiki/Generated_Linden_Credits
-                linden_names_path = os.getenv("linden_credits")
+                linden_names_path = os.getenv("LINDEN_CREDITS")
                 if linden_names_path :
                     try:
                         linden_file = open(linden_names_path,'r')
@@ -79,9 +81,13 @@ class ViewerManifest(LLManifest):
                         linden_names = ', '.join(linden_file.readlines())
                         self.put_in_file(linden_names, "lindens.txt")
                         linden_file.close()
+                        print "Linden names extracted from '%s'" % linden_names_path
+                        self.file_list.append([linden_names_path,self.dst_path_of("lindens.txt")])
                     except IOError:
                         print "No Linden names found at '%s', using built-in list" % linden_names_path
                         pass
+                else :
+                    print "No 'LINDEN_CREDITS' specified in environment, using built-in list"
 
                 # ... and the entire windlight directory
                 self.path("windlight")