diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index d5d8cda8cecc973208651708132d1fb359810bd1..e8da45816858395920ee71e215a748a0ccda5053 100644
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -34,15 +34,101 @@
 
 // viewer
 #include "llagent.h"
-#include "llfloaterregioninfo.h" // for invoice id
 #include "llviewerregion.h"
-
 #include "llcorehttputil.h"
 
-LLEstateInfoModel::LLEstateInfoModel()
-:	mID(0)
-,	mFlags(0)
-,	mSunHour(0)
+//=========================================================================
+namespace 
+{
+	class LLDispatchEstateUpdateInfo : public LLDispatchHandler
+	{
+	public:
+	    LLDispatchEstateUpdateInfo() {}
+	    virtual ~LLDispatchEstateUpdateInfo() {}
+	    virtual bool operator()(const LLDispatcher* dispatcher, const std::string& key, 
+            const LLUUID& invoice, const sparam_t& strings)
+	    {
+	        // key = "estateupdateinfo"
+	        // strings[0] = estate name
+	        // strings[1] = str(owner_id)
+	        // strings[2] = str(estate_id)
+	        // strings[3] = str(estate_flags)
+	        // strings[4] = str((S32)(sun_hour * 1024))
+	        // strings[5] = str(parent_estate_id)
+	        // strings[6] = str(covenant_id)
+	        // strings[7] = str(covenant_timestamp)
+	        // strings[8] = str(send_to_agent_only)
+	        // strings[9] = str(abuse_email_addr)
+	
+	        LL_DEBUGS("ESTATEINFOM") << "Received estate update" << LL_ENDL;
+	
+	        // Update estate info model.
+	        // This will call LLPanelEstateInfo::refreshFromEstate().
+	        // *TODO: Move estate message handling stuff to llestateinfomodel.cpp.
+	        LLEstateInfoModel::instance().updateEstateInfo(strings);
+	
+	        return true;
+	    }
+	};
+	
+	class LLDispatchSetEstateAccess : public LLDispatchHandler
+	{
+	public:
+	    LLDispatchSetEstateAccess() {}
+	    virtual ~LLDispatchSetEstateAccess() {}
+	    virtual bool operator()(
+	        const LLDispatcher* dispatcher, const std::string& key,
+	        const LLUUID& invoice, const sparam_t& strings)
+	    {
+	        // key = "setaccess"
+	        // strings[0] = str(estate_id)
+	        // strings[1] = str(packed_access_lists)
+	        // strings[2] = str(num allowed agent ids)
+	        // strings[3] = str(num allowed group ids)
+	        // strings[4] = str(num banned agent ids)
+	        // strings[5] = str(num estate manager agent ids)
+	        // strings[6] = bin(uuid)
+	        // strings[7] = bin(uuid)
+	        // strings[8] = bin(uuid)
+	        // ...
+
+            LLEstateInfoModel::instance().updateAccessInfo(strings);
+	
+	        return true;
+	    }
+	
+	};
+
+    class LLDispatchSetEstateExperience : public LLDispatchHandler
+    {
+    public:
+        virtual bool operator()(const LLDispatcher* dispatcher, const std::string& key,
+                const LLUUID& invoice, const sparam_t& strings)
+        {
+            // key = "setexperience"
+            // strings[0] = str(estate_id)
+            // strings[1] = str(send_to_agent_only)
+            // strings[2] = str(num blocked)
+            // strings[3] = str(num trusted)
+            // strings[4] = str(num allowed)
+            // strings[8] = bin(uuid) ...
+            // ...
+
+            LLEstateInfoModel::instance().updateExperienceInfo(strings);
+
+            return true;
+        }
+
+    };
+
+}
+
+//=========================================================================
+LLEstateInfoModel::LLEstateInfoModel():	
+    mID(0),	
+    mFlags(0),	
+    mSunHour(0),
+    mRegion(nullptr)
 {
 }
 
@@ -51,40 +137,52 @@ boost::signals2::connection LLEstateInfoModel::setUpdateCallback(const update_si
 	return mUpdateSignal.connect(cb);
 }
 
+boost::signals2::connection LLEstateInfoModel::setUpdateAccessCallback(const update_flaged_signal_t::slot_type& cb)
+{
+    return mUpdateAccess.connect(cb);
+}
+
+boost::signals2::connection LLEstateInfoModel::setUpdateExperienceCallback(const update_signal_t::slot_type& cb)
+{
+    return mUpdateExperience.connect(cb);
+}
+
 boost::signals2::connection LLEstateInfoModel::setCommitCallback(const update_signal_t::slot_type& cb)
 {
 	return mCommitSignal.connect(cb);
 }
 
+void LLEstateInfoModel::setRegion(LLViewerRegion* region)
+{
+    if (region != mRegion)
+    {
+        mRegion = region;
+
+        if (mRegion)
+        {
+	        nextInvoice();
+	        sendEstateOwnerMessage("getinfo", strings_t());
+        }
+    }
+}
+
+
+void LLEstateInfoModel::clearRegion()
+{
+    mRegion = nullptr;
+}
+
 void LLEstateInfoModel::sendEstateInfo()
 {
 	if (!commitEstateInfoCaps())
 	{
 		// the caps method failed, try the old way
-		LLFloaterRegionInfo::nextInvoice();
+		nextInvoice();
 		commitEstateInfoDataserver();
 	}
 }
 
-bool LLEstateInfoModel::getUseFixedSun()			const {	return getFlag(REGION_FLAGS_SUN_FIXED);				}
-bool LLEstateInfoModel::getIsExternallyVisible()	const {	return getFlag(REGION_FLAGS_EXTERNALLY_VISIBLE);	}
-bool LLEstateInfoModel::getAllowDirectTeleport()	const {	return getFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT);	}
-bool LLEstateInfoModel::getDenyAnonymous()			const {	return getFlag(REGION_FLAGS_DENY_ANONYMOUS); 		}
-bool LLEstateInfoModel::getDenyAgeUnverified()		const {	return getFlag(REGION_FLAGS_DENY_AGEUNVERIFIED);	}
-bool LLEstateInfoModel::getAllowVoiceChat()			const { return getFlag(REGION_FLAGS_ALLOW_VOICE); }
-bool LLEstateInfoModel::getAllowAccessOverride()	const { return getFlag(REGION_FLAGS_ALLOW_ACCESS_OVERRIDE); }
-bool LLEstateInfoModel::getAllowEnvironmentOverride() const { return getFlag(REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE); }
-
-void LLEstateInfoModel::setUseFixedSun(bool val)			{ setFlag(REGION_FLAGS_SUN_FIXED, 				val);	}
-void LLEstateInfoModel::setIsExternallyVisible(bool val)	{ setFlag(REGION_FLAGS_EXTERNALLY_VISIBLE,		val);	}
-void LLEstateInfoModel::setAllowDirectTeleport(bool val)	{ setFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT,	val);	}
-void LLEstateInfoModel::setDenyAnonymous(bool val)			{ setFlag(REGION_FLAGS_DENY_ANONYMOUS,			val);	}
-void LLEstateInfoModel::setDenyAgeUnverified(bool val)		{ setFlag(REGION_FLAGS_DENY_AGEUNVERIFIED,		val);	}
-void LLEstateInfoModel::setAllowVoiceChat(bool val)		    { setFlag(REGION_FLAGS_ALLOW_VOICE,				val);	}
-void LLEstateInfoModel::setAllowAccessOverride(bool val)    { setFlag(REGION_FLAGS_ALLOW_ACCESS_OVERRIDE,   val);   }
-void LLEstateInfoModel::setAllowEnvironmentOverride(bool val)    { setFlag(REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE, val); }
-
-void LLEstateInfoModel::update(const strings_t& strings)
+void LLEstateInfoModel::updateEstateInfo(const strings_t& strings)
 {
 	// NOTE: LLDispatcher extracts strings with an extra \0 at the
 	// end.  If we pass the std::string direct to the UI/renderer
@@ -95,10 +193,10 @@ void LLEstateInfoModel::update(const strings_t& strings)
 	mFlags		= strtoul(strings[3].c_str(), NULL, 10);
 	mSunHour	= ((F32)(strtod(strings[4].c_str(), NULL)))/1024.0f;
 
-	LL_DEBUGS("WindlightSync") << "Received estate info: "
+    LL_DEBUGS("ESTATEINFOM") << "Received estate info: "
 		<< "is_sun_fixed = " << getUseFixedSun()
 		<< ", sun_hour = " << getSunHour() << LL_ENDL;
-	LL_DEBUGS() << getInfoDump() << LL_ENDL;
+    LL_DEBUGS("ESTATEINFOM") << getInfoDump() << LL_ENDL;
 
 	// Update region owner.
 	LLViewerRegion* regionp = gAgent.getRegion();
@@ -108,20 +206,205 @@ void LLEstateInfoModel::update(const strings_t& strings)
 	mUpdateSignal();
 }
 
+void LLEstateInfoModel::updateAccessInfo(const strings_t& strings)
+{
+    S32 index = 1;	// skip estate_id
+    U32 access_flags = strtoul(strings[index++].c_str(), NULL, 10);
+    S32 num_allowed_agents = strtol(strings[index++].c_str(), NULL, 10);
+    S32 num_allowed_groups = strtol(strings[index++].c_str(), NULL, 10);
+    S32 num_banned_agents = strtol(strings[index++].c_str(), NULL, 10);
+    S32 num_estate_managers = strtol(strings[index++].c_str(), NULL, 10);
+
+    // sanity ckecks
+    if (num_allowed_agents > 0
+        && !(access_flags & ESTATE_ACCESS_ALLOWED_AGENTS))
+    {
+        LL_WARNS("ESTATEINFOM") << "non-zero count for allowed agents, but no corresponding flag" << LL_ENDL;
+    }
+    if (num_allowed_groups > 0
+        && !(access_flags & ESTATE_ACCESS_ALLOWED_GROUPS))
+    {
+        LL_WARNS("ESTATEINFOM") << "non-zero count for allowed groups, but no corresponding flag" << LL_ENDL;
+    }
+    if (num_banned_agents > 0
+        && !(access_flags & ESTATE_ACCESS_BANNED_AGENTS))
+    {
+        LL_WARNS("ESTATEINFOM") << "non-zero count for banned agents, but no corresponding flag" << LL_ENDL;
+    }
+    if (num_estate_managers > 0
+        && !(access_flags & ESTATE_ACCESS_MANAGERS))
+    {
+        LL_WARNS("ESTATEINFOM") << "non-zero count for managers, but no corresponding flag" << LL_ENDL;
+    }
+
+    // grab the UUID's out of the string fields
+    if (access_flags & ESTATE_ACCESS_ALLOWED_AGENTS)
+    {
+        mAllowedAgents.clear();
+
+        for (S32 i = 0; i < num_allowed_agents && i < ESTATE_MAX_ACCESS_IDS; i++)
+        {
+            LLUUID id;
+            memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
+            mAllowedAgents.insert(id);
+        }
+    }
+
+    if (access_flags & ESTATE_ACCESS_ALLOWED_GROUPS)
+    {
+        mAllowedGroups.clear();
+
+        for (S32 i = 0; i < num_allowed_groups && i < ESTATE_MAX_GROUP_IDS; i++)
+        {
+            LLUUID id;
+            memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
+            mAllowedGroups.insert(id);
+        }
+    }
+
+    if (access_flags & ESTATE_ACCESS_BANNED_AGENTS)
+    {
+        mBannedAgents.clear();
+
+        for (S32 i = 0; i < num_banned_agents && i < ESTATE_MAX_ACCESS_IDS; i++)
+        {
+            LLUUID id;
+            memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
+            mBannedAgents.insert(id);
+        }
+    }
+
+    if (access_flags & ESTATE_ACCESS_MANAGERS)
+    {
+        mEstateManagers.clear();
+
+        // There should be only ESTATE_MAX_MANAGERS people in the list, but if the database gets more (SL-46107) don't 
+        // truncate the list unless it's really big.  Go ahead and show the extras so the user doesn't get confused, 
+        // and they can still remove them.
+        for (S32 i = 0; i < num_estate_managers && i < (ESTATE_MAX_MANAGERS * 4); i++)
+        {
+            LLUUID id;
+            memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
+            mEstateManagers.insert(id);
+        }
+    }
+
+    // Update the buttons which may change based on the list contents but also needs to account for general access features.
+    mUpdateAccess(access_flags);
+}
+
+void LLEstateInfoModel::updateExperienceInfo(const strings_t& strings)
+{
+    strings_t::const_iterator it = strings.begin();
+    ++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10);
+    ++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10);
+
+    LLUUID id;
+    S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10);
+    S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10);
+    S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10);
+
+    mExperienceAllowed.clear();
+    mExperienceTrusted.clear();
+    mExperienceBlocked.clear();
+
+    while (num_blocked-- > 0)
+    {
+        memcpy(id.mData, (*(it++)).data(), UUID_BYTES);
+        mExperienceBlocked.insert(id);
+    }
+
+    while (num_trusted-- > 0)
+    {
+        memcpy(id.mData, (*(it++)).data(), UUID_BYTES);
+        mExperienceTrusted.insert(id);
+    }
+
+    while (num_allowed-- > 0)
+    {
+        memcpy(id.mData, (*(it++)).data(), UUID_BYTES);
+        mExperienceAllowed.insert(id);
+    }
+
+    mUpdateExperience();
+}
+
 void LLEstateInfoModel::notifyCommit()
 {
 	mCommitSignal();
 }
 
+void LLEstateInfoModel::initSingleton()
+{
+    gMessageSystem->setHandlerFunc("EstateOwnerMessage", &processEstateOwnerRequest);
+
+    //	name.assign("setowner");
+    //	static LLDispatchSetEstateOwner set_owner;
+    //	dispatch.addHandler(name, &set_owner);
+
+    static LLDispatchEstateUpdateInfo estate_update_info;
+    mDispatch.addHandler("estateupdateinfo", &estate_update_info);
+
+    static LLDispatchSetEstateAccess set_access;
+    mDispatch.addHandler("setaccess", &set_access);
+
+    static LLDispatchSetEstateExperience set_experience;
+    mDispatch.addHandler("setexperience", &set_experience);
+
+}
+
+void LLEstateInfoModel::sendEstateOwnerMessage(const std::string& request, const strings_t& strings)
+{
+    if (!mRegion)
+    {
+        LL_WARNS("ESTATEINFOM") << "No selected region." << LL_ENDL;
+        return;
+    }
+    LLMessageSystem* msg(gMessageSystem);
+    LLUUID invoice(LLEstateInfoModel::instance().getLastInvoice());
+
+    LL_INFOS() << "Sending estate request '" << request << "'" << LL_ENDL;
+    msg->newMessage("EstateOwnerMessage");
+    msg->nextBlockFast(_PREHASH_AgentData);
+    msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+    msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+    msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
+    msg->nextBlock("MethodData");
+    msg->addString("Method", request);
+    msg->addUUID("Invoice", invoice);
+    if (strings.empty())
+    {
+        msg->nextBlock("ParamList");
+        msg->addString("Parameter", NULL);
+    }
+    else
+    {
+        strings_t::const_iterator it = strings.begin();
+        strings_t::const_iterator end = strings.end();
+        for (; it != end; ++it)
+        {
+            msg->nextBlock("ParamList");
+            msg->addString("Parameter", *it);
+        }
+    }
+    msg->sendReliable(mRegion->getHost());
+}
+
 //== PRIVATE STUFF ============================================================
 
 // tries to send estate info using a cap; returns true if it succeeded
 bool LLEstateInfoModel::commitEstateInfoCaps()
 {
-	std::string url = gAgent.getRegionCapability("EstateChangeInfo");
+    if (!mRegion)
+    {
+        LL_WARNS("ESTATEINFOM") << "Attempt to update estate caps with no anchor region! Don't do that!" << LL_ENDL;
+        return false;
+    }
+    std::string url = mRegion->getCapability("EstateChangeInfo");
 
 	if (url.empty())
 	{
+        LL_WARNS("ESTATEINFOM") << "No EstateChangeInfo cap from region." << LL_ENDL;
 		// whoops, couldn't find the cap, so bail out
 		return false;
 	}
@@ -152,12 +435,12 @@ void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
     body["override_public_access"] = getAllowAccessOverride();
     body["override_environment"] = getAllowEnvironmentOverride();
 
-    body["invoice"] = LLFloaterRegionInfo::getLastInvoice();
+    body["invoice"] = getLastInvoice();
 
-    LL_DEBUGS("WindlightSync") << "Sending estate caps: "
+    LL_DEBUGS("ESTATEINFOM") << "Sending estate caps: "
         << "is_sun_fixed = " << getUseFixedSun()
         << ", sun_hour = " << getSunHour() << LL_ENDL;
-    LL_DEBUGS() << body << LL_ENDL;
+    LL_DEBUGS("ESTATEINFOM") << body << LL_ENDL;
 
     LLSD result = httpAdapter->postAndSuspend(httpRequest, url, body);
 
@@ -166,12 +449,12 @@ void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
 
     if (status)
     {
-        LL_INFOS() << "Committed estate info" << LL_ENDL;
+        LL_INFOS("ESTATEINFOM") << "Committed estate info" << LL_ENDL;
         LLEstateInfoModel::instance().notifyCommit();
     }
     else
     {
-        LL_WARNS() << "Failed to commit estate info " << LL_ENDL;
+        LL_WARNS("ESTATEINFOM") << "Failed to commit estate info " << LL_ENDL;
     }
 }
 
@@ -184,10 +467,15 @@ void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
 // strings[3] = str((S32)(sun_hour * 1024.f))
 void LLEstateInfoModel::commitEstateInfoDataserver()
 {
-	LL_DEBUGS("WindlightSync") << "Sending estate info: "
+    if (!mRegion)
+    {
+        LL_WARNS("ESTATEINFOM") << "No selected region." << LL_ENDL;
+        return;
+    }
+    LL_DEBUGS("ESTATEINFOM") << "Sending estate info: "
 		<< "is_sun_fixed = " << getUseFixedSun()
 		<< ", sun_hour = " << getSunHour() << LL_ENDL;
-	LL_DEBUGS() << getInfoDump() << LL_ENDL;
+    LL_DEBUGS("ESTATEINFOM") << getInfoDump() << LL_ENDL;
 
 	LLMessageSystem* msg = gMessageSystem;
 	msg->newMessage("EstateOwnerMessage");
@@ -198,7 +486,7 @@ void LLEstateInfoModel::commitEstateInfoDataserver()
 
 	msg->nextBlock("MethodData");
 	msg->addString("Method", "estatechangeinfo");
-	msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice());
+	msg->addUUID("Invoice", getLastInvoice());
 
 	msg->nextBlock("ParamList");
 	msg->addString("Parameter", getName());
@@ -209,7 +497,7 @@ void LLEstateInfoModel::commitEstateInfoDataserver()
 	msg->nextBlock("ParamList");
 	msg->addString("Parameter", llformat("%d", (S32) (getSunHour() * 1024.0f)));
 
-	gAgent.sendMessage();
+    msg->sendReliable(mRegion->getHost());
 }
 
 std::string LLEstateInfoModel::getInfoDump()
@@ -231,3 +519,22 @@ std::string LLEstateInfoModel::getInfoDump()
 	dump_str << dump;
 	return dump_str.str();
 }
+
+// static
+void LLEstateInfoModel::processEstateOwnerRequest(LLMessageSystem* msg, void**)
+{
+    // unpack the message
+    std::string request;
+    LLUUID invoice;
+    LLDispatcher::sparam_t strings;
+    LLDispatcher::unpackMessage(msg, request, invoice, strings);
+    if (invoice != LLEstateInfoModel::instance().getLastInvoice())
+    {
+        LL_WARNS("ESTATEINFOM") << "Mismatched Estate message: " << request << LL_ENDL;
+        return;
+    }
+
+    //dispatch the message
+    LLEstateInfoModel::instance().mDispatch.dispatch(request, invoice, strings);
+}
+
diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h
index d6f00c573cf11c619d9ee62917c6bde60d31938e..85f9f91d862ea87e0c3e1220f4e6444f0f681136 100644
--- a/indra/newview/llestateinfomodel.h
+++ b/indra/newview/llestateinfomodel.h
@@ -32,7 +32,10 @@ class LLMessageSystem;
 #include "llsingleton.h"
 #include "llcoros.h"
 #include "lleventcoro.h"
+#include "lldispatcher.h"
+#include "llregionflags.h"
 
+class LLViewerRegion;
 /**
  * Contains estate info, notifies interested parties of its changes.
  */
@@ -42,68 +45,110 @@ class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel>
 	LOG_CLASS(LLEstateInfoModel);
 
 public:
-	typedef boost::signals2::signal<void()> update_signal_t;
-	boost::signals2::connection setUpdateCallback(const update_signal_t::slot_type& cb); /// the model has been externally updated
-	boost::signals2::connection setCommitCallback(const update_signal_t::slot_type& cb); /// our changes have been applied
+    typedef std::vector<std::string>            strings_t;
+	typedef boost::signals2::signal<void()>     update_signal_t;
+    typedef boost::signals2::signal<void(U32)>  update_flaged_signal_t;
+    typedef boost::signals2::connection         connection_t;
 
-	void sendEstateInfo(); /// send estate info to the simulator
+    connection_t            setUpdateCallback(const update_signal_t::slot_type& cb); /// the model has been externally updated
+    connection_t            setUpdateAccessCallback(const update_flaged_signal_t::slot_type& cb);
+    connection_t            setUpdateExperienceCallback(const update_signal_t::slot_type& cb);
+    connection_t            setCommitCallback(const update_signal_t::slot_type& cb); /// our changes have been applied
+
+    void                    setRegion(LLViewerRegion* region);
+    void                    clearRegion();
+	void                    sendEstateInfo(); /// send estate info to the simulator
 
 	// getters
-	bool				getUseFixedSun()			const;
-	bool				getIsExternallyVisible()	const;
-	bool				getAllowDirectTeleport()	const;
-	bool				getDenyAnonymous()			const;
-	bool				getDenyAgeUnverified()		const;
-	bool				getAllowVoiceChat()			const;
-    bool                getAllowAccessOverride()    const;
-    bool                getAllowEnvironmentOverride() const;
-
-	const std::string&	getName()					const { return mName; }
-	const LLUUID&		getOwnerID()				const { return mOwnerID; }
-	U32					getID()						const { return mID; }
-	F32					getSunHour()				const { return getUseFixedSun() ? mSunHour : 0.f; }
+    bool                    getUseFixedSun() const              { return getFlag(REGION_FLAGS_SUN_FIXED); }
+    bool                    getIsExternallyVisible() const      { return getFlag(REGION_FLAGS_EXTERNALLY_VISIBLE); }
+    bool                    getAllowDirectTeleport() const      { return getFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT); }
+    bool                    getDenyAnonymous() const            { return getFlag(REGION_FLAGS_DENY_ANONYMOUS); }
+    bool                    getDenyAgeUnverified() const        { return getFlag(REGION_FLAGS_DENY_AGEUNVERIFIED); }
+    bool                    getAllowVoiceChat() const           { return getFlag(REGION_FLAGS_ALLOW_VOICE); }
+    bool                    getAllowAccessOverride() const      { return getFlag(REGION_FLAGS_ALLOW_ACCESS_OVERRIDE); }
+    bool                    getAllowEnvironmentOverride() const { return getFlag(REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE); }
+
+	const std::string&	    getName()					const { return mName; }
+	const LLUUID&		    getOwnerID()				const { return mOwnerID; }
+	U32					    getID()						const { return mID; }
+	F32					    getSunHour()				const { return getUseFixedSun() ? mSunHour : 0.f; }
 
 	// setters
-	void setUseFixedSun(bool val);
-	void setIsExternallyVisible(bool val);
-	void setAllowDirectTeleport(bool val);
-	void setDenyAnonymous(bool val);
-	void setDenyAgeUnverified(bool val);
-	void setAllowVoiceChat(bool val);
-    void setAllowAccessOverride(bool val);
-    void setAllowEnvironmentOverride(bool val);
+    void                    setUseFixedSun(bool val)                { setFlag(REGION_FLAGS_SUN_FIXED, val); }
+    void                    setIsExternallyVisible(bool val)        { setFlag(REGION_FLAGS_EXTERNALLY_VISIBLE, val); }
+    void                    setAllowDirectTeleport(bool val)        { setFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT, val); }
+    void                    setDenyAnonymous(bool val)              { setFlag(REGION_FLAGS_DENY_ANONYMOUS, val); }
+    void                    setDenyAgeUnverified(bool val)          { setFlag(REGION_FLAGS_DENY_AGEUNVERIFIED, val); }
+    void                    setAllowVoiceChat(bool val)             { setFlag(REGION_FLAGS_ALLOW_VOICE, val); }
+    void                    setAllowAccessOverride(bool val)        { setFlag(REGION_FLAGS_ALLOW_ACCESS_OVERRIDE, val); }
+    void                    setAllowEnvironmentOverride(bool val)   { setFlag(REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE, val); }
 
-	void setSunHour(F32 sun_hour) { mSunHour = sun_hour; }
+	void                    setSunHour(F32 sun_hour) { mSunHour = sun_hour; }
 
-protected:
-	typedef std::vector<std::string> strings_t;
+    const uuid_set_t &      getAllowedAgents() const                { return mAllowedAgents; }
+    const uuid_set_t &      getAllowedGroups() const                { return mAllowedGroups; }
+    const uuid_set_t &      getBannedAgents() const                 { return mBannedAgents; }
+    const uuid_set_t &      getEstateManagers() const               { return mEstateManagers; }
+
+    const uuid_set_t &      getAllowedExperiences() const           { return mExperienceAllowed; }
+    const uuid_set_t &      getTrustedExperiences() const           { return mExperienceTrusted; }
+    const uuid_set_t &      getBlockedExperiences() const           { return mExperienceBlocked; }
+
+    void                    sendEstateOwnerMessage(const std::string& request, const strings_t& strings);
+
+    //---------------------------------------------------------------------
+    /// refresh model with data from the incoming server message
+    void                    updateEstateInfo(const strings_t& strings);
+    void                    updateAccessInfo(const strings_t& strings);
+    void                    updateExperienceInfo(const strings_t& strings);
+
+    const LLUUID &          getLastInvoice()    { return mRequestInvoice; }
+    const LLUUID &          nextInvoice()       { mRequestInvoice.generate(); return mRequestInvoice; }
 
-	friend class LLDispatchEstateUpdateInfo;
+protected:
 
-	/// refresh model with data from the incoming server message
-	void update(const strings_t& strings);
+	void                    notifyCommit();
 
-	void notifyCommit();
+    virtual void            initSingleton() override;
 
 private:
-	bool commitEstateInfoCaps();
-	void commitEstateInfoDataserver();
-	inline bool getFlag(U64 flag) const;
-	inline void setFlag(U64 flag, bool val);
-	U64  getFlags() const { return mFlags; }
-	std::string getInfoDump();
+	bool                    commitEstateInfoCaps();
+	void                    commitEstateInfoDataserver();
+	inline bool             getFlag(U64 flag) const;
+	inline void             setFlag(U64 flag, bool val);
+	U64                     getFlags() const { return mFlags; }
+	std::string             getInfoDump();
 
 	// estate info
-	std::string	mName;			/// estate name
-	LLUUID		mOwnerID;		/// estate owner id
-	U32			mID;			/// estate id
-	U64			mFlags;			/// estate flags
-	F32			mSunHour;		/// estate sun hour
+	std::string	            mName;			/// estate name
+	LLUUID		            mOwnerID;		/// estate owner id
+	U32			            mID;			/// estate id
+	U64			            mFlags;			/// estate flags
+	F32			            mSunHour;		/// estate sun hour
+
+    uuid_set_t              mAllowedAgents;
+    uuid_set_t              mAllowedGroups;
+    uuid_set_t              mBannedAgents;
+    uuid_set_t              mEstateManagers;
+
+    uuid_set_t              mExperienceAllowed;
+    uuid_set_t              mExperienceTrusted;
+    uuid_set_t              mExperienceBlocked;
+
+	update_signal_t         mUpdateSignal; /// emitted when we receive update from sim
+    update_flaged_signal_t  mUpdateAccess;
+    update_signal_t         mUpdateExperience;
+	update_signal_t         mCommitSignal; /// emitted when our update gets applied to sim
+
+    LLDispatcher            mDispatch;
+    LLUUID                  mRequestInvoice;
+    LLViewerRegion*         mRegion;
+
+    void                    commitEstateInfoCapsCoro(std::string url);
 
-	update_signal_t mUpdateSignal; /// emitted when we receive update from sim
-	update_signal_t mCommitSignal; /// emitted when our update gets applied to sim
+    static void             processEstateOwnerRequest(LLMessageSystem* msg, void**);
 
-    void commitEstateInfoCapsCoro(std::string url);
 };
 
 inline bool LLEstateInfoModel::getFlag(U64 flag) const
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 3e07c4abc73d46c5aef83719448d718192d63329..40e26ba3bdae41610ecc24af1d752e86eee03a80 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -106,43 +106,6 @@ const S32 CORNER_COUNT = 4;
 /// Local class declaration
 ///----------------------------------------------------------------------------
 
-class LLDispatchEstateUpdateInfo : public LLDispatchHandler
-{
-public:
-	LLDispatchEstateUpdateInfo() {}
-	virtual ~LLDispatchEstateUpdateInfo() {}
-	virtual bool operator()(
-		const LLDispatcher* dispatcher,
-		const std::string& key,
-		const LLUUID& invoice,
-		const sparam_t& strings);
-};
-
-class LLDispatchSetEstateAccess : public LLDispatchHandler
-{
-public:
-	LLDispatchSetEstateAccess() {}
-	virtual ~LLDispatchSetEstateAccess() {}
-	virtual bool operator()(
-		const LLDispatcher* dispatcher,
-		const std::string& key,
-		const LLUUID& invoice,
-		const sparam_t& strings);
-};
-
-class LLDispatchSetEstateExperience : public LLDispatchHandler
-{
-public:
-	virtual bool operator()(
-		const LLDispatcher* dispatcher,
-		const std::string& key,
-		const LLUUID& invoice,
-		const sparam_t& strings);
-
-	LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count );
-};
-
-
 /*
 void unpack_request_params(
 	LLMessageSystem* msg,
@@ -180,6 +143,7 @@ class LLPanelRegionEnvironment : public LLPanelEnvironmentInfo
 {
 public:
                         LLPanelRegionEnvironment();
+    virtual             ~LLPanelRegionEnvironment();
 
     virtual void        refresh() override;
 
@@ -205,7 +169,7 @@ class LLPanelRegionEnvironment : public LLPanelEnvironmentInfo
 
 private:
     bool                mAllowOverrideRestore;
-
+    connection_t        mCommitConnect;
 };
 
 
@@ -217,10 +181,6 @@ bool estate_dispatch_initialized = false;
 /// LLFloaterRegionInfo
 ///----------------------------------------------------------------------------
 
-//S32 LLFloaterRegionInfo::sRequestSerial = 0;
-LLUUID LLFloaterRegionInfo::sRequestInvoice;
-
-
 LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
 	: LLFloater(seed),
     mEnvironmentPanel(NULL),
@@ -278,10 +238,6 @@ BOOL LLFloaterRegionInfo::postBuild()
 		mTab->addTabPanel(panel);
 	}
 
-	gMessageSystem->setHandlerFunc(
-		"EstateOwnerMessage", 
-		&processEstateOwnerRequest);
-
 	// Request region info when agent region changes.
 	mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterRegionInfo::onRegionChanged, this));
 
@@ -337,42 +293,6 @@ void LLFloaterRegionInfo::requestRegionInfo()
 	gAgent.sendReliableMessage();
 }
 
-// static
-void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**)
-{
-	static LLDispatcher dispatch;
-	LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
-	if(!floater)
-	{
-		return;
-	}
-	
-	if (!estate_dispatch_initialized)
-	{
-		LLPanelEstateInfo::initDispatch(dispatch);
-	}
-
-	LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
-	LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild<LLPanel>("Estate");
-
-	// unpack the message
-	std::string request;
-	LLUUID invoice;
-	LLDispatcher::sparam_t strings;
-	LLDispatcher::unpackMessage(msg, request, invoice, strings);
-	if(invoice != getLastInvoice())
-	{
-		LL_WARNS() << "Mismatched Estate message: " << request << LL_ENDL;
-		return;
-	}
-
-	//dispatch the message
-	dispatch.dispatch(request, invoice, strings);
-
-	panel->updateControls(gAgent.getRegion());
-}
-
-
 // static
 void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
 {
@@ -687,43 +607,10 @@ void LLPanelRegionInfo::updateChild(LLUICtrl* child_ctr)
 // virtual
 bool LLPanelRegionInfo::refreshFromRegion(LLViewerRegion* region)
 {
-	if (region) mHost = region->getHost();
+    LLEstateInfoModel::instance().setRegion(region);
 	return true;
 }
 
-void LLPanelRegionInfo::sendEstateOwnerMessage(
-	LLMessageSystem* msg,
-	const std::string& request,
-	const LLUUID& invoice,
-	const strings_t& strings)
-{
-	LL_INFOS() << "Sending estate request '" << request << "'" << LL_ENDL;
-	msg->newMessage("EstateOwnerMessage");
-	msg->nextBlockFast(_PREHASH_AgentData);
-	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
-	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-	msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
-	msg->nextBlock("MethodData");
-	msg->addString("Method", request);
-	msg->addUUID("Invoice", invoice);
-	if(strings.empty())
-	{
-		msg->nextBlock("ParamList");
-		msg->addString("Parameter", NULL);
-	}
-	else
-	{
-		strings_t::const_iterator it = strings.begin();
-		strings_t::const_iterator end = strings.end();
-		for(; it != end; ++it)
-		{
-			msg->nextBlock("ParamList");
-			msg->addString("Parameter", *it);
-		}
-	}
-	msg->sendReliable(mHost);
-}
-
 void LLPanelRegionInfo::enableButton(const std::string& btn_name, BOOL enable)
 {
 	LLView* button = findChildView(btn_name);
@@ -857,8 +744,7 @@ void LLPanelRegionGeneralInfo::onKickCommit(const uuid_vec_t& ids)
 		ids[0].toString(buffer);
 		strings.push_back(strings_t::value_type(buffer));
 
-		LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-		sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings);
+		LLEstateInfoModel::instance().sendEstateOwnerMessage("teleporthomeuser", strings);
 	}
 }
 
@@ -883,9 +769,8 @@ bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const L
 		gAgent.getID().toString(buffer);
 		strings.push_back(buffer);
 
-		LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
 		// historical message name
-		sendEstateOwnerMessage(gMessageSystem, "teleporthomeallusers", invoice, strings);
+        LLEstateInfoModel::instance().sendEstateOwnerMessage("teleporthomeallusers", strings);
 	}
 	return false;
 }
@@ -924,8 +809,7 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
 	LLAgentUI::buildFullname(name);
 	strings.push_back(strings_t::value_type(name));
 	strings.push_back(strings_t::value_type(text));
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	sendEstateOwnerMessage(gMessageSystem, "simulatormessage", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("simulatormessage", strings);
 	return false;
 }
 
@@ -1011,8 +895,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
 		buffer = llformat("%s", (getChild<LLUICtrl>("allow_parcel_changes_check")->getValue().asBoolean() ? "Y" : "N"));
 		strings.push_back(strings_t::value_type(buffer));
 
-		LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-		sendEstateOwnerMessage(gMessageSystem, "setregioninfo", invoice, strings);
+        LLEstateInfoModel::instance().sendEstateOwnerMessage("setregioninfo", strings);
 	}
 
 	// if we changed access levels, tell user about it
@@ -1084,8 +967,7 @@ BOOL LLPanelRegionDebugInfo::sendUpdate()
 	buffer = llformat("%s", (getChild<LLUICtrl>("disable_physics_check")->getValue().asBoolean() ? "Y" : "N"));
 	strings.push_back(buffer);
 
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	sendEstateOwnerMessage(gMessageSystem, "setregiondebug", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("setregiondebug", strings);
 	return TRUE;
 }
 
@@ -1155,9 +1037,7 @@ bool LLPanelRegionDebugInfo::callbackReturn(const LLSD& notification, const LLSD
 			strings.push_back(llformat("%d", flags));
 			strings.push_back(target_avatar.asString());
 
-			LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-		
-			sendEstateOwnerMessage(gMessageSystem, "estateobjectreturn", invoice, strings);
+            LLEstateInfoModel::instance().sendEstateOwnerMessage("estateobjectreturn", strings);
 		}
 		else
 		{
@@ -1175,7 +1055,6 @@ void LLPanelRegionDebugInfo::onClickTopColliders(void* data)
 	LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data;
 	strings_t strings;
 	strings.push_back("1");	// one physics step
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
 	LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
 	if(!instance) return;
 	LLFloaterReg::showInstance("top_objects");
@@ -1185,7 +1064,7 @@ void LLPanelRegionDebugInfo::onClickTopColliders(void* data)
 	self->getChildView("top_colliders_btn")->setEnabled(false);
 	self->getChildView("top_scripts_btn")->setEnabled(false);
 
-	self->sendEstateOwnerMessage(gMessageSystem, "colliders", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("colliders", strings);
 }
 
 // static
@@ -1194,7 +1073,6 @@ void LLPanelRegionDebugInfo::onClickTopScripts(void* data)
 	LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data;
 	strings_t strings;
 	strings.push_back("6");	// top 5 scripts
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
 	LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance<LLFloaterTopObjects>("top_objects");
 	if(!instance) return;
 	LLFloaterReg::showInstance("top_objects");
@@ -1204,7 +1082,7 @@ void LLPanelRegionDebugInfo::onClickTopScripts(void* data)
 	self->getChildView("top_colliders_btn")->setEnabled(false);
 	self->getChildView("top_scripts_btn")->setEnabled(false);
 
-	self->sendEstateOwnerMessage(gMessageSystem, "scripts", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("scripts", strings);
 }
 
 // static
@@ -1221,19 +1099,16 @@ bool LLPanelRegionDebugInfo::callbackRestart(const LLSD& notification, const LLS
 
 	strings_t strings;
 	strings.push_back("120");
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("restart", strings);
 	return false;
 }
 
 // static
 void LLPanelRegionDebugInfo::onClickCancelRestart(void* data)
 {
-	LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data;
 	strings_t strings;
 	strings.push_back("-1");
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	self->sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("restart", strings);
 }
 
 // static
@@ -1398,7 +1273,6 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
 	LL_INFOS() << "LLPanelRegionTerrainInfo::sendUpdate" << LL_ENDL;
 	std::string buffer;
 	strings_t strings;
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
 
 	// update the model
 	LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
@@ -1407,7 +1281,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
 	region_info.mTerrainLowerLimit = (F32) getChild<LLUICtrl>("terrain_lower_spin")->getValue().asReal();
 
 	// and sync the region with it
-	region_info.sendRegionTerrain(invoice);
+	region_info.sendRegionTerrain(LLEstateInfoModel::instance().getLastInvoice());
 	
 	// =======================================
 	// Assemble and send texturedetail message
@@ -1435,7 +1309,6 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
 
 	LLTextureCtrl* texture_ctrl;
 	std::string id_str;
-	LLMessageSystem* msg = gMessageSystem;
 
 	for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
 	{
@@ -1449,7 +1322,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
 			strings.push_back(buffer);
 		}
 	}
-	sendEstateOwnerMessage(msg, "texturedetail", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("texturedetail", strings);
 	strings.clear();
 
 	// ========================================
@@ -1462,13 +1335,13 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate()
 		std::string buffer3 = llformat("%d %f %f", i, (F32)getChild<LLUICtrl>(buffer)->getValue().asReal(), (F32)getChild<LLUICtrl>(buffer2)->getValue().asReal());
 		strings.push_back(buffer3);
 	}
-	sendEstateOwnerMessage(msg, "textureheights", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("textureheights", strings);
 	strings.clear();
 
 	// ========================================
 	// Send texturecommit message
 
-	sendEstateOwnerMessage(msg, "texturecommit", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("texturecommit", strings);
 
 	return TRUE;
 }
@@ -1508,12 +1381,10 @@ void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data)
 	std::string filepath = picker.getFirstFile();
 	gXferManager->expectFileForRequest(filepath);
 
-	LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data;
 	strings_t strings;
 	strings.push_back("download filename");
 	strings.push_back(filepath);
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("terrain", strings);
 }
 
 // static
@@ -1528,12 +1399,10 @@ void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data)
 	std::string filepath = picker.getFirstFile();
 	gXferManager->expectFileForTransfer(filepath);
 
-	LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data;
 	strings_t strings;
 	strings.push_back("upload filename");
 	strings.push_back(filepath);
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("terrain", strings);
 
 	LLNotificationsUtil::add("RawUploadStarted");
 }
@@ -1551,8 +1420,7 @@ bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, con
 
 	strings_t strings;
 	strings.push_back("bake");
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("terrain", strings);
 
 	return false;
 }
@@ -1566,33 +1434,11 @@ LLPanelEstateInfo::LLPanelEstateInfo()
 	mEstateID(0)	// invalid
 {
 	LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
+
 	estate_info.setCommitCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this));
 	estate_info.setUpdateCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this));
-}
-
-// static
-void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch)
-{
-	std::string name;
-
-//	name.assign("setowner");
-//	static LLDispatchSetEstateOwner set_owner;
-//	dispatch.addHandler(name, &set_owner);
 
-	name.assign("estateupdateinfo");
-	static LLDispatchEstateUpdateInfo estate_update_info;
-	dispatch.addHandler(name, &estate_update_info);
-
-	name.assign("setaccess");
-	static LLDispatchSetEstateAccess set_access;
-	dispatch.addHandler(name, &set_access);
-
-
-	name.assign("setexperience");
-	static LLDispatchSetEstateExperience set_experience;
-	dispatch.addHandler(name, &set_experience);
-
-	estate_dispatch_initialized = true;
+    estate_info.setUpdateAccessCallback(boost::bind(&LLPanelEstateInfo::refreshAccessFromEstate, this, _1));
 }
 
 //---------------------------------------------------------------------------
@@ -1755,7 +1601,7 @@ bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& re
 			strings_t strings;
 			strings.push_back(notification["payload"]["agent_id"].asString());
 
-			sendEstateOwnerMessage(gMessageSystem, "kickestate", LLFloaterRegionInfo::getLastInvoice(), strings);
+            LLEstateInfoModel::instance().sendEstateOwnerMessage("kickestate", strings);
 			break;
 		}
 	default:
@@ -2152,7 +1998,7 @@ void LLPanelEstateInfo::sendEstateAccessDelta(U32 flags, const LLUUID& agent_or_
 
 	msg->nextBlock("MethodData");
 	msg->addString("Method", "estateaccessdelta");
-	msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice());
+	msg->addUUID("Invoice", LLEstateInfoModel::instance().getLastInvoice());
 
 	std::string buf;
 	gAgent.getID().toString(buf);
@@ -2255,16 +2101,13 @@ bool LLPanelEstateInfo::refreshFromRegion(LLViewerRegion* region)
 	strings_t strings;
 	//integers_t integers;
 	//LLFloaterRegionInfo::incrementSerial();
-	LLFloaterRegionInfo::nextInvoice();
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
 	//integers.push_back(LLFloaterRegionInfo::());::getPanelEstate();
 
 	
 	LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate();
 	panel->clearAccessLists();
 	
-
-	sendEstateOwnerMessage(gMessageSystem, "getinfo", invoice, strings);
+    LLEstateInfoModel::instance().setRegion(region);
 
 	refresh();
 
@@ -2383,6 +2226,147 @@ void LLPanelEstateInfo::refreshFromEstate()
 	refresh();
 }
 
+
+void LLPanelEstateInfo::refreshAccessFromEstate(U32 flags)
+{
+    const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
+
+    // grab the UUID's out of the string fields
+    if (flags & ESTATE_ACCESS_ALLOWED_AGENTS)
+    {
+        LLNameListCtrl *allowed_agent_name_list(getChild<LLNameListCtrl>("allowed_avatar_name_list"));
+
+        const uuid_set_t& allowed_agents(estate_info.getAllowedAgents());
+        int totalAllowedAgents = allowed_agents.size();
+
+        if (allowed_agent_name_list)
+        {
+            totalAllowedAgents += allowed_agent_name_list->getItemCount();
+        }
+
+        LLStringUtil::format_map_t args;
+        args["[ALLOWEDAGENTS]"] = llformat("%d", totalAllowedAgents);
+        args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
+        std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args);
+        getChild<LLUICtrl>("allow_resident_label")->setValue(LLSD(msg));
+
+        if (allowed_agent_name_list)
+        {
+            // Don't sort these as we add them, sort them when we are done.
+            allowed_agent_name_list->clearSortOrder();
+            allowed_agent_name_list->deleteAllItems();
+
+            for (const LLUUID &id : allowed_agents)
+            {
+                allowed_agent_name_list->addNameItem(id);
+            }
+            allowed_agent_name_list->sortByName(TRUE);
+        }
+    }
+
+    if (flags & ESTATE_ACCESS_ALLOWED_GROUPS)
+    {
+        LLNameListCtrl* allowed_group_name_list(getChild<LLNameListCtrl>("allowed_group_name_list"));
+        const uuid_set_t &allowed_groups(estate_info.getAllowedGroups());
+
+        LLStringUtil::format_map_t args;
+        args["[ALLOWEDGROUPS]"] = llformat("%d", allowed_groups.size());
+        args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_GROUP_IDS);
+        std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args);
+        getChild<LLUICtrl>("allow_group_label")->setValue(LLSD(msg));
+
+        if (allowed_group_name_list)
+        {
+            // Don't sort these as we add them, sort them when we are done.
+            allowed_group_name_list->clearSortOrder();
+            allowed_group_name_list->deleteAllItems();
+
+            for (const LLUUID &id: allowed_groups)
+            {
+                allowed_group_name_list->addGroupNameItem(id);
+            }
+            allowed_group_name_list->sortByName(TRUE);
+        }
+    }
+
+    if (flags & ESTATE_ACCESS_BANNED_AGENTS)
+    {
+        LLNameListCtrl* banned_agent_name_list(getChild<LLNameListCtrl>("banned_avatar_name_list"));
+        const uuid_set_t &banned_agents(estate_info.getBannedAgents());
+        int totalBannedAgents = banned_agents.size();
+
+        if (banned_agent_name_list)
+        {
+            totalBannedAgents += banned_agent_name_list->getItemCount();
+        }
+
+
+        LLStringUtil::format_map_t args;
+        args["[BANNEDAGENTS]"] = llformat("%d", totalBannedAgents);
+        args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
+        std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);
+        getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));
+
+        if (banned_agent_name_list)
+        {
+            // Don't sort these as we add them, sort them when we are done.
+            banned_agent_name_list->clearSortOrder();
+
+            for (const LLUUID &id: banned_agents)
+            {
+                banned_agent_name_list->addNameItem(id);
+            }
+            banned_agent_name_list->sortByName(TRUE);
+        }
+    }
+
+    if (flags & ESTATE_ACCESS_MANAGERS)
+    {
+        LLNameListCtrl* estate_manager_name_list(getChild<LLNameListCtrl>("estate_manager_name_list"));
+        const uuid_set_t &estate_mgrs(estate_info.getEstateManagers());
+
+        LLStringUtil::format_map_t args;
+        args["[ESTATEMANAGERS]"] = llformat("%d", estate_mgrs.size());
+        args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS);
+        std::string msg = LLTrans::getString("RegionInfoEstateManagers", args);
+        getChild<LLUICtrl>("estate_manager_label")->setValue(LLSD(msg));
+
+        if (estate_manager_name_list)
+        {
+            // Don't sort these as we add them, sort them when we are done.
+            estate_manager_name_list->clearSortOrder();
+            estate_manager_name_list->deleteAllItems();		// Clear existing entries
+
+            // There should be only ESTATE_MAX_MANAGERS people in the list, but if the database gets more (SL-46107) don't 
+            // truncate the list unless it's really big.  Go ahead and show the extras so the user doesn't get confused, 
+            // and they can still remove them.
+            for (const LLUUID &id : estate_mgrs)
+            {
+                estate_manager_name_list->addNameItem(id);
+            }
+            estate_manager_name_list->sortByName(TRUE);
+        }
+    }
+
+    // Update the buttons which may change based on the list contents but also needs to account for general access features.
+    updateControls(gAgent.getRegion());
+}
+
+
+namespace
+{
+    LLSD set_to_llsdarray(const uuid_set_t &values)
+    {
+        LLSD result(LLSD::emptyArray());
+
+        for (const LLUUID &id : values)
+        {
+            result.append(id);
+        }
+        return result;
+    }
+}
+
 BOOL LLPanelEstateInfo::sendUpdate()
 {
 	LL_INFOS() << "LLPanelEsateInfo::sendUpdate()" << LL_ENDL;
@@ -2515,8 +2499,8 @@ bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& re
 	LLAgentUI::buildFullname(name);
 	strings.push_back(strings_t::value_type(name));
 	strings.push_back(strings_t::value_type(text));
-	LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
-	sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings);
+
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("instantmessage", strings);
 	return false;
 }
 
@@ -2801,7 +2785,7 @@ void LLPanelEstateCovenant::sendChangeCovenantID(const LLUUID &asset_id)
 
 		msg->nextBlock("MethodData");
 		msg->addString("Method", "estatechangecovenantid");
-		msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice());
+		msg->addUUID("Invoice", LLEstateInfoModel::instance().getLastInvoice());
 
 		msg->nextBlock("ParamList");
 		msg->addString("Parameter", getCovenantID().asString());
@@ -2881,261 +2865,6 @@ void LLPanelEstateCovenant::setCovenantTextEditor(const std::string& text)
 	mEditor->setText(text);
 }
 
-// key = "estateupdateinfo"
-// strings[0] = estate name
-// strings[1] = str(owner_id)
-// strings[2] = str(estate_id)
-// strings[3] = str(estate_flags)
-// strings[4] = str((S32)(sun_hour * 1024))
-// strings[5] = str(parent_estate_id)
-// strings[6] = str(covenant_id)
-// strings[7] = str(covenant_timestamp)
-// strings[8] = str(send_to_agent_only)
-// strings[9] = str(abuse_email_addr)
-bool LLDispatchEstateUpdateInfo::operator()(
-		const LLDispatcher* dispatcher,
-		const std::string& key,
-		const LLUUID& invoice,
-		const sparam_t& strings)
-{
-	LL_DEBUGS() << "Received estate update" << LL_ENDL;
-
-	// Update estate info model.
-	// This will call LLPanelEstateInfo::refreshFromEstate().
-	// *TODO: Move estate message handling stuff to llestateinfomodel.cpp.
-	LLEstateInfoModel::instance().update(strings);
-
-	return true;
-}
-
-
-// key = "setaccess"
-// strings[0] = str(estate_id)
-// strings[1] = str(packed_access_lists)
-// strings[2] = str(num allowed agent ids)
-// strings[3] = str(num allowed group ids)
-// strings[4] = str(num banned agent ids)
-// strings[5] = str(num estate manager agent ids)
-// strings[6] = bin(uuid)
-// strings[7] = bin(uuid)
-// strings[8] = bin(uuid)
-// ...
-bool LLDispatchSetEstateAccess::operator()(
-		const LLDispatcher* dispatcher,
-		const std::string& key,
-		const LLUUID& invoice,
-		const sparam_t& strings)
-{
-	LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate();
-	if (!panel) return true;
-
-	S32 index = 1;	// skip estate_id
-	U32 access_flags = strtoul(strings[index++].c_str(), NULL,10);
-	S32 num_allowed_agents = strtol(strings[index++].c_str(), NULL, 10);
-	S32 num_allowed_groups = strtol(strings[index++].c_str(), NULL, 10);
-	S32 num_banned_agents = strtol(strings[index++].c_str(), NULL, 10);
-	S32 num_estate_managers = strtol(strings[index++].c_str(), NULL, 10);
-
-	// sanity ckecks
-	if (num_allowed_agents > 0
-		&& !(access_flags & ESTATE_ACCESS_ALLOWED_AGENTS))
-	{
-		LL_WARNS() << "non-zero count for allowed agents, but no corresponding flag" << LL_ENDL;
-	}
-	if (num_allowed_groups > 0
-		&& !(access_flags & ESTATE_ACCESS_ALLOWED_GROUPS))
-	{
-		LL_WARNS() << "non-zero count for allowed groups, but no corresponding flag" << LL_ENDL;
-	}
-	if (num_banned_agents > 0
-		&& !(access_flags & ESTATE_ACCESS_BANNED_AGENTS))
-	{
-		LL_WARNS() << "non-zero count for banned agents, but no corresponding flag" << LL_ENDL;
-	}
-	if (num_estate_managers > 0
-		&& !(access_flags & ESTATE_ACCESS_MANAGERS))
-	{
-		LL_WARNS() << "non-zero count for managers, but no corresponding flag" << LL_ENDL;
-	}
-
-	// grab the UUID's out of the string fields
-	if (access_flags & ESTATE_ACCESS_ALLOWED_AGENTS)
-	{
-		LLNameListCtrl* allowed_agent_name_list;
-		allowed_agent_name_list = panel->getChild<LLNameListCtrl>("allowed_avatar_name_list");
-
-		int totalAllowedAgents = num_allowed_agents;
-		
-		if (allowed_agent_name_list) 
-		{
-			totalAllowedAgents += allowed_agent_name_list->getItemCount();
-		}
-
-		LLStringUtil::format_map_t args;
-		args["[ALLOWEDAGENTS]"] = llformat ("%d", totalAllowedAgents);
-		args["[MAXACCESS]"] = llformat ("%d", ESTATE_MAX_ACCESS_IDS);
-		std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args);
-		panel->getChild<LLUICtrl>("allow_resident_label")->setValue(LLSD(msg));
-
-		if (allowed_agent_name_list)
-		{
-			// Don't sort these as we add them, sort them when we are done.
-			allowed_agent_name_list->clearSortOrder();
-			for (S32 i = 0; i < num_allowed_agents && i < ESTATE_MAX_ACCESS_IDS; i++)
-			{
-				LLUUID id;
-				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
-				allowed_agent_name_list->addNameItem(id);
-			}
-			allowed_agent_name_list->sortByName(TRUE);
-		}
-	}
-
-	if (access_flags & ESTATE_ACCESS_ALLOWED_GROUPS)
-	{
-		LLNameListCtrl* allowed_group_name_list;
-		allowed_group_name_list = panel->getChild<LLNameListCtrl>("allowed_group_name_list");
-
-		LLStringUtil::format_map_t args;
-		args["[ALLOWEDGROUPS]"] = llformat ("%d", num_allowed_groups);
-		args["[MAXACCESS]"] = llformat ("%d", ESTATE_MAX_GROUP_IDS);
-		std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args);
-		panel->getChild<LLUICtrl>("allow_group_label")->setValue(LLSD(msg));
-
-		if (allowed_group_name_list)
-		{
-			// Don't sort these as we add them, sort them when we are done.
-			allowed_group_name_list->clearSortOrder();
-			allowed_group_name_list->deleteAllItems();
-			for (S32 i = 0; i < num_allowed_groups && i < ESTATE_MAX_GROUP_IDS; i++)
-			{
-				LLUUID id;
-				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
-				allowed_group_name_list->addGroupNameItem(id);
-			}
-			allowed_group_name_list->sortByName(TRUE);
-		}
-	}
-
-	if (access_flags & ESTATE_ACCESS_BANNED_AGENTS)
-	{
-		LLNameListCtrl* banned_agent_name_list;
-		banned_agent_name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list");
-
-		int totalBannedAgents = num_banned_agents;
-		
-		if (banned_agent_name_list) 
-		{
-			totalBannedAgents += banned_agent_name_list->getItemCount();
-		}
-
-
-		LLStringUtil::format_map_t args;
-		args["[BANNEDAGENTS]"] = llformat("%d", totalBannedAgents);
-		args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
-		std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);
-		panel->getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));
-
-		if (banned_agent_name_list)
-		{
-			// Don't sort these as we add them, sort them when we are done.
-			banned_agent_name_list->clearSortOrder();
-
-			for (S32 i = 0; i < num_banned_agents && i < ESTATE_MAX_ACCESS_IDS; i++)
-			{
-				LLUUID id;
-				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
-				banned_agent_name_list->addNameItem(id);
-			}
-			banned_agent_name_list->sortByName(TRUE);
-		}
-	}
-
-	if (access_flags & ESTATE_ACCESS_MANAGERS)
-	{
-		LLStringUtil::format_map_t args;
-		args["[ESTATEMANAGERS]"] = llformat("%d", num_estate_managers);
-		args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS);
-		std::string msg = LLTrans::getString("RegionInfoEstateManagers", args);
-		panel->getChild<LLUICtrl>("estate_manager_label")->setValue(LLSD(msg));
-
-		LLNameListCtrl* estate_manager_name_list =
-			panel->getChild<LLNameListCtrl>("estate_manager_name_list");
-		if (estate_manager_name_list)
-		{	
-			// Don't sort these as we add them, sort them when we are done.
-			estate_manager_name_list->clearSortOrder();
-
-			estate_manager_name_list->deleteAllItems();		// Clear existing entries
-
-			// There should be only ESTATE_MAX_MANAGERS people in the list, but if the database gets more (SL-46107) don't 
-			// truncate the list unless it's really big.  Go ahead and show the extras so the user doesn't get confused, 
-			// and they can still remove them.
-			for (S32 i = 0; i < num_estate_managers && i < (ESTATE_MAX_MANAGERS * 4); i++)
-			{
-				LLUUID id;
-				memcpy(id.mData, strings[index++].data(), UUID_BYTES);		/* Flawfinder: ignore */
-				estate_manager_name_list->addNameItem(id);
-			}
-			estate_manager_name_list->sortByName(TRUE);
-		}
-	}
-
-	// Update the buttons which may change based on the list contents but also needs to account for general access features.
-	panel->updateControls(gAgent.getRegion());
-
-	return true;
-}
-
-LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count )
-{
-	LLSD idList = LLSD::emptyArray();
-	LLUUID id;
-	while(count--> 0)
-	{
-		memcpy(id.mData, (*(it++)).data(), UUID_BYTES);
-		idList.append(id);
-	}
-	return idList;
-}
-
-// key = "setexperience"
-// strings[0] = str(estate_id)
-// strings[1] = str(send_to_agent_only)
-// strings[2] = str(num blocked)
-// strings[3] = str(num trusted)
-// strings[4] = str(num allowed)
-// strings[8] = bin(uuid) ...
-// ...
-bool LLDispatchSetEstateExperience::operator()(
-	const LLDispatcher* dispatcher,
-	const std::string& key,
-	const LLUUID& invoice,
-	const sparam_t& strings)
-{
-	LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences();
-	if (!panel) return true;
-
-	sparam_t::const_iterator it = strings.begin();
-	++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10);
-	++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10);
-
-	LLUUID id;
-	S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10);
-	S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10);
-	S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10);
-
-	LLSD ids = LLSD::emptyMap()
-		.with("blocked", getIDs(it,								strings.end(), num_blocked))
-		.with("trusted", getIDs(it + (num_blocked),				strings.end(), num_trusted))
-		.with("allowed", getIDs(it + (num_blocked+num_trusted),	strings.end(), num_allowed));
-
-	panel->processResponse(ids);			
-
-	return true;
-}
-
-
 BOOL LLPanelRegionExperiences::postBuild()
 {
 	mAllowed = setupList("panel_allowed", ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE);
@@ -3148,6 +2877,8 @@ BOOL LLPanelRegionExperiences::postBuild()
 	getChild<LLTextBox>("allowed_text_help")->setText(getString("allowed_estate_text"));
 	getChild<LLTextBox>("blocked_text_help")->setText(getString("blocked_estate_text"));
 
+    LLEstateInfoModel::instance().setUpdateExperienceCallback(boost::bind(&LLPanelRegionExperiences::refreshExperiencesFromEstate, this));
+
 	return LLPanelRegionInfo::postBuild();
 }
 
@@ -3191,6 +2922,18 @@ void LLPanelRegionExperiences::processResponse( const LLSD& content )
 
 }
 
+void LLPanelRegionExperiences::refreshExperiencesFromEstate()
+{
+    const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
+
+    LLSD ids = LLSDMap("blocked", set_to_llsdarray(estate_info.getBlockedExperiences()))
+        ("trusted", set_to_llsdarray(estate_info.getTrustedExperiences()))
+        ("allowed", set_to_llsdarray(estate_info.getAllowedExperiences()));
+
+    processResponse(ids);
+}
+
+
 // Used for both access add and remove operations, depending on the flag
 // passed in (ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE, etc.)
 // static
@@ -3253,11 +2996,7 @@ void LLPanelRegionExperiences::sendEstateExperienceDelta(U32 flags, const LLUUID
 	str[1] = llformat("%u", flags);
 	experience_id.toString(str[2]);
 
-	LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences();
-	if (panel)
-	{
-		panel->sendEstateOwnerMessage(gMessageSystem, "estateexperiencedelta", LLFloaterRegionInfo::getLastInvoice(), str);
-	}
+    LLEstateInfoModel::instance().sendEstateOwnerMessage("estateexperiencedelta", str);
 }
 
 
@@ -3402,14 +3141,18 @@ LLPanelRegionEnvironment::LLPanelRegionEnvironment():
     LLPanelEnvironmentInfo(),
     mAllowOverrideRestore(false)
 {
-    LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
-    estate_info.setCommitCallback(boost::bind(&LLPanelRegionEnvironment::refreshFromEstate, this));
-    estate_info.setUpdateCallback(boost::bind(&LLPanelRegionEnvironment::refreshFromEstate, this));
 }
 
+LLPanelRegionEnvironment::~LLPanelRegionEnvironment()
+{
+    if (mCommitConnect.connected())
+        mCommitConnect.disconnect();
+}
 
 BOOL LLPanelRegionEnvironment::postBuild()
 {
+    LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
+
     if (!LLPanelEnvironmentInfo::postBuild())
         return FALSE;
 
@@ -3418,6 +3161,8 @@ BOOL LLPanelRegionEnvironment::postBuild()
     getChild<LLUICtrl>(PNL_ENVIRONMENT_ALTITUDES)->setVisible(TRUE);
 
     getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setCommitCallback([this](LLUICtrl *, const LLSD &value){ onChkAllowOverride(value.asBoolean()); });
+
+    mCommitConnect = estate_info.setCommitCallback(boost::bind(&LLPanelRegionEnvironment::refreshFromEstate, this));
     return TRUE;
 }
 
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 0566c4b2ce497da04aa744893cfcc2c5cc58ca96..e4687fff0c27485cf5159c00c23adc3ef22a7d0b 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -77,13 +77,9 @@ class LLFloaterRegionInfo : public LLFloater
 	/*virtual*/ void onOpen(const LLSD& key);
 	/*virtual*/ BOOL postBuild();
 
-	static void processEstateOwnerRequest(LLMessageSystem* msg, void**);
-
 	// get and process region info if necessary.
 	static void processRegionInfo(LLMessageSystem* msg);
 
-	static const LLUUID& getLastInvoice() { return sRequestInvoice; }
-	static void nextInvoice() { sRequestInvoice.generate(); }
 	//static S32 getSerial() { return sRequestSerial; }
 	//static void incrementSerial() { sRequestSerial++; }
 
@@ -119,8 +115,7 @@ class LLFloaterRegionInfo : public LLFloater
 	typedef std::vector<LLPanelRegionInfo*> info_panels_t;
 	info_panels_t mInfoPanels;
     LLPanelRegionEnvironment *mEnvironmentPanel;
-	//static S32 sRequestSerial;	// serial # of last EstateOwnerRequest
-	static LLUUID sRequestInvoice;
+
 private:
     boost::signals2::connection mRegionChangedCallback;
 };
@@ -157,14 +152,6 @@ class LLPanelRegionInfo : public LLPanel
 	
 	typedef std::vector<std::string> strings_t;
 	//typedef std::vector<U32> integers_t;
-	void sendEstateOwnerMessage(
-					 LLMessageSystem* msg,
-					 const std::string& request,
-					 const LLUUID& invoice,
-					 const strings_t& strings);
-	
-	// member data
-	LLHost mHost;
 };
 
 /////////////////////////////////////////////////////////////////////////////
@@ -266,12 +253,9 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo
 };
 
 /////////////////////////////////////////////////////////////////////////////
-
 class LLPanelEstateInfo : public LLPanelRegionInfo
 {
 public:
-	static void initDispatch(LLDispatcher& dispatch);
-	
 	void onChangeFixedSun();
 	void onChangeUseGlobalTime();
 	void onChangeAccessOverride();
@@ -331,6 +315,7 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
 	virtual void refresh();
 
 	void refreshFromEstate();
+    void refreshAccessFromEstate(U32 flags);
 	
 	static bool isLindenEstate();
 	
@@ -433,7 +418,7 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo
 	void sendPurchaseRequest()const;
 	void processResponse( const LLSD& content );
 private:
-	void refreshRegionExperiences();
+    void refreshExperiencesFromEstate();
 
     static std::string regionCapabilityQuery(LLViewerRegion* region, const std::string &cap);
 
diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp
index b4007cfdf0d9714965b519feb4de6a725bd0d048..a64053f5319293e49b8259f25e270ddd3f66aab0 100644
--- a/indra/newview/llpanelenvironment.cpp
+++ b/indra/newview/llpanelenvironment.cpp
@@ -140,10 +140,13 @@ LLPanelEnvironmentInfo::~LLPanelEnvironmentInfo()
         mChangeMonitor.disconnect();
     if (mCommitConnection.connected())
         mCommitConnection.disconnect();
+    if (mUpdateConnection.connected())
+        mUpdateConnection.disconnect();
 }
 
 BOOL LLPanelEnvironmentInfo::postBuild()
 {
+
     getChild<LLUICtrl>(BTN_USEDEFAULT)->setCommitCallback([this](LLUICtrl *, const LLSD &){ onBtnDefault(); });
     getChild<LLUICtrl>(BTN_SELECTINV)->setCommitCallback([this](LLUICtrl *, const LLSD &){ onBtnSelect(); });
     getChild<LLUICtrl>(BTN_EDIT)->setCommitCallback([this](LLUICtrl *, const LLSD &){ onBtnEdit(); });
@@ -158,6 +161,9 @@ BOOL LLPanelEnvironmentInfo::postBuild()
 
     mChangeMonitor = LLEnvironment::instance().setEnvironmentChanged([this](LLEnvironment::EnvSelection_t env, S32 version) { onEnvironmentChanged(env, version); });
 
+    // if we ever allow LLEstateInfoModel to work for non-EMs, uncomment this line.
+    // mUpdateConnection = LLEstateInfoModel::instance().setUpdateCallback(boost::bind(&LLPanelEnvironmentInfo::refreshFromEstate, this));
+
     getChild<LLSettingsDropTarget>(SDT_DROP_TARGET)->setPanel(this);
 
     return TRUE;
@@ -283,21 +289,13 @@ void LLPanelEnvironmentInfo::refresh()
 
 void LLPanelEnvironmentInfo::refreshFromEstate()
 {
-    /*TODO: Bug!!  estate_info seems stale if regain floater has not been opened.*/
-    const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
+    /*TODO: Unfortunately only estate manager may get information from the LLEstateInfoModel.  
+     * The proletariat is not allowed to know what options are set for an estate. We should fix this.*/
 
-    if (isRegion())
-    { // this should always work... but estate_info gives back false when it shouldn't for parcels
-        bool oldAO = mAllowOverride;
-        mAllowOverride = estate_info.getAllowEnvironmentOverride();
-        if (oldAO != mAllowOverride)
-            refresh();
-    }
-    else
-    {
-        // Get rid of this when I solve the above.
-        mAllowOverride = true;
-    }
+    bool oldAO = mAllowOverride;
+    mAllowOverride = (!isRegion()) || LLEstateInfoModel::instance().getAllowEnvironmentOverride();
+    if (oldAO != mAllowOverride)
+        refresh();
 }
 
 std::string LLPanelEnvironmentInfo::getInventoryNameForAssetId(LLUUID asset_id) 
diff --git a/indra/newview/llpanelenvironment.h b/indra/newview/llpanelenvironment.h
index 3649abe93940f1f8cb98f342ff8d42473f37cc4e..abdbda864b7a4c4a81dd3c77cb615a2e43793b47 100644
--- a/indra/newview/llpanelenvironment.h
+++ b/indra/newview/llpanelenvironment.h
@@ -97,14 +97,14 @@ class LLPanelEnvironmentInfo : public LLPanel
 
     static const U32            DIRTY_FLAG_MASK;
 
-    bool setControlsEnabled(bool enabled);
+    bool                        setControlsEnabled(bool enabled);
     void                        setApplyProgress(bool started);
     void                        setDirtyFlag(U32 flag);
     void                        clearDirtyFlag(U32 flag);
     bool                        getIsDirty() const                  { return (mDirtyFlag != 0); }
     bool                        getIsDirtyFlag(U32 flag) const      { return ((mDirtyFlag & flag) != 0); }
     U32                         getDirtyFlag() const                { return mDirtyFlag; }
-    void updateAltLabel(const std::string &alt_name, U32 sky_index, F32 alt_value);
+    void                        updateAltLabel(const std::string &alt_name, U32 sky_index, F32 alt_value);
     void                        readjustAltLabels();
 
     void                        onSldDayLengthChanged(F32 value);
@@ -164,16 +164,18 @@ class LLPanelEnvironmentInfo : public LLPanel
     S32                             mCurEnvVersion; // used to filter duplicate callbacks/refreshes
 
 protected:
+    typedef boost::signals2::connection connection_t;
+
     void                            refreshFromEstate();
     bool                            mAllowOverride;
 
 private:
     static void                     onIdlePlay(void *);
 
-    typedef boost::signals2::connection connection_t;
-
     connection_t                    mCommitConnection;
     connection_t                    mChangeMonitor;
+    connection_t                    mUpdateConnection;
+
     LLHandle<LLFloater>             mSettingsFloater;
     LLHandle<LLFloater>             mEditFloater;
     S32                             mDirtyFlag;