From bc543c1797c629a8584dd2e74d3c5f7a67de96c9 Mon Sep 17 00:00:00 2001
From: PixelTomsen
Date: Wed, 23 May 2012 21:06:25 +0200
Subject: Environment Module - allows Environment settings for Viewer3 warning:
 includes database region store migrations for mssql, mysql, sqlite

enable/disable this module:
Cap_EnvironmentSettings = "localhost" (for enable)
Cap_EnvironmentSettings = "" (for disable) at ClientStack.LindenCaps section (OpenSimDefaults.ini file)
 or owerwrite in OpenSim.ini

mantis: http://opensimulator.org/mantis/view.php?id=5860

Signed-off-by: BlueWall <jamesh@bluewallgroup.com>
---
 OpenSim/Capabilities/LLSDEnvironmentSettings.cs    |  68 +++++++
 OpenSim/Data/MSSQL/MSSQLSimulationData.cs          |  66 ++++++
 .../Data/MSSQL/Resources/RegionStore.migrations    |  14 ++
 OpenSim/Data/MySQL/MySQLSimulationData.cs          |  62 ++++++
 .../Data/MySQL/Resources/RegionStore.migrations    |  11 +
 OpenSim/Data/Null/NullSimulationData.cs            |  18 ++
 .../Data/SQLite/Resources/RegionStore.migrations   |  11 +
 OpenSim/Data/SQLite/SQLiteSimulationData.cs        | 101 +++++++++-
 .../CoreModules/LightShare/EnvironmentModule.cs    | 224 +++++++++++++++++++++
 .../Framework/Interfaces/IEnvironmentModule.cs     |  36 ++++
 .../Framework/Interfaces/ISimulationDataService.cs |  21 ++
 .../Framework/Interfaces/ISimulationDataStore.cs   |  20 ++
 .../Connectors/Simulation/SimulationDataService.cs |  16 ++
 OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs  |  35 +++-
 14 files changed, 701 insertions(+), 2 deletions(-)
 create mode 100644 OpenSim/Capabilities/LLSDEnvironmentSettings.cs
 create mode 100644 OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs
 create mode 100644 OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs

(limited to 'OpenSim')

diff --git a/OpenSim/Capabilities/LLSDEnvironmentSettings.cs b/OpenSim/Capabilities/LLSDEnvironmentSettings.cs
new file mode 100644
index 0000000..39019af
--- /dev/null
+++ b/OpenSim/Capabilities/LLSDEnvironmentSettings.cs
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using OpenMetaverse;
+
+namespace OpenSim.Framework.Capabilities
+{
+    [OSDMap]
+    public class LLSDEnvironmentRequest
+    {
+        public UUID messageID;
+        public UUID regionID;
+    }
+
+    [OSDMap]
+    public class LLSDEnvironmentSetResponse
+    {
+        public UUID regionID;
+        public UUID messageID;
+        public Boolean success;
+        public String fail_reason;
+    }
+
+    public class EnvironmentSettings
+    {
+        /// <summary>
+        /// generates a empty llsd settings response for viewer
+        /// </summary>
+        /// <param name="messageID">the message UUID</param>
+        /// <param name="regionID">the region UUID</param>
+        public static string EmptySettings(UUID messageID, UUID regionID)
+        {
+            OSDArray arr = new OSDArray();
+            LLSDEnvironmentRequest msg = new LLSDEnvironmentRequest();
+            msg.messageID = messageID;
+            msg.regionID = regionID;
+            arr.Array.Add(msg);
+            return LLSDHelpers.SerialiseLLSDReply(arr);
+        }
+    }
+
+}
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index d9dfe86..3f29f5b 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -1181,6 +1181,72 @@ VALUES
             //            }
             #endregion
         }
+
+        #region Environment Settings
+        public string LoadRegionEnvironmentSettings(UUID regionUUID)
+        {
+            string sql = "select * from [regionenvironment] where region_id = @region_id";
+            using (SqlConnection conn = new SqlConnection(m_connectionString))
+            using (SqlCommand cmd = new SqlCommand(sql, conn))
+            {
+                cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
+                conn.Open();
+                using (SqlDataReader result = cmd.ExecuteReader())
+                {
+                    if (!result.Read())
+                    {
+                        return String.Empty;
+                    }
+                    else
+                    {
+                        return Convert.ToString(result["llsd_settings"]);
+                    }
+                }
+            }
+        }
+
+        public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
+        {
+            {
+                string sql = "DELETE FROM [regionenvironment] WHERE region_id = @region_id";
+                using (SqlConnection conn = new SqlConnection(m_connectionString))
+
+                using (SqlCommand cmd = new SqlCommand(sql, conn))
+                {
+                    cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
+                    conn.Open();
+                    cmd.ExecuteNonQuery();
+                }
+
+                sql = "INSERT INTO [regionenvironment] (region_id, llsd_settings) VALUES (@region_id, @llsd_settings)";
+
+                using (SqlConnection conn = new SqlConnection(m_connectionString))
+
+                using (SqlCommand cmd = new SqlCommand(sql, conn))
+                {
+                    cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
+                    cmd.Parameters.Add(_Database.CreateParameter("@llsd_settings", settings));
+
+                    conn.Open();
+                    cmd.ExecuteNonQuery();
+                }
+            }
+        }
+
+        public void RemoveRegionEnvironmentSettings(UUID regionUUID)
+        {
+            string sql = "delete from [regionenvironment] where region_id = @region_id";
+            using (SqlConnection conn = new SqlConnection(m_connectionString))
+            using (SqlCommand cmd = new SqlCommand(sql, conn))
+            {
+                cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionUUID));
+
+                conn.Open();
+                cmd.ExecuteNonQuery();
+            }
+        }
+        #endregion
+
         /// <summary>
         /// Loads the settings of a region.
         /// </summary>
diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
index d6a3be9..350e548 100644
--- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
@@ -1134,3 +1134,17 @@ ALTER TABLE landaccesslist ADD Expires integer NOT NULL  DEFAULT 0;
 
 COMMIT
 
+:VERSION 37       #---------------- Environment Settings
+
+BEGIN TRANSACTION
+
+CREATE TABLE [dbo].[regionenvironment](
+	[region_id] [uniqueidentifier] NOT NULL,
+	[llsd_settings] [varchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
+ PRIMARY KEY CLUSTERED
+(
+	[region_id] ASC
+)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
+) ON [PRIMARY]
+
+COMMIT
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index b2a1481..1a2e113 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -969,6 +969,68 @@ namespace OpenSim.Data.MySQL
             }
         }
 
+        #region RegionEnvironmentSettings
+        public string LoadRegionEnvironmentSettings(UUID regionUUID)
+        {
+            using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+            {
+                dbcon.Open();
+
+                string command = "select * from `regionenvironment` where region_id = ?region_id";
+
+                using (MySqlCommand cmd = new MySqlCommand(command))
+                {
+                    cmd.Connection = dbcon;
+
+                    cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
+
+                    IDataReader result = ExecuteReader(cmd);
+                    if (!result.Read())
+                    {
+                        return String.Empty;
+                    }
+                    else
+                    {
+                        return Convert.ToString(result["llsd_settings"]);
+                    }
+                }
+            }
+        }
+
+        public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
+        {
+            using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+            {
+                dbcon.Open();
+
+                using (MySqlCommand cmd = dbcon.CreateCommand())
+                {
+                    cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
+
+                    cmd.Parameters.AddWithValue("region_id", regionUUID);
+                    cmd.Parameters.AddWithValue("llsd_settings", settings);
+
+                    ExecuteNonQuery(cmd);
+                }
+            }
+        }
+
+        public void RemoveRegionEnvironmentSettings(UUID regionUUID)
+        {
+            using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
+            {
+                dbcon.Open();
+
+                using (MySqlCommand cmd = dbcon.CreateCommand())
+                {
+                    cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
+                    cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
+                    ExecuteNonQuery(cmd);
+                }
+            }
+        }
+        #endregion
+
         public void StoreRegionSettings(RegionSettings rs)
         {
             lock (m_dbLock)
diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
index 099beaf..4a925fb 100644
--- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
@@ -883,4 +883,15 @@ ALTER TABLE `regionsettings` MODIFY COLUMN `TelehubObject` VARCHAR(36) NOT NULL
 
 COMMIT;
 
+:VERSION 44         #--------------------- Environment Settings
+
+BEGIN;
+
+CREATE TABLE `regionenvironment` (
+  `region_id` varchar(36) NOT NULL,
+  `llsd_settings` TEXT NOT NULL,
+  PRIMARY KEY (`region_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+COMMIT;
 
diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs
index 18a4818..8f2314f 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -76,6 +76,24 @@ namespace OpenSim.Data.Null
             //This connector doesn't support the windlight module yet
         }
 
+        #region Environment Settings
+        public string LoadRegionEnvironmentSettings(UUID regionUUID)
+        {
+            //This connector doesn't support the Environment module yet
+            return string.Empty;
+        }
+
+        public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
+        {
+            //This connector doesn't support the Environment module yet
+        }
+
+        public void RemoveRegionEnvironmentSettings(UUID regionUUID)
+        {
+            //This connector doesn't support the Environment module yet
+        }
+        #endregion
+
         public RegionSettings LoadRegionSettings(UUID regionUUID)
         {
             RegionSettings rs = new RegionSettings();
diff --git a/OpenSim/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
index 1ceddf9..e872977 100644
--- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations
+++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
@@ -564,3 +564,14 @@ COMMIT;
 BEGIN;
 ALTER TABLE `regionsettings` ADD COLUMN `parcel_tile_ID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
 COMMIT;
+
+:VERSION 26
+
+BEGIN;
+
+CREATE TABLE `regionenvironment` (
+  `region_id` varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000' PRIMARY KEY,
+  `llsd_settings` TEXT NOT NULL
+);
+
+COMMIT;
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 7e7c08a..f40e866 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -61,6 +61,7 @@ namespace OpenSim.Data.SQLite
         private const string regionbanListSelect = "select * from regionban";
         private const string regionSettingsSelect = "select * from regionsettings";
         private const string regionWindlightSelect = "select * from regionwindlight";
+        private const string regionEnvironmentSelect = "select * from regionenvironment";
         private const string regionSpawnPointsSelect = "select * from spawn_points";
 
         private DataSet ds;
@@ -72,6 +73,7 @@ namespace OpenSim.Data.SQLite
         private SqliteDataAdapter landAccessListDa;
         private SqliteDataAdapter regionSettingsDa;
         private SqliteDataAdapter regionWindlightDa;
+        private SqliteDataAdapter regionEnvironmentDa;
         private SqliteDataAdapter regionSpawnPointsDa;
 
         private SqliteConnection m_conn;
@@ -146,6 +148,9 @@ namespace OpenSim.Data.SQLite
                 SqliteCommand regionWindlightSelectCmd = new SqliteCommand(regionWindlightSelect, m_conn);
                 regionWindlightDa = new SqliteDataAdapter(regionWindlightSelectCmd);
 
+                SqliteCommand regionEnvironmentSelectCmd = new SqliteCommand(regionEnvironmentSelect, m_conn);
+                regionEnvironmentDa = new SqliteDataAdapter(regionEnvironmentSelectCmd);
+
                 SqliteCommand regionSpawnPointsSelectCmd = new SqliteCommand(regionSpawnPointsSelect, m_conn);
                 regionSpawnPointsDa = new SqliteDataAdapter(regionSpawnPointsSelectCmd);
 
@@ -179,6 +184,9 @@ namespace OpenSim.Data.SQLite
                     ds.Tables.Add(createRegionWindlightTable());
                     setupRegionWindlightCommands(regionWindlightDa, m_conn);
 
+                    ds.Tables.Add(createRegionEnvironmentTable());
+                    setupRegionEnvironmentCommands(regionEnvironmentDa, m_conn);
+
                     ds.Tables.Add(createRegionSpawnPointsTable());
                     setupRegionSpawnPointsCommands(regionSpawnPointsDa, m_conn);
 
@@ -260,6 +268,15 @@ namespace OpenSim.Data.SQLite
 
                     try
                     {
+                        regionEnvironmentDa.Fill(ds.Tables["regionenvironment"]);
+                    }
+                    catch (Exception e)
+                    {
+                        m_log.ErrorFormat("[SQLITE REGION DB]: Caught fill error on regionenvironment table :{0}", e.Message);
+                    }
+
+                    try
+                    {
                         regionSpawnPointsDa.Fill(ds.Tables["spawn_points"]);
                     }
                     catch (Exception e)
@@ -278,12 +295,13 @@ namespace OpenSim.Data.SQLite
                     CreateDataSetMapping(landAccessListDa, "landaccesslist");
                     CreateDataSetMapping(regionSettingsDa, "regionsettings");
                     CreateDataSetMapping(regionWindlightDa, "regionwindlight");
+                    CreateDataSetMapping(regionEnvironmentDa, "regionenvironment");
                     CreateDataSetMapping(regionSpawnPointsDa, "spawn_points");
                 }
             }
             catch (Exception e)
             {
-                m_log.ErrorFormat("[SQLITE REGION DB]: ", e);
+                m_log.ErrorFormat("[SQLITE REGION DB]: {0} - {1}", e.Message, e.StackTrace);
                 Environment.Exit(23);
             }
             return;
@@ -341,6 +359,11 @@ namespace OpenSim.Data.SQLite
                 regionWindlightDa.Dispose();
                 regionWindlightDa = null;
             }
+            if (regionEnvironmentDa != null)
+            {
+                regionEnvironmentDa.Dispose();
+                regionEnvironmentDa = null;
+            }
             if (regionSpawnPointsDa != null)
             {
                 regionSpawnPointsDa.Dispose();
@@ -474,6 +497,63 @@ namespace OpenSim.Data.SQLite
             }
         }
 
+        #region Region Environment Settings
+        public string LoadRegionEnvironmentSettings(UUID regionUUID)
+        {
+            lock (ds)
+            {
+                DataTable environmentTable = ds.Tables["regionenvironment"];
+                DataRow row = environmentTable.Rows.Find(regionUUID.ToString());
+                if (row == null)
+                {
+                    return String.Empty;
+                }
+
+                return (String)row["llsd_settings"];
+            }
+        }
+
+        public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
+        {
+            lock (ds)
+            {
+                DataTable environmentTable = ds.Tables["regionenvironment"];
+                DataRow row = environmentTable.Rows.Find(regionUUID.ToString());
+
+                if (row == null)
+                {
+                    row = environmentTable.NewRow();
+                    row["region_id"] = regionUUID.ToString();
+                    row["llsd_settings"] = settings;
+                    environmentTable.Rows.Add(row);
+                }
+                else
+                {
+                    row["llsd_settings"] = settings;
+                }
+
+                regionEnvironmentDa.Update(ds, "regionenvironment");
+            }
+        }
+
+        public void RemoveRegionEnvironmentSettings(UUID regionUUID)
+        {
+            lock (ds)
+            {
+                DataTable environmentTable = ds.Tables["regionenvironment"];
+                DataRow row = environmentTable.Rows.Find(regionUUID.ToString());
+
+                if (row != null)
+                {
+                    row.Delete();
+                }
+
+                regionEnvironmentDa.Update(ds, "regionenvironment");
+            }
+        }
+
+        #endregion
+
         public RegionSettings LoadRegionSettings(UUID regionUUID)
         {
             lock (ds)
@@ -1430,6 +1510,17 @@ namespace OpenSim.Data.SQLite
             return regionwindlight;
         }
 
+        private static DataTable createRegionEnvironmentTable()
+        {
+            DataTable regionEnvironment = new DataTable("regionenvironment");
+            createCol(regionEnvironment, "region_id", typeof(String));
+            createCol(regionEnvironment, "llsd_settings", typeof(String));
+
+            regionEnvironment.PrimaryKey = new DataColumn[] { regionEnvironment.Columns["region_id"] };
+
+            return regionEnvironment;
+        }
+
         private static DataTable createRegionSpawnPointsTable()
         {
             DataTable spawn_points = new DataTable("spawn_points");
@@ -2691,6 +2782,14 @@ namespace OpenSim.Data.SQLite
             da.UpdateCommand.Connection = conn;
         }
 
+        private void setupRegionEnvironmentCommands(SqliteDataAdapter da, SqliteConnection conn)
+        {
+            da.InsertCommand = createInsertCommand("regionenvironment", ds.Tables["regionenvironment"]);
+            da.InsertCommand.Connection = conn;
+            da.UpdateCommand = createUpdateCommand("regionenvironment", "region_id=:region_id", ds.Tables["regionenvironment"]);
+            da.UpdateCommand.Connection = conn;
+        }
+
         private void setupRegionSpawnPointsCommands(SqliteDataAdapter da, SqliteConnection conn)
         {
             da.InsertCommand = createInsertCommand("spawn_points", ds.Tables["spawn_points"]);
diff --git a/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs b/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs
new file mode 100644
index 0000000..1526886
--- /dev/null
+++ b/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Reflection;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Framework.Capabilities;
+using OpenSim.Framework.Servers.HttpServer;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using log4net;
+using Nini.Config;
+using Mono.Addins;
+
+using Caps = OpenSim.Framework.Capabilities.Caps;
+
+
+namespace OpenSim.Region.CoreModules.World.LightShare
+{
+    [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EnvironmentModule")]
+
+    public class EnvironmentModule : INonSharedRegionModule, IEnvironmentModule
+    {
+        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+        private Scene m_scene = null;
+        private UUID regionID = UUID.Zero;
+        private static bool Enabled = false;
+        
+        private static readonly string capsName = "EnvironmentSettings";
+        private static readonly string capsBase = "/CAPS/0020/";
+        
+        private LLSDEnvironmentSetResponse setResponse = null;
+
+        #region INonSharedRegionModule
+        public void Initialise(IConfigSource source)
+        {
+            IConfig config = source.Configs["ClientStack.LindenCaps"];
+
+            if (null == config)
+                return;
+
+            if (config.GetString("Cap_EnvironmentSettings", String.Empty) != "localhost")
+            {
+                m_log.InfoFormat("[{0}]: Module is disabled.", Name);
+                return;
+            }
+
+            Enabled = true;
+            
+            m_log.InfoFormat("[{0}]: Module is enabled.", Name);
+        }
+
+        public void Close()
+        {
+        }
+
+        public string Name
+        {
+            get { return "EnvironmentModule"; }
+        }
+
+        public Type ReplaceableInterface
+        {
+            get { return null; }
+        }
+
+        public void AddRegion(Scene scene)
+        {
+            if (!Enabled)
+                return;
+
+            scene.RegisterModuleInterface<IEnvironmentModule>(this);
+            m_scene = scene;
+            regionID = scene.RegionInfo.RegionID;
+        }
+
+        public void RegionLoaded(Scene scene)
+        {
+            if (!Enabled)
+                return;
+
+            setResponse = new LLSDEnvironmentSetResponse();
+            scene.EventManager.OnRegisterCaps += OnRegisterCaps;
+        }
+
+        public void RemoveRegion(Scene scene)
+        {
+            if (Enabled)
+                return;
+
+            scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
+            m_scene = null;
+        }
+        #endregion
+
+        #region IEnvironmentModule
+        public void ResetEnvironmentSettings(UUID regionUUID)
+        {
+            if (!Enabled)
+                return;
+
+            m_scene.SimulationDataService.RemoveRegionEnvironmentSettings(regionUUID);
+        }
+        #endregion
+
+        #region Events
+        private void OnRegisterCaps(UUID agentID, Caps caps)
+        {
+//            m_log.DebugFormat("[{0}]: Register capability for agentID {1} in region {2}",
+//                Name, agentID, caps.RegionName);
+
+            string capsPath = capsBase + UUID.Random();
+
+            // Get handler
+            caps.RegisterHandler(
+                capsName,
+                new RestStreamHandler(
+                    "GET",
+                    capsPath,
+                    (request, path, param, httpRequest, httpResponse)
+                     => GetEnvironmentSettings(request, path, param, agentID, caps),
+                     capsName,
+                     agentID.ToString()));
+
+            // Set handler
+            caps.HttpListener.AddStreamHandler(
+                new RestStreamHandler(
+                "POST",
+                capsPath,
+                (request, path, param, httpRequest, httpResponse)
+                 => SetEnvironmentSettings(request, path, param, agentID, caps),
+                 capsName,
+                 agentID.ToString()));
+        }
+        #endregion
+
+        private string GetEnvironmentSettings(string request, string path, string param,
+              UUID agentID, Caps caps)
+        {
+//            m_log.DebugFormat("[{0}]: Environment GET handle for agentID {1} in region {2}",
+//                Name, agentID, caps.RegionName);
+
+            string env = String.Empty;
+
+            try
+            {
+                env = m_scene.SimulationDataService.LoadRegionEnvironmentSettings(regionID);
+            }
+            catch (Exception e)
+            {
+                m_log.ErrorFormat("[{0}]: Unable to load environment settings for region {1}, Exception: {2} - {3}",
+                    Name, caps.RegionName, e.Message, e.StackTrace);
+            }
+
+            if (String.IsNullOrEmpty(env))
+                env = EnvironmentSettings.EmptySettings(UUID.Zero, regionID);
+
+            return env;
+        }
+
+        private string SetEnvironmentSettings(string request, string path, string param,
+                              UUID agentID, Caps caps)
+        {
+
+//            m_log.DebugFormat("[{0}]: Environment SET handle from agentID {1} in region {2}",
+//                Name, agentID, caps.RegionName);
+
+            setResponse.regionID = regionID;
+            setResponse.success = false;
+
+            if (!m_scene.Permissions.CanIssueEstateCommand(agentID, false))
+            {
+                setResponse.fail_reason = "Insufficient estate permissions, settings has not been saved.";
+                return LLSDHelpers.SerialiseLLSDReply(setResponse);
+            }
+
+            try
+            {
+                m_scene.SimulationDataService.StoreRegionEnvironmentSettings(regionID, request);
+                setResponse.success = true;
+                
+                m_log.InfoFormat("[{0}]: New Environment settings has been saved from agentID {1} in region {2}",
+                    Name, agentID, caps.RegionName);
+            }
+            catch (Exception e)
+            {
+                m_log.ErrorFormat("[{0}]: Environment settings has not been saved for region {1}, Exception: {2} - {3}",
+                    Name, caps.RegionName, e.Message, e.StackTrace);
+
+                setResponse.success = false;
+                setResponse.fail_reason = String.Format("Environment Set for region {0} has failed, settings has not been saved.", caps.RegionName);
+            }
+
+            return LLSDHelpers.SerialiseLLSDReply(setResponse);
+        }
+    }
+}
+
diff --git a/OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs b/OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs
new file mode 100644
index 0000000..7a7b782
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IEnvironmentModule.cs
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using OpenMetaverse;
+
+namespace OpenSim.Region.Framework.Interfaces
+{
+    public interface IEnvironmentModule
+    {
+        void ResetEnvironmentSettings(UUID regionUUID);
+    }
+}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 5295a72..0fcafcc 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -95,5 +95,26 @@ namespace OpenSim.Region.Framework.Interfaces
         RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID);
         void StoreRegionWindlightSettings(RegionLightShareData wl);
         void RemoveRegionWindlightSettings(UUID regionID);
+
+        /// <summary>
+        /// Load Environment settings from region storage
+        /// </summary>
+        /// <param name="regionUUID">the region UUID</param>
+        /// <returns>LLSD string for viewer</returns>
+        string LoadRegionEnvironmentSettings(UUID regionUUID);
+
+        /// <summary>
+        /// Store Environment settings into region storage
+        /// </summary>
+        /// <param name="regionUUID">the region UUID</param>
+        /// <param name="settings">LLSD string from viewer</param>
+        void StoreRegionEnvironmentSettings(UUID regionUUID, string settings);
+
+        /// <summary>
+        /// Delete Environment settings from region storage
+        /// </summary>
+        /// <param name="regionUUID">the region UUID</param>
+        void RemoveRegionEnvironmentSettings(UUID regionUUID);
+
     }
 }
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 615f377..e424976 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -107,6 +107,26 @@ namespace OpenSim.Region.Framework.Interfaces
         void StoreRegionWindlightSettings(RegionLightShareData wl);
         void RemoveRegionWindlightSettings(UUID regionID);
 
+        /// <summary>
+        /// Load Environment settings from region storage
+        /// </summary>
+        /// <param name="regionUUID">the region UUID</param>
+        /// <returns>LLSD string for viewer</returns>
+        string LoadRegionEnvironmentSettings(UUID regionUUID);
+
+        /// <summary>
+        /// Store Environment settings into region storage
+        /// </summary>
+        /// <param name="regionUUID">the region UUID</param>
+        /// <param name="settings">LLSD string from viewer</param>
+        void StoreRegionEnvironmentSettings(UUID regionUUID, string settings);
+
+        /// <summary>
+        /// Delete Environment settings from region storage
+        /// </summary>
+        /// <param name="regionUUID">the region UUID</param>
+        void RemoveRegionEnvironmentSettings(UUID regionUUID);
+
         void Shutdown();
     }
 }
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
index ccef50b..c9cbbfa 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
@@ -148,5 +148,21 @@ namespace OpenSim.Services.Connectors
         {
             m_database.RemoveRegionWindlightSettings(regionID);
         }
+
+        public string LoadRegionEnvironmentSettings(UUID regionUUID)
+        {
+            return m_database.LoadRegionEnvironmentSettings(regionUUID);
+        }
+
+        public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
+        {
+            m_database.StoreRegionEnvironmentSettings(regionUUID, settings);
+        }
+
+        public void RemoveRegionEnvironmentSettings(UUID regionUUID)
+        {
+            m_database.RemoveRegionEnvironmentSettings(regionUUID);
+        }
+
     }
 }
diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
index 579d41c..1845eb9 100644
--- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
@@ -112,6 +112,21 @@ namespace OpenSim.Data.Null
         {
             m_store.StoreRegionWindlightSettings(wl);
         }
+
+        public string LoadRegionEnvironmentSettings(UUID regionUUID)
+        {
+            return m_store.LoadRegionEnvironmentSettings(regionUUID);
+        }
+
+        public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
+        {
+            m_store.StoreRegionEnvironmentSettings(regionUUID, settings);
+        }
+
+        public void RemoveRegionEnvironmentSettings(UUID regionUUID)
+        {
+            m_store.RemoveRegionEnvironmentSettings(regionUUID);
+        }
     }
 
     /// <summary>
@@ -158,7 +173,25 @@ namespace OpenSim.Data.Null
         {
             //This connector doesn't support the windlight module yet
         }
-        
+
+        #region Environment Settings
+        public string LoadRegionEnvironmentSettings(UUID regionUUID)
+        {
+            //This connector doesn't support the Environment module yet
+            return string.Empty;
+        }
+
+        public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
+        {
+            //This connector doesn't support the Environment module yet
+        }
+
+        public void RemoveRegionEnvironmentSettings(UUID regionUUID)
+        {
+            //This connector doesn't support the Environment module yet
+        }
+        #endregion
+
         public RegionSettings LoadRegionSettings(UUID regionUUID)
         {
             RegionSettings rs = null;
-- 
cgit v1.1