diff --git a/.hgignore b/.hgignore
new file mode 100644
index 0000000000000000000000000000000000000000..28c78eb9942622bea5da5f668ff28a2aa06ed5b6
--- /dev/null
+++ b/.hgignore
@@ -0,0 +1,42 @@
+syntax: glob
+
+*.pyc
+*~
+.*.swp
+LICENSES
+indra/.distcc
+indra/build-darwin-*
+indra/build-vc[0-9]*
+indra/lib/mono/1.0/*.dll
+indra/lib/mono/indra/*.dll
+indra/lib/mono/indra/*.exe
+indra/lib/mono/indra/*.pdb
+indra/llwindow/glh/glh_linear.h
+indra/newview/app_settings/mozilla
+indra/newview/app_settings/mozilla-runtime-*
+indra/newview/app_settings/mozilla_debug
+indra/newview/app_settings/static_*.db2
+indra/newview/character
+indra/newview/fmod.dll
+indra/newview/mozilla-theme
+indra/newview/mozilla-universal-darwin.tgz
+indra/newview/res-sdl
+indra/newview/skins
+indra/newview/vivox-runtime
+indra/server-linux-*
+indra/test/linden_file.dat
+indra/test_apps/llmediatest/dependencies/i686-win32
+indra/test_apps/terrain_mule/*.dll
+indra/viewer-linux-*
+indra/web/doc/asset-upload/plugins/lsl_compiler/lslc
+indra/web/doc/asset-upload/plugins/verify-notecard
+indra/web/doc/asset-upload/plugins/verify-texture
+installed.xml
+libraries
+tarfile_tmp
+^web/locale.*
+^web/secondlife.com.*
+^web/config.*
+^indra/web/dataservice/locale.*
+^indra/web/dataservice/lib/shared/vault.*
+^indra/web/dataservice/vendor.*
diff --git a/etc/message.xml b/etc/message.xml
index dd1fda059e5689293f0c64fd05839c963751a16a..7ad392d0b54650cdd94463402827b064302b69a7 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -668,6 +668,9 @@
 		
 			<key>FetchLib</key>
 			<boolean>true</boolean>
+
+			<key>UploadBakedTexture</key>
+			<boolean>true</boolean>
 		</map>
 
 		<key>messageBans</key>
diff --git a/indra/cmake/GoogleMock.cmake b/indra/cmake/GoogleMock.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..ca5a8034ba442082c5881ec4c046ebe4b7a777e9
--- /dev/null
+++ b/indra/cmake/GoogleMock.cmake
@@ -0,0 +1,27 @@
+# -*- cmake -*-
+include(Prebuilt)
+include(Linking)
+
+use_prebuilt_binary(googlemock)
+
+set(GOOGLEMOCK_INCLUDE_DIRS 
+    ${LIBS_PREBUILT_DIR}/include)
+
+if (LINUX)
+    set(GOOGLEMOCK_LIBRARIES 
+        gmock  
+        gtest)
+elseif(WINDOWS)
+    set(GOOGLEMOCK_LIBRARIES 
+        gmock)
+    set(GOOGLEMOCK_INCLUDE_DIRS 
+        ${LIBS_PREBUILT_DIR}/include
+        ${LIBS_PREBUILT_DIR}/include/gmock
+        ${LIBS_PREBUILT_DIR}/include/gmock/boost/tr1/tr1)
+elseif(DARWIN)
+    set(GOOGLEMOCK_LIBRARIES
+        gmock
+        gtest)
+endif(LINUX)
+
+
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 7d6ef9ab1a719eaca78b5c8730e1c2002231ea67..373ad4d4e94dbaaa11ad99b9981bbe80e78c239d 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -13,6 +13,8 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
   #
   # WARNING: do NOT modify this code without working with poppy or daveh -
   # there is another branch that will conflict heavily with any changes here.
+INCLUDE(GoogleMock)
+
 
   IF(LL_TEST_VERBOSE)
     MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
@@ -32,8 +34,10 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
     ${LLMATH_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
     ${LIBS_OPEN_DIR}/test
+    ${GOOGLEMOCK_INCLUDE_DIRS}
     )
   SET(alltest_LIBRARIES
+    ${GOOGLEMOCK_LIBRARIES}
     ${PTHREAD_LIBRARY}
     ${WINDOWS_LIBRARIES}
     )
@@ -42,6 +46,11 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
     ${CMAKE_SOURCE_DIR}/test/test.h
     )
 
+  # Use the default flags
+  if (LINUX)
+    SET(CMAKE_EXE_LINKER_FLAGS "")
+  endif (LINUX)
+
   # start the source test executable definitions
   SET(${project}_TEST_OUTPUT "")
   FOREACH (source ${sources})
@@ -84,9 +93,9 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
       MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
     ENDIF(LL_TEST_VERBOSE)
 
+
     # Setup target
     ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
-
     #
     # Per-codefile additional / external project dep and lib dep property extraction
     #
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index 1190d88663964a6c3dace2c291778ab676d0579e..4527b115f9ad07b6a2f9180090466c2f562112a1 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -238,7 +238,7 @@ def ARRAY(self, v):
     def MAP(self, v):
         return self.elt(
             'map',
-            ''.join(["%s%s" % (self.elt('key', key), self.generate(value))
+            ''.join(["%s%s" % (self.elt('key', self.xml_esc(str(key))), self.generate(value))
              for key, value in v.items()]))
 
     typeof = type
diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py
index aceea29cd2082273456e06da21798853ccc5f145..1cdd8e915b996cf6d315339a400260ca677a3135 100644
--- a/indra/lib/python/indra/base/lluuid.py
+++ b/indra/lib/python/indra/base/lluuid.py
@@ -26,8 +26,14 @@
 $/LicenseInfo$
 """
 
-import md5, random, socket, string, time, re
+import random, socket, string, time, re
 import uuid
+try:
+    # Python 2.6
+    from hashlib import md5
+except ImportError:
+    # Python 2.5 and earlier
+    from md5 import new as md5
 
 def _int2binstr(i,l):
     s=''
@@ -196,7 +202,7 @@ def generate(self):
         from c++ implementation for portability reasons.
         Returns self.
         """
-        m = md5.new()
+        m = md5()
         m.update(uuid.uuid1().bytes)
         self._bits = m.digest()
         return self
diff --git a/indra/lib/python/indra/util/llsubprocess.py b/indra/lib/python/indra/util/llsubprocess.py
index c4c40739ec9514180d57f3c75db7259293ba679e..7e0e115d14600f29fe4b855077232a8d10529271 100644
--- a/indra/lib/python/indra/util/llsubprocess.py
+++ b/indra/lib/python/indra/util/llsubprocess.py
@@ -90,6 +90,17 @@ def run(command, args=None, data=None, timeout=None):
                     child.tochild.close()
         result = child.poll()
         if result != -1:
+            # At this point, the child process has exited and result
+            # is the return value from the process. Between the time
+            # we called select() and poll() the process may have
+            # exited so read all the data left on the child process
+            # stdout and stderr.
+            last = child.fromchild.read()
+            if last:
+                out.append(last)
+            last = child.childerr.read()
+            if last:
+                err.append(last)
             child.tochild.close()
             child.fromchild.close()
             child.childerr.close()
diff --git a/indra/lib/python/indra/util/llversion.py b/indra/lib/python/indra/util/llversion.py
index 770b861ddc1604e6dd2d133aa94513560c154455..2718a85f414cb958db30e8035bf21742583a084b 100644
--- a/indra/lib/python/indra/util/llversion.py
+++ b/indra/lib/python/indra/util/llversion.py
@@ -1,7 +1,7 @@
 """@file llversion.py
 @brief Utility for parsing llcommon/llversion${server}.h
        for the version string and channel string
-       Utility that parses svn info for branch and revision
+       Utility that parses hg or svn info for branch and revision
 
 $LicenseInfo:firstyear=2006&license=mit$
 
@@ -79,8 +79,8 @@ def get_svn_status_matching(regular_expression):
     status, output = commands.getstatusoutput('svn info %s' % get_src_root())
     m = regular_expression.search(output)
     if not m:
-        print "Failed to parse svn info output, resultfollows:"
-        print output
+        print >> sys.stderr, "Failed to parse svn info output, result follows:"
+        print >> sys.stderr, output
         raise Exception, "No matching svn status in "+src_root
     return m.group(1)
 
@@ -92,4 +92,35 @@ def get_svn_revision():
     last_rev_re = re.compile('Last Changed Rev: (\d+)')
     return get_svn_status_matching(last_rev_re)
 
-
+def get_hg_repo():
+    status, output = commands.getstatusoutput('hg showconfig paths.default')
+    if status:
+        print >> sys.stderr, output
+        sys.exit(1)
+    if not output:
+        print >> sys.stderr, 'ERROR: cannot find repo we cloned from'
+        sys.exit(1)
+    return output
+
+def get_hg_changeset():
+    # The right thing to do:
+    # status, output = commands.getstatusoutput('hg id -i')
+    # if status:
+    #     print >> sys.stderr, output
+    #    sys.exit(1)
+
+    # The temporary hack:
+    status, output = commands.getstatusoutput('hg parents --template "{rev}"')
+    if status:
+        print >> sys.stderr, output
+        sys.exit(1)
+    lines = output.splitlines()
+    if len(lines) > 1:
+        print >> sys.stderr, 'ERROR: working directory has %d parents' % len(lines)
+    return lines[0]
+
+def using_svn():
+    return os.path.isdir(os.path.join(get_src_root(), '.svn'))
+
+def using_hg():
+    return os.path.isdir(os.path.join(get_src_root(), '.hg'))
diff --git a/indra/lib/python/indra/util/named_query.py b/indra/lib/python/indra/util/named_query.py
index 693b483f792f485d206dbac812865a6fef3d0170..5c19368240afa08b8576f3f16ec01c4b738c5f76 100644
--- a/indra/lib/python/indra/util/named_query.py
+++ b/indra/lib/python/indra/util/named_query.py
@@ -48,8 +48,8 @@
 from indra.base import config
 
 DEBUG = False
-NQ_FILE_SUFFIX = None
-NQ_FILE_SUFFIX_LEN = None
+NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
+NQ_FILE_SUFFIX_LEN  = len(NQ_FILE_SUFFIX)
 
 _g_named_manager = None
 
diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp
index 1d42298f4d395adb638efae4713af11a74e45e72..1ae0ddeea0fba8787885b6a247866c0809973a28 100644
--- a/indra/llcharacter/llkeyframestandmotion.cpp
+++ b/indra/llcharacter/llkeyframestandmotion.cpp
@@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask)
 	if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD)
 	{
 		mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation();
-		mLastGoodPelvisRotation.normQuat();
+		mLastGoodPelvisRotation.normalize();
 		mTrackAnkles = TRUE;
 	}
 	else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD)
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index bc4e44d7e68cf1ba169c5a5cbac071c59621a941..138dc85459e46ae297606513f45004dea8ce6fa4 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -240,7 +240,7 @@ SET(llcommon_TEST_SOURCE_FILES
 LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
 
 #set(TEST_DEBUG on)
-set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES})
 # Have to treat lllazy test as an integration test until this issue is resolved:
 # https://jira.lindenlab.com/jira/browse/DEV-29456
 LL_ADD_INTEGRATION_TEST(lllazy lllazy.cpp "${test_libs}")
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 5d7672b3780a01386dc8a66e4d55d1b05c0bb510..78aa6f4f37693f2b25191658239a5557861618a6 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -289,6 +289,7 @@ bool LLAssetType::lookupIsEnsembleCategoryType(EType asset_type)
 			asset_type <= AT_FOLDER_ENSEMBLE_END);
 }
 
+
 // static. Generate a good default description
 void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
 										 std::string& description)
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 5e5118854161f3348244f712e0a81cae2f8fb1ba..880b7a19b5b3d272aa53d7f9511ba4c4d8889564 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -150,6 +150,7 @@ class LLAssetType
 
 		
 		AT_COUNT = 49,
+
 			// +*********************************************************+
 			// |  TO ADD AN ELEMENT TO THIS ENUM:                        |
 			// +*********************************************************+
diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h
index 873f50a65ef8abbeb1d2fcdbd2f50025f66cf90f..7544ab1d11ffb2a3f853d1709457186689fbf828 100644
--- a/indra/llcommon/llkeythrottle.h
+++ b/indra/llcommon/llkeythrottle.h
@@ -118,6 +118,63 @@ class LLKeyThrottle
 		THROTTLE_BLOCKED,		// rate exceed, block key
 	};
 
+	F64 getActionCount(const T& id)
+	{
+		U64 now = 0;
+		if ( mIsRealtime )
+		{
+			now = LLKeyThrottleImpl<T>::getTime();
+		}
+		else
+		{
+			now = LLKeyThrottleImpl<T>::getFrame();
+		}
+
+		if (now >= (m.startTime + m.intervalLength))
+		{
+			if (now < (m.startTime + 2 * m.intervalLength))
+			{
+				// prune old data
+				delete m.prevMap;
+				m.prevMap = m.currMap;
+				m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+				m.startTime += m.intervalLength;
+			}
+			else
+			{
+				// lots of time has passed, all data is stale
+				delete m.prevMap;
+				delete m.currMap;
+				m.prevMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+				m.currMap = new typename LLKeyThrottleImpl<T>::EntryMap;
+
+				m.startTime = now;
+			}
+		}
+
+		U32 prevCount = 0;
+
+		typename LLKeyThrottleImpl<T>::EntryMap::const_iterator prev = m.prevMap->find(id);
+		if (prev != m.prevMap->end())
+		{
+			prevCount = prev->second.count;
+		}
+
+		typename LLKeyThrottleImpl<T>::Entry& curr = (*m.currMap)[id];
+
+		// curr.count is the number of keys in
+		// this current 'time slice' from the beginning of it until now
+		// prevCount is the number of keys in the previous
+		// time slice scaled to be one full time slice back from the current 
+		// (now) time.
+
+		// compute current, windowed rate
+		F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength);
+		F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent);
+		return averageCount;
+	}
+
 	// call each time the key wants use
 	State noteAction(const T& id, S32 weight = 1)
 	{
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index c12ca350de53f301860ed57bd42c2f8e323a82fc..7e1c2e35e0da678d2fdf7d0acbfde9c001fa6173 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -37,6 +37,7 @@
 #include <deque>
 
 #include "apr_base64.h"
+#include <boost/regex.hpp>
 
 extern "C"
 {
@@ -777,10 +778,17 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
 		
 		case ELEMENT_BINARY:
 		{
-			S32 len = apr_base64_decode_len(mCurrentContent.c_str());
+			// Regex is expensive, but only fix for whitespace in base64,
+			// created by python and other non-linden systems - DEV-39358
+			// Fortunately we have very little binary passing now,
+			// so performance impact shold be negligible. + poppy 2009-09-04
+			boost::regex r;
+			r.assign("\\s");
+			std::string stripped = boost::regex_replace(mCurrentContent, r, "");
+			S32 len = apr_base64_decode_len(stripped.c_str());
 			std::vector<U8> data;
 			data.resize(len);
-			len = apr_base64_decode_binary(&data[0], mCurrentContent.c_str());
+			len = apr_base64_decode_binary(&data[0], stripped.c_str());
 			data.resize(len);
 			value = data;
 			break;
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 90dae117937254d03e8f2fabe78bc8ed23c6cecd..0bd2609f4a9ab462cbc4eecd483bbba2c680a240 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -43,7 +43,7 @@
 
 
 // statics
-BOOL            LLPerfBlock::sStatsEnabled = FALSE;    // Flag for detailed information
+S32	            LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS;       // Control what is being recorded
 LLPerfBlock::stat_map_t    LLPerfBlock::sStatMap;    // Map full path string to LLStatTime objects, tracks all active objects
 std::string        LLPerfBlock::sCurrentStatPath = "";    // Something like "/total_time/physics/physics step"
 LLStat::stat_map_t LLStat::sStatList;
@@ -130,6 +130,7 @@ bool LLStatsConfigFile::loadFile()
 
     F32 duration = 0.f;
     F32 interval = 0.f;
+	S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS;
 
     const char * w = "duration";
     if (stats_config.has(w))
@@ -141,8 +142,18 @@ bool LLStatsConfigFile::loadFile()
     {
         interval = (F32)stats_config[w].asReal();
     } 
+    w = "flags";
+    if (stats_config.has(w))
+    {
+		flags = (S32)stats_config[w].asInteger();
+		if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS &&
+			duration > 0)
+		{   // No flags passed in, but have a duration, so reset to basic stats
+			flags = LLPerfBlock::LLSTATS_BASIC_STATS;
+		}
+    } 
 
-    mStatsp->setReportPerformanceDuration( duration );
+    mStatsp->setReportPerformanceDuration( duration, flags );
     mStatsp->setReportPerformanceInterval( interval );
 
     if ( duration > 0 )
@@ -254,13 +265,14 @@ void LLPerfStats::dumpIntervalPerformanceStats()
     }
 }
 
-// Set length of performance stat recording
-void    LLPerfStats::setReportPerformanceDuration( F32 seconds )
+// Set length of performance stat recording.  
+// If turning stats on, caller must provide flags
+void    LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ )
 { 
 	if ( seconds <= 0.f )
 	{
 		mReportPerformanceStatEnd = 0.0;
-		LLPerfBlock::setStatsEnabled( FALSE );
+		LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS);		// Make sure all recording is off
 		mFrameStatsFile.close();
 		LLPerfBlock::clearDynamicStats();
 	}
@@ -269,8 +281,8 @@ void    LLPerfStats::setReportPerformanceDuration( F32 seconds )
 		mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds);
 		// Clear failure flag to try and create the log file once
 		mFrameStatsFileFailure = FALSE;
-		LLPerfBlock::setStatsEnabled( TRUE );
 		mSkipFirstFrameStats = TRUE;		// Skip the first report (at the end of this frame)
+		LLPerfBlock::setStatsFlags(flags);
 	}
 }
 
@@ -612,11 +624,26 @@ LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicSta
     }
 }
 
-// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key.
-// These are also turned on or off via the switch passed in
-LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+// Use this constructor for normal, optional LLPerfBlock time slices
+LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL)
 {
-    if (!sStatsEnabled) return;
+    if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0)
+	{	// These are off unless the base set is enabled
+		return;
+	}
+
+	initDynamicStat(key);
+}
+
+	
+// Use this constructor for dynamically created LLPerfBlock time slices
+// that are only enabled by specific control flags
+LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL)
+{
+    if ((sStatsFlags & flags) == 0)
+	{
+		return;
+	}
 
     if (NULL == key2 || strlen(key2) == 0)
     {
@@ -630,10 +657,12 @@ LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat
     }
 }
 
+// Set up the result data map if dynamic stats are enabled
 void LLPerfBlock::initDynamicStat(const std::string& key)
 {
     // Early exit if dynamic stats aren't enabled.
-    if (!sStatsEnabled) return;
+    if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS) 
+		return;
 
     mLastPath = sCurrentStatPath;		// Save and restore current path
     sCurrentStatPath += "/" + key;		// Add key to current path
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index bad18f46a0aea70e8abfeacca42703f96a86553c..76aa3963f4e95839756c8f8580063a150eb1e1d5 100644
--- a/indra/llcommon/llstat.h
+++ b/indra/llcommon/llstat.h
@@ -192,14 +192,23 @@ class LLPerfBlock
 	// Use this constructor for pre-defined LLStatTime objects
 	LLPerfBlock(LLStatTime* stat);
 
-	// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key
-	LLPerfBlock( const char* key1, const char* key2 = NULL);
+	// Use this constructor for normal, optional LLPerfBlock time slices
+	LLPerfBlock( const char* key );
 
+	// Use this constructor for dynamically created LLPerfBlock time slices
+	// that are only enabled by specific control flags
+	LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS );
 
 	~LLPerfBlock();
 
-	static void setStatsEnabled( BOOL enable )		{ sStatsEnabled = enable;	};
-	static S32  getStatsEnabled()					{ return sStatsEnabled;		};
+	enum
+	{	// Stats bitfield flags
+		LLSTATS_NO_OPTIONAL_STATS	= 0x00,		// No optional stats gathering, just pre-defined LLStatTime objects
+		LLSTATS_BASIC_STATS			= 0x01,		// Gather basic optional runtime stats
+		LLSTATS_SCRIPT_FUNCTIONS	= 0x02,		// Include LSL function calls
+	};
+	static void setStatsFlags( S32 flags )	{ sStatsFlags = flags;	};
+	static S32  getStatsFlags()				{ return sStatsFlags;	};
 
 	static void clearDynamicStats();		// Reset maps to clear out dynamic objects
 	static void addStatsToLLSDandReset( LLSD & stats,		// Get current information and clear time bin
@@ -213,7 +222,7 @@ class LLPerfBlock
 	LLStatTime * 			mPredefinedStat;		// LLStatTime object to get data
 	StatEntry *				mDynamicStat;   		// StatEntryobject to get data
 
-	static BOOL				sStatsEnabled;			// Normally FALSE
+	static S32				sStatsFlags;			// Control what is being recorded
     static stat_map_t		sStatMap;				// Map full path string to LLStatTime objects
 	static std::string		sCurrentStatPath;		// Something like "frame/physics/physics step"
 };
@@ -236,7 +245,7 @@ class LLPerfStats
     BOOL    frameStatsIsRunning()                                { return (mReportPerformanceStatEnd > 0.);        };
     F32     getReportPerformanceInterval() const                { return mReportPerformanceStatInterval;        };
     void    setReportPerformanceInterval( F32 interval )        { mReportPerformanceStatInterval = interval;    };
-    void    setReportPerformanceDuration( F32 seconds );
+    void    setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS );
     void    setProcessName(const std::string& process_name) { mProcessName = process_name; }
     void    setProcessPID(S32 process_pid) { mProcessPID = process_pid; }
 
diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h
index 4492063275e64f4d3bc7934802e87dd04bba8f52..2a0c0d8d2967ffef75903080bb1a998617a1af59 100644
--- a/indra/llcommon/llstringtable.h
+++ b/indra/llcommon/llstringtable.h
@@ -48,10 +48,12 @@
 //# define STRING_TABLE_HASH_MAP 1
 #endif
 
-#if LL_WINDOWS
-#include <hash_map>
-#else
-#include <ext/hash_map>
+#if STRING_TABLE_HASH_MAP
+# if LL_WINDOWS
+#  include <hash_map>
+# else
+#  include <ext/hash_map>
+# endif
 #endif
 
 const U32 MAX_STRINGS_LENGTH = 256;
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
index 23e39ceb08f0f02d5848c45f2cf7d0e56d485b2d..77a03879bf6152229c05cd96da877f569187da83 100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llversionserver.h
@@ -34,9 +34,9 @@
 #define LL_LLVERSIONSERVER_H
 
 const S32 LL_VERSION_MAJOR = 1;
-const S32 LL_VERSION_MINOR = 29;
+const S32 LL_VERSION_MINOR = 31;
 const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 2639;
 
 const char * const LL_CHANNEL = "Second Life Server";
 
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 45810a101d66b711ba7b4006e7f0342234008133..ccea101cd6a70ab2a48d5d3b080a5c6a2a2a15c3 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -36,7 +36,7 @@
 const S32 LL_VERSION_MAJOR = 2;
 const S32 LL_VERSION_MINOR = 0;
 const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 2639;
 
 const char * const LL_CHANNEL = "Second Life 2009";
 
diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h
index 79a536a224ffaf1ae668747fb5ab3bfd95451b93..5ad230d1d5e8fb8556b84fa28a5a873c673e2621 100644
--- a/indra/llcommon/metapropertyt.h
+++ b/indra/llcommon/metapropertyt.h
@@ -93,6 +93,13 @@ inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* obje
 	return NULL;
 }
 
+template <>
+inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const
+{
+	checkObjectClass(object);
+	return NULL;
+}
+
 template <>
 inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const
 {
@@ -111,6 +118,12 @@ inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const
 	return *(getProperty(object));
 }
 
+template <>
+inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const
+{
+	return *(getProperty(object));
+}
+
 template<class TObject, class TProperty>
 class LLMetaPropertyTT : public LLMetaPropertyT<TProperty>
 {
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 363486fb9c013caa8e9ec4141c412638171e9188..2352c8edd725112b80c12cd7937d9ed538ef4dd6 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -178,8 +178,8 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 							mMaxBytes(0),
 							mRawDiscardLevel(-1),
 							mRate(0.0f),
-							mReversible(FALSE)
-	
+							mReversible(FALSE),
+							mAreaUsedForDataSizeCalcs(0)
 {
 	//We assume here that if we wanted to create via
 	//a dynamic library that the approriate open calls were made
@@ -195,6 +195,12 @@ LLImageJ2C::LLImageJ2C() : 	LLImageFormatted(IMG_CODEC_J2C),
 	}
 
 	mImpl = j2cimpl_create_func();
+
+	// Clear data size table
+	for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
+	{	// Array size is MAX_DISCARD_LEVEL+1
+		mDataSizes[i] = 0;
+	}
 }
 
 // virtual
@@ -367,9 +373,45 @@ S32 LLImageJ2C::calcHeaderSize()
 	return calcHeaderSizeJ2C();
 }
 
+
+// calcDataSize() returns how many bytes to read 
+// to load discard_level (including header and higher discard levels)
 S32 LLImageJ2C::calcDataSize(S32 discard_level)
 {
-	return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
+	discard_level = llclamp(discard_level, 0, MAX_DISCARD_LEVEL);
+
+	if ( mAreaUsedForDataSizeCalcs != (getHeight() * getWidth()) 
+		|| mDataSizes[0] == 0)
+	{
+		mAreaUsedForDataSizeCalcs = getHeight() * getWidth();
+		
+		S32 level = MAX_DISCARD_LEVEL;	// Start at the highest discard
+		while ( level >= 0 )
+		{
+			mDataSizes[level] = calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+			level--;
+		}
+
+		/* This is technically a more correct way to calculate the size required
+		   for each discard level, since they should include the size needed for
+		   lower levels.   Unfortunately, this doesn't work well and will lead to 
+		   download stalls.  The true correct way is to parse the header.  This will
+		   all go away with http textures at some point.
+
+		// Calculate the size for each discard level.   Lower levels (higher quality)
+		// contain the cumulative size of higher levels		
+		S32 total_size = calcHeaderSizeJ2C();
+
+		S32 level = MAX_DISCARD_LEVEL;	// Start at the highest discard
+		while ( level >= 0 )
+		{	// Add in this discard level and all before it
+			total_size += calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), level, mRate);
+			mDataSizes[level] = total_size;
+			level--;
+		}
+		*/
+	}
+	return mDataSizes[discard_level];
 }
 
 S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index 23f6ef5fd10b8a7a82cc4283143acd990eaf51e8..55df7f44296e537ec9cf50c796a7831ed3b48a21 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -87,6 +87,10 @@ class LLImageJ2C : public LLImageFormatted
 	void updateRawDiscardLevel();
 
 	S32 mMaxBytes; // Maximum number of bytes of data to use...
+	
+	S32 mDataSizes[MAX_DISCARD_LEVEL+1];		// Size of data required to reach a given level
+	U32 mAreaUsedForDataSizeCalcs;				// Height * width used to calculate mDataSizes
+
 	S8  mRawDiscardLevel;
 	F32 mRate;
 	BOOL mReversible;
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index e2a77f1d1e5f4f7f14b6daf16a9a401d15546d34..5d3fbe51289192d1c33db39247376434fa9df1be 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -458,6 +458,39 @@ void LLInventoryItem::setCreationDate(time_t creation_date_utc)
 	mCreationDate = creation_date_utc;
 }
 
+void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
+{
+	// Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags 
+	// because we now detect when they should be set.
+	setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItem::II_FLAGS_PERM_OVERWRITE_MASK)) );
+
+	// Enforce the PERM_OVERWRITE flags for any masks that are different
+	// but only for AT_OBJECT's since that is the only asset type that can 
+	// exist in-world (instead of only in-inventory or in-object-contents).
+	if (LLAssetType::AT_OBJECT == getType())
+	{
+		LLPermissions old_permissions = old_item.getPermissions();
+		U32 flags_to_be_set = 0;
+		if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+		}
+		if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+		}
+		if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+		}
+		LLSaleInfo old_sale_info = old_item.getSaleInfo();
+		if(old_sale_info != getSaleInfo())
+		{
+			flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+		}
+		setFlags(getFlags() | flags_to_be_set);
+	}
+}
 
 const LLSaleInfo& LLInventoryItem::getSaleInfo() const
 {
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 64af6c94f5dd996cbd368b4313e0bd293fd2785d..bd581e860f3a230dd919f9836e3d402c3c8aaf0b 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -93,7 +93,6 @@ class LLInventoryObject : public LLRefCount
 	virtual const LLUUID& getUUID() const;
 	const LLUUID& getParentUUID() const;
 	virtual const LLUUID& getLinkedUUID() const; // get the inventoryID that this item points to, else this item's inventoryID
-
 	virtual const std::string& getName() const;
 	virtual LLAssetType::EType getType() const;
 	LLAssetType::EType getActualType() const; // bypasses indirection for linked items
@@ -263,6 +262,10 @@ class LLInventoryItem : public LLInventoryObject
 	void setInventoryType(LLInventoryType::EType inv_type);
 	void setFlags(U32 flags);
 	void setCreationDate(time_t creation_date_utc);
+
+	// Check for changes in permissions masks and sale info
+	// and set the corresponding bits in mFlags
+	void accumulatePermissionSlamBits(const LLInventoryItem& old_item);
 	
 	// This is currently only used in the Viewer to handle calling cards
 	// where the creator is actually used to store the target.
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index aa8391230c30b72cc3bd5b85360e6224355de8c1..2a9a596912fce7403ab1da61cc7590f8128ccaa2 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -136,9 +136,9 @@ class LLSD;
 class LLAccessEntry
 {
 public:
-	LLUUID		mID;
-	S32			mTime;
-	U32			mFlags;
+	LLUUID		mID;		// Agent ID
+	S32			mTime;		// Time (unix seconds) when entry expires
+	U32			mFlags;		// Not used - currently should always be zero
 };
 
 typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 0babf26457e91ee463ae662697d5c4aea7b3380f..d2e503473401a6063679c4ea0dfff1ecac5040ed 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -288,6 +288,17 @@ BOOL LLPermissions::setOwnerAndGroup(
 	return allowed;
 }
 
+//Fix for DEV-33917, last owner isn't used much and has little impact on
+//permissions so it's reasonably safe to do this, however, for now, 
+//limiting the functionality of this routine to objects which are 
+//group owned.
+void LLPermissions::setLastOwner(const LLUUID& last_owner)
+{
+	if (isGroupOwned())
+		mLastOwner = last_owner;
+}
+
+ 
 // only call this if you know what you're doing
 // there are usually perm-bit consequences when the 
 // ownerhsip changes
@@ -895,6 +906,8 @@ void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class)
 {
 	reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator);
 	reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner);
+	reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup);
+	reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned);
 }
 
 // virtual
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index 864088148f58ccb64f3582dacc75c262324bb53e..d5a0881c8f2ab684ed52f526c3e29dc26c3154de 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -232,6 +232,10 @@ class LLPermissions : public LLReflective
 	// ownerhsip changes
 	void yesReallySetOwner(const LLUUID& owner, bool group_owned);
 
+	// Last owner doesn't have much in the way of permissions so it's 
+	//not too dangerous to do this. 
+	void setLastOwner(const LLUUID& last_owner);
+
 	// saves last owner, sets owner to uuid null, sets group
 	// owned. group_id must be the group of the object (that's who it
 	// is being deeded to) and the object must be group
diff --git a/indra/llinventory/lltransactiontypes.h b/indra/llinventory/lltransactiontypes.h
index 1cb7308bd417fbcfd473e5b65385359df6753719..2c699bcb87cb7761882b5435b2c1b78c8ee7b93a 100644
--- a/indra/llinventory/lltransactiontypes.h
+++ b/indra/llinventory/lltransactiontypes.h
@@ -69,6 +69,12 @@ const S32 TRANS_PARCEL_DIR_FEE		= 2003;
 const S32 TRANS_GROUP_TAX		    = 2004; // Taxes incurred as part of group membership
 const S32 TRANS_CLASSIFIED_RENEW	= 2005;
 
+// Codes 2100-2999 reserved for recurring billing services
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC  = 2100;
+
 // Codes 3000-3999 reserved for inventory transactions
 const S32 TRANS_GIVE_INVENTORY		= 3000;
 
@@ -84,6 +90,12 @@ const S32 TRANS_DWELL_BONUS			= 5007;
 const S32 TRANS_PAY_OBJECT			= 5008;
 const S32 TRANS_OBJECT_PAYS			= 5009;
 
+// Codes 5100-5999 reserved for recurring billing transfers between users
+// New codes can be created through an admin interface so may not
+// automatically end up in the list below :-(
+// So make sure you check the transaction_description table
+const S32 TRANS_RECURRING_GENERIC_USER  = 5100;
+
 // Codes 6000-6999 reserved for group transactions
 //const S32 TRANS_GROUP_JOIN		    = 6000;  //reserved for future use
 const S32 TRANS_GROUP_LAND_DEED		= 6001;
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index cfd6183ec44cc3f118b16647b028fded6b811b9e..fdcc19d657b6ee0144121cdbd411fc82b22b6513 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -121,7 +121,7 @@ void	LLQuaternion::quantize16(F32 lower, F32 upper)
 	mQ[VZ] = z;
 	mQ[VS] = s;
 
-	normQuat();
+	normalize();
 }
 
 void	LLQuaternion::quantize8(F32 lower, F32 upper)
@@ -131,7 +131,7 @@ void	LLQuaternion::quantize8(F32 lower, F32 upper)
 	mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
 	mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
 
-	normQuat();
+	normalize();
 }
 
 // LLVector3 Magnitude and Normalization Functions
@@ -346,7 +346,7 @@ const LLQuaternion&	LLQuaternion::setQuat(const LLMatrix4 &mat)
 //    mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
 //#endif
 //
-//	normQuat();
+//	normalize();
 //	return (*this);
 }
 
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 5db9c5be2ed5167b82d85db3d1847d3fb6f5d31e..0769f29f235d747a3a36ef74d34027fcb6a659e9 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -469,20 +469,30 @@ inline const LLQuaternion&	operator*=(LLQuaternion &a, const LLQuaternion &b)
 	return a;
 }
 
+const F32 ONE_PART_IN_A_MILLION = 0.000001f;
+
 inline F32	LLQuaternion::normalize()
 {
 	F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
 
 	if (mag > FP_MAG_THRESHOLD)
 	{
-		F32 oomag = 1.f/mag;
-		mQ[VX] *= oomag;
-		mQ[VY] *= oomag;
-		mQ[VZ] *= oomag;
-		mQ[VS] *= oomag;
+		// Floating point error can prevent some quaternions from achieving
+		// exact unity length.  When trying to renormalize such quaternions we
+		// can oscillate between multiple quantized states.  To prevent such
+		// drifts we only renomalize if the length is far enough from unity.
+		if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+		{
+			F32 oomag = 1.f/mag;
+			mQ[VX] *= oomag;
+			mQ[VY] *= oomag;
+			mQ[VZ] *= oomag;
+			mQ[VS] *= oomag;
+		}
 	}
 	else
 	{
+		// we were given a very bad quaternion so we set it to identity
 		mQ[VX] = 0.f;
 		mQ[VY] = 0.f;
 		mQ[VZ] = 0.f;
@@ -499,11 +509,15 @@ inline F32	LLQuaternion::normQuat()
 
 	if (mag > FP_MAG_THRESHOLD)
 	{
-		F32 oomag = 1.f/mag;
-		mQ[VX] *= oomag;
-		mQ[VY] *= oomag;
-		mQ[VZ] *= oomag;
-		mQ[VS] *= oomag;
+		if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+		{
+			// only renormalize if length not close enough to 1.0 already
+			F32 oomag = 1.f/mag;
+			mQ[VX] *= oomag;
+			mQ[VY] *= oomag;
+			mQ[VZ] *= oomag;
+			mQ[VS] *= oomag;
+		}
 	}
 	else
 	{
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 1e8b5517e416d29b6c8cf62d751c951de14e2829..453286b83d8ff019940c1db7d6a3c9b65bceb93a 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -3,6 +3,7 @@
 project(llmessage)
 
 include(00-Common)
+include(GoogleMock)
 include(LLAddBuildTest)
 include(LLCommon)
 include(LLMath)
@@ -221,6 +222,7 @@ IF (NOT LINUX AND VIEWER)
       # llhttpclientadapter.cpp
       lltrustedmessageservice.cpp
       lltemplatemessagedispatcher.cpp
+      llregionpresenceverifier.cpp
       )
 #    set(TEST_DEBUG on)
     set(test_libs
@@ -229,6 +231,7 @@ IF (NOT LINUX AND VIEWER)
       ${LLVFS_LIBRARIES}
       ${LLMATH_LIBRARIES}
       ${LLCOMMON_LIBRARIES}
+      ${GOOGLEMOCK_LIBRARIES}
       )
 
     LL_ADD_INTEGRATION_TEST(
@@ -241,3 +244,4 @@ IF (NOT LINUX AND VIEWER)
 
     LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
 ENDIF (NOT LINUX AND VIEWER)
+
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 47d49076f4a28ed1b38407a5c82ffd957472a2fc..c044b3d80d15ac9b4a80a373b912b72fb72a9551 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -100,7 +100,6 @@ class LLCacheName
 	
 	// LEGACY
 	boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
-
 	// This method needs to be called from time to time to send out
 	// requests.
 	void processPending();
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index a4af8e989ba7436c067ae67105c197feb19af458..5ff41322b7b65ca2168245ca8ab7c5f12737ce62 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -131,7 +131,7 @@ void LLCurl::Responder::errorWithContent(
 // virtual
 void LLCurl::Responder::error(U32 status, const std::string& reason)
 {
-	llinfos << status << ": " << reason << llendl;
+	llinfos << mURL << " [" << status << "]: " << reason << llendl;
 }
 
 // virtual
@@ -139,6 +139,11 @@ void LLCurl::Responder::result(const LLSD& content)
 {
 }
 
+void LLCurl::Responder::setURL(const std::string& url)
+{
+	mURL = url;
+}
+
 // virtual
 void LLCurl::Responder::completedRaw(
 	U32 status,
@@ -148,7 +153,11 @@ void LLCurl::Responder::completedRaw(
 {
 	LLSD content;
 	LLBufferStream istr(channels, buffer.get());
-	LLSDSerialize::fromXML(content, istr);
+	if (!LLSDSerialize::fromXML(content, istr))
+	{
+		llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl;
+	}
+
 	completed(status, reason, content);
 }
 
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fbd3077cbf75eddadebadb6ecb535fb7757ee8cd..0b58e7c4a59fa82538b2fa31b4fc93dbcf3a81d2 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -120,8 +120,14 @@ class LLCurl
 			// of the header can be parsed.  In the ::completed call above only the body is contained in the LLSD.
 			virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content);
 
+			// Used internally to set the url for debugging later.
+			void setURL(const std::string& url);
+
 	public: /* but not really -- don't touch this */
 		U32 mReferenceCount;
+
+	private:
+		std::string mURL;
 	};
 	typedef boost::intrusive_ptr<Responder>	ResponderPtr;
 
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 8b90a4c5cacd2ed5df432d2ca9c3e7f49847deae..12ecbb36eb8ea85862fe1e723daaa1c27ffc9bf0 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -265,6 +265,11 @@ static void request(
 		}
 	}
 
+	if (responder)
+	{
+		responder->setURL(url);
+	}
+
 	req->setCallback(new LLHTTPClientURLAdaptor(responder));
 
 	if (method == LLURLRequest::HTTP_POST  &&  gMessageSystem)
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index b6988224ce7356524caa73e4d37681a84a84f3bf..9d3c83f82870c2f13f2b8115dd520400b83e3aea 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientadapter.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index 7f76390d0c59d9a2ff2cb43966867f407ff3a86d..a205a2f260e122faa8a636e90f88c7d5ccb86233 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientadepter.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 42a8e5cd0a9bac2068c71a12ca73569c33f949f7..085a59cf2776816ff67ed8dfe766b188eba71ecd 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llhttpclientinterface.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index a00dbd180906235cf13f3fd688b2b9ed54c99815..97134bd336c45938f464646dacf36b4025728e78 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -521,7 +521,7 @@ class LLHTTPResponder : public LLIOPipe
 	 * seek orfor string assignment.
 	 * @returns Returns true if a line was found.
 	 */
-	bool readLine(
+	bool readHeaderLine(
 		const LLChannelDescriptors& channels,
 		buffer_ptr_t buffer,
 		U8* dest,
@@ -592,7 +592,7 @@ LLHTTPResponder::~LLHTTPResponder()
 	//lldebugs << "destroying LLHTTPResponder" << llendl;
 }
 
-bool LLHTTPResponder::readLine(
+bool LLHTTPResponder::readHeaderLine(
 	const LLChannelDescriptors& channels,
 	buffer_ptr_t buffer,
 	U8* dest,
@@ -670,7 +670,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 #endif
 		
 		PUMP_DEBUG;
-		if(readLine(channels, buffer, (U8*)buf, len))
+		if(readHeaderLine(channels, buffer, (U8*)buf, len))
 		{
 			bool read_next_line = false;
 			bool parse_all = true;
@@ -734,7 +734,13 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(
 					if(read_next_line)
 					{
 						len = HEADER_BUFFER_SIZE;	
-						readLine(channels, buffer, (U8*)buf, len);
+						if (!readHeaderLine(channels, buffer, (U8*)buf, len))
+						{
+							// Failed to read the header line, probably too long.
+							// readHeaderLine already marked the channel/buffer as bad.
+							keep_parsing = false;
+							break;
+						}
 					}
 					if(0 == len)
 					{
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index d52ff6c7e8bbc0eb063a38131c24f6b04d88ac99..ce206d8d7d17bb7ffdefb4d861db5ea433f1d831 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction(
 // static
 bool LLMail::send(
 	const std::string& header,
-	const std::string& message,
+	const std::string& raw_message,
 	const char* from_address,
 	const char* to_address)
 {
@@ -276,8 +276,20 @@ bool LLMail::send(
 		return false;
 	}
 
-	// *FIX: this translation doesn't deal with a single period on a
-	// line by itself.
+	// remove any "." SMTP commands to prevent injection (DEV-35777)
+	// we don't need to worry about "\r\n.\r\n" because of the 
+	// "\n" --> "\n\n" conversion going into rfc2822_msg below
+	std::string message = raw_message;
+	std::string bad_string = "\n.\n";
+	std::string good_string = "\n..\n";
+	while (1)
+	{
+		int index = message.find(bad_string);
+		if (index == std::string::npos) break;
+		message.replace(index, bad_string.size(), good_string);
+	}
+
+	// convert all "\n" into "\r\n"
 	std::ostringstream rfc2822_msg;
 	for(U32 i = 0; i < message.size(); ++i)
 	{
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index 119eb1d7f73f2013e01af8ea9b711b6a7a9bbb7c..af6733fa05acecb377a6ac5787c4c318a5ea521e 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llmessagesenderinterface.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index 0527d5cb8debff456cbf674598a5a22a0fe944b0..e02c735ce7e459b04c21a9c90393f5ba6a8dba63 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llregionpresenceverifier.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -36,11 +36,40 @@
 #include "net.h"
 #include "message.h"
 
+namespace boost
+{
+	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p)
+	{
+		++p->mReferenceCount;
+	}
+	
+	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p)
+	{
+		if(p && 0 == --p->mReferenceCount)
+		{
+			delete p;
+		}
+	}
+};
 
-LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::Response::~Response()
 {
 }
 
+LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string&
+														   uri,
+														   ResponsePtr data,
+														   S32 retry_count) :
+	mUri(uri),
+	mSharedData(data),
+	mRetryCount(retry_count)
+{
+}
+
+//virtual
+LLRegionPresenceVerifier::RegionResponder::~RegionResponder()
+{
+}
 
 void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
 {
@@ -49,30 +78,36 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)
 	LLHost destination(host, port);
 	LLUUID id = content["region_id"];
 
-	llinfos << "Verifying " << destination.getString() << " is region " << id << llendl;
+	lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl;
 
 	std::stringstream uri;
 	uri << "http://" << destination.getString() << "/state/basic/";
-	mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content));
+	mSharedData->getHttpClient().get(
+		uri.str(),
+		new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));
 }
 
-void LLRegionPresenceVerifier::RegionResponder::completed(
-	U32 status,
-	const std::string& reason,
-	const LLSD& content)
+void LLRegionPresenceVerifier::RegionResponder::error(U32 status,
+													 const std::string& reason)
 {
-	LLHTTPClient::Responder::completed(status, reason, content);
-	
-	mSharedData->onCompletedRegionRequest();
+	// TODO: babbage: distinguish between region presence service and
+	// region verification errors?
+	mSharedData->onRegionVerificationFailed();
 }
 
-
-LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content)
+LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content,
+	S32 retry_count):
+	mUri(uri),
+	mSharedData(data),
+	mContent(content),
+	mRetryCount(retry_count) 
 {
 }
 
-
-
+//virtual
+LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder()
+{
+}
 
 void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)
 {
@@ -87,13 +122,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&
 	{
 		mSharedData->onRegionVerified(mContent);
 	}
-	else if (mSharedData->shouldRetry())
+	else if (mRetryCount > 0)
 	{
 		retry();
 	}
 	else
 	{
-		llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl;
+		llwarns << "Simulator verification failed. Region: " << mUri << llendl;
+		mSharedData->onRegionVerificationFailed();
 	}
 }
 
@@ -101,13 +137,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()
 {
 	LLSD headers;
 	headers["Cache-Control"] = "no-cache, max-age=0";
-	llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl;
-	mSharedData->decrementRetries();
-	mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers);
+	llinfos << "Requesting region information, get uncached for region "
+			<< mUri << llendl;
+	--mRetryCount;
+	mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);
 }
 
 void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)
 {
-	retry();
+	if(mRetryCount > 0)
+	{
+		retry();
+	}
+	else
+	{
+		llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl;
+		mSharedData->onRegionVerificationFailed();
+	}
 }
-
diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h
index 54ad6226d645cbe7c4aed403aec028367b504504..f57a62a731317f509b84a7f7208174a5eab4d250 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llregionpresenceverifier.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -37,7 +37,7 @@
 #include "llhttpclient.h"
 #include <string>
 #include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
 
 class LLHTTPClientInterface;
 
@@ -47,49 +47,58 @@ class LLRegionPresenceVerifier
 	class Response
 	{
 	public:
-		virtual ~Response() {}
+		virtual ~Response() = 0;
 
 		virtual bool checkValidity(const LLSD& content) const = 0;
 		virtual void onRegionVerified(const LLSD& region_details) = 0;
-
-		virtual void decrementRetries() = 0;
+		virtual void onRegionVerificationFailed() = 0;
 
 		virtual LLHTTPClientInterface& getHttpClient() = 0;
-		virtual std::string getRegionUri() const = 0;
-		virtual bool shouldRetry() const = 0;
 
-		virtual void onCompletedRegionRequest() {}
+	public: /* but not really -- don't touch this */
+		U32 mReferenceCount;		
 	};
 
-	typedef boost::shared_ptr<Response> ResponsePtr;
+	typedef boost::intrusive_ptr<Response> ResponsePtr;
 
 	class RegionResponder : public LLHTTPClient::Responder
 	{
 	public:
-		RegionResponder(ResponsePtr data);
+		RegionResponder(const std::string& uri, ResponsePtr data,
+						S32 retry_count);
+		virtual ~RegionResponder(); 
 		virtual void result(const LLSD& content);
-		virtual void completed(
-			U32 status,
-			const std::string& reason,
-			const LLSD& content);
+		virtual void error(U32 status, const std::string& reason);
 
 	private:
 		ResponsePtr mSharedData;
+		std::string mUri;
+		S32 mRetryCount;
 	};
 
 	class VerifiedDestinationResponder : public LLHTTPClient::Responder
 	{
 	public:
-		VerifiedDestinationResponder(ResponsePtr data, const LLSD& content);
+		VerifiedDestinationResponder(const std::string& uri, ResponsePtr data,
+									 const LLSD& content, S32 retry_count);
+		virtual ~VerifiedDestinationResponder();
 		virtual void result(const LLSD& content);
 		
 		virtual void error(U32 status, const std::string& reason);
+		
 	private:
 		void retry();
 		ResponsePtr mSharedData;
 		LLSD mContent;
+		std::string mUri;
+		S32 mRetryCount;
 	};
 };
 
+namespace boost
+{
+	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p);
+	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p);
+};
 
 #endif //LL_LLREGIONPRESENCEVERIFIER_H
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 32cbb15cb385fcf072e5e7375634fe353db704bf..d6b2f45d04e58d08f6fa411e64431f74d2bc5e72 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llstoredmessage.cpp
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index 5069c2cb2e19226d283d19fe6dfefa8c02321e9e..359e4c5aeac96ba32f23aee834792a9d95d02a92 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,5 +1,5 @@
 /** 
- * @file 
+ * @file llstoredmessage.h
  * @brief 
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 70279a3c62d033ab8eab74103eac4d93bf548bdf..0872efba508ff8d427f557881356de7bf4320fc6 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)
 	return changed;
 }
 
+// Return bits available in the channel
+S32		LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+	S32 retval = 0;
+
+	F32 category_bps = mCurrentBPS[throttle_cat];
+	F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+	// use a temporary bits_available
+	// since we don't want to change mBitsAvailable every time
+	F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
+	F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
+
+	if (bits_available >= lookahead_bits)
+	{
+		retval = (S32) gThrottleMaximumBPS[throttle_cat];
+	}
+	else 
+	{
+		retval = (S32) bits_available;
+	}
+	
+	return retval;
+}
+
 
 BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
 {
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 7d1679beb232ead9c23259f0bab6799fdca3d9f8..47a7c653b23b1679a73d845c9da4a4ec73172468 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -84,6 +84,8 @@ class LLThrottleGroup
 	BOOL	dynamicAdjust();		// Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred
 	BOOL	setNominalBPS(F32* throttle_vec);				// TRUE if any value was different, resets adjustment system if was different
 
+	S32		getAvailable(S32 throttle_cat);					// Return bits available in the channel
+
 	void packThrottle(LLDataPacker &dp) const;
 	void unpackThrottle(LLDataPacker &dp);
 public:
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index 5a1cd95ffcd54183a95618dbd321b145d6e96952..41f3f3f607d9fcae5fa610b871c7126f6efeccbd 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -270,7 +270,6 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
 		case LLAssetType::AT_BODYPART:
 		case LLAssetType::AT_ANIMATION:
 		case LLAssetType::AT_GESTURE:
-		case LLAssetType::AT_FAVORITE:
 			rv = true;
 			break;
 		default:
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb0951576a5f4d1dea241e404c65e4c3..81b7761ed5fdec3b2263ab3c6c6da23d2f471f31 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
  * String constants
  */
 const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
+const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
 
 
 static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user);
@@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 	PUMP_DEBUG;
 	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
 	//llinfos << "LLURLRequest::process_impl()" << llendl;
-	if(!buffer) return STATUS_ERROR;
+	if (!buffer) return STATUS_ERROR;
+	
+	// we're still waiting or prcessing, check how many
+	// bytes we have accumulated.
+	const S32 MIN_ACCUMULATION = 100000;
+	if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+	{
+		 // This is a pretty sloppy calculation, but this
+		 // tries to make the gross assumption that if data
+		 // is coming in at 56kb/s, then this transfer will
+		 // probably succeed. So, if we're accumlated
+		 // 100,000 bytes (MIN_ACCUMULATION) then let's
+		 // give this client another 2s to complete.
+		 const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+		 mDetail->mByteAccumulator = 0;
+		 pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+		 lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl;
+		 if (mState == STATE_INITIALIZED)
+		 {
+			  llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl;
+		 }
+	}
+
 	switch(mState)
 	{
 	case STATE_INITIALIZED:
@@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 			bool newmsg = mDetail->mCurlRequest->getResult(&result);
 			if(!newmsg)
 			{
-				// we're still waiting or prcessing, check how many
-				// bytes we have accumulated.
-				const S32 MIN_ACCUMULATION = 100000;
-				if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
-				{
-					// This is a pretty sloppy calculation, but this
-					// tries to make the gross assumption that if data
-					// is coming in at 56kb/s, then this transfer will
-					// probably succeed. So, if we're accumlated
-					// 100,000 bytes (MIN_ACCUMULATION) then let's
-					// give this client another 2s to complete.
-					const F32 TIMEOUT_ADJUSTMENT = 2.0f;
-					mDetail->mByteAccumulator = 0;
-					pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
-				}
-
 				// keep processing
 				break;
 			}
 
 			mState = STATE_HAVE_RESPONSE;
+			context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+			context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+			lldebugs << this << "Setting context to " << context << llendl;
 			switch(result)
 			{
 				case CURLE_OK:
@@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
 		// we already stuffed everything into channel in in the curl
 		// callback, so we are done.
 		eos = true;
+		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+		lldebugs << this << "Setting context to " << context << llendl;
 		return STATUS_DONE;
 
 	default:
 		PUMP_DEBUG;
+		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes;
+		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes;
+		lldebugs << this << "Setting context to " << context << llendl;
 		return STATUS_ERROR;
 	}
 }
@@ -369,6 +385,8 @@ void LLURLRequest::initialize()
 	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
 	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);
 	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this);
+	mRequestTransferedBytes = 0;
+	mResponseTransferedBytes = 0;
 }
 
 bool LLURLRequest::configure()
@@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback(
 		req->mDetail->mChannels.out(),
 		(U8*)data,
 		bytes);
+	req->mResponseTransferedBytes += bytes;
 	req->mDetail->mByteAccumulator += bytes;
 	return bytes;
 }
@@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback(
 		req->mDetail->mLastRead,
 		(U8*)data,
 		bytes);
+	req->mRequestTransferedBytes += bytes;
 	return bytes;
 }
 
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
index 86ef71f085b7048386f68a9c086681987d9d5b21..cb3c46644062cbb26530cc4fbc4e13c90a99309e 100644
--- a/indra/llmessage/llurlrequest.h
+++ b/indra/llmessage/llurlrequest.h
@@ -45,6 +45,12 @@
 #include "llchainio.h"
 #include "llerror.h"
 
+
+extern const std::string CONTEXT_REQUEST;
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+extern const std::string CONTEXT_RESPONSE;
+extern const std::string CONTEXT_TRANSFERED_BYTES;
+
 class LLURLRequestDetail;
 
 class LLURLRequestComplete;
@@ -208,6 +214,8 @@ class LLURLRequest : public LLIOPipe
 	ERequestAction mAction;
 	LLURLRequestDetail* mDetail;
 	LLIOPipe::ptr_t mCompletionCallback;
+	 S32 mRequestTransferedBytes;
+	 S32 mResponseTransferedBytes;
 
 private:
 	/** 
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 08c9192c9ff5c4ddc117de55811223ad464903dd..209bdb2249459fe446fb336e4b287db0ebf08ed6 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -760,30 +760,36 @@ static bool remove_prefix(std::string& filename, const std::string& prefix)
 static bool verify_cache_filename(const std::string& filename)
 {
 	//NOTE: This routine is only used to check file names that our own
-	// code places in the cache directory.  As such, it can be limited
-	// to this very restrictive file name pattern.  It does not need to
-	// handle other characters.
-
+	// code places in the cache directory.	As such, it can be limited
+	// to this very restrictive file name pattern.	It does not need to
+	// handle other characters. The only known uses of this are (with examples):
+	//	sim to sim object pass:			fc0b72d8-9456-63d9-a802-a557ef847313.tmp
+	//	sim to viewer mute list:		mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
+	//	sim to viewer task inventory:	inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
+	
+	//IMPORTANT: Do not broaden the filenames accepted by this routine
+	// without careful analysis. Anything allowed by this function can
+	// be downloaded by the viewer.
+	
 	size_t len = filename.size();
-	//const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>");
-	if (len < 1 || len > 50)
-	{
+	//const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
+	if (len < 5 || len > 50)
+	{	
 		return false;
 	}
-	for(unsigned i=0; i<len; ++i)
-	{
+	for(size_t i=0; i<(len-4); ++i)
+	{	
 		char c = filename[i];
-		bool ok = isalnum(c);
-		if (!ok && i > 0)
-		{
-			ok = '_'==c || '-'==c || '.'==c;
-		}
+		bool ok = isalnum(c) || '_'==c || '-'==c;
 		if (!ok)
 		{
 			return false;
 		}
 	}
-	return true;
+	return filename[len-4] == '.'
+		&& filename[len-3] == 't'
+		&& filename[len-2] == 'm'
+		&& filename[len-1] == 'p';
 }
 
 void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f55e97fcc95f89a9eaf390e3c5e95314df4eb90
--- /dev/null
+++ b/indra/llmessage/tests/llmockhttpclient.h
@@ -0,0 +1,61 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2008, Linden Research, Inc.
+ * 
+ * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
+ * this source code is governed by the Linden Lab Source Code Disclosure
+ * Agreement ("Agreement") previously entered between you and Linden
+ * Lab. By accessing, using, copying, modifying or distributing this
+ * software, you acknowledge that you have been informed of your
+ * obligations under the Agreement and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+/* Macro Definitions */
+#ifndef LL_LLMOCKHTTPCLIENT_H
+#define LL_LLMOCKHTTPCLIENT_H
+
+#include "linden_common.h"
+#include "llhttpclientinterface.h"
+
+#include <gmock/gmock.h>
+
+class LLMockHTTPClient : public LLHTTPClientInterface
+{
+public:
+  MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder));
+  MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers));
+  MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder));
+};
+
+// A helper to match responder types
+template<typename T>
+struct ResponderType
+{
+	bool operator()(LLCurl::ResponderPtr ptr) const
+	{
+		T* p = dynamic_cast<T*>(ptr.get());
+		return p != NULL;
+	}
+};
+
+inline bool operator==(const LLSD& l, const LLSD& r)
+{
+	std::ostringstream ls, rs;
+	ls << l;
+	rs << r;
+	return ls.str() == rs.str();
+
+}
+
+
+#endif //LL_LLMOCKHTTPCLIENT_H
+
diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b7602ef15ca5dd04ae725d3e21ffb2d29449f11c
--- /dev/null
+++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp
@@ -0,0 +1,111 @@
+/** 
+ * @file 
+ * @brief 
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ * 
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "../test/lltut.h"
+#include "llregionpresenceverifier.h"
+#include "llcurl_stub.cpp"
+#include "llhost.cpp"
+#include "net.cpp"
+#include "lltesthttpclientadapter.cpp"
+
+class LLTestResponse : public LLRegionPresenceVerifier::Response
+{
+public:
+
+	virtual bool checkValidity(const LLSD& content) const
+	{
+		return true;
+	}
+
+	virtual void onRegionVerified(const LLSD& region_details)
+	{
+	}
+
+	virtual void onRegionVerificationFailed()
+	{
+	}
+	
+	virtual LLHTTPClientInterface& getHttpClient()
+	{
+		return mHttpInterface;
+	}
+
+	LLTestHTTPClientAdapter mHttpInterface;
+};
+
+namespace tut
+{
+	struct LLRegionPresenceVerifierData
+	{
+		LLRegionPresenceVerifierData() :
+			mResponse(new LLTestResponse()),
+			mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse),
+					   LLSD(), 3)
+		{
+		}
+		
+		LLTestResponse* mResponse;
+		LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder;
+	};
+
+	typedef test_group<LLRegionPresenceVerifierData> factory;
+	typedef factory::object object;
+}
+
+namespace
+{
+	tut::factory tf("LLRegionPresenceVerifier test");
+}
+
+namespace tut
+{
+	// Test that VerifiedDestinationResponder does retry
+    // on error when shouldRetry returns true.
+	template<> template<>
+	void object::test<1>()
+	{
+		mResponder.error(500, "Internal server error");
+		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1);
+	}
+
+	// Test that VerifiedDestinationResponder only retries
+	// on error until shouldRetry returns false.
+	template<> template<>
+	void object::test<2>()
+	{
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		mResponder.error(500, "Internal server error");
+		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3);
+	}
+}
+
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index b925d97b5c9a375bbe58e4d9435d5c145be5c483..4e733ff56a2ac28271d4569202d295853b944cf0 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -746,16 +746,201 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
 
 	U32 old_face_mask = mVolumep->mFaceMask;
 
+	S32 face_bit = 0;
+	S32 cur_mask = 0;
+
+	// Grab copies of the old faces from the original shape, ordered by type.
+	// We will use these to figure out what old texture info gets mapped to new
+	// faces in the new shape.
+	std::vector<LLProfile::Face> old_faces; 
+	for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
+	{
+		old_faces.push_back(mVolumep->getProfile().mFaces[face]);
+	}
+
+	// Copy the old texture info off to the side, but not in the order in which
+	// they live in the mTextureList, rather in order of ther "face id" which
+	// is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex.
+	//
+	// Hence, some elements of old_tes::mEntryList will be invalid.  It is
+	// initialized to a size of 9 (max number of possible faces on a volume?)
+	// and only the ones with valid types are filled in.
+	LLPrimTextureList old_tes;
+	old_tes.setSize(9);
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		cur_mask = 0x1 << face_bit;
+		if (old_face_mask & cur_mask)
+		{
+			S32 te_index = face_index_from_id(cur_mask, old_faces);
+			old_tes.copyTexture(face_bit, *(getTE(te_index)));
+			//llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl;
+		}
+	}
+
+
 	// build the new object
 	sVolumeManager->unrefVolume(mVolumep);
 	mVolumep = volumep;
 	
 	U32 new_face_mask = mVolumep->mFaceMask;
-	if (old_face_mask != new_face_mask) 
+	S32 i;
+
+	if (old_face_mask == new_face_mask) 
 	{
+		// nothing to do
+		return TRUE;
+	}
+
+	if (mVolumep->getNumFaces() == 0 && new_face_mask != 0)
+	{
+		llwarns << "Object with 0 faces found...INCORRECT!" << llendl;
 		setNumTEs(mVolumep->getNumFaces());
+		return TRUE;
+	}
+
+	// initialize face_mapping
+	S32 face_mapping[9];
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		face_mapping[face_bit] = face_bit;
+	}
+
+	// The new shape may have more faces than the original, but we can't just
+	// add them to the end -- the ordering matters and it may be that we must
+	// insert the new faces in the middle of the list.  When we add a face it
+	// will pick up the texture/color info of one of the old faces an so we
+	// now figure out which old face info gets mapped to each new face, and 
+	// store in the face_mapping lookup table.
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		cur_mask = 0x1 << face_bit;
+		if (!(new_face_mask & cur_mask))
+		{
+			// Face doesn't exist in new map.
+			face_mapping[face_bit] = -1;
+			continue;
+		}
+		else if (old_face_mask & cur_mask)
+		{
+			// Face exists in new and old map.
+			face_mapping[face_bit] = face_bit;
+			continue;
+		}
+
+		// OK, how we've got a mismatch, where we have to fill a new face with one from
+		// the old face.
+		if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE))
+		{
+			// It's a top/bottom/hollow interior face.
+			if (old_face_mask & LL_FACE_PATH_END)
+			{
+				face_mapping[face_bit] = 1;
+				continue;
+			}
+			else
+			{
+				S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+				for (i = 0; i < 4; i++)
+				{
+					if (old_face_mask & cur_outer_mask)
+					{
+						face_mapping[face_bit] = 5 + i;
+						break;
+					}
+					cur_outer_mask <<= 1;
+				}
+				if (i == 4)
+				{
+					llwarns << "No path end or outer face in volume!" << llendl;
+				}
+				continue;
+			}
+		}
+
+		if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END))
+		{
+			// A cut slice.  Use the hollow interior if we have it.
+			if (old_face_mask & LL_FACE_INNER_SIDE)
+			{
+				face_mapping[face_bit] = 2;
+				continue;
+			}
+
+			// No interior, use the bottom face.
+			// Could figure out which of the outer faces was nearest, but that would be harder.
+			if (old_face_mask & LL_FACE_PATH_END)
+			{
+				face_mapping[face_bit] = 1;
+				continue;
+			}
+			else
+			{
+				S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
+				for (i = 0; i < 4; i++)
+				{
+					if (old_face_mask & cur_outer_mask)
+					{
+						face_mapping[face_bit] = 5 + i;
+						break;
+					}
+					cur_outer_mask <<= 1;
+				}
+				if (i == 4)
+				{
+					llwarns << "No path end or outer face in volume!" << llendl;
+				}
+				continue;
+			}
+		}
+
+		// OK, the face that's missing is an outer face...
+		// Pull from the nearest adjacent outer face (there's always guaranteed to be one...
+		S32 cur_outer = face_bit - 5;
+		S32 min_dist = 5;
+		S32 min_outer_bit = -1;
+		S32 i;
+		for (i = 0; i < 4; i++)
+		{
+			if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i))
+			{
+				S32 dist = abs(i - cur_outer);
+				if (dist < min_dist)
+				{
+					min_dist = dist;
+					min_outer_bit = i + 5;
+				}
+			}
+		}
+		if (-1 == min_outer_bit)
+		{
+			llinfos << (LLVolume *)mVolumep << llendl;
+			llwarns << "Bad!  No outer faces, impossible!" << llendl;
+		}
+		face_mapping[face_bit] = min_outer_bit;
 	}
+	
 
+	setNumTEs(mVolumep->getNumFaces());
+	for (face_bit = 0; face_bit < 9; face_bit++)
+	{
+		// For each possible face type on the new shape we check to see if that
+		// face exists and if it does we create a texture entry that is a copy
+		// of one of the originals.  Since the originals might not have a
+		// matching face, we use the face_mapping lookup table to figure out
+		// which face information to copy.
+		cur_mask = 0x1 << face_bit;
+		if (new_face_mask & cur_mask)
+		{
+			if (-1 == face_mapping[face_bit])
+			{
+				llwarns << "No mapping from old face to new face!" << llendl;
+			}
+
+			S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces);
+			setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
+		}
+	}
 	return TRUE;
 }
 
@@ -1714,10 +1899,10 @@ LLSD LLLightImageParams::asLLSD() const
 
 bool LLLightImageParams::fromLLSD(LLSD& sd)
 {
-	if (sd.has("texture") && sd.has("params") && sd["params"].size() == 3)
+	if (sd.has("texture"))
 	{
 		setLightTexture( sd["texture"] );
-		setParams( LLVector3(sd["params"][0].asReal(), sd["params"][1].asReal(), sd["params"][2].asReal()) );
+		setParams( LLVector3( sd["params"] ) );
 		return true;
 	} 
 	
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index d03150fc78b2b0873eedb452186087296679b61e..1c7de9597545627504c1c85cfb5cbeabc5bc7937 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -135,13 +135,12 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te)
 {
 	if (S32(index) >= mEntryList.size())
 	{
-		// TODO -- assert here
 		S32 current_size = mEntryList.size();
-		llerrs << "index = " << S32(index) << "  current_size = " << current_size << llendl;
+		llwarns << "ignore copy of index = " << S32(index) << " into texture entry list of size = " << current_size << llendl;
 		return TEM_CHANGE_NONE;
 	}
 
-	// we're changing an existing entry
+		// we're changing an existing entry
 	llassert(mEntryList[index]);
 	delete (mEntryList[index]);
 	if  (&te)
@@ -387,8 +386,18 @@ void LLPrimTextureList::setSize(S32 new_size)
 		mEntryList.resize(new_size);
 		for (S32 index = current_size; index < new_size; ++index)
 		{
-			LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
-			mEntryList[index] = new_entry;
+			if (current_size > 0
+				&& mEntryList[current_size - 1])
+			{
+				// copy the last valid entry for the new one
+				mEntryList[index] = mEntryList[current_size - 1]->newCopy();
+			}
+			else
+			{
+				// no valid enries to copy, so we new one up
+				LLTextureEntry* new_entry = LLPrimTextureList::newTextureEntry();
+				mEntryList[index] = new_entry;
+			}
 		}
 	}
 	else if (new_size < current_size)
diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index 93ac1203023c45ca049a259f1143718f8e183b51..315baa001d2a6a0c01596ac6e7d1a8e1e062af90 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -62,7 +62,7 @@ class LLPidLockFile
 			mSaving(FALSE), mWaiting(FALSE), 
 			mClean(TRUE), mPID(getpid())
 		{
-			mLockName = gDirUtilp->getTempDir() + "/savelock";
+			mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
 		}
 		bool requestLock(LLNameTable<void *> *name_table, bool autosave,
 						bool force_immediate=FALSE, F32 timeout=300.0);
diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h
index ba2c46bef253bf3a0fa685b7f49b8e26710159dc..a54ebd5831a122350e28e834443a8737a12ac562 100644
--- a/indra/lscript/lscript_byteformat.h
+++ b/indra/lscript/lscript_byteformat.h
@@ -556,7 +556,7 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
 // http_request string constants
 extern const char* URL_REQUEST_GRANTED;
 extern const char* URL_REQUEST_DENIED;
-extern const U64 LSL_HTTP_REQUEST_TIMEOUT;
+extern const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC;
 
 #endif
 
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index 98146d6f2bd9ba299ee838a6f5b55dd3ba8289a0..3b8bbbe805f57d305624ec53c6e119726a37fcb1 100644
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -631,9 +631,7 @@ static void print_cil_cast(LLFILE* fp, LSCRIPTType srcType, LSCRIPTType targetTy
 		switch(targetType)
 		{
 		case LST_INTEGER:
-			//fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
-			fprintf(fp, "conv.i4\n"); // TODO replace this line with the above
-			// we the entire grid is > 1.25.1
+			fprintf(fp, "call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)\n");
 			break;
 		case LST_STRING:
 			fprintf(fp, "call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ToString(float32)\n");
@@ -8375,10 +8373,18 @@ void LLScriptStateChange::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTComp
 			chunk->addInteger(mIdentifier->mScopeEntry->mCount);
 		}
 		break;
+	case LSCP_TYPE:
+		mReturnType = basetype;
+		break;
 	case LSCP_EMIT_CIL_ASSEMBLY:
 		fprintf(fp, "ldarg.0\n");
 		fprintf(fp, "ldstr \"%s\"\n", mIdentifier->mName);
 		fprintf(fp, "call instance void class [LslUserScript]LindenLab.SecondLife.LslUserScript::ChangeState(string)\n");
+		// We are doing a state change. In the LSL interpreter, this is basically a longjmp. We emulate it
+		// here using a call to the ChangeState followed by a short cut return of the current method. To
+		// maintain type safety we need to push an arbitrary variable of the current method's return type
+		// onto the stack before returning. This will be ignored and discarded.
+		print_cil_init_variable(fp, mReturnType);
 		fprintf(fp, "ret\n");
 		break;
 	default:
diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h
index 12c16908af2b6aab5313e63014dbd0b9b6979702..a667e1eb5b796fbbea67a1dd34793a7e06df6f54 100644
--- a/indra/lscript/lscript_compile/lscript_tree.h
+++ b/indra/lscript/lscript_compile/lscript_tree.h
@@ -1888,6 +1888,7 @@ class LLScriptStateChange : public LLScriptStatement
 	S32 getSize();
 
 	LLScriptIdentifier *mIdentifier;
+	LSCRIPTType mReturnType;
 };
 
 class LLScriptJump : public LLScriptStatement
diff --git a/indra/lscript/lscript_execute.h b/indra/lscript/lscript_execute.h
index 245fc320d1154ee84b0847bebba58adf2fb69332..96855abea0fdf7f9cd60a99c3df828277b1b5d83 100644
--- a/indra/lscript/lscript_execute.h
+++ b/indra/lscript/lscript_execute.h
@@ -371,8 +371,7 @@ class LLScriptExecute
 {
 public:
 	LLScriptExecute();
-	virtual ~LLScriptExecute() {;}
-
+	virtual ~LLScriptExecute()  = 0;
 	virtual S32 getVersion() const = 0;
 	virtual void deleteAllEvents() = 0;
 	virtual void addEvent(LLScriptDataCollection* event) = 0;
diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp
index 2fd81210c069ef68545d80e26fd51dbd03db552f..e849fa9a6e8532586fc8d70913b157e62917be7c 100644
--- a/indra/lscript/lscript_execute/lscript_execute.cpp
+++ b/indra/lscript/lscript_execute/lscript_execute.cpp
@@ -41,6 +41,8 @@
 #include "lscript_library.h"
 #include "lscript_heapruntime.h"
 #include "lscript_alloc.h"
+#include "llstat.h"
+
 
 // Static
 const	S32	DEFAULT_SCRIPT_TIMER_CHECK_SKIP = 4;
@@ -72,7 +74,7 @@ const char* URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED";
 const char* URL_REQUEST_DENIED = "URL_REQUEST_DENIED";
 
 // HTTP Requests to LSL scripts will time out after 25 seconds.
-const U64 LSL_HTTP_REQUEST_TIMEOUT = 25 * USEC_PER_SEC; 
+const U64 LSL_HTTP_REQUEST_TIMEOUT_USEC = 25 * USEC_PER_SEC; 
 
 LLScriptExecuteLSL2::LLScriptExecuteLSL2(LLFILE *fp)
 {
@@ -110,6 +112,7 @@ LLScriptExecuteLSL2::LLScriptExecuteLSL2(const U8* bytecode, U32 bytecode_size)
 	init();
 }
 
+LLScriptExecute::~LLScriptExecute() {}
 LLScriptExecuteLSL2::~LLScriptExecuteLSL2()
 {
 	delete[] mBuffer;
@@ -4234,19 +4237,16 @@ S32 lscript_push_variable(LLScriptLibData *data, U8 *buffer)
 	return 4;
 }
 
-BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+
+// Shared code for run_calllib() and run_calllib_two_byte()
+BOOL run_calllib_common(U8 *buffer, S32 &offset, const LLUUID &id, U16 arg)
 {
-	if (b_print)
-		printf("[0x%X]\tCALLLIB ", offset);
-	offset++;
-	U8 arg = safe_instruction_bytestream2byte(buffer, offset);
-	if (arg >= (U8)gScriptLibrary.mFunctions.size())
+	if (arg >= gScriptLibrary.mFunctions.size())
 	{
 		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
 		return FALSE;
 	}
-	if (b_print)
-		printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
+	LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
 
 	// pull out the arguments and the return values
 	LLScriptLibData	*arguments = NULL;
@@ -4254,14 +4254,14 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 
 	S32 i, number;
 
-	if (gScriptLibrary.mFunctions[arg].mReturnType)
+	if (function.mReturnType)
 	{
 		returnvalue = new LLScriptLibData;
 	}
 
-	if (gScriptLibrary.mFunctions[arg].mArgs)
+	if (function.mArgs)
 	{
-		number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs);		/*Flawfinder: ignore*/
+		number = (S32)strlen(function.mArgs);		//Flawfinder: ignore
 		arguments = new LLScriptLibData[number];
 	}
 	else
@@ -4271,23 +4271,18 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 
 	for (i = number - 1; i >= 0; i--)
 	{
-		lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
+		lscript_pop_variable(&arguments[i], buffer, function.mArgs[i]);
 	}
 
-	if (b_print)
-	{
-		printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
-	}
+	// Actually execute the function call
+	function.mExecFunc(returnvalue, arguments, id);
 
-	{
-		gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
-	}
-	add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
-	add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+	add_register_fp(buffer, LREG_ESR, -(function.mEnergyUse));
+	add_register_fp(buffer, LREG_SLR, function.mSleepTime);
 
 	if (returnvalue)
 	{
-		returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
+		returnvalue->mType = char2type(*function.mReturnType);
 		lscript_push_return_variable(returnvalue, buffer);
 	}
 
@@ -4304,71 +4299,32 @@ BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 }
 
 
-BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+BOOL run_calllib(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
 {
-	if (b_print)
-		printf("[0x%X]\tCALLLIB ", offset);
 	offset++;
-	U16 arg = safe_instruction_bytestream2u16(buffer, offset);
-	if (arg >= (U16)gScriptLibrary.mFunctions.size())
+	U16 arg = (U16) safe_instruction_bytestream2byte(buffer, offset);
+	if (b_print &&
+		arg < gScriptLibrary.mFunctions.size())
 	{
-		set_fault(buffer, LSRF_BOUND_CHECK_ERROR);
-		return FALSE;
-	}
-	if (b_print)
-		printf("%d (%s)\n", (U32)arg, gScriptLibrary.mFunctions[arg].mName);
-
-	// pull out the arguments and the return values
-	LLScriptLibData	*arguments = NULL;
-	LLScriptLibData	*returnvalue = NULL;
-
-	S32 i, number;
-
-	if (gScriptLibrary.mFunctions[arg].mReturnType)
-	{
-		returnvalue = new LLScriptLibData;
-	}
-
-	if (gScriptLibrary.mFunctions[arg].mArgs)
-	{
-		number = (S32)strlen(gScriptLibrary.mFunctions[arg].mArgs);		/*Flawfinder: ignore*/
-		arguments = new LLScriptLibData[number];
-	}
-	else
-	{
-		number = 0;
-	}
-
-	for (i = number - 1; i >= 0; i--)
-	{
-		lscript_pop_variable(&arguments[i], buffer, gScriptLibrary.mFunctions[arg].mArgs[i]);
-	}
-
-	if (b_print)
-	{
-		printf("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
-	}
-
-	{
-		gScriptLibrary.mFunctions[arg].mExecFunc(returnvalue, arguments, id);
+		printf("[0x%X]\tCALLLIB ", offset);
+		LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+		printf("%d (%s)\n", (U32)arg, function.mName);
+		//printf("%s\n", function.mDesc);
 	}
-	add_register_fp(buffer, LREG_ESR, -gScriptLibrary.mFunctions[arg].mEnergyUse);
-	add_register_fp(buffer, LREG_SLR, gScriptLibrary.mFunctions[arg].mSleepTime);
+	return run_calllib_common(buffer, offset, id, arg);
+}
 
-	if (returnvalue)
+BOOL run_calllib_two_byte(U8 *buffer, S32 &offset, BOOL b_print, const LLUUID &id)
+{
+	offset++;
+	U16 arg = safe_instruction_bytestream2u16(buffer, offset);
+	if (b_print &&
+		arg < gScriptLibrary.mFunctions.size())
 	{
-		returnvalue->mType = char2type(*gScriptLibrary.mFunctions[arg].mReturnType);
-		lscript_push_return_variable(returnvalue, buffer);
+		printf("[0x%X]\tCALLLIB ", (offset-1));
+		LLScriptLibraryFunction const & function = gScriptLibrary.mFunctions[arg];
+		printf("%d (%s)\n", (U32)arg, function.mName);
+		//printf("%s\n", function.mDesc);
 	}
-
-	delete [] arguments;
-	delete returnvalue;
-
-	// reset the BP after calling the library files
-	S32 bp = lscript_pop_int(buffer);
-	set_bp(buffer, bp);
-
-	// pop off the spot for the instruction pointer
-	lscript_poparg(buffer, 4);
-	return FALSE;
+	return run_calllib_common(buffer, offset, id, arg);
 }
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e4e4d8a2fa5c64011fc6a572c6dfb65c3fda5e7c..7b707a67203fc61374c2ea4c44e3e51d02d6065f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1542,6 +1542,7 @@ set(test_libs
   ${LLVFS_LIBRARIES}
   ${LLMATH_LIBRARIES}
   ${LLCOMMON_LIBRARIES} 
+  ${GOOGLEMOCK_LIBRARIES}
   )
 
 LL_ADD_INTEGRATION_TEST(llcapabilitylistener 
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 735424c64787ac02ecb5a4944adee4c8aab6efe2..0e685c818ac5b29ae0ddfb11125f6e3ea1b39aae 100644
--- a/indra/newview/English.lproj/InfoPlist.strings
+++ b/indra/newview/English.lproj/InfoPlist.strings
@@ -2,6 +2,6 @@
 
 CFBundleName = "Second Life";
 
-CFBundleShortVersionString = "Second Life version 2.0.0.0";
-CFBundleGetInfoString = "Second Life version 2.0.0.0, Copyright 2004-2009 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 2.0.0.2639";
+CFBundleGetInfoString = "Second Life version 2.0.0.2639, Copyright 2004-2009 Linden Research, Inc.";
 
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index 7264044d37c0a3c3bddc7a599cd99d43150fdd06..0c1d6ea10599c4c0f55f808d9f4fa201068ece25 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>2.0.0.0</string>
+	<string>2.0.0.2639</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
 </dict>
diff --git a/indra/newview/character/avatar_eye.llm b/indra/newview/character/avatar_eye.llm
new file mode 100644
index 0000000000000000000000000000000000000000..8c6e74e1deb8379e7f7dbc3e01106dadaf295f44
Binary files /dev/null and b/indra/newview/character/avatar_eye.llm differ
diff --git a/indra/newview/character/avatar_eye_1.llm b/indra/newview/character/avatar_eye_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..7a3b0d6f289b1d864da66ab276653a5fc4395a15
Binary files /dev/null and b/indra/newview/character/avatar_eye_1.llm differ
diff --git a/indra/newview/character/avatar_eyelashes.llm b/indra/newview/character/avatar_eyelashes.llm
new file mode 100644
index 0000000000000000000000000000000000000000..99995b575825e1eb1c79dab31177b9734a0ad313
Binary files /dev/null and b/indra/newview/character/avatar_eyelashes.llm differ
diff --git a/indra/newview/character/avatar_hair.llm b/indra/newview/character/avatar_hair.llm
new file mode 100644
index 0000000000000000000000000000000000000000..df99de8db7b5515b06dc0ce19a92c3a5f125b1b0
Binary files /dev/null and b/indra/newview/character/avatar_hair.llm differ
diff --git a/indra/newview/character/avatar_hair_1.llm b/indra/newview/character/avatar_hair_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..6de31fdc23a3c8dc996deceae24e0ad82b0e53ee
Binary files /dev/null and b/indra/newview/character/avatar_hair_1.llm differ
diff --git a/indra/newview/character/avatar_hair_2.llm b/indra/newview/character/avatar_hair_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..47d02ba9ce03df5269c3119ef38c880599513a2a
Binary files /dev/null and b/indra/newview/character/avatar_hair_2.llm differ
diff --git a/indra/newview/character/avatar_hair_3.llm b/indra/newview/character/avatar_hair_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..107f9e2a532cc1da9aa6ce39ce8a79b483519969
Binary files /dev/null and b/indra/newview/character/avatar_hair_3.llm differ
diff --git a/indra/newview/character/avatar_hair_4.llm b/indra/newview/character/avatar_hair_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..1b9a12a0cac620df8bda2fd1188f0d907eb1914b
Binary files /dev/null and b/indra/newview/character/avatar_hair_4.llm differ
diff --git a/indra/newview/character/avatar_hair_5.llm b/indra/newview/character/avatar_hair_5.llm
new file mode 100644
index 0000000000000000000000000000000000000000..1b9a12a0cac620df8bda2fd1188f0d907eb1914b
Binary files /dev/null and b/indra/newview/character/avatar_hair_5.llm differ
diff --git a/indra/newview/character/avatar_head.llm b/indra/newview/character/avatar_head.llm
new file mode 100644
index 0000000000000000000000000000000000000000..8d8b5e0442bb98c795c4b9ab6c64c13ff9eee79d
Binary files /dev/null and b/indra/newview/character/avatar_head.llm differ
diff --git a/indra/newview/character/avatar_head_1.llm b/indra/newview/character/avatar_head_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..26291e6584b57080c6257de7884a32c55ec5e862
Binary files /dev/null and b/indra/newview/character/avatar_head_1.llm differ
diff --git a/indra/newview/character/avatar_head_2.llm b/indra/newview/character/avatar_head_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..c2b808b1a61282d52106684cd566dcb86988795a
Binary files /dev/null and b/indra/newview/character/avatar_head_2.llm differ
diff --git a/indra/newview/character/avatar_head_3.llm b/indra/newview/character/avatar_head_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..a0676b1f1ce64686913cb67701412054349b2089
Binary files /dev/null and b/indra/newview/character/avatar_head_3.llm differ
diff --git a/indra/newview/character/avatar_head_4.llm b/indra/newview/character/avatar_head_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..5035585770bfff0018608d552ea8f9e660c24fbb
Binary files /dev/null and b/indra/newview/character/avatar_head_4.llm differ
diff --git a/indra/newview/character/avatar_lower_body.llm b/indra/newview/character/avatar_lower_body.llm
new file mode 100644
index 0000000000000000000000000000000000000000..04208997399f46846dd4054c4890127155dbf070
Binary files /dev/null and b/indra/newview/character/avatar_lower_body.llm differ
diff --git a/indra/newview/character/avatar_lower_body_1.llm b/indra/newview/character/avatar_lower_body_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..1394eb848b3995d333906f293b870bd3b3310cc6
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_1.llm differ
diff --git a/indra/newview/character/avatar_lower_body_2.llm b/indra/newview/character/avatar_lower_body_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..0da9c1249ea4bd0cd6fcf29d21e1dc151c5ec100
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_2.llm differ
diff --git a/indra/newview/character/avatar_lower_body_3.llm b/indra/newview/character/avatar_lower_body_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..f3c49a1568d76ff16c454ff0b1fa4fafccd3b74a
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_3.llm differ
diff --git a/indra/newview/character/avatar_lower_body_4.llm b/indra/newview/character/avatar_lower_body_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..e71721063ec39d799592c493b65706b76e2999c2
Binary files /dev/null and b/indra/newview/character/avatar_lower_body_4.llm differ
diff --git a/indra/newview/character/avatar_skirt.llm b/indra/newview/character/avatar_skirt.llm
new file mode 100644
index 0000000000000000000000000000000000000000..08ce3d170039ff5d2e099346ac95b128aec4866c
Binary files /dev/null and b/indra/newview/character/avatar_skirt.llm differ
diff --git a/indra/newview/character/avatar_skirt_1.llm b/indra/newview/character/avatar_skirt_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..88076c321f787d62eee2496d12510ed405c2a96d
Binary files /dev/null and b/indra/newview/character/avatar_skirt_1.llm differ
diff --git a/indra/newview/character/avatar_skirt_2.llm b/indra/newview/character/avatar_skirt_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..73b3effbc600a3e92ec695c3133aa92c2d8c528d
Binary files /dev/null and b/indra/newview/character/avatar_skirt_2.llm differ
diff --git a/indra/newview/character/avatar_skirt_3.llm b/indra/newview/character/avatar_skirt_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..ded546fdeadeaf9ce914dd05a9004cc88de25098
Binary files /dev/null and b/indra/newview/character/avatar_skirt_3.llm differ
diff --git a/indra/newview/character/avatar_skirt_4.llm b/indra/newview/character/avatar_skirt_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..b9d5cb945e3fc0b91cbf882a4df824223f7537c9
Binary files /dev/null and b/indra/newview/character/avatar_skirt_4.llm differ
diff --git a/indra/newview/character/avatar_upper_body.llm b/indra/newview/character/avatar_upper_body.llm
new file mode 100644
index 0000000000000000000000000000000000000000..da7d99054093854e6da5e0fd94e69c9d5e3a5800
Binary files /dev/null and b/indra/newview/character/avatar_upper_body.llm differ
diff --git a/indra/newview/character/avatar_upper_body_1.llm b/indra/newview/character/avatar_upper_body_1.llm
new file mode 100644
index 0000000000000000000000000000000000000000..31e104cc20b5c7bd6f7c2aae1880778eade1870e
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_1.llm differ
diff --git a/indra/newview/character/avatar_upper_body_2.llm b/indra/newview/character/avatar_upper_body_2.llm
new file mode 100644
index 0000000000000000000000000000000000000000..c1f4199b9c943a4e3fb01dc4cb28ae8ccd0dcab5
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_2.llm differ
diff --git a/indra/newview/character/avatar_upper_body_3.llm b/indra/newview/character/avatar_upper_body_3.llm
new file mode 100644
index 0000000000000000000000000000000000000000..9e89ed8b3e112cecf66e77de1f9dd14d5cb5267f
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_3.llm differ
diff --git a/indra/newview/character/avatar_upper_body_4.llm b/indra/newview/character/avatar_upper_body_4.llm
new file mode 100644
index 0000000000000000000000000000000000000000..ec836d1dc3aebe9e570d6b33b421e87b4e9fda12
Binary files /dev/null and b/indra/newview/character/avatar_upper_body_4.llm differ
diff --git a/indra/newview/character/blush_alpha.tga b/indra/newview/character/blush_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..05be7e7e3d7f37dc76b90bee270e5597e8b2e322
Binary files /dev/null and b/indra/newview/character/blush_alpha.tga differ
diff --git a/indra/newview/character/body_skingrain.tga b/indra/newview/character/body_skingrain.tga
new file mode 100644
index 0000000000000000000000000000000000000000..7264baac144fd5d9fe8b4bbb47f97b0c4d5ff430
Binary files /dev/null and b/indra/newview/character/body_skingrain.tga differ
diff --git a/indra/newview/character/bodyfreckles_alpha.tga b/indra/newview/character/bodyfreckles_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..d30ab3d122607cf445420eb107c2457ee5ccb783
Binary files /dev/null and b/indra/newview/character/bodyfreckles_alpha.tga differ
diff --git a/indra/newview/character/bump_face_wrinkles.tga b/indra/newview/character/bump_face_wrinkles.tga
new file mode 100644
index 0000000000000000000000000000000000000000..54bf7a55be3fe90f306b454b18a7d7df18acac8c
Binary files /dev/null and b/indra/newview/character/bump_face_wrinkles.tga differ
diff --git a/indra/newview/character/bump_head_base.tga b/indra/newview/character/bump_head_base.tga
new file mode 100644
index 0000000000000000000000000000000000000000..fa3568573a4694b28dfce80e28ab6b4bca3a5d48
Binary files /dev/null and b/indra/newview/character/bump_head_base.tga differ
diff --git a/indra/newview/character/bump_lowerbody_base.tga b/indra/newview/character/bump_lowerbody_base.tga
new file mode 100644
index 0000000000000000000000000000000000000000..498ea3c721dc34f8768f16e8f5f824c8de066089
Binary files /dev/null and b/indra/newview/character/bump_lowerbody_base.tga differ
diff --git a/indra/newview/character/bump_pants_wrinkles.tga b/indra/newview/character/bump_pants_wrinkles.tga
new file mode 100644
index 0000000000000000000000000000000000000000..cca72415e808d0a760ba88041316659697d4df31
Binary files /dev/null and b/indra/newview/character/bump_pants_wrinkles.tga differ
diff --git a/indra/newview/character/bump_shirt_wrinkles.tga b/indra/newview/character/bump_shirt_wrinkles.tga
new file mode 100644
index 0000000000000000000000000000000000000000..9e0d757a48ac8f35985f27d04a66bcc42d585a1d
Binary files /dev/null and b/indra/newview/character/bump_shirt_wrinkles.tga differ
diff --git a/indra/newview/character/bump_upperbody_base.tga b/indra/newview/character/bump_upperbody_base.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e57d6352e6ad449d80690b82c920a9a33c37f32a
Binary files /dev/null and b/indra/newview/character/bump_upperbody_base.tga differ
diff --git a/indra/newview/character/eyebrows_alpha.tga b/indra/newview/character/eyebrows_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..c363e482e13e1c9437fdb7c11444e4b894aa34b4
Binary files /dev/null and b/indra/newview/character/eyebrows_alpha.tga differ
diff --git a/indra/newview/character/eyeliner_alpha.tga b/indra/newview/character/eyeliner_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..1611eb3355c07ce404223a42f081c749dc4ec3ff
Binary files /dev/null and b/indra/newview/character/eyeliner_alpha.tga differ
diff --git a/indra/newview/character/eyeshadow_inner_alpha.tga b/indra/newview/character/eyeshadow_inner_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..37d791939578dbacbe6a8768a46431406c5a0854
Binary files /dev/null and b/indra/newview/character/eyeshadow_inner_alpha.tga differ
diff --git a/indra/newview/character/eyeshadow_outer_alpha.tga b/indra/newview/character/eyeshadow_outer_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..00eef9d9f7cf40ab48ad7e941a99b9f03f0c7eb6
Binary files /dev/null and b/indra/newview/character/eyeshadow_outer_alpha.tga differ
diff --git a/indra/newview/character/eyewhite.tga b/indra/newview/character/eyewhite.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a720496988e33e69e4cedc05744dc0b3fb035b5a
Binary files /dev/null and b/indra/newview/character/eyewhite.tga differ
diff --git a/indra/newview/character/facehair_chincurtains_alpha.tga b/indra/newview/character/facehair_chincurtains_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..b10397063c08f084891baae79a24dfacc06f5964
Binary files /dev/null and b/indra/newview/character/facehair_chincurtains_alpha.tga differ
diff --git a/indra/newview/character/facehair_moustache_alpha.tga b/indra/newview/character/facehair_moustache_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..4068c4f2b139688c99ec444bc9fc58a1b2d3a3ba
Binary files /dev/null and b/indra/newview/character/facehair_moustache_alpha.tga differ
diff --git a/indra/newview/character/facehair_sideburns_alpha.tga b/indra/newview/character/facehair_sideburns_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..acddc2d9bddfcc242fc9bb7671bfa34177179983
Binary files /dev/null and b/indra/newview/character/facehair_sideburns_alpha.tga differ
diff --git a/indra/newview/character/facehair_soulpatch_alpha.tga b/indra/newview/character/facehair_soulpatch_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..687091a29f6a83761d1886828a26be70d52b108a
Binary files /dev/null and b/indra/newview/character/facehair_soulpatch_alpha.tga differ
diff --git a/indra/newview/character/freckles_alpha.tga b/indra/newview/character/freckles_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a9a4ec073531c19b3588bb7ad9531caf070d2694
Binary files /dev/null and b/indra/newview/character/freckles_alpha.tga differ
diff --git a/indra/newview/character/glove_length_alpha.tga b/indra/newview/character/glove_length_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..db89ad57e7c52a73e8801bd3b0597a596bb59a16
Binary files /dev/null and b/indra/newview/character/glove_length_alpha.tga differ
diff --git a/indra/newview/character/gloves_fingers_alpha.tga b/indra/newview/character/gloves_fingers_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..dba2eec2777c7021b2e897c728ac549a2ca50cad
Binary files /dev/null and b/indra/newview/character/gloves_fingers_alpha.tga differ
diff --git a/indra/newview/character/head_alpha.tga b/indra/newview/character/head_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..8164525353a764ff53aab784a2c6e1d8d0056607
Binary files /dev/null and b/indra/newview/character/head_alpha.tga differ
diff --git a/indra/newview/character/head_color.tga b/indra/newview/character/head_color.tga
new file mode 100644
index 0000000000000000000000000000000000000000..74b1b3078b3b60df9854086b839f8383cf4dea88
Binary files /dev/null and b/indra/newview/character/head_color.tga differ
diff --git a/indra/newview/character/head_hair.tga b/indra/newview/character/head_hair.tga
new file mode 100644
index 0000000000000000000000000000000000000000..5321f35204b09610a332c40486f47f19060561ff
Binary files /dev/null and b/indra/newview/character/head_hair.tga differ
diff --git a/indra/newview/character/head_highlights_alpha.tga b/indra/newview/character/head_highlights_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..8dc5239f977da36f8f36ce3bdb62b23f12aed758
Binary files /dev/null and b/indra/newview/character/head_highlights_alpha.tga differ
diff --git a/indra/newview/character/head_shading_alpha.tga b/indra/newview/character/head_shading_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e8ea490109d8c5401633ea33ad296aa507d8c9b3
Binary files /dev/null and b/indra/newview/character/head_shading_alpha.tga differ
diff --git a/indra/newview/character/head_skingrain.tga b/indra/newview/character/head_skingrain.tga
new file mode 100644
index 0000000000000000000000000000000000000000..b42dee08090b967ffe4db4fae19533a316cb030e
Binary files /dev/null and b/indra/newview/character/head_skingrain.tga differ
diff --git a/indra/newview/character/jacket_length_lower_alpha.tga b/indra/newview/character/jacket_length_lower_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..722bc192a832dd887ef7c90eee4055a6447cbcac
Binary files /dev/null and b/indra/newview/character/jacket_length_lower_alpha.tga differ
diff --git a/indra/newview/character/jacket_length_upper_alpha.tga b/indra/newview/character/jacket_length_upper_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e9db7e7b1fa8cc81c046200c2a497cf852d2cd5e
Binary files /dev/null and b/indra/newview/character/jacket_length_upper_alpha.tga differ
diff --git a/indra/newview/character/jacket_open_lower_alpha.tga b/indra/newview/character/jacket_open_lower_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..db0c2fb0e3ebc004b44a42168ecb9d0fd7a10ea7
Binary files /dev/null and b/indra/newview/character/jacket_open_lower_alpha.tga differ
diff --git a/indra/newview/character/jacket_open_upper_alpha.tga b/indra/newview/character/jacket_open_upper_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..71b8a0b805b0fcbb3cd17077a9624aee944d6228
Binary files /dev/null and b/indra/newview/character/jacket_open_upper_alpha.tga differ
diff --git a/indra/newview/character/lipgloss_alpha.tga b/indra/newview/character/lipgloss_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..78ceecaf85a5b157083f05973f65702ef45429bb
Binary files /dev/null and b/indra/newview/character/lipgloss_alpha.tga differ
diff --git a/indra/newview/character/lips_mask.tga b/indra/newview/character/lips_mask.tga
new file mode 100644
index 0000000000000000000000000000000000000000..ae1401c006adda76985ed7eeaa5336c471c40f87
Binary files /dev/null and b/indra/newview/character/lips_mask.tga differ
diff --git a/indra/newview/character/lipstick_alpha.tga b/indra/newview/character/lipstick_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..2795f1bd40f076eded229e25ecfdeba83a662a3d
Binary files /dev/null and b/indra/newview/character/lipstick_alpha.tga differ
diff --git a/indra/newview/character/lowerbody_color.tga b/indra/newview/character/lowerbody_color.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a63aa12fca04bb16b23f6f8bdc168371b6a7960b
Binary files /dev/null and b/indra/newview/character/lowerbody_color.tga differ
diff --git a/indra/newview/character/lowerbody_highlights_alpha.tga b/indra/newview/character/lowerbody_highlights_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..ae3413ac8bd98507416f565ebf9d9119342f62a2
Binary files /dev/null and b/indra/newview/character/lowerbody_highlights_alpha.tga differ
diff --git a/indra/newview/character/lowerbody_shading_alpha.tga b/indra/newview/character/lowerbody_shading_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..0242663a7db248b6e6af96fcc9168ee917067476
Binary files /dev/null and b/indra/newview/character/lowerbody_shading_alpha.tga differ
diff --git a/indra/newview/character/nailpolish_alpha.tga b/indra/newview/character/nailpolish_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..91af762902820acca0e0630438f7b19aef5136ed
Binary files /dev/null and b/indra/newview/character/nailpolish_alpha.tga differ
diff --git a/indra/newview/character/pants_length_alpha.tga b/indra/newview/character/pants_length_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..3c4f21c0f2ab5743e804179d792db45e69885b2e
Binary files /dev/null and b/indra/newview/character/pants_length_alpha.tga differ
diff --git a/indra/newview/character/pants_waist_alpha.tga b/indra/newview/character/pants_waist_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..35658c08968a9202710a82ba7d11b4f6c792f8cc
Binary files /dev/null and b/indra/newview/character/pants_waist_alpha.tga differ
diff --git a/indra/newview/character/rosyface_alpha.tga b/indra/newview/character/rosyface_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a0c8513da2f860da84825a17b980bdc2f963fc82
Binary files /dev/null and b/indra/newview/character/rosyface_alpha.tga differ
diff --git a/indra/newview/character/rouge_alpha.tga b/indra/newview/character/rouge_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..a0c8513da2f860da84825a17b980bdc2f963fc82
Binary files /dev/null and b/indra/newview/character/rouge_alpha.tga differ
diff --git a/indra/newview/character/shirt_bottom_alpha.tga b/indra/newview/character/shirt_bottom_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..7cce03dbe040bc7cbe25a2b4f4be579327d12961
Binary files /dev/null and b/indra/newview/character/shirt_bottom_alpha.tga differ
diff --git a/indra/newview/character/shirt_collar_alpha.tga b/indra/newview/character/shirt_collar_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..f55f635473413cacd722c5e2b04c81e78f9a2c72
Binary files /dev/null and b/indra/newview/character/shirt_collar_alpha.tga differ
diff --git a/indra/newview/character/shirt_collar_back_alpha.tga b/indra/newview/character/shirt_collar_back_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..43a645310739931da7f9216cdde577c78a04445b
Binary files /dev/null and b/indra/newview/character/shirt_collar_back_alpha.tga differ
diff --git a/indra/newview/character/shirt_sleeve_alpha.tga b/indra/newview/character/shirt_sleeve_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e3b18f4fc69578f65c7dda9b675cc101fa389a60
Binary files /dev/null and b/indra/newview/character/shirt_sleeve_alpha.tga differ
diff --git a/indra/newview/character/shoe_height_alpha.tga b/indra/newview/character/shoe_height_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..d08dd750f308982b4200b04f1722814474412843
Binary files /dev/null and b/indra/newview/character/shoe_height_alpha.tga differ
diff --git a/indra/newview/character/skirt_length_alpha.tga b/indra/newview/character/skirt_length_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..c86799469d5fdadc6e0e614ab45060685b0e1695
Binary files /dev/null and b/indra/newview/character/skirt_length_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_back_alpha.tga b/indra/newview/character/skirt_slit_back_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..0e49688b146a55e7d776a80ddb65ff81bffa3202
Binary files /dev/null and b/indra/newview/character/skirt_slit_back_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_front_alpha.tga b/indra/newview/character/skirt_slit_front_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..888bbf71a1193cbc9ff4a564e6c0837f6affab5a
Binary files /dev/null and b/indra/newview/character/skirt_slit_front_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_left_alpha.tga b/indra/newview/character/skirt_slit_left_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..210feac1ea0e4014ddd8187e1460ef1781a5c8e0
Binary files /dev/null and b/indra/newview/character/skirt_slit_left_alpha.tga differ
diff --git a/indra/newview/character/skirt_slit_right_alpha.tga b/indra/newview/character/skirt_slit_right_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..ce11c64bf6763e517b16f4c0d70f02065132e4c2
Binary files /dev/null and b/indra/newview/character/skirt_slit_right_alpha.tga differ
diff --git a/indra/newview/character/underpants_trial_female.tga b/indra/newview/character/underpants_trial_female.tga
new file mode 100644
index 0000000000000000000000000000000000000000..96bf732351786a699ae30e74ef2fed61b14b87b6
Binary files /dev/null and b/indra/newview/character/underpants_trial_female.tga differ
diff --git a/indra/newview/character/underpants_trial_male.tga b/indra/newview/character/underpants_trial_male.tga
new file mode 100644
index 0000000000000000000000000000000000000000..095695ca1c47993db36460a35071b9f0a5c16fc9
Binary files /dev/null and b/indra/newview/character/underpants_trial_male.tga differ
diff --git a/indra/newview/character/undershirt_trial_female.tga b/indra/newview/character/undershirt_trial_female.tga
new file mode 100644
index 0000000000000000000000000000000000000000..e17a30953154e0b135fda708c90eeddbd4189034
Binary files /dev/null and b/indra/newview/character/undershirt_trial_female.tga differ
diff --git a/indra/newview/character/upperbody_color.tga b/indra/newview/character/upperbody_color.tga
new file mode 100644
index 0000000000000000000000000000000000000000..85fcc41142102114244c28c9743d97b119e2f3e1
Binary files /dev/null and b/indra/newview/character/upperbody_color.tga differ
diff --git a/indra/newview/character/upperbody_highlights_alpha.tga b/indra/newview/character/upperbody_highlights_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..2d8102b583d3a8346afb6cb671b9b7f9f3d3780d
Binary files /dev/null and b/indra/newview/character/upperbody_highlights_alpha.tga differ
diff --git a/indra/newview/character/upperbody_shading_alpha.tga b/indra/newview/character/upperbody_shading_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..b420506b3e1407d0eb0b8bd07f63621dba6be557
Binary files /dev/null and b/indra/newview/character/upperbody_shading_alpha.tga differ
diff --git a/indra/newview/character/upperbodyfreckles_alpha.tga b/indra/newview/character/upperbodyfreckles_alpha.tga
new file mode 100644
index 0000000000000000000000000000000000000000..76c7ce8849f59a2355b55d7454af4c6703772050
Binary files /dev/null and b/indra/newview/character/upperbodyfreckles_alpha.tga differ
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 390e1fe032730b57bdad796fb542163a9e79fd62..5e000bba6db7cfcb7cf13c99b0a09351b4b9f3c1 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5607,7 +5607,8 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
 	LLPanelLandCovenant::updateLastModified(last_modified);
 	LLFloaterBuyLand::updateLastModified(last_modified);
 
-	gCacheName->get(estate_owner_id, false, &callbackCacheEstateOwnerName);
+	BOOL is_group = FALSE;
+	gCacheName->get(estate_owner_id, is_group, &callbackCacheEstateOwnerName);
 	
 	// load the actual covenant asset data
 	const BOOL high_priority = TRUE;
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 6401389c8f51dfb629df4d151bcf5ce4b36f3512..3c1ac3d571bce451a10cca0d97e29d8923d95ded 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -6921,7 +6921,8 @@ void LLVoiceClient::notifyFriendObservers()
 
 void LLVoiceClient::lookupName(const LLUUID &id)
 {
-	gCacheName->get(id, FALSE, &LLVoiceClient::onAvatarNameLookup);
+	BOOL is_group = FALSE;
+	gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup);
 }
 
 //static
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index 87a8bd5787a2e240630222c819a5fcb3511cbfab..bdf76317706d1b25c5cd4834d56333388d0672b3 100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -138,8 +138,8 @@ TOOLMEDIAOPEN           CURSOR                  "toolmediaopen.cur"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,0,0,0
- PRODUCTVERSION 2,0,0,0
+ FILEVERSION 2,0,0,2639
+ PRODUCTVERSION 2,0,0,2639
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -156,12 +156,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Linden Lab"
             VALUE "FileDescription", "Second Life"
-            VALUE "FileVersion", "2.0.0.0"
+            VALUE "FileVersion", "2.0.0.2639"
             VALUE "InternalName", "Second Life"
-            VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."
+            VALUE "LegalCopyright", "Copyright � 2001-2008, Linden Research, Inc."
             VALUE "OriginalFilename", "SecondLife.exe"
             VALUE "ProductName", "Second Life"
-            VALUE "ProductVersion", "2.0.0.0"
+            VALUE "ProductVersion", "2.0.0.2639"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 463eedb4fd2fb50117f03898d9d0a1f8444c34f6..98ad8af02d9d6d445dc007d9a7da03c8b9caaac5 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -14,6 +14,7 @@ include(LScript)
 include(Linking)
 include(Tut)
 include(Boost)
+include(GoogleMock)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
@@ -24,6 +25,7 @@ include_directories(
     ${LLVFS_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
     ${LSCRIPT_INCLUDE_DIRS}
+    ${GOOGLEMOCK_INCLUDE_DIRS}
     )
 
 set(test_SOURCE_FILES
@@ -126,6 +128,7 @@ target_link_libraries(test
     ${LLXML_LIBRARIES}
     ${LSCRIPT_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
+    ${GOOGLEMOCK_LIBRARIES}
     ${APRICONV_LIBRARIES}
     ${PTHREAD_LIBRARY}
     ${WINDOWS_LIBRARIES}
@@ -145,12 +148,18 @@ endif (WINDOWS)
 
 get_target_property(TEST_EXE test LOCATION)
 
+SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(TEST_LD_CMD 
+  ${CMAKE_COMMAND} 
+  -DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
+  -DTEST_CMD:STRING="${TEST_CMD}" 
+  -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
+  )
+
 add_custom_command(
   OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
-  COMMAND ${TEST_EXE}
-  ARGS
-    --output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt
-    --touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt
+  COMMAND ${TEST_LD_CMD}
   DEPENDS test
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   COMMENT "C++ unit tests"
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index ba81c6e49e96067384fd12803b79bea39c4c07d4..e7ba8e33b8c19a59f6fa44d05dec56d661bd5990 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -54,6 +54,11 @@
 #	include "ctype_workaround.h"
 #endif
 
+#ifndef LL_WINDOWS
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#endif
+
 namespace tut
 {
 	std::string sSourceDir;
@@ -238,6 +243,11 @@ void wouldHaveCrashed(const std::string& message)
 
 int main(int argc, char **argv)
 {
+	// The following line must be executed to initialize Google Mock
+	// (and Google Test) before running the tests.
+#ifndef LL_WINDOWS
+	::testing::InitGoogleMock(&argc, argv);
+#endif
 	LLError::initForApplication(".");
 	LLError::setFatalFunction(wouldHaveCrashed);
 	LLError::setDefaultLevel(LLError::LEVEL_ERROR);
diff --git a/install.xml b/install.xml
index 6366b3104b807beb30d8d86871a4fa41684feb4a..225dc76a9aff0e6915c53d275434d47b6a61910b 100644
--- a/install.xml
+++ b/install.xml
@@ -578,6 +578,39 @@
           </map>
         </map>
       </map>
+      <key>googlemock</key>
+      <map>
+        <key>copyright</key>
+        <string>Copyright 2008, Google Inc.</string>
+        <key>description</key>
+        <string>Google C++ Mocking Framework (or Google Mock for short) is a library for writing and using C++ mock classes.</string>
+        <key>license</key>
+        <string>bsd</string>
+        <key>packages</key>
+        <map>
+          <key>darwin</key>
+          <map>
+            <key>md5sum</key>
+            <string>4863e9fea433d0a4be761ea5d3e8346a</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-darwin-20090626.tar.bz2</uri>
+          </map>
+          <key>linux</key>
+          <map>
+            <key>md5sum</key>
+            <string>877dabecf84339690191c6115c76366e</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-linux32-20090527.tar.bz2</uri>
+          </map>
+          <key>windows</key>
+          <map>
+            <key>md5sum</key>
+            <string>be37695d9f26552aec81c8e97ded0212</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-windows-20090529.tar.bz2</uri>
+          </map>
+        </map>
+      </map>
       <key>google-perftools</key>
       <map>
         <key>copyright</key>
diff --git a/scripts/install.py b/scripts/install.py
index 6278fba16cb5897f951fd543b76a7759df524c0a..78b8880b95ca09c0de1bc883394fa970e5efdb87 100755
--- a/scripts/install.py
+++ b/scripts/install.py
@@ -64,7 +64,6 @@ def add_indra_lib_path():
 base_dir = add_indra_lib_path()
 
 import copy
-import md5
 import optparse
 import os
 import platform
@@ -75,7 +74,12 @@ def add_indra_lib_path():
 import urllib2
 import urlparse
 
-from sets import Set as set, ImmutableSet as frozenset
+try:
+    # Python 2.6
+    from hashlib import md5
+except ImportError:
+    # Python 2.5 and earlier
+    from md5 import new as md5
 
 from indra.base import llsd
 from indra.util import helpformatter
@@ -106,7 +110,7 @@ def __str__(self):
         return "ifile{%s:%s}" % (self.pkgname, self.url)
 
     def _is_md5sum_match(self):
-        hasher = md5.new(file(self.filename, 'rb').read())
+        hasher = md5(file(self.filename, 'rb').read())
         if hasher.hexdigest() == self.md5sum:
             return  True
         return False
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 0ddd0dbcdb60d870decaaee4e7e0bdbe379ed8fd..f0c6780938b9bbc6fd2ed155e247a5b1756c3f67 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -5288,6 +5288,10 @@ version 2.0
 		{	AgentLegacyAccess		U8	}
 		{	AgentMaxAccess			U8	}
 	}
+	{
+		AgentInfo				Variable
+		{	Flags					U32	}
+	}
 }
 
 // ChildAgentAlive
diff --git a/scripts/update_version_files.py b/scripts/update_version_files.py
index 9081941521709e01df401be093179d5a7017f32f..ee1ce69a15bb5d865f3f6c6a4e0a647e15b23b43 100755
--- a/scripts/update_version_files.py
+++ b/scripts/update_version_files.py
@@ -241,23 +241,17 @@ def main():
         if update_server:
             server_version = new_version
     else:
-        # Assume we're updating just the build number
-        cl = '%s info "%s"' % (svn, src_root)
-        status, output = _getstatusoutput(cl)
-        if verbose:
-            print
-            print "svn info output:"
-            print "----------------"
-            print output
-
-        branch_match = svn_branch_re.search(output)
-        revision_match = svn_revision_re.search(output)
-        if not branch_match or not revision_match:
-            print "Failed to execute svn info, output follows:"
-            print output
+
+        if llversion.using_svn():
+            revision = llversion.get_svn_revision()
+            branch = llversion.get_svn_branch()
+        elif llversion.using_hg():
+            revision = llversion.get_hg_changeset()
+            branch = llversion.get_hg_repo()
+        else:
+            print >>sys.stderr, "ERROR: could not determine revision and branch"
             return -1
-        branch = branch_match.group(1)
-        revision = revision_match.group(1)
+        
         if skip_on_branch_re and skip_on_branch_re.match(branch):
             print "Release Candidate Build, leaving version files untouched."
             return 0