From 24b26d71ee01211aa796b8061b66ec06a133e4ce Mon Sep 17 00:00:00 2001
From: Dave Simmons <simon@lindenlab.com>
Date: Fri, 20 Mar 2009 20:00:47 +0000
Subject: [PATCH] svn merge -r113004:115000
 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.26 Merge
 latest 1.26 into trunk

---
 etc/message.xml                               |  20 +-
 indra/cmake/LLAddBuildTest.cmake              |  19 +-
 indra/llcommon/indra_constants.h              |   5 +-
 indra/llcommon/lldate.h                       |   2 +-
 indra/llcommon/llqueuedthread.cpp             |   3 +-
 indra/llcommon/llstring.h                     |   3 +-
 indra/llmessage/llcachename.cpp               |   1 +
 indra/llmessage/llclassifiedflags.cpp         |  25 +-
 indra/llmessage/llclassifiedflags.h           |  17 +-
 indra/llmessage/lldispatcher.cpp              |  32 ++-
 indra/llmessage/lleventflags.h                |   1 +
 indra/llmessage/llhttpclient.cpp              |  14 ++
 indra/llmessage/llhttpclientadapter.cpp       |  11 +-
 indra/llmessage/llqueryflags.h                |  32 +++
 indra/llmessage/llsdmessagereader.cpp         |   6 +
 indra/llmessage/message.cpp                   |  26 +-
 indra/llmessage/message.h                     |   1 +
 indra/llmessage/message_prehash.cpp           |   3 +
 indra/llmessage/message_prehash.h             |   2 +
 indra/llvfs/llvfs.cpp                         |  55 ++--
 indra/llxml/CMakeLists.txt                    |   1 +
 indra/llxml/llcontrol.cpp                     |  53 +++-
 indra/llxml/llcontrol.h                       |  13 +-
 indra/llxml/llcontrolgroupreader.h            |  51 ++++
 indra/newview/CMakeLists.txt                  |   5 +
 indra/newview/app_settings/settings.xml       | 234 ++++++++++++++++--
 indra/newview/llagent.cpp                     | 133 ++++++++--
 indra/newview/llagent.h                       |  35 ++-
 indra/newview/llagentaccess.cpp               | 154 ++++++++++++
 indra/newview/llagentaccess.h                 |  69 ++++++
 indra/newview/llfloaterbuyland.cpp            |   6 +
 indra/newview/llfloaterland.cpp               |  86 +++++--
 indra/newview/llfloaterland.h                 |   3 +
 indra/newview/llfloaterregioninfo.cpp         |  17 +-
 indra/newview/llfloatersettingsdebug.cpp      |   5 +-
 indra/newview/llfloaterworldmap.cpp           |  17 +-
 indra/newview/llpanelclassified.cpp           |  10 +-
 indra/newview/llpanelplace.cpp                |   9 +-
 indra/newview/llprogressview.cpp              |   3 +-
 indra/newview/llstartup.cpp                   |  28 ++-
 indra/newview/llviewermenu.cpp                |  13 +-
 indra/newview/llviewermenu.h                  |   1 -
 indra/newview/llviewermessage.cpp             | 215 ++++++++++++++--
 indra/newview/llviewermessage.h               |   1 +
 indra/newview/llviewerregion.cpp              |  79 +++---
 indra/newview/llviewerregion.h                |  24 +-
 indra/newview/llviewerwindow.cpp              |   4 +-
 indra/newview/llworldmap.cpp                  |  31 ++-
 indra/newview/llworldmap.h                    |   2 +
 indra/newview/llworldmapview.cpp              |  96 ++++++-
 indra/newview/llworldmapview.h                |   2 +
 .../default/textures/icon_event_adult.tga     | Bin 0 -> 648 bytes
 .../default/textures/icon_for_sale_adult.tga  | Bin 0 -> 743 bytes
 .../default/textures/map_event_adult.tga      | Bin 0 -> 648 bytes
 indra/newview/tests/llagentaccess_test.cpp    | 234 ++++++++++++++++++
 scripts/messages/message_template.msg         |  24 +-
 56 files changed, 1686 insertions(+), 250 deletions(-)
 create mode 100644 indra/llxml/llcontrolgroupreader.h
 create mode 100644 indra/newview/llagentaccess.cpp
 create mode 100644 indra/newview/llagentaccess.h
 create mode 100644 indra/newview/skins/default/textures/icon_event_adult.tga
 create mode 100644 indra/newview/skins/default/textures/icon_for_sale_adult.tga
 create mode 100644 indra/newview/skins/default/textures/map_event_adult.tga
 create mode 100644 indra/newview/tests/llagentaccess_test.cpp

diff --git a/etc/message.xml b/etc/message.xml
index 406235ff73..ddfd3e982e 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -474,8 +474,16 @@
 					<key>trusted-sender</key>
 					<boolean>true</boolean>
 				</map>
-				
-				<key>CrossedRegion</key>
+
+        <key>TeleportFailed</key>
+        <map>
+          <key>flavor</key>
+          <string>llsd</string>
+          <key>trusted-sender</key>
+          <boolean>true</boolean>
+        </map>
+
+        <key>CrossedRegion</key>
 				<map>
 					<key>flavor</key>
 					<string>llsd</string>
@@ -524,14 +532,6 @@
 					<boolean>false</boolean>
 				</map>
 
-				<key>EstateOwnerMessage</key>
-				<map>
-					<key>flavor</key>
-					<string>llsd</string>
-					<key>trusted-sender</key>
-					<boolean>false</boolean>
-				</map>
-
 				<key>RpcScriptRequestInboundForward</key>
 				<map>
 					<key>flavor</key>
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 918a90e982..08151bc732 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -88,10 +88,11 @@ MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
     GET_TARGET_PROPERTY(TEST_EXE ${name}_test LOCATION)
     SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}_test_ok.txt)
 
-    SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
-    IF (wrapper)
-      SET(TEST_CMD ${PYTHON_EXECUTABLE} ${wrapper} ${TEST_CMD})
-    ENDIF (wrapper)
+    IF ("${wrapper}" STREQUAL "")
+      SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
+    ELSE ("${wrapper}" STREQUAL "")
+      SET(TEST_CMD ${PYTHON_EXECUTABLE} ${wrapper} ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
+    ENDIF ("${wrapper}" STREQUAL "")
 
     #MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_cmd  = ${TEST_CMD}")
     SET(TEST_SCRIPT_CMD 
@@ -103,11 +104,11 @@ MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
 
     #MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_script  = ${TEST_SCRIPT_CMD}")
     ADD_CUSTOM_COMMAND(
-      OUTPUT ${TEST_OUTPUT}
-      COMMAND ${TEST_SCRIPT_CMD}
-      DEPENDS ${name}_test
-      WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-      )
+        OUTPUT ${TEST_OUTPUT}
+        COMMAND ${TEST_SCRIPT_CMD}
+        DEPENDS ${name}_test
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        )
 
     ADD_CUSTOM_TARGET(${name}_test_ok ALL DEPENDS ${TEST_OUTPUT})
     IF (${parent})
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 4109eade19..ae7863d100 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -244,12 +244,11 @@ const F32 DEFAULT_WATER_HEIGHT 	= 20.0f;
 
 // Maturity ratings for simulators
 const U8 SIM_ACCESS_MIN 	= 0;		// Treated as 'unknown', usually ends up being SIM_ACCESS_PG
-const U8 SIM_ACCESS_TRIAL	= 7;
 const U8 SIM_ACCESS_PG		= 13;
 const U8 SIM_ACCESS_MATURE	= 21;
 const U8 SIM_ACCESS_ADULT	= 42;		// Seriously Adult Only
 const U8 SIM_ACCESS_DOWN	= 254;
-const U8 SIM_ACCESS_MAX 	= SIM_ACCESS_MATURE;
+const U8 SIM_ACCESS_MAX 	= SIM_ACCESS_ADULT;
 
 // group constants
 const S32 MAX_AGENT_GROUPS = 25;
@@ -360,6 +359,8 @@ const U32 MAP_ITEM_POPULAR = 0x04;
 const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06;
 const U32 MAP_ITEM_LAND_FOR_SALE = 0x07;
 const U32 MAP_ITEM_CLASSIFIED = 0x08;
+const U32 MAP_ITEM_ADULT_EVENT = 0x09;
+const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a;
 
 // Crash reporter behavior
 const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml";
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 36c14a7c7c..32825b18dc 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -55,7 +55,7 @@ public:
 	LLDate();
 
 	/** 
-	 * @brief Construct a date equal the source date.
+	 * @brief Construct a date equal to the source date.
 	 */
 	LLDate(const LLDate& date);
 
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 7e0fb27d60..cd53e701d2 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -197,8 +197,9 @@ LLQueuedThread::handle_t LLQueuedThread::generateHandle()
 	{
 		mNextHandle++;
 	}
+	const LLQueuedThread::handle_t res = mNextHandle++;
 	unlockData();
-	return mNextHandle++;
+	return res;
 }
 
 // MAIN thread
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 8915890e18..99a9b9e269 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -40,9 +40,10 @@
 #include <wchar.h>
 #endif
 
+#include <string.h>
+
 #if LL_SOLARIS
 // stricmp and strnicmp do not exist on Solaris:
-#include <string.h>
 #define stricmp strcasecmp
 #define strnicmp strncasecmp
 #endif
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 776f2b1535..1e6584a085 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -566,6 +566,7 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb
 	if(id.isNull())
 	{
 		callback(id, CN_NOBODY, "", is_group, user_data);
+		return;
 	}
 
 	LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
diff --git a/indra/llmessage/llclassifiedflags.cpp b/indra/llmessage/llclassifiedflags.cpp
index 62415cde5f..da608e490b 100644
--- a/indra/llmessage/llclassifiedflags.cpp
+++ b/indra/llmessage/llclassifiedflags.cpp
@@ -41,18 +41,35 @@
 #include "linden_common.h"
 
 #include "llclassifiedflags.h"
- 
-ClassifiedFlags pack_classified_flags(BOOL is_mature, BOOL auto_renew)
+
+ClassifiedFlags pack_classified_flags_request(BOOL auto_renew, BOOL inc_pg, BOOL inc_mature, BOOL inc_adult)
+{
+	U8 rv = 0;
+	if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG;
+	if(inc_mature) rv |= CLASSIFIED_QUERY_INC_MATURE;
+	if (inc_pg && !inc_mature) rv |= CLASSIFIED_FLAG_MATURE;
+	if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT;
+	if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW;
+	return rv;
+}
+
+ClassifiedFlags pack_classified_flags(BOOL auto_renew, BOOL inc_pg, BOOL inc_mature, BOOL inc_adult)
 {
 	U8 rv = 0;
-	if(is_mature) rv |= CLASSIFIED_FLAG_MATURE;
+	if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG;
+	if(inc_mature)
+    {
+        rv |= CLASSIFIED_QUERY_INC_MATURE;
+        rv |= CLASSIFIED_FLAG_MATURE;
+    }
+	if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT;
 	if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW;
 	return rv;
 }
 
 bool is_cf_mature(ClassifiedFlags flags)
 {
-	return ((flags & CLASSIFIED_FLAG_MATURE) != 0);
+	return ((flags & CLASSIFIED_FLAG_MATURE) != 0) || ((flags & CLASSIFIED_QUERY_INC_MATURE) != 0);
 }
 
 // Deprecated, but leaving commented out because someday we might
diff --git a/indra/llmessage/llclassifiedflags.h b/indra/llmessage/llclassifiedflags.h
index 1205112d41..9d3e49b90c 100644
--- a/indra/llmessage/llclassifiedflags.h
+++ b/indra/llmessage/llclassifiedflags.h
@@ -43,12 +43,23 @@ const U8 CLASSIFIED_FLAG_UPDATE_TIME= 1 << 4;
 const U8 CLASSIFIED_FLAG_AUTO_RENEW = 1 << 5;
 
 const U8 CLASSIFIED_QUERY_FILTER_MATURE		= 1 << 1;
-const U8 CLASSIFIED_QUERY_FILTER_ENABLED	= 1 << 2;
-const U8 CLASSIFIED_QUERY_FILTER_PRICE		= 1 << 3;
+//const U8 CLASSIFIED_QUERY_FILTER_ENABLED	= 1 << 2;
+//const U8 CLASSIFIED_QUERY_FILTER_PRICE	= 1 << 3;
+
+// These are new with Adult-enabled viewers (1.23 and later)
+const U8 CLASSIFIED_QUERY_INC_PG			= 1 << 2;
+const U8 CLASSIFIED_QUERY_INC_MATURE		= 1 << 3;
+const U8 CLASSIFIED_QUERY_INC_ADULT			= 1 << 6;
+const U8 CLASSIFIED_QUERY_INC_NEW_VIEWER	= (CLASSIFIED_QUERY_INC_PG | CLASSIFIED_QUERY_INC_MATURE | CLASSIFIED_QUERY_INC_ADULT);
 
 const S32 MAX_CLASSIFIEDS = 100;
 
-ClassifiedFlags pack_classified_flags(BOOL is_mature, BOOL auto_renew);
+// This function is used in AO viewers to pack old query flags into the request 
+// so that they can talk to old dataservers properly. When the AO servers are deployed on agni
+// we can revert back to ClassifiedFlags pack_classified_flags and get rider of this one.
+ClassifiedFlags pack_classified_flags_request(BOOL auto_renew, BOOL is_pg, BOOL is_mature, BOOL is_adult);
+
+ClassifiedFlags pack_classified_flags(BOOL auto_renew, BOOL is_pg, BOOL is_mature, BOOL is_adult);
 bool is_cf_mature(ClassifiedFlags flags);
 //bool is_cf_enabled(ClassifiedFlags flags);
 bool is_cf_update_time(ClassifiedFlags flags);
diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp
index 7ce3d11be4..bb7c833b49 100644
--- a/indra/llmessage/lldispatcher.cpp
+++ b/indra/llmessage/lldispatcher.cpp
@@ -111,14 +111,40 @@ bool LLDispatcher::unpackMessage(
 		LLUUID& invoice,
 		LLDispatcher::sparam_t& parameters)
 {
+	char buf[MAX_STRING];	/*Flawfinder: ignore*/
 	msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
 	msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
+	S32 size;
 	S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
 	for (S32 i = 0; i < count; ++i)
 	{
-		std::string parameter;
-		msg->getStringFast(_PREHASH_ParamList,_PREHASH_Parameter, parameter, i);
-		parameters.push_back(parameter);
+		// we treat the SParam as binary data (since it might be an 
+		// LLUUID in compressed form which may have embedded \0's,)
+		size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter);
+		msg->getBinaryDataFast(
+			_PREHASH_ParamList, _PREHASH_Parameter,
+			buf, size, i, MAX_STRING-1);
+
+		// If the last byte of the data is 0x0, this is either a normally
+		// packed string, or a binary packed UUID (which for these messages
+		// are packed with a 17th byte 0x0).  Unpack into a std::string
+		// without the trailing \0, so "abc\0" becomes std::string("abc", 3)
+		// which matches const char* "abc".
+		if (size > 0
+			&& buf[size-1] == 0x0)
+		{
+			// special char*/size constructor because UUIDs may have embedded
+			// 0x0 bytes.
+			std::string binary_data(buf, size-1);
+			parameters.push_back(binary_data);
+		}
+		else
+		{
+			// This is either a NULL string, or a string that was packed 
+			// incorrectly as binary data, without the usual trailing '\0'.
+			std::string string_data(buf, size);
+			parameters.push_back(string_data);
+		}
 	}
 	return true;
 }
diff --git a/indra/llmessage/lleventflags.h b/indra/llmessage/lleventflags.h
index 8d4d08be63..965d978a5c 100644
--- a/indra/llmessage/lleventflags.h
+++ b/indra/llmessage/lleventflags.h
@@ -37,5 +37,6 @@ const U32 EVENT_FLAG_NONE   = 0x0000;
 
 // set for mature events
 const U32 EVENT_FLAG_MATURE = 0x0001;
+const U32 EVENT_FLAG_ADULT  = 0x0002;
 
 #endif
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 884ec1309d..a6041b4139 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -402,6 +402,14 @@ LLSD LLHTTPClient::blockingGet(const std::string& url)
 	curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer);
 	curl_easy_setopt(curlp, CURLOPT_FAILONERROR, 1);
 
+	struct curl_slist *header_list = NULL;
+	header_list = curl_slist_append(header_list, "Accept: application/llsd+xml");
+	CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, header_list);
+	if ( curl_result != CURLE_OK )
+	{
+		llinfos << "Curl is hosed - can't add Accept header for llsd+xml" << llendl;
+	}
+
 	LLSD response = LLSD::emptyMap();
 
 	S32 curl_success = curl_easy_perform(curlp);
@@ -423,6 +431,12 @@ LLSD LLHTTPClient::blockingGet(const std::string& url)
 		response["body"] = http_buffer.asLLSD();
 	}
 	
+	if(header_list)
+	{	// free the header list  
+		curl_slist_free_all(header_list); 
+		header_list = NULL;
+	}
+
 	curl_easy_cleanup(curlp);
 
 	return response;
diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp
index f0e7654646..bbb56960df 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -38,12 +38,19 @@ LLHTTPClientAdapter::~LLHTTPClientAdapter()
 
 void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder) 
 {
-	LLHTTPClient::get(url, responder);
+	LLSD empty_pragma_header;
+	// Pragma is required to stop curl adding "no-cache"
+	// Space is required to stop llurlrequest from turnning off proxying
+	empty_pragma_header["Pragma"] = " "; 
+	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
 
 void LLHTTPClientAdapter::get(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers) 
 {
-	LLHTTPClient::get(url, responder, headers);
+	LLSD empty_pragma_header = headers;
+	// as above
+	empty_pragma_header["Pragma"] = " ";
+	LLHTTPClient::get(url, responder, empty_pragma_header);
 }
 
 void LLHTTPClientAdapter::put(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder) 
diff --git a/indra/llmessage/llqueryflags.h b/indra/llmessage/llqueryflags.h
index d0496cc077..960d7777a7 100644
--- a/indra/llmessage/llqueryflags.h
+++ b/indra/llmessage/llqueryflags.h
@@ -65,6 +65,13 @@ const U32 DFQ_LIMIT_BY_AREA		= 0x1 << 21;
 const U32 DFQ_FILTER_MATURE		= 0x1 << 22;
 const U32 DFQ_PG_PARCELS_ONLY	= 0x1 << 23;
 
+const U32 DFQ_INC_PG		 	= 0x1 << 24;	// Flags appear in 1.23 viewer or later
+const U32 DFQ_INC_MATURE     	= 0x1 << 25;
+const U32 DFQ_INC_ADULT     	= 0x1 << 26;
+const U32 DFQ_INC_NEW_VIEWER	= (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT);	// Indicates 1.23 viewer or later
+
+const U32 DFQ_ADULT_SIMS_ONLY	= 0x1 << 27;
+
 // Sell Type flags
 const U32 ST_AUCTION	= 0x1 << 1;
 const U32 ST_NEWBIE		= 0x1 << 2;
@@ -73,4 +80,29 @@ const U32 ST_ESTATE		= 0x1 << 4;
 
 const U32 ST_ALL		= 0xFFFFFFFF;
 
+// status flags embedded in search replay messages of classifieds, events, groups, and places.
+// Places
+const U32 STATUS_SEARCH_PLACES_NONE				= 0x0;
+const U32 STATUS_SEARCH_PLACES_BANNEDWORD		= 0x1 << 0;
+const U32 STATUS_SEARCH_PLACES_SHORTSTRING		= 0x1 << 1;
+const U32 STATUS_SEARCH_PLACES_FOUNDNONE		= 0x1 << 2;
+const U32 STATUS_SEARCH_PLACES_SEARCHDISABLED	= 0x1 << 3;
+const U32 STATUS_SEARCH_PLACES_ESTATEEMPTY		= 0x1 << 4;
+// Events
+const U32 STATUS_SEARCH_EVENTS_NONE				= 0x0;
+const U32 STATUS_SEARCH_EVENTS_BANNEDWORD		= 0x1 << 0;
+const U32 STATUS_SEARCH_EVENTS_SHORTSTRING		= 0x1 << 1;
+const U32 STATUS_SEARCH_EVENTS_FOUNDNONE		= 0x1 << 2;
+const U32 STATUS_SEARCH_EVENTS_SEARCHDISABLED	= 0x1 << 3;
+const U32 STATUS_SEARCH_EVENTS_NODATEOFFSET		= 0x1 << 4;
+const U32 STATUS_SEARCH_EVENTS_NOCATEGORY		= 0x1 << 5;
+const U32 STATUS_SEARCH_EVENTS_NOQUERY		= 0x1 << 6;
+
+//Classifieds
+const U32 STATUS_SEARCH_CLASSIFIEDS_NONE			= 0x0;
+const U32 STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD		= 0x1 << 0;
+const U32 STATUS_SEARCH_CLASSIFIEDS_SHORTSTRING		= 0x1 << 1;
+const U32 STATUS_SEARCH_CLASSIFIEDS_FOUNDNONE		= 0x1 << 2;
+const U32 STATUS_SEARCH_CLASSIFIEDS_SEARCHDISABLED	= 0x1 << 3;
+
 #endif
diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp
index c47d4b78bc..e699ec9e28 100755
--- a/indra/llmessage/llsdmessagereader.cpp
+++ b/indra/llmessage/llsdmessagereader.cpp
@@ -108,6 +108,12 @@ void LLSDMessageReader::getBinaryData(const char *block, const char *var,
 		data_size = max_size;
 	}
 	
+	// Calls to memcpy will fail if data_size is not positive.
+	// Phoenix 2009-02-27
+	if(data_size <= 0)
+	{
+		return;
+	}
 	memcpy(datap, &(data[0]), data_size);
 }
 
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 8ab12ce991..78af35bf65 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -923,6 +923,28 @@ LLSD LLMessageSystem::wrapReceivedTemplateData() const
 	}
 }
 
+LLSD LLMessageSystem::wrapBuiltTemplateData() const
+{
+	LLSD result;
+	if (mLLSDMessageBuilder == mMessageBuilder)
+	{
+		result = getBuiltMessageLLSD();
+	}
+	else
+	{
+		U8 buffer[MAX_BUFFER_SIZE];
+		const U8 offset_to_data = 0;
+		U32 size = mTemplateMessageBuilder->buildMessage(
+			buffer, MAX_BUFFER_SIZE,
+			offset_to_data);
+		std::vector<U8> binary_data(buffer, buffer+size);
+		LLSD wrapped_data = LLSD::emptyMap();
+		wrapped_data["binary-template-data"] = binary_data;
+		result = wrapped_data;
+	}
+	return result;
+}
+
 LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const
 {
 	const std::string& name = mMessageReader->getMessageName();
@@ -934,7 +956,7 @@ LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const
 LLStoredMessagePtr LLMessageSystem::getBuiltMessage() const
 {
 	const std::string& name = mMessageBuilder->getMessageName();
-	LLSD message = getBuiltMessageLLSD();
+	LLSD message = wrapBuiltTemplateData();
 
 	return LLStoredMessagePtr(new LLStoredMessage(name, message));
 }
@@ -1131,7 +1153,7 @@ LLHTTPClient::ResponderPtr LLMessageSystem::createResponder(const std::string& n
 		return new LLFnPtrResponder(
 			NULL,
 			NULL,
-			mMessageBuilder->getMessageName());
+			name);
 	}
 }
 
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 4fda8f01d7..b25b27eb0f 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -395,6 +395,7 @@ private:
 	// but while the unsafe code is run in old processes, this
 	// method should be used to forward unsafe messages.
 	LLSD wrapReceivedTemplateData() const;
+	LLSD wrapBuiltTemplateData() const;
 
 public:
 
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index d554ec2f34..716d895334 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -314,6 +314,7 @@ char* _PREHASH_TextColor = LLMessageStringTable::getInstance()->getString("TextC
 char* _PREHASH_SlaveID = LLMessageStringTable::getInstance()->getString("SlaveID");
 char* _PREHASH_Charter = LLMessageStringTable::getInstance()->getString("Charter");
 char* _PREHASH_AlertData = LLMessageStringTable::getInstance()->getString("AlertData");
+char* _PREHASH_AlertInfo = LLMessageStringTable::getInstance()->getString("AlertInfo");
 char* _PREHASH_TargetBlock = LLMessageStringTable::getInstance()->getString("TargetBlock");
 char* _PREHASH_CheckParcelAuctions = LLMessageStringTable::getInstance()->getString("CheckParcelAuctions");
 char* _PREHASH_ParcelAuctions = LLMessageStringTable::getInstance()->getString("ParcelAuctions");
@@ -1375,4 +1376,6 @@ char* _PREHASH_AgeVerificationBlock = LLMessageStringTable::getInstance()->getSt
 char* _PREHASH_UCoord = LLMessageStringTable::getInstance()->getString("UCoord");
 char* _PREHASH_VCoord = LLMessageStringTable::getInstance()->getString("VCoord");
 char* _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex");
+char* _PREHASH_StatusData = LLMessageStringTable::getInstance()->getString("StatusData");
+
 
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index e71518c6d6..c7bb7fff26 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -314,6 +314,7 @@ extern char * _PREHASH_TextColor;
 extern char * _PREHASH_SlaveID;
 extern char * _PREHASH_Charter;
 extern char * _PREHASH_AlertData;
+extern char * _PREHASH_AlertInfo;
 extern char * _PREHASH_TargetBlock;
 extern char * _PREHASH_CheckParcelAuctions;
 extern char * _PREHASH_ParcelAuctions;
@@ -1375,5 +1376,6 @@ extern char * _PREHASH_AgeVerificationBlock;
 extern char * _PREHASH_UCoord;
 extern char * _PREHASH_VCoord;
 extern char * _PREHASH_FaceIndex;
+extern char * _PREHASH_StatusData;
 
 #endif
diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp
index 8c0ea5fd14..e5ffce4ffc 100644
--- a/indra/llvfs/llvfs.cpp
+++ b/indra/llvfs/llvfs.cpp
@@ -232,7 +232,7 @@ struct LLVFSFileBlock_less
 
 const S32 LLVFSFileBlock::SERIAL_SIZE = 34;
      
-    
+
 LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)
 :	mRemoveAfterCrash(remove_after_crash)
 {
@@ -400,6 +400,12 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
 				mDataFP = NULL;
 				LLFile::remove( mDataFilename );
 
+				LL_WARNS("VFS") << "Deleted corrupt VFS files " 
+					<< mDataFilename 
+					<< " and "
+					<< mIndexFilename
+					<< LL_ENDL;
+
 				mValid = VFSVALID_BAD_CORRUPT;
 				return;
 			}
@@ -505,6 +511,13 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
 						<< " ID " << cur_file_block->mFileID 
 						<< " type " << cur_file_block->mFileType 
 						<< LL_ENDL;
+
+					LL_WARNS("VFS") << "Deleted corrupt VFS files " 
+						<< mDataFilename 
+						<< " and "
+						<< mIndexFilename
+						<< LL_ENDL;
+
 					mValid = VFSVALID_BAD_CORRUPT;
 					return;
 				}
@@ -718,8 +731,14 @@ S32  LLVFS::getMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
 
 BOOL LLVFS::checkAvailable(S32 max_size)
 {
+	lockData();
+	
 	blocks_length_map_t::iterator iter = mFreeBlocksByLength.lower_bound(max_size); // first entry >= size
-	return (iter == mFreeBlocksByLength.end()) ? FALSE : TRUE;
+	const BOOL res(iter == mFreeBlocksByLength.end() ? FALSE : TRUE);
+
+	unlockData();
+	
+	return res;
 }
 
 BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type, S32 max_size)
@@ -825,13 +844,20 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
     
 			if (free_block)
 			{
+				// Save location where data is going, useFreeSpace will move free_block->mLocation;
+				U32 new_data_location = free_block->mLocation;
+
+				//mark the free block as used so it does not
+				//interfere with other operations such as addFreeBlock
+				useFreeSpace(free_block, max_size);		// useFreeSpace takes ownership (and may delete) free_block
+
 				if (block->mLength > 0)
 				{
 					// create a new free block where this file used to be
 					LLVFSBlock *new_free_block = new LLVFSBlock(block->mLocation, block->mLength);
 
 					addFreeBlock(new_free_block);
-    
+					
 					if (block->mSize > 0)
 					{
 						// move the file into the new block
@@ -839,7 +865,7 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
 						fseek(mDataFP, block->mLocation, SEEK_SET);
 						if (fread(buffer, block->mSize, 1, mDataFP) == 1)
 						{
-							fseek(mDataFP, free_block->mLocation, SEEK_SET);
+							fseek(mDataFP, new_data_location, SEEK_SET);
 							if (fwrite(buffer, block->mSize, 1, mDataFP) != 1)
 							{
 								llwarns << "Short write" << llendl;
@@ -852,13 +878,10 @@ BOOL LLVFS::setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type
 					}
 				}
     
-				block->mLocation = free_block->mLocation;
+				block->mLocation = new_data_location;
     
 				block->mLength = max_size;
 
-				// Must call useFreeSpace before sync(), as sync()
-				// unlocks data structures.
-				useFreeSpace(free_block, max_size);
 
 				sync(block);
 
@@ -1073,14 +1096,14 @@ S32 LLVFS::getData(const LLUUID &file_id, const LLAssetType::EType file_type, U8
 		}
 	}
 
-	unlockData();
-
 	if (do_read)
 	{
 		fseek(mDataFP, location, SEEK_SET);
 		bytesread = (S32)fread(buffer, 1, length, mDataFP);
 	}
 	
+	unlockData();
+
 	return bytesread;
 }
     
@@ -1145,8 +1168,6 @@ S32 LLVFS::storeData(const LLUUID &file_id, const LLAssetType::EType file_type,
 			}
 			U32 file_location = location + block->mLocation;
 			
-			unlockData();
-			
 			fseek(mDataFP, file_location, SEEK_SET);
 			S32 write_len = (S32)fwrite(buffer, 1, length, mDataFP);
 			if (write_len != length)
@@ -1155,7 +1176,6 @@ S32 LLVFS::storeData(const LLUUID &file_id, const LLAssetType::EType file_type,
 			}
 			// fflush(mDataFP);
 			
-			lockData();
 			if (location + length > block->mSize)
 			{
 				block->mSize = location + write_len;
@@ -1404,7 +1424,7 @@ void LLVFS::addFreeBlock(LLVFSBlock *block)
 // 	}
 //}
 	
-
+// length bytes from free_block are going to be used (so they are no longer free)
 void LLVFS::useFreeSpace(LLVFSBlock *free_block, S32 length)
 {
 	if (free_block->mLength == length)
@@ -1487,8 +1507,6 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove)
 		block->serialize(buffer);
 	}
 
-	unlockData();
-
 	// If set_index_to_end, file pointer is already at seek_pos
 	// and we don't need to do anything.  Only seek if not at end.
 	if (!set_index_to_end)
@@ -1500,11 +1518,10 @@ void LLVFS::sync(LLVFSFileBlock *block, BOOL remove)
 	{
 		llwarns << "Short write" << llendl;
 	}
-	
+
+	// *NOTE:  Why was this commented out?
 	// fflush(mIndexFP);
 	
-	lockData();
-	
 	return;
 }
 
diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt
index 9febd9775d..487c5b9a8a 100644
--- a/indra/llxml/CMakeLists.txt
+++ b/indra/llxml/CMakeLists.txt
@@ -23,6 +23,7 @@ set(llxml_HEADER_FILES
     CMakeLists.txt
 
     llcontrol.h
+    llcontrolgroupreader.h
     llxmlnode.h
     llxmlparser.h
     llxmltree.h
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 9bf1d122bc..d9ed45ab9d 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -102,11 +102,12 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
 
 LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
 							 LLSD initial, const std::string& comment,
-							 bool persist)
+							 bool persist, bool hidefromsettingseditor)
 	: mName(name),
 	  mComment(comment),
 	  mType(type),
-	  mPersist(persist)
+	  mPersist(persist),
+	  mHideFromSettingsEditor(hidefromsettingseditor)
 {
 	if (mPersist && mComment.empty())
 	{
@@ -213,6 +214,11 @@ void LLControlVariable::setPersist(bool state)
 	mPersist = state;
 }
 
+void LLControlVariable::setHiddenFromSettingsEditor(bool hide)
+{
+	mHideFromSettingsEditor = hide;
+}
+
 void LLControlVariable::setComment(const std::string& comment)
 {
 	mComment = comment;
@@ -296,17 +302,27 @@ std::string LLControlGroup::typeEnumToString(eControlType typeenum)
 	return mTypeString[typeenum];
 }
 
-BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist)
+BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor)
 {
-	if(mNameTable.find(name) != mNameTable.end())
-	{
-		llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl;
-		mNameTable[name]->setValue(initial_val);
-		return TRUE;
+	LLControlVariable* existing_control = getControl(name);
+	if (existing_control)
+ 	{
+		if (persist && existing_control->isType(type))
+		{
+			// Sometimes we need to declare a control *after* it has been loaded from a settings file.
+			LLSD cur_value = existing_control->getValue(); // get the current value
+			existing_control->setDefaultValue(initial_val); // set the default to the declared value
+			existing_control->setValue(cur_value); // now set to the loaded value
+		}
+		else
+		{
+			llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl;
+		}
+ 		return TRUE;
 	}
 
 	// if not, create the control and add it to the name table
-	LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist);
+	LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor);
 	mNameTable[name] = control;	
 	return TRUE;
 }
@@ -1043,7 +1059,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 	}
 
 	U32	validitems = 0;
-	bool persist = false;
+	bool persist = true;
+	bool hidefromsettingseditor = false;
 	for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
 	{
 		name = (*itr).first;
@@ -1054,6 +1071,18 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 			persist = control_map["Persist"].asInteger();
 		}
 		
+		// Sometimes we want to use the settings system to provide cheap persistence, but we
+		// don't want the settings themselves to be easily manipulated in the UI because 
+		// doing so can cause support problems. So we have this option:
+		if(control_map.has("HideFromEditor"))
+		{
+			hidefromsettingseditor = control_map["HideFromEditor"].asInteger();
+		}
+		else
+		{
+			hidefromsettingseditor = false;
+		}
+		
 		// If the control exists just set the value from the input file.
 		LLControlVariable* existing_control = getControl(name);
 		if(existing_control)
@@ -1067,6 +1096,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 				{
 					existing_control->setDefaultValue(control_map["Value"]);
 					existing_control->setPersist(persist);
+					existing_control->setHiddenFromSettingsEditor(hidefromsettingseditor);
 					existing_control->setComment(control_map["Comment"].asString());
 				}
 				else
@@ -1090,7 +1120,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
 						   typeStringToEnum(control_map["Type"].asString()), 
 						   control_map["Value"], 
 						   control_map["Comment"].asString(), 
-						   persist
+						   persist,
+						   hidefromsettingseditor
 						   );
 		}
 		
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 3be781ef78..ba0a1c7cbf 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -39,6 +39,8 @@
 #include "llstring.h"
 #include "llrect.h"
 
+#include "llcontrolgroupreader.h"
+
 #include <vector>
 
 // *NOTE: boost::visit_each<> generates warning 4675 on .net 2003
@@ -93,7 +95,8 @@ private:
 	std::string		mName;
 	std::string		mComment;
 	eControlType	mType;
-	bool mPersist;
+	bool			mPersist;
+	bool			mHideFromSettingsEditor;
 	std::vector<LLSD> mValues;
 	
 	signal_t mSignal;
@@ -101,7 +104,7 @@ private:
 public:
 	LLControlVariable(const std::string& name, eControlType type,
 					  LLSD initial, const std::string& comment,
-					  bool persist = true);
+					  bool persist = true, bool hidefromsettingseditor = false);
 
 	virtual ~LLControlVariable();
 	
@@ -118,6 +121,7 @@ public:
 	bool isDefault() { return (mValues.size() == 1); }
 	bool isSaveValueDefault();
 	bool isPersisted() { return mPersist; }
+	bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
 	LLSD get()			const	{ return getValue(); }
 	LLSD getValue()		const	{ return mValues.back(); }
 	LLSD getDefault()	const	{ return mValues.front(); }
@@ -127,6 +131,7 @@ public:
 	void setValue(const LLSD& value, bool saved_value = TRUE);
 	void setDefaultValue(const LLSD& value);
 	void setPersist(bool state);
+	void setHiddenFromSettingsEditor(bool hide);
 	void setComment(const std::string& comment);
 
 	void firePropertyChanged()
@@ -140,7 +145,7 @@ private:
 };
 
 //const U32 STRING_CACHE_SIZE = 10000;
-class LLControlGroup
+class LLControlGroup : public LLControlGroupReader
 {
 protected:
 	typedef std::map<std::string, LLPointer<LLControlVariable> > ctrl_name_table_t;
@@ -164,7 +169,7 @@ public:
 	};
 	void applyToAll(ApplyFunctor* func);
 	
-	BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist);
+	BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE);
 	BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE);
 	BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE);
 	BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE);
diff --git a/indra/llxml/llcontrolgroupreader.h b/indra/llxml/llcontrolgroupreader.h
new file mode 100644
index 0000000000..960b19036e
--- /dev/null
+++ b/indra/llxml/llcontrolgroupreader.h
@@ -0,0 +1,51 @@
+/** 
+ * @file llcontrolgroupreader.h
+ * @brief Interface providing readonly access to LLControlGroup (intended for unit testing)
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCONTROLGROUPREADER_H
+#define LL_LLCONTROLGROUPREADER_H
+
+#include "stdtypes.h"
+#include <string>
+
+// Many of the types below are commented out because for the purposes of the early testing we're doing,
+// we don't need them and we don't want to pull in all the machinery to support them.
+// But the model is here for future unit test extensions.
+
+class LLControlGroupReader
+{
+public:
+	LLControlGroupReader() {}
+	virtual ~LLControlGroupReader() {}
+
+	virtual std::string 	getString(const std::string& name) = 0;
+	//virtual LLWString	getWString(const std::string& name) = 0;
+	virtual std::string	getText(const std::string& name) = 0;
+	//virtual LLVector3	getVector3(const std::string& name) = 0;
+	//virtual LLVector3d	getVector3d(const std::string& name) = 0;
+	//virtual LLRect		getRect(const std::string& name) = 0;
+	virtual BOOL		getBOOL(const std::string& name) = 0;
+	virtual S32			getS32(const std::string& name) = 0;
+	virtual F32			getF32(const std::string& name) = 0;
+	virtual U32			getU32(const std::string& name) = 0;
+	//virtual LLSD        getLLSD(const std::string& name) = 0;
+
+	//virtual LLColor4	getColor(const std::string& name) = 0;
+	//virtual LLColor4U	getColor4U(const std::string& name) = 0;
+	//virtual LLColor4	getColor4(const std::string& name) = 0;
+	//virtual LLColor3	getColor3(const std::string& name) = 0;
+};
+
+#endif /* LL_LLCONTROLGROUPREADER_H */
+
+
+
+
+
+
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1ca1b4f915..ac05a7dbd7 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -11,6 +11,7 @@ include(ELFIO)
 include(FMOD)
 include(OPENAL)
 include(FindOpenGL)
+include(LLAddBuildTest)
 include(LLAudio)
 include(LLCharacter)
 include(LLCommon)
@@ -64,6 +65,7 @@ include_directories(
 
 set(viewer_SOURCE_FILES
     llagent.cpp
+    llagentaccess.cpp
     llagentdata.cpp
     llagentlanguage.cpp
     llagentpilot.cpp
@@ -466,6 +468,7 @@ set(viewer_HEADER_FILES
     ViewerInstall.cmake
 
     llagent.h
+    llagentaccess.h
     llagentdata.h
     llagentlanguage.h
     llagentpilot.h
@@ -1566,3 +1569,5 @@ endif (DARWIN)
 if (INSTALL)
   include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake)
 endif (INSTALL)
+
+ADD_VIEWER_BUILD_TEST(llagentaccess viewer)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 41120522d5..d90882fb96 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4867,18 +4867,18 @@
       <key>Value</key>
       <real>0.0</real>
     </map>
-	<key>InstallLanguage</key>
-	<map>
-		<key>Comment</key>
-		<string>Language passed from installer (for UI)</string>
-		<key>Persist</key>
-		<integer>1</integer>
-		<key>Type</key>
-		<string>String</string>
-		<key>Value</key>
-		<string>default</string>
-	</map>
-	<key>InventoryAutoOpenDelay</key>
+    <key>InstallLanguage</key>
+    <map>
+      <key>Comment</key>
+      <string>Language passed from installer (for UI)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>default</string>
+    </map>
+    <key>InventoryAutoOpenDelay</key>
     <map>
       <key>Comment</key>
       <string>Seconds before automatically opening inventory when mouse is over inventory button when performing inventory drag and drop</string>
@@ -6409,6 +6409,17 @@
       <string>F32</string>
       <key>Value</key>
       <real>6.0</real>
+    </map>
+	<key>PreferredMaturity</key>
+    <map>
+      <key>Comment</key>
+      <string>Setting for the user's preferred maturity level.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+	  <integer>13</integer>
     </map>
     <key>PreviewAnimRect</key>
     <map>
@@ -7966,10 +7977,12 @@
       <string>URL to load for empty searches</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>http://secondlife.com/app/search/index.php?</string>
+      <string>http://search.secondlife.com/client_search.php?</string>
     </map>
     <key>SearchURLQuery</key>
     <map>
@@ -7977,10 +7990,12 @@
       <string>URL to use for searches</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>http://secondlife.com/app/search/search_proxy.php?q=[QUERY]&amp;s=[COLLECTION]&amp;</string>
+      <string>http://search.secondlife.com/client_search.php?q=[QUERY]&amp;s=[COLLECTION]&amp;</string>
     </map>
     <key>SearchURLSuffix2</key>
     <map>
@@ -7988,10 +8003,12 @@
       <string>Parameters added to end of search queries</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>String</string>
       <key>Value</key>
-      <string>lang=[LANG]&amp;m=[MATURE]&amp;t=[TEEN]&amp;region=[REGION]&amp;x=[X]&amp;y=[Y]&amp;z=[Z]&amp;session=[SESSION]</string>
+      <string>lang=[LANG]&amp;mat=[MATURITY]&amp;t=[TEEN]&amp;region=[REGION]&amp;x=[X]&amp;y=[Y]&amp;z=[Z]&amp;session=[SESSION]</string>
     </map>
     <key>SelectMovableOnly</key>
     <map>
@@ -8301,45 +8318,209 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>ShowPGSearchAll</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of search All that are flagged as PG</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>ShowMatureSearchAll</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of search All that are flagged as mature</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowAdultSearchAll</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of search All that are flagged as adult</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowPGGroups</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find groups that are flagged as PG</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>ShowMatureGroups</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find groups that are flagged as mature</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowAdultGroups</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find groups that are flagged as adult</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowPGClassifieds</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find classifieds that are flagged as PG</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>ShowMatureClassifieds</key>
     <map>
       <key>Comment</key>
       <string>Display results of find classifieds that are flagged as mature</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowAdultClassifieds</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find classifieds that are flagged as adult</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>ShowPGEvents</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find events that are flagged as PG</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>ShowMatureEvents</key>
     <map>
       <key>Comment</key>
       <string>Display results of find events that are flagged as mature</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>ShowMatureFindAll</key>
+    <key>ShowAdultEvents</key>
     <map>
       <key>Comment</key>
-      <string>Display results of find all that are in mature sims</string>
+      <string>Display results of find events that are flagged as adult</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>ShowMatureGroups</key>
+    <key>ShowPGLand</key>
     <map>
       <key>Comment</key>
-      <string>Display results of find groups that are in flagged as mature</string>
+      <string>Display results of find land sales that are flagged as PG</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>ShowMatureLand</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find land sales that are flagged as mature</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowAdultLand</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find land sales that are flagged as adult</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowPGSims</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find places or find popular that are in PG sims</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
@@ -8351,6 +8532,21 @@
       <string>Display results of find places or find popular that are in mature sims</string>
       <key>Persist</key>
       <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>ShowAdultSims</key>
+    <map>
+      <key>Comment</key>
+      <string>Display results of find places or find popular that are in adult sims</string>
+      <key>Persist</key>
+      <integer>1</integer>
+	  <key>HideFromEditor</key>
+	  <integer>1</integer>
       <key>Type</key>
       <string>Boolean</string>
       <key>Value</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 858855fe18..a894bca619 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -283,7 +283,7 @@ LLAgent::LLAgent() :
 	mbAlwaysRun(false),
 	mbRunning(false),
 
-	mAccess(SIM_ACCESS_PG),
+	mAgentAccess(gSavedSettings),
 	mTeleportState( TELEPORT_NONE ),
 	mRegionp(NULL),
 
@@ -387,9 +387,7 @@ LLAgent::LLAgent() :
 	mHaveHomePosition(FALSE),
 	mHomeRegionHandle( 0 ),
 	mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f),
-	mAdminOverride(FALSE),
 
-	mGodLevel( GOD_NOT ),
 	mNextFidgetTime(0.f),
 	mCurrentFidget(0),
 	mFirstLogin(FALSE),
@@ -4820,41 +4818,132 @@ void LLAgent::onAnimStop(const LLUUID& id)
 
 BOOL LLAgent::isGodlike() const
 {
-#ifdef HACKED_GODLIKE_VIEWER
-	return TRUE;
-#else
-	if(mAdminOverride) return TRUE;
-	return mGodLevel > GOD_NOT;
-#endif
+	return mAgentAccess.isGodlike();
 }
 
 U8 LLAgent::getGodLevel() const
 {
-#ifdef HACKED_GODLIKE_VIEWER
-	return GOD_MAINTENANCE;
-#else
-	if(mAdminOverride) return GOD_FULL;
-	return mGodLevel;
-#endif
+	return mAgentAccess.getGodLevel();
+}
+
+bool LLAgent::wantsPGOnly() const
+{
+	return mAgentAccess.wantsPGOnly();
+}
+
+bool LLAgent::canAccessMature() const
+{
+	return mAgentAccess.canAccessMature();
+}
+
+bool LLAgent::canAccessAdult() const
+{
+	return mAgentAccess.canAccessAdult();
+}
+
+bool LLAgent::prefersPG() const
+{
+	return mAgentAccess.prefersPG();
+}
+
+bool LLAgent::prefersMature() const
+{
+	return mAgentAccess.prefersMature();
+}
+	
+bool LLAgent::prefersAdult() const
+{
+	return mAgentAccess.prefersAdult();
 }
 
 bool LLAgent::isTeen() const
 {
-	return mAccess < SIM_ACCESS_MATURE;
+	return mAgentAccess.isTeen();
+}
+
+bool LLAgent::isMature() const
+{
+	return mAgentAccess.isMature();
+}
+
+bool LLAgent::isAdult() const
+{
+	return mAgentAccess.isAdult();
 }
 
 void LLAgent::setTeen(bool teen)
 {
-	if (teen)
-	{
-		mAccess = SIM_ACCESS_PG;
-	}
-	else
+	mAgentAccess.setTeen(teen);
+}
+
+//static 
+int LLAgent::convertTextToMaturity(char text)
+{
+	return LLAgentAccess::convertTextToMaturity(text);
+}
+
+bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity)
+{
+	// Update agent access preference on the server
+	std::string url = getRegion()->getCapability("UpdateAgentInformation");
+	if (!url.empty())
 	{
-		mAccess = SIM_ACCESS_MATURE;
+		// Set new access preference
+		LLSD access_prefs = LLSD::emptyMap();
+		if (preferredMaturity == SIM_ACCESS_PG)
+		{
+			access_prefs["max"] = "PG";
+		}
+		else if (preferredMaturity == SIM_ACCESS_MATURE)
+		{
+			access_prefs["max"] = "M";
+		}
+		if (preferredMaturity == SIM_ACCESS_ADULT)
+		{
+			access_prefs["max"] = "A";
+		}
+		
+		LLSD body = LLSD::emptyMap();
+		body["access_prefs"] = access_prefs;
+		llinfos << "Sending access prefs update to " << (access_prefs["max"].asString()) << " via capability to: "
+		<< url << llendl;
+		LLHTTPClient::post(url, body, new LLHTTPClient::Responder());    // Ignore response
+		return true;
 	}
+	return false;
+}
+
+BOOL LLAgent::getAdminOverride() const	
+{ 
+	return mAgentAccess.getAdminOverride(); 
 }
 
+void LLAgent::setMaturity(char text)
+{
+	mAgentAccess.setMaturity(text);
+}
+
+void LLAgent::setAdminOverride(BOOL b)	
+{ 
+	mAgentAccess.setAdminOverride(b);
+}
+
+void LLAgent::setGodLevel(U8 god_level)	
+{ 
+	mAgentAccess.setGodLevel(god_level);
+}
+
+void LLAgent::setAOTransition()
+{
+	mAgentAccess.setTransition();
+}
+
+const LLAgentAccess& LLAgent::getAgentAccess()
+{
+	return mAgentAccess;
+}
+
+
 void LLAgent::buildFullname(std::string& name) const
 {
 	if (mAvatarObject.notNull())
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 9d08c94150..fefb2a1d0b 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -40,6 +40,7 @@
 #include "llcontrol.h"
 #include "llcoordframe.h"
 #include "llevent.h"
+#include "llagentaccess.h"
 #include "llagentconstants.h"
 #include "llanimationstates.h"
 #include "lldbstrings.h"
@@ -223,8 +224,8 @@ public:
 	void			clearBusy();
 	BOOL			getBusy() const;
 
-	void			setAdminOverride(BOOL b)	{ mAdminOverride = b; }
-	void			setGodLevel(U8 god_level)	{ mGodLevel = god_level; }
+	void			setAdminOverride(BOOL b);
+	void			setGodLevel(U8 god_level);
 	void			setFirstLogin(BOOL b)		{ mFirstLogin = b; }
 	void			setGenderChosen(BOOL b)		{ mGenderChosen = b; }
 
@@ -250,8 +251,29 @@ public:
 		
 	BOOL			isGodlike() const;
 	U8				getGodLevel() const;
+	// note: this is a prime candidate for pulling out into a Maturity class
+	// rather than just expose the preference setting, we're going to actually
+	// expose what the client code cares about -- what the user should see
+	// based on a combination of the is* and prefers* flags, combined with God bit.
+	bool wantsPGOnly() const;
+	bool canAccessMature() const;
+	bool canAccessAdult() const;
+	bool prefersPG() const;
+	bool prefersMature() const;
+	bool prefersAdult() const;
 	bool isTeen() const;
+	bool isMature() const;
+	bool isAdult() const;
 	void setTeen(bool teen);
+	void setMaturity(char text);
+	static int convertTextToMaturity(char text);
+	bool sendMaturityPreferenceToServer(int preferredMaturity);
+	
+	const LLAgentAccess&  getAgentAccess();
+	
+	// This function can go away after the AO transition (see llstartup.cpp)
+	void setAOTransition();
+	
 	BOOL			isGroupTitleHidden() const		{ return mHideGroupTitle; }
 	BOOL			isGroupMember() const		{ return !mGroupID.isNull(); }		// This is only used for building titles!
 	const LLUUID	&getGroupID() const			{ return mGroupID; }
@@ -261,7 +283,7 @@ public:
 	F32				getFocusObjectDist() const	{ return mFocusObjectDist; }
 	BOOL			inPrelude();
 	BOOL			canManageEstate() const;
-	BOOL			getAdminOverride() const	{ return mAdminOverride; }
+	BOOL			getAdminOverride() const;
 
 	LLUUID			getLastChatter() const { return mLastChatterID; }
 	bool			getAlwaysRun() const { return mbAlwaysRun; }
@@ -741,8 +763,8 @@ private:
 	bool mbAlwaysRun; // should the avatar run by default rather than walk
 	bool mbRunning;	// is the avatar trying to run right now
 
-	// Access or "maturity" level
-	U8				mAccess;	// SIM_ACCESS_MATURE or SIM_ACCESS_PG
+	LLAgentAccess   mAgentAccess;
+	
 	ETeleportState	mTeleportState;
 	std::string		mTeleportMessage;
 
@@ -865,10 +887,7 @@ private:
 	LLFrameTimer	mChatTimer;
 	LLUUID			mLastChatterID;
 	F32				mNearChatRadius;
-	BOOL			mAdminOverride;
 
-	// See indra_constants.h for values.
-	U8				mGodLevel;
 	LLFrameTimer	mFidgetTimer;
 	LLFrameTimer	mFocusObjectFadeTimer;
 	F32				mNextFidgetTime;
diff --git a/indra/newview/llagentaccess.cpp b/indra/newview/llagentaccess.cpp
new file mode 100644
index 0000000000..a4fbc04855
--- /dev/null
+++ b/indra/newview/llagentaccess.cpp
@@ -0,0 +1,154 @@
+/** 
+ * @file llagentaccess.cpp
+ * @brief LLAgentAccess class implementation - manages maturity and godmode info
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+#include "llviewerprecompiledheaders.h"
+
+#include "llagentaccess.h"
+#include "indra_constants.h"
+#include "llcontrolgroupreader.h"
+
+LLAgentAccess::LLAgentAccess(LLControlGroupReader& savedSettings) :
+	mSavedSettings(savedSettings),
+	mAccess(SIM_ACCESS_PG),
+	mAdminOverride(false),
+	mGodLevel(GOD_NOT),
+	mAOTransition(false)
+{
+}
+
+bool LLAgentAccess::getAdminOverride() const	
+{ 
+	return mAdminOverride; 
+}
+
+void LLAgentAccess::setAdminOverride(bool b)
+{ 
+	mAdminOverride = b; 
+}
+
+void LLAgentAccess::setGodLevel(U8 god_level)
+{ 
+	mGodLevel = god_level; 
+}
+
+bool LLAgentAccess::isGodlike() const
+{
+#ifdef HACKED_GODLIKE_VIEWER
+	return true;
+#else
+	if(mAdminOverride) return true;
+	return mGodLevel > GOD_NOT;
+#endif
+}
+
+U8 LLAgentAccess::getGodLevel() const
+{
+#ifdef HACKED_GODLIKE_VIEWER
+	return GOD_MAINTENANCE;
+#else
+	if(mAdminOverride) return GOD_FULL;
+	return mGodLevel;
+#endif
+}
+
+bool LLAgentAccess::wantsPGOnly() const
+{
+	return (prefersPG() || isTeen()) && !isGodlike();
+}
+
+bool LLAgentAccess::canAccessMature() const
+{
+	// if you prefer mature, you're either mature or adult, and
+	// therefore can access all mature content
+	return isGodlike() || (prefersMature() && !isTeen());
+}
+
+bool LLAgentAccess::canAccessAdult() const
+{
+	// if you prefer adult, you must BE adult.
+	return isGodlike() || (prefersAdult() && isAdult());
+}
+
+bool LLAgentAccess::prefersPG() const
+{
+	U32 access = mSavedSettings.getU32("PreferredMaturity");
+	return access < SIM_ACCESS_MATURE;
+}
+
+bool LLAgentAccess::prefersMature() const
+{
+	U32 access = mSavedSettings.getU32("PreferredMaturity");
+	return access >= SIM_ACCESS_MATURE;
+}
+
+bool LLAgentAccess::prefersAdult() const
+{
+	U32 access = mSavedSettings.getU32("PreferredMaturity");
+	return access >= SIM_ACCESS_ADULT;
+}
+
+bool LLAgentAccess::isTeen() const
+{
+	return mAccess < SIM_ACCESS_MATURE;
+}
+
+bool LLAgentAccess::isMature() const
+{
+	return mAccess >= SIM_ACCESS_MATURE;
+}
+
+bool LLAgentAccess::isAdult() const
+{
+	return mAccess >= SIM_ACCESS_ADULT;
+}
+
+void LLAgentAccess::setTeen(bool teen)
+{
+	if (teen)
+	{
+		mAccess = SIM_ACCESS_PG;
+	}
+	else
+	{
+		mAccess = SIM_ACCESS_MATURE;
+	}
+}
+
+//static 
+int LLAgentAccess::convertTextToMaturity(char text)
+{
+	if ('A' == text)
+	{
+		return SIM_ACCESS_ADULT;
+	}
+	else if ('M'== text)
+	{
+		return SIM_ACCESS_MATURE;
+	}
+	else if ('P'== text)
+	{
+		return SIM_ACCESS_PG;
+	}
+	return SIM_ACCESS_MIN;
+}
+
+void LLAgentAccess::setMaturity(char text)
+{
+	mAccess = LLAgentAccess::convertTextToMaturity(text);
+}
+
+void LLAgentAccess::setTransition()
+{
+	mAOTransition = true;
+}
+
+bool LLAgentAccess::isInTransition() const
+{
+	return mAOTransition;
+}
+
diff --git a/indra/newview/llagentaccess.h b/indra/newview/llagentaccess.h
new file mode 100644
index 0000000000..dec0d76cc9
--- /dev/null
+++ b/indra/newview/llagentaccess.h
@@ -0,0 +1,69 @@
+/** 
+ * @file llagentaccess.h
+ * @brief LLAgentAccess class implementation - manages maturity and godmode info
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLAGENTACCESS_H
+#define LL_LLAGENTACCESS_H
+
+#include "stdtypes.h"
+
+// forward declaration so that we don't have to include the whole class
+class LLControlGroupReader;
+
+class LLAgentAccess
+{
+public:
+	LLAgentAccess(LLControlGroupReader& savedSettings);
+	
+	bool getAdminOverride() const;
+	void setAdminOverride(bool b);
+
+	void setGodLevel(U8 god_level);
+	bool isGodlike() const;
+	U8 getGodLevel() const;
+	
+	
+	// rather than just expose the preference setting, we're going to actually
+	// expose what the client code cares about -- what the user should see
+	// based on a combination of the is* and prefers* flags, combined with God bit.
+	bool wantsPGOnly() const;
+	bool canAccessMature() const;
+	bool canAccessAdult() const;
+	bool prefersPG() const;
+	bool prefersMature() const;
+	bool prefersAdult() const;
+	bool isTeen() const;
+	bool isMature() const;
+	bool isAdult() const;
+	
+	void setTeen(bool teen);
+	void setMaturity(char text);
+	
+	static int convertTextToMaturity(char text);
+	
+	void setTransition();	// sets the transition bit, which defaults to false
+	bool isInTransition() const;
+	
+private:
+	U8 mAccess;	// SIM_ACCESS_MATURE etc
+	U8 mGodLevel;
+	bool mAdminOverride;
+	
+	// this should be deleted after the 60-day AO transition.
+	// It should be safe to remove it in Viewer 2009
+	// It's set by a special short-term flag in login.cgi 
+	// called ao_transition. When that's gone, this can go, along with
+	// all of the code that depends on it.
+	bool mAOTransition;
+	
+	// we want this to be const but the getters for it aren't, so we're 
+	// overriding it for now
+	/* const */ LLControlGroupReader& mSavedSettings;
+};
+
+#endif // LL_LLAGENTACCESS_H
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index ff63aa1837..8e2d44911c 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -529,6 +529,12 @@ void LLFloaterBuyLandUI::updateCovenantInfo()
 		region_name->setText(region->getName());
 	}
 
+	LLTextBox* region_type = getChild<LLTextBox>("region_type_text");
+	if (region_type)
+	{
+		region_type->setText(region->getSimProductName());
+	}
+	
 	LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause");
 	if (resellable_clause)
 	{
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index e0396e070c..dc18369bb6 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -41,6 +41,7 @@
 #include "llfocusmgr.h"
 #include "llparcel.h"
 #include "message.h"
+#include "lluserauth.h"
 
 #include "llagent.h"
 #include "llfloateravatarpicker.h"
@@ -319,7 +320,9 @@ BOOL LLPanelLandGeneral::postBuild()
 	mTextSalePending = getChild<LLTextBox>("SalePending");
 	mTextOwnerLabel = getChild<LLTextBox>("Owner:");
 	mTextOwner = getChild<LLTextBox>("OwnerText");
-
+	
+	mContentRating = getChild<LLTextBox>("ContentRatingText");
+	mLandType = getChild<LLTextBox>("LandTypeText");
 	
 	mBtnProfile = getChild<LLButton>("Profile...");
 	mBtnProfile->setClickedCallback(onClickProfile, this);
@@ -445,6 +448,8 @@ void LLPanelLandGeneral::refresh()
 		mCheckContributeWithDeed->setEnabled(FALSE);
 
 		mTextOwner->setText(LLStringUtil::null);
+		mContentRating->setText(LLStringUtil::null);
+		mLandType->setText(LLStringUtil::null);
 		mBtnProfile->setLabel(getString("profile_text"));
 		mBtnProfile->setEnabled(FALSE);
 
@@ -479,6 +484,12 @@ void LLPanelLandGeneral::refresh()
 		{
 			region_xfer = TRUE;
 		}
+		
+		if (regionp)
+		{
+			mContentRating->setText(regionp->getSimAccessString());
+			mLandType->setText(regionp->getSimProductName());
+		}
 
 		// estate owner/manager cannot edit other parts of the parcel
 		BOOL estate_manager_sellable = !parcel->getAuctionID()
@@ -1768,8 +1779,7 @@ BOOL LLPanelLandOptions::postBuild()
 	mPublishHelpButton = getChild<LLButton>("?");
 	mPublishHelpButton->setClickedCallback(onClickPublishHelp, this);
 
-
-	if (gAgent.isTeen())
+	if (gAgent.wantsPGOnly())
 	{
 		// Disable these buttons if they are PG (Teen) users
 		mPublishHelpButton->setVisible(FALSE);
@@ -1777,26 +1787,14 @@ BOOL LLPanelLandOptions::postBuild()
 		mMatureCtrl->setVisible(FALSE);
 		mMatureCtrl->setEnabled(FALSE);
 	}
-
-		// Load up the category list
-	//now in xml file
-	/*
-	S32 i;
-	for (i = 0; i < LLParcel::C_COUNT; i++)
+	
+	if (!gAgent.getAgentAccess().isInTransition())
 	{
-		LLParcel::ECategory cat = (LLParcel::ECategory)i;
-
-		// Selecting Linden Location when you're not a god
-		// is also blocked on the server.
-		BOOL enabled = TRUE;
-		if (!gAgent.isGodlike()
-			&& i == LLParcel::C_LINDEN) 
-		{
-			enabled = FALSE;
-		}
-
-		mCategoryCombo->add( LLParcel::getCategoryUIString(cat), ADD_BOTTOM, enabled );
-	}*/
+		// remove category for adult if we're post-transition
+		// (this code can go away, and the category can be removed from the xml,
+		// once we've completed the transition period for adult)
+		mCategoryCombo->remove(getString("adult_land_category_label"));
+	}	
 
 	
 	mSnapshotCtrl = getChild<LLTextureCtrl>("snapshot_ctrl");
@@ -1969,11 +1967,9 @@ void LLPanelLandOptions::refresh()
 		mSetBtn->setEnabled( can_change_landing_point );
 		mClearBtn->setEnabled( can_change_landing_point );
 
-		mMatureCtrl->set(parcel->getMaturePublish());
-		mMatureCtrl->setEnabled( can_change_identity );
 		mPublishHelpButton->setEnabled( can_change_identity );
 
-		if (gAgent.isTeen())
+		if (gAgent.wantsPGOnly())
 		{
 			// Disable these buttons if they are PG (Teen) users
 			mPublishHelpButton->setVisible(FALSE);
@@ -1981,6 +1977,34 @@ void LLPanelLandOptions::refresh()
 			mMatureCtrl->setVisible(FALSE);
 			mMatureCtrl->setEnabled(FALSE);
 		}
+		else
+		{
+			// not teen so fill in the data for the maturity control
+			mMatureCtrl->setVisible(TRUE);
+			mMatureCtrl->setLabel(getString("mature_check_mature"));
+			// they can see the checkbox, but its disposition depends on the 
+			// state of the region
+			LLViewerRegion* regionp = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+			if (regionp)
+			{
+				if (regionp->getSimAccess() == SIM_ACCESS_PG)
+				{
+					mMatureCtrl->setEnabled(FALSE);
+					mMatureCtrl->set(FALSE);
+				}
+				else if (regionp->getSimAccess() == SIM_ACCESS_MATURE)
+				{
+					mMatureCtrl->setEnabled(can_change_identity);
+					mMatureCtrl->set(parcel->getMaturePublish());
+				}
+				else if (regionp->getSimAccess() == SIM_ACCESS_ADULT)
+				{
+					mMatureCtrl->setEnabled(FALSE);
+					mMatureCtrl->set(TRUE);
+					mMatureCtrl->setLabel(getString("mature_check_adult"));
+				}
+			}
+		}
 	}
 }
 
@@ -2749,6 +2773,18 @@ void LLPanelLandCovenant::refresh()
 		region_name->setText(region->getName());
 	}
 
+	LLTextBox* region_landtype = getChild<LLTextBox>("region_landtype_text");
+	if (region_landtype)
+	{
+		region_landtype->setText(region->getSimProductName());
+	}
+	
+	LLTextBox* region_maturity = getChild<LLTextBox>("region_maturity_text");
+	if (region_maturity)
+	{
+		region_maturity->setText(region->getSimAccessString());
+	}
+	
 	LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause");
 	if (resellable_clause)
 	{
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 520ed4147e..4c3de65d71 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -186,6 +186,9 @@ protected:
 	LLTextBox*		mTextOwnerLabel;
 	LLTextBox*		mTextOwner;
 	LLButton*		mBtnProfile;
+	
+	LLTextBox*		mContentRating;
+	LLTextBox*		mLandType;
 
 	LLTextBox*		mTextGroup;
 	LLTextBox*		mTextGroupLabel;
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 86bc8221d9..588df7b43b 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -295,6 +295,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
 
 	// extract message
 	std::string sim_name;
+	std::string sim_type = "(unknown)";
 	U32 region_flags;
 	U8 agent_limit;
 	F32 object_bonus_factor;
@@ -315,10 +316,18 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
 	msg->getBOOL("RegionInfo", "UseEstateSun", use_estate_sun);
 	// actually the "last set" sun hour, not the current sun hour. JC
 	msg->getF32("RegionInfo", "SunHour", sun_hour);
+	// the only reasonable way to decide if we actually have any data is to
+	// check to see if any of these fields have nonzero sizes
+	if (msg->getSize("RegionInfo2", "ProductSKU") ||
+		msg->getSize("RegionInfo2", "ProductName"))
+	{
+		msg->getString("RegionInfo2", "ProductName", sim_type);
+	}
 
 	// GENERAL PANEL
 	panel = tab->getChild<LLPanel>("General");
 	panel->childSetValue("region_text", LLSD(sim_name));
+	panel->childSetValue("region_type", LLSD(sim_type));
 	panel->childSetValue("version_channel_text", gLastVersionChannel);
 
 	panel->childSetValue("block_terraform_check", (region_flags & REGION_FLAGS_BLOCK_TERRAFORM) ? TRUE : FALSE );
@@ -330,7 +339,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
 	panel->childSetValue("block_parcel_search_check", (region_flags & REGION_FLAGS_BLOCK_PARCEL_SEARCH) ? TRUE : FALSE );
 	panel->childSetValue("agent_limit_spin", LLSD((F32)agent_limit) );
 	panel->childSetValue("object_bonus_spin", LLSD(object_bonus_factor) );
-	panel->childSetValue("access_combo", LLSD(LLViewerRegion::accessToString(sim_access)) );
+	panel->childSetValue("access_combo", LLSD(sim_access) );
 
 
  	// detect teen grid for maturity
@@ -718,7 +727,7 @@ void LLPanelRegionGeneralInfo::onClickManageTelehub(void* data)
 // strings[3] = 'Y' - allow land sale, 'N' - not
 // strings[4] = agent limit
 // strings[5] = object bonus
-// strings[6] = sim access (0 = unknown, 13 = PG, 21 = Mature)
+// strings[6] = sim access (0 = unknown, 13 = PG, 21 = Mature, 42 = Adult)
 // strings[7] = restrict pushobject
 // strings[8] = 'Y' - allow parcel subdivide, 'N' - not
 // strings[9] = 'Y' - block parcel search, 'N' - allow
@@ -739,7 +748,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
 		body["prim_bonus"] = childGetValue("object_bonus_spin");
 		// the combo box stores strings "Mature" and "PG", but we have to convert back to a number, 
 		// because the sim doesn't know from strings for this stuff
-		body["sim_access"] = LLViewerRegion::stringToAccess(childGetValue("access_combo").asString());
+		body["sim_access"] = childGetValue("access_combo");
 		body["restrict_pushobject"] = childGetValue("restrict_pushobject");
 		body["allow_parcel_changes"] = childGetValue("allow_parcel_changes_check");
 		body["block_parcel_search"] = childGetValue("block_parcel_search_check");
@@ -771,7 +780,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
 		buffer = llformat("%f", value);
 		strings.push_back(strings_t::value_type(buffer));
 
-		U8 access = LLViewerRegion::stringToAccess(childGetValue("access_combo").asString());
+		U8 access = childGetValue("access_combo").asInteger();
 		buffer = llformat("%d", (S32)access);
 		strings.push_back(strings_t::value_type(buffer));
 
diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp
index f6002653ab..2677467611 100644
--- a/indra/newview/llfloatersettingsdebug.cpp
+++ b/indra/newview/llfloatersettingsdebug.cpp
@@ -61,7 +61,10 @@ BOOL LLFloaterSettingsDebug::postBuild()
 		f(LLComboBox* c) : combo(c) {}
 		virtual void apply(const std::string& name, LLControlVariable* control)
 		{
-			combo->add(name, (void*)control);
+			if (!control->isHiddenFromSettingsEditor())
+			{
+				combo->add(name, (void*)control);
+			}
 		}
 	} func(settings_combo);
 
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index d59f513925..e2e71f51fa 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -429,9 +429,19 @@ void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent
 void LLFloaterWorldMap::draw()
 {
 	// Hide/Show Mature Events controls
-	childSetVisible("events_mature_icon", !gAgent.isTeen());
-	childSetVisible("events_mature_label", !gAgent.isTeen());
-	childSetVisible("event_mature_chk", !gAgent.isTeen());
+	childSetVisible("events_mature_icon", gAgent.canAccessMature());
+	childSetVisible("events_mature_label", gAgent.canAccessMature());
+	childSetVisible("event_mature_chk", gAgent.canAccessMature());
+
+	childSetVisible("events_adult_icon", gAgent.canAccessMature());
+	childSetVisible("events_adult_label", gAgent.canAccessMature());
+	childSetVisible("event_adult_chk", gAgent.canAccessMature());
+	bool adult_enabled = gAgent.canAccessAdult();
+	if (!adult_enabled)
+	{
+		childSetValue("event_adult_chk", FALSE);
+	}
+	childSetEnabled("event_adult_chk", adult_enabled);
 
 	// On orientation island, users don't have a home location yet, so don't
 	// let them teleport "home".  It dumps them in an often-crowed welcome
@@ -1315,6 +1325,7 @@ void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data)
 	LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
 	if(!self) return;
 	self->childSetEnabled("event_mature_chk", self->childGetValue("event_chk"));
+	self->childSetEnabled("event_adult_chk", self->childGetValue("event_chk"));
 }
 
 // protected
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 0c60357dfb..e6639a2da5 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -223,6 +223,7 @@ void LLPanelClassified::reset()
 	mPosGlobal.clearVec();
 
 	clearCtrls();
+	resetDirty();
 }
 
 
@@ -285,7 +286,7 @@ BOOL LLPanelClassified::postBuild()
 	mMatureCombo->setCurrentByIndex(0);
 	mMatureCombo->setCommitCallback(onCommitAny);
 	mMatureCombo->setCallbackUserData(this);
-	if (gAgent.isTeen())
+	if (gAgent.wantsPGOnly())
 	{
 		// Teens don't get to set mature flag. JC
 		mMatureCombo->setVisible(FALSE);
@@ -308,6 +309,7 @@ BOOL LLPanelClassified::postBuild()
 		mClickThroughText = getChild<LLTextBox>("click_through_text");
 	}
 	
+	resetDirty();
     return TRUE;
 }
 
@@ -540,7 +542,10 @@ void LLPanelClassified::sendClassifiedInfoUpdate()
 	{
 		auto_renew = mAutoRenewCheck->get();
 	}
-	U8 flags = pack_classified_flags(mature, auto_renew);
+    // These flags doesn't matter here.
+    const bool adult_enabled = false;
+	const bool is_pg = false;
+	U8 flags = pack_classified_flags_request(auto_renew, is_pg, mature, adult_enabled);
 	msg->addU8Fast(_PREHASH_ClassifiedFlags, flags);
 	msg->addS32("PriceForListing", mPriceForListing);
 	gAgent.sendReliableMessage();
@@ -678,6 +683,7 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void **
 
 		self->resetDirty();
 
+		// I don't know if a second call is deliberate or a bad merge, so I'm leaving it here. 
 		self->resetDirty();
     }
 }
diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp
index a4013f104c..47ed72aa77 100644
--- a/indra/newview/llpanelplace.cpp
+++ b/indra/newview/llpanelplace.cpp
@@ -294,9 +294,14 @@ void LLPanelPlace::processParcelInfoReply(LLMessageSystem *msg, void **)
 			self->mInfoEditor->setText(info_text);
 		}
 
-		// HACK: Flag 0x1 == mature region, otherwise assume PG
+		// HACK: Flag 0x2 == adult region,
+		// Flag 0x1 == mature region, otherwise assume PG
 		std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG);
-		if (flags & 0x1)
+		if (flags & 0x2)
+		{
+			rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT);
+		}
+		else if (flags & 0x1)
 		{
 			rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE);
 		}
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index cdcd68de38..86f590a0f0 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -89,8 +89,7 @@ BOOL LLProgressView::postBuild()
 
 	getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle()));
 
-	getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage);
-	getChild<LLTextBox>("message_text")->setCallbackUserData(this);
+	getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage, this);
 
 	sInstance = this;
 	return TRUE;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 5f96fc7da0..bd2e157779 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1361,14 +1361,32 @@ bool idle_startup()
 				LLStartUp::deletePasswordFromDisk();
 			}
 
-			text = LLUserAuth::getInstance()->getResponse("agent_access");
-			if(!text.empty() && (text[0] == 'M'))
+			// this is their actual ability to access content
+			text = LLUserAuth::getInstance()->getResponse("agent_access_max");
+			if (!text.empty())
 			{
-				gAgent.setTeen(false);
+				// agent_access can be 'A', 'M', and 'PG'.
+				gAgent.setMaturity(text[0]);
 			}
-			else
+			
+			// this is the value of their preference setting for that content
+			// which will always be <= agent_access_max
+			text = LLUserAuth::getInstance()->getResponse("agent_region_access");
+			if (!text.empty())
+			{
+				int preferredMaturity = LLAgent::convertTextToMaturity(text[0]);
+				gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
+			}
+			// During the AO transition, this flag will be true. Then the flag will
+			// go away. After the AO transition, this code and all the code that
+			// uses it can be deleted.
+			text = LLUserAuth::getInstance()->getResponse("ao_transition");
+			if (!text.empty())
 			{
-				gAgent.setTeen(true);
+				if (text == "1")
+				{
+					gAgent.setAOTransition();
+				}
 			}
 
 			text = LLUserAuth::getInstance()->getResponse("start_location");
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 50e5b4e90c..96a4f74927 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -470,7 +470,6 @@ BOOL enable_grab_texture(void*);
 void handle_dump_region_object_cache(void*);
 
 BOOL menu_ui_enabled(void *user_data);
-void check_toggle_control( LLUICtrl *, void* user_data );
 BOOL menu_check_control( void* user_data);
 void menu_toggle_variable( void* user_data );
 BOOL menu_check_variable( void* user_data);
@@ -1025,6 +1024,11 @@ extern BOOL gDebugSelectMgr;
 
 void init_debug_ui_menu(LLMenuGL* menu)
 {
+	menu->append(new LLMenuItemCheckGL("Rotate Mini-Map", menu_toggle_control, NULL, menu_check_control, (void*)"MiniMapRotate"));
+	menu->append(new LLMenuItemCheckGL("Use default system color picker", menu_toggle_control, NULL, menu_check_control, (void*)"UseDefaultColorPicker"));
+	menu->append(new LLMenuItemCheckGL("Show search panel in overlay bar", menu_toggle_control, NULL, menu_check_control, (void*)"ShowSearchBar"));
+	menu->appendSeparator();
+
 	menu->append(new LLMenuItemCallGL("Web Browser Test", &handle_web_browser_test));
 	menu->append(new LLMenuItemCallGL("Buy Currency Test", &handle_buy_currency_test));
 	menu->append(new LLMenuItemCallGL("Editable UI", &edit_ui));
@@ -6182,13 +6186,6 @@ class LLToggleControl : public view_listener_t
 	}
 };
 
-// As above, but can be a callback from a LLCheckboxCtrl
-void check_toggle_control( LLUICtrl *, void* user_data )
-{
-	BOOL checked = gSavedSettings.getBOOL( static_cast<char*>(user_data) );
-	gSavedSettings.setBOOL( static_cast<char*>(user_data), !checked );
-}
-
 BOOL menu_check_control( void* user_data)
 {
 	return gSavedSettings.getBOOL((char*)user_data);
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index a82e4a9a4d..e9fedf37d8 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -80,7 +80,6 @@ BOOL is_agent_friend(const LLUUID& agent_id);
 BOOL is_agent_mappable(const LLUUID& agent_id);
 
 void menu_toggle_control( void* user_data );
-void check_toggle_control( LLUICtrl *, void* user_data );
 void confirm_replace_attachment(S32 option, void* user_data);
 void handle_detach_from_avatar(void* user_data);
 void attach_label(std::string& label, void* user_data);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index dae3529319..6ffb19bcdf 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4118,29 +4118,158 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )
 	}
 }
 
-void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data)
+bool handle_special_notification_callback(const LLSD& notification, const LLSD& response)
 {
-	std::string buffer;
-	msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer);
-	BOOL modal = FALSE;
-	msgsystem->getBOOL("AlertData", "Modal", modal);
-	process_alert_core(buffer, modal);
+	S32 option = LLNotification::getSelectedOption(notification, response);
+	
+	if (0 == option)
+	{
+		// set the preference to the maturity of the region we're calling
+		int preferredMaturity = notification["payload"]["_region_access"].asInteger();
+		gSavedSettings.setU32("PreferredMaturity", preferredMaturity);
+		gAgent.sendMaturityPreferenceToServer(preferredMaturity);
+
+	}
+	
+	return false;
 }
 
-void process_alert_message(LLMessageSystem *msgsystem, void **user_data)
+// some of the server notifications need special handling. This is where we do that.
+bool handle_special_notification(std::string notificationID, LLSD& llsdBlock)
 {
-	std::string buffer;
-	msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer);
-	BOOL modal = FALSE;
-	process_alert_core(buffer, modal);
+	int regionAccess = llsdBlock["_region_access"].asInteger();
+	llsdBlock["REGIONMATURITY"] = LLViewerRegion::accessToString(regionAccess);
+	
+	// we're going to throw the LLSD in there in case anyone ever wants to use it
+	LLNotifications::instance().add(notificationID+"_Notify", llsdBlock);
+	
+	if (regionAccess == SIM_ACCESS_MATURE)
+	{
+		if (gAgent.isTeen())
+		{
+			LLNotifications::instance().add(notificationID+"_KB", llsdBlock);
+			return true;
+		}
+		else if (gAgent.prefersPG())
+		{
+			LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
+			return true;
+		}
+	}
+	else if (regionAccess == SIM_ACCESS_ADULT)
+	{
+		if (!gAgent.isAdult())
+		{
+			LLNotifications::instance().add(notificationID+"_KB", llsdBlock);
+			return true;
+		}
+		else if (gAgent.prefersPG() || gAgent.prefersMature())
+		{
+			LLNotifications::instance().add(notificationID+"_Change", llsdBlock, llsdBlock, handle_special_notification_callback);
+			return true;
+		}
+	}
+	return false;
 }
 
-void process_alert_core(const std::string& message, BOOL modal)
+bool attempt_standard_notification(LLMessageSystem* msgsystem)
+{
+	// if we have additional alert data
+	if (msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0)
+	{
+		// notification was specified using the new mechanism, so we can just handle it here
+		std::string notificationID;
+		std::string llsdRaw;
+		LLSD llsdBlock;
+		msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID);
+		msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsdRaw);
+		if (llsdRaw.length())
+		{
+			std::istringstream llsdData(llsdRaw);
+			if (!LLSDSerialize::deserialize(llsdBlock, llsdData, llsdRaw.length()))
+			{
+				llwarns << "attempt_standard_notification: Attempted to read notification parameter data into LLSD but failed:" << llsdRaw << llendl;
+			}
+		}
+		
+		if (
+			(notificationID == "RegionEntryAccessBlocked") ||
+			(notificationID == "LandClaimAccessBlocked") ||
+			(notificationID == "LandBuyAccessBlocked")
+		   )
+		{
+			/*---------------------------------------------------------------------
+			 (Commented so a grep will find the notification strings, since
+			 we construct them on the fly; if you add additional notifications,
+			 please update the comment.)
+			 
+			 Could throw any of the following notifications:
+			 
+				RegionEntryAccessBlocked
+				RegionEntryAccessBlocked_Notify
+				RegionEntryAccessBlocked_Change
+				RegionEntryAccessBlocked_KB
+				LandClaimAccessBlocked 
+				LandClaimAccessBlocked_Notify 
+				LandClaimAccessBlocked_Change 
+				LandClaimAccessBlocked_KB 
+				LandBuyAccessBlocked
+				LandBuyAccessBlocked_Notify
+				LandBuyAccessBlocked_Change
+				LandBuyAccessBlocked_KB
+			 
+			-----------------------------------------------------------------------*/ 
+			if (handle_special_notification(notificationID, llsdBlock))
+			{
+				return true;
+			}
+		}
+		
+		LLNotifications::instance().add(notificationID, llsdBlock);
+		return true;
+	}	
+	return false;
+}
+
+
+void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data)
+{
+	// make sure the cursor is back to the usual default since the
+	// alert is probably due to some kind of error.
+	gViewerWindow->getWindow()->resetBusyCount();
+	
+	if (!attempt_standard_notification(msgsystem))
+	{
+		BOOL modal = FALSE;
+		msgsystem->getBOOL("AlertData", "Modal", modal);
+		std::string buffer;
+		msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer);
+		process_alert_core(buffer, modal);
+	}
+}
+
+// The only difference between this routine and the previous is the fact that
+// for this routine, the modal parameter is always false. Sadly, for the message
+// handled by this routine, there is no "Modal" parameter on the message, and
+// there's no API to tell if a message has the given parameter or not.
+// So we can't handle the messages with the same handler.
+void process_alert_message(LLMessageSystem *msgsystem, void **user_data)
 {
 	// make sure the cursor is back to the usual default since the
 	// alert is probably due to some kind of error.
 	gViewerWindow->getWindow()->resetBusyCount();
+		
+	if (!attempt_standard_notification(msgsystem))
+	{
+		BOOL modal = FALSE;
+		std::string buffer;
+		msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, buffer);
+		process_alert_core(buffer, modal);
+	}
+}
 
+void process_alert_core(const std::string& message, BOOL modal)
+{
 	// HACK -- handle callbacks for specific alerts
 	if ( message == "You died and have been teleported to your home location")
 	{
@@ -4732,17 +4861,63 @@ std::string formatted_time(const time_t& the_time)
 void process_teleport_failed(LLMessageSystem *msg, void**)
 {
 	std::string reason;
-	msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason);
-
+	std::string big_reason;
 	LLSD args;
-	std::string big_reason = LLAgent::sTeleportErrorMessages[reason];
-	if ( big_reason.size() > 0 )
-	{	// Substitute verbose reason from the local map
-		args["REASON"] = big_reason;
+
+	// if we have additional alert data
+	if (msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0)
+	{
+		// Get the message ID
+		msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, reason);
+		big_reason = LLAgent::sTeleportErrorMessages[reason];
+		if ( big_reason.size() > 0 )
+		{	// Substitute verbose reason from the local map
+			args["REASON"] = big_reason;
+		}
+		else
+		{	// Nothing found in the map - use what the server returned in the original message block
+			msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason);
+			args["REASON"] = reason;
+		}
+
+		LLSD llsd_block;
+		std::string llsd_raw;
+		msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_ExtraParams, llsd_raw);
+		if (llsd_raw.length())
+		{
+			std::istringstream llsd_data(llsd_raw);
+			if (!LLSDSerialize::deserialize(llsd_block, llsd_data, llsd_raw.length()))
+			{
+				llwarns << "process_teleport_failed: Attempted to read alert parameter data into LLSD but failed:" << llsd_raw << llendl;
+			}
+			else
+			{
+				// change notification name in this special case
+				if (handle_special_notification("RegionEntryAccessBlocked", llsd_block))
+				{
+					if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
+					{
+						gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+					}
+					return;
+				}
+			}
+		}
+
 	}
 	else
-	{	// Nothing found in the map - use what the server returned
-		args["REASON"] = reason;
+	{
+		msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason);
+
+		big_reason = LLAgent::sTeleportErrorMessages[reason];
+		if ( big_reason.size() > 0 )
+		{	// Substitute verbose reason from the local map
+			args["REASON"] = big_reason;
+		}
+		else
+		{	// Nothing found in the map - use what the server returned
+			args["REASON"] = reason;
+		}
 	}
 
 	LLNotifications::instance().add("CouldNotTeleportReason", args);
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index bf40ccce49..e7a4303a8e 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -107,6 +107,7 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/);
 void process_money_balance_reply(LLMessageSystem* msg_system, void**);
 void process_adjust_balance(LLMessageSystem* msg_system, void**);
 
+bool attempt_standard_notification(LLMessageSystem* msg);
 void process_alert_message(LLMessageSystem* msg, void**);
 void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data);
 void process_alert_core(const std::string& message, BOOL modal);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 87b6652056..750151ea2d 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -56,6 +56,7 @@
 #include "llhttpnode.h"
 #include "llsdutil.h"
 #include "llstartup.h"
+#include "lltrans.h"
 #include "llviewerobjectlist.h"
 #include "llviewerparceloverlay.h"
 #include "llvlmanager.h"
@@ -162,6 +163,11 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 	mSimAccess( SIM_ACCESS_MIN ),
 	mBillableFactor(1.0),
 	mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT),
+	mClassID(0),
+	mCPURatio(0),
+	mColoName("unknown"),
+	mProductSKU("unknown"),
+	mProductName("unknown"),
 	mCacheLoaded(FALSE),
 	mCacheEntriesCount(0),
 	mCacheID(),
@@ -539,55 +545,29 @@ std::string LLViewerRegion::regionFlagsToString(U32 flags)
 	return result;
 }
 
-// *TODO:Translate
-const char* SIM_ACCESS_STR[] = { "Free Trial",
-						   "PG",
-						   "Mature",
-						   "Offline",
-						   "Unknown" };
-							
 // static
 std::string LLViewerRegion::accessToString(U8 sim_access)
 {
 	switch(sim_access)
 	{
-	case SIM_ACCESS_TRIAL:
-		return SIM_ACCESS_STR[0];
-
 	case SIM_ACCESS_PG:
-		return SIM_ACCESS_STR[1];
+		return LLTrans::getString("SIM_ACCESS_PG");
 
 	case SIM_ACCESS_MATURE:
-		return SIM_ACCESS_STR[2];
+		return LLTrans::getString("SIM_ACCESS_MATURE");
+
+	case SIM_ACCESS_ADULT:
+		return LLTrans::getString("SIM_ACCESS_ADULT");
 
 	case SIM_ACCESS_DOWN:
-		return SIM_ACCESS_STR[3];
+		return LLTrans::getString("SIM_ACCESS_DOWN");
 
 	case SIM_ACCESS_MIN:
 	default:
-		return SIM_ACCESS_STR[4];
+		return LLTrans::getString("SIM_ACCESS_MIN");
 	}
 }
 
-// static
-U8 LLViewerRegion::stringToAccess(const std::string& access_str)
-{
-	U8 sim_access = SIM_ACCESS_MIN;
-	if (access_str == SIM_ACCESS_STR[0])
-	{
-		sim_access = SIM_ACCESS_TRIAL;
-	}
-	else if (access_str == SIM_ACCESS_STR[1])
-	{
-		sim_access = SIM_ACCESS_PG;
-	}
-	else if (access_str == SIM_ACCESS_STR[2])
-	{
-		sim_access = SIM_ACCESS_MATURE;
-	}
-	return sim_access;
-}
-
 // static
 std::string LLViewerRegion::accessToShortString(U8 sim_access)
 {
@@ -596,12 +576,12 @@ std::string LLViewerRegion::accessToShortString(U8 sim_access)
 	case SIM_ACCESS_PG:
 		return "PG";
 
-	case SIM_ACCESS_TRIAL:
-		return "TR";
-
 	case SIM_ACCESS_MATURE:
 		return "M";
 
+	case SIM_ACCESS_ADULT:
+		return "A";
+
 	case SIM_ACCESS_MIN:
 	default:
 		return "U";
@@ -1315,6 +1295,32 @@ void LLViewerRegion::unpackRegionHandshake()
 	LLUUID region_id;
 	msg->getUUID("RegionInfo2", "RegionID", region_id);
 	setRegionID(region_id);
+	
+	// Retrieve the CR-53 (Homestead/Land SKU) information
+	S32 classID = 0;
+	S32 cpuRatio = 0;
+	std::string coloName;
+	std::string productSKU;
+	std::string productName;
+
+	// the only reasonable way to decide if we actually have any data is to
+	// check to see if any of these fields have nonzero sizes
+	if (msg->getSize("RegionInfo3", "ColoName") ||
+	    msg->getSize("RegionInfo3", "ProductSKU") ||
+	    msg->getSize("RegionInfo3", "ProductName"))
+	{
+		msg->getS32     ("RegionInfo3", "CPUClassID",  classID);
+		msg->getS32     ("RegionInfo3", "CPURatio",    cpuRatio);
+		msg->getString  ("RegionInfo3", "ColoName",    coloName);
+		msg->getString  ("RegionInfo3", "ProductSKU",  productSKU);
+		msg->getString  ("RegionInfo3", "ProductName", productName);
+		
+		mClassID = classID;
+		mCPURatio = cpuRatio;
+		mColoName = coloName;
+		mProductSKU = productSKU;
+		mProductName = productName;
+	}
 
 	LLVLComposition *compp = getComposition();
 	if (compp)
@@ -1420,6 +1426,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
 	capabilityNames.append("ServerReleaseNotes");
 	capabilityNames.append("StartGroupProposal");
 	capabilityNames.append("UntrustedSimulatorMessage");
+	capabilityNames.append("UpdateAgentInformation");
 	capabilityNames.append("UpdateAgentLanguage");
 	capabilityNames.append("UpdateGestureAgentInventory");
 	capabilityNames.append("UpdateNotecardAgentInventory");
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 6b71ea07bb..b0a98a99b8 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -182,18 +182,24 @@ public:
 	void setSimAccess(U8 sim_access)			{ mSimAccess = sim_access; }
 	U8 getSimAccess() const						{ return mSimAccess; }
 	const std::string getSimAccessString() const;
+	
+	// Homestead-related getters; there are no setters as nobody should be
+	// setting them other than the individual message handler which is a member
+	S32 getSimClassID()                    const { return mClassID; }
+	S32 getSimCPURatio()                   const { return mCPURatio; }
+	const std::string& getSimColoName()    const { return mColoName; }
+	const std::string& getSimProductSKU()  const { return mProductSKU; }
+	const std::string& getSimProductName() const { return mProductName; }
 
 	// Returns "Sandbox", "Expensive", etc.
 	static std::string regionFlagsToString(U32 flags);
 
-	// Returns "Mature", "PG", etc.
+	// Returns translated version of "Mature", "PG", "Adult", etc.
 	static std::string accessToString(U8 sim_access);
 
-	static U8 stringToAccess(const std::string& access_str);
-
-	// Returns "M", "PG", etc.
+	// Returns "M", "PG", "A" etc.
 	static std::string accessToShortString(U8 sim_access);
-
+	
 	// helper function which just makes sure all interested parties
 	// can process the message.
 	static void processRegionInfo(LLMessageSystem* msg, void**);
@@ -357,6 +363,14 @@ private:
 	U32		mMaxTasks;				// max prim count
 	F32		mCameraDistanceSquared;	// updated once per frame
 	
+	// Information for Homestead / CR-53
+	S32 mClassID;
+	S32 mCPURatio;
+	std::string mColoName;
+	std::string mProductSKU;
+	std::string mProductName;
+	
+	
 	// Maps local ids to cache entries.
 	// Regions can have order 10,000 objects, so assume
 	// a structure of size 2^14 = 16,000
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 44d9a72868..71406d268d 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2450,9 +2450,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
 		}
 	}
 
-	// Debugging view for unified notifications
+	// Debugging view for unified notifications -- we need Ctrl+Shift+Alt to get it 
+	// since Ctrl+Shift maps to Nighttime under windlight.
 	if ((MASK_SHIFT & mask) 
 		&& (MASK_CONTROL & mask)
+		&& (MASK_ALT & mask)
 		&& ('N' == key || 'n' == key))
 	{
 		LLFloaterNotificationConsole::showInstance();
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index c9a3bd2112..572f31f566 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -186,6 +186,7 @@ void LLWorldMap::eraseItems()
 		mInfohubs.clear();
 		mPGEvents.clear();
 		mMatureEvents.clear();
+		mAdultEvents.clear();
 		mLandForSale.clear();
 	}
 // 	mAgentLocationsMap.clear(); // persists
@@ -311,11 +312,23 @@ void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer)
 		sendItemRequest(MAP_ITEM_MATURE_EVENT);
 	}
 
+	if (mAdultEvents.size() == 0)
+	{
+		// Request for events (adult)
+		sendItemRequest(MAP_ITEM_ADULT_EVENT);
+	}
+
 	if (mLandForSale.size() == 0)
 	{
 		// Request for Land For Sale
 		sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
 	}
+	
+	if (mLandForSaleAdult.size() == 0)
+	{
+		// Request for Land For Sale
+		sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT);
+	}
 
 	clearImageRefs();
 	clearSimFlags();
@@ -742,6 +755,7 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**)
 			}
 			case MAP_ITEM_PG_EVENT: // events
 			case MAP_ITEM_MATURE_EVENT:
+			case MAP_ITEM_ADULT_EVENT:
 			{
 				struct tm* timep;
 				// Convert to Pacific, based on server's opinion of whether
@@ -762,16 +776,29 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**)
 				{
 					LLWorldMap::getInstance()->mPGEvents.push_back(new_item);
 				}
-				else
+				else if (type == MAP_ITEM_MATURE_EVENT)
 				{
 					LLWorldMap::getInstance()->mMatureEvents.push_back(new_item);
 				}
+				else if (type == MAP_ITEM_ADULT_EVENT)
+				{
+					LLWorldMap::getInstance()->mAdultEvents.push_back(new_item);
+				}
+
 				break;
 			}
 			case MAP_ITEM_LAND_FOR_SALE: // land for sale
+			case MAP_ITEM_LAND_FOR_SALE_ADULT: // adult land for sale 
 			{
 				new_item.mToolTip = llformat("%d sq. m. L$%d", new_item.mExtra, new_item.mExtra2);
-				LLWorldMap::getInstance()->mLandForSale.push_back(new_item);
+				if (type == MAP_ITEM_LAND_FOR_SALE)
+				{
+					LLWorldMap::getInstance()->mLandForSale.push_back(new_item);
+				}
+				else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT)
+				{
+					LLWorldMap::getInstance()->mLandForSaleAdult.push_back(new_item);
+				}
 				break;
 			}
 			case MAP_ITEM_CLASSIFIED: // classifieds
diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h
index 423af6a289..6ce66ffab0 100644
--- a/indra/newview/llworldmap.h
+++ b/indra/newview/llworldmap.h
@@ -192,7 +192,9 @@ public:
 	item_info_list_t mInfohubs;
 	item_info_list_t mPGEvents;
 	item_info_list_t mMatureEvents;
+	item_info_list_t mAdultEvents;
 	item_info_list_t mLandForSale;
+	item_info_list_t mLandForSaleAdult;
 
 	std::map<U64,S32> mNumAgents;
 
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 9ff94751d0..7f8f4cc026 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -83,12 +83,14 @@ LLUIImagePtr LLWorldMapView::sInfohubImage = NULL;
 LLUIImagePtr LLWorldMapView::sHomeImage = NULL;
 LLUIImagePtr LLWorldMapView::sEventImage = NULL;
 LLUIImagePtr LLWorldMapView::sEventMatureImage = NULL;
+LLUIImagePtr LLWorldMapView::sEventAdultImage = NULL;
 
 LLUIImagePtr LLWorldMapView::sTrackCircleImage = NULL;
 LLUIImagePtr LLWorldMapView::sTrackArrowImage = NULL;
 
 LLUIImagePtr LLWorldMapView::sClassifiedsImage = NULL;
 LLUIImagePtr LLWorldMapView::sForSaleImage = NULL;
+LLUIImagePtr LLWorldMapView::sForSaleAdultImage = NULL;
 
 F32 LLWorldMapView::sThresholdA = 48.f;
 F32 LLWorldMapView::sThresholdB = 96.f;
@@ -125,11 +127,15 @@ void LLWorldMapView::initClass()
 	sInfohubImage = 		LLUI::getUIImage("map_infohub.tga");
 	sEventImage =			LLUI::getUIImage("map_event.tga");
 	sEventMatureImage =		LLUI::getUIImage("map_event_mature.tga");
+	// To Do: update the image resource for adult events.
+	sEventAdultImage =		LLUI::getUIImage("map_event_adult.tga");
 
 	sTrackCircleImage =		LLUI::getUIImage("map_track_16.tga");
 	sTrackArrowImage =		LLUI::getUIImage("direction_arrow.tga");
 	sClassifiedsImage =		LLUI::getUIImage("icon_top_pick.tga");
 	sForSaleImage =			LLUI::getUIImage("icon_for_sale.tga");
+	// To Do: update the image resource for adult lands on sale.
+	sForSaleAdultImage =    LLUI::getUIImage("icon_for_sale_adult.tga");
 	
 	sStringsMap["loading"] = LLTrans::getString("texture_loading");
 	sStringsMap["offline"] = LLTrans::getString("worldmap_offline");
@@ -149,11 +155,13 @@ void LLWorldMapView::cleanupClass()
 	sHomeImage = NULL;
 	sEventImage = NULL;
 	sEventMatureImage = NULL;
+	sEventAdultImage = NULL;
 
 	sTrackCircleImage = NULL;
 	sTrackArrowImage = NULL;
 	sClassifiedsImage = NULL;
 	sForSaleImage = NULL;
+	sForSaleAdultImage = NULL;
 }
 
 LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect )
@@ -332,12 +340,11 @@ void LLWorldMapView::draw()
 		}
 		LLWorldMapLayer *layer = &LLWorldMap::getInstance()->mMapLayers[LLWorldMap::getInstance()->mCurrentMap][layer_idx];
 		LLViewerImage *current_image = layer->LayerImage;
-#if 1 || LL_RELEASE_FOR_DOWNLOAD
+
 		if (current_image->isMissingAsset())
 		{
 			continue; // better to draw nothing than the missing asset image
 		}
-#endif
 		
 		LLVector3d origin_global((F64)layer->LayerExtents.mLeft * REGION_WIDTH_METERS, (F64)layer->LayerExtents.mBottom * REGION_WIDTH_METERS, 0.f);
 
@@ -419,7 +426,7 @@ void LLWorldMapView::draw()
 	gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 	gGL.setColorMask(true, true);
 
-#if 1
+	// there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code?
 	F32 sim_alpha = 1.f;
 
 	// Draw one image per region, centered on the camera position.
@@ -633,7 +640,11 @@ void LLWorldMapView::draw()
 			gGL.end();
 		}
 
-		// If this is mature, and you are not, draw a line across it
+		// As part of the AO project, we no longer want to draw access indicators;
+		// it's too complicated to get all the rules straight and will only 
+		// cause confusion.
+		/**********************
+		 // If this is mature, and you are not, draw a line across it
 		if (info->mAccess != SIM_ACCESS_DOWN
 			&& info->mAccess > SIM_ACCESS_PG
 			&& gAgent.isTeen())
@@ -649,6 +660,7 @@ void LLWorldMapView::draw()
 				gGL.vertex2f(right, top);
 			gGL.end();
 		}
+		 **********************/
 
 		// Draw the region name in the lower left corner
 		LLFontGL* font = LLFontGL::getFontSansSerifSmall();
@@ -705,10 +717,10 @@ void LLWorldMapView::draw()
 			}
 		}
 	}
-#endif
+	// #endif used to be here
 
 
-#if 1
+	// there used to be an #if 1 here, but it was uncommented; perhaps marking a block of code?
 	// Draw background rectangle
 	LLGLSUIDefault gls_ui;
 	{
@@ -744,8 +756,15 @@ void LLWorldMapView::draw()
 	if (gSavedSettings.getBOOL("MapShowLandForSale"))
 	{
 		drawGenericItems(LLWorldMap::getInstance()->mLandForSale, sForSaleImage);
+		// for 1.23, we're showing normal land and adult land in the same UI; you don't
+		// get a choice about which ones you want. If you're currently asking for adult
+		// content and land you'll get the adult land.
+		if (gAgent.canAccessAdult())
+		{
+			drawGenericItems(LLWorldMap::getInstance()->mLandForSaleAdult, sForSaleAdultImage);
+		}
 	}
-
+	
 	if (gSavedSettings.getBOOL("MapShowEvents"))
 	{
 		drawEvents();
@@ -809,7 +828,7 @@ void LLWorldMapView::draw()
 			drawTracking( LLWorldMap::getInstance()->mUnknownLocation, loading_color, TRUE, "Loading...", "");
 		}
 	}
-#endif
+	// #endif used to be here
 	
 	// turn off the scissor
 	LLGLDisable no_scissor(GL_SCISSOR_TEST);
@@ -943,7 +962,11 @@ void LLWorldMapView::drawAgents()
 
 void LLWorldMapView::drawEvents()
 {
-    BOOL show_mature = gSavedSettings.getBOOL("ShowMatureEvents");
+	bool mature_enabled = gAgent.canAccessMature();
+	bool adult_enabled = gAgent.canAccessAdult();
+
+    BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("ShowMatureEvents");
+	BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("ShowAdultEvents");
 
     // First the non-selected events
     LLWorldMap::item_info_list_t::const_iterator e;
@@ -964,7 +987,16 @@ void LLWorldMapView::drawEvents()
             }
         }
     }
-
+	if (show_adult)
+    {
+        for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e)
+        {
+            if (!e->mSelected)
+            {
+                drawGenericItem(*e, sEventAdultImage);       
+            }
+        }
+    }
     // Then the selected events
     for (e = LLWorldMap::getInstance()->mPGEvents.begin(); e != LLWorldMap::getInstance()->mPGEvents.end(); ++e)
     {
@@ -983,6 +1015,16 @@ void LLWorldMapView::drawEvents()
             }
         }
     }
+	if (show_adult)
+    {
+        for (e = LLWorldMap::getInstance()->mAdultEvents.begin(); e != LLWorldMap::getInstance()->mAdultEvents.end(); ++e)
+        {
+            if (e->mSelected)
+            {
+                drawGenericItem(*e, sEventAdultImage);       
+            }
+        }
+    }
 }
 
 
@@ -1572,6 +1614,10 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask,
 	{
 		(*it).mSelected = FALSE;
 	}
+	for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it)
+	{
+		(*it).mSelected = FALSE;
+	}
 	for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it)
 	{
 		(*it).mSelected = FALSE;
@@ -1607,6 +1653,21 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask,
 				}
 			}
 		}
+		if (gSavedSettings.getBOOL("ShowAdultEvents"))
+		{
+			for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it)
+			{
+				LLItemInfo& event = *it;
+
+				if (checkItemHit(x, y, event, id, false))
+				{
+					*hit_type = MAP_ITEM_ADULT_EVENT;
+					mItemPicked = TRUE;
+					gFloaterWorldMap->trackEvent(event);
+					return;
+				}
+			}
+		}
 	}
 
 	if (gSavedSettings.getBOOL("MapShowLandForSale"))
@@ -1622,8 +1683,19 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask,
 				return;
 			}
 		}
-	}
+		
+		for (it = LLWorldMap::getInstance()->mLandForSaleAdult.begin(); it != LLWorldMap::getInstance()->mLandForSaleAdult.end(); ++it)
+		{
+			LLItemInfo& land = *it;
 
+			if (checkItemHit(x, y, land, id, true))
+			{
+				*hit_type = MAP_ITEM_LAND_FOR_SALE_ADULT;
+				mItemPicked = TRUE;
+				return;
+			}
+		}
+	}
 	// If we get here, we haven't clicked on an icon
 
 	gFloaterWorldMap->trackLocation(pos_global);
@@ -1803,6 +1875,7 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )
 		{
 		case MAP_ITEM_PG_EVENT:
 		case MAP_ITEM_MATURE_EVENT:
+		case MAP_ITEM_ADULT_EVENT:
 			{
 				gFloaterWorldMap->close();
 				// This is an ungainly hack
@@ -1815,6 +1888,7 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )
 				break;
 			}
 		case MAP_ITEM_LAND_FOR_SALE:
+		case MAP_ITEM_LAND_FOR_SALE_ADULT:
 			{
 				gFloaterWorldMap->close();
 				LLFloaterDirectory::showLandForSale(id);
diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h
index 980ddf9c73..1717b76beb 100644
--- a/indra/newview/llworldmapview.h
+++ b/indra/newview/llworldmapview.h
@@ -148,10 +148,12 @@ public:
 	static LLUIImagePtr	sHomeImage;
 	static LLUIImagePtr	sEventImage;
 	static LLUIImagePtr	sEventMatureImage;
+	static LLUIImagePtr	sEventAdultImage;
 	static LLUIImagePtr	sTrackCircleImage;
 	static LLUIImagePtr	sTrackArrowImage;
 	static LLUIImagePtr	sClassifiedsImage;
 	static LLUIImagePtr	sForSaleImage;
+	static LLUIImagePtr	sForSaleAdultImage;
 
 	static F32		sThresholdA;
 	static F32		sThresholdB;
diff --git a/indra/newview/skins/default/textures/icon_event_adult.tga b/indra/newview/skins/default/textures/icon_event_adult.tga
new file mode 100644
index 0000000000000000000000000000000000000000..c344fb1e78887afe2b20ac4830ffb057772416cd
GIT binary patch
literal 648
zcmZ9JOG*Pl5Qb|e2E<j4;01K&N*6(hFc=hkA(BOKB_duRWYO)Iv&36@ld`_QXOfs+
z%vAl4s_JU9BkRw|Ms|Fd#+MgDJXL1?O{xgc#qLP_{jKN<fg^$Ki32zHpS9;@9g0C@
z_B(qi=~kO*7Nj{c4*%@Sh1Weo3+eQ!cf~E53fq5?y2GvDY(r}1id5G?p{^QIQ4)qi
z+F`dF>HT#c^DQ)DQeni34v65mBNO7&s5J7=kB|kc>NQsB<1b{;JG(`eWoFh_wh%Qi
zWSm1;soJ&cO)Y)5H&OHj)-sG%vU!kzJ6zAL7l5QDl+Zn@JaVB{luRfU+1dHENiIy0
YF#2#F?j9#k&3$uwbMk!EOed%I2Uv>&3jhEB

literal 0
HcmV?d00001

diff --git a/indra/newview/skins/default/textures/icon_for_sale_adult.tga b/indra/newview/skins/default/textures/icon_for_sale_adult.tga
new file mode 100644
index 0000000000000000000000000000000000000000..6a99188f87f550eaeccdf787a99cdad01740d817
GIT binary patch
literal 743
zcmZQz;9`IQ0R{mE1&+qHwl=UxRVR@84`Nn<#o!YEI~gQ?gC+i>Ni>5b8W~Du{)1T{
zz356BK}uL{{qFwPp6LG{q?ET-`+v~ty8j?Cuq>K3CXgv0U8;Q^5W^XDCI$W%XwZl7
zn8H%-g5^<dV?)-)Qla>tw@wFcOcTgrMyNNCoX7~%)Ch77qr-xX|I+O?|G~<c6uO<U
z*uw(T0&<2>qv3z%as{X}K|TbD66Y&6-N`}!O=m>^_gzu`KW*nUuvSbbVhIkAB9Jq|
zA<q=Cp%sfWIbhBNdCY5B$$#Y@S8(t%mdb+Z#BCF>Iuxjn0T=*4D;OX#1PnO_kYb1!
zNEVR_K;c&fQU;c61UU+x5+JFl36#9R!3<K?2K67%29S6&hyZ&KBngrO#{(k#zzSO6
iDYO}6I}kHe!Nowlkf2c4FwbC5e?Q#_H%}i|Jq7>*FCeJ^

literal 0
HcmV?d00001

diff --git a/indra/newview/skins/default/textures/map_event_adult.tga b/indra/newview/skins/default/textures/map_event_adult.tga
new file mode 100644
index 0000000000000000000000000000000000000000..c344fb1e78887afe2b20ac4830ffb057772416cd
GIT binary patch
literal 648
zcmZ9JOG*Pl5Qb|e2E<j4;01K&N*6(hFc=hkA(BOKB_duRWYO)Iv&36@ld`_QXOfs+
z%vAl4s_JU9BkRw|Ms|Fd#+MgDJXL1?O{xgc#qLP_{jKN<fg^$Ki32zHpS9;@9g0C@
z_B(qi=~kO*7Nj{c4*%@Sh1Weo3+eQ!cf~E53fq5?y2GvDY(r}1id5G?p{^QIQ4)qi
z+F`dF>HT#c^DQ)DQeni34v65mBNO7&s5J7=kB|kc>NQsB<1b{;JG(`eWoFh_wh%Qi
zWSm1;soJ&cO)Y)5H&OHj)-sG%vU!kzJ6zAL7l5QDl+Zn@JaVB{luRfU+1dHENiIy0
YF#2#F?j9#k&3$uwbMk!EOed%I2Uv>&3jhEB

literal 0
HcmV?d00001

diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp
new file mode 100644
index 0000000000..fc18f10e7d
--- /dev/null
+++ b/indra/newview/tests/llagentaccess_test.cpp
@@ -0,0 +1,234 @@
+/** 
+ * @file llagentaccess_test.cpp
+ * @brief LLAgentAccess tests
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+#include "../test/lltut.h"
+
+#include "../llagentaccess.h"
+
+#include "llcontrolgroupreader.h"
+#include "indra_constants.h"
+
+#include <iostream>
+
+class LLControlGroupReader_Test : public LLControlGroupReader
+{
+public:
+	LLControlGroupReader_Test() : test_preferred_maturity(SIM_ACCESS_PG) {}
+	
+	virtual std::string getString(const std::string& name)
+	{
+		return "";
+	}
+	virtual std::string	getText(const std::string& name)
+	{
+		return "";
+	}
+	virtual BOOL getBOOL(const std::string& name)
+	{
+		return false;
+	}
+	virtual S32	getS32(const std::string& name)
+	{
+		return 0;
+	}
+	virtual F32 getF32(const std::string& name)
+	{
+		return 0;
+	}
+	virtual U32	getU32(const std::string& name)
+	{
+		return test_preferred_maturity;
+	}
+	
+	//--------------------------------------
+	// Everything from here down is test code and not part of the interface
+	void setPreferredMaturity(U32 m)
+	{
+		test_preferred_maturity = m;
+	}
+private:
+	U32 test_preferred_maturity;
+	
+};
+
+namespace tut
+{
+    struct agentaccess
+    {
+    };
+    
+	typedef test_group<agentaccess> agentaccess_t;
+	typedef agentaccess_t::object agentaccess_object_t;
+	tut::agentaccess_t tut_agentaccess("agentaccess");
+
+	template<> template<>
+	void agentaccess_object_t::test<1>()
+	{
+		LLControlGroupReader_Test cgr;
+		LLAgentAccess aa(cgr);
+		
+		cgr.setPreferredMaturity(SIM_ACCESS_PG);
+		ensure("1 prefersPG",     aa.prefersPG());
+		ensure("1 prefersMature", !aa.prefersMature());
+		ensure("1 prefersAdult",  !aa.prefersAdult());
+		
+		cgr.setPreferredMaturity(SIM_ACCESS_MATURE);
+		ensure("2 prefersPG",     !aa.prefersPG());
+		ensure("2 prefersMature", aa.prefersMature());
+		ensure("2 prefersAdult",  !aa.prefersAdult());
+		
+		cgr.setPreferredMaturity(SIM_ACCESS_ADULT);
+		ensure("3 prefersPG",     !aa.prefersPG());
+		ensure("3 prefersMature", aa.prefersMature());
+		ensure("3 prefersAdult",  aa.prefersAdult());
+    }
+    
+	template<> template<>
+	void agentaccess_object_t::test<2>()
+	{
+		LLControlGroupReader_Test cgr;
+		LLAgentAccess aa(cgr);
+		
+		// make sure default is PG
+		ensure("1 isTeen",     aa.isTeen());
+		ensure("1 isMature",   !aa.isMature());
+		ensure("1 isAdult",    !aa.isAdult());
+		
+		// this is kinda bad -- setting this forces maturity to MATURE but !teen != Mature anymore
+		aa.setTeen(false);
+		ensure("2 isTeen",     !aa.isTeen());
+		ensure("2 isMature",   aa.isMature());
+		ensure("2 isAdult",    !aa.isAdult());
+
+		// have to flip it back and make sure it still works
+		aa.setTeen(true);
+		ensure("3 isTeen",     aa.isTeen());
+		ensure("3 isMature",   !aa.isMature());
+		ensure("3 isAdult",    !aa.isAdult());		
+
+		// check the conversion routine
+		ensure_equals("1 conversion", SIM_ACCESS_PG, aa.convertTextToMaturity('P'));
+		ensure_equals("2 conversion", SIM_ACCESS_MATURE, aa.convertTextToMaturity('M'));
+		ensure_equals("3 conversion", SIM_ACCESS_ADULT, aa.convertTextToMaturity('A'));
+		ensure_equals("4 conversion", SIM_ACCESS_MIN, aa.convertTextToMaturity('Q'));
+		
+		// now try the other method of setting it - PG
+		aa.setMaturity('P');
+		ensure("4 isTeen",     aa.isTeen());
+		ensure("4 isMature",   !aa.isMature());
+		ensure("4 isAdult",    !aa.isAdult());
+		
+		// Mature
+		aa.setMaturity('M');
+		ensure("5 isTeen",     !aa.isTeen());
+		ensure("5 isMature",   aa.isMature());
+		ensure("5 isAdult",    !aa.isAdult());
+		
+		// Adult
+		aa.setMaturity('A');
+		ensure("6 isTeen",     !aa.isTeen());
+		ensure("6 isMature",   aa.isMature());
+		ensure("6 isAdult",    aa.isAdult());
+		
+	}
+
+	template<> template<>
+	void agentaccess_object_t::test<3>()
+	{
+		LLControlGroupReader_Test cgr;
+		LLAgentAccess aa(cgr);
+		
+		ensure("starts normal", !aa.isGodlike());
+		aa.setGodLevel(GOD_NOT);
+		ensure("stays normal", !aa.isGodlike());
+		aa.setGodLevel(GOD_FULL);
+		ensure("sets full", aa.isGodlike());
+		aa.setGodLevel(GOD_NOT);
+		ensure("resets normal", !aa.isGodlike());
+		aa.setAdminOverride(true);
+		ensure("admin true", aa.getAdminOverride());
+		ensure("overrides 1", aa.isGodlike());
+		aa.setGodLevel(GOD_FULL);
+		ensure("overrides 2", aa.isGodlike());
+		aa.setAdminOverride(false);
+		ensure("admin false", !aa.getAdminOverride());
+		ensure("overrides 3", aa.isGodlike());
+    }
+    
+	template<> template<>
+	void agentaccess_object_t::test<4>()
+	{
+		LLControlGroupReader_Test cgr;
+		LLAgentAccess aa(cgr);
+		
+		ensure("1 pg to start", aa.wantsPGOnly());
+		ensure("2 pg to start", !aa.canAccessMature());
+		ensure("3 pg to start", !aa.canAccessAdult());
+		
+		aa.setGodLevel(GOD_FULL);
+		ensure("1 full god", !aa.wantsPGOnly());
+		ensure("2 full god", aa.canAccessMature());
+		ensure("3 full god", aa.canAccessAdult());
+				
+		aa.setGodLevel(GOD_NOT);
+		aa.setAdminOverride(true);
+		ensure("1 admin mode", !aa.wantsPGOnly());
+		ensure("2 admin mode", aa.canAccessMature());
+		ensure("3 admin mode", aa.canAccessAdult());
+
+		aa.setAdminOverride(false);
+		aa.setMaturity('M');
+		// preferred is still pg by default
+		ensure("1 mature pref pg", aa.wantsPGOnly());
+		ensure("2 mature pref pg", !aa.canAccessMature());
+		ensure("3 mature pref pg", !aa.canAccessAdult());
+		
+		cgr.setPreferredMaturity(SIM_ACCESS_MATURE);
+		ensure("1 mature", !aa.wantsPGOnly());
+		ensure("2 mature", aa.canAccessMature());
+		ensure("3 mature", !aa.canAccessAdult());
+		
+		cgr.setPreferredMaturity(SIM_ACCESS_PG);
+		ensure("1 mature pref pg", aa.wantsPGOnly());
+		ensure("2 mature pref pg", !aa.canAccessMature());
+		ensure("3 mature pref pg", !aa.canAccessAdult());
+		
+		aa.setMaturity('A');
+		ensure("1 adult pref pg", aa.wantsPGOnly());
+		ensure("2 adult pref pg", !aa.canAccessMature());
+		ensure("3 adult pref pg", !aa.canAccessAdult());
+
+		cgr.setPreferredMaturity(SIM_ACCESS_ADULT);
+		ensure("1 adult", !aa.wantsPGOnly());
+		ensure("2 adult", aa.canAccessMature());
+		ensure("3 adult", aa.canAccessAdult());
+
+		// make sure that even if pref is high, if access is low we block access
+		// this shouldn't occur in real life but we want to be safe
+		cgr.setPreferredMaturity(SIM_ACCESS_ADULT);
+		aa.setMaturity('P');
+		ensure("1 pref adult, actual pg", aa.wantsPGOnly());
+		ensure("2 pref adult, actual pg", !aa.canAccessMature());
+		ensure("3 pref adult, actual pg", !aa.canAccessAdult());
+		
+	}
+
+	template<> template<>
+	void agentaccess_object_t::test<5>()
+	{
+		LLControlGroupReader_Test cgr;
+		LLAgentAccess aa(cgr);
+		
+		ensure("1 transition starts false", !aa.isInTransition());
+		aa.setTransition();
+		ensure("2 transition now true", aa.isInTransition());
+	}
+
+}
+
+
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index c6d42cf882..22752ef33c 100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -723,6 +723,10 @@ version 2.0
 		{	Auction			BOOL		}
 		{	Dwell			F32			}
 	}
+	{
+		StatusData            Variable
+		{	Status		U32		}
+	}
 }
 
 // DirPeopleReply
@@ -767,6 +771,10 @@ version 2.0
 		{	UnixTime	U32				}
 		{	EventFlags	U32				}
 	}
+	{
+		StatusData Variable
+		{	Status		U32			}
+	}
 }
 
 // DirGroupsReply
@@ -852,6 +860,10 @@ version 2.0
 		{	ExpirationDate	U32			}
 		{	PriceForListing	S32			}
 	}
+	{
+		StatusData Variable
+		{	Status			U32		}
+	}
 }
 
 
@@ -1465,7 +1477,7 @@ version 2.0
 	}
 }
 
-// TeleportFailed somehwere->sim->viewer
+// TeleportFailed somewhere->sim->viewer
 // announce failure of teleport request
 {
 	TeleportFailed Low 74 Trusted Unencoded
@@ -1474,6 +1486,11 @@ version 2.0
 		{	AgentID		LLUUID			}
 		{	Reason		Variable	1	}  // string
 	}
+	{
+		AlertInfo			Variable
+		{	Message			Variable	1	}	// string id
+		{	ExtraParams		Variable	1	}	// llsd extra parameters
+	}
 }
 
 
@@ -2810,6 +2827,11 @@ version 2.0
 		AlertData			Single
 		{	Message			Variable	1	}
 	}
+	{
+		AlertInfo			Variable
+		{	Message			Variable	1	}
+		{	ExtraParams		Variable	1	}
+	}
 }
 
 // Send an AlertMessage to the named agent.
-- 
GitLab