diff --git a/.hgtags b/.hgtags
index 59b516bf928e9259c855c94f27785093c2ffb18b..13d301fd4526ed5904ac9a256c8643e0a5cdaafd 100644
--- a/.hgtags
+++ b/.hgtags
@@ -35,3 +35,5 @@ b0cd7e150009809a0b5b0a9d5785cd4bb230413a 2.2.0-beta3
 a3c12342b1af0951b8aa3b828aacef17fcea8178 2.3.0-beta1
 db0fe9bb65187f365e58a717dd23d0f4754a9c1d 2.3.0-beta2
 6ad3d6fa35a4e320e9ce442fce2bf9c7fc852556 2.3.0-beta3
+6ad3d6fa35a4e320e9ce442fce2bf9c7fc852556 2.3.0-release
+dbc206fc61d89ff4cfe15aade0bf0c7bc7fee1c9 2.4.0-start
diff --git a/BuildParams b/BuildParams
index 8bd72d2ce8da445faac0add37ee69814b4d7dbdb..abeaebae984f95ca6f7c4beb8a2a5a64e0b8446a 100644
--- a/BuildParams
+++ b/BuildParams
@@ -51,7 +51,7 @@ viewer-release.viewer_channel = "Second Life Release"
 viewer-release.login_channel = "Second Life Release"
 viewer-release.build_debug_release_separately = true
 viewer-release.build_viewer_update_version_manager = true
-
+viewer-release.release-viewer.jira = DRTVWR-13
 
 # ========================================
 # aimee
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 7773de47f8f2d10e8f9670ed41402318f4ede31c..adfee2cce9c0885026d90ada659423e870e91328 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -355,6 +355,7 @@ Joghert LeSabre
 	VWR-64
 Jonathan Yap
 	VWR-17801
+	STORM-616
 Kage Pixel
 	VWR-11
 Ken March
@@ -767,6 +768,9 @@ WolfPup Lowenhar
 	STORM-102
 	STORM-103
 	STORM-143
+	STORM-535
+	STORM-544
+	STORM-654
 	VWR-20741
 	VWR-20933
 Zai Lynch
diff --git a/etc/message.xml b/etc/message.xml
index ebbb4e57a96fafd0407f74861500e67daf1916cf..7c4a927cc5e7997b7533e98ec4d2143c60f19b87 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -442,6 +442,14 @@
           <boolean>true</boolean>
         </map>
 
+        <key>SimConsoleResponse</key>
+        <map>
+          <key>flavor</key>
+          <string>llsd</string>
+          <key>trusted-sender</key>
+          <boolean>true</boolean>
+        </map>
+
         <key>DirLandReply</key>
         <map>
           <key>flavor</key>
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 8d4969a49ea7100e8bf6e35df302d7437067cc60..d01e1869b6983dfbb1116499330bdbb783504e54 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -22,7 +22,10 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
 include(Variables)
 
 if (DARWIN)
-  cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
+  # 2.6.4 fixes a Mac bug in get_target_property(... "SLPlugin" LOCATION):
+  # before that version it returns "pathname/SLPlugin", whereas the correct
+  # answer is "pathname/SLPlugin.app/Contents/MacOS/SLPlugin".
+  cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR)
 endif (DARWIN)
 
 if (NOT CMAKE_BUILD_TYPE)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index a114d6e7783497b8ad194ee5eb9263617ca1c560..db2cdb5ff8fa3f41e8f41621d3067f0797d80ca0 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -38,10 +38,10 @@ if (WINDOWS)
   set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP"
       CACHE STRING "C++ compiler debug options" FORCE)
   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO 
-      "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP"
+      "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP /Ob2"
       CACHE STRING "C++ compiler release-with-debug options" FORCE)
   set(CMAKE_CXX_FLAGS_RELEASE
-      "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP"
+      "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /Ob2"
       CACHE STRING "C++ compiler release options" FORCE)
 
   set(CMAKE_CXX_STANDARD_LIBRARIES "")
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 79c3bb7da25b3d3d4417f44335aa6a30e5d1b695..29e2492551cfd3f0b81c8708d860da14416ccf0c 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -1,265 +1,273 @@
-# -*- cmake -*-
-include(LLTestCommand)
-include(GoogleMock)
-
-MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
-  # Given a project name and a list of sourcefiles (with optional properties on each),
-  # add targets to build and run the tests specified.
-  # ASSUMPTIONS:
-  # * this macro is being executed in the project file that is passed in
-  # * current working SOURCE dir is that project dir
-  # * there is a subfolder tests/ with test code corresponding to the filenames passed in
-  # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
-  #
-  # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
-  #
-  # WARNING: do NOT modify this code without working with poppy -
-  # 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}")
-  ENDIF(LL_TEST_VERBOSE)
-
-  # Start with the header and project-wide setup before making targets
-  #project(UNITTEST_PROJECT_${project})
-  # Setup includes, paths, etc
-  SET(alltest_SOURCE_FILES
-    ${CMAKE_SOURCE_DIR}/test/test.cpp
-    ${CMAKE_SOURCE_DIR}/test/lltut.cpp
-    )
-  SET(alltest_DEP_TARGETS
-    # needed by the test harness itself
-    ${APRUTIL_LIBRARIES}
-    ${APR_LIBRARIES}
-    llcommon
-    )
-  IF(NOT "${project}" STREQUAL "llmath")
-    # add llmath as a dep unless the tested module *is* llmath!
-    LIST(APPEND alltest_DEP_TARGETS
-      llmath
-      )
-  ENDIF(NOT "${project}" STREQUAL "llmath")
-  SET(alltest_INCLUDE_DIRS
-    ${LLMATH_INCLUDE_DIRS}
-    ${LLCOMMON_INCLUDE_DIRS}
-    ${LIBS_OPEN_DIR}/test
-    ${GOOGLEMOCK_INCLUDE_DIRS}
-    )
-  SET(alltest_LIBRARIES
-    ${GOOGLEMOCK_LIBRARIES}
-    ${PTHREAD_LIBRARY}
-    ${WINDOWS_LIBRARIES}
-    )
-  # Headers, for convenience in targets.
-  SET(alltest_HEADER_FILES
-    ${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})
-    STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
-    STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
-    IF(LL_TEST_VERBOSE)
-      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
-    ENDIF(LL_TEST_VERBOSE)
-
-    #
-    # Per-codefile additional / external source, header, and include dir property extraction
-    #
-    # Source
-    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
-    IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
-      SET(${name}_test_additional_SOURCE_FILES "")
-    ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
-    SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
-    IF(LL_TEST_VERBOSE)
-      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
-    ENDIF(LL_TEST_VERBOSE)
-    # Headers
-    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
-    IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
-      SET(${name}_test_additional_HEADER_FILES "")
-    ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
-    SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
-    set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
-    LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
-    IF(LL_TEST_VERBOSE)
-      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
-    ENDIF(LL_TEST_VERBOSE)
-    # Include dirs
-    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
-    IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
-      SET(${name}_test_additional_INCLUDE_DIRS "")
-    ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
-    INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
-    IF(LL_TEST_VERBOSE)
-      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})
-    SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
-
-    #
-    # Per-codefile additional / external project dep and lib dep property extraction
-    #
-    # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
-    # Projects
-    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
-    IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
-      SET(${name}_test_additional_PROJECTS "")
-    ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
-    # Libraries
-    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
-    IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
-      SET(${name}_test_additional_LIBRARIES "")
-    ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
-    IF(LL_TEST_VERBOSE)
-      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
-      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
-    ENDIF(LL_TEST_VERBOSE)
-    # Add to project
-    TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
-    
-    #
-    # Setup test targets
-    #
-    GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
-    SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
-    SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
-
-    # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
-    IF(LL_TEST_VERBOSE)
-      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd  = ${TEST_CMD}")
-    ENDIF(LL_TEST_VERBOSE)
-
-    SET_TEST_PATH(LD_LIBRARY_PATH)
-    LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD})
-    IF(LL_TEST_VERBOSE)
-      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script  = ${TEST_SCRIPT_CMD}")
-    ENDIF(LL_TEST_VERBOSE)
-    # Add test 
-    ADD_CUSTOM_COMMAND(
-        OUTPUT ${TEST_OUTPUT}
-        COMMAND ${TEST_SCRIPT_CMD}
-        DEPENDS PROJECT_${project}_TEST_${name}
-        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-        )
-    # Why not add custom target and add POST_BUILD command?
-    # Slightly less uncertain behavior
-    # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
-    # > I did not use a post build step as I could not make it notify of a 
-    # > failure after the first time you build and fail a test. - daveh 2009-04-20
-    LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
-  ENDFOREACH (source)
-
-  # Add the test runner target per-project
-  # (replaces old _test_ok targets all over the place)
-  ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
-  ADD_DEPENDENCIES(${project} ${project}_tests)
-ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
-
-FUNCTION(LL_ADD_INTEGRATION_TEST 
-    testname
-    additional_source_files
-    library_dependencies
-# variable args
-    )
-  if(TEST_DEBUG)
-    message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
-  endif(TEST_DEBUG)
-  
-  SET(source_files
-    tests/${testname}_test.cpp
-    ${CMAKE_SOURCE_DIR}/test/test.cpp
-    ${CMAKE_SOURCE_DIR}/test/lltut.cpp
-    ${additional_source_files}
-    )
-
-  SET(libraries
-    ${library_dependencies}
-    ${GOOGLEMOCK_LIBRARIES}
-    ${PTHREAD_LIBRARY}
-    )
-
-  # Add test executable build target
-  if(TEST_DEBUG)
-    message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
-  endif(TEST_DEBUG)
-  ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
-  SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
-
-  # Add link deps to the executable
-  if(TEST_DEBUG)
-    message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
-  endif(TEST_DEBUG)
-  TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
-
-  # Create the test running command
-  SET(test_command ${ARGN})
-  GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
-  LIST(FIND test_command "{}" test_exe_pos)
-  IF(test_exe_pos LESS 0)
-    # The {} marker means "the full pathname of the test executable."
-    # test_exe_pos -1 means we didn't find it -- so append the test executable
-    # name to $ARGN, the variable part of the arg list. This is convenient
-    # shorthand for both straightforward execution of the test program (empty
-    # $ARGN) and for running a "wrapper" program of some kind accepting the
-    # pathname of the test program as the last of its args. You need specify
-    # {} only if the test program's pathname isn't the last argument in the
-    # desired command line.
-    LIST(APPEND test_command "${TEST_EXE}")
-  ELSE (test_exe_pos LESS 0)
-    # Found {} marker at test_exe_pos. Remove the {}...
-    LIST(REMOVE_AT test_command test_exe_pos)
-    # ...and replace it with the actual name of the test executable.
-    LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
-  ENDIF (test_exe_pos LESS 0)
-
-  SET_TEST_PATH(LD_LIBRARY_PATH)
-  LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command})
-
-  if(TEST_DEBUG)
-    message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
-  endif(TEST_DEBUG)
-
-  ADD_CUSTOM_COMMAND(
-    TARGET INTEGRATION_TEST_${testname}
-    POST_BUILD
-    COMMAND ${TEST_SCRIPT_CMD}
-    )
-
-  # Use CTEST? Not sure how to yet...
-  # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
-
-ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
-
-MACRO(SET_TEST_PATH LISTVAR)
-  IF(WINDOWS)
-    # We typically build/package only Release variants of third-party
-    # libraries, so append the Release staging dir in case the library being
-    # sought doesn't have a debug variant.
-    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release)
-  ELSEIF(DARWIN)
-    # We typically build/package only Release variants of third-party
-    # libraries, so append the Release staging dir in case the library being
-    # sought doesn't have a debug variant.
-    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib)
-  ELSE(WINDOWS)
-    # Linux uses a single staging directory anyway.
-    IF (STANDALONE)
-      set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib)
-    ELSE (STANDALONE)
-      set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
-    ENDIF (STANDALONE)
-  ENDIF(WINDOWS)
-ENDMACRO(SET_TEST_PATH)
+# -*- cmake -*-
+include(LLTestCommand)
+include(GoogleMock)
+
+MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
+  # Given a project name and a list of sourcefiles (with optional properties on each),
+  # add targets to build and run the tests specified.
+  # ASSUMPTIONS:
+  # * this macro is being executed in the project file that is passed in
+  # * current working SOURCE dir is that project dir
+  # * there is a subfolder tests/ with test code corresponding to the filenames passed in
+  # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
+  #
+  # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
+  #
+  # WARNING: do NOT modify this code without working with poppy -
+  # 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}")
+  ENDIF(LL_TEST_VERBOSE)
+
+  # Start with the header and project-wide setup before making targets
+  #project(UNITTEST_PROJECT_${project})
+  # Setup includes, paths, etc
+  SET(alltest_SOURCE_FILES
+    ${CMAKE_SOURCE_DIR}/test/test.cpp
+    ${CMAKE_SOURCE_DIR}/test/lltut.cpp
+    )
+  SET(alltest_DEP_TARGETS
+    # needed by the test harness itself
+    ${APRUTIL_LIBRARIES}
+    ${APR_LIBRARIES}
+    llcommon
+    )
+  IF(NOT "${project}" STREQUAL "llmath")
+    # add llmath as a dep unless the tested module *is* llmath!
+    LIST(APPEND alltest_DEP_TARGETS
+      llmath
+      )
+  ENDIF(NOT "${project}" STREQUAL "llmath")
+  SET(alltest_INCLUDE_DIRS
+    ${LLMATH_INCLUDE_DIRS}
+    ${LLCOMMON_INCLUDE_DIRS}
+    ${LIBS_OPEN_DIR}/test
+    ${GOOGLEMOCK_INCLUDE_DIRS}
+    )
+  SET(alltest_LIBRARIES
+    ${GOOGLEMOCK_LIBRARIES}
+    ${PTHREAD_LIBRARY}
+    ${WINDOWS_LIBRARIES}
+    )
+  # Headers, for convenience in targets.
+  SET(alltest_HEADER_FILES
+    ${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})
+    STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
+    STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
+    IF(LL_TEST_VERBOSE)
+      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
+    ENDIF(LL_TEST_VERBOSE)
+
+    #
+    # Per-codefile additional / external source, header, and include dir property extraction
+    #
+    # Source
+    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
+    IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
+      SET(${name}_test_additional_SOURCE_FILES "")
+    ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
+    SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
+    IF(LL_TEST_VERBOSE)
+      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
+    ENDIF(LL_TEST_VERBOSE)
+    # Headers
+    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
+    IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
+      SET(${name}_test_additional_HEADER_FILES "")
+    ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
+    SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
+    set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
+    LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
+    IF(LL_TEST_VERBOSE)
+      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
+    ENDIF(LL_TEST_VERBOSE)
+    # Include dirs
+    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
+    IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
+      SET(${name}_test_additional_INCLUDE_DIRS "")
+    ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
+    INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
+    IF(LL_TEST_VERBOSE)
+      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})
+    SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
+
+    #
+    # Per-codefile additional / external project dep and lib dep property extraction
+    #
+    # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
+    # Projects
+    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
+    IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
+      SET(${name}_test_additional_PROJECTS "")
+    ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
+    # Libraries
+    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
+    IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
+      SET(${name}_test_additional_LIBRARIES "")
+    ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
+    IF(LL_TEST_VERBOSE)
+      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
+      MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
+    ENDIF(LL_TEST_VERBOSE)
+    # Add to project
+    TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
+    # Compile-time Definitions
+    GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS)
+     IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
+       SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} )
+       IF(LL_TEST_VERBOSE)
+         MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}")
+       ENDIF(LL_TEST_VERBOSE)
+     ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
+     
+    #
+    # Setup test targets
+    #
+    GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
+    SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
+    SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
+
+    # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
+    IF(LL_TEST_VERBOSE)
+      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd  = ${TEST_CMD}")
+    ENDIF(LL_TEST_VERBOSE)
+
+    SET_TEST_PATH(LD_LIBRARY_PATH)
+    LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD})
+    IF(LL_TEST_VERBOSE)
+      MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script  = ${TEST_SCRIPT_CMD}")
+    ENDIF(LL_TEST_VERBOSE)
+    # Add test 
+    ADD_CUSTOM_COMMAND(
+        OUTPUT ${TEST_OUTPUT}
+        COMMAND ${TEST_SCRIPT_CMD}
+        DEPENDS PROJECT_${project}_TEST_${name}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        )
+    # Why not add custom target and add POST_BUILD command?
+    # Slightly less uncertain behavior
+    # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
+    # > I did not use a post build step as I could not make it notify of a 
+    # > failure after the first time you build and fail a test. - daveh 2009-04-20
+    LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
+  ENDFOREACH (source)
+
+  # Add the test runner target per-project
+  # (replaces old _test_ok targets all over the place)
+  ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
+  ADD_DEPENDENCIES(${project} ${project}_tests)
+ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
+
+FUNCTION(LL_ADD_INTEGRATION_TEST 
+    testname
+    additional_source_files
+    library_dependencies
+# variable args
+    )
+  if(TEST_DEBUG)
+    message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
+  endif(TEST_DEBUG)
+  
+  SET(source_files
+    tests/${testname}_test.cpp
+    ${CMAKE_SOURCE_DIR}/test/test.cpp
+    ${CMAKE_SOURCE_DIR}/test/lltut.cpp
+    ${additional_source_files}
+    )
+
+  SET(libraries
+    ${library_dependencies}
+    ${GOOGLEMOCK_LIBRARIES}
+    ${PTHREAD_LIBRARY}
+    )
+
+  # Add test executable build target
+  if(TEST_DEBUG)
+    message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
+  endif(TEST_DEBUG)
+  ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
+  SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
+
+  # Add link deps to the executable
+  if(TEST_DEBUG)
+    message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
+  endif(TEST_DEBUG)
+  TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
+
+  # Create the test running command
+  SET(test_command ${ARGN})
+  GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
+  LIST(FIND test_command "{}" test_exe_pos)
+  IF(test_exe_pos LESS 0)
+    # The {} marker means "the full pathname of the test executable."
+    # test_exe_pos -1 means we didn't find it -- so append the test executable
+    # name to $ARGN, the variable part of the arg list. This is convenient
+    # shorthand for both straightforward execution of the test program (empty
+    # $ARGN) and for running a "wrapper" program of some kind accepting the
+    # pathname of the test program as the last of its args. You need specify
+    # {} only if the test program's pathname isn't the last argument in the
+    # desired command line.
+    LIST(APPEND test_command "${TEST_EXE}")
+  ELSE (test_exe_pos LESS 0)
+    # Found {} marker at test_exe_pos. Remove the {}...
+    LIST(REMOVE_AT test_command test_exe_pos)
+    # ...and replace it with the actual name of the test executable.
+    LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
+  ENDIF (test_exe_pos LESS 0)
+
+  SET_TEST_PATH(LD_LIBRARY_PATH)
+  LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command})
+
+  if(TEST_DEBUG)
+    message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
+  endif(TEST_DEBUG)
+
+  ADD_CUSTOM_COMMAND(
+    TARGET INTEGRATION_TEST_${testname}
+    POST_BUILD
+    COMMAND ${TEST_SCRIPT_CMD}
+    )
+
+  # Use CTEST? Not sure how to yet...
+  # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
+
+ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
+
+MACRO(SET_TEST_PATH LISTVAR)
+  IF(WINDOWS)
+    # We typically build/package only Release variants of third-party
+    # libraries, so append the Release staging dir in case the library being
+    # sought doesn't have a debug variant.
+    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release)
+  ELSEIF(DARWIN)
+    # We typically build/package only Release variants of third-party
+    # libraries, so append the Release staging dir in case the library being
+    # sought doesn't have a debug variant.
+    set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib)
+  ELSE(WINDOWS)
+    # Linux uses a single staging directory anyway.
+    IF (STANDALONE)
+      set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib)
+    ELSE (STANDALONE)
+      set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
+    ENDIF (STANDALONE)
+  ENDIF(WINDOWS)
+ENDMACRO(SET_TEST_PATH)
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index 0901c1b7a2174979f4d5546962c7db9c1fd62f02..748c8c2bec1b80b3680c2b7e410fbf3de1830df5 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -9,10 +9,12 @@ if (WINDOWS)
     NAMES python25.exe python23.exe python.exe
     NO_DEFAULT_PATH # added so that cmake does not find cygwin python
     PATHS
+    [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.3\\InstallPath]
+    [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath]
     [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath]
     [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath]
     [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\2.4\\InstallPath]
diff --git a/indra/cmake/TemplateCheck.cmake b/indra/cmake/TemplateCheck.cmake
index fa4e387dd5c60aac177fb36fa3bfc1ddc0ed2b75..90d58d93ad4bd652f0260d48f03ec9e04239edea 100644
--- a/indra/cmake/TemplateCheck.cmake
+++ b/indra/cmake/TemplateCheck.cmake
@@ -7,8 +7,9 @@ macro (check_message_template _target)
       TARGET ${_target}
       POST_BUILD
       COMMAND ${PYTHON_EXECUTABLE}
-      ARGS ${SCRIPTS_DIR}/template_verifier.py
-           --mode=development --cache_master
-      COMMENT "Verifying message template"
+      ARGS ${SCRIPTS_DIR}/md5check.py
+           3f19d130400c547de36278a6b6f9b028
+           ${SCRIPTS_DIR}/messages/message_template.msg
+      COMMENT "Verifying message template - See http://wiki.secondlife.com/wiki/Template_verifier.py"
       )
 endmacro (check_message_template)
diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake
index 32c4bc81dfc4af75a888e511ba62beb7004a984f..df013b1665058e458ede89172c2aa5281ea480a5 100644
--- a/indra/cmake/ViewerMiscLibs.cmake
+++ b/indra/cmake/ViewerMiscLibs.cmake
@@ -3,7 +3,7 @@ include(Prebuilt)
 
 if (NOT STANDALONE)
   use_prebuilt_binary(libuuid)
-  use_prebuilt_binary(vivox)
+  use_prebuilt_binary(slvoice)
   use_prebuilt_binary(fontconfig)
 endif(NOT STANDALONE)
 
diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp
index 23c34e52e799deae245a6b1c803f5ef5aa89262e..d909516bf8fbce6872458eec049e0b4c836df6ae 100644
--- a/indra/linux_updater/linux_updater.cpp
+++ b/indra/linux_updater/linux_updater.cpp
@@ -49,6 +49,7 @@ const guint ROTATE_IMAGE_TIMEOUT = 8000;
 typedef struct _updater_app_state {
 	std::string app_name;
 	std::string url;
+	std::string file;
 	std::string image_dir;
 	std::string dest_dir;
 	std::string strings_dirs;
@@ -113,7 +114,7 @@ BOOL install_package(std::string package_file, std::string destination);
 BOOL spawn_viewer(UpdaterAppState *app_state);
 
 extern "C" {
-	void on_window_closed(GtkWidget *sender, gpointer state);
+	void on_window_closed(GtkWidget *sender, GdkEvent *event, gpointer state);
 	gpointer worker_thread_cb(gpointer *data);
 	int download_progress_cb(gpointer data, double t, double d, double utotal, double ulnow);
 	gboolean rotate_image_cb(gpointer data);
@@ -220,7 +221,7 @@ std::string next_image_filename(std::string& image_path)
 	return image_path + "/" + image_filename;
 }
 
-void on_window_closed(GtkWidget *sender, gpointer data)
+void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data)
 {
 	UpdaterAppState *app_state;
 
@@ -266,85 +267,95 @@ gpointer worker_thread_cb(gpointer data)
 	CURLcode result;
 	FILE *package_file;
 	GError *error = NULL;
-	char *tmp_filename = NULL;
 	int fd;
 
 	//g_return_val_if_fail (data != NULL, NULL);
 	app_state = (UpdaterAppState *) data;
 
 	try {
-		// create temporary file to store the package.
-		fd = g_file_open_tmp
-			("secondlife-update-XXXXXX", &tmp_filename, &error);
-		if (error != NULL)
-		{
-			llerrs << "Unable to create temporary file: "
-			       << error->message
-			       << llendl;
-
-			g_error_free(error);
-			throw 0;
-		}
 
-		package_file = fdopen(fd, "wb");
-		if (package_file == NULL)
+		if(!app_state->url.empty())
 		{
-			llerrs << "Failed to create temporary file: "
-			       << tmp_filename
-			       << llendl;
+			char* tmp_local_filename = NULL;
+			// create temporary file to store the package.
+			fd = g_file_open_tmp
+				("secondlife-update-XXXXXX", &tmp_local_filename, &error);
+			if (error != NULL)
+			{
+				llerrs << "Unable to create temporary file: "
+					   << error->message
+					   << llendl;
 
-			gdk_threads_enter();
-			display_error(app_state->window,
-				      LLTrans::getString("UpdaterFailDownloadTitle"),
-				      LLTrans::getString("UpdaterFailUpdateDescriptive"));
-			gdk_threads_leave();
-			throw 0;
-		}
+				g_error_free(error);
+				throw 0;
+			}
+			
+			if(tmp_local_filename != NULL)
+			{
+				app_state->file = tmp_local_filename;
+				g_free(tmp_local_filename);
+			}
 
-		// initialize curl and start downloading the package
-		llinfos << "Downloading package: " << app_state->url << llendl;
+			package_file = fdopen(fd, "wb");
+			if (package_file == NULL)
+			{
+				llerrs << "Failed to create temporary file: "
+					   << app_state->file.c_str()
+					   << llendl;
+
+				gdk_threads_enter();
+				display_error(app_state->window,
+							  LLTrans::getString("UpdaterFailDownloadTitle"),
+							  LLTrans::getString("UpdaterFailUpdateDescriptive"));
+				gdk_threads_leave();
+				throw 0;
+			}
 
-		curl = curl_easy_init();
-		if (curl == NULL)
-		{
-			llerrs << "Failed to initialize libcurl" << llendl;
+			// initialize curl and start downloading the package
+			llinfos << "Downloading package: " << app_state->url << llendl;
 
-			gdk_threads_enter();
-			display_error(app_state->window,
-				      LLTrans::getString("UpdaterFailDownloadTitle"),
-				      LLTrans::getString("UpdaterFailUpdateDescriptive"));
-			gdk_threads_leave();
-			throw 0;
-		}
+			curl = curl_easy_init();
+			if (curl == NULL)
+			{
+				llerrs << "Failed to initialize libcurl" << llendl;
+
+				gdk_threads_enter();
+				display_error(app_state->window,
+							  LLTrans::getString("UpdaterFailDownloadTitle"),
+							  LLTrans::getString("UpdaterFailUpdateDescriptive"));
+				gdk_threads_leave();
+				throw 0;
+			}
 
-		curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str());
-		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
-		curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
-		curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
-		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
-		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, 
-				 &download_progress_cb);
-		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
+			curl_easy_setopt(curl, CURLOPT_URL, app_state->url.c_str());
+			curl_easy_setopt(curl, CURLOPT_NOSIGNAL, TRUE);
+			curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
+			curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
+			curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
+			curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, 
+							 &download_progress_cb);
+			curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
 
-		result = curl_easy_perform(curl);
-		fclose(package_file);
-		curl_easy_cleanup(curl);
+			result = curl_easy_perform(curl);
+			fclose(package_file);
+			curl_easy_cleanup(curl);
 
-		if (result)
-		{
-			llerrs << "Failed to download update: " 
-			       << app_state->url 
-			       << llendl;
+			if (result)
+			{
+				llerrs << "Failed to download update: " 
+					   << app_state->url 
+					   << llendl;
 
-			gdk_threads_enter();
-			display_error(app_state->window,
-				      LLTrans::getString("UpdaterFailDownloadTitle"),
-				      LLTrans::getString("UpdaterFailUpdateDescriptive"));
-			gdk_threads_leave();
+				gdk_threads_enter();
+				display_error(app_state->window,
+							  LLTrans::getString("UpdaterFailDownloadTitle"),
+							  LLTrans::getString("UpdaterFailUpdateDescriptive"));
+				gdk_threads_leave();
 
-			throw 0;
+				throw 0;
+			}
 		}
-
+		
 		// now pulse the progres bar back and forth while the package is
 		// being unpacked
 		gdk_threads_enter();
@@ -357,7 +368,7 @@ gpointer worker_thread_cb(gpointer data)
 
 		// *TODO: if the destination is not writable, terminate this
 		// thread and show file chooser?
-		if (!install_package(tmp_filename, app_state->dest_dir))
+		if (!install_package(app_state->file.c_str(), app_state->dest_dir))
 		{
 			llwarns << "Failed to install package to destination: "
 				<< app_state->dest_dir
@@ -392,15 +403,6 @@ gpointer worker_thread_cb(gpointer data)
 		app_state->failure = TRUE;
 	}
 
-	// FIXME: delete package file also if delete-event is raised on window
-	if (tmp_filename != NULL)
-	{
-		if (gDirUtilp->fileExists(tmp_filename))
-		{
-			LLFile::remove(tmp_filename);
-		}
-	}
-
 	gdk_threads_enter();
 	updater_app_quit(app_state);
 	gdk_threads_leave();
@@ -712,7 +714,7 @@ BOOL spawn_viewer(UpdaterAppState *app_state)
 
 void show_usage_and_exit()
 {
-	std::cout << "Usage: linux-updater --url URL --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE"
+	std::cout << "Usage: linux-updater <--url URL | --file FILE> --name NAME --dest PATH --stringsdir PATH1,PATH2 --stringsfile FILE"
 		  << "[--image-dir PATH]"
 		  << std::endl;
 	exit(1);
@@ -728,6 +730,10 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
 		{
 			app_state->url = argv[i];
 		}
+		else if ((!strcmp(argv[i], "--file")) && (++i < argc))
+		{
+			app_state->file = argv[i];
+		}
 		else if ((!strcmp(argv[i], "--name")) && (++i < argc))
 		{
 			app_state->app_name = argv[i];
@@ -756,7 +762,7 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
 	}
 
 	if (app_state->app_name.empty() 
-	    || app_state->url.empty() 
+	    || (app_state->url.empty() && app_state->file.empty())  
 	    || app_state->dest_dir.empty())
 	{
 		show_usage_and_exit();
@@ -771,10 +777,10 @@ void parse_args_and_init(int argc, char **argv, UpdaterAppState *app_state)
 
 int main(int argc, char **argv)
 {
-	UpdaterAppState app_state;
+	UpdaterAppState* app_state = new UpdaterAppState;
 	GThread *worker_thread;
 
-	parse_args_and_init(argc, argv, &app_state);
+	parse_args_and_init(argc, argv, app_state);
 
 	// Initialize logger, and rename old log file
 	gDirUtilp->initAppDirs("SecondLife");
@@ -797,17 +803,29 @@ int main(int argc, char **argv)
 	gtk_init(&argc, &argv);
 
 	// create UI
-	updater_app_ui_init(&app_state);
+	updater_app_ui_init(app_state);
 
 	//llinfos << "SAMPLE TRANSLATION IS: " << LLTrans::getString("LoginInProgress") << llendl;
 
 	// create download thread
 	worker_thread = g_thread_create
-		(GThreadFunc(worker_thread_cb), &app_state, FALSE, NULL);
+		(GThreadFunc(worker_thread_cb), app_state, FALSE, NULL);
 
 	gdk_threads_enter();
 	gtk_main();
 	gdk_threads_leave();
 
-	return (app_state.failure == FALSE) ? 0 : 1;
+	// Delete the file only if created from url download.
+	if(!app_state->url.empty() && !app_state->file.empty())
+	{
+		if (gDirUtilp->fileExists(app_state->file))
+		{
+			LLFile::remove(app_state->file);
+		}
+	}
+
+	bool success = !app_state->failure;
+	delete app_state;
+	return success ? 0 : 1;
 }
+
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 478f2fedbd1912b8807e8730ffc645cb33ab2604..9342a22d46f9d0a3a0b0017544af3aa6a19383bd 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -93,6 +93,7 @@ set(llcommon_SOURCE_FILES
     llstringtable.cpp
     llsys.cpp
     llthread.cpp
+    llthreadsafequeue.cpp
     lltimer.cpp
     lluri.cpp
     lluuid.cpp
@@ -225,6 +226,7 @@ set(llcommon_HEADER_FILES
     llstringtable.h
     llsys.h
     llthread.h
+    llthreadsafequeue.h
     lltimer.h
     lltreeiterators.h
     lluri.h
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index b0618bfe596ebb1727f18a45a269d5019d902f02..95cb606240276669b171d4113d18b213e4cd46a5 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -245,9 +245,6 @@ const U8 SIM_ACCESS_ADULT	= 42;		// Seriously Adult Only
 const U8 SIM_ACCESS_DOWN	= 254;
 const U8 SIM_ACCESS_MAX 	= SIM_ACCESS_ADULT;
 
-// group constants
-const S32 MAX_AGENT_GROUPS = 25;
-
 // attachment constants
 const S32 MAX_AGENT_ATTACHMENTS = 38;
 const U8  ATTACHMENT_ADD = 0x80;
@@ -300,6 +297,14 @@ const U32 START_LOCATION_ID_COUNT 		= 6;
 // group constants
 const U32 GROUP_MIN_SIZE = 2;
 
+// gMaxAgentGroups is now sent by login.cgi, which
+// looks it up from globals.xml.
+//
+// For now we need an old default value however,
+// so the viewer can be deployed ahead of login.cgi.
+//
+const S32 DEFAULT_MAX_AGENT_GROUPS = 25;
+
 // radius within which a chat message is fully audible
 const F32 CHAT_WHISPER_RADIUS = 10.f;
 const F32 CHAT_NORMAL_RADIUS = 20.f;
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index 289ce0bc2cfda4b52a63975e7d1905e47d03210b..8f02391e75a7dcbcf6f2d1b8734aca1550d7969f 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -318,7 +318,12 @@ void llofstream::close()
 	if(is_open())
 	{
 		if (_Filebuffer->close() == 0)
+		{
 			_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/
+		}
+		delete _Filebuffer;
+		_Filebuffer = NULL;
+		_ShouldClose = false;
 	}
 }
 
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index d7b7c3699ccdca91002c21d34bcd25fba57a28d0..148aaf8aed7cc31b5eea35f4deef0ab0d6668d4a 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -147,16 +147,20 @@ void LLThread::shutdown()
 		{
 			// This thread just wouldn't stop, even though we gave it time
 			llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
+			// Put a stake in its heart.
+			apr_thread_exit(mAPRThreadp, -1);
 			return;
 		}
 		mAPRThreadp = NULL;
 	}
 
 	delete mRunCondition;
+	mRunCondition = 0;
 	
-	if (mIsLocalPool)
+	if (mIsLocalPool && mAPRPoolp)
 	{
 		apr_pool_destroy(mAPRPoolp);
+		mAPRPoolp = 0;
 	}
 }
 
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8a73e632a9ada2249b4353f88828d5d66fcfe00d
--- /dev/null
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -0,0 +1,109 @@
+/** 
+ * @file llthread.cpp
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include <apr_pools.h>
+#include <apr_queue.h>
+#include "llthreadsafequeue.h"
+
+
+
+// LLThreadSafeQueueImplementation
+//-----------------------------------------------------------------------------
+
+
+LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity):
+	mOwnsPool(pool == 0),
+	mPool(pool),
+	mQueue(0)
+{
+	if(mOwnsPool) {
+		apr_status_t status = apr_pool_create(&mPool, 0);
+		if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool");
+	} else {
+		; // No op.
+	}
+	
+	apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
+	if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue");
+}
+
+
+LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation()
+{
+	if(mQueue != 0) {
+		if(apr_queue_size(mQueue) != 0) llwarns << 
+			"terminating queue which still contains " << apr_queue_size(mQueue) <<
+			" elements;" << "memory will be leaked" << LL_ENDL;
+		apr_queue_term(mQueue);
+	}
+	if(mOwnsPool && (mPool != 0)) apr_pool_destroy(mPool);
+}
+
+
+void LLThreadSafeQueueImplementation::pushFront(void * element)
+{
+	apr_status_t status = apr_queue_push(mQueue, element);
+	
+	if(status == APR_EINTR) {
+		throw LLThreadSafeQueueInterrupt();
+	} else if(status != APR_SUCCESS) {
+		throw LLThreadSafeQueueError("push failed");
+	} else {
+		; // Success.
+	}
+}
+
+
+bool LLThreadSafeQueueImplementation::tryPushFront(void * element){
+	return apr_queue_trypush(mQueue, element) == APR_SUCCESS;
+}
+
+
+void * LLThreadSafeQueueImplementation::popBack(void)
+{
+	void * element;
+	apr_status_t status = apr_queue_pop(mQueue, &element);
+
+	if(status == APR_EINTR) {
+		throw LLThreadSafeQueueInterrupt();
+	} else if(status != APR_SUCCESS) {
+		throw LLThreadSafeQueueError("pop failed");
+	} else {
+		return element;
+	}
+}
+
+
+bool LLThreadSafeQueueImplementation::tryPopBack(void *& element)
+{
+	return apr_queue_trypop(mQueue, &element) == APR_SUCCESS;
+}
+
+
+size_t LLThreadSafeQueueImplementation::size()
+{
+	return apr_queue_size(mQueue);
+}
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
new file mode 100644
index 0000000000000000000000000000000000000000..58cac38769cd2d3801fc9f01b1d1cc2a010ae0c6
--- /dev/null
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -0,0 +1,205 @@
+/** 
+ * @file llthreadsafequeue.h
+ * @brief Base classes for thread, mutex and condition handling.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTHREADSAFEQUEUE_H
+#define LL_LLTHREADSAFEQUEUE_H
+
+
+#include <string>
+#include <stdexcept>
+
+
+struct apr_pool_t; // From apr_pools.h
+class LLThreadSafeQueueImplementation; // See below.
+
+
+//
+// A general queue exception.
+//
+class LL_COMMON_API LLThreadSafeQueueError:
+public std::runtime_error
+{
+public:
+	LLThreadSafeQueueError(std::string const & message):
+	std::runtime_error(message)
+	{
+		; // No op.
+	}
+};
+
+
+//
+// An exception raised when blocking operations are interrupted.
+//
+class LL_COMMON_API LLThreadSafeQueueInterrupt:
+	public LLThreadSafeQueueError
+{
+public:
+	LLThreadSafeQueueInterrupt(void):
+		LLThreadSafeQueueError("queue operation interrupted")
+	{
+		; // No op.
+	}
+};
+
+
+struct apr_queue_t; // From apr_queue.h
+
+
+//
+// Implementation details. 
+//
+class LL_COMMON_API LLThreadSafeQueueImplementation
+{
+public:
+	LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity);
+	~LLThreadSafeQueueImplementation();
+	void pushFront(void * element);
+	bool tryPushFront(void * element);
+	void * popBack(void);
+	bool tryPopBack(void *& element);
+	size_t size();
+	
+private:
+	bool mOwnsPool;
+	apr_pool_t * mPool;
+	apr_queue_t * mQueue;
+};
+
+
+//
+// Implements a thread safe FIFO.
+//
+template<typename ElementT>
+class LLThreadSafeQueue
+{
+public:
+	typedef ElementT value_type;
+	
+	// If the pool is set to NULL one will be allocated and managed by this
+	// queue.
+	LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024);
+	
+	// Add an element to the front of queue (will block if the queue has
+	// reached capacity).
+	//
+	// This call will raise an interrupt error if the queue is deleted while
+	// the caller is blocked.
+	void pushFront(ElementT const & element);
+	
+	// Try to add an element to the front ofqueue without blocking. Returns
+	// true only if the element was actually added.
+	bool tryPushFront(ElementT const & element);
+	
+	// Pop the element at the end of the queue (will block if the queue is
+	// empty).
+	//
+	// This call will raise an interrupt error if the queue is deleted while
+	// the caller is blocked.
+	ElementT popBack(void);
+	
+	// Pop an element from the end of the queue if there is one available.
+	// Returns true only if an element was popped.
+	bool tryPopBack(ElementT & element);
+	
+	// Returns the size of the queue.
+	size_t size();
+
+private:
+	LLThreadSafeQueueImplementation mImplementation;
+};
+
+
+
+// LLThreadSafeQueue
+//-----------------------------------------------------------------------------
+
+
+template<typename ElementT>
+LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity):
+	mImplementation(pool, capacity)
+{
+	; // No op.
+}
+
+
+template<typename ElementT>
+void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
+{
+	ElementT * elementCopy = new ElementT(element);
+	try {
+		mImplementation.pushFront(elementCopy);
+	} catch (LLThreadSafeQueueInterrupt) {
+		delete elementCopy;
+		throw;
+	}
+}
+
+
+template<typename ElementT>
+bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element)
+{
+	ElementT * elementCopy = new ElementT(element);
+	bool result = mImplementation.tryPushFront(elementCopy);
+	if(!result) delete elementCopy;
+	return result;
+}
+
+
+template<typename ElementT>
+ElementT LLThreadSafeQueue<ElementT>::popBack(void)
+{
+	ElementT * element = reinterpret_cast<ElementT *> (mImplementation.popBack());
+	ElementT result(*element);
+	delete element;
+	return result;
+}
+
+
+template<typename ElementT>
+bool LLThreadSafeQueue<ElementT>::tryPopBack(ElementT & element)
+{
+	void * storedElement;
+	bool result = mImplementation.tryPopBack(storedElement);
+	if(result) {
+		ElementT * elementPtr = reinterpret_cast<ElementT *>(storedElement); 
+		element = *elementPtr;
+		delete elementPtr;
+	} else {
+		; // No op.
+	}
+	return result;
+}
+
+
+template<typename ElementT>
+size_t LLThreadSafeQueue<ElementT>::size(void)
+{
+	return mImplementation.size();
+}
+
+
+#endif
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 5cc7d355cca0bc69c19c32e04edb070b24459d0a..04f72d93b4c299e3f8237fd8efddc14de2c8537d 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -28,7 +28,7 @@
 #define LL_LLVERSIONVIEWER_H
 
 const S32 LL_VERSION_MAJOR = 2;
-const S32 LL_VERSION_MINOR = 4;
+const S32 LL_VERSION_MINOR = 5;
 const S32 LL_VERSION_PATCH = 0;
 const S32 LL_VERSION_BUILD = 211776;
 
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index ff9af21e545eb762ec7a33874532a2d4c7b590b0..19c42bf61a2e1de48ddd96c13dcea36e32b94dd5 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1620,7 +1620,10 @@ void LLUI::initClass(const settings_map_t& settings,
 
 void LLUI::cleanupClass()
 {
-	sImageProvider->cleanUp();
+	if(sImageProvider)
+	{
+		sImageProvider->cleanUp();
+	}
 }
 
 void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup,  const clear_popups_t& clear_popups)
diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp
index 83ccb277b35ba49888948f59967c86443602d2ba..8788bd63e87d2b8030324ffcd0e0434057844151 100644
--- a/indra/llvfs/tests/lldir_test.cpp
+++ b/indra/llvfs/tests/lldir_test.cpp
@@ -263,7 +263,9 @@ namespace tut
       std::string path = dir + delim + file;
       LLFILE* handle = LLFile::fopen( path, "w" );
       ensure("failed to open test file '"+path+"'", handle != NULL );
-      ensure("failed to write to test file '"+path+"'", !fputs("test file", handle) );
+      // Harbison & Steele, 4th ed., p. 366: "If an error occurs, fputs
+      // returns EOF; otherwise, it returns some other, nonnegative value."
+      ensure("failed to write to test file '"+path+"'", fputs("test file", handle) >= 0);
       fclose(handle);
       return path;
    }
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index f9a39826f56203dab893ca78815704df497f2164..27c694dde97fef4294ccb2dee95b3b1a285ee7e3 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -1107,7 +1107,7 @@ bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::strin
 		return sd.asBoolean();
 	else
 	{
-		CONTROL_ERRS << "Invalid BOOL value" << llendl;
+		CONTROL_ERRS << "Invalid BOOL value for " << control_name << ": " << sd << llendl;
 		return FALSE;
 	}
 }
@@ -1119,7 +1119,7 @@ S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string&
 		return sd.asInteger();
 	else
 	{
-		CONTROL_ERRS << "Invalid S32 value" << llendl;
+		CONTROL_ERRS << "Invalid S32 value for " << control_name << ": " << sd << llendl;
 		return 0;
 	}
 }
@@ -1131,7 +1131,7 @@ U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string&
 		return sd.asInteger();
 	else
 	{
-		CONTROL_ERRS << "Invalid U32 value" << llendl;
+		CONTROL_ERRS << "Invalid U32 value for " << control_name << ": " << sd << llendl;
 		return 0;
 	}
 }
@@ -1143,7 +1143,7 @@ F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string&
 		return (F32) sd.asReal();
 	else
 	{
-		CONTROL_ERRS << "Invalid F32 value" << llendl;
+		CONTROL_ERRS << "Invalid F32 value for " << control_name << ": " << sd << llendl;
 		return 0.0f;
 	}
 }
@@ -1155,7 +1155,7 @@ std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, co
 		return sd.asString();
 	else
 	{
-		CONTROL_ERRS << "Invalid string value" << llendl;
+		CONTROL_ERRS << "Invalid string value for " << control_name << ": " << sd << llendl;
 		return LLStringUtil::null;
 	}
 }
@@ -1173,7 +1173,7 @@ LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const
 		return (LLVector3)sd;
 	else
 	{
-		CONTROL_ERRS << "Invalid LLVector3 value" << llendl;
+		CONTROL_ERRS << "Invalid LLVector3 value for " << control_name << ": " << sd << llendl;
 		return LLVector3::zero;
 	}
 }
@@ -1185,7 +1185,7 @@ LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, cons
 		return (LLVector3d)sd;
 	else
 	{
-		CONTROL_ERRS << "Invalid LLVector3d value" << llendl;
+		CONTROL_ERRS << "Invalid LLVector3d value for " << control_name << ": " << sd << llendl;
 		return LLVector3d::zero;
 	}
 }
@@ -1197,7 +1197,7 @@ LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::s
 		return LLRect(sd);
 	else
 	{
-		CONTROL_ERRS << "Invalid rect value" << llendl;
+		CONTROL_ERRS << "Invalid rect value for " << control_name << ": " << sd << llendl;
 		return LLRect::null;
 	}
 }
@@ -1211,19 +1211,19 @@ LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const st
 		LLColor4 color(sd);
 		if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
 		{
-			llwarns << "Color " << control_name << " value out of range " << llendl;
+			llwarns << "Color " << control_name << " red value out of range: " << color << llendl;
 		}
 		else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
 		{
-			llwarns << "Color " << control_name << " value out of range " << llendl;
+			llwarns << "Color " << control_name << " green value out of range: " << color << llendl;
 		}
 		else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
 		{
-			llwarns << "Color " << control_name << " value out of range " << llendl;
+			llwarns << "Color " << control_name << " blue value out of range: " << color << llendl;
 		}
 		else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
 		{
-			llwarns << "Color " << control_name << " value out of range " << llendl;
+			llwarns << "Color " << control_name << " alpha value out of range: " << color << llendl;
 		}
 
 		return LLColor4(sd);
@@ -1242,7 +1242,7 @@ LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const st
 		return sd;
 	else
 	{
-		CONTROL_ERRS << "Invalid LLColor3 value" << llendl;
+		CONTROL_ERRS << "Invalid LLColor3 value for " << control_name << ": " << sd << llendl;
 		return LLColor3::white;
 	}
 }
diff --git a/indra/mac_updater/mac_updater.cpp b/indra/mac_updater/mac_updater.cpp
index 23980ffac22a7954a0a6327369b71e5b2129ef38..5d19e8a8899b0eb3ca3bd36d558cf6ca5d5a7b4c 100644
--- a/indra/mac_updater/mac_updater.cpp
+++ b/indra/mac_updater/mac_updater.cpp
@@ -26,6 +26,9 @@
 
 #include "linden_common.h"
 
+#include <boost/format.hpp>
+
+#include <libgen.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -62,6 +65,8 @@ Boolean gCancelled = false;
 const char *gUpdateURL;
 const char *gProductName;
 const char *gBundleID;
+const char *gDmgFile;
+const char *gMarkerPath;
 
 void *updatethreadproc(void*);
 
@@ -334,6 +339,14 @@ int parse_args(int argc, char **argv)
 		{
 			gBundleID = argv[j];
 		}
+		else if ((!strcmp(argv[j], "-dmg")) && (++j < argc)) 
+		{
+			gDmgFile = argv[j];
+		}
+		else if ((!strcmp(argv[j], "-marker")) && (++j < argc)) 
+		{
+			gMarkerPath = argv[j];;
+		}
 	}
 
 	return 0;
@@ -361,10 +374,12 @@ int main(int argc, char **argv)
 	gUpdateURL  = NULL;
 	gProductName = NULL;
 	gBundleID = NULL;
+	gDmgFile = NULL;
+	gMarkerPath = NULL;
 	parse_args(argc, argv);
-	if (!gUpdateURL)
+	if ((gUpdateURL == NULL) && (gDmgFile == NULL))
 	{
-		llinfos << "Usage: mac_updater -url <url> [-name <product_name>] [-program <program_name>]" << llendl;
+		llinfos << "Usage: mac_updater -url <url> | -dmg <dmg file> [-name <product_name>] [-program <program_name>]" << llendl;
 		exit(1);
 	}
 	else
@@ -488,11 +503,18 @@ int main(int argc, char **argv)
 					NULL,
 					&retval_mac);
 		}
-
+		
+		if(gMarkerPath != 0)
+		{
+			// Create a install fail marker that can be used by the viewer to
+			// detect install problems.
+			std::ofstream stream(gMarkerPath);
+			if(stream) stream << -1;
+		}
+		exit(-1);
+	} else {
+		exit(0);
 	}
-	
-	// Don't dispose of things, just exit.  This keeps the update thread from potentially getting hosed.
-	exit(0);
 
 	if(gWindow != NULL)
 	{
@@ -700,17 +722,26 @@ static OSErr findAppBundleOnDiskImage(FSRef *parent, FSRef *app)
 						// Looks promising.  Check to see if it has the right bundle identifier.
 						if(isFSRefViewerBundle(&ref))
 						{
+							llinfos << name << " is the one" << llendl;
 							// This is the one.  Return it.
 							*app = ref;
 							found = true;
+							break;
+						} else {
+							llinfos << name << " is not the bundle we are looking for; move along" << llendl;
 						}
+
 					}
 				}
 			}
 		}
-		while(!err && !found);
+		while(!err);
+		
+		llinfos << "closing the iterator" << llendl;
 		
 		FSCloseIterator(iterator);
+		
+		llinfos << "closed" << llendl;
 	}
 	
 	if(!err && !found)
@@ -921,6 +952,22 @@ void *updatethreadproc(void*)
 
 #endif // 0 *HACK for DEV-11935
 		
+		// Skip downloading the file if the dmg was passed on the command line.
+		std::string dmgName;
+		if(gDmgFile != NULL) {
+			dmgName = basename((char *)gDmgFile);
+			char * dmgDir = dirname((char *)gDmgFile);
+			strncpy(tempDir, dmgDir, sizeof(tempDir));
+			err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL);
+			if(err != noErr) throw 0;
+			chdir(tempDir);
+			goto begin_install;
+		} else {
+			// Continue on to download file.
+			dmgName = "SecondLife.dmg";
+		}
+
+		
 		strncat(temp, "/SecondLifeUpdate_XXXXXX", (sizeof(temp) - strlen(temp)) - 1);
 		if(mkdtemp(temp) == NULL)
 		{
@@ -979,14 +1026,17 @@ void *updatethreadproc(void*)
 			fclose(downloadFile);
 			downloadFile = NULL;
 		}
-		
+
+	begin_install:
 		sendProgress(0, 0, CFSTR("Mounting image..."));
 		LLFile::mkdir("mnt", 0700);
 		
 		// NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder,
 		//		but if our cleanup fails, this makes it much harder for the user to unmount the image.
 		std::string mountOutput;
-		FILE* mounter = popen("hdiutil attach SecondLife.dmg -mountpoint mnt", "r");		/* Flawfinder: ignore */
+		boost::format cmdFormat("hdiutil attach %s -mountpoint mnt");
+		cmdFormat % dmgName;
+		FILE* mounter = popen(cmdFormat.str().c_str(), "r");		/* Flawfinder: ignore */
 		
 		if(mounter == NULL)
 		{
@@ -1052,12 +1102,19 @@ void *updatethreadproc(void*)
 			throw 0;
 		}
 
+		sendProgress(0, 0, CFSTR("Searching for the app bundle..."));
 		err = findAppBundleOnDiskImage(&mountRef, &sourceRef);
 		if(err != noErr)
 		{
 			llinfos << "Couldn't find application bundle on mounted disk image." << llendl;
 			throw 0;
 		}
+		else
+		{
+			llinfos << "found the bundle." << llendl;
+		}
+
+		sendProgress(0, 0, CFSTR("Preparing to copy files..."));
 		
 		FSRef asideRef;
 		char aside[MAX_PATH];		/* Flawfinder: ignore */
@@ -1077,7 +1134,11 @@ void *updatethreadproc(void*)
 			// Move aside old version (into work directory)
 			err = FSMoveObject(&targetRef, &tempDirRef, &asideRef);
 			if(err != noErr)
+			{
+				llwarns << "failed to move aside old version (error code " << 
+					err << ")" << llendl;
 				throw 0;
+			}
 
 			// Grab the path for later use.
 			err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside));
@@ -1175,6 +1236,10 @@ void *updatethreadproc(void*)
 		llinfos << "Moving work directory to the trash." << llendl;
 
 		err = FSMoveObject(&tempDirRef, &trashFolderRef, NULL);
+		if(err != noErr) {
+			llwarns << "failed to move files to trash, (error code " <<
+				err << ")" << llendl;
+		}
 
 //		snprintf(temp, sizeof(temp), "rm -rf '%s'", tempDir);
 //		printf("%s\n", temp);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3a4b9be0d7393c4def4188c5af5178130421798b..fa49c1ac4c420e19dbf04a36c21b84f5b8be3c16 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -64,6 +64,7 @@ include_directories(
     ${LSCRIPT_INCLUDE_DIRS}
     ${LSCRIPT_INCLUDE_DIRS}/lscript_compile
     ${LLLOGIN_INCLUDE_DIRS}
+    ${UPDATER_INCLUDE_DIRS}
     )
 
 set(viewer_SOURCE_FILES
@@ -284,6 +285,7 @@ set(viewer_SOURCE_FILES
     llloginhandler.cpp
     lllogininstance.cpp
     llmachineid.cpp
+    llmainlooprepeater.cpp
     llmanip.cpp
     llmaniprotate.cpp
     llmanipscale.cpp
@@ -445,6 +447,7 @@ set(viewer_SOURCE_FILES
     lltoastimpanel.cpp
     lltoastnotifypanel.cpp
     lltoastpanel.cpp
+    lltoastscripttextbox.cpp
     lltool.cpp
     lltoolbrush.cpp
     lltoolcomp.cpp
@@ -817,6 +820,7 @@ set(viewer_HEADER_FILES
     llloginhandler.h
     lllogininstance.h
     llmachineid.h
+    llmainlooprepeater.h
     llmanip.h
     llmaniprotate.h
     llmanipscale.h
@@ -975,6 +979,7 @@ set(viewer_HEADER_FILES
     lltoastimpanel.h
     lltoastnotifypanel.h
     lltoastpanel.h
+    lltoastscripttextbox.h
     lltool.h
     lltoolbrush.h
     lltoolcomp.h
@@ -1644,7 +1649,14 @@ if (WINDOWS)
     endif (PACKAGE)
 endif (WINDOWS)
 
+# *NOTE - this list is very sensitive to ordering, test carefully on all
+# platforms if you change the releative order of the entries here.
+# In particular, cmake 2.6.4 (when buidling with linux/makefile generators)
+# appears to sometimes de-duplicate redundantly listed dependencies improperly.
+# To work around this, higher level modules should be listed before the modules
+# that they depend upon. -brad
 target_link_libraries(${VIEWER_BINARY_NAME}
+    ${UPDATER_LIBRARIES}
     ${LLAUDIO_LIBRARIES}
     ${LLCHARACTER_LIBRARIES}
     ${LLIMAGE_LIBRARIES}
@@ -1831,10 +1843,18 @@ if (PACKAGE)
     set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
   endif (LINUX)
 
+  if(CMAKE_CFG_INTDIR STREQUAL ".")
+      set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE})
+  else(CMAKE_CFG_INTDIR STREQUAL ".")
+      # set LLBUILD_CONFIG to be a shell variable evaluated at build time
+      # reflecting the configuration we are currently building.
+      set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR})
+  endif(CMAKE_CFG_INTDIR STREQUAL ".")
   add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
     COMMAND "${PYTHON_EXECUTABLE}"
     ARGS
       "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py"
+      "${LLBUILD_CONFIG}"
       "${VIEWER_DIST_DIR}"
       "${VIEWER_EXE_GLOBS}"
       "${VIEWER_LIB_GLOB}"
@@ -1843,7 +1863,7 @@ if (PACKAGE)
     DEPENDS generate_breakpad_symbols.py
     VERBATIM
   )
-  add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}")
+  add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}")
   add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}")
   add_dependencies(package generate_breakpad_symbols)
 endif (PACKAGE)
@@ -1858,6 +1878,7 @@ if (LL_TESTS)
     llmediadataclient.cpp
     lllogininstance.cpp
     llviewerhelputil.cpp
+    llversioninfo.cpp
   )
 
   ##################################################
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 0562cf5480e901c8d090674e14f53aee5ab961ee..1b8393330d92dade02d5417fd6d5ec222b023537 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -363,8 +363,7 @@
     <map>
       <key>count</key>
       <integer>1</integer>
-      <key>map-to</key>
-      <string>VersionChannelName</string>
+      <!-- Special case. Not mapped to a setting. -->
     </map>
 
     <key>loginpage</key>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 561456c9d68c8dec47532692fcd6130b80240165..0f946b0f0b2deb47e6be125f95056e300510c4ea 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1365,6 +1365,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>LetterKeysFocusChatBar</key>
+    <map>
+      <key>Comment</key>
+      <string>When printable characters keys (possibly with Shift held) are pressed, the chatbar takes focus</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>S32</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>ChatBubbleOpacity</key>
     <map>
       <key>Comment</key>
@@ -8340,6 +8351,17 @@
       <key>Value</key>
       <real>1.0</real>
     </map>
+	<key>RenderTransparentWater</key>
+	<map>
+	  <key>Comment</key>
+	  <string>Render water as transparent.  Setting to false renders water as opaque with a simple texture applied.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+	</map>
     <key>RenderTreeLODFactor</key>
     <map>
       <key>Comment</key>
@@ -11068,7 +11090,62 @@
       <key>Value</key>
       <integer>15</integer>
     </map>
-	<key>UploadBakedTexOld</key>
+    <key>UpdaterServiceActive</key>
+    <map>
+      <key>Comment</key>
+      <string>Enable or disable the updater service.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>UpdaterServiceCheckPeriod</key>
+    <map>
+      <key>Comment</key>
+      <string>Default period between update checking.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>3600</integer>
+    </map>
+    <key>UpdaterServiceURL</key>
+    <map>
+      <key>Comment</key>
+      <string>Default location for the updater service.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>http://update.secondlife.com</string>
+    </map>
+    <key>UpdaterServicePath</key>
+    <map>
+      <key>Comment</key>
+      <string>Path on the update server host.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>update</string>
+    </map>
+    <key>UpdaterServiceProtocolVersion</key>
+    <map>
+      <key>Comment</key>
+      <string>The update protocol version to use.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>v1.0</string>
+    </map>
+    <key>UploadBakedTexOld</key>
     <map>
       <key>Comment</key>
       <string>Forces the baked texture pipeline to upload using the old method.</string>
@@ -11421,17 +11498,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>VersionChannelName</key>
-    <map>
-      <key>Comment</key>
-      <string>Versioning Channel Name.</string>
-      <key>Persist</key>
-      <integer>0</integer>
-      <key>Type</key>
-      <string>String</string>
-      <key>Value</key>
-      <string>Second Life Release</string>
-    </map>
     <key>VertexShaderEnable</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index d69842d5f100320355b9f9e60c98e5603fd8577b..a95abd7dd185e55e8992b612dfbb20f393d61788 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -42,6 +42,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	4
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVBOEnable				1	1
@@ -80,6 +81,7 @@ RenderObjectBump			1	0
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	0
 RenderTerrainLODFactor		1	1
+RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	0.5
@@ -108,6 +110,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	1.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -135,6 +138,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	2
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -162,6 +166,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	4
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	2.0
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index efe29005f23895393beffe1f9cf34e8b4fe299bf..a52b32355de22ba0efbafb2451686a9cf8fdf8d4 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -42,6 +42,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	4
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVBOEnable				1	1
@@ -79,6 +80,7 @@ RenderObjectBump			1	0
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	0
 RenderTerrainLODFactor		1	1
+RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	0.5
@@ -107,6 +109,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	1.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -134,6 +137,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	2
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -161,6 +165,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	4
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	2.0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index f030c9f8e594015287ff2d7946f1f67559a158fd..6dabef53a846a54d69de2f6f83ed623c531c3e65 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -43,6 +43,7 @@ RenderObjectBump				1	1
 RenderReflectionDetail			1	3
 RenderTerrainDetail				1	1
 RenderTerrainLODFactor			1	2.0
+RenderTransparentWater			1	1
 RenderTreeLODFactor				1	1.0
 RenderUseImpostors				1	1
 RenderVBOEnable					1	1
@@ -80,6 +81,7 @@ RenderObjectBump			1	0
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	0
 RenderTerrainLODFactor		1	1
+RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	0.5
@@ -107,6 +109,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	1.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -133,6 +136,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	2
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -159,6 +163,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	3
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	2.0
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index dae77059710835a1c45477dc308e0d806b794438..a09ba17c6246535e031014482d732addb02f9114 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -42,6 +42,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	4
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVBOEnable				1	1
@@ -80,6 +81,7 @@ RenderObjectBump			1	0
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	0
 RenderTerrainLODFactor		1	1
+RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	0.5
@@ -108,6 +110,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	0
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	1.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -135,6 +138,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	2
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	1.125
@@ -162,6 +166,7 @@ RenderObjectBump			1	1
 RenderReflectionDetail		1	4
 RenderTerrainDetail			1	1
 RenderTerrainLODFactor		1	2.0
+RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderUseImpostors			1	1
 RenderVolumeLODFactor		1	2.0
diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py
index 8f2dfd2348909bec0991d12992956d4c5bcd91c7..4fd04d780eb0a8b926797d7623d26b1b04ab611e 100644
--- a/indra/newview/generate_breakpad_symbols.py
+++ b/indra/newview/generate_breakpad_symbols.py
@@ -31,6 +31,7 @@
 import itertools
 import operator
 import os
+import re
 import sys
 import shlex
 import subprocess
@@ -45,8 +46,12 @@ def __init__(self, modules):
         Exception.__init__(self, "Failed to find required modules: %r" % modules)
         self.modules = modules
 
-def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file):
-    print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file))
+def main(configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file):
+    print "generate_breakpad_symbols run with args: %s" % str((configuration, viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file))
+
+    if not re.match("release", configuration, re.IGNORECASE):
+        print "skipping breakpad symbol generation for non-release build."
+        return 0
 
     # split up list of viewer_exes
     # "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin']
@@ -122,7 +127,7 @@ def match_module_basename(m):
     return 0
 
 if __name__ == "__main__":
-    if len(sys.argv) != 6:
+    if len(sys.argv) != 7:
         usage()
         sys.exit(1)
     sys.exit(main(*sys.argv[1:]))
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index d5712f80cfffe15745b26700903103c2d90778ce..4e8ed807eeef65541d288055ff4dbb948fd91b9b 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -85,6 +85,8 @@ AutoCloseWindow true					; after all files install, close window
 InstallDir "$PROGRAMFILES\${INSTNAME}"
 InstallDirRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" ""
 DirText $(DirectoryChooseTitle) $(DirectoryChooseSetup)
+Page directory dirPre
+Page instfiles
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; Variables
@@ -95,6 +97,8 @@ Var INSTFLAGS
 Var INSTSHORTCUT
 Var COMMANDLINE         ; command line passed to this installer, set in .onInit
 Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer
+Var SKIP_DIALOGS        ; set from command line in  .onInit. autoinstall 
+                        ; GUI and the defaults.
 
 ;;; Function definitions should go before file includes, because calls to
 ;;; DLLs like LangDLL trigger an implicit file include, so if that call is at
@@ -110,6 +114,9 @@ Var SHORTCUT_LANG_PARAM ; "--set InstallLanguage de", passes language to viewer
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 Function .onInstSuccess
     Push $R0	# Option value, unused
+
+    StrCmp $SKIP_DIALOGS "true" label_launch 
+
     ${GetOptions} $COMMANDLINE "/AUTOSTART" $R0
     # If parameter was there (no error) just launch
     # Otherwise ask
@@ -128,6 +135,13 @@ label_no_launch:
 	Pop $R0
 FunctionEnd
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Pre-directory page callback
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+Function dirPre
+    StrCmp $SKIP_DIALOGS "true" 0 +2
+	Abort
+FunctionEnd    
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Make sure we're not on Windows 98 / ME
@@ -145,7 +159,8 @@ Function CheckWindowsVersion
 	StrCmp $R0 "NT" win_ver_bad
 	Return
 win_ver_bad:
-	MessageBox MB_YESNO $(CheckWindowsVersionMB) IDNO win_ver_abort
+	StrCmp $SKIP_DIALOGS "true" +2 ; If skip_dialogs is set just install
+            MessageBox MB_YESNO $(CheckWindowsVersionMB) IDNO win_ver_abort
 	Return
 win_ver_abort:
 	Quit
@@ -184,13 +199,13 @@ FunctionEnd
 ; If it has, allow user to bail out of install process.
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 Function CheckIfAlreadyCurrent
-  Push $0
-	ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version"
-    StrCmp $0 ${VERSION_LONG} 0 DONE
-	MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK DONE
+    Push $0
+    ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version"
+    StrCmp $0 ${VERSION_LONG} 0 continue_install
+    StrCmp $SKIP_DIALOGS "true" continue_install
+    MessageBox MB_OKCANCEL $(CheckIfCurrentMB) /SD IDOK IDOK continue_install
     Quit
-
-  DONE:
+continue_install:
     Pop $0
     Return
 FunctionEnd
@@ -203,7 +218,9 @@ Function CloseSecondLife
   Push $0
   FindWindow $0 "Second Life" ""
   IntCmp $0 0 DONE
-  MessageBox MB_OKCANCEL $(CloseSecondLifeInstMB) IDOK CLOSE IDCANCEL CANCEL_INSTALL
+  
+  StrCmp $SKIP_DIALOGS "true" CLOSE
+    MessageBox MB_OKCANCEL $(CloseSecondLifeInstMB) IDOK CLOSE IDCANCEL CANCEL_INSTALL
 
   CANCEL_INSTALL:
     Quit
@@ -659,23 +676,29 @@ FunctionEnd
 Function .onInit
     Push $0
     ${GetParameters} $COMMANDLINE              ; get our command line
+
+    ${GetOptions} $COMMANDLINE "/SKIP_DIALOGS" $0   
+    IfErrors +2 0 ; If error jump past setting SKIP_DIALOGS
+        StrCpy $SKIP_DIALOGS "true"
+
     ${GetOptions} $COMMANDLINE "/LANGID=" $0   ; /LANGID=1033 implies US English
     ; If no language (error), then proceed
-    IfErrors lbl_check_silent
+    IfErrors lbl_configure_default_lang
     ; No error means we got a language, so use it
     StrCpy $LANGUAGE $0
     Goto lbl_return
 
-lbl_check_silent:
-    ; For silent installs, no language prompt, use default
-    IfSilent lbl_return
-    
-	; If we currently have a version of SL installed, default to the language of that install
+lbl_configure_default_lang:
+    ; If we currently have a version of SL installed, default to the language of that install
     ; Otherwise don't change $LANGUAGE and it will default to the OS UI language.
-	ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" "InstallerLanguage"
-    IfErrors lbl_build_menu
+    ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" "InstallerLanguage"
+    IfErrors +2 0 ; If error skip the copy instruction 
 	StrCpy $LANGUAGE $0
 
+    ; For silent installs, no language prompt, use default
+    IfSilent lbl_return
+    StrCmp $SKIP_DIALOGS "true" lbl_return
+  
 lbl_build_menu:
 	Push ""
     # Use separate file so labels can be UTF-16 but we can still merge changes
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index c9bd7851ed5c610a046130665cea1e94f8de9b79..3a45c79ec3322844b7d946e40bc43acb2da0c307 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -59,6 +59,7 @@
 #include "llsidetray.h"
 #include "llsky.h"
 #include "llsmoothstep.h"
+#include "llstartup.h"
 #include "llstatusbar.h"
 #include "llteleportflags.h"
 #include "lltool.h"
@@ -2452,7 +2453,7 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO
 
 BOOL LLAgent::canJoinGroups() const
 {
-	return mGroups.count() < MAX_AGENT_GROUPS;
+	return mGroups.count() < gMaxAgentGroups;
 }
 
 LLQuaternion LLAgent::getHeadRotation()
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f66663891da2eca6d0bd8450f1b994a022f742d6..b6f52e3e15c2dc146e5b4fd03cd746840e4f3cd6 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -83,6 +83,7 @@
 
 #include "llweb.h"
 #include "llsecondlifeurls.h"
+#include "llupdaterservice.h"
 
 // Linden library includes
 #include "llavatarnamecache.h"
@@ -196,6 +197,8 @@
 #include "llsecapi.h"
 #include "llmachineid.h"
 
+#include "llmainlooprepeater.h"
+
 // *FIX: These extern globals should be cleaned up.
 // The globals either represent state/config/resource-storage of either 
 // this app, or another 'component' of the viewer. App globals should be 
@@ -576,7 +579,8 @@ LLAppViewer::LLAppViewer() :
 	mAgentRegionLastAlive(false),
 	mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
 	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
-	mFastTimerLogThread(NULL)
+	mFastTimerLogThread(NULL),
+	mUpdater(new LLUpdaterService())
 {
 	if(NULL != sInstance)
 	{
@@ -652,10 +656,13 @@ bool LLAppViewer::init()
     initThreads();
     writeSystemInfo();
 
-	// Build a string representing the current version number.
-    gCurrentVersion = llformat("%s %s", 
-							   gSavedSettings.getString("VersionChannelName").c_str(),
-							   LLVersionInfo::getVersion().c_str());
+	// Initialize updater service (now that we have an io pump)
+	initUpdater();
+	if(isQuitting())
+	{
+		// Early out here because updater set the quitting flag.
+		return true;
+	}
 
 	//////////////////////////////////////////////////////////////////////////////
 	//////////////////////////////////////////////////////////////////////////////
@@ -799,6 +806,9 @@ bool LLAppViewer::init()
 		return 1;
 	}
 	
+	// Initialize the repeater service.
+	LLMainLoopRepeater::instance().start();
+	
 	//
 	// Initialize the window
 	//
@@ -895,7 +905,8 @@ bool LLAppViewer::init()
 	gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString();
 
 	// Save the current version to the prefs file
-	gSavedSettings.setString("LastRunVersion", gCurrentVersion);
+	gSavedSettings.setString("LastRunVersion", 
+							 LLVersionInfo::getVersionAndChannel());
 
 	gSimLastTime = gRenderStartTime.getElapsedTimeF32();
 	gSimFrames = (F32)gFrameCount;
@@ -970,7 +981,7 @@ bool LLAppViewer::mainLoop()
 	gServicePump = new LLPumpIO(gAPRPoolp);
 	LLHTTPClient::setPump(*gServicePump);
 	LLCurl::setCAFile(gDirUtilp->getCAFile());
-
+	
 	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
 
 	LLVoiceChannel::initClass();
@@ -1353,11 +1364,14 @@ bool LLAppViewer::cleanup()
 	llinfos << "Cleaning Up" << llendflush;
 
 	// Must clean up texture references before viewer window is destroyed.
-	LLHUDManager::getInstance()->updateEffects();
-	LLHUDObject::updateAll();
-	LLHUDManager::getInstance()->cleanupEffects();
-	LLHUDObject::cleanupHUDObjects();
-	llinfos << "HUD Objects cleaned up" << llendflush;
+	if(LLHUDManager::instanceExists())
+	{
+		LLHUDManager::getInstance()->updateEffects();
+		LLHUDObject::updateAll();
+		LLHUDManager::getInstance()->cleanupEffects();
+		LLHUDObject::cleanupHUDObjects();
+		llinfos << "HUD Objects cleaned up" << llendflush;
+	}
 
 	LLKeyframeDataCache::clear();
 	
@@ -1369,8 +1383,10 @@ bool LLAppViewer::cleanup()
 	// Note: this is where gWorldMap used to be deleted.
 
 	// Note: this is where gHUDManager used to be deleted.
-	LLHUDManager::getInstance()->shutdownClass();
-	
+	if(LLHUDManager::instanceExists())
+	{
+		LLHUDManager::getInstance()->shutdownClass();
+	}
 
 	delete gAssetStorage;
 	gAssetStorage = NULL;
@@ -1666,7 +1682,10 @@ bool LLAppViewer::cleanup()
 
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	llinfos << "Auditing VFS" << llendl;
-	gVFS->audit();
+	if(gVFS)
+	{
+		gVFS->audit();
+	}
 #endif
 
 	llinfos << "Misc Cleanup" << llendflush;
@@ -1707,6 +1726,8 @@ bool LLAppViewer::cleanup()
 		llinfos << "File launched." << llendflush;
 	}
 
+	LLMainLoopRepeater::instance().stop();
+
 	ll_close_fail_log();
 
     llinfos << "Goodbye!" << llendflush;
@@ -1953,8 +1974,6 @@ bool LLAppViewer::initConfiguration()
 	gSavedSettings.setString("ClientSettingsFile", 
         gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global")));
 
-	gSavedSettings.setString("VersionChannelName", LLVersionInfo::getChannel());
-
 #ifndef	LL_RELEASE_FOR_DOWNLOAD
 	// provide developer build only overrides for these control variables that are not
 	// persisted to settings.xml
@@ -2095,6 +2114,11 @@ bool LLAppViewer::initConfiguration()
         }
     }
 
+    if(clp.hasOption("channel"))
+    {
+		LLVersionInfo::resetChannel(clp.getOption("channel")[0]);
+	}
+	
 
 	// If we have specified crash on startup, set the global so we'll trigger the crash at the right time
 	if(clp.hasOption("crashonstartup"))
@@ -2364,6 +2388,58 @@ bool LLAppViewer::initConfiguration()
 	return true; // Config was successful.
 }
 
+namespace {
+    // *TODO - decide if there's a better place for this function.
+    // do we need a file llupdaterui.cpp or something? -brad
+    bool notify_update(LLSD const & evt)
+    {
+		switch (evt["type"].asInteger())
+		{
+			case LLUpdaterService::DOWNLOAD_COMPLETE:
+				LLNotificationsUtil::add("DownloadBackground");
+				break;
+			case LLUpdaterService::INSTALL_ERROR:
+				LLNotificationsUtil::add("FailedUpdateInstall");
+				break;
+			default:
+				llinfos << "unhandled update event " << evt << llendl;
+				break;
+		}
+
+		// let others also handle this event by default
+        return false;
+    }
+};
+
+void LLAppViewer::initUpdater()
+{
+	// Initialize the updater service.
+	// Generate URL to the udpater service
+	// Get Channel
+	// Get Version
+	std::string url = gSavedSettings.getString("UpdaterServiceURL");
+	std::string channel = LLVersionInfo::getChannel();
+	std::string version = LLVersionInfo::getVersion();
+	std::string protocol_version = gSavedSettings.getString("UpdaterServiceProtocolVersion");
+	std::string service_path = gSavedSettings.getString("UpdaterServicePath");
+	U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod");
+
+	mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
+	mUpdater->initialize(protocol_version, 
+						 url, 
+						 service_path, 
+						 channel, 
+						 version);
+ 	mUpdater->setCheckPeriod(check_period);
+	if(gSavedSettings.getBOOL("UpdaterServiceActive"))
+	{
+		bool install_if_ready = true;
+		mUpdater->startChecking(install_if_ready);
+	}
+
+    LLEventPump & updater_pump = LLEventPumps::instance().obtain(LLUpdaterService::pumpName());
+    updater_pump.listen("notify_update", &notify_update);
+}
 
 void LLAppViewer::checkForCrash(void)
 {
@@ -2524,15 +2600,18 @@ void LLAppViewer::cleanupSavedSettings()
 
 	// save window position if not maximized
 	// as we don't track it in callbacks
-	BOOL maximized = gViewerWindow->mWindow->getMaximized();
-	if (!maximized)
+	if(NULL != gViewerWindow)
 	{
-		LLCoordScreen window_pos;
-
-		if (gViewerWindow->mWindow->getPosition(&window_pos))
+		BOOL maximized = gViewerWindow->mWindow->getMaximized();
+		if (!maximized)
 		{
-			gSavedSettings.setS32("WindowX", window_pos.mX);
-			gSavedSettings.setS32("WindowY", window_pos.mY);
+			LLCoordScreen window_pos;
+
+			if (gViewerWindow->mWindow->getPosition(&window_pos))
+			{
+				gSavedSettings.setS32("WindowX", window_pos.mX);
+				gSavedSettings.setS32("WindowY", window_pos.mY);
+			}
 		}
 	}
 
@@ -2555,7 +2634,7 @@ void LLAppViewer::writeSystemInfo()
 {
 	gDebugInfo["SLLog"] = LLError::logFileName();
 
-	gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
+	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
 	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
 	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
 	gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
@@ -2658,7 +2737,7 @@ void LLAppViewer::handleViewerCrash()
 	
 	//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version
 	//to check against no matter what
-	gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
+	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
 
 	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
 	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
@@ -4271,7 +4350,10 @@ void LLAppViewer::disconnectViewer()
 
 	// This is where we used to call gObjectList.destroy() and then delete gWorldp.
 	// Now we just ask the LLWorld singleton to cleanly shut down.
-	LLWorld::getInstance()->destroyClass();
+	if(LLWorld::instanceExists())
+	{
+		LLWorld::getInstance()->destroyClass();
+	}
 
 	// call all self-registered classes
 	LLDestroyClassList::instance().fireCallbacks();
@@ -4385,7 +4467,7 @@ void LLAppViewer::handleLoginComplete()
 	initMainloopTimeout("Mainloop Init");
 
 	// Store some data to DebugInfo in case of a freeze.
-	gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName");
+	gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::getChannel();
 
 	gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::getMajor();
 	gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
@@ -4491,7 +4573,7 @@ void LLAppViewer::launchUpdater()
 	// *TODO change userserver to be grid on both viewer and sim, since
 	// userserver no longer exists.
 	query_map["userserver"] = LLGridManager::getInstance()->getGridLabel();
-	query_map["channel"] = gSavedSettings.getString("VersionChannelName");
+	query_map["channel"] = LLVersionInfo::getChannel();
 	// *TODO constantize this guy
 	// *NOTE: This URL is also used in win_setup/lldownloader.cpp
 	LLURI update_url = LLURI::buildHTTP("secondlife.com", 80, "update.php", query_map);
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index a14ab4362f104922abe0602321ba7211c83b4765..aa4256a2bde478debe60e235d99fb1536dc02cdf 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -39,7 +39,7 @@ class LLTextureCache;
 class LLImageDecodeThread;
 class LLTextureFetch;
 class LLWatchdogTimeout;
-class LLCommandLineParser;
+class LLUpdaterService;
 
 struct apr_dso_handle_t;
 
@@ -186,7 +186,7 @@ class LLAppViewer : public LLApp
 
 	bool initThreads(); // Initialize viewer threads, return false on failure.
 	bool initConfiguration(); // Initialize settings from the command line/config file.
-
+	void initUpdater(); // Initialize the updater service.
 	bool initCache(); // Initialize local client cache.
 
 
@@ -264,7 +264,14 @@ class LLAppViewer : public LLApp
 
 	U32 mAvailPhysicalMemInKB ;
 	U32 mAvailVirtualMemInKB ;
+	
+	boost::scoped_ptr<LLUpdaterService> mUpdater;
+
+	//---------------------------------------------
+	//*NOTE: Mani - legacy updater stuff
+	// Still useable?
 public:
+
 	//some information for updater
 	typedef struct
 	{
@@ -274,6 +281,7 @@ class LLAppViewer : public LLApp
 	static LLUpdaterInfo *sUpdaterInfo ;
 
 	void launchUpdater();
+	//---------------------------------------------
 };
 
 // consts from viewer.h
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 8f385160e9e50c084a03a3f5b62515a4117a468c..885d5535247e86c3de6449e2d06fd110bd85b21e 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -1092,9 +1092,11 @@ LLChicletPanel::LLChicletPanel(const Params&p)
 
 LLChicletPanel::~LLChicletPanel()
 {
-	LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton);
-	LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton);
-
+	if(LLTransientFloaterMgr::instanceExists())
+	{
+		LLTransientFloaterMgr::getInstance()->removeControlView(mLeftScrollButton);
+		LLTransientFloaterMgr::getInstance()->removeControlView(mRightScrollButton);
+	}
 }
 
 void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index 2b92b228b39c2274981a3bae9df64905fb92abf8..b4a1457f47f9d302982bbfecc489ebb9f8cd0b35 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -166,7 +166,7 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo()
 		gAgent.getSecureSessionID().asString());
 	keywordArgs.appendString("language", LLUI::getLanguage());
 	keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
-	keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+	keywordArgs.appendString("viewerChannel", LLVersionInfo::getChannel());
 	keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
 	keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
 	keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
@@ -241,7 +241,7 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
 	{
 		keywordArgs.appendString("password", password);
 	}
-	keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+	keywordArgs.appendString("viewerChannel", LLVersionInfo::getChannel());
 	keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::getMajor());
 	keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::getMinor());
 	keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::getPatch());
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 0ee70bcdd14525a810dd9c11461b4d8239a927b1..dc94924da4e2cc358fee04a08d82c861061ae4de 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -48,7 +48,8 @@
 #include "llviewershadermgr.h"
 #include "llwaterparammanager.h"
 
-const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004");
+const LLUUID TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004");
+const LLUUID OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055");
 
 static float sTime;
 
@@ -71,10 +72,14 @@ LLDrawPoolWater::LLDrawPoolWater() :
 	gGL.getTexUnit(0)->bind(mHBTex[1]);
 	mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
 
-	mWaterImagep = LLViewerTextureManager::getFetchedTexture(WATER_TEST);
-	mWaterImagep->setNoDelete() ;
+
+	mWaterImagep = LLViewerTextureManager::getFetchedTexture(TRANSPARENT_WATER_TEXTURE);
+	llassert(mWaterImagep);
+	mWaterImagep->setNoDelete();
+	mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(OPAQUE_WATER_TEXTURE);
+	llassert(mOpaqueWaterImagep);
 	mWaterNormp = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL);
-	mWaterNormp->setNoDelete() ;
+	mWaterNormp->setNoDelete();
 
 	restoreGL();
 }
@@ -161,6 +166,14 @@ void LLDrawPoolWater::render(S32 pass)
 
 	std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
 
+	// See if we are rendering water as opaque or not
+	if (!gSavedSettings.getBOOL("RenderTransparentWater"))
+	{
+		// render water for low end hardware
+		renderOpaqueLegacyWater();
+		return;
+	}
+
 	LLGLEnable blend(GL_BLEND);
 
 	if ((mVertexShaderLevel > 0) && !sSkipScreenCopy)
@@ -314,6 +327,87 @@ void LLDrawPoolWater::render(S32 pass)
 	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
 }
 
+// for low end hardware
+void LLDrawPoolWater::renderOpaqueLegacyWater()
+{
+	LLVOSky *voskyp = gSky.mVOSkyp;
+
+	stop_glerror();
+
+	// Depth sorting and write to depth buffer
+	// since this is opaque, we should see nothing
+	// behind the water.  No blending because
+	// of no transparency.  And no face culling so
+	// that the underside of the water is also opaque.
+	LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
+	LLGLDisable no_cull(GL_CULL_FACE);
+	LLGLDisable no_blend(GL_BLEND);
+
+	gPipeline.disableLights();
+
+	mOpaqueWaterImagep->addTextureStats(1024.f*1024.f);
+
+	// Activate the texture binding and bind one
+	// texture since all images will have the same texture
+	gGL.getTexUnit(0)->activate();
+	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+	gGL.getTexUnit(0)->bind(mOpaqueWaterImagep);
+
+	// Automatically generate texture coords for water texture
+	glEnable(GL_TEXTURE_GEN_S); //texture unit 0
+	glEnable(GL_TEXTURE_GEN_T); //texture unit 0
+	glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+	glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+	// Use the fact that we know all water faces are the same size
+	// to save some computation
+
+	// Slowly move texture coordinates over time so the watter appears
+	// to be moving.
+	F32 movement_period_secs = 50.f;
+
+	F32 offset = fmod(gFrameTimeSeconds, movement_period_secs);
+
+	if (movement_period_secs != 0)
+	{
+	 	offset /= movement_period_secs;
+	}
+	else
+	{
+		offset = 0;
+	}
+
+	F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset };
+	F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset };
+
+	glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
+	glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
+
+	glColor3f(1.f, 1.f, 1.f);
+
+	for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+		 iter != mDrawFace.end(); iter++)
+	{
+		LLFace *face = *iter;
+		if (voskyp->isReflFace(face))
+		{
+			continue;
+		}
+
+		face->renderIndexed();
+	}
+
+	stop_glerror();
+
+	// Reset the settings back to expected values
+	glDisable(GL_TEXTURE_GEN_S); //texture unit 0
+	glDisable(GL_TEXTURE_GEN_T); //texture unit 0
+
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+}
+
+
 void LLDrawPoolWater::renderReflection(LLFace* face)
 {
 	LLVOSky *voskyp = gSky.mVOSkyp;
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index 2648a5276cb6b2ae8d8121a4ed5869ca4daba49b..99b541ca5a384d1de939c9795e96b908f0265abd 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -39,6 +39,7 @@ class LLDrawPoolWater: public LLFacePool
 protected:
 	LLPointer<LLViewerTexture> mHBTex[2];
 	LLPointer<LLViewerTexture> mWaterImagep;
+	LLPointer<LLViewerTexture> mOpaqueWaterImagep;
 	LLPointer<LLViewerTexture> mWaterNormp;
 
 public:
@@ -80,6 +81,9 @@ class LLDrawPoolWater: public LLFacePool
 
 	void renderReflection(LLFace* face);
 	void shade();
+
+protected:
+	void renderOpaqueLegacyWater();
 };
 
 void cgErrorCallback();
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 135137069c5a4735a5b39cf0dc1ca803e475352c..8ae3ccbae3146d824c83a63b492c06b46ebf1060 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -213,7 +213,7 @@ LLSD LLFloaterAbout::getInfo()
 	info["VIEWER_VERSION_STR"] = LLVersionInfo::getVersion();
 	info["BUILD_DATE"] = __DATE__;
 	info["BUILD_TIME"] = __TIME__;
-	info["CHANNEL"] = gSavedSettings.getString("VersionChannelName");
+	info["CHANNEL"] = LLVersionInfo::getChannel();
 
 	info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url();
 
@@ -291,7 +291,7 @@ static std::string get_viewer_release_notes_url()
 	std::string url = LLTrans::getString("RELEASE_NOTES_BASE_URL");
 	if (! LLStringUtil::endsWith(url, "/"))
 		url += "/";
-	url += gSavedSettings.getString("VersionChannelName") + "/";
+	url += LLVersionInfo::getChannel() + "/";
 	url += LLVersionInfo::getShortVersion();
 	return LLWeb::escapeURL(url);
 }
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index 234a09d157d1656d0e536a210dcaeae64006f796..d84364a68a76e4fac73e28bfad7f4bc5330ae099 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -41,6 +41,7 @@
 #include "llbutton.h"
 #include "llgroupactions.h"
 #include "llscrolllistctrl.h"
+#include "llstartup.h"
 #include "lltextbox.h"
 #include "lluictrlfactory.h"
 #include "lltrans.h"
@@ -171,7 +172,7 @@ void LLPanelGroups::reset()
 		group_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
 	}
 	getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count()));
-	getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",MAX_AGENT_GROUPS));
+	getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",gMaxAgentGroups));
 
 	init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID());
 	enableButtons();
@@ -182,7 +183,7 @@ BOOL LLPanelGroups::postBuild()
 	childSetCommitCallback("group list", onGroupList, this);
 
 	getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count()));
-	getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",MAX_AGENT_GROUPS));
+	getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",gMaxAgentGroups));
 
 	LLScrollListCtrl *list = getChild<LLScrollListCtrl>("group list");
 	if (list)
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index c105f023c770eb11b1400b1143d2d3d990df7ab7..ac940f4f77596ac2b37b00449189142633049f51 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -282,7 +282,8 @@ std::string LLFloaterPreference::sSkin = "";
 LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	: LLFloater(key),
 	mGotPersonalInfo(false),
-	mOriginalIMViaEmail(false)
+	mOriginalIMViaEmail(false),
+	mDoubleClickActionDirty(false)
 {
 	//Build Floater is now Called from 	LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>);
 	
@@ -320,6 +321,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.getUIColor",				boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2));
 	mCommitCallbackRegistrar.add("Pref.MaturitySettings",		boost::bind(&LLFloaterPreference::onChangeMaturity, this));
 	mCommitCallbackRegistrar.add("Pref.BlockList",				boost::bind(&LLFloaterPreference::onClickBlockList, this));
+	mCommitCallbackRegistrar.add("Pref.CommitDoubleClickChekbox",	boost::bind(&LLFloaterPreference::onDoubleClickCheckBox, this, _1));
+	mCommitCallbackRegistrar.add("Pref.CommitRadioDoubleClick",	boost::bind(&LLFloaterPreference::onDoubleClickRadio, this));
 
 	sSkin = gSavedSettings.getString("SkinCurrent");
 	
@@ -342,6 +345,8 @@ BOOL LLFloaterPreference::postBuild()
 	if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
 		tabcontainer->selectFirstTab();
 
+	updateDoubleClickControls();
+
 	getChild<LLUICtrl>("cache_location")->setEnabled(FALSE); // make it read-only but selectable (STORM-227)
 	std::string cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
 	setCacheLocation(cache_location);
@@ -475,6 +480,12 @@ void LLFloaterPreference::apply()
 			gAgent.sendAgentUpdateUserInfo(new_im_via_email,mDirectoryVisibility);
 		}
 	}
+
+	if (mDoubleClickActionDirty)
+	{
+		updateDoubleClickSettings();
+		mDoubleClickActionDirty = false;
+	}
 }
 
 void LLFloaterPreference::cancel()
@@ -501,6 +512,12 @@ void LLFloaterPreference::cancel()
 	
 	// reverts any changes to current skin
 	gSavedSettings.setString("SkinCurrent", sSkin);
+
+	if (mDoubleClickActionDirty)
+	{
+		updateDoubleClickControls();
+		mDoubleClickActionDirty = false;
+	}
 }
 
 void LLFloaterPreference::onOpen(const LLSD& key)
@@ -1318,6 +1335,68 @@ void LLFloaterPreference::onClickBlockList()
 	}
 }
 
+void LLFloaterPreference::onDoubleClickCheckBox(LLUICtrl* ctrl)
+{
+	if (!ctrl) return;
+	mDoubleClickActionDirty = true;
+	LLRadioGroup* radio_double_click_action = getChild<LLRadioGroup>("double_click_action");
+	if (!radio_double_click_action) return;
+	// select default value("teleport") in radio-group.
+	radio_double_click_action->setSelectedIndex(0);
+	// set radio-group enabled depending on state of checkbox
+	radio_double_click_action->setEnabled(ctrl->getValue());
+}
+
+void LLFloaterPreference::onDoubleClickRadio()
+{
+	mDoubleClickActionDirty = true;
+}
+
+void LLFloaterPreference::updateDoubleClickSettings()
+{
+	LLCheckBoxCtrl* double_click_action_cb = getChild<LLCheckBoxCtrl>("double_click_chkbox");
+	if (!double_click_action_cb) return;
+	bool enable = double_click_action_cb->getValue().asBoolean();
+
+	LLRadioGroup* radio_double_click_action = getChild<LLRadioGroup>("double_click_action");
+	if (!radio_double_click_action) return;
+	
+	// enable double click radio-group depending on state of checkbox
+	radio_double_click_action->setEnabled(enable);
+	
+	if (!enable)
+	{
+		// set double click action settings values to false if checkbox was unchecked
+		gSavedSettings.setBOOL("DoubleClickAutoPilot", false);
+		gSavedSettings.setBOOL("DoubleClickTeleport", false);
+	}
+	else
+	{
+		std::string selected = radio_double_click_action->getValue().asString();
+		bool teleport_selected = selected == "radio_teleport";
+		// set double click action settings values depending on chosen radio-button
+		gSavedSettings.setBOOL( "DoubleClickTeleport", teleport_selected );
+		gSavedSettings.setBOOL( "DoubleClickAutoPilot", !teleport_selected );
+	}
+}
+
+void LLFloaterPreference::updateDoubleClickControls()
+{
+	// check is one of double-click actions settings enabled
+	bool double_click_action_enabled = gSavedSettings.getBOOL("DoubleClickAutoPilot") || gSavedSettings.getBOOL("DoubleClickTeleport");
+	LLCheckBoxCtrl* double_click_action_cb = getChild<LLCheckBoxCtrl>("double_click_chkbox");
+	if (double_click_action_cb)
+	{
+		// check checkbox if one of double-click actions settings enabled, uncheck otherwise
+		double_click_action_cb->setValue(double_click_action_enabled);
+	}
+	LLRadioGroup* double_click_action_radio = getChild<LLRadioGroup>("double_click_action");
+	if (!double_click_action_radio) return;
+	// set radio-group enabled if one of double-click actions settings enabled
+	double_click_action_radio->setEnabled(double_click_action_enabled);
+	// select button in radio-group depending on setting
+	double_click_action_radio->setSelectedIndex(gSavedSettings.getBOOL("DoubleClickAutoPilot"));
+}
 
 void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
 {
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index e99731b92e41c0d3b0808283ac2e99ca7cd25f88..46f50d9a4d3f957e22459d927a0cdc634dbf03a4 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -95,6 +95,14 @@ class LLFloaterPreference : public LLFloater
 	void setHardwareDefaults();
 	// callback for when client turns on shaders
 	void onVertexShaderEnable();
+	// callback for changing double click action checkbox
+	void onDoubleClickCheckBox(LLUICtrl* ctrl);
+	// callback for selecting double click action radio-button
+	void onDoubleClickRadio();
+	// updates double-click action settings depending on controls from preferences
+	void updateDoubleClickSettings();
+	// updates double-click action controls depending on values from settings.xml
+	void updateDoubleClickControls();
 	
 	// This function squirrels away the current values of the controls so that
 	// cancel() can restore them.	
@@ -145,6 +153,9 @@ class LLFloaterPreference : public LLFloater
 	static void refreshSkin(void* data);
 private:
 	static std::string sSkin;
+	// set true if state of double-click action checkbox or radio-group was changed by user
+	// (reset back to false on apply or cancel)
+	bool mDoubleClickActionDirty;
 	bool mGotPersonalInfo;
 	bool mOriginalIMViaEmail;
 	
diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp
index 159dee7631bfaabb5a4959b8232e42cb9335e022..b3b7645dd4f2f07f6576c809fc0ef10cd413eb59 100644
--- a/indra/newview/llfloaterregiondebugconsole.cpp
+++ b/indra/newview/llfloaterregiondebugconsole.cpp
@@ -37,34 +37,120 @@
 
 #include "llagent.h"
 #include "llhttpclient.h"
+#include "llhttpnode.h"
 #include "lllineeditor.h"
 #include "lltexteditor.h"
 #include "llviewerregion.h"
 
-class Responder : public LLHTTPClient::Responder {
-public:
-    Responder(LLTextEditor *output) : mOutput(output)
-    {
-    }
-
-    /*virtual*/
-    void error(U32 status, const std::string& reason)
-    {
-    }
-
-    /*virtual*/
-    void result(const LLSD& content)
-    {
-		std::string text = content.asString() + "\n\n> ";
-		mOutput->appendText(text, false);
-    };
-
-    LLTextEditor * mOutput;
-};
+// Two versions of the sim console API are supported.
+//
+// SimConsole capability (deprecated):
+// This is the initial implementation that is supported by some versions of the
+// simulator. It is simple and straight forward, just POST a command and the
+// body of the response has the result. This API is deprecated because it
+// doesn't allow the sim to use any asynchronous API.
+//
+// SimConsoleAsync capability:
+// This capability replaces the original SimConsole capability. It is similar
+// in that the command is POSTed to the SimConsoleAsync cap, but the response
+// comes in through the event poll, which gives the simulator more flexibility
+// and allows it to perform complex operations without blocking any frames.
+//
+// We will assume the SimConsoleAsync capability is available, and fall back to
+// the SimConsole cap if it is not. The simulator will only support one or the
+// other.
+
+namespace
+{
+	// Signal used to notify the floater of responses from the asynchronous
+	// API.
+	typedef boost::signals2::signal<
+		void (const std::string& output)> console_reply_signal_t;
+	console_reply_signal_t sConsoleReplySignal;
+
+	const std::string PROMPT("\n\n> ");
+	const std::string UNABLE_TO_SEND_COMMAND(
+		"ERROR: The last command was not received by the server.");
+	const std::string CONSOLE_UNAVAILABLE(
+		"ERROR: No console available for this region/simulator.");
+	const std::string CONSOLE_NOT_SUPPORTED(
+		"This region does not support the simulator console.");
+
+	// This responder handles the initial response. Unless error() is called
+	// we assume that the simulator has received our request. Error will be
+	// called if this request times out.
+	class AsyncConsoleResponder : public LLHTTPClient::Responder
+	{
+	public:
+		/* virtual */
+		void error(U32 status, const std::string& reason)
+		{
+			sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
+		}
+	};
+
+	class ConsoleResponder : public LLHTTPClient::Responder
+	{
+	public:
+		ConsoleResponder(LLTextEditor *output) : mOutput(output)
+		{
+		}
+
+		/*virtual*/
+		void error(U32 status, const std::string& reason)
+		{
+			if (mOutput)
+			{
+				mOutput->appendText(
+					UNABLE_TO_SEND_COMMAND + PROMPT,
+					false);
+			}
+		}
+
+		/*virtual*/
+		void result(const LLSD& content)
+		{
+			if (mOutput)
+			{
+				mOutput->appendText(
+					content.asString() + PROMPT, false);
+			}
+		}
+
+		LLTextEditor * mOutput;
+	};
+
+	// This handles responses for console commands sent via the asynchronous
+	// API.
+	class ConsoleResponseNode : public LLHTTPNode
+	{
+	public:
+		/* virtual */
+		void post(
+			LLHTTPNode::ResponsePtr reponse,
+			const LLSD& context,
+			const LLSD& input) const
+		{
+			llinfos << "Received response from the debug console: "
+				<< input << llendl;
+			sConsoleReplySignal(input["body"].asString());
+		}
+	};
+}
 
 LLFloaterRegionDebugConsole::LLFloaterRegionDebugConsole(LLSD const & key)
 : LLFloater(key), mOutput(NULL)
 {
+	mReplySignalConnection = sConsoleReplySignal.connect(
+		boost::bind(
+			&LLFloaterRegionDebugConsole::onReplyReceived,
+			this,
+			_1));
+}
+
+LLFloaterRegionDebugConsole::~LLFloaterRegionDebugConsole()
+{
+	mReplySignalConnection.disconnect();
 }
 
 BOOL LLFloaterRegionDebugConsole::postBuild()
@@ -77,17 +163,21 @@ BOOL LLFloaterRegionDebugConsole::postBuild()
 
 	mOutput = getChild<LLTextEditor>("region_debug_console_output");
 
-	std::string url = gAgent.getRegion()->getCapability("SimConsole");
-	if ( url.size() == 0 )
+	std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
+	if (url.empty())
 	{
-		mOutput->appendText("This region does not support the simulator console.\n\n> ", false);
+		// Fall back to see if the old API is supported.
+		url = gAgent.getRegion()->getCapability("SimConsole");
+		if (url.empty())
+		{
+			mOutput->appendText(
+				CONSOLE_NOT_SUPPORTED + PROMPT,
+				false);
+			return TRUE;
+		}
 	}
-	else
-	{
-		mOutput->appendText("> ", false);
-	}
-	
 
+	mOutput->appendText("> ", false);
 	return TRUE;
 }
 
@@ -96,20 +186,42 @@ void LLFloaterRegionDebugConsole::onInput(LLUICtrl* ctrl, const LLSD& param)
 	LLLineEditor* input = static_cast<LLLineEditor*>(ctrl);
 	std::string text = input->getText() + "\n";
 
-
-    std::string url = gAgent.getRegion()->getCapability("SimConsole");
-
-	if ( url.size() > 0 )
+	std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
+	if (url.empty())
 	{
-		LLHTTPClient::post(url, LLSD(input->getText()), new ::Responder(mOutput));
+		// Fall back to the old API
+		url = gAgent.getRegion()->getCapability("SimConsole");
+		if (url.empty())
+		{
+			text += CONSOLE_UNAVAILABLE + PROMPT;
+		}
+		else
+		{
+			// Using SimConsole (deprecated)
+			LLHTTPClient::post(
+				url,
+				LLSD(input->getText()),
+				new ConsoleResponder(mOutput));
+		}
 	}
 	else
 	{
-		text += "\nError: No console available for this region/simulator.\n\n> ";
+		// Using SimConsoleAsync
+		LLHTTPClient::post(
+			url,
+			LLSD(input->getText()),
+			new AsyncConsoleResponder);
 	}
 
 	mOutput->appendText(text, false);
-
 	input->clear();
 }
 
+void LLFloaterRegionDebugConsole::onReplyReceived(const std::string& output)
+{
+	mOutput->appendText(output + PROMPT, false);
+}
+
+LLHTTPRegistration<ConsoleResponseNode>
+	gHTTPRegistrationMessageDebugConsoleResponse(
+		"/message/SimConsoleResponse");
diff --git a/indra/newview/llfloaterregiondebugconsole.h b/indra/newview/llfloaterregiondebugconsole.h
index 69d7773fecb9b0e3f7930d2c8d1c2c0957ac4a5e..4171a4da6baf293c0475c410b7bd65f6288f2d13 100644
--- a/indra/newview/llfloaterregiondebugconsole.h
+++ b/indra/newview/llfloaterregiondebugconsole.h
@@ -34,6 +34,8 @@
 #ifndef LL_LLFLOATERREGIONDEBUGCONSOLE_H
 #define LL_LLFLOATERREGIONDEBUGCONSOLE_H
 
+#include <boost/signals2.hpp>
+
 #include "llfloater.h"
 #include "llhttpclient.h"
 
@@ -43,6 +45,7 @@ class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Respo
 {
 public:
 	LLFloaterRegionDebugConsole(LLSD const & key);
+	virtual ~LLFloaterRegionDebugConsole();
 
 	// virtual
 	BOOL postBuild();
@@ -50,6 +53,11 @@ class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Respo
 	void onInput(LLUICtrl* ctrl, const LLSD& param);
 
 	LLTextEditor * mOutput;
+
+ private:
+	void onReplyReceived(const std::string& output);
+
+	boost::signals2::connection mReplySignalConnection;
 };
 
 #endif // LL_LLFLOATERREGIONDEBUGCONSOLE_H
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
index fc758569e4b5fcf6d0ba005dfe2c97bb62db13a8..c099a3964b9b2c1cd24d384f2037576be0c84108 100644
--- a/indra/newview/llhudnametag.cpp
+++ b/indra/newview/llhudnametag.cpp
@@ -87,7 +87,6 @@ LLHUDNameTag::LLHUDNameTag(const U8 type)
 	mZCompare(TRUE),
 	mVisibleOffScreen(FALSE),
 	mOffscreen(FALSE),
-	mColor(1.f, 1.f, 1.f, 1.f),
 //	mScale(),
 	mWidth(0.f),
 	mHeight(0.f),
@@ -109,6 +108,8 @@ LLHUDNameTag::LLHUDNameTag(const U8 type)
 {
 	LLPointer<LLHUDNameTag> ptr(this);
 	sTextObjects.insert(ptr);
+
+	mColor = LLUIColorTable::instance().getColor("BackgroundChatColor");
 }
 
 LLHUDNameTag::~LLHUDNameTag()
@@ -256,6 +257,7 @@ void LLHUDNameTag::renderText(BOOL for_select)
 	
 	LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f);
 	F32 alpha_factor = 1.f;
+	mColor = LLUIColorTable::instance().getColor("BackgroundChatColor");
 	LLColor4 text_color = mColor;
 	if (mDoFade)
 	{
@@ -521,7 +523,6 @@ void LLHUDNameTag::renderText(BOOL for_select)
 				x_offset += 1;
 			}
 
-			text_color = segment_iter->mColor;
 			text_color.mV[VALPHA] *= alpha_factor;
 
 			hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, FALSE);
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index e000abda2a3a6e73ccb2847687549816db097801..bdc0dfa7e2f6f4bc57b30ba2f9e1d04980ae8257 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -680,8 +680,6 @@ void LLIMFloater::updateMessages()
 
 	if (messages.size())
 	{
-//		LLUIColor chat_color = LLUIColorTable::instance().getColor("IMChatColor");
-
 		LLSD chat_args;
 		chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
 
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index cc482260528106e590014b91e12704e9b6150e3d..3578c986224b1713f1f9ac33ae8abbd756d29850 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -537,7 +537,15 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
 
 void LLIMModel::LLIMSession::onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name)
 {
-	mHistoryFileName = av_name.mUsername;
+	if (av_name.mUsername.empty())
+	{
+		// display names is off, use mDisplayName which will be the legacy name
+		mHistoryFileName = LLCacheName::buildUsername(av_name.mDisplayName);
+	}
+	else
+	{  
+		mHistoryFileName = av_name.mUsername;
+	}
 }
 
 void LLIMModel::LLIMSession::buildHistoryFileName()
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 029e700c4ccd7678ad8a1df48b9393ccf48cd0da..83a8134580437064a1294d264c23a8c30abbc6b4 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -42,6 +42,7 @@
 // newview
 #include "llviewernetwork.h"
 #include "llviewercontrol.h"
+#include "llversioninfo.h"
 #include "llslurl.h"
 #include "llstartup.h"
 #include "llfloaterreg.h"
@@ -149,6 +150,7 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 	requested_options.append("newuser-config");
 	requested_options.append("ui-config");
 #endif
+	requested_options.append("max-agent-groups");	
 	requested_options.append("map-server-url");	
 	requested_options.append("voice-config");
 	requested_options.append("tutorial_setting");
@@ -181,8 +183,8 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
 	request_params["read_critical"] = false; // handleTOSResponse
 	request_params["last_exec_event"] = mLastExecEvent;
 	request_params["mac"] = hashed_unique_id_string;
-	request_params["version"] = gCurrentVersion; // Includes channel name
-	request_params["channel"] = gSavedSettings.getString("VersionChannelName");
+	request_params["version"] = LLVersionInfo::getVersionAndChannel(); // Includes channel name
+	request_params["channel"] = LLVersionInfo::getChannel();
 	request_params["id0"] = mSerialNumber;
 
 	mRequestData.clear();
diff --git a/indra/newview/llmainlooprepeater.cpp b/indra/newview/llmainlooprepeater.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5c020e6d982eb7060b857a800f36b4d050f87f25
--- /dev/null
+++ b/indra/newview/llmainlooprepeater.cpp
@@ -0,0 +1,88 @@
+/** 
+ * @file llmachineid.cpp
+ * @brief retrieves unique machine ids
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llapr.h"
+#include "llevents.h"
+#include "llmainlooprepeater.h"
+
+
+
+// LLMainLoopRepeater
+//-----------------------------------------------------------------------------
+
+
+LLMainLoopRepeater::LLMainLoopRepeater(void):
+	mQueue(0)
+{
+	; // No op.
+}
+
+
+void LLMainLoopRepeater::start(void)
+{
+	if(mQueue != 0) return;
+
+	mQueue = new LLThreadSafeQueue<LLSD>(gAPRPoolp, 1024);
+	mMainLoopConnection = LLEventPumps::instance().
+		obtain("mainloop").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMainLoop, this, _1));
+	mRepeaterConnection = LLEventPumps::instance().
+		obtain("mainlooprepeater").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMessage, this, _1));
+}
+
+
+void LLMainLoopRepeater::stop(void)
+{
+	mMainLoopConnection.release();
+	mRepeaterConnection.release();
+
+	delete mQueue;
+	mQueue = 0;
+}
+
+
+bool LLMainLoopRepeater::onMainLoop(LLSD const &)
+{
+	LLSD message;
+	while(mQueue->tryPopBack(message)) {
+		std::string pump = message["pump"].asString();
+		if(pump.length() == 0 ) continue; // No pump.
+		LLEventPumps::instance().obtain(pump).post(message["payload"]);
+	}
+	return false;
+}
+
+
+bool LLMainLoopRepeater::onMessage(LLSD const & event)
+{
+	try {
+		mQueue->pushFront(event);
+	} catch(LLThreadSafeQueueError & e) {
+		llwarns << "could not repeat message (" << e.what() << ")" << 
+			event.asString() << LL_ENDL;
+	}
+	return false;
+}
diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h
new file mode 100644
index 0000000000000000000000000000000000000000..f84c0ca94c2d1b4c812533d655e689a357c275a8
--- /dev/null
+++ b/indra/newview/llmainlooprepeater.h
@@ -0,0 +1,65 @@
+/** 
+ * @file llmainlooprepeater.h
+ * @brief a service for repeating messages on the main loop.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMAINLOOPREPEATER_H
+#define LL_LLMAINLOOPREPEATER_H
+
+
+#include "llsd.h"
+#include "llthreadsafequeue.h"
+
+
+//
+// A service which creates the pump 'mainlooprepeater' to which any thread can
+// post a message that will be re-posted on the main loop.
+//
+// The posted message should contain two map elements: pump and payload.  The
+// pump value is a string naming the pump to which the message should be
+// re-posted.  The payload value is what will be posted to the designated pump.
+//
+class LLMainLoopRepeater:
+	public LLSingleton<LLMainLoopRepeater>
+{
+public:
+	LLMainLoopRepeater(void);
+	
+	// Start the repeater service.
+	void start(void);
+	
+	// Stop the repeater service.
+	void stop(void);
+	
+private:
+	LLTempBoundListener mMainLoopConnection;
+	LLTempBoundListener mRepeaterConnection;
+	LLThreadSafeQueue<LLSD> * mQueue;
+	
+	bool onMainLoop(LLSD const &);
+	bool onMessage(LLSD const & event);
+};
+
+
+#endif
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 6658e1d7e89b6eefeae012e711ad50ed616a4b6d..d38bb5aa4a45a240d006d7cb6c4229c16649a5aa 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -552,7 +552,7 @@ LLPanelStandStopFlying::LLPanelStandStopFlying() :
 }
 
 // static
-inline LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
+LLPanelStandStopFlying* LLPanelStandStopFlying::getInstance()
 {
 	static LLPanelStandStopFlying* panel = getStandStopFlyingPanel();
 	return panel;
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 467aefc60f44edae403d945663775025d1aa2e69..cf567fb208f89d97899cbc195fb4ef9d10b2c285 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -230,7 +230,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 
 	getChild<LLPanel>("login")->setDefaultBtn("connect_btn");
 
-	std::string channel = gSavedSettings.getString("VersionChannelName");
+	std::string channel = LLVersionInfo::getChannel();
 	std::string version = llformat("%s (%d)",
 								   LLVersionInfo::getShortVersion().c_str(),
 								   LLVersionInfo::getBuild());
@@ -817,7 +817,7 @@ void LLPanelLogin::loadLoginPage()
 								   LLVersionInfo::getShortVersion().c_str(),
 								   LLVersionInfo::getBuild());
 
-	char* curl_channel = curl_escape(gSavedSettings.getString("VersionChannelName").c_str(), 0);
+	char* curl_channel = curl_escape(LLVersionInfo::getChannel().c_str(), 0);
 	char* curl_version = curl_escape(version.c_str(), 0);
 
 	oStr << "&channel=" << curl_channel;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 904e3dabcc6adc4f5d59efb8c48f356e813cbd92..17433a557b91d805bf4bd601c67b5dfef2b13ce0 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -329,15 +329,23 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
 	if (sort_field == "name")
 	{
 		U32 order = getActivePanel()->getSortOrder();
-		getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
-			
+		order &= ~LLInventoryFilter::SO_DATE;
+
+		getActivePanel()->setSortOrder( order );
+
+		gSavedSettings.setU32("InventorySortOrder", order);
+
 		gSavedSettings.setBOOL("Inventory.SortByName", TRUE );
 		gSavedSettings.setBOOL("Inventory.SortByDate", FALSE );
 	}
 	else if (sort_field == "date")
 	{
 		U32 order = getActivePanel()->getSortOrder();
-		getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE );
+		order |= LLInventoryFilter::SO_DATE;
+
+		getActivePanel()->setSortOrder( order );
+
+		gSavedSettings.setU32("InventorySortOrder", order);
 
 		gSavedSettings.setBOOL("Inventory.SortByName", FALSE );
 		gSavedSettings.setBOOL("Inventory.SortByDate", TRUE );
@@ -375,6 +383,8 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
 			gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE );
 		}
 		getActivePanel()->setSortOrder( order );
+
+		gSavedSettings.setU32("InventorySortOrder", order);
 	}
 }
 
@@ -915,6 +925,7 @@ void LLPanelMainInventory::initListCommandsHandlers()
 			));
 
 	mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
+	mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
 	mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
 	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mGearMenuButton->setMenu(mMenuGearDefault);
@@ -1000,6 +1011,11 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 		const LLSD arg = "date";
 		setSortBy(arg);
 	}
+	if (command_name == "sort_system_folders_to_top")
+	{
+		const LLSD arg = "systemfolderstotop";
+		setSortBy(arg);
+	}
 	if (command_name == "show_filters")
 	{
 		toggleFindOptions();
@@ -1173,6 +1189,31 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
 	return TRUE;
 }
 
+BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
+{
+	const std::string command_name = userdata.asString();
+
+	if (command_name == "sort_by_name")
+	{
+		U32 order = getActivePanel()->getSortOrder();
+		return ~order & LLInventoryFilter::SO_DATE;
+	}
+
+	if (command_name == "sort_by_recent")
+	{
+		U32 order = getActivePanel()->getSortOrder();
+		return order & LLInventoryFilter::SO_DATE;
+	}
+
+	if (command_name == "sort_system_folders_to_top")
+	{
+		U32 order = getActivePanel()->getSortOrder();
+		return order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+	}
+
+	return FALSE;
+}
+
 bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
 {
 	*accept = ACCEPT_NO;
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index d136e2d32ea686cf7242df0732920ba33f65a1c7..c2b78ff9ea0370e26a9fc9b5ddc13b6efdb317b7 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -136,6 +136,7 @@ class LLPanelMainInventory : public LLPanel, LLInventoryObserver
 	void onTrashButtonClick();
 	void onClipboardAction(const LLSD& userdata);
 	BOOL isActionEnabled(const LLSD& command_name);
+	BOOL isActionChecked(const LLSD& userdata);
 	void onCustomAction(const LLSD& command_name);
 	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
 	/**
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 2334f0cde5544ad7592c73acaab1bd6f56974cd3..170e23e4c5d98c1583162c8ee3466e942970defa 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -32,11 +32,13 @@
 #include "llchannelmanager.h"
 #include "llchiclet.h"
 #include "llfloaterreg.h"
+#include "lllslconstants.h"
 #include "llnotifications.h"
 #include "llnotificationsutil.h"
 #include "llscreenchannel.h"
 #include "llsyswellwindow.h"
 #include "lltoastnotifypanel.h"
+#include "lltoastscripttextbox.h"
 #include "lltrans.h"
 #include "llviewerwindow.h"
 #include "llimfloater.h"
@@ -151,10 +153,18 @@ void LLScriptFloater::createForm(const LLUUID& notification_id)
 
 	// create new form
 	LLRect toast_rect = getRect();
-	// LLToastNotifyPanel will fit own content in vertical direction,
-	// but it needs an initial rect to properly calculate  its width
- 	// Use an initial rect of the script floater to make the floater window more configurable.
-	mScriptForm = new LLToastNotifyPanel(notification, toast_rect); 
+	if (isScriptTextbox(notification))
+	{
+		mScriptForm = new LLToastScriptTextbox(notification);
+	}
+	else
+	{
+		// LLToastNotifyPanel will fit own content in vertical direction,
+		// but it needs an initial rect to properly calculate  its width
+		// Use an initial rect of the script floater to make the floater
+		// window more configurable.
+		mScriptForm = new LLToastNotifyPanel(notification, toast_rect); 
+	}
 	addChild(mScriptForm);
 
 	// position form on floater
@@ -564,4 +574,32 @@ void LLScriptFloaterManager::setFloaterVisible(const LLUUID& notification_id, bo
 	}
 }
 
+//////////////////////////////////////////////////////////////////
+
+bool LLScriptFloater::isScriptTextbox(LLNotificationPtr notification)
+{
+	// get a form for the notification
+	LLNotificationFormPtr form(notification->getForm());
+
+	if (form)
+	{
+		// get number of elements in the form
+		int num_options = form->getNumElements();
+	
+		// if ANY of the buttons have the magic lltextbox string as
+		// name, then treat the whole dialog as a simple text entry
+		// box (i.e. mixed button and textbox forms are not supported)
+		for (int i=0; i<num_options; ++i)
+		{
+			LLSD form_element = form->getElement(i);
+			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN)
+			{
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
 // EOF
diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h
index da70bb4334680598c648fc7ddfb2d07eb94ad1c9..dc52baa11528a0c4d7b8ad6dd11e5c4fc5c766b2 100644
--- a/indra/newview/llscriptfloater.h
+++ b/indra/newview/llscriptfloater.h
@@ -28,6 +28,7 @@
 #define LL_SCRIPTFLOATER_H
 
 #include "lltransientdockablefloater.h"
+#include "llnotificationptr.h"
 
 class LLToastNotifyPanel;
 
@@ -203,6 +204,8 @@ class LLScriptFloater : public LLDockableFloater
 	void dockToChiclet(bool dock);
 
 private:
+	bool isScriptTextbox(LLNotificationPtr notification);
+
 	LLToastNotifyPanel* mScriptForm;
 	LLUUID mNotificationId;
 	LLUUID mObjectId;
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index 3dce66f394d49fef75b17a0e77188d710c656052..c76ecae4a2b513d613ae616999d6f489269a9ddc 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -134,8 +134,11 @@ LLSpeakButton::LLSpeakButton(const Params& p)
 
 LLSpeakButton::~LLSpeakButton()
 {
-	LLTransientFloaterMgr::getInstance()->removeControlView(mSpeakBtn);
-	LLTransientFloaterMgr::getInstance()->removeControlView(mShowBtn);
+	if(LLTransientFloaterMgr::instanceExists())
+	{
+		LLTransientFloaterMgr::getInstance()->removeControlView(mSpeakBtn);
+		LLTransientFloaterMgr::getInstance()->removeControlView(mShowBtn);
+	}
 }
 
 void LLSpeakButton::setSpeakToolTip(const std::string& msg)
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index ede1d6bebee7c02795af170fd95b01dffd54f34c..9b38bf22ffe03ec7cea5ca373633c7f807ecb5f2 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -308,7 +308,10 @@ void LLSpeakingIndicatorManager::registerSpeakingIndicator(const LLUUID& speaker
 
 void LLSpeakingIndicatorManager::unregisterSpeakingIndicator(const LLUUID& speaker_id, const LLSpeakingIndicator* const speaking_indicator)
 {
-	SpeakingIndicatorManager::instance().unregisterSpeakingIndicator(speaker_id, speaking_indicator);
+	if(SpeakingIndicatorManager::instanceExists())
+	{
+		SpeakingIndicatorManager::instance().unregisterSpeakingIndicator(speaker_id, speaking_indicator);
+	}
 }
 
 // EOF
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 5ee45992000daf7eed4d0bf97e2668f1a2b8f6ce..80cf7e3cd022533e0e3111c2febda2b976acaf2a 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -198,6 +198,7 @@
 // exported globals
 //
 bool gAgentMovementCompleted = false;
+S32  gMaxAgentGroups;
 
 std::string SCREEN_HOME_FILENAME = "screen_home.bmp";
 std::string SCREEN_LAST_FILENAME = "screen_last.bmp";
@@ -3151,6 +3152,18 @@ bool process_login_success_response()
 		LLViewerMedia::openIDSetup(openid_url, openid_token);
 	}
 
+	if(response.has("max-agent-groups")) {		
+		std::string max_agent_groups(response["max-agent-groups"]);
+		gMaxAgentGroups = atoi(max_agent_groups.c_str());
+		LL_INFOS("LLStartup") << "gMaxAgentGroups read from login.cgi: "
+							  << gMaxAgentGroups << LL_ENDL;
+	}
+	else {
+		gMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS;
+		LL_INFOS("LLStartup") << "using gMaxAgentGroups default: "
+							  << gMaxAgentGroups << LL_ENDL;
+	}
+		
 	bool success = false;
 	// JC: gesture loading done below, when we have an asset system
 	// in place.  Don't delete/clear gUserCredentials until then.
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index be1043cf910a05c8f1f22f7b97d1e3d9b2d7e385..b3d9ef1dcc7805b9a3003ba87fe70c42d3f51c2f 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -70,6 +70,7 @@ typedef enum {
 
 // exported symbols
 extern bool gAgentMovementCompleted;
+extern S32  gMaxAgentGroups;
 extern LLPointer<LLViewerTexture> gStartTexture;
 
 class LLStartUp
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index 371aad64bbd3950e2ce4095769380750c63feccf..563c27c4d739ddbf535a2f01bc2ced256e778a01 100644
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -60,7 +60,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
 	LLGroupData groupData;
 	if (!gAgent.getGroupData(payload["group_id"].asUUID(),groupData))
 	{
-		llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl;
+		llwarns << "Group notice for unknown group: " << payload["group_id"].asUUID() << llendl;
 	}
 
 	//group icon
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 9017f5ec5574e175e0f07295a15ae28695fd2bfc..3f7dc24ade072686fe286c42806b2e9f4501a63b 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -33,6 +33,7 @@
 
 // library includes
 #include "lldbstrings.h"
+#include "lllslconstants.h"
 #include "llnotifications.h"
 #include "lluiconstants.h"
 #include "llrect.h"
@@ -70,11 +71,11 @@ mCloseNotificationOnDestroy(true)
 	mControlPanel = getChild<LLPanel>("control_panel");
 	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth");
 	// customize panel's attributes
-	// is it intended for displaying a tip
+	// is it intended for displaying a tip?
 	mIsTip = notification->getType() == "notifytip";
-	// is it a script dialog
+	// is it a script dialog?
 	mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup");
-	// is it a caution
+	// is it a caution?
 	//
 	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
 	// notify xml template specifies that it is a caution
@@ -139,6 +140,12 @@ mCloseNotificationOnDestroy(true)
 			LLSD form_element = form->getElement(i);
 			if (form_element["type"].asString() != "button")
 			{
+				// not a button.
+				continue;
+			}
+			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN)
+			{
+				// a textbox pretending to be a button.
 				continue;
 			}
 			LLButton* new_button = createButton(form_element, TRUE);
@@ -159,7 +166,7 @@ mCloseNotificationOnDestroy(true)
 			if(h_pad < 2*HPAD)
 			{
 				/*
-				 * Probably it is  a scriptdialog toast
+				 * Probably it is a scriptdialog toast
 				 * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons.
 				 * In last case set default h_pad to avoid heaping of buttons 
 				 */
@@ -261,7 +268,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
 	}
 	else if (mIsScriptDialog && is_ignore_btn)
 	{
-		// this is ignore button,make it smaller
+		// this is ignore button, make it smaller
 		p.rect.height = BTN_HEIGHT_SMALL;
 		p.rect.width = 1;
 		p.auto_resize = true;
diff --git a/indra/newview/lltoastscripttextbox.cpp b/indra/newview/lltoastscripttextbox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c013f521cc46289ee5d76bdb665a278f049b5fd1
--- /dev/null
+++ b/indra/newview/lltoastscripttextbox.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file lltoastscripttextbox.cpp
+ * @brief Panel for script llTextBox dialogs
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltoastscripttextbox.h"
+
+#include "llfocusmgr.h"
+
+#include "llbutton.h"
+#include "llnotifications.h"
+#include "llviewertexteditor.h"
+
+#include "llavatarnamecache.h"
+#include "lluiconstants.h"
+#include "llui.h"
+#include "llviewercontrol.h"
+#include "lltrans.h"
+#include "llstyle.h"
+
+#include "llglheaders.h"
+#include "llagent.h"
+
+const S32 LLToastScriptTextbox::DEFAULT_MESSAGE_MAX_LINE_COUNT= 7;
+
+LLToastScriptTextbox::LLToastScriptTextbox(LLNotificationPtr& notification)
+:	LLToastNotifyPanel(notification)
+{
+	buildFromFile( "panel_notify_textbox.xml");
+
+	const LLSD& payload = notification->getPayload();
+
+	//message body
+	const std::string& message = payload["message"].asString();
+
+	LLViewerTextEditor* pMessageText = getChild<LLViewerTextEditor>("message");
+	pMessageText->clear();
+
+	LLStyle::Params style;
+	style.font = pMessageText->getDefaultFont();
+	pMessageText->appendText(message, TRUE, style);
+
+	//submit button
+	LLButton* pSubmitBtn = getChild<LLButton>("btn_submit");
+	pSubmitBtn->setClickedCallback((boost::bind(&LLToastScriptTextbox::onClickSubmit, this)));
+	setDefaultBtn(pSubmitBtn);
+
+	S32 maxLinesCount;
+	std::istringstream ss( getString("message_max_lines_count") );
+	if (!(ss >> maxLinesCount))
+	{
+		maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
+	}
+	//snapToMessageHeight(pMessageText, maxLinesCount);
+}
+
+// virtual
+LLToastScriptTextbox::~LLToastScriptTextbox()
+{
+}
+
+void LLToastScriptTextbox::close()
+{
+	die();
+}
+
+#include "lllslconstants.h"
+void LLToastScriptTextbox::onClickSubmit()
+{
+	LLViewerTextEditor* pMessageText = getChild<LLViewerTextEditor>("message");
+
+	if (pMessageText)
+	{
+		LLSD response = mNotification->getResponseTemplate();
+		response[TEXTBOX_MAGIC_TOKEN] = pMessageText->getText();
+		if (response[TEXTBOX_MAGIC_TOKEN].asString().empty())
+		{
+			// so we can distinguish between a successfully
+			// submitted blank textbox, and an ignored toast
+			response[TEXTBOX_MAGIC_TOKEN] = true;
+		}
+		mNotification->respond(response);
+		close();
+		llwarns << response << llendl;
+	}
+}
diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h
new file mode 100644
index 0000000000000000000000000000000000000000..ae3b545e0a8b3e4ff7bb5e8b4117b02c6996044d
--- /dev/null
+++ b/indra/newview/lltoastscripttextbox.h
@@ -0,0 +1,58 @@
+/**
+ * @file lltoastscripttextbox.h
+ * @brief Panel for script llTextBox dialogs
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTOASTSCRIPTTEXTBOX_H
+#define LL_LLTOASTSCRIPTTEXTBOX_H
+
+#include "lltoastnotifypanel.h"
+#include "llnotificationptr.h"
+
+class LLButton;
+
+/**
+ * Toast panel for scripted llTextbox notifications.
+ */
+class LLToastScriptTextbox
+:	public LLToastNotifyPanel
+{
+public:
+	void close();
+
+	static bool onNewNotification(const LLSD& notification);
+
+	// Non-transient messages.  You can specify non-default button
+	// layouts (like one for script dialogs) by passing various
+	// numbers in for "layout".
+	LLToastScriptTextbox(LLNotificationPtr& notification);
+
+	/*virtual*/ ~LLToastScriptTextbox();
+protected:
+	void onClickSubmit();
+private:
+	static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
+};
+
+#endif
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
index 78dd602f39bbde39b9bdd3f514882fedde3d20fe..6deab96b454602c1a0dccb6431c7c6f91a5f96ad 100644
--- a/indra/newview/lltransientfloatermgr.cpp
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -36,8 +36,11 @@
 
 LLTransientFloaterMgr::LLTransientFloaterMgr()
 {
-	gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
+	if(gViewerWindow)
+	{
+		gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
 			&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+	}
 
 	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>()));
 	mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(DOCKED, std::set<LLView*>()));
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 050e34ade9ab137afb56fc864a8e437591998e7c..8ccfdb071b663a0c5d73955c0c3dafef5f13976b 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -36,7 +36,7 @@
 
 #include "llbufferstream.h"
 #include "llui.h"
-#include "llversionviewer.h"
+#include "llversioninfo.h"
 #include "llviewercontrol.h"
 
 #include "jsoncpp/reader.h"
@@ -64,11 +64,11 @@ void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std
 	getTranslateUrl(url, from_lang, to_lang, mesg);
 
     std::string user_agent = llformat("%s %d.%d.%d (%d)",
-		LL_CHANNEL,
-		LL_VERSION_MAJOR,
-		LL_VERSION_MINOR,
-		LL_VERSION_PATCH,
-		LL_VERSION_BUILD );
+		LLVersionInfo::getChannel().c_str(),
+		LLVersionInfo::getMajor(),
+		LLVersionInfo::getMinor(),
+		LLVersionInfo::getPatch(),
+		LLVersionInfo::getBuild());
 
 	if (!m_Header.size())
 	{
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
index 733d05834a13d89d34462cbc2c3c3023a78f8481..53994c68f2ca86b90877a4bf687b69d99572f322 100644
--- a/indra/newview/llversioninfo.cpp
+++ b/indra/newview/llversioninfo.cpp
@@ -95,9 +95,42 @@ const std::string &LLVersionInfo::getShortVersion()
 	return version;
 }
 
+namespace
+{
+	/// Storage of the channel name the viewer is using.
+	//  The channel name is set by hardcoded constant, 
+	//  or by calling LLVersionInfo::resetChannel()
+	std::string sWorkingChannelName(LL_CHANNEL);
+
+	// Storage for the "version and channel" string.
+	// This will get reset too.
+	std::string sVersionChannel("");
+}
+
+//static
+const std::string &LLVersionInfo::getVersionAndChannel()
+{
+	if (sVersionChannel.empty())
+	{
+		// cache the version string
+		std::ostringstream stream;
+		stream << LLVersionInfo::getVersion() 
+			   << " "
+			   << LLVersionInfo::getChannel();
+		sVersionChannel = stream.str();
+	}
+
+	return sVersionChannel;
+}
+
 //static
 const std::string &LLVersionInfo::getChannel()
 {
-	static std::string name(LL_CHANNEL);
-	return name;
+	return sWorkingChannelName;
+}
+
+void LLVersionInfo::resetChannel(const std::string& channel)
+{
+	sWorkingChannelName = channel;
+	sVersionChannel.clear(); // Reset version and channel string til next use.
 }
diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h
index e468b6ae4ec9707068adff45176018af16edfc12..36defbcd68f467e4257ef059f0e04137971111ac 100644
--- a/indra/newview/llversioninfo.h
+++ b/indra/newview/llversioninfo.h
@@ -58,8 +58,15 @@ class LLVersionInfo
 	/// return the viewer version as a string like "2.0.0"
 	static const std::string &getShortVersion();
 
+	/// return the viewer version and channel as a string
+	/// like "2.0.0.200030 Second Life Release"
+	static const std::string &getVersionAndChannel();
+
 	/// return the channel name, e.g. "Second Life"
 	static const std::string &getChannel();
+	
+	/// reset the channel name used by the viewer.
+	static void resetChannel(const std::string& channel);
 };
 
 #endif
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index fbec2a7b9e6e36571bd3b21bee612a20db82a5e8..622d09c60015b0639258bf9a96b05de66c173668 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -70,6 +70,7 @@
 #include "llpaneloutfitsinventory.h"
 #include "llpanellogin.h"
 #include "llpaneltopinfobar.h"
+#include "llupdaterservice.h"
 
 #ifdef TOGGLE_HACKED_GODLIKE_VIEWER
 BOOL 				gHackGodmode = FALSE;
@@ -82,7 +83,6 @@ LLControlGroup gCrashSettings("CrashSettings");	// saved at end of session
 LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warnings
 
 std::string gLastRunVersion;
-std::string gCurrentVersion;
 
 extern BOOL gResizeScreenTexture;
 extern BOOL gDebugGL;
@@ -117,10 +117,23 @@ static bool handleSetShaderChanged(const LLSD& newvalue)
 	gBumpImageList.destroyGL();
 	gBumpImageList.restoreGL();
 
+	// Changing shader also changes the terrain detail to high, reflect that change here
+	if (newvalue.asBoolean())
+	{
+		// shaders enabled, set terrain detail to high
+		gSavedSettings.setS32("RenderTerrainDetail", 1);
+	}
+	// else, leave terrain detail as is
 	LLViewerShaderMgr::instance()->setShaders();
 	return true;
 }
 
+bool handleRenderTransparentWaterChanged(const LLSD& newvalue)
+{
+	LLWorld::getInstance()->updateWaterObjects();
+	return true;
+}
+
 static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
 {
 	if (gPipeline.isInit())
@@ -489,6 +502,18 @@ bool toggle_show_object_render_cost(const LLSD& newvalue)
 	return true;
 }
 
+void toggle_updater_service_active(LLControlVariable* control, const LLSD& new_value)
+{
+    if(new_value.asBoolean())
+    {
+        LLUpdaterService().startChecking();
+    }
+    else
+    {
+        LLUpdaterService().stopChecking();
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////
 
 void settings_setup_listeners()
@@ -636,7 +661,9 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2));
 	gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2));
 	gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2));
+	gSavedSettings.getControl("UpdaterServiceActive")->getSignal()->connect(&toggle_updater_service_active);
 	gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2));
+	gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2));
 }
 
 #if TEST_CACHED_CONTROL
diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h
index 22b48f8906b1ec26ebb2e88bea9ff134b2d767f0..d7191f5c8d5d8703ec7d76b80fdb8ab9a2c49259 100644
--- a/indra/newview/llviewercontrol.h
+++ b/indra/newview/llviewercontrol.h
@@ -57,7 +57,5 @@ extern LLControlGroup gCrashSettings;
 
 // Set after settings loaded
 extern std::string gLastRunVersion;
-extern std::string gCurrentVersion;
-
 
 #endif // LL_LLVIEWERCONTROL_H
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 31cf0acdd761b88225f2c1df53494f05f43f8d73..fae4eb3c056029e2ea5085f299dbb7e8a14a9e1e 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -492,7 +492,7 @@ std::string LLViewerMedia::getCurrentUserAgent()
 
 	// Just in case we need to check browser differences in A/B test
 	// builds.
-	std::string channel = gSavedSettings.getString("VersionChannelName");
+	std::string channel = LLVersionInfo::getChannel();
 
 	// append our magic version number string to the browser user agent id
 	// See the HTTP 1.0 and 1.1 specifications for allowed formats:
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 92a78c155e8a299a21884a0e8afa32319a6e8675..b7432cd1ec7bdab6babffb409270bc69f2944ae9 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6500,16 +6500,6 @@ class LLToggleControl : public view_listener_t
 		std::string control_name = userdata.asString();
 		BOOL checked = gSavedSettings.getBOOL( control_name );
 		gSavedSettings.setBOOL( control_name, !checked );
-
-        // Doubleclick actions - there can be only one
-        if ((control_name == "DoubleClickAutoPilot") && !checked)
-        {
-			gSavedSettings.setBOOL( "DoubleClickTeleport", FALSE );
-        }
-        else if ((control_name == "DoubleClickTeleport") && !checked)
-        {
-			gSavedSettings.setBOOL( "DoubleClickAutoPilot", FALSE );
-        }
 		return true;
 	}
 };
@@ -7805,6 +7795,9 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType");
 	view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments");
 
+	// Me > Movement
+	view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
+	
 	// World menu
 	commit.add("World.Chat", boost::bind(&handle_chat, (void*)NULL));
 	view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
@@ -7878,9 +7871,6 @@ void initialize_menus()
 
 	// Advanced Other Settings	
 	view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache");
-
-	// Advanced > Shortcuts
-	view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying");
 	
 	// Advanced > Render > Types
 	view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 7c0fc681a43f4f03e0abeaa8f58ac5a0b73d2796..5cbd5ffa0b21cde4c51d6f03d2278aee19f6e38a 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -39,6 +39,7 @@
 #include "llfloaterreg.h"
 #include "llfollowcamparams.h"
 #include "llinventorydefines.h"
+#include "lllslconstants.h"
 #include "llregionhandle.h"
 #include "llsdserialize.h"
 #include "llteleportflags.h"
@@ -638,7 +639,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
 	if(option == 0 && !group_id.isNull())
 	{
 		// check for promotion or demotion.
-		S32 max_groups = MAX_AGENT_GROUPS;
+		S32 max_groups = gMaxAgentGroups;
 		if(gAgent.isInGroup(group_id)) ++max_groups;
 
 		if(gAgent.mGroups.count() < max_groups)
@@ -3031,6 +3032,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
 		}
 		else
 		{
+			args["NAME"] = source_name;
 			LLNotificationsUtil::add("OfferCallingCard", args, payload);
 		}
 	}
@@ -6435,8 +6437,22 @@ const char* SCRIPT_DIALOG_HEADER = "Script Dialog:\n";
 bool callback_script_dialog(const LLSD& notification, const LLSD& response)
 {
 	LLNotificationForm form(notification["form"]);
-	std::string button = LLNotification::getSelectedOptionName(response);
-	S32 button_idx = LLNotification::getSelectedOption(notification, response);
+
+	std::string rtn_text;
+	S32 button_idx;
+	button_idx = LLNotification::getSelectedOption(notification, response);
+	if (response[TEXTBOX_MAGIC_TOKEN].isDefined())
+	{
+		if (response[TEXTBOX_MAGIC_TOKEN].isString())
+			rtn_text = response[TEXTBOX_MAGIC_TOKEN].asString();
+		else
+			rtn_text.clear(); // bool marks empty string
+	}
+	else
+	{
+		rtn_text = LLNotification::getSelectedOptionName(response);
+	}
+
 	// Didn't click "Ignore"
 	if (button_idx != -1)
 	{
@@ -6449,7 +6465,7 @@ bool callback_script_dialog(const LLSD& notification, const LLSD& response)
 		msg->addUUID("ObjectID", notification["payload"]["object_id"].asUUID());
 		msg->addS32("ChatChannel", notification["payload"]["chat_channel"].asInteger());
 		msg->addS32("ButtonIndex", button_idx);
-		msg->addString("ButtonLabel", button);
+		msg->addString("ButtonLabel", rtn_text);
 		msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
 	}
 
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index e693fc65ea98cc529253c636328233b7778f583d..c73b5fdd4056925eec7a988a16b8c78f671c3405 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1400,7 +1400,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("SendUserReportWithScreenshot");
 	capabilityNames.append("ServerReleaseNotes");
 	capabilityNames.append("SetDisplayName");
-	capabilityNames.append("SimConsole");
+	capabilityNames.append("SimConsoleAsync");
 	capabilityNames.append("StartGroupProposal");
 	capabilityNames.append("TextureStats");
 	capabilityNames.append("UntrustedSimulatorMessage");
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 46c78e2bb4210c87a55bc605cfd6b9e2b61e467d..402f00c5e73b3d310911f707a3dceb6e53edc79b 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -48,6 +48,7 @@
 #include "llagent.h"
 #include "llagentcamera.h"
 #include "llviewercontrol.h"
+#include "llversioninfo.h"
 #include "llfloatertools.h"
 #include "lldebugview.h"
 #include "llfasttimerview.h"
@@ -749,7 +750,7 @@ void send_stats()
 
 	// send fps only for time app spends in foreground
 	agent["fps"] = (F32)gForegroundFrameCount / gForegroundTime.getElapsedTimeF32();
-	agent["version"] = gCurrentVersion;
+	agent["version"] = LLVersionInfo::getVersionAndChannel();
 	std::string language = LLUI::getLanguage();
 	agent["language"] = language;
 	
diff --git a/indra/newview/llviewerthrottle.cpp b/indra/newview/llviewerthrottle.cpp
index b614ccdbc2762142e644e227e8a1ad2652fc5347..5147272122e6c0d5d4f1b1809302c7675e0916bd 100644
--- a/indra/newview/llviewerthrottle.cpp
+++ b/indra/newview/llviewerthrottle.cpp
@@ -46,7 +46,7 @@ const F32 MAX_FRACTIONAL = 1.5f;
 const F32 MIN_FRACTIONAL = 0.2f;
 
 const F32 MIN_BANDWIDTH = 50.f;
-const F32 MAX_BANDWIDTH = 1500.f;
+const F32 MAX_BANDWIDTH = 3000.f;
 const F32 STEP_FRACTIONAL = 0.1f;
 const F32 TIGHTEN_THROTTLE_THRESHOLD = 3.0f; // packet loss % per s
 const F32 EASE_THROTTLE_THRESHOLD = 0.5f; // packet loss % per s
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 743def4a0ce7d7d5ac12867eb8e9c1288f0f97d1..a7790243ed35a687770461fe8d34acbb569a22e0 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2266,6 +2266,20 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
 		return TRUE;
 	}
 
+	// If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, 
+	// no view has keyboard focus, this is a printable character key (and no modifier key is 
+	// pressed except shift), then give focus to nearby chat (STORM-560)
+	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && 
+		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )
+	{
+		LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
+		if (chat_editor)
+		{
+			// passing NULL here, character will be added later when it is handled by character handler.
+			LLBottomTray::getInstance()->getNearbyChatBar()->startChat(NULL);
+			return TRUE;
+		}
+	}
 
 	// give menus a chance to handle unmodified accelerator keys
 	if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 9280eb8fa48ded86450bab537fc1700b7d93c049..71f08ec36d7dfcee856a86d1919fa9c5f81cecb5 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -60,8 +60,10 @@ const U32 WIDTH			= (N_RES * WAVE_STEP); //128.f //64		// width of wave tile, in
 const F32 WAVE_STEP_INV	= (1. / WAVE_STEP);
 
 
-LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
-:	LLStaticViewerObject(id, pcode, regionp),
+LLVOWater::LLVOWater(const LLUUID &id, 
+					 const LLPCode pcode, 
+					 LLViewerRegion *regionp) :
+	LLStaticViewerObject(id, pcode, regionp),
 	mRenderType(LLPipeline::RENDER_TYPE_WATER)
 {
 	// Terrain must draw during selection passes so it can block objects behind it.
@@ -153,11 +155,17 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable)
 	LLStrider<U16> indicesp;
 	U16 index_offset;
 
-	S32 size = 16;
 
-	S32 num_quads = size*size;	
-	face->setSize(4*num_quads, 6*num_quads);
+	// A quad is 4 vertices and 6 indices (making 2 triangles)
+	static const unsigned int vertices_per_quad = 4;
+	static const unsigned int indices_per_quad = 6;
 
+	const S32 size = gSavedSettings.getBOOL("RenderTransparentWater") ? 16 : 1;
+
+	const S32 num_quads = size * size;
+	face->setSize(vertices_per_quad * num_quads,
+				  indices_per_quad * num_quads);
+	
 	if (face->mVertexBuffer.isNull())
 	{
 		face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index f8660419b407b180ea741bd772b1e378a9a37b73..aeea2306f773d8082e67e852b40cdb3e71750010 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -399,9 +399,6 @@
     <color
      name="HighlightParentColor"
      value="0.67 0.83 0.96 1" />
-    <color
-     name="IMChatColor"
-     reference="LtGray" />
     <color
      name="IMHistoryBgColor"
      reference="Unused?" />
diff --git a/indra/newview/skins/default/xui/da/floater_bumps.xml b/indra/newview/skins/default/xui/da/floater_bumps.xml
index d22de6e7f135ade8784adadcb99a469133e66412..1db2e93fd27c5bd23021d30e8b0eff8e1808e402 100644
--- a/indra/newview/skins/default/xui/da/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/da/floater_bumps.xml
@@ -4,19 +4,19 @@
 		Ingen registreret
 	</floater.string>
 	<floater.string name="bump">
-		[TIME]  [FIRST] [LAST] ramte dig
+		[TIME]  [NAME] ramte dig
 	</floater.string>
 	<floater.string name="llpushobject">
-		[TIME]  [FIRST] [LAST] skubbede dig med et script
+		[TIME]  [NAME] skubbede dig med et script
 	</floater.string>
 	<floater.string name="selected_object_collide">
-		[TIME]  [FIRST] [LAST] ramte dig med et objekt
+		[TIME]  [NAME] ramte dig med et objekt
 	</floater.string>
 	<floater.string name="scripted_object_collide">
-		[TIME]  [FIRST] [LAST] ramte dig med et scriptet objekt
+		[TIME]  [NAME] ramte dig med et scriptet objekt
 	</floater.string>
 	<floater.string name="physical_object_collide">
-		[TIME]  [FIRST] [LAST] ramte dig med et fysisk objekt
+		[TIME]  [NAME] ramte dig med et fysisk objekt
 	</floater.string>
 	<floater.string name="timeStr">
 		[[hour,datetime,slt]:[min,datetime,slt]]
diff --git a/indra/newview/skins/default/xui/da/floater_pay.xml b/indra/newview/skins/default/xui/da/floater_pay.xml
index b2cdc0bfe78164de6ab59c18f142ea717694268f..5ebdd3f084ca30c41aad9d70d5ff8d8524bcd7a7 100644
--- a/indra/newview/skins/default/xui/da/floater_pay.xml
+++ b/indra/newview/skins/default/xui/da/floater_pay.xml
@@ -11,7 +11,7 @@
 	</text>
 	<icon name="icon_person" tool_tip="Person"/>
 	<text name="payee_name">
-		[FIRST] [LAST]
+		Test Name That Is Extremely Long To Check Clipping
 	</text>
 	<button label="L$1" label_selected="L$1" name="fastpay 1"/>
 	<button label="L$5" label_selected="L$5" name="fastpay 5"/>
diff --git a/indra/newview/skins/default/xui/da/floater_pay_object.xml b/indra/newview/skins/default/xui/da/floater_pay_object.xml
index 368d6786818411ff12861504b702748a29ad51bd..260b257c33311c8073cc83f7ceee189465872fa2 100644
--- a/indra/newview/skins/default/xui/da/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/da/floater_pay_object.xml
@@ -8,7 +8,7 @@
 	</string>
 	<icon name="icon_person" tool_tip="Person"/>
 	<text name="payee_name">
-		[FIRST] [LAST]
+		Ericacita Moostopolison
 	</text>
 	<text name="object_name_label">
 		Via objekt:
diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml
index 917b7cc21e34541f94aef41509b512c96312b8f6..a8849861cf6e092c993628df0737447113335550 100644
--- a/indra/newview/skins/default/xui/da/notifications.xml
+++ b/indra/newview/skins/default/xui/da/notifications.xml
@@ -931,10 +931,10 @@ Henvis til dette fra en hjemmeside for at give andre nem adgang til denne lokati
 		Erstattet manglende tøj/kropsdele med standard.
 	</notification>
 	<notification name="FriendOnline">
-		[FIRST] [LAST] er Online
+		[NAME] er Online
 	</notification>
 	<notification name="FriendOffline">
-		[FIRST] [LAST] er Offline
+		[NAME] er Offline
 	</notification>
 	<notification name="AddSelfFriend">
 		Selvom du nok er meget sød, kan du ikke tilføje dig selv som ven.
@@ -1002,9 +1002,6 @@ Prøv venligst igen.
 	<notification name="CannotRemoveProtectedCategories">
 		Du kan ikke fjerne beskyttede kategorier.
 	</notification>
-	<notification name="OfferedCard">
-		Du har tilbudt et visitkort til [FIRST] [LAST]
-	</notification>
 	<notification name="UnableToBuyWhileDownloading">
 		Ikke muligt at købe, imens genstandens data hentes.
 Prøv venligst igen.
@@ -1120,7 +1117,7 @@ Prøv venligst at geninstallere plugin eller kontakt leverandøren hvis probleme
 		De genstande du ejer på det valgte stykke land er blevet returneret til din beholdning.
 	</notification>
 	<notification name="OtherObjectsReturned">
-		Genstandene på det valgte stykke land der er ejet af [FIRST] [LAST] er blevet returneret til hans eller hendes beholdning.
+		Genstandene på det valgte stykke land der er ejet af [NAME] er blevet returneret til hans eller hendes beholdning.
 	</notification>
 	<notification name="OtherObjectsReturned2">
 		Objekterne i den valgte parcel, ejet af beboeren &apos;[NAME]&apos;, er blevet returneret til deres ejer.
@@ -1321,7 +1318,7 @@ Prøv igen om lidt.
 		Tilbud om venskab afvist.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] tilbyder dig et visitkort.
+		[NAME] tilbyder dig et visitkort.
 Dette vil lave et bogmørke i din beholding, så du hurtigt kan sende en IM til denne beboer.
 		<form name="form">
 			<button name="Accept" text="Acceptér"/>
@@ -1380,7 +1377,7 @@ Tillad denne anmodning?
 		</form>
 	</notification>
 	<notification name="ScriptDialog">
-		[FIRST] [LAST]&apos;s &apos;[TITLE]&apos;
+		[NAME]&apos;s &apos;&lt;nolink&gt;[TITLE]&lt;/nolink&gt;&apos;
 [MESSAGE]
 		<form name="form">
 			<button name="Ignore" text="Ignorér"/>
@@ -1424,13 +1421,13 @@ Klik på Acceptér for at deltage eller Afvis for at afvise invitationen. Klik p
 		</form>
 	</notification>
 	<notification name="AutoUnmuteByIM">
-		[FIRST] [LAST] fik tilsendt en personlig besked og er dermed automatisk ikke mere blokeret.
+		[NAME] fik tilsendt en personlig besked og er dermed automatisk ikke mere blokeret.
 	</notification>
 	<notification name="AutoUnmuteByMoney">
-		[FIRST] [LAST] blev givet penge og er dermed automatisk ikke mere blokeret.
+		[NAME] blev givet penge og er dermed automatisk ikke mere blokeret.
 	</notification>
 	<notification name="AutoUnmuteByInventory">
-		[FIRST] [LAST] blev tilbudt en genstand og er dermed automatisk ikke mere blokeret.
+		[NAME] blev tilbudt en genstand og er dermed automatisk ikke mere blokeret.
 	</notification>
 	<notification name="VoiceInviteGroup">
 		[NAME] har has sluttet sig til stemme-chaten i gruppen [GROUP].
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index afd933c7fab406de4f9dd7bf671a1e372513990c..1c583f2e95ec1b441e496051494e83720408712d 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -3469,7 +3469,7 @@ Hvis du bliver ved med at modtage denne besked, kontakt venligst [SUPPORT_SITE].
 		Du er den eneste deltager i denne samtale
 	</string>
 	<string name="offline_message">
-		[FIRST] [LAST] er ikke logget på.
+		[NAME] er ikke logget på.
 	</string>
 	<string name="invite_message">
 		Tryk på [BUTTON NAME] knappen for at acceptére/tilslutte til denne stemme chat.
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index c2ca0c2fb032a1c2d7fca38c81cfafda561f856a..a904604b628c6bd24354298fefc7ca21a793249f 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -2481,7 +2481,7 @@ Versuchen Sie es in einigen Minuten erneut.
 		Ihr Freundschaftsangebot wurde abgelehnt.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] bietet Ihnen ihre/seine Visitenkarte an.
+		[NAME] bietet Ihnen ihre/seine Visitenkarte an.
 Ihrem Inventar wird ein Lesezeichen erstellt, damit Sie diesem Einwohner einfach eine IM schicken können.
 		<form name="form">
 			<button name="Accept" text="Akzeptieren"/>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_profile.xml b/indra/newview/skins/default/xui/de/panel_edit_profile.xml
index 7f6054dd608e3d5d564f34f0dc423f1f46d85b1a..be124050e89dbe79dd5f456611582b434314569f 100644
--- a/indra/newview/skins/default/xui/de/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/de/panel_edit_profile.xml
@@ -54,7 +54,7 @@
 				<text name="my_account_link" value="[[URL] Meine Startseite aufrufen]"/>
 				<text name="title_partner_text" value="Mein Partner:"/>
 				<panel name="partner_data_panel">
-					<text initial_value="(wird in Datenbank gesucht)" name="partner_text" value="[FIRST] [LAST]"/>
+					<text initial_value="(wird in Datenbank gesucht)" name="partner_text"/>
 				</panel>
 				<text name="partner_edit_link" value="[[URL] bearbeiten]"/>
 			</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index f361cb7f8e26639226fa6678826981fdaca3ab45..e70e1eb61b3a05db9c45570b418838b72f10e048 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -160,7 +160,7 @@
      layout="topleft"
      left="10"
       height="70"
-      top="54"
+      top="59"
      name="focus_radio_group">
         <radio_item
          top_pad="6"
@@ -197,7 +197,7 @@
    <radio_group
       left="10"
       height="70"
-      top="54"
+      top="59"
      layout="topleft"
      name="move_radio_group">
         <radio_item
@@ -931,7 +931,7 @@
 			 height="23"
 			 image_overlay="Edit_Wrench"
 			 layout="topleft"
-			 left_pad="3"
+			 left_pad="13"
 			 name="button set group"
 			 tab_stop="false"
 			 tool_tip="Choose a group to share this object's permissions"
@@ -944,7 +944,7 @@
              name="checkbox share with group"
              tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."
              top_pad="10"
-             left="106"
+             left="100"
              width="87" />
             <button
              follows="top|left"
@@ -953,7 +953,7 @@
              label_selected="Deed"
              layout="topleft"
              name="button deed"
-             left_pad="3"
+             left_pad="19"
              tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer."
              width="80" />
             <text
@@ -974,7 +974,7 @@
              layout="topleft"
              name="clickaction"
              width="148"
-             left_pad="0">
+             left_pad="10">
                 <combo_box.item
                  label="Touch  (default)"
                  name="Touch/grab(default)"
@@ -1009,7 +1009,7 @@
              width="100" />
 <!-- NEW SALE TYPE COMBO BOX -->
       <combo_box
-            left_pad="0"
+            left_pad="10"
             layout="topleft"
             follows="left|top"
             allow_text_entry="false"
@@ -1041,7 +1041,7 @@ even though the user gets a free copy.
         decimal_digits="0"
         increment="1"
         top_pad="8"
-        left="108"
+        left="118"
         control_name="Edit Cost"
         name="Edit Cost"
         label="Price: L$"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
index 679d5bc82e4582d588fef5630463de6ff410aea4..7fa4cd840a6b0ad30475b078757e23a530786756 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml
@@ -16,22 +16,39 @@
     </menu_item_call>
     <menu_item_separator
      layout="topleft" />
-    <menu_item_call
+    <menu_item_check
      label="Sort by Name"
      layout="topleft"
      name="sort_by_name">
         <on_click
          function="Inventory.GearDefault.Custom.Action"
          parameter="sort_by_name" />
-    </menu_item_call>
-    <menu_item_call
+        <on_check
+         function="Inventory.GearDefault.Check"
+         parameter="sort_by_name" />
+    </menu_item_check>
+    <menu_item_check
      label="Sort by Most Recent"
      layout="topleft"
      name="sort_by_recent">
         <on_click
          function="Inventory.GearDefault.Custom.Action"
          parameter="sort_by_recent" />
-    </menu_item_call>
+        <on_check
+         function="Inventory.GearDefault.Check"
+         parameter="sort_by_recent" />         
+    </menu_item_check>
+    <menu_item_check
+     label="Sort System Folders to Top"
+     layout="topleft"
+     name="sort_system_folders_to_top">
+        <on_click
+         function="Inventory.GearDefault.Custom.Action"
+         parameter="sort_system_folders_to_top" />
+        <on_check
+         function="Inventory.GearDefault.Check"
+         parameter="sort_system_folders_to_top" />
+    </menu_item_check>
     <menu_item_separator
      layout="topleft" />
     <menu_item_call
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 9fcf952bf0f3a0ea6a1adb862eac323258a569b5..0aaed36cf0ba956b5f7e7c687e090af40ac5fee1 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -94,6 +94,49 @@
              function="Floater.Toggle"
              parameter="voice_effect" />
         </menu_item_check>
+		<menu
+		 create_jump_keys="true"
+		 label="Movement"
+		 name="Movement"
+		 tear_off="true">
+            <menu_item_call
+             label="Sit Down"
+             layout="topleft"
+		     shortcut="alt|shift|S"
+             name="Sit Down Here">
+                <menu_item_call.on_click
+                 function="Self.SitDown"
+                 parameter="" />
+                <menu_item_call.on_enable
+                 function="Self.EnableSitDown" />
+            </menu_item_call>
+            <menu_item_check
+             label="Fly"
+             name="Fly"
+             shortcut="Home">
+                <menu_item_check.on_check
+                 function="Agent.getFlying" />
+                <menu_item_check.on_click
+                 function="Agent.toggleFlying" />
+                <menu_item_check.on_enable
+                 function="Agent.enableFlying" />
+            </menu_item_check>
+            <menu_item_check
+             label="Always Run"
+             name="Always Run"
+             shortcut="control|R">
+                <menu_item_check.on_check
+                 function="World.CheckAlwaysRun" />
+                <menu_item_check.on_click
+                 function="World.AlwaysRun" />
+            </menu_item_check>
+            <menu_item_call
+             label="Stop Animating Me"
+             name="Stop Animating My Avatar">
+                 <menu_item_call.on_click
+                  function="Tools.StopAllAnimations" />
+            </menu_item_call>
+		</menu>
         <menu
          create_jump_keys="true"
          label="My Status"
@@ -995,12 +1038,6 @@
      name="Advanced"
      tear_off="true"
      visible="false">
-        <menu_item_call
-         label="Stop Animating Me"
-         name="Stop Animating My Avatar">
-            <menu_item_call.on_click
-             function="Tools.StopAllAnimations" />
-        </menu_item_call>
         <menu_item_call
          label="Rebake Textures"
          name="Rebake Texture"
@@ -1553,29 +1590,6 @@
 
             <menu_item_separator/>
 
-            <menu_item_check
-             label="Always Run"
-             name="Always Run"
-             shortcut="control|R">
-                <menu_item_check.on_check
-                 function="World.CheckAlwaysRun" />
-                <menu_item_check.on_click
-                 function="World.AlwaysRun" />
-            </menu_item_check>
-            <menu_item_check
-             label="Fly"
-             name="Fly"
-             shortcut="Home">
-                <menu_item_check.on_check
-                 function="Agent.getFlying" />
-                <menu_item_check.on_click
-                 function="Agent.toggleFlying" />
-                <menu_item_check.on_enable
-                 function="Agent.enableFlying" />
-            </menu_item_check>
-
-            <menu_item_separator/>
-
             <menu_item_call
              label="Close Window"
              name="Close Window"
@@ -2661,24 +2675,16 @@
                  function="Advanced.PrintTextureMemoryStats" />
             </menu_item_call>
             <menu_item_check
-             label="Double-ClickAuto-Pilot"
-             name="Double-ClickAuto-Pilot">
-                <menu_item_check.on_check
-                 function="CheckControl"
-                 parameter="DoubleClickAutoPilot" />
-                <menu_item_check.on_click
-                 function="ToggleControl"
-                 parameter="DoubleClickAutoPilot" />
-            </menu_item_check>
-            <menu_item_check
-             label="Double-Click Teleport"
-             name="DoubleClick Teleport">
+             label="Region Debug Console"
+             name="Region Debug Console"
+             shortcut="control|shift|`"
+             use_mac_ctrl="true">
                 <menu_item_check.on_check
-                 function="CheckControl"
-                 parameter="DoubleClickTeleport" />
+                 function="Floater.Visible"
+                 parameter="region_debug_console" />
                 <menu_item_check.on_click
-                 function="ToggleControl"
-                 parameter="DoubleClickTeleport" />
+                 function="Floater.Toggle"
+                 parameter="region_debug_console" />
             </menu_item_check>
             <menu_item_check
              label="Region Debug Console"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index a0fd0a13ccea2a0e24b830aaba974e6f3353e785..9536bf2cf70c8db5fa98f796dcc9ec84d6fa56cf 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2869,6 +2869,25 @@ Download to your Applications folder?
      yestext="Download"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="FailedUpdateInstall"
+   type="alertmodal">
+An error occurred installing the viewer update.
+Please download and install the latest viewer from
+http://secondlife.com/download.
+    <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+  <notification
+   icon="notifytip.tga"
+   name="DownloadBackground"
+   type="notifytip">
+An updated version of [APP_NAME] has been downloaded.
+It will be applied the next time you restart [APP_NAME]
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="DeedObjectToGroup"
@@ -5539,7 +5558,7 @@ Friendship offer declined.
    name="OfferCallingCard"
    persist="true"
    type="notify">
-[FIRST] [LAST] is offering their calling card.
+[NAME] is offering their calling card.
 This will add a bookmark in your inventory so you can quickly IM this Resident.
     <form name="form">
       <button
diff --git a/indra/newview/skins/default/xui/en/panel_notify_textbox.xml b/indra/newview/skins/default/xui/en/panel_notify_textbox.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4634eeed4676ef840885b56894568c11d8bc0250
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notify_textbox.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+   background_visible="true"
+   height="230"
+   label="instant_message"
+   layout="topleft"
+   left="0"
+   name="panel_notify_textbox"
+   top="0"
+   width="305">
+  <string
+     name="message_max_lines_count"
+     value="7" />
+  <panel
+   bevel_style="none"
+   follows="left|right|top"
+   height="150"
+   label="info_panel"
+   layout="topleft"
+   left="0"
+   name="info_panel"
+   top="0"
+   width="305">
+    <text_editor
+     parse_urls="true"
+     enabled="true"
+     follows="all"
+     height="60"
+     layout="topleft"
+     left="25"
+     max_length="250"
+     name="message"
+     parse_highlights="true"
+     read_only="false"
+     top="40"
+     type="string"
+     use_ellipses="true"
+     value="message"
+     width="260"
+     word_wrap="true" >
+    </text_editor>
+     parse_urls="false"
+    <button
+     top="110"
+     follows="top|left"
+     height="20"
+     label="Submit"
+     layout="topleft"
+     left="25"
+     name="btn_submit"
+     width="70" />
+  </panel>
+  <panel
+     background_visible="false"
+     follows="left|right|bottom"
+     height="0" 
+     width="290"
+     label="control_panel"
+     layout="topleft"
+     left="10"
+     name="control_panel"
+     top_pad="5">
+    <!-- 
+	 Notes:
+	 This panel holds the Ignore button and possibly other buttons of notification.
+      -->
+  </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 15d1222d001b5e7f054c247b2bde62dbb93f7eaf..d6e4c5611363e08b7b435a383db2a0737b1c93e7 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -79,6 +79,7 @@
     </radio_group>
 
     <check_box
+     control_name="AllowMultipleViewers"
      follows="top|left"
      height="15"
      label="Allow Multiple Viewer"
@@ -88,6 +89,7 @@
      top_pad="20"
      width="237"/>
     <check_box
+     control_name="ForceShowGrid"
      follows="top|left"
      height="15"
      label="Show Grid Selection at login"
@@ -97,6 +99,7 @@
      top_pad="5"
      width="237"/>
     <check_box
+     control_name="UseDebugMenus"
      follows="top|left"
      height="15"
      label="Show Advanced Menu"
@@ -106,6 +109,7 @@
      top_pad="5"
      width="237"/>
     <check_box
+     control_name="QAMode"
      follows="top|left"
      height="15"
      label="Show Developer Menu"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
index 036730a646c79efbf600729eeb1d8d3732707479..6dc419a96c2b095014ffc96d22f54fa1fc9f7e41 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml
@@ -113,22 +113,22 @@
   </text>
   <color_swatch
    can_apply_immediately="true"
-   color="LtGray"
+   color="EmphasisColor_35"
    follows="left|top"
    height="24"
    label_height="0"
    label_width="60"
    layout="topleft"
    left="360"
-   name="im"
+   name="objects"
    top_pad="-15"
    width="44">
     <color_swatch.init_callback
 		 function="Pref.getUIColor"
-		 parameter="IMChatColor" />
+		 parameter="ObjectChatColor" />
     <color_swatch.commit_callback
 		 function="Pref.applyUIColor"
-		 parameter="IMChatColor" />
+		 parameter="ObjectChatColor" />
   </color_swatch>
   <text
      type="string"
@@ -141,7 +141,7 @@
      name="text_box3"
      top_delta="5"
      width="95">
-    IM
+    Objects
   </text>
   <color_swatch
    can_apply_immediately="true"
@@ -206,37 +206,6 @@
    width="95">
     Errors
   </text>
-  <color_swatch
-   can_apply_immediately="true"
-   color="EmphasisColor_35"
-   follows="left|top"
-   height="24"
-   label_height="0"
-   layout="topleft"
-   left="360"
-   name="objects"
-   top_pad="-15"
-   width="44" >
-    <color_swatch.init_callback
-		 function="Pref.getUIColor"
-		 parameter="ObjectChatColor" />
-    <color_swatch.commit_callback
-		 function="Pref.applyUIColor"
-		 parameter="ObjectChatColor" />
-  </color_swatch>
-  <text
-   type="string"
-   length="1"
-   follows="left|top"
-   height="10"
-   layout="topleft"
-   left_pad="5"
-   mouse_opaque="false"
-   name="text_box6"
-   top_delta="5"
-   width="95">
-    Objects
-  </text>
   <color_swatch
    can_apply_immediately="true"
    color="LtYellow"
@@ -305,7 +274,7 @@
    left="30"
    height="12"
    name="bubble_chat"
-   top_pad="28"
+   top_pad="20"
    width="120"
    >
     Bubble chat:
@@ -336,11 +305,58 @@
    height="16"
    increment="0.05"
    initial_value="1"
-   label="Opacity"
+   label="Opacity:"
    layout="topleft"
-   left_pad="15"
-   label_width="56"
+   left_pad="10"
+   label_width="70"
    name="bubble_chat_opacity"
    top_delta = "6"
-   width="347" />
+   width="378" />
+  <text
+   follows="left|top"
+   layout="topleft"
+   left="30"
+   height="12"
+   name="bubble_chat"
+   top_pad="15"
+   width="120"
+   >
+    Floater Opacity:
+  </text>
+ <slider
+   can_edit_text="false"
+   control_name="ActiveFloaterTransparency"
+   decimal_digits="2"
+   follows="left|top"
+   height="16"
+   increment="0.01"
+   initial_value="0.8"
+   layout="topleft"
+   label_width="115"
+   label="Active :"
+   left="50"
+   max_val="1.00"
+   min_val="0.00"
+   name="active"
+   show_text="true"
+   top_pad="5"
+   width="415" />
+  <slider
+   can_edit_text="false"
+   control_name="InactiveFloaterTransparency"
+   decimal_digits="2"
+   follows="left|top"
+   height="16"
+   increment="0.01"
+   initial_value="0.5"
+   layout="topleft"
+   label_width="115"
+   label="Inctive :"
+   left="50"
+   max_val="1.00"
+   min_val="0.00"
+   name="active"
+   show_text="true"
+   top_pad="5"
+   width="415" />
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index a660b5d785d629d75fd6c3d0ce03f780f586f8e0..36f8f991789402b79939992a6e57177bc499235b 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -331,6 +331,7 @@
        Pressing letter keys:
    </text>
    <radio_group
+     control_name="LetterKeysFocusChatBar" 
      height="20"
      layout="topleft"
      left="35"
@@ -338,12 +339,12 @@
      name="inworld_typing_preference">
         <radio_item
          label="Starts local chat"
-         name="radio_button1"
+         name="radio_start_chat"
          top_delta="20" 
          layout="topleft"
          height="16" 
          left="0" 
-         value="0"
+         value="1"
          width="150" />
         <radio_item
          label="Affects movement (i.e. WASD)"
@@ -351,8 +352,8 @@
          layout="topleft"
          top_delta="0" 
          height="16" 
-         name="radio_button2"
-         value="1"
+         name="radio_move"
+         value="0"
          width="75" />
     </radio_group>
     
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 7d49a671e66d258865730cc6635a8ca2edd07039..3ceee609273bfc914de8b758f8aac0b0a2321d91 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -163,536 +163,546 @@
      top="76"
      width="485">
 		<text
-		type="string"
-		length="1"
-		follows="left|top"
-		height="12"
-		layout="topleft"
-		left_delta="5"
-		name="ShadersText"
-		top="3"
-		width="128">
+		 type="string"
+		 length="1"
+		 follows="left|top"
+		 height="12"
+		 layout="topleft"
+		 left_delta="5"
+		 name="ShadersText"
+		 top="3"
+		 width="128">
 			Shaders:
 		</text>
 		<check_box
-		control_name="RenderObjectBump"
-		height="16"
-		initial_value="true"
-		label="Bump mapping and shiny"
-		layout="topleft"
-		left_delta="0"
-		name="BumpShiny"
-		top_pad="7"
-		width="256" />
+		 control_name="RenderTransparentWater"
+		 height="16"
+		 initial_value="true"
+		 label="Transparent Water"
+		 layout="topleft"
+		 left_delta="0"
+		 name="BumpShiny"
+		 top_pad="7"
+		 width="256" />
 		<check_box
-		control_name="VertexShaderEnable"
-		height="16"
-		initial_value="true"
-		label="Basic shaders"
-		layout="topleft"
-		left_delta="0"
-		name="BasicShaders"
-		tool_tip="Disabling this option may prevent some graphics card drivers from crashing"
-		top_pad="1"
-		width="315">
+		 control_name="RenderObjectBump"
+		 height="16"
+		 initial_value="true"
+		 label="Bump mapping and shiny"
+		 layout="topleft"
+		 left_delta="0"
+		 name="BumpShiny"
+		 top_pad="1"
+		 width="256" />
+		<check_box
+		 control_name="VertexShaderEnable"
+		 height="16"
+		 initial_value="true"
+		 label="Basic shaders"
+		 layout="topleft"
+		 left_delta="0"
+		 name="BasicShaders"
+		 tool_tip="Disabling this option may prevent some graphics card drivers from crashing"
+		 top_pad="1"
+		 width="315">
 			<check_box.commit_callback
-			function="Pref.VertexShaderEnable" />
+		     function="Pref.VertexShaderEnable" />
 		</check_box>
 		<check_box
-		control_name="WindLightUseAtmosShaders"
-		height="16"
-		initial_value="true"
-		label="Atmospheric shaders"
-		layout="topleft"
-		left_delta="0"
-		name="WindLightUseAtmosShaders"
-		top_pad="1"
-		width="256">
+		 control_name="WindLightUseAtmosShaders"
+		 height="16"
+		 initial_value="true"
+		 label="Atmospheric shaders"
+		 layout="topleft"
+		 left_delta="0"
+		 name="WindLightUseAtmosShaders"
+		 top_pad="1"
+		 width="256">
 			<check_box.commit_callback
-			function="Pref.VertexShaderEnable" />
+			 function="Pref.VertexShaderEnable" />
 		</check_box>
 <!-- DISABLED UNTIL WE REALLY WANT TO SUPPORT THIS
-    <check_box
-		control_name="RenderDeferred"
-		height="16"
-		initial_value="true"
-		label="Lighting and Shadows"
-		layout="topleft"
-		left_delta="0"
-		name="UseLightShaders"
-		top_pad="1"
-		width="256">
-      <check_box.commit_callback
-			function="Pref.VertexShaderEnable" />
-    </check_box>
-    <check_box
-		control_name="RenderDeferredSSAO"
-		height="16"
-		initial_value="true"
-		label="Ambient Occlusion"
-		layout="topleft"
-		left_delta="0"
-		name="UseSSAO"
-		top_pad="1"
-		width="256">
-      <check_box.commit_callback
-			function="Pref.VertexShaderEnable" />
-    </check_box>
+    	<check_box
+		 control_name="RenderDeferred"
+		 height="16"
+		 initial_value="true"
+		 label="Lighting and Shadows"
+		 layout="topleft"
+		 left_delta="0"
+		 name="UseLightShaders"
+		 top_pad="1"
+		 width="256">
+         	<check_box.commit_callback
+			 function="Pref.VertexShaderEnable" />
+    	</check_box>
+    	<check_box
+		 control_name="RenderDeferredSSAO"
+		 height="16"
+		 initial_value="true"
+		 label="Ambient Occlusion"
+		 layout="topleft"
+		 left_delta="0"
+		 name="UseSSAO"
+		 top_pad="1"
+		 width="256">
+         	<check_box.commit_callback
+			 function="Pref.VertexShaderEnable" />
+    	</check_box>
 
-     <text
-    type="string"
-    length="1"
-    top_pad="8"
-    follows="top|left"
-    height="23"
-    width="110"
-    word_wrap="true"
-    layout="topleft"
-    left="10"
-    name="shadows_label">
-        Shadows:
-      </text>
-      <combo_box
-      control_name="RenderShadowDetail"
-      height="23"
-      layout="topleft"
-      left="10"
-      top_pad="0" 
-      name="ShadowDetail"
-      width="150">
-        <combo_box.item
-        label="None"
-        name="0"
-        value="0"/>
-        <combo_box.item
-        label="Sun/Moon"
-        name="1"
-        value="1"/>
-        <combo_box.item
-        label="Sun/Moon + Projectors"
-        name="2"
-        value="2"/>
-      </combo_box>
+        <text
+         type="string"
+         length="1"
+         top_pad="8"
+         follows="top|left"
+         height="23"
+         width="110"
+         word_wrap="true"
+         layout="topleft"
+         left="10"
+         name="shadows_label">
+         	Shadows:
+        </text>
+        <combo_box
+         control_name="RenderShadowDetail"
+         height="23"
+         layout="topleft"
+         left="10"
+         top_pad="0" 
+         name="ShadowDetail"
+         width="150">
+           <combo_box.item
+            label="None"
+            name="0"
+            value="0"/>
+           <combo_box.item
+            label="Sun/Moon"
+            name="1"
+            value="1"/>
+           <combo_box.item
+            label="Sun/Moon + Projectors"
+            name="2"
+            value="2"/>
+        </combo_box>
 -->
-      <text
-  type="string"
-  length="1"
-  top_pad="8"
-  follows="top|left"
-  height="23"
-  width="110"
-  word_wrap="true"
-  layout="topleft"
-  left="10"
-  name="reflection_label">
-        Water Reflections:
-      </text>
-      <combo_box
-      control_name="RenderReflectionDetail"
-      height="23"
-      layout="topleft"
-      left_delta="10"
-      top_pad ="0"
-      name="Reflections"
-      width="150">
-        <combo_box.item
-        label="Minimal"
-        name="0"
-        value="0"/>
-        <combo_box.item
-        label="Terrain and trees"
-        name="1"
-        value="1"/>
-        <combo_box.item
-        label="All static objects"
-        name="2"
-        value="2"/>
-        <combo_box.item
-        label="All avatars and objects"
-        name="3"
-        value="3"/>
-        <combo_box.item
-        label="Everything"
-        name="4"
-        value="4"/>
-      </combo_box>
+        <text
+         type="string"
+         length="1"
+         top_pad="8"
+         follows="top|left"
+         height="12"
+         width="110"
+         word_wrap="true"
+         layout="topleft"
+         left="05"
+         name="reflection_label">
+            Water Reflections:
+        </text>
+        <combo_box
+         control_name="RenderReflectionDetail"
+         height="18"
+         layout="topleft"
+         left_delta="10"
+         top_pad ="3"
+         name="Reflections"
+         width="150">
+            <combo_box.item
+             label="Minimal"
+             name="0"
+             value="0"/>
+            <combo_box.item
+             label="Terrain and trees"
+             name="1"
+             value="1"/>
+            <combo_box.item
+             label="All static objects"
+             name="2"
+             value="2"/>
+            <combo_box.item
+             label="All avatars and objects"
+             name="3"
+             value="3"/>
+            <combo_box.item
+             label="Everything"
+             name="4"
+             value="4"/>
+        </combo_box>
     
 		<slider
-		control_name="RenderFarClip"
-		decimal_digits="0"
-		follows="left|top"
-		height="16"
-		increment="8"
-		initial_value="160"
-		label="Draw distance:"
-		label_width="185"
-		layout="topleft"
-		left="200"
-		max_val="512"
-		min_val="64"
-		name="DrawDistance"
-		top="3"
-		width="296" />
+		 control_name="RenderFarClip"
+		 decimal_digits="0"
+		 follows="left|top"
+		 height="16"
+		 increment="8"
+		 initial_value="160"
+		 label="Draw distance:"
+		 label_width="185"
+		 layout="topleft"
+		 left="200"
+		 max_val="512"
+		 min_val="64"
+		 name="DrawDistance"
+		 top="3"
+		 width="296" />
 		<text
-		type="string"
-		length="1"
-		follows="left|top"
-		height="12"
-		layout="topleft"
-		left_delta="291"
-		name="DrawDistanceMeterText2"
-		top_delta="0"
-		width="128">
+		 type="string"
+		 length="1"
+		 follows="left|top"
+		 height="12"
+		 layout="topleft"
+		 left_delta="291"
+		 name="DrawDistanceMeterText2"
+		 top_delta="0"
+		 width="128">
 			m
 		</text>    
 		<slider
-		control_name="RenderMaxPartCount"
-		decimal_digits="0"
-		follows="left|top"
-		height="16"
-		increment="256"
-		initial_value="4096"
-		label="Max. particle count:"
-		label_width="185"
-		layout="topleft"
-		left="200"
-		max_val="8192"
-		name="MaxParticleCount"
-		top_pad="7"
-		width="303" />
-    <slider
-    control_name="RenderAvatarMaxVisible"
-    decimal_digits="0"
-    follows="left|top"
-    height="16"
-    increment="1"
-    initial_value="12"
-    label="Max. # of non-impostor avatars:"
-    label_width="185"
-    layout="topleft"
-    left_delta="0"
-    max_val="65"
-    min_val="1"
-    name="MaxNumberAvatarDrawn"
-    top_pad="4"
-    width="290" />
+		 control_name="RenderMaxPartCount"
+		 decimal_digits="0"
+		 follows="left|top"
+		 height="16"
+		 increment="256"
+		 initial_value="4096"
+		 label="Max. particle count:"
+		 label_width="185"
+		 layout="topleft"
+		 left="200"
+		 max_val="8192"
+		 name="MaxParticleCount"
+		 top_pad="7"
+		 width="303" />
+        <slider
+         control_name="RenderAvatarMaxVisible"
+         decimal_digits="0"
+         follows="left|top"
+         height="16"
+         increment="1"
+         initial_value="12"
+         label="Max. # of non-impostor avatars:"
+         label_width="185"
+         layout="topleft"
+         left_delta="0"
+         max_val="65"
+         min_val="1"
+         name="MaxNumberAvatarDrawn"
+         top_pad="4"
+         width="290" />
 		<slider
-		control_name="RenderGlowResolutionPow"
-		decimal_digits="0"
-		follows="left|top"
-		height="16"
-		increment="1"
-		initial_value="8"
-		label="Post process quality:"
-		label_width="185"
-		layout="topleft"
-		left="200"
-		max_val="9"
-		min_val="8"
-		name="RenderPostProcess"
-		show_text="false"
-		top_pad="4"
-		width="264">
+ 		 control_name="RenderGlowResolutionPow"
+		 decimal_digits="0"
+		 follows="left|top"
+		 height="16"
+		 increment="1"
+		 initial_value="8"
+		 label="Post process quality:"
+		 label_width="185"
+		 layout="topleft"
+		 left="200"
+		 max_val="9"
+		 min_val="8"
+		 name="RenderPostProcess"
+		 show_text="false"
+		 top_pad="4"
+		 width="264">
 			<slider.commit_callback
-			function="Pref.UpdateSliderText"
-			parameter="PostProcessText" />
+			 function="Pref.UpdateSliderText"
+			 parameter="PostProcessText" />
 		</slider>
 		<text
-		type="string"
-		length="1"
-		follows="left|top"
-		height="12"
-		layout="topleft"
-		left_delta="0"
-		name="MeshDetailText"
-		top_pad="5"
-		width="128">
+		 type="string"
+		 length="1"
+		 follows="left|top"
+		 height="12"
+		 layout="topleft"
+		 left_delta="0"
+		 name="MeshDetailText"
+		 top_pad="5"
+		 width="128">
 			Mesh detail:
 		</text>
 		<slider
-		control_name="RenderVolumeLODFactor"
-		follows="left|top"
-		height="16"
-		increment="0.125"
-		initial_value="160"
-		label="  Objects:"
-		label_width="185"
-		layout="topleft"
-		left_delta="0"
-		max_val="2"
-		name="ObjectMeshDetail"
-		show_text="false"
-		top_pad="6"
-		width="264">
+		 control_name="RenderVolumeLODFactor"
+		 follows="left|top"
+		 height="16"
+		 increment="0.125"
+		 initial_value="160"
+		 label="  Objects:"
+		 label_width="185"
+		 layout="topleft"
+		 left_delta="0"
+		 max_val="2"
+		 name="ObjectMeshDetail"
+		 show_text="false"
+		 top_pad="6"
+		 width="264">
 			<slider.commit_callback
-			function="Pref.UpdateSliderText"
-			parameter="ObjectMeshDetailText" />
+			 function="Pref.UpdateSliderText"
+			 parameter="ObjectMeshDetailText" />
 		</slider>
 		<slider
-		control_name="RenderFlexTimeFactor"
-		follows="left|top"
-		height="16"
-		initial_value="160"
-		label="  Flexiprims:"
-		label_width="185"
-		layout="topleft"
-		left_delta="0"
-		name="FlexibleMeshDetail"
-		show_text="false"
-		top_pad="4"
-		width="264">
+		 control_name="RenderFlexTimeFactor"
+		 follows="left|top"
+		 height="16"
+		 initial_value="160"
+		 label="  Flexiprims:"
+		 label_width="185"
+		 layout="topleft"
+		 left_delta="0"
+		 name="FlexibleMeshDetail"
+		 show_text="false"
+		 top_pad="4"
+		 width="264">
 			<slider.commit_callback
-			function="Pref.UpdateSliderText"
-			parameter="FlexibleMeshDetailText" />
+			 function="Pref.UpdateSliderText"
+			 parameter="FlexibleMeshDetailText" />
 		</slider>
         <slider
-        control_name="RenderTreeLODFactor"
-        follows="left|top"
-        height="16"
-        increment="0.125"
-        initial_value="160"
-        label="  Trees:"
-        label_width="185"
-        layout="topleft"
-        left_delta="0"
-        name="TreeMeshDetail"
-        show_text="false"
-        top_pad="4"
-        width="264">
-           <slider.commit_callback
-            function="Pref.UpdateSliderText"
-            parameter="TreeMeshDetailText" />
-        </slider>
+         control_name="RenderTreeLODFactor"
+         follows="left|top"
+         height="16"
+         increment="0.125"
+         initial_value="160"
+         label="  Trees:"
+         label_width="185"
+         layout="topleft"
+         left_delta="0"
+         name="TreeMeshDetail"
+         show_text="false"
+         top_pad="4"
+         width="264">
+            <slider.commit_callback
+             function="Pref.UpdateSliderText"
+             parameter="TreeMeshDetailText" />
+            </slider>
         <slider
-        control_name="RenderAvatarLODFactor"
-        follows="left|top"
-        height="16"
-        increment="0.125"
-        initial_value="160"
-        label="  Avatars:"
-        label_width="185"
-        layout="topleft"
-        left_delta="0"
-        name="AvatarMeshDetail"
-        show_text="false"
-        top_pad="4"
-        width="264">
-           <slider.commit_callback
-            function="Pref.UpdateSliderText"
-            parameter="AvatarMeshDetailText" />
+         control_name="RenderAvatarLODFactor"
+         follows="left|top"
+         height="16"
+         increment="0.125"
+         initial_value="160"
+         label="  Avatars:"
+         label_width="185"
+         layout="topleft"
+         left_delta="0"
+         name="AvatarMeshDetail"
+         show_text="false"
+         top_pad="4"
+         width="264">
+            <slider.commit_callback
+             function="Pref.UpdateSliderText"
+             parameter="AvatarMeshDetailText" />
         </slider>
         <slider
-        control_name="RenderTerrainLODFactor"
-        follows="left|top"
-        height="16"
-        increment="0.125"
-        initial_value="160"
-        label="  Terrain:"
-        label_width="185"
-        layout="topleft"
-        left_delta="0"
-        max_val="2"
-        min_val="1"
-        name="TerrainMeshDetail"
-        show_text="false"
-        top_pad="4"
-        width="264">
-           <slider.commit_callback
-            function="Pref.UpdateSliderText"
-            parameter="TerrainMeshDetailText" />
+         control_name="RenderTerrainLODFactor"
+         follows="left|top"
+         height="16"
+         increment="0.125"
+         initial_value="160"
+         label="  Terrain:"
+         label_width="185"
+         layout="topleft"
+         left_delta="0"
+         max_val="2"
+         min_val="1"
+         name="TerrainMeshDetail"
+         show_text="false"
+         top_pad="4"
+         width="264">
+            <slider.commit_callback
+             function="Pref.UpdateSliderText"
+             parameter="TerrainMeshDetailText" />
         </slider>
         <slider
-        control_name="WLSkyDetail"
-		enabled_control="WindLightUseAtmosShaders"
-        decimal_digits="0"
-        follows="left|top"
-        height="16"
-        increment="8"
-        initial_value="160"
-        label="  Sky:"
-        label_width="185"
-        layout="topleft"
-        left_delta="0"
-        max_val="128"
-        min_val="16"
-        name="SkyMeshDetail"
-        show_text="false"
-        top_pad="4"
-        width="264">
-           <slider.commit_callback
-            function="Pref.UpdateSliderText"
-            parameter="SkyMeshDetailText" />
+         control_name="WLSkyDetail"
+		 enabled_control="WindLightUseAtmosShaders"
+         decimal_digits="0"
+         follows="left|top"
+         height="16"
+         increment="8"
+         initial_value="160"
+         label="  Sky:"
+         label_width="185"
+         layout="topleft"
+         left_delta="0"
+         max_val="128"
+         min_val="16"
+         name="SkyMeshDetail"
+         show_text="false"
+         top_pad="4"
+         width="264">
+            <slider.commit_callback
+             function="Pref.UpdateSliderText"
+             parameter="SkyMeshDetailText" />
         </slider>
         <text
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left="469"
-        name="PostProcessText"
-        top="60"
-        width="128">
-           Low
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left="469"
+         name="PostProcessText"
+         top="60"
+         width="128">
+            Low
         </text>
         <text
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left_delta="0"
-        name="ObjectMeshDetailText"
-        top_pad="26"
-        width="128">
-           Low
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left_delta="0"
+         name="ObjectMeshDetailText"
+         top_pad="26"
+         width="128">
+            Low
         </text>
         <text
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left_delta="0"
-        name="FlexibleMeshDetailText"
-        top_pad="8"
-        width="128">
-           Low
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left_delta="0"
+         name="FlexibleMeshDetailText"
+         top_pad="8"
+         width="128">
+            Low
         </text>
         <text
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left_delta="0"
-        name="TreeMeshDetailText"
-        top_pad="8"
-        width="128">
-           Low
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left_delta="0"
+         name="TreeMeshDetailText"
+         top_pad="8"
+         width="128">
+            Low
         </text>
         <text
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left_delta="0"
-        name="AvatarMeshDetailText"
-        top_pad="8"
-        width="128">
-           Low
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left_delta="0"
+         name="AvatarMeshDetailText"
+         top_pad="8"
+         width="128">
+            Low
         </text>
         <text
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left_delta="0"
-        name="TerrainMeshDetailText"
-        top_pad="8"
-        width="128">
-           Low
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left_delta="0"
+         name="TerrainMeshDetailText"
+         top_pad="8"
+         width="128">
+            Low
         </text>
         <text
-		enabled_control="WindLightUseAtmosShaders"
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left_delta="0"
-        name="SkyMeshDetailText"
-        top_pad="8"
-        width="128">
-           Low
+		 enabled_control="WindLightUseAtmosShaders"
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left_delta="0"
+         name="SkyMeshDetailText"
+         top_pad="8"
+         width="128">
+            Low
         </text>
-      <text
-      type="string"
-      length="1"
-      follows="left|top"
-      height="12"
-      layout="topleft"
-      left_delta="-260"
-      name="AvatarRenderingText"
-        top_pad="18"
-      width="128">
-        Avatar rendering:
+        <text
+         type="string"
+         length="1"
+         follows="left|top"
+         height="12"
+         layout="topleft"
+         left_delta="-260"
+         name="AvatarRenderingText"
+         top_pad="18"
+         width="128">
+            Avatar rendering:
       </text>
       <check_box
-      control_name="RenderUseImpostors"
-      height="16"
-      initial_value="true"
-      label="Avatar impostors"
-      layout="topleft"
-      left_delta="0"
-      name="AvatarImpostors"
-      top_pad="7"
-      width="256" />
+       control_name="RenderUseImpostors"
+       height="16"
+       initial_value="true"
+       label="Avatar impostors"
+       layout="topleft"
+       left_delta="0"
+       name="AvatarImpostors"
+       top_pad="7"
+       width="256" />
       <check_box
-      control_name="RenderAvatarVP"
-      height="16"
-      initial_value="true"
-      label="Hardware skinning"
-      layout="topleft"
-      left_delta="0"
-      name="AvatarVertexProgram"
-      top_pad="1"
-      width="256">
-        <check_box.commit_callback
-        function="Pref.VertexShaderEnable" />
+       control_name="RenderAvatarVP"
+       height="16"
+       initial_value="true"
+       label="Hardware skinning"
+       layout="topleft"
+       left_delta="0"
+       name="AvatarVertexProgram"
+       top_pad="1"
+       width="256">
+          <check_box.commit_callback
+           function="Pref.VertexShaderEnable" />
       </check_box>
       <check_box
-      control_name="RenderAvatarCloth"
-      height="16"
-      initial_value="true"
-      label="Avatar cloth"
-      layout="topleft"
-      left_delta="0"
-      name="AvatarCloth"
-      top_pad="1"
-      width="256" />
-        <text
-        type="string"
-        length="1"
-        follows="left|top"
-        height="12"
-        layout="topleft"
-        left="358"
-        left_pad="-30"
-        name="TerrainDetailText"
-        top="226"
-        width="155">
-           Terrain detail:
-        </text>
-        <radio_group
-        control_name="RenderTerrainDetail"
-        draw_border="false"
-        height="38"
-        layout="topleft"
-        left_delta="0"
-        name="TerrainDetailRadio"
-        top_pad="5"
-        width="70">
-           <radio_item
-            height="16"
-            label="Low"
-            layout="topleft"
-            name="0"
-            top="3"
-            width="50" />
-           <radio_item
-            height="16"
-            label="High"
-            layout="topleft"
-            name="2"
-            top_delta="16"
-            width="50" />
-        </radio_group> -->
+       control_name="RenderAvatarCloth"
+       height="16"
+       initial_value="true"
+       label="Avatar cloth"
+       layout="topleft"
+       left_delta="0"
+       name="AvatarCloth"
+       top_pad="1"
+       width="256" />
+      <text
+       type="string"
+       length="1"
+       follows="left|top"
+       height="12"
+       layout="topleft"
+       left="358"
+       left_pad="-30"
+       name="TerrainDetailText"
+       top="226"
+       width="155">
+          Terrain detail:
+      </text>
+      <radio_group
+       control_name="RenderTerrainDetail"
+       draw_border="false"
+       height="38"
+       layout="topleft"
+       left_delta="0"
+       name="TerrainDetailRadio"
+       top_pad="5"
+       width="70">
+          <radio_item
+           height="16"
+           label="Low"
+           layout="topleft"
+           name="0"
+           top="3"
+           width="50" />
+          <radio_item
+           height="16"
+           label="High"
+           layout="topleft"
+           name="2"
+           top_delta="16"
+           width="50" />
+      </radio_group> -->
 	</panel>
 	
-        <button
+    <button
      follows="left|bottom"
      height="23"
      label="Apply"
@@ -701,8 +711,7 @@
      left="10"
      name="Apply"
      top="383"
-     width="115"
-      >
+     width="115">
         <button.commit_callback
          function="Pref.Apply" />
     </button>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
index ec80efe188b3a5b65854ceaff1a62952d68471dc..d2fc6ea09a3ae2a575e11abab399166c9b4e05cc 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
@@ -177,7 +177,10 @@
    left_delta="0"
    name="double_click_chkbox"
    width="237"
-   top_pad="0"/>
+   top_pad="0">
+   <check_box.commit_callback
+    function="Pref.CommitDoubleClickChekbox"/>
+  </check_box>
   <radio_group
      height="20"
      layout="topleft"
@@ -191,7 +194,6 @@
      left="0"
      name="radio_teleport"
      top_delta="20"
-     value="0"
      width="100" />
     <radio_item
      height="16"
@@ -200,7 +202,19 @@
      layout="topleft"
      name="radio_autopilot"
      top_delta="0"
-     value="1"
      width="75" />
+    <radio_group.commit_callback
+	     function="Pref.CommitRadioDoubleClick"/>
   </radio_group>
-</panel>
+  <button
+   height="23"
+   label="Other Devices"
+   left="30"
+   name="joystick_setup_button"
+   top="30"
+   width="155">
+    <button.commit_callback
+     function="Floater.Show"
+     parameter="pref_joystick" />
+  </button>
+</panel>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 14aa38c5d36f03dc27e29fe8870d3a3227a72b51..584bd1ea9d88430cd70301cf557b9570287739c0 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -341,4 +341,20 @@
    name="web_proxy_port"
    top_delta="0"
    width="145" />
+
+  <check_box
+    top_delta="2"
+    enabled="true"
+    follows="left|top"
+    height="18"
+    initial_value="true"
+    control_name="UpdaterServiceActive"
+    label="Automatically download and install [APP_NAME] updates"
+    left="30"
+    mouse_opaque="true"
+    name="updater_service_active"
+    radio_style="false"
+    width="400"
+    top_pad="10"/>
+
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 8ade41f587b6246205fb685cd2bee4a503d8e47f..da366f30aef79687850b22b734d8e380f433e25b 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -70,7 +70,7 @@
 		name="UI Volume"
 		show_text="false"
 		slider_label.halign="right"
-		top_pad="5"
+		top_pad="4"
 		volume="true"
 		width="300">
 	  <slider.commit_callback
@@ -104,7 +104,7 @@
      name="Wind Volume"
      show_text="false"
      slider_label.halign="right"
-     top_pad="5"
+     top_pad="4"
      volume="true"
      width="300">
         <slider.commit_callback
@@ -138,7 +138,7 @@
      left="0"
      name="SFX Volume"
      show_text="false"
-     top_pad="7"
+     top_pad="4"
      volume="true"
      width="300">
         <slider.commit_callback
@@ -172,7 +172,7 @@
      name="Music Volume"
      slider_label.halign="right"
      show_text="false"
-     top_pad="5"
+     top_pad="4"
      volume="true"
      width="300">
         <slider.commit_callback
@@ -215,7 +215,7 @@
 		name="Media Volume"
 		show_text="false"
 		slider_label.halign="right"
-		top_pad="5"
+		top_pad="4"
 		volume="true"
 		width="300">
 	  <slider.commit_callback
@@ -257,7 +257,7 @@
 		label_width="120"
 		layout="topleft"
 		left="0"
-		top_pad="5"
+		top_pad="4"
 		name="Voice Volume"
 		show_text="false"
 		slider_label.halign="right"
@@ -301,9 +301,9 @@
 		height="15"
 		tool_tip="Check this to let media auto-play if it wants"
 		label="Allow Media to auto-play"
-		top_pad="5"
+		top_pad="1"
 		left="25"/>
-	<check_box
+ 	<check_box
 		name="media_show_on_others_btn"
 		control_name="MediaShowOnOthers"
 		value="true"
@@ -313,16 +313,6 @@
 		label="Play media attached to other avatars"
 		left="25"
     width="230"/>
-  <check_box
-     control_name="LipSyncEnabled"
-     follows="left|top"
-     height="20"
-     label="Move avatar lips when speaking"
-     layout="topleft"
-     left_pad="0"
-     name="enable_lip_sync"
-     width="237"
-     top_delta="-4" />
 
     <text
      type="string"
@@ -333,7 +323,7 @@
      left="25"
      name="voice_chat_settings"
      width="180"
-     top_pad="10">
+     top_pad="7">
 	  Voice Chat Settings
     </text>
     <text
@@ -341,10 +331,10 @@
      length="1"
      follows="left|top"
      layout="topleft"
-	   left="80"
+	   left="46"
 	   top_delta="16"
      name="Listen from"
-     width="102">
+     width="112">
         Listen from:
     </text>
 	<icon
@@ -363,7 +353,7 @@
 		height="18"
 		image_name="Move_Walk_Off"
 		layout="topleft"
-    left_pad="130" 
+    left_pad="170" 
 		name="avatar_icon"
 		mouse_opaque="false"
 		visible="true"
@@ -375,7 +365,7 @@
      draw_border="false"
      follows="left|top"
      layout="topleft"
-     left_delta="-128"
+     left_delta="-168"
      width="221"
      height="20"
      name="ear_location">
@@ -391,11 +381,21 @@
      follows="left|top"
      label="Avatar position"
      layout="topleft"
-     left_pad="-54"
+     left_pad="-16"
      name="1"
      top_delta ="0" 
      width="200" />
    </radio_group>
+  <check_box
+   control_name="LipSyncEnabled"
+   follows="left|top"
+   height="15"
+   label="Move avatar lips when speaking"
+   layout="topleft"
+   left="44"
+   name="enable_lip_sync"
+   top_pad="5" 
+   width="237"/>
  <check_box
   follows="top|left"
   enabled_control="EnableVoiceChat"
@@ -403,10 +403,11 @@
   height="15"
   label="Toggle speak on/off when I press:"
   layout="topleft"
-  left="30"
+  left="44"
   name="push_to_talk_toggle_check"
   width="237"
-  tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."/>
+  tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."
+  top_pad="3"/>
   <line_editor
    follows="top|left"
    control_name="PushToTalkButton"
@@ -454,7 +455,7 @@
    label="Input/Output devices"
    layout="topleft"
    left="20"
-   top_pad="8"
+   top_pad="6"
    name="device_settings_btn"
    width="190">
   </button>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1ec0d34d9a6cfa2e6153fb8ad8dbe7e292ce6a05..51fba470cb0653b6f5f76769dbfd7d5d51da99e7 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -1823,8 +1823,8 @@ key llRequestUsername(key id)
 Requests single-word username of an avatar.  When data is available the dataserver event will be raised.
 </string>
 <string name="LSLTipText_llGetDisplayName" translate="false">
-string llGetDisplayName(key id)
-Returns the name of an avatar, iff the avatar is in the current simulator, otherwise the empty string.
+  string llGetDisplayName(key id)
+  Returns the name of an avatar, iff the avatar is in the current simulator, and the name has been cached, otherwise the same as llGetUsername.  Use llRequestDisplayName if you absolutely must have the display name.
 </string>
 <string name="LSLTipText_llRequestDisplayName" translate="false">
 key llRequestDisplayName(key id)
diff --git a/indra/newview/skins/default/xui/es/floater_im.xml b/indra/newview/skins/default/xui/es/floater_im.xml
deleted file mode 100644
index 3850b94fd67fd4ad678c88caa565b49148ef99fe..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/es/floater_im.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<multi_floater name="im_floater" title="Mensaje Instantáneo">
-	<string name="only_user_message">
-		Eres el único Residente en esta sesión.
-	</string>
-	<string name="offline_message">
-		[FIRST] [LAST] no está conectado.
-	</string>
-	<string name="invite_message">
-		Pulse el botón [BUTTON NAME] para aceptar/conectar este chat de voz.
-	</string>
-	<string name="muted_message">
-		Has ignorado a este Residente. Enviándole un mensaje, automáticamente dejarás de ignorarle.
-	</string>
-	<string name="generic_request_error">
-		Error al hacer lo solicitado; por favor, inténtelo más tarde.
-	</string>
-	<string name="insufficient_perms_error">
-		Usted no tiene permisos suficientes.
-	</string>
-	<string name="session_does_not_exist_error">
-		La sesión ya acabó
-	</string>
-	<string name="no_ability_error">
-		Usted no tiene esa capacidad.
-	</string>
-	<string name="not_a_mod_error">
-		Usted no es un moderador de la sesión.
-	</string>
-	<string name="muted_error">
-		Un moderador del grupo le ha desactivado el chat de texto.
-	</string>
-	<string name="add_session_event">
-		No es posible añadir Residentes a la sesión de chat con [RECIPIENT].
-	</string>
-	<string name="message_session_event">
-		No se ha podido enviar su mensaje a la sesión de chat con [RECIPIENT].
-	</string>
-	<string name="removed_from_group">
-		Ha sido eliminado del grupo.
-	</string>
-	<string name="close_on_no_ability">
-		Usted ya no tendrá más la capacidad de estar en la sesión de chat.
-	</string>
-</multi_floater>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 286af718e39d8e5732b74849b1f1255803bf3316..6c5fe6a9ebc906ca57630d83f32e7de73f928ad3 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -2469,7 +2469,7 @@ Por favor, vuelve a intentarlo en unos momentos.
 		Rehusado el ofrecimiento de amistad.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] te está ofreciendo su tarjeta de visita.
+		[NAME] te está ofreciendo su tarjeta de visita.
 Esto añadirá un marcador en tu inventario para que puedas enviarle rápidamente un MI.
 		<form name="form">
 			<button name="Accept" text="Aceptar"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml
index 8bda133a0b469002b24fdfe1343b541dd48dbac4..17254ff325f1802100a79d37524276917b93acb5 100644
--- a/indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml
+++ b/indra/newview/skins/default/xui/fr/menu_inspect_avatar_gear.xml
@@ -3,7 +3,7 @@
 	<menu_item_call label="Voir le profil" name="view_profile"/>
 	<menu_item_call label="Devenir amis" name="add_friend"/>
 	<menu_item_call label="IM" name="im"/>
-	<menu_item_call label="Appeler" name="call"/>
+	<menu_item_call label="Appel" name="call"/>
 	<menu_item_call label="Téléporter" name="teleport"/>
 	<menu_item_call label="Inviter dans le groupe" name="invite_to_group"/>
 	<menu_item_call label="Ignorer" name="block"/>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index 89fd9c6fdcaadaa715ccd9746d7042bd0346cb3f..341cc9830dde6b65edfc69d77f3dfe264c4e25e5 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -2464,7 +2464,7 @@ Veuillez réessayer dans quelques minutes.
 		Amitié refusée.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] vous offre sa carte de visite.
+		[NAME] vous offre sa carte de visite.
 Cela ajoute un marque-page dans votre inventaire, ce qui vous permet d&apos;envoyer rapidement un IM à ce résident.
 		<form name="form">
 			<button name="Accept" text="Accepter"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_profile.xml b/indra/newview/skins/default/xui/fr/panel_edit_profile.xml
index 30799caf1f57f5e0ceb2b65b9410f5a6bf9a4693..ef65d2fe242fd3c0a82a0fa6abdcca976c6901f7 100644
--- a/indra/newview/skins/default/xui/fr/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/fr/panel_edit_profile.xml
@@ -54,7 +54,7 @@
 				<text name="my_account_link" value="[[URL] Accéder à ma Page d&apos;accueil]"/>
 				<text name="title_partner_text" value="Mon partenaire :"/>
 				<panel name="partner_data_panel">
-					<text initial_value="(récupération en cours)" name="partner_text" value="[FIRST] [LAST]"/>
+					<text initial_value="(récupération en cours)" name="partner_text"/>
 				</panel>
 				<text name="partner_edit_link" value="[[URL] Modifier]"/>
 			</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_main_inventory.xml b/indra/newview/skins/default/xui/fr/panel_main_inventory.xml
index e4c35d60fe400d7a5ac6ae1979f2a7b12a97c08d..3e7225d8ac82b4e160c99def8ffff7cdc7cf1829 100644
--- a/indra/newview/skins/default/xui/fr/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/fr/panel_main_inventory.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Choses" name="main inventory panel">
 	<panel.string name="ItemcountFetching">
-		Récupération de [ITEM_COUNT] articles... [FILTER]
+		Récupération : [ITEM_COUNT] articles... [FILTER]
 	</panel.string>
 	<panel.string name="ItemcountCompleted">
 		[ITEM_COUNT] articles [FILTER]
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index d6c701dc904a7c84f270387f976607f75fe62c8e..8b958119eb7e9d8f13afafbcf4994313af8d0935 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -1089,7 +1089,7 @@
 	<string name="Textures" value=" Textures,"/>
 	<string name="Snapshots" value=" Photos,"/>
 	<string name="No Filters" value="Non "/>
-	<string name="Since Logoff" value=" - Depuis la déconnexion"/>
+	<string name="Since Logoff" value=" depuis la déconnexion"/>
 	<string name="InvFolder My Inventory">
 		Mon inventaire
 	</string>
diff --git a/indra/newview/skins/default/xui/it/floater_bumps.xml b/indra/newview/skins/default/xui/it/floater_bumps.xml
index d9dd3f26d722946375722b46e575614661b5e100..6de2fea67f98947063350c48867a4485b6f95899 100644
--- a/indra/newview/skins/default/xui/it/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/it/floater_bumps.xml
@@ -4,19 +4,19 @@
 		Nessuno rilevato
 	</floater.string>
 	<floater.string name="bump">
-		[TIME]  [FIRST] [LAST] ti ha urtato
+		[TIME]  [NAME] ti ha urtato
 	</floater.string>
 	<floater.string name="llpushobject">
-		[TIME]  [FIRST] [LAST] ti ha spinto per mezzo di uno script
+		[TIME]  [NAME] ti ha spinto per mezzo di uno script
 	</floater.string>
 	<floater.string name="selected_object_collide">
-		[TIME]  [FIRST] [LAST] ti ha colpito con un oggetto
+		[TIME]  [NAME] ti ha colpito con un oggetto
 	</floater.string>
 	<floater.string name="scripted_object_collide">
-		[TIME]  [FIRST] [LAST] ti ha colpito con un oggetto scriptato
+		[TIME]  [NAME] ti ha colpito con un oggetto scriptato
 	</floater.string>
 	<floater.string name="physical_object_collide">
-		[TIME]  [FIRST] [LAST] ti ha colpito con un oggetto fisico
+		[TIME]  [NAME] ti ha colpito con un oggetto fisico
 	</floater.string>
 	<floater.string name="timeStr">
 		[[hour,datetime,slt]:[min,datetime,slt]]
diff --git a/indra/newview/skins/default/xui/it/floater_pay.xml b/indra/newview/skins/default/xui/it/floater_pay.xml
index c1ea8ec9c8e243e7cdef68b2b7d98eaf2a843d04..6389cbfbf7bc9ffd4e12b82ee8e8104cb74fb68f 100644
--- a/indra/newview/skins/default/xui/it/floater_pay.xml
+++ b/indra/newview/skins/default/xui/it/floater_pay.xml
@@ -11,7 +11,7 @@
 	</text>
 	<icon name="icon_person" tool_tip="Persona"/>
 	<text left="115" name="payee_name">
-		[FIRST] [LAST]
+		Test Name That Is Extremely Long To Check Clipping
 	</text>
 	<button label="1 L$" label_selected="1 L$" left="118" name="fastpay 1" width="80"/>
 	<button label="5 L$" label_selected="5 L$" left="210" name="fastpay 5"/>
diff --git a/indra/newview/skins/default/xui/it/floater_pay_object.xml b/indra/newview/skins/default/xui/it/floater_pay_object.xml
index 37f549b5da077bafd80205a9fe27d2993bd490a6..8805f3208e726c88dbae5c5867e6738a9e4a350d 100644
--- a/indra/newview/skins/default/xui/it/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/it/floater_pay_object.xml
@@ -8,7 +8,7 @@
 	</string>
 	<icon name="icon_person" tool_tip="Persona"/>
 	<text left="120" name="payee_name">
-		[FIRST] [LAST]
+		Ericacita Moostopolison
 	</text>
 	<text halign="left" left="5" name="object_name_label" width="110">
 		Mediante l&apos;oggetto:
diff --git a/indra/newview/skins/default/xui/it/floater_tools.xml b/indra/newview/skins/default/xui/it/floater_tools.xml
index fbe611407eecd23200f3d66e898e056e8a6fe010..a8c985cb124fa412d9341b5cfb82ce3a80e2efa5 100644
--- a/indra/newview/skins/default/xui/it/floater_tools.xml
+++ b/indra/newview/skins/default/xui/it/floater_tools.xml
@@ -283,7 +283,7 @@
 				<combo_box.item label="Plastica" name="Plastic"/>
 				<combo_box.item label="Gomma" name="Rubber"/>
 			</combo_box>
-			<text name="text cut">
+			<text name="text cut" left_delta="-10" width="170">
 				Riduci una sezione (inizio/fine)
 			</text>
 			<spinner label="I" name="cut begin"/>
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index ffd27d55e8895c5d68013bf37088d93f88ebf5a5..32483881b2b6d07aa2a5f62210bf4ab6df776145 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -2035,10 +2035,10 @@ Inseriscilo in una pagina web per dare ad altri un accesso facile a questa ubica
 		Oggetto: [SUBJECT], Messaggio: [MESSAGE]
 	</notification>
 	<notification name="FriendOnline">
-		[FIRST] [LAST] è Online
+		[NAME] è Online
 	</notification>
 	<notification name="FriendOffline">
-		[FIRST] [LAST] è Offline
+		[NAME] è Offline
 	</notification>
 	<notification name="AddSelfFriend">
 		Anche se sei molto simpatico, non puoi aggiungere te stesso all&apos;elenco degli amici.
@@ -2105,9 +2105,6 @@ Questo potrebbe incidere sulla tua password.
 	<notification name="CannotRemoveProtectedCategories">
 		Non è possibile rimuovere le categorie protette.
 	</notification>
-	<notification name="OfferedCard">
-		Hai offerto un biglietto da visita a [FIRST] [LAST]
-	</notification>
 	<notification name="UnableToBuyWhileDownloading">
 		Impossibile acquistare l&apos;oggetto durante il download dei dati.
 Riprova.
@@ -2223,7 +2220,7 @@ Reinstalla il plugin o contatta il venditore se continui ad avere questi problem
 		Gli oggetti che possiedi sul terreno selezionato ti sono stati restituiti nell&apos;inventario.
 	</notification>
 	<notification name="OtherObjectsReturned">
-		Gli oggetti selezionati sul terreno che è di proprietà di [FIRST] [LAST] sono stati restituiti nel suo inventario.
+		Gli oggetti selezionati sul terreno che è di proprietà di [NAME] sono stati restituiti nel suo inventario.
 	</notification>
 	<notification name="OtherObjectsReturned2">
 		Sono stati restituiti al proprietario gli oggetti selezionati sul lotto nella terra di proprietà del residente &apos;[NAME]&apos;.
@@ -2433,7 +2430,7 @@ Riprova tra qualche istante.
 		Offerta di amicizia rifiutata.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] ti offre il suo biglietto da visita.
+		[NAME] ti offre il suo biglietto da visita.
 Questo sarà aggiunto nel tuo inventario come segnalibro per consentirti di inviare rapidamente messaggi IM a questo residente.
 		<form name="form">
 			<button name="Accept" text="Accetta"/>
@@ -2493,7 +2490,7 @@ Concedi questa richiesta?
 		</form>
 	</notification>
 	<notification name="ScriptDialog">
-		[FIRST] [LAST] &apos;[TITLE]&apos;
+		[NAME] &apos;&lt;nolink&gt;[TITLE]&lt;/nolink&gt;&apos;
 [MESSAGE]
 		<form name="form">
 			<button name="Ignore" text="Ignora"/>
@@ -2537,13 +2534,13 @@ Clicca su Accetta per unirti alla chiamata oppure su Declina to declinare l&apos
 		</form>
 	</notification>
 	<notification name="AutoUnmuteByIM">
-		[FIRST] [LAST] ha ricevuto un IM ed è stato automaticamente sbloccato.
+		[NAME] ha ricevuto un IM ed è stato automaticamente sbloccato.
 	</notification>
 	<notification name="AutoUnmuteByMoney">
-		[FIRST] [LAST] ha ricevuto del denaro e pertanto è stato automaticamente sbloccato.
+		[NAME] ha ricevuto del denaro e pertanto è stato automaticamente sbloccato.
 	</notification>
 	<notification name="AutoUnmuteByInventory">
-		A [FIRST] [LAST] è stato offerto un elemento dell&apos;Inventario e pertanto è stato automaticamente sbloccato.
+		A [NAME] è stato offerto un elemento dell&apos;Inventario e pertanto è stato automaticamente sbloccato.
 	</notification>
 	<notification name="VoiceInviteGroup">
 		[NAME] si è aggiunto alla chiamata in chat vocale con il gruppo [GROUP].
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index 9dbfc2b79c9851acc3fe9d559ad8819c6a9d5744..dfe635182e60ccf3090e6ab955fc30000213e574 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -3478,7 +3478,7 @@ Se il messaggio persiste, contatta [SUPPORT_SITE].
 		Sei l&apos;unico utente di questa sessione.
 	</string>
 	<string name="offline_message">
-		[FIRST] [LAST] è offline.
+		[NAME] è offline.
 	</string>
 	<string name="invite_message">
 		Clicca il tasto [BUTTON NAME] per accettare/connetterti a questa voice chat.
diff --git a/indra/newview/skins/default/xui/ja/floater_bumps.xml b/indra/newview/skins/default/xui/ja/floater_bumps.xml
index 8a1e19b852928ca35ee1cde81f29fdef59dad3a4..c7e4dd348fb704665b65572f9b6fd530aa5eb459 100644
--- a/indra/newview/skins/default/xui/ja/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/ja/floater_bumps.xml
@@ -4,19 +4,19 @@
 		検出なし
 	</floater.string>
 	<floater.string name="bump">
-		[TIME]  [FIRST] [LAST]が、あなたにぶつかりました。
+		[TIME]  [NAME]が、あなたにぶつかりました。
 	</floater.string>
 	<floater.string name="llpushobject">
-		[TIME]  [FIRST] [LAST]が、スクリプトであなたをプッシュしました。
+		[TIME]  [NAME]が、スクリプトであなたをプッシュしました。
 	</floater.string>
 	<floater.string name="selected_object_collide">
-		[TIME]  [FIRST] [LAST]が、オブジェクトをあなたに当てました。
+		[TIME]  [NAME]が、オブジェクトをあなたに当てました。
 	</floater.string>
 	<floater.string name="scripted_object_collide">
-		[TIME]  [FIRST] [LAST]が、スクリプト・オブジェクトをあなたに当てました。
+		[TIME]  [NAME]が、スクリプト・オブジェクトをあなたに当てました。
 	</floater.string>
 	<floater.string name="physical_object_collide">
-		[TIME]  [FIRST] [LAST]が、物理オブジェクトをあなたに当てました。
+		[TIME]  [NAME]が、物理オブジェクトをあなたに当てました。
 	</floater.string>
 	<floater.string name="timeStr">
 		[[hour,datetime,slt]:[min,datetime,slt]]
diff --git a/indra/newview/skins/default/xui/ja/floater_pay.xml b/indra/newview/skins/default/xui/ja/floater_pay.xml
index 39bc37bc6c2e9beac84be7e3718750eecfb7dc4e..83a3c641f9a75b58c99c7f63dae0726b1d56f74a 100644
--- a/indra/newview/skins/default/xui/ja/floater_pay.xml
+++ b/indra/newview/skins/default/xui/ja/floater_pay.xml
@@ -11,7 +11,7 @@
 	</text>
 	<icon name="icon_person" tool_tip="住人"/>
 	<text name="payee_name">
-		[FIRST] [LAST]
+		Test Name That Is Extremely Long To Check Clipping
 	</text>
 	<button label="L$1" label_selected="L$1" name="fastpay 1"/>
 	<button label="L$5" label_selected="L$5" name="fastpay 5"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_pay_object.xml b/indra/newview/skins/default/xui/ja/floater_pay_object.xml
index ffd57ab67b5f53a1abf38f5d0f0e169f7e1e2ff5..637ad496efab8d712e9a32e44caea39e3853dd5c 100644
--- a/indra/newview/skins/default/xui/ja/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/ja/floater_pay_object.xml
@@ -8,7 +8,7 @@
 	</string>
 	<icon name="icon_person" tool_tip="住人"/>
 	<text name="payee_name">
-		[FIRST] [LAST]
+		Ericacita Moostopolison
 	</text>
 	<text name="object_name_label">
 		オブジェクトを介して:
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 93d664490203c28541d3447a1ded8d3d046d2ca8..c0af0e03ff2edfddb4ddeb85b97272b97703b3fe 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -2082,10 +2082,10 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 		件名: [SUBJECT]、メッセージ: [MESSAGE]
 	</notification>
 	<notification name="FriendOnline">
-		[FIRST] [LAST] はオンラインです
+		[NAME] はオンラインです
 	</notification>
 	<notification name="FriendOffline">
-		[FIRST] [LAST] はオフラインです
+		[NAME] はオフラインです
 	</notification>
 	<notification name="AddSelfFriend">
 		残念ながら自分自身をフレンド登録することはできません。
@@ -2153,9 +2153,6 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 	<notification name="CannotRemoveProtectedCategories">
 		保護されたカテゴリは削除できません。
 	</notification>
-	<notification name="OfferedCard">
-		[FIRST] [LAST] にコーリングカードを送りました。
-	</notification>
 	<notification name="UnableToBuyWhileDownloading">
 		オブジェクトデータのダウンロード中は購入できません。
 もう一度お試しください。
@@ -2273,7 +2270,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 	</notification>
 	<notification name="OtherObjectsReturned">
 		選択した土地の区画上にあった
- [FIRST] [LAST]
+ [NAME]
  が所有するオブジェクトは、すべて所有者の「持ち物」に返却されました。
 	</notification>
 	<notification name="OtherObjectsReturned2">
@@ -2488,7 +2485,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 		フレンドの登録依頼が拒否されました。
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] がコーリングカードを渡そうとしています。
+		[NAME] がコーリングカードを渡そうとしています。
 あなたの「持ち物」にブックマークが追加され、この住人に素早く IM を送ることができます。
 		<form name="form">
 			<button name="Accept" text="受け入れる"/>
@@ -2548,7 +2545,7 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 		</form>
 	</notification>
 	<notification name="ScriptDialog">
-		[FIRST] [LAST] の「 [TITLE] 」
+		[NAME] の「 &lt;nolink&gt;[TITLE]&lt;/nolink&gt; 」
 [MESSAGE]
 		<form name="form">
 			<button name="Ignore" text="無視する"/>
@@ -2592,13 +2589,13 @@ M キーを押して変更します。
 		</form>
 	</notification>
 	<notification name="AutoUnmuteByIM">
-		[FIRST] [LAST] はインスタントメッセージを受け取り、自動的にブロックが解除されました。
+		[NAME] はインスタントメッセージを受け取り、自動的にブロックが解除されました。
 	</notification>
 	<notification name="AutoUnmuteByMoney">
-		[FIRST] [LAST] はお金を受け取り、自動的にブロックが解除されました。
+		[NAME] はお金を受け取り、自動的にブロックが解除されました。
 	</notification>
 	<notification name="AutoUnmuteByInventory">
-		[FIRST] [LAST] はアイテムを受け取り、自動的にブロックが解除されました。
+		[NAME] はアイテムを受け取り、自動的にブロックが解除されました。
 	</notification>
 	<notification name="VoiceInviteGroup">
 		[NAME] は [GROUP] のボイスチャットコールに参加しました。
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_profile.xml b/indra/newview/skins/default/xui/ja/panel_edit_profile.xml
index 2aba4edc0d6c9afae404350d5dd1585834ee288d..334cf54a4dd24f58e3c55b23c91df9782fc09e63 100644
--- a/indra/newview/skins/default/xui/ja/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/ja/panel_edit_profile.xml
@@ -46,7 +46,7 @@
 				<text name="my_account_link" value="[[URL] マイアカウントに移動]"/>
 				<text name="title_partner_text" value="マイパートナー:"/>
 				<panel name="partner_data_panel">
-					<name_box initial_value="(取得中)" name="partner_text" value="[FIRST] [LAST]"/>
+					<name_box initial_value="(取得中)" name="partner_text"/>
 				</panel>
 				<text name="partner_edit_link" value="[[URL] 編集]" width="100"/>
 			</panel>
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 92bbedaee52e06dea5bbe63088ba4cf8c2cb54ee..187f21257a33755e89a8f57faae26f910ea36dc8 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -3574,7 +3574,7 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 		このセッションにいるユーザーはあなただけです。
 	</string>
 	<string name="offline_message">
-		[FIRST] [LAST] はオフラインです。
+		[NAME] はオフラインです。
 	</string>
 	<string name="invite_message">
 		このボイスチャットに応答・接続する場合は、[BUTTON NAME] をクリックしてください。
diff --git a/indra/newview/skins/default/xui/nl/floater_bumps.xml b/indra/newview/skins/default/xui/nl/floater_bumps.xml
index df9a99d62ef8bfb81cbdb4bdfc50622e3713529b..516b59658d9d421dae23a6c55262c98999558382 100644
--- a/indra/newview/skins/default/xui/nl/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/nl/floater_bumps.xml
@@ -4,18 +4,18 @@
 		Geen gedetecteerd
 	</string>
 	<string name="bump">
-		[TIME]  [FIRST] [LAST] botste tegen u aan
+		[TIME]  [NAME] botste tegen u aan
 	</string>
 	<string name="llpushobject">
-		[TIME]  [FIRST] [LAST] duwde u met een script
+		[TIME]  [NAME] duwde u met een script
 	</string>
 	<string name="selected_object_collide">
-		[TIME]  [FIRST] [LAST] raakte u met een object
+		[TIME]  [NAME] raakte u met een object
 	</string>
 	<string name="scripted_object_collide">
-		[TIME]  [FIRST] [LAST] raakte u met een gescript object
+		[TIME]  [NAME] raakte u met een gescript object
 	</string>
 	<string name="physical_object_collide">
-		[TIME]  [FIRST] [LAST] raakte u met een fysiek object
+		[TIME]  [NAME] raakte u met een fysiek object
 	</string>
 </floater>
diff --git a/indra/newview/skins/default/xui/nl/floater_pay.xml b/indra/newview/skins/default/xui/nl/floater_pay.xml
index 4018ebdc93b0f977083a569260f446ff33c4099e..f2b34d78d727e15fadfad7c7e8be6c6578c93799 100644
--- a/indra/newview/skins/default/xui/nl/floater_pay.xml
+++ b/indra/newview/skins/default/xui/nl/floater_pay.xml
@@ -10,7 +10,7 @@
 		Betaal inwoner:
 	</text>
 	<text name="payee_name" left="110">
-		[FIRST] [LAST]
+		Test Name That Is Extremely Long To Check Clipping
 	</text>
 	<text name="fastpay text">
 		Snel betalen:
diff --git a/indra/newview/skins/default/xui/nl/floater_pay_object.xml b/indra/newview/skins/default/xui/nl/floater_pay_object.xml
index d3826648f23a37acc8d3219f9345aa200340740b..11fa6d4a44d6c90e4ecff95a7092e6a37d875461 100644
--- a/indra/newview/skins/default/xui/nl/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/nl/floater_pay_object.xml
@@ -7,7 +7,7 @@
 		Betaal inwoner:
 	</text>
 	<text name="payee_name" left="100" width="200">
-		[FIRST] [LAST]
+		Ericacita Moostopolison
 	</text>
 	<text name="object_name_label" left="5" width="90" halign="left">
 		Via object:
diff --git a/indra/newview/skins/default/xui/nl/floater_tools.xml b/indra/newview/skins/default/xui/nl/floater_tools.xml
index d49ffc2f51225369b1385b6bd5c40ccaa7b3c81a..4ffe675831579ddd98bfd2299914a398b9cc6b4d 100644
--- a/indra/newview/skins/default/xui/nl/floater_tools.xml
+++ b/indra/newview/skins/default/xui/nl/floater_tools.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="BOUWEN" height="587">
+<floater name="toolbox floater" title="" short_title="BOUWEN" height="592">
 	<button label="" label_selected="" name="button focus" tool_tip="Focus"/>
 	<button label="" label_selected="" name="button move" tool_tip="Verplaats"/>
 	<button label="" label_selected="" name="button edit" tool_tip="Bewerk"/>
@@ -81,13 +81,13 @@
 	<text name="Strength:">
 		Sterkte
 	</text>
-	<text name="obj_count" top_pad="15">
+	<text name="obj_count" top_pad="20">
 		Geselecteerde objecten: [COUNT]
 	</text>
 	<text name="prim_count">
 		primitieven: [COUNT]
 	</text>
-	<tab_container name="Object Info Tabs" tab_max_width="62" tab_min_width="30" top="180">
+	<tab_container name="Object Info Tabs" tab_max_width="62" tab_min_width="30" top="185">
 		<panel label="Algemeen" name="General">
 			<text name="Name:">
 				Naam:
@@ -115,19 +115,19 @@
 			<text name="Group Name Proxy">
 				De Lindens
 			</text>
-			<button label="Instellen..." label_selected="Instellen..." name="button set group" left_pad="13"/>
+			<button label="Instellen..." label_selected="Instellen..." name="button set group"/>
 			<text name="Permissions:">
 				Permissies:
 			</text>
 
-			<check_box label="Deel met groep" name="checkbox share with group" tool_tip="Alle leden van de ingestelde groep toestaan om te delen en uw permissies voor dit object te gebruiken. U moet &apos;Overdragen&apos; om rolbeperkingen in te schakelen." left="100"/>
+			<check_box label="Deel met groep" name="checkbox share with group" tool_tip="Alle leden van de ingestelde groep toestaan om te delen en uw permissies voor dit object te gebruiken. U moet &apos;Overdragen&apos; om rolbeperkingen in te schakelen."/>
 			<string name="text deed continued">
 				Overdragen...
 			</string>
 			<string name="text deed">
 				Overdragen
 			</string>
-			<button label="Overdragen..." label_selected="Overdragen..." name="button deed" tool_tip="Groepgedeelde objecten kunnen door een groepofficier worden overgedragen" left_pad="19"/>
+			<button label="Overdragen..." label_selected="Overdragen..." name="button deed" tool_tip="Groepgedeelde objecten kunnen door een groepofficier worden overgedragen"/>
 			<check_box label="Iedereen mag verplaatsen" name="checkbox allow everyone move"/>
 			<check_box label="Iedereen mag kopiëren" name="checkbox allow everyone copy"/>
 			<check_box label="Toon in zoeken" name="search_check" tool_tip="Laat mensen dit object zien in zoekresultaten"/>
diff --git a/indra/newview/skins/default/xui/nl/notifications.xml b/indra/newview/skins/default/xui/nl/notifications.xml
index b4b56a035ff55204ce95f82819382f57d08f8a3b..be0c17d2ff8a7145f51aca577a62311a38bbe875 100644
--- a/indra/newview/skins/default/xui/nl/notifications.xml
+++ b/indra/newview/skins/default/xui/nl/notifications.xml
@@ -2478,9 +2478,6 @@ Wilt u de [SECOND_LIFE] website bezoeken om dit in te stellen?
 	<notification name="CannotRemoveProtectedCategories">
 		U kunt geen beschermde categorieën verwijderen.
 	</notification>
-	<notification name="OfferedCard">
-		U heeft een visitekaartje aangeboden aan [FIRST] [LAST]
-	</notification>
 	<notification name="UnableToBuyWhileDownloading">
 		Niet mogelijk te kopen terwijl objectdata wordt gedownload. Probeer het alstublieft opnieuw.
 	</notification>
@@ -2780,7 +2777,7 @@ Probeer het alstublieft opnieuw over enkele ogenblikken.
 		[NAME] heeft uw vriendschapsaanbod afgewezen.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] biedt zijn/haar visitekaartje aan.
+		[NAME] biedt zijn/haar visitekaartje aan.
 Dit zal een bladwijzer in uw inventaris toevoegen zodat u deze inwoner snel kunt een IM kunt sturen.
 		<form name="form">
 			<button name="Accept" text="Accepteren"/>
diff --git a/indra/newview/skins/default/xui/nl/panel_edit_profile.xml b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml
index 172395e20a27b6ca938f09d58240b33ee8ac636e..fffdb9e8dfd9b71e656aff5a575ea7f874fb3c1d 100644
--- a/indra/newview/skins/default/xui/nl/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/nl/panel_edit_profile.xml
@@ -35,7 +35,7 @@
       </panel>
         <text name="title_partner_text" value="Partner:"/>
         <panel name="partner_data_panel">
-            <text name="partner_text" value="[FIRST] [LAST]"/>
+            <text name="partner_text"/>
          </panel>
       <text name="text_box3">
 	Antwoord bij Niet Storen:
diff --git a/indra/newview/skins/default/xui/nl/strings.xml b/indra/newview/skins/default/xui/nl/strings.xml
index 844945913fb31a86cd49de3a36f5585b8f95f6cb..07265d27162a5d65edc62c7ae49144a6b1f9c557 100644
--- a/indra/newview/skins/default/xui/nl/strings.xml
+++ b/indra/newview/skins/default/xui/nl/strings.xml
@@ -3211,7 +3211,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
 		U bent de enige gebruiker in deze sessie.
 	</string>
 	<string name="offline_message">
-		[FIRST] [LAST] is offline.
+		[NAME] is offline.
 	</string>
 	<string name="invite_message">
 		Klik de [BUTTON NAME] knop om deze voicechat te accepteren/verbinden.
diff --git a/indra/newview/skins/default/xui/pl/floater_tools.xml b/indra/newview/skins/default/xui/pl/floater_tools.xml
index 8c77df92487610984fab5c30186d21841ebdd481..7c1ced0eaee7349f6de61cef899a7760a383da45 100644
--- a/indra/newview/skins/default/xui/pl/floater_tools.xml
+++ b/indra/newview/skins/default/xui/pl/floater_tools.xml
@@ -307,7 +307,7 @@
 				<combo_box.item label="Kwadrat" name="Square"/>
 				<combo_box.item label="Trójkąt" name="Triangle"/>
 			</combo_box>
-			<text name="text twist">
+			<text name="text twist" left_delta="-5" width="160">
 				Skręcenie (początek/koniec)
 			</text>
 			<spinner label="P" name="Twist Begin"/>
diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml
index 7e5ed4347553c1b58c99c15db92bc64c17f22b90..8151c7eb938304846d51f890b8b1d769879b4d9f 100644
--- a/indra/newview/skins/default/xui/pl/notifications.xml
+++ b/indra/newview/skins/default/xui/pl/notifications.xml
@@ -2440,7 +2440,7 @@ Spróbuj ponowanie za kilka minut.
 		Propozycja znajomości została odrzucona.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] daje Tobie swoją wizytówkę.
+		[NAME] daje Tobie swoją wizytówkę.
 Wizytówka będzie znajdowała się w Szafie i umożliwi szybkie wysłanie IM do tego Rezydenta.
 		<form name="form">
 			<button name="Accept" text="Zaakceptuj"/>
diff --git a/indra/newview/skins/default/xui/pl/panel_edit_profile.xml b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml
index dad8bca1830342d98d6f31b44d7a22a4c16e032a..c409666ec92b307772d1a1673ffd95064197e0c9 100644
--- a/indra/newview/skins/default/xui/pl/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/pl/panel_edit_profile.xml
@@ -46,7 +46,7 @@
 				<text name="my_account_link" value="[[URL] idź do dashboard]"/>
 				<text name="title_partner_text" value="Partner:"/>
 				<panel name="partner_data_panel">
-					<text initial_value="(wyszukiwanie)" name="partner_text" value="[FIRST] [LAST]"/>
+					<text initial_value="(wyszukiwanie)" name="partner_text"/>
 				</panel>
 				<text name="partner_edit_link" value="[[URL] Edytuj]"/>
 			</panel>
diff --git a/indra/newview/skins/default/xui/pt/floater_im.xml b/indra/newview/skins/default/xui/pt/floater_im.xml
deleted file mode 100644
index c81d0dd7ef37d079c0641a4044a9cc20a11d28a0..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/pt/floater_im.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<multi_floater name="im_floater" title="Mensagem Instantânea">
-	<string name="only_user_message">
-		Você é o único residente nesta sessão
-	</string>
-	<string name="offline_message">
-		[FIRST] [LAST] está offline.
-	</string>
-	<string name="invite_message">
-		Clique no botão [BUTTON NAME] para aceitar/ conectar a este bate-papo em voz.
-	</string>
-	<string name="muted_message">
-		Você bloqueou este residente.  Se quiser retirar o bloqueio, basta enviar uma mensagem.
-	</string>
-	<string name="generic_request_error">
-		Erro na requisição, por favor, tente novamente.
-	</string>
-	<string name="insufficient_perms_error">
-		Você não tem permissões suficientes.
-	</string>
-	<string name="session_does_not_exist_error">
-		A sessão deixou de existir
-	</string>
-	<string name="no_ability_error">
-		Você não possui esta habilidade.
-	</string>
-	<string name="not_a_mod_error">
-		Você não é um moderador de sessão.
-	</string>
-	<string name="muted_error">
-		Um moderador do grupo desabilitou seu bate-papo em texto.
-	</string>
-	<string name="add_session_event">
-		Não foi possível adicionar residentes ao bate-papo com [RECIPIENT].
-	</string>
-	<string name="message_session_event">
-		Não foi possível enviar sua mensagem na sessão de bate- papo com [RECIPIENT].
-	</string>
-	<string name="removed_from_group">
-		Você foi removido do grupo.
-	</string>
-	<string name="close_on_no_ability">
-		Você não possui mais a habilidade de estar na sessão de bate-papo.
-	</string>
-</multi_floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml
index 2925e286edf255d9db2317538d7a82279445212f..bd5fbf80d13ece103f164ebab873ac30e2188147 100644
--- a/indra/newview/skins/default/xui/pt/floater_tools.xml
+++ b/indra/newview/skins/default/xui/pt/floater_tools.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" short_title="BUILD TOOLS" title="" width="288">
+<floater name="toolbox floater" short_title="BUILD TOOLS" title="">
 	<floater.string name="status_rotate">
 		Arrastar as faixas coloridas para girar o objeto
 	</floater.string>
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index 466a24742d0f2ad20de56c234fae1c2b6d373307..76399e966c589819953f330518be940ce017a69d 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -2448,7 +2448,7 @@ Cada um pode ver o status do outro (definição padrão).
 		Oferta de amizada aceita.
 	</notification>
 	<notification name="OfferCallingCard">
-		[FIRST] [LAST] estão te oferecendo um cartão de visita.
+		[NAME] estão te oferecendo um cartão de visita.
 Ele colocará um item de inventário, para você possa contatá-lo facilmente.
 		<form name="form">
 			<button name="Accept" text="Aceitar"/>
@@ -2552,13 +2552,13 @@ Clique em Aceitar para atender ou em Recusar para recusar este convite.  Clique
 		</form>
 	</notification>
 	<notification name="AutoUnmuteByIM">
-		[FIRST] recebeu uma MI e foi desbloqueado(a) automaticamente.
+		[NAME] recebeu uma MI e foi desbloqueado(a) automaticamente.
 	</notification>
 	<notification name="AutoUnmuteByMoney">
-		[FIRST] recebeu dinheiro e foi desbloqueado(a) automaticamente.
+		[NAME] recebeu dinheiro e foi desbloqueado(a) automaticamente.
 	</notification>
 	<notification name="AutoUnmuteByInventory">
-		[FIRST] recebeu dinheiro e foi desbloqueado(a) automaticamente.
+		[NAME] recebeu dinheiro e foi desbloqueado(a) automaticamente.
 	</notification>
 	<notification name="VoiceInviteGroup">
 		[NAME] atendeu uma ligação de bate-papo de voz com o grupo [GROUP].  
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index db50b896204988faff21ca5d606e97d086bcc715..b902c7ab09a0cb211efd432a321b09b7b885849a 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -48,6 +48,9 @@ const std::string VIEWERLOGIN_GRIDLABEL("viewerlogin_grid");
 
 const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno");
 
+const std::string VIEWERLOGIN_CHANNEL("invalid_channel");
+const std::string VIEWERLOGIN_VERSION_CHANNEL("invalid_version");
+
 // Link seams.
 
 //-----------------------------------------------------------------------------
@@ -160,7 +163,6 @@ std::string LLGridManager::getAppSLURLBase(const std::string& grid_name)
 //-----------------------------------------------------------------------------
 #include "../llviewercontrol.h"
 LLControlGroup gSavedSettings("Global");
-std::string gCurrentVersion = "invalid_version";
 
 LLControlGroup::LLControlGroup(const std::string& name) :
 	LLInstanceTracker<LLControlGroup, std::string>(name){}
@@ -177,6 +179,10 @@ BOOL LLControlGroup::declareString(const std::string& name, const std::string &i
 #include "lluicolortable.h"
 void LLUIColorTable::saveUserSettings(void)const {}
 
+//-----------------------------------------------------------------------------
+#include "../llversioninfo.h"
+const std::string &LLVersionInfo::getVersionAndChannel() { return VIEWERLOGIN_VERSION_CHANNEL; }
+const std::string &LLVersionInfo::getChannel() { return VIEWERLOGIN_CHANNEL; }
 
 //-----------------------------------------------------------------------------
 #include "llnotifications.h"
@@ -290,7 +296,6 @@ namespace tut
 			gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE);
 			gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE);
 			gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE);
-			gSavedSettings.declareString("VersionChannelName", "test_version_string", "", FALSE);
 			gSavedSettings.declareString("NextLoginLocation", "", "", FALSE);
 			gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE);
 
diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8855a24eadefde9b98dc685503bd2013493357ab
--- /dev/null
+++ b/indra/newview/tests/llversioninfo_test.cpp
@@ -0,0 +1,114 @@
+/** 
+ * @file llversioninfo_test.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../llversioninfo.h"
+#include "llversionviewer.h"
+
+namespace tut
+{
+    struct versioninfo
+    {
+		versioninfo()
+			: mResetChannel("Reset Channel")
+		{
+			std::ostringstream stream;
+			stream << LL_VERSION_MAJOR << "."
+				   << LL_VERSION_MINOR << "."
+				   << LL_VERSION_PATCH << "."
+				   << LL_VERSION_BUILD;
+			mVersion = stream.str();
+			stream.str("");
+
+			stream << LL_VERSION_MAJOR << "."
+				   << LL_VERSION_MINOR << "."
+				   << LL_VERSION_PATCH;
+			mShortVersion = stream.str();
+			stream.str("");
+
+			stream << mVersion
+				   << " "
+				   << LL_CHANNEL;
+			mVersionAndChannel = stream.str();
+			stream.str("");
+
+			stream << mVersion
+				   << " "
+				   << mResetChannel;
+			mResetVersionAndChannel = stream.str();
+		}
+		std::string mResetChannel;
+		std::string mVersion;
+		std::string mShortVersion;
+		std::string mVersionAndChannel;
+		std::string mResetVersionAndChannel;
+    };
+    
+	typedef test_group<versioninfo> versioninfo_t;
+	typedef versioninfo_t::object versioninfo_object_t;
+	tut::versioninfo_t tut_versioninfo("LLVersionInfo");
+
+	template<> template<>
+	void versioninfo_object_t::test<1>()
+	{
+		ensure_equals("Major version", 
+					  LLVersionInfo::getMajor(), 
+					  LL_VERSION_MAJOR);
+		ensure_equals("Minor version", 
+					  LLVersionInfo::getMinor(), 
+					  LL_VERSION_MINOR);
+		ensure_equals("Patch version", 
+					  LLVersionInfo::getPatch(), 
+					  LL_VERSION_PATCH);
+		ensure_equals("Build version", 
+					  LLVersionInfo::getBuild(), 
+					  LL_VERSION_BUILD);
+		ensure_equals("Channel version", 
+					  LLVersionInfo::getChannel(), 
+					  LL_CHANNEL);
+
+		ensure_equals("Version String", 
+					  LLVersionInfo::getVersion(), 
+					  mVersion);
+		ensure_equals("Short Version String", 
+					  LLVersionInfo::getShortVersion(), 
+					  mShortVersion);
+		ensure_equals("Version and channel String", 
+					  LLVersionInfo::getVersionAndChannel(), 
+					  mVersionAndChannel);
+
+		LLVersionInfo::resetChannel(mResetChannel);
+		ensure_equals("Reset channel version", 
+					  LLVersionInfo::getChannel(), 
+					  mResetChannel);
+
+		ensure_equals("Reset Version and channel String", 
+					  LLVersionInfo::getVersionAndChannel(), 
+					  mResetVersionAndChannel);
+	}
+}
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
index a0f1d1c3c34499998e1cc6a0f1abd3679dd6fe67..b425b50c8bd36a2be38d959b586c880bdb867ceb 100644
--- a/indra/newview/tests/llviewerhelputil_test.cpp
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -72,16 +72,13 @@ static void substitute_string(std::string &input, const std::string &search, con
 	}
 }
 
-class LLAgent
-{
-public:
-	LLAgent() {}
-	~LLAgent() {}
-#ifdef __GNUC__
-	__attribute__ ((noinline))
-#endif
-	bool isGodlike() const { return FALSE; }
-};
+#include "../llagent.h"
+LLAgent::LLAgent() : mAgentAccess(gSavedSettings) { }
+LLAgent::~LLAgent() { }
+bool LLAgent::isGodlike() const { return FALSE; }
+LLAgentAccess::LLAgentAccess(LLControlGroup& settings) : mSavedSettings(settings) { }
+LLUIColor::LLUIColor() {}
+
 LLAgent gAgent;
 
 std::string LLWeb::expandURLSubstitutions(const std::string &url,
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 6861f02bfbad6876bd36d6fb3c2286a2c1bffc0d..1bc118139fb57ec3b8db703cb17e0935dc06e157 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -247,6 +247,8 @@ def construct(self):
         
         self.disable_manifest_check()
 
+        self.path(src="../viewer_components/updater/scripts/windows/update_install.bat", dst="update_install.bat")
+
         # Get shared libs from the shared libs staging directory
         if self.prefix(src=os.path.join(os.pardir, 'sharedlibs', self.args['configuration']),
                        dst=""):
@@ -572,6 +574,8 @@ def construct(self):
             # copy additional libs in <bundle>/Contents/MacOS/
             self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib")
 
+            self.path("../viewer_components/updater/scripts/darwin/update_install", "MacOS/update_install")
+
             # most everything goes in the Resources directory
             if self.prefix(src="", dst="Resources"):
                 super(DarwinManifest, self).construct()
@@ -743,6 +747,11 @@ def package_finish(self):
             devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
             volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
 
+            if devfile != '/dev/disk1':
+                # adding more debugging info based upon nat's hunches to the
+                # logs to help track down 'SetFile -a V' failures -brad
+                print "WARNING: 'SetFile -a V' command below is probably gonna fail"
+
             # Copy everything in to the mounted .dmg
 
             if self.default_channel() and not self.default_grid():
@@ -842,6 +851,8 @@ def construct(self):
             # recurse
             self.end_prefix("res-sdl")
 
+        self.path("../viewer_components/updater/scripts/linux/update_install", "bin/update_install")
+
         # plugins
         if self.prefix(src="", dst="bin/llplugin"):
             self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so")
@@ -870,7 +881,7 @@ def package_finish(self):
 
         if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():
             print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"
-            self.run_command("find %(d)r/bin %(d)r/lib -type f | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
+            self.run_command("find %(d)r/bin %(d)r/lib -type f \\! -name update_install | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure
 
         # Fix access permissions
         self.run_command("""
@@ -897,6 +908,9 @@ def package_finish(self):
                         'dir': self.get_build_prefix(),
                         'inst_name': installer_name,
                         'inst_path':self.build_path_of(installer_name)})
+            else:
+                print "Skipping %s.tar.bz2 for non-Release build (%s)" % \
+                      (installer_name, self.args['buildtype'])
         finally:
             self.run_command("mv %(inst)s %(dst)s" % {
                 'dst': self.get_dst_prefix(),
diff --git a/indra/viewer_components/CMakeLists.txt b/indra/viewer_components/CMakeLists.txt
index 0993b64b14781415b4de7a1b20488a7182487231..74c9b4568d97b9d46cbef7a481b8c25e04632c43 100644
--- a/indra/viewer_components/CMakeLists.txt
+++ b/indra/viewer_components/CMakeLists.txt
@@ -1,4 +1,4 @@
 # -*- cmake -*-
 
 add_subdirectory(login)
-
+add_subdirectory(updater)
diff --git a/indra/viewer_components/updater/CMakeLists.txt b/indra/viewer_components/updater/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0e288bb4963a52f91620cea48a01e7310659f92b
--- /dev/null
+++ b/indra/viewer_components/updater/CMakeLists.txt
@@ -0,0 +1,82 @@
+# -*- cmake -*-
+
+project(updater_service)
+
+include(00-Common)
+if(LL_TESTS)
+  include(LLAddBuildTest)
+endif(LL_TESTS)
+include(CMakeCopyIfDifferent)
+include(CURL)
+include(LLCommon)
+include(LLMessage)
+include(LLPlugin)
+include(LLVFS)
+
+include_directories(
+    ${LLCOMMON_INCLUDE_DIRS}
+    ${LLMESSAGE_INCLUDE_DIRS}
+    ${LLPLUGIN_INCLUDE_DIRS}
+	${LLVFS_INCLUDE_DIRS}
+	${CURL_INCLUDE_DIRS}
+    )
+
+set(updater_service_SOURCE_FILES
+    llupdaterservice.cpp
+    llupdatechecker.cpp
+    llupdatedownloader.cpp
+    llupdateinstaller.cpp
+    )
+
+set(updater_service_HEADER_FILES
+    llupdaterservice.h
+    llupdatechecker.h
+    llupdatedownloader.h
+    llupdateinstaller.h
+    )
+
+set_source_files_properties(${updater_service_HEADER_FILES}
+                            PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND 
+    updater_service_SOURCE_FILES 
+    ${updater_service_HEADER_FILES} 
+    )
+
+add_library(llupdaterservice
+            ${updater_service_SOURCE_FILES}
+            )
+
+target_link_libraries(llupdaterservice
+    ${LLCOMMON_LIBRARIES}
+    ${LLMESSAGE_LIBRARIES}
+    ${LLPLUGIN_LIBRARIES}
+	${LLVFS_LIBRARIES}
+    )
+
+if(LL_TESTS)
+  SET(llupdater_service_TEST_SOURCE_FILES
+      llupdaterservice.cpp
+      )
+
+# *NOTE:Mani - I was trying to use the preprocessor seam to mock out
+#              llifstream (and other) llcommon classes. I didn't work
+#              because of the windows declspec(dllimport)attribute.
+#set_source_files_properties(
+#    llupdaterservice.cpp
+#    PROPERTIES
+#      LL_TEST_ADDITIONAL_CFLAGS "-Dllifstream=llus_mock_llifstream"
+#    )
+
+  LL_ADD_PROJECT_UNIT_TESTS(llupdaterservice "${llupdater_service_TEST_SOURCE_FILES}")
+endif(LL_TESTS)
+
+set(UPDATER_INCLUDE_DIRS 
+  ${LIBS_OPEN_DIR}/viewer_components/updater 
+  CACHE INTERNAL ""
+)
+
+set(UPDATER_LIBRARIES 
+  llupdaterservice
+  CACHE INTERNAL ""
+)
diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c6aa9b0f110d1422e4c665c7e6532cc4bc91684d
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatechecker.cpp
@@ -0,0 +1,194 @@
+/** 
+ * @file llupdaterservice.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include <stdexcept>
+#include <boost/format.hpp>
+#include "llhttpclient.h"
+#include "llsd.h"
+#include "llupdatechecker.h"
+#include "lluri.h"
+
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+
+class LLUpdateChecker::CheckError:
+	public std::runtime_error
+{
+public:
+	CheckError(const char * message):
+		std::runtime_error(message)
+	{
+		; // No op.
+	}
+};
+
+
+class LLUpdateChecker::Implementation:
+	public LLHTTPClient::Responder
+{
+public:
+	Implementation(Client & client);
+	~Implementation();
+	void check(std::string const & protocolVersion, std::string const & hostUrl, 
+			   std::string const & servicePath, std::string channel, std::string version);
+	
+	// Responder:
+	virtual void completed(U32 status,
+						   const std::string & reason,
+						   const LLSD& content);
+	virtual void error(U32 status, const std::string & reason);
+	
+private:	
+	static const char * sProtocolVersion;
+	
+	Client & mClient;
+	LLHTTPClient mHttpClient;
+	bool mInProgress;
+	std::string mVersion;
+	
+	std::string buildUrl(std::string const & protocolVersion, std::string const & hostUrl, 
+						 std::string const & servicePath, std::string channel, std::string version);
+
+	LOG_CLASS(LLUpdateChecker::Implementation);
+};
+
+
+
+// LLUpdateChecker
+//-----------------------------------------------------------------------------
+
+
+LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client):
+	mImplementation(new LLUpdateChecker::Implementation(client))
+{
+	; // No op.
+}
+
+
+void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, 
+							std::string const & servicePath, std::string channel, std::string version)
+{
+	mImplementation->check(protocolVersion, hostUrl, servicePath, channel, version);
+}
+
+
+
+// LLUpdateChecker::Implementation
+//-----------------------------------------------------------------------------
+
+
+const char * LLUpdateChecker::Implementation::sProtocolVersion = "v1.0";
+
+
+LLUpdateChecker::Implementation::Implementation(LLUpdateChecker::Client & client):
+	mClient(client),
+	mInProgress(false)
+{
+	; // No op.
+}
+
+
+LLUpdateChecker::Implementation::~Implementation()
+{
+	; // No op.
+}
+
+
+void LLUpdateChecker::Implementation::check(std::string const & protocolVersion, std::string const & hostUrl, 
+											std::string const & servicePath, std::string channel, std::string version)
+{
+	llassert(!mInProgress);
+	
+	if(protocolVersion != sProtocolVersion) throw CheckError("unsupported protocol");
+		
+	mInProgress = true;
+	mVersion = version;
+	std::string checkUrl = buildUrl(protocolVersion, hostUrl, servicePath, channel, version);
+	LL_INFOS("UpdateCheck") << "checking for updates at " << checkUrl << llendl;
+	
+	// The HTTP client will wrap a raw pointer in a boost::intrusive_ptr causing the
+	// passed object to be silently and automatically deleted.  We pass a self-
+	// referential intrusive pointer to which we add a reference to keep the
+	// client from deleting the update checker implementation instance.
+	LLHTTPClient::ResponderPtr temporaryPtr(this);
+	boost::intrusive_ptr_add_ref(temporaryPtr.get());
+	mHttpClient.get(checkUrl, temporaryPtr);
+}
+
+void LLUpdateChecker::Implementation::completed(U32 status,
+							  const std::string & reason,
+							  const LLSD & content)
+{
+	mInProgress = false;	
+	
+	if(status != 200) {
+		LL_WARNS("UpdateCheck") << "html error " << status << " (" << reason << ")" << llendl;
+		mClient.error(reason);
+	} else if(!content.asBoolean()) {
+		LL_INFOS("UpdateCheck") << "up to date" << llendl;
+		mClient.upToDate();
+	} else if(content["required"].asBoolean()) {
+		LL_INFOS("UpdateCheck") << "version invalid" << llendl;
+		LLURI uri(content["url"].asString());
+		mClient.requiredUpdate(content["version"].asString(), uri, content["hash"].asString());
+	} else {
+		LL_INFOS("UpdateCheck") << "newer version " << content["version"].asString() << " available" << llendl;
+		LLURI uri(content["url"].asString());
+		mClient.optionalUpdate(content["version"].asString(), uri, content["hash"].asString());
+	}
+}
+
+
+void LLUpdateChecker::Implementation::error(U32 status, const std::string & reason)
+{
+	mInProgress = false;
+	LL_WARNS("UpdateCheck") << "update check failed; " << reason << llendl;
+	mClient.error(reason);
+}
+
+
+std::string LLUpdateChecker::Implementation::buildUrl(std::string const & protocolVersion, std::string const & hostUrl, 
+													  std::string const & servicePath, std::string channel, std::string version)
+{	
+#ifdef LL_WINDOWS
+	static const char * platform = "win";
+#elif LL_DARWIN
+	static const char * platform = "mac";
+#else
+	static const char * platform = "lnx";
+#endif
+	
+	LLSD path;
+	path.append(servicePath);
+	path.append(protocolVersion);
+	path.append(channel);
+	path.append(version);
+	path.append(platform);
+	return LLURI::buildHTTP(hostUrl, path).asString();
+}
diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h
new file mode 100644
index 0000000000000000000000000000000000000000..cea1f13647dc2275182691c6ac022ab89d075b7d
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatechecker.h
@@ -0,0 +1,82 @@
+/** 
+ * @file llupdatechecker.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATERCHECKER_H
+#define LL_UPDATERCHECKER_H
+
+
+#include <boost/shared_ptr.hpp>
+
+
+//
+// Implements asynchronous checking for updates.
+//
+class LLUpdateChecker {
+public:
+	class Client;
+	class Implementation;
+	
+	// An exception that may be raised on check errors.
+	class CheckError;
+	
+	LLUpdateChecker(Client & client);
+	
+	// Check status of current app on the given host for the channel and version provided.
+	void check(std::string const & protocolVersion, std::string const & hostUrl, 
+			   std::string const & servicePath, std::string channel, std::string version);
+	
+private:
+	boost::shared_ptr<Implementation> mImplementation;
+};
+
+
+class LLURI; // From lluri.h
+
+
+//
+// The client interface implemented by a requestor checking for an update.
+//
+class LLUpdateChecker::Client
+{
+public:
+	// An error occurred while checking for an update.
+	virtual void error(std::string const & message) = 0;
+	
+	// A newer version is available, but the current version may still be used.
+	virtual void optionalUpdate(std::string const & newVersion,
+								LLURI const & uri,
+								std::string const & hash) = 0;
+	
+	// A newer version is available, and the current version is no longer valid. 
+	virtual void requiredUpdate(std::string const & newVersion,
+								LLURI const & uri,
+								std::string const & hash) = 0;
+	
+	// The checked version is up to date; no newer version exists.
+	virtual void upToDate(void) = 0;
+};
+
+
+#endif
diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c17a50e24245aeb3d5846ab5fb569696b744dd7d
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatedownloader.cpp
@@ -0,0 +1,428 @@
+/** 
+ * @file llupdatedownloader.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include <stdexcept>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+#include <curl/curl.h>
+#include "lldir.h"
+#include "llfile.h"
+#include "llmd5.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llthread.h"
+#include "llupdatedownloader.h"
+#include "llupdaterservice.h"
+
+
+class LLUpdateDownloader::Implementation:
+	public LLThread
+{
+public:
+	Implementation(LLUpdateDownloader::Client & client);
+	~Implementation();
+	void cancel(void);
+	void download(LLURI const & uri, std::string const & hash);
+	bool isDownloading(void);
+	size_t onHeader(void * header, size_t size);
+	size_t onBody(void * header, size_t size);
+	void resume(void);
+	
+private:
+	bool mCancelled;
+	LLUpdateDownloader::Client & mClient;
+	CURL * mCurl;
+	LLSD mDownloadData;
+	llofstream mDownloadStream;
+	std::string mDownloadRecordPath;
+	curl_slist * mHeaderList;
+	
+	void initializeCurlGet(std::string const & url, bool processHeader);
+	void resumeDownloading(size_t startByte);
+	void run(void);
+	void startDownloading(LLURI const & uri, std::string const & hash);
+	void throwOnCurlError(CURLcode code);
+	bool validateDownload(void);
+
+	LOG_CLASS(LLUpdateDownloader::Implementation);
+};
+
+
+namespace {
+	class DownloadError:
+		public std::runtime_error
+	{
+	public:
+		DownloadError(const char * message):
+			std::runtime_error(message)
+		{
+			; // No op.
+		}
+	};
+
+		
+	const char * gSecondLifeUpdateRecord = "SecondLifeUpdateDownload.xml";
+};
+
+
+
+// LLUpdateDownloader
+//-----------------------------------------------------------------------------
+
+
+
+std::string LLUpdateDownloader::downloadMarkerPath(void)
+{
+	return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, gSecondLifeUpdateRecord);
+}
+
+
+LLUpdateDownloader::LLUpdateDownloader(Client & client):
+	mImplementation(new LLUpdateDownloader::Implementation(client))
+{
+	; // No op.
+}
+
+
+void LLUpdateDownloader::cancel(void)
+{
+	mImplementation->cancel();
+}
+
+
+void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash)
+{
+	mImplementation->download(uri, hash);
+}
+
+
+bool LLUpdateDownloader::isDownloading(void)
+{
+	return mImplementation->isDownloading();
+}
+
+
+void LLUpdateDownloader::resume(void)
+{
+	mImplementation->resume();
+}
+
+
+
+// LLUpdateDownloader::Implementation
+//-----------------------------------------------------------------------------
+
+
+namespace {
+	size_t write_function(void * data, size_t blockSize, size_t blocks, void * downloader)
+	{
+		size_t bytes = blockSize * blocks;
+		return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onBody(data, bytes);
+	}
+
+
+	size_t header_function(void * data, size_t blockSize, size_t blocks, void * downloader)
+	{
+		size_t bytes = blockSize * blocks;
+		return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes);
+	}
+}
+
+
+LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client):
+	LLThread("LLUpdateDownloader"),
+	mCancelled(false),
+	mClient(client),
+	mCurl(0),
+	mHeaderList(0)
+{
+	CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case.
+	llverify(code == CURLE_OK); // TODO: real error handling here. 
+}
+
+
+LLUpdateDownloader::Implementation::~Implementation()
+{
+	if(isDownloading()) {
+		cancel();
+		shutdown();
+	} else {
+		; // No op.
+	}
+	if(mCurl) curl_easy_cleanup(mCurl);
+}
+
+
+void LLUpdateDownloader::Implementation::cancel(void)
+{
+	mCancelled = true;
+}
+	
+
+void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash)
+{
+	if(isDownloading()) mClient.downloadError("download in progress");
+
+	mDownloadRecordPath = downloadMarkerPath();
+	mDownloadData = LLSD();
+	try {
+		startDownloading(uri, hash);
+	} catch(DownloadError const & e) {
+		mClient.downloadError(e.what());
+	}
+}
+
+
+bool LLUpdateDownloader::Implementation::isDownloading(void)
+{
+	return !isStopped();
+}
+
+
+void LLUpdateDownloader::Implementation::resume(void)
+{
+	mCancelled = false;
+
+	if(isDownloading()) {
+		mClient.downloadError("download in progress");
+	}
+
+	mDownloadRecordPath = downloadMarkerPath();
+	llifstream dataStream(mDownloadRecordPath);
+	if(!dataStream) {
+		mClient.downloadError("no download marker");
+		return;
+	}
+	
+	LLSDSerialize::fromXMLDocument(mDownloadData, dataStream);
+	
+	if(!mDownloadData.asBoolean()) {
+		mClient.downloadError("no download information in marker");
+		return;
+	}
+	
+	std::string filePath = mDownloadData["path"].asString();
+	try {
+		if(LLFile::isfile(filePath)) {		
+			llstat fileStatus;
+			LLFile::stat(filePath, &fileStatus);
+			if(fileStatus.st_size != mDownloadData["size"].asInteger()) {
+				resumeDownloading(fileStatus.st_size);
+			} else if(!validateDownload()) {
+				LLFile::remove(filePath);
+				download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString());
+			} else {
+				mClient.downloadComplete(mDownloadData);
+			}
+		} else {
+			download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString());
+		}
+	} catch(DownloadError & e) {
+		mClient.downloadError(e.what());
+	}
+}
+
+
+size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size)
+{
+	char const * headerPtr = reinterpret_cast<const char *> (buffer);
+	std::string header(headerPtr, headerPtr + size);
+	size_t colonPosition = header.find(':');
+	if(colonPosition == std::string::npos) return size; // HTML response; ignore.
+	
+	if(header.substr(0, colonPosition) == "Content-Length") {
+		try {
+			size_t firstDigitPos = header.find_first_of("0123456789", colonPosition);
+			size_t lastDigitPos = header.find_last_of("0123456789");
+			std::string contentLength = header.substr(firstDigitPos, lastDigitPos - firstDigitPos + 1);
+			size_t size = boost::lexical_cast<size_t>(contentLength);
+			LL_INFOS("UpdateDownload") << "download size is " << size << LL_ENDL;
+			
+			mDownloadData["size"] = LLSD(LLSD::Integer(size));
+			llofstream odataStream(mDownloadRecordPath);
+			LLSDSerialize::toPrettyXML(mDownloadData, odataStream);
+		} catch (std::exception const & e) {
+			LL_WARNS("UpdateDownload") << "unable to read content length (" 
+				<< e.what() << ")" << LL_ENDL;
+		}
+	} else {
+		; // No op.
+	}
+	
+	return size;
+}
+
+
+size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size)
+{
+	if(mCancelled) return 0; // Forces a write error which will halt curl thread.
+	if((size == 0) || (buffer == 0)) return 0; 
+	
+	mDownloadStream.write(reinterpret_cast<const char *>(buffer), size);
+	if(mDownloadStream.bad()) {
+		return 0;
+	} else {
+		return size;
+	}
+}
+
+
+void LLUpdateDownloader::Implementation::run(void)
+{
+	CURLcode code = curl_easy_perform(mCurl);
+	mDownloadStream.close();
+	if(code == CURLE_OK) {
+		LLFile::remove(mDownloadRecordPath);
+		if(validateDownload()) {
+			LL_INFOS("UpdateDownload") << "download successful" << LL_ENDL;
+			mClient.downloadComplete(mDownloadData);
+		} else {
+			LL_INFOS("UpdateDownload") << "download failed hash check" << LL_ENDL;
+			std::string filePath = mDownloadData["path"].asString();
+			if(filePath.size() != 0) LLFile::remove(filePath);
+			mClient.downloadError("failed hash check");
+		}
+	} else if(mCancelled && (code == CURLE_WRITE_ERROR)) {
+		LL_INFOS("UpdateDownload") << "download canceled by user" << LL_ENDL;
+		// Do not call back client.
+	} else {
+		LL_WARNS("UpdateDownload") << "download failed with error '" << 
+			curl_easy_strerror(code) << "'" << LL_ENDL;
+		LLFile::remove(mDownloadRecordPath);
+		if(mDownloadData.has("path")) LLFile::remove(mDownloadData["path"].asString());
+		mClient.downloadError("curl error");
+	}
+	
+	if(mHeaderList) {
+		curl_slist_free_all(mHeaderList);
+		mHeaderList = 0;
+	}
+}
+
+
+void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)
+{
+	if(mCurl == 0) {
+		mCurl = curl_easy_init();
+	} else {
+		curl_easy_reset(mCurl);
+	}
+	
+	if(mCurl == 0) throw DownloadError("failed to initialize curl");
+	
+	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOSIGNAL, true));
+	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_FOLLOWLOCATION, true));
+	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, &write_function));
+	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, this));
+	if(processHeader) {
+	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, &header_function));
+	   throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, this));
+	}
+	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true));
+	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str()));
+}
+
+
+void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)
+{
+	LL_INFOS("UpdateDownload") << "resuming download from " << mDownloadData["url"].asString()
+		<< " at byte " << startByte << LL_ENDL;
+
+	initializeCurlGet(mDownloadData["url"].asString(), false);
+	
+	// The header 'Range: bytes n-' will request the bytes remaining in the
+	// source begining with byte n and ending with the last byte.
+	boost::format rangeHeaderFormat("Range: bytes=%u-");
+	rangeHeaderFormat % startByte;
+	mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());
+	if(mHeaderList == 0) throw DownloadError("cannot add Range header");
+	throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaderList));
+	
+	mDownloadStream.open(mDownloadData["path"].asString(),
+						 std::ios_base::out | std::ios_base::binary | std::ios_base::app);
+	start();
+}
+
+
+void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std::string const & hash)
+{
+	mDownloadData["url"] = uri.asString();
+	mDownloadData["hash"] = hash;
+	mDownloadData["current_version"] = ll_get_version();
+	LLSD path = uri.pathArray();
+	if(path.size() == 0) throw DownloadError("no file path");
+	std::string fileName = path[path.size() - 1].asString();
+	std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);
+	mDownloadData["path"] = filePath;
+
+	LL_INFOS("UpdateDownload") << "downloading " << filePath
+		<< " from " << uri.asString() << LL_ENDL;
+	LL_INFOS("UpdateDownload") << "hash of file is " << hash << LL_ENDL;
+		
+	llofstream dataStream(mDownloadRecordPath);
+	LLSDSerialize::toPrettyXML(mDownloadData, dataStream);
+	
+	mDownloadStream.open(filePath, std::ios_base::out | std::ios_base::binary);
+	initializeCurlGet(uri.asString(), true);
+	start();
+}
+
+
+void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)
+{
+	if(code != CURLE_OK) {
+		const char * errorString = curl_easy_strerror(code);
+		if(errorString != 0) {
+			throw DownloadError(curl_easy_strerror(code));
+		} else {
+			throw DownloadError("unknown curl error");
+		}
+	} else {
+		; // No op.
+	}
+}
+
+
+bool LLUpdateDownloader::Implementation::validateDownload(void)
+{
+	std::string filePath = mDownloadData["path"].asString();
+	llifstream fileStream(filePath, std::ios_base::in | std::ios_base::binary);
+	if(!fileStream) return false;
+
+	std::string hash = mDownloadData["hash"].asString();
+	if(hash.size() != 0) {
+		LL_INFOS("UpdateDownload") << "checking hash..." << LL_ENDL;
+		char digest[33];
+		LLMD5(fileStream).hex_digest(digest);
+		if(hash != digest) {
+			LL_WARNS("UpdateDownload") << "download hash mismatch; expeted " << hash <<
+				" but download is " << digest << LL_ENDL;
+		}
+		return hash == digest;
+	} else {
+		return true; // No hash check provided.
+	}
+}
diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b3d7480fd1785747b5d5f6e5509667a03f791ac
--- /dev/null
+++ b/indra/viewer_components/updater/llupdatedownloader.h
@@ -0,0 +1,87 @@
+/** 
+ * @file llupdatedownloader.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATE_DOWNLOADER_H
+#define LL_UPDATE_DOWNLOADER_H
+
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include "lluri.h"
+
+
+//
+// An asynchronous download service for fetching updates.
+//
+class LLUpdateDownloader
+{
+public:
+	class Client;
+	class Implementation;
+	
+	// Returns the path to the download marker file containing details of the
+	// latest download.
+	static std::string downloadMarkerPath(void);
+	
+	LLUpdateDownloader(Client & client);
+	
+	// Cancel any in progress download; a no op if none is in progress.  The
+	// client will not receive a complete or error callback.
+	void cancel(void);
+	
+	// Start a new download.
+	void download(LLURI const & uri, std::string const & hash);
+	
+	// Returns true if a download is in progress.
+	bool isDownloading(void);
+	
+	// Resume a partial download.
+	void resume(void);
+	
+private:
+	boost::shared_ptr<Implementation> mImplementation;
+};
+
+
+//
+// An interface to be implemented by clients initiating a update download.
+//
+class LLUpdateDownloader::Client {
+public:
+	
+	// The download has completed successfully.
+	// data is a map containing the following items:
+	// url - source (remote) location
+	// hash - the md5 sum that should match the installer file.
+	// path - destination (local) location
+	// size - the size of the installer in bytes
+	virtual void downloadComplete(LLSD const & data) = 0;
+	
+	// The download failed.
+	virtual void downloadError(std::string const & message) = 0;
+};
+
+
+#endif
diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6e69bcf28b8b9d201b701709855dd1e431162b73
--- /dev/null
+++ b/indra/viewer_components/updater/llupdateinstaller.cpp
@@ -0,0 +1,90 @@
+/** 
+ * @file llupdateinstaller.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include <apr_file_io.h>
+#include "llapr.h"
+#include "llprocesslauncher.h"
+#include "llupdateinstaller.h"
+#include "lldir.h"
+
+
+namespace {
+	class RelocateError {};
+	
+	
+	std::string copy_to_temp(std::string const & path)
+	{
+		std::string scriptFile = gDirUtilp->getBaseFileName(path);
+		std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);
+		apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp);
+		if(status != APR_SUCCESS) throw RelocateError();
+		
+		return newPath;
+	}
+}
+
+
+int ll_install_update(std::string const & script, std::string const & updatePath, LLInstallScriptMode mode)
+{
+	std::string actualScriptPath;
+	switch(mode) {
+		case LL_COPY_INSTALL_SCRIPT_TO_TEMP:
+			try {
+				actualScriptPath = copy_to_temp(script);
+			}
+			catch (RelocateError &) {
+				return -1;
+			}
+			break;
+		case LL_RUN_INSTALL_SCRIPT_IN_PLACE:
+			actualScriptPath = script;
+			break;
+		default:
+			llassert(!"unpossible copy mode");
+	}
+	
+	llinfos << "UpdateInstaller: installing " << updatePath << " using " <<
+		actualScriptPath << LL_ENDL;
+	
+	LLProcessLauncher launcher;
+	launcher.setExecutable(actualScriptPath);
+	launcher.addArgument(updatePath);
+	launcher.addArgument(ll_install_failed_marker_path().c_str());
+	int result = launcher.launch();
+	launcher.orphan();
+	
+	return result;
+}
+
+
+std::string const & ll_install_failed_marker_path(void)
+{
+	static std::string path;
+	if(path.empty()) {
+		path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeInstallFailed.marker");
+	}
+	return path;
+}
diff --git a/indra/viewer_components/updater/llupdateinstaller.h b/indra/viewer_components/updater/llupdateinstaller.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ce08ce6fa51ece998fc77469b473c2fd3f3742d
--- /dev/null
+++ b/indra/viewer_components/updater/llupdateinstaller.h
@@ -0,0 +1,57 @@
+/** 
+ * @file llupdateinstaller.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATE_INSTALLER_H
+#define LL_UPDATE_INSTALLER_H
+
+
+#include <string>
+
+
+enum LLInstallScriptMode {
+	LL_RUN_INSTALL_SCRIPT_IN_PLACE,
+	LL_COPY_INSTALL_SCRIPT_TO_TEMP
+};
+
+//
+// Launch the installation script.
+// 
+// The updater will overwrite the current installation, so it is highly recommended
+// that the current application terminate once this function is called.
+//
+int ll_install_update(
+					   std::string const & script, // Script to execute.
+					   std::string const & updatePath, // Path to update file.
+					   LLInstallScriptMode mode=LL_COPY_INSTALL_SCRIPT_TO_TEMP); // Run in place or copy to temp?
+
+
+//
+// Returns the path which points to the failed install marker file, should it
+// exist.
+//
+std::string const & ll_install_failed_marker_path(void);
+
+
+#endif
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cc60eaead27a9ba49e5804bce09f4e415c277fb5
--- /dev/null
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -0,0 +1,519 @@
+/** 
+ * @file llupdaterservice.cpp
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llupdatedownloader.h"
+#include "llevents.h"
+#include "lltimer.h"
+#include "llupdaterservice.h"
+#include "llupdatechecker.h"
+#include "llupdateinstaller.h"
+#include "llversionviewer.h"
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include "lldir.h"
+#include "llsdserialize.h"
+#include "llfile.h"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
+
+namespace 
+{
+	boost::weak_ptr<LLUpdaterServiceImpl> gUpdater;
+
+	const std::string UPDATE_MARKER_FILENAME("SecondLifeUpdateReady.xml");
+	std::string update_marker_path()
+	{
+		return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, 
+											  UPDATE_MARKER_FILENAME);
+	}
+	
+	std::string install_script_path(void)
+	{
+#ifdef LL_WINDOWS
+		std::string scriptFile = "update_install.bat";
+#else
+		std::string scriptFile = "update_install";
+#endif
+		return gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, scriptFile);
+	}
+	
+	LLInstallScriptMode install_script_mode(void) 
+	{
+#ifdef LL_WINDOWS
+		return LL_COPY_INSTALL_SCRIPT_TO_TEMP;
+#else
+		return LL_RUN_INSTALL_SCRIPT_IN_PLACE;
+#endif
+	};
+	
+}
+
+class LLUpdaterServiceImpl : 
+	public LLUpdateChecker::Client,
+	public LLUpdateDownloader::Client
+{
+	static const std::string sListenerName;
+	
+	std::string mProtocolVersion;
+	std::string mUrl;
+	std::string mPath;
+	std::string mChannel;
+	std::string mVersion;
+	
+	unsigned int mCheckPeriod;
+	bool mIsChecking;
+	bool mIsDownloading;
+	
+	LLUpdateChecker mUpdateChecker;
+	LLUpdateDownloader mUpdateDownloader;
+	LLTimer mTimer;
+
+	LLUpdaterService::app_exit_callback_t mAppExitCallback;
+	
+	LOG_CLASS(LLUpdaterServiceImpl);
+	
+public:
+	LLUpdaterServiceImpl();
+	virtual ~LLUpdaterServiceImpl();
+
+	void initialize(const std::string& protocol_version,
+				   const std::string& url, 
+				   const std::string& path,
+				   const std::string& channel,
+				   const std::string& version);
+	
+	void setCheckPeriod(unsigned int seconds);
+
+	void startChecking(bool install_if_ready);
+	void stopChecking();
+	bool isChecking();
+	
+	void setAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { mAppExitCallback = aecb;}
+
+	bool checkForInstall(bool launchInstaller); // Test if a local install is ready.
+	bool checkForResume(); // Test for resumeable d/l.
+
+	// LLUpdateChecker::Client:
+	virtual void error(std::string const & message);
+	virtual void optionalUpdate(std::string const & newVersion,
+								LLURI const & uri,
+								std::string const & hash);
+	virtual void requiredUpdate(std::string const & newVersion,
+								LLURI const & uri,
+								std::string const & hash);
+	virtual void upToDate(void);
+	
+	// LLUpdateDownloader::Client
+	void downloadComplete(LLSD const & data);
+	void downloadError(std::string const & message);
+
+	bool onMainLoop(LLSD const & event);
+
+private:
+	void restartTimer(unsigned int seconds);
+	void stopTimer();
+};
+
+const std::string LLUpdaterServiceImpl::sListenerName = "LLUpdaterServiceImpl";
+
+LLUpdaterServiceImpl::LLUpdaterServiceImpl() :
+	mIsChecking(false),
+	mIsDownloading(false),
+	mCheckPeriod(0),
+	mUpdateChecker(*this),
+	mUpdateDownloader(*this)
+{
+}
+
+LLUpdaterServiceImpl::~LLUpdaterServiceImpl()
+{
+	LL_INFOS("UpdaterService") << "shutting down updater service" << LL_ENDL;
+	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
+}
+
+void LLUpdaterServiceImpl::initialize(const std::string& protocol_version,
+									  const std::string& url, 
+									  const std::string& path,
+									  const std::string& channel,
+									  const std::string& version)
+{
+	if(mIsChecking || mIsDownloading)
+	{
+		throw LLUpdaterService::UsageError("LLUpdaterService::initialize call "
+										   "while updater is running.");
+	}
+		
+	mProtocolVersion = protocol_version;
+	mUrl = url;
+	mPath = path;
+	mChannel = channel;
+	mVersion = version;
+}
+
+void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds)
+{
+	mCheckPeriod = seconds;
+}
+
+void LLUpdaterServiceImpl::startChecking(bool install_if_ready)
+{
+	if(mUrl.empty() || mChannel.empty() || mVersion.empty())
+	{
+		throw LLUpdaterService::UsageError("Set params before call to "
+			"LLUpdaterService::startCheck().");
+	}
+
+	mIsChecking = true;
+
+    // Check to see if an install is ready.
+	bool has_install = checkForInstall(install_if_ready);
+	if(!has_install)
+	{
+		checkForResume(); // will set mIsDownloading to true if resuming
+
+		if(!mIsDownloading)
+		{
+			// Checking can only occur during the mainloop.
+			// reset the timer to 0 so that the next mainloop event 
+			// triggers a check;
+			restartTimer(0); 
+		}
+	}
+}
+
+void LLUpdaterServiceImpl::stopChecking()
+{
+	if(mIsChecking)
+	{
+		mIsChecking = false;
+		stopTimer();
+	}
+
+    if(mIsDownloading)
+    {
+        mUpdateDownloader.cancel();
+		mIsDownloading = false;
+    }
+}
+
+bool LLUpdaterServiceImpl::isChecking()
+{
+	return mIsChecking;
+}
+
+bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller)
+{
+	bool foundInstall = false; // return true if install is found.
+
+	llifstream update_marker(update_marker_path(), 
+							 std::ios::in | std::ios::binary);
+
+	if(update_marker.is_open())
+	{
+		// Found an update info - now lets see if its valid.
+		LLSD update_info;
+		LLSDSerialize::fromXMLDocument(update_info, update_marker);
+		update_marker.close();
+
+		// Get the path to the installer file.
+		LLSD path = update_info.get("path");
+		if(update_info["current_version"].asString() != ll_get_version())
+		{
+			// This viewer is not the same version as the one that downloaded
+			// the update.  Do not install this update.
+			if(!path.asString().empty())
+			{
+				llinfos << "ignoring update dowloaded by different client version" << llendl;
+				LLFile::remove(path.asString());
+				LLFile::remove(update_marker_path());
+			}
+			else
+			{
+				; // Nothing to clean up.
+			}
+			
+			foundInstall = false;
+		} 
+		else if(path.isDefined() && !path.asString().empty())
+		{
+			if(launchInstaller)
+			{
+				LLFile::remove(update_marker_path());
+
+				int result = ll_install_update(install_script_path(),
+											   update_info["path"].asString(),
+											   install_script_mode());	
+				
+				if((result == 0) && mAppExitCallback)
+				{
+					mAppExitCallback();
+				} else if(result != 0) {
+					llwarns << "failed to run update install script" << LL_ENDL;
+				} else {
+					; // No op.
+				}
+			}
+			
+			foundInstall = true;
+		}
+	}
+	return foundInstall;
+}
+
+bool LLUpdaterServiceImpl::checkForResume()
+{
+	bool result = false;
+	std::string download_marker_path = mUpdateDownloader.downloadMarkerPath();
+	if(LLFile::isfile(download_marker_path))
+	{
+		llifstream download_marker_stream(download_marker_path, 
+								 std::ios::in | std::ios::binary);
+		if(download_marker_stream.is_open())
+		{
+			LLSD download_info;
+			LLSDSerialize::fromXMLDocument(download_info, download_marker_stream);
+			download_marker_stream.close();
+			if(download_info["current_version"].asString() == ll_get_version())
+			{
+				mIsDownloading = true;
+				mUpdateDownloader.resume();
+				result = true;
+			}
+			else 
+			{
+				// The viewer that started this download is not the same as this viewer; ignore.
+				llinfos << "ignoring partial download from different viewer version" << llendl;
+				std::string path = download_info["path"].asString();
+				if(!path.empty()) LLFile::remove(path);
+				LLFile::remove(download_marker_path);
+			}
+		} 
+	}
+	return result;
+}
+
+void LLUpdaterServiceImpl::error(std::string const & message)
+{
+	if(mIsChecking)
+	{
+		restartTimer(mCheckPeriod);
+	}
+}
+
+void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion,
+										  LLURI const & uri,
+										  std::string const & hash)
+{
+	stopTimer();
+	mIsDownloading = true;
+	mUpdateDownloader.download(uri, hash);
+}
+
+void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion,
+										  LLURI const & uri,
+										  std::string const & hash)
+{
+	stopTimer();
+	mIsDownloading = true;
+	mUpdateDownloader.download(uri, hash);
+}
+
+void LLUpdaterServiceImpl::upToDate(void)
+{
+	if(mIsChecking)
+	{
+		restartTimer(mCheckPeriod);
+	}
+}
+
+void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) 
+{ 
+	mIsDownloading = false;
+
+	// Save out the download data to the SecondLifeUpdateReady
+	// marker file. 
+	llofstream update_marker(update_marker_path());
+	LLSDSerialize::toPrettyXML(data, update_marker);
+	
+	LLSD event;
+	event["pump"] = LLUpdaterService::pumpName();
+	LLSD payload;
+	payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE);
+	event["payload"] = payload;
+	LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+}
+
+void LLUpdaterServiceImpl::downloadError(std::string const & message) 
+{ 
+	LL_INFOS("UpdaterService") << "Error downloading: " << message << LL_ENDL;
+
+	mIsDownloading = false;
+
+	// Restart the timer on error
+	if(mIsChecking)
+	{
+		restartTimer(mCheckPeriod); 
+	}
+
+	LLSD event;
+	event["pump"] = LLUpdaterService::pumpName();
+	LLSD payload;
+	payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_ERROR);
+	payload["message"] = message;
+	event["payload"] = payload;
+	LLEventPumps::instance().obtain("mainlooprepeater").post(event);
+}
+
+void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)
+{
+	LL_INFOS("UpdaterService") << "will check for update again in " << 
+	seconds << " seconds" << LL_ENDL; 
+	mTimer.start();
+	mTimer.setTimerExpirySec(seconds);
+	LLEventPumps::instance().obtain("mainloop").listen(
+		sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));
+}
+
+void LLUpdaterServiceImpl::stopTimer()
+{
+	mTimer.stop();
+	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
+}
+
+bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)
+{
+	if(mTimer.getStarted() && mTimer.hasExpired())
+	{
+		stopTimer();
+
+		// Check for failed install.
+		if(LLFile::isfile(ll_install_failed_marker_path()))
+		{
+			// TODO: notify the user.
+			llinfos << "found marker " << ll_install_failed_marker_path() << llendl;
+			llinfos << "last install attempt failed" << llendl;
+			LLFile::remove(ll_install_failed_marker_path());
+			
+			LLSD event;
+			event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR);
+			LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event);
+		}
+		else
+		{
+			mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion);
+		}
+	} 
+	else 
+	{
+		// Keep on waiting...
+	}
+	
+	return false;
+}
+
+
+//-----------------------------------------------------------------------
+// Facade interface
+
+std::string const & LLUpdaterService::pumpName(void)
+{
+	static std::string name("updater_service");
+	return name;
+}
+
+LLUpdaterService::LLUpdaterService()
+{
+	if(gUpdater.expired())
+	{
+		mImpl = 
+			boost::shared_ptr<LLUpdaterServiceImpl>(new LLUpdaterServiceImpl());
+		gUpdater = mImpl;
+	}
+	else
+	{
+		mImpl = gUpdater.lock();
+	}
+}
+
+LLUpdaterService::~LLUpdaterService()
+{
+}
+
+void LLUpdaterService::initialize(const std::string& protocol_version,
+								 const std::string& url, 
+								 const std::string& path,
+								 const std::string& channel,
+								 const std::string& version)
+{
+	mImpl->initialize(protocol_version, url, path, channel, version);
+}
+
+void LLUpdaterService::setCheckPeriod(unsigned int seconds)
+{
+	mImpl->setCheckPeriod(seconds);
+}
+	
+void LLUpdaterService::startChecking(bool install_if_ready)
+{
+	mImpl->startChecking(install_if_ready);
+}
+
+void LLUpdaterService::stopChecking()
+{
+	mImpl->stopChecking();
+}
+
+bool LLUpdaterService::isChecking()
+{
+	return mImpl->isChecking();
+}
+
+void LLUpdaterService::setImplAppExitCallback(LLUpdaterService::app_exit_callback_t aecb)
+{
+	return mImpl->setAppExitCallback(aecb);
+}
+
+
+std::string const & ll_get_version(void) {
+	static std::string version("");
+	
+	if (version.empty()) {
+		std::ostringstream stream;
+		stream << LL_VERSION_MAJOR << "."
+		<< LL_VERSION_MINOR << "."
+		<< LL_VERSION_PATCH << "."
+		<< LL_VERSION_BUILD;
+		version = stream.str();
+	}
+	
+	return version;
+}
+
diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h
new file mode 100644
index 0000000000000000000000000000000000000000..752a6f834b4f93a7204a9e8573d30812f9d7de90
--- /dev/null
+++ b/indra/viewer_components/updater/llupdaterservice.h
@@ -0,0 +1,85 @@
+/** 
+ * @file llupdaterservice.h
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UPDATERSERVICE_H
+#define LL_UPDATERSERVICE_H
+
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+
+class LLUpdaterServiceImpl;
+
+class LLUpdaterService
+{
+public:
+	class UsageError: public std::runtime_error
+	{
+	public:
+		UsageError(const std::string& msg) : std::runtime_error(msg) {}
+	};
+	
+	// Name of the event pump through which update events will be delivered.
+	static std::string const & pumpName(void);
+	
+	// Type codes for events posted by this service.  Stored the event's 'type' element.
+	enum eUpdateEvent {
+		INVALID,
+		DOWNLOAD_COMPLETE,
+		DOWNLOAD_ERROR,
+		INSTALL_ERROR
+	};
+
+	LLUpdaterService();
+	~LLUpdaterService();
+
+	void initialize(const std::string& protocol_version,
+				    const std::string& url, 
+				    const std::string& path,
+				    const std::string& channel,
+				    const std::string& version);
+
+	void setCheckPeriod(unsigned int seconds);
+	
+	void startChecking(bool install_if_ready = false);
+	void stopChecking();
+	bool isChecking();
+
+	typedef boost::function<void (void)> app_exit_callback_t;
+	template <typename F>
+	void setAppExitCallback(F const &callable) 
+	{ 
+		app_exit_callback_t aecb = callable;
+		setImplAppExitCallback(aecb);
+	}
+
+private:
+	boost::shared_ptr<LLUpdaterServiceImpl> mImpl;
+	void setImplAppExitCallback(app_exit_callback_t aecb);
+};
+
+// Returns the full version as a string.
+std::string const & ll_get_version(void);
+
+#endif // LL_UPDATERSERVICE_H
diff --git a/indra/viewer_components/updater/scripts/darwin/update_install b/indra/viewer_components/updater/scripts/darwin/update_install
new file mode 100644
index 0000000000000000000000000000000000000000..b174b3570a2bf4854c11d021d4523db931449a59
--- /dev/null
+++ b/indra/viewer_components/updater/scripts/darwin/update_install
@@ -0,0 +1,9 @@
+#! /bin/bash
+
+#
+# The first argument contains the path to the installer app.  The second a path
+# to a marker file which should be created if the installer fails.q
+#
+
+open ../Resources/mac-updater.app --args -dmg "$1" -name "Second Life Viewer 2" -marker "$2"
+exit 0
diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install
new file mode 100644
index 0000000000000000000000000000000000000000..fef5ef7d09a95393d8e9bf8edf1a21fedd2e8416
--- /dev/null
+++ b/indra/viewer_components/updater/scripts/linux/update_install
@@ -0,0 +1,10 @@
+#! /bin/bash
+INSTALL_DIR=$(cd "$(dirname $0)/.." ; pwd)
+export LD_LIBRARY_PATH=$INSTALL_DIR/lib
+bin/linux-updater.bin --file "$1" --dest "$INSTALL_DIR" --name "Second Life Viewer 2" --stringsdir "$INSTALL_DIR/skins/default/xui/en" --stringsfile "strings.xml"
+
+if [ $? -ne 0 ]
+   then touch $2
+fi
+
+rm -f $1
diff --git a/indra/viewer_components/updater/scripts/windows/update_install.bat b/indra/viewer_components/updater/scripts/windows/update_install.bat
new file mode 100644
index 0000000000000000000000000000000000000000..42e148a707e11433798ac33e3d2e56e86acac394
--- /dev/null
+++ b/indra/viewer_components/updater/scripts/windows/update_install.bat
@@ -0,0 +1,3 @@
+start /WAIT %1 /SKIP_DIALOGS
+IF ERRORLEVEL 1 ECHO %ERRORLEVEL% > %2
+DEL %1
diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..04ed4e63640b24aab81ef74db2960cfe5dc7cbdb
--- /dev/null
+++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp
@@ -0,0 +1,199 @@
+/**
+ * @file   llupdaterservice_test.cpp
+ * @brief  Tests of llupdaterservice.cpp.
+ * 
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "../llupdaterservice.h"
+#include "../llupdatechecker.h"
+#include "../llupdatedownloader.h"
+#include "../llupdateinstaller.h"
+
+#include "../../../test/lltut.h"
+//#define DEBUG_ON
+#include "../../../test/debug.h"
+
+#include "llevents.h"
+#include "lldir.h"
+
+/*****************************************************************************
+*   MOCK'd
+*****************************************************************************/
+LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
+{}
+void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, 
+								  std::string const & servicePath, std::string channel, std::string version)
+{}
+LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
+void LLUpdateDownloader::download(LLURI const & , std::string const &){}
+
+class LLDir_Mock : public LLDir
+{
+	void initAppDirs(const std::string &app_name, 
+		   			 const std::string& app_read_only_data_dir = "") {}
+	U32 countFilesInDir(const std::string &dirname, const std::string &mask) 
+	{
+		return 0;
+	}
+
+	BOOL getNextFileInDir(const std::string &dirname, 
+						  const std::string &mask, 
+						  std::string &fname) 
+	{
+		return false;
+	}
+	void getRandomFileInDir(const std::string &dirname, 
+							const std::string &mask, 
+							std::string &fname) {}
+	std::string getCurPath() { return ""; }
+	BOOL fileExists(const std::string &filename) const { return false; }
+	std::string getLLPluginLauncher() { return ""; }
+	std::string getLLPluginFilename(std::string base_name) { return ""; }
+
+} gDirUtil;
+LLDir* gDirUtilp = &gDirUtil;
+LLDir::LLDir() {}
+LLDir::~LLDir() {}
+S32 LLDir::deleteFilesInDir(const std::string &dirname, 
+							const std::string &mask)
+{ return 0; }
+
+void LLDir::setChatLogsDir(const std::string &path){}		
+void LLDir::setPerAccountChatLogsDir(const std::string &username){}
+void LLDir::setLindenUserDir(const std::string &username){}		
+void LLDir::setSkinFolder(const std::string &skin_folder){}
+bool LLDir::setCacheDir(const std::string &path){ return true; }
+void LLDir::dumpCurrentDirectories() {}
+
+std::string LLDir::getExpandedFilename(ELLPath location, 
+									   const std::string &filename) const 
+{
+	return "";
+}
+
+std::string LLUpdateDownloader::downloadMarkerPath(void)
+{
+	return "";
+}
+
+void LLUpdateDownloader::resume(void) {}
+void LLUpdateDownloader::cancel(void) {}
+
+int ll_install_update(std::string const &, std::string const &, LLInstallScriptMode)
+{
+	return 0;
+}
+
+std::string const & ll_install_failed_marker_path()
+{
+	static std::string wubba;
+	return wubba;
+}
+
+/*
+#pragma warning(disable: 4273)
+llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename,
+										   ios_base::openmode _Mode,
+										   int _Prot) :
+	std::basic_istream<char,std::char_traits< char > >(NULL,true)
+{}
+
+llus_mock_llifstream::~llus_mock_llifstream() {}
+bool llus_mock_llifstream::is_open() const {return true;}
+void llus_mock_llifstream::close() {}
+*/
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llupdaterservice_data
+    {
+		llupdaterservice_data() :
+            pumps(LLEventPumps::instance()),
+			test_url("dummy_url"),
+			test_channel("dummy_channel"),
+			test_version("dummy_version")
+		{}
+		LLEventPumps& pumps;
+		std::string test_url;
+		std::string test_channel;
+		std::string test_version;
+	};
+
+    typedef test_group<llupdaterservice_data> llupdaterservice_group;
+    typedef llupdaterservice_group::object llupdaterservice_object;
+    llupdaterservice_group llupdaterservicegrp("LLUpdaterService");
+
+    template<> template<>
+    void llupdaterservice_object::test<1>()
+    {
+        DEBUG;
+		LLUpdaterService updater;
+		bool got_usage_error = false;
+		try
+		{
+			updater.startChecking();
+		}
+		catch(LLUpdaterService::UsageError)
+		{
+			got_usage_error = true;
+		}
+		ensure("Caught start before params", got_usage_error);
+	}
+
+    template<> template<>
+    void llupdaterservice_object::test<2>()
+    {
+        DEBUG;
+		LLUpdaterService updater;
+		bool got_usage_error = false;
+		try
+		{
+			updater.initialize("1.0",test_url, "update" ,test_channel, test_version);
+			updater.startChecking();
+			updater.initialize("1.0", "other_url", "update", test_channel, test_version);
+		}
+		catch(LLUpdaterService::UsageError)
+		{
+			got_usage_error = true;
+		}
+		ensure("Caught params while running", got_usage_error);
+	}
+
+    template<> template<>
+    void llupdaterservice_object::test<3>()
+    {
+        DEBUG;
+		LLUpdaterService updater;
+		updater.initialize("1.0", test_url, "update", test_channel, test_version);
+		updater.startChecking();
+		ensure(updater.isChecking());
+		updater.stopChecking();
+		ensure(!updater.isChecking());
+	}
+}
diff --git a/install.xml b/install.xml
index 391d83b2246f8017bfaf5a2500a214c41c36f14d..98e983299e413afa5c879da1852f30389cf162fa 100644
--- a/install.xml
+++ b/install.xml
@@ -1408,7 +1408,7 @@ anguage Infrstructure (CLI) international standard</string>
           </map>
         </map>
       </map>
-      <key>vivox</key>
+      <key>slvoice</key>
       <map>
         <key>copyright</key>
         <string> </string>
@@ -1419,23 +1419,23 @@ anguage Infrstructure (CLI) international standard</string>
           <key>darwin</key>
           <map>
             <key>md5sum</key>
-            <string>aa144917d0e33453d3c2cc2c05c6c47c</string>
+            <string>2f9b3528d4b5f858fb8dcee4b6dd5188</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.8821-darwin-20100529.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-darwin-20101117a.tar.bz2</uri>
           </map>
           <key>linux</key>
           <map>
             <key>md5sum</key>
-            <string>98f7945755f3ee8e52f685a3eff4d7be</string>
+            <string>cde4728b8a75a76c72a8785815cb769f</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.8821-linux-20100529.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-linux-20101117a.tar.bz2</uri>
           </map>
           <key>windows</key>
           <map>
             <key>md5sum</key>
-            <string>e8fdd46cb026c2ec72c4489eb3bf39c1</string>
+            <string>940ac55a6d0141c958bf2b14939d8474</string>
             <key>url</key>
-            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/vivox-3.1.0001.8821-windows-20100529.tar.bz2</uri>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/slvoice-3.2.0002.9361-windows-20101117a.tar.bz2</uri>
           </map>
         </map>
       </map>
diff --git a/scripts/md5check.py b/scripts/md5check.py
new file mode 100755
index 0000000000000000000000000000000000000000..951fe0105ca8a7106c0ac9649b6f4d050b016402
--- /dev/null
+++ b/scripts/md5check.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+"""\
+@file md5check.py
+@brief Replacement for message template compatibility verifier.
+
+$LicenseInfo:firstyear=20i10&license=viewergpl$
+Copyright (c) 2010, 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://secondlifegrid.net/programs/open_source/licensing/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://secondlifegrid.net/programs/open_source/licensing/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$
+"""
+
+import sys
+import hashlib
+
+if len(sys.argv) != 3:
+    print """Usage: %s --create|<hash-digest> <file>
+
+Creates an md5sum hash digest of the specified file content
+and compares it with the given hash digest.
+
+If --create is used instead of a hash digest, it will simply
+print out the hash digest of specified file content.
+""" % sys.argv[0]
+    sys.exit(1)
+
+if sys.argv[2] == '-':
+    fh = sys.stdin
+    filename = "<stdin>"
+else:
+    filename = sys.argv[2]
+    fh = open(filename)
+
+hexdigest = hashlib.md5(fh.read()).hexdigest()
+if sys.argv[1] == '--create':
+    print hexdigest
+elif hexdigest == sys.argv[1]:
+    print "md5sum check passed:", filename
+else:
+    print "md5sum check FAILED:", filename
+    sys.exit(1)