aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie2013-11-03 21:34:36 +0000
committerMelanie2013-11-03 21:34:36 +0000
commitba203ed94fb9fb27e4da2663dad6cac21d5892e3 (patch)
treec03981fa7b9070af3cec331234b78762c49a8a06 /OpenSim
parentMerge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into ... (diff)
parentAdd current .NET windows framework requirement to README. (diff)
downloadopensim-SC-ba203ed94fb9fb27e4da2663dad6cac21d5892e3.zip
opensim-SC-ba203ed94fb9fb27e4da2663dad6cac21d5892e3.tar.gz
opensim-SC-ba203ed94fb9fb27e4da2663dad6cac21d5892e3.tar.bz2
opensim-SC-ba203ed94fb9fb27e4da2663dad6cac21d5892e3.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
Diffstat (limited to '')
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAssetData.cs296
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs254
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAvatarData.cs72
-rw-r--r--OpenSim/Data/PGSQL/PGSQLEstateData.cs602
-rw-r--r--OpenSim/Data/PGSQL/PGSQLFramework.cs111
-rw-r--r--OpenSim/Data/PGSQL/PGSQLFriendsData.cs116
-rw-r--r--OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs519
-rw-r--r--OpenSim/Data/PGSQL/PGSQLGridUserData.cs68
-rw-r--r--OpenSim/Data/PGSQL/PGSQLGroupsData.cs481
-rw-r--r--OpenSim/Data/PGSQL/PGSQLHGTravelData.cs80
-rw-r--r--OpenSim/Data/PGSQL/PGSQLInventoryData.cs831
-rw-r--r--OpenSim/Data/PGSQL/PGSQLManager.cs350
-rw-r--r--OpenSim/Data/PGSQL/PGSQLMigration.cs102
-rw-r--r--OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs56
-rw-r--r--OpenSim/Data/PGSQL/PGSQLPresenceData.cs115
-rw-r--r--OpenSim/Data/PGSQL/PGSQLRegionData.cs392
-rw-r--r--OpenSim/Data/PGSQL/PGSQLSimulationData.cs2252
-rw-r--r--OpenSim/Data/PGSQL/PGSQLUserAccountData.cs330
-rw-r--r--OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs1075
-rw-r--r--OpenSim/Data/PGSQL/PGSQLXAssetData.cs535
-rw-r--r--OpenSim/Data/PGSQL/PGSQLXInventoryData.cs330
-rw-r--r--OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs65
-rw-r--r--OpenSim/Data/PGSQL/Resources/AssetStore.migrations94
-rw-r--r--OpenSim/Data/PGSQL/Resources/AuthStore.migrations32
-rw-r--r--OpenSim/Data/PGSQL/Resources/Avatar.migrations59
-rw-r--r--OpenSim/Data/PGSQL/Resources/EstateStore.migrations307
-rw-r--r--OpenSim/Data/PGSQL/Resources/FriendsStore.migrations44
-rw-r--r--OpenSim/Data/PGSQL/Resources/GridStore.migrations242
-rw-r--r--OpenSim/Data/PGSQL/Resources/GridUserStore.migrations60
-rw-r--r--OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations17
-rw-r--r--OpenSim/Data/PGSQL/Resources/IM_Store.migrations26
-rw-r--r--OpenSim/Data/PGSQL/Resources/InventoryStore.migrations220
-rw-r--r--OpenSim/Data/PGSQL/Resources/LogStore.migrations16
-rw-r--r--OpenSim/Data/PGSQL/Resources/Presence.migrations30
-rw-r--r--OpenSim/Data/PGSQL/Resources/RegionStore.migrations1154
-rw-r--r--OpenSim/Data/PGSQL/Resources/UserAccount.migrations51
-rw-r--r--OpenSim/Data/PGSQL/Resources/UserProfiles.migrations83
-rw-r--r--OpenSim/Data/PGSQL/Resources/UserStore.migrations404
-rw-r--r--OpenSim/Data/PGSQL/Resources/XAssetStore.migrations27
-rw-r--r--OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations94
-rw-r--r--OpenSim/Framework/BasicDOSProtector.cs275
-rw-r--r--OpenSim/Framework/CircularBuffer.cs312
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs107
-rw-r--r--OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs119
-rw-r--r--OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs91
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs9
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs12
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs74
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs47
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs21
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs135
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs107
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs172
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs49
-rw-r--r--OpenSim/Server/Handlers/Login/LLLoginHandlers.cs11
-rw-r--r--OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs15
63 files changed, 13356 insertions, 252 deletions
diff --git a/OpenSim/Data/PGSQL/PGSQLAssetData.cs b/OpenSim/Data/PGSQL/PGSQLAssetData.cs
new file mode 100644
index 0000000..7c5c01d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLAssetData.cs
@@ -0,0 +1,296 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Data;
30using System.Reflection;
31using System.Collections.Generic;
32using OpenMetaverse;
33using log4net;
34using OpenSim.Framework;
35using Npgsql;
36using NpgsqlTypes;
37
38namespace OpenSim.Data.PGSQL
39{
40 /// <summary>
41 /// A PGSQL Interface for the Asset server
42 /// </summary>
43 public class PGSQLAssetData : AssetDataBase
44 {
45 private const string _migrationStore = "AssetStore";
46
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private long m_ticksToEpoch;
49 /// <summary>
50 /// Database manager
51 /// </summary>
52 private PGSQLManager m_database;
53 private string m_connectionString;
54
55 protected virtual Assembly Assembly
56 {
57 get { return GetType().Assembly; }
58 }
59
60 #region IPlugin Members
61
62 override public void Dispose() { }
63
64 /// <summary>
65 /// <para>Initialises asset interface</para>
66 /// </summary>
67 // [Obsolete("Cannot be default-initialized!")]
68 override public void Initialise()
69 {
70 m_log.Info("[PGSQLAssetData]: " + Name + " cannot be default-initialized!");
71 throw new PluginNotInitialisedException(Name);
72 }
73
74 /// <summary>
75 /// Initialises asset interface
76 /// </summary>
77 /// <para>
78 /// a string instead of file, if someone writes the support
79 /// </para>
80 /// <param name="connectionString">connect string</param>
81 override public void Initialise(string connectionString)
82 {
83 m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks;
84
85 m_database = new PGSQLManager(connectionString);
86 m_connectionString = connectionString;
87
88 //New migration to check for DB changes
89 m_database.CheckMigration(_migrationStore);
90 }
91
92 /// <summary>
93 /// Database provider version.
94 /// </summary>
95 override public string Version
96 {
97 get { return m_database.getVersion(); }
98 }
99
100 /// <summary>
101 /// The name of this DB provider.
102 /// </summary>
103 override public string Name
104 {
105 get { return "PGSQL Asset storage engine"; }
106 }
107
108 #endregion
109
110 #region IAssetDataPlugin Members
111
112 /// <summary>
113 /// Fetch Asset from m_database
114 /// </summary>
115 /// <param name="assetID">the asset UUID</param>
116 /// <returns></returns>
117 override public AssetBase GetAsset(UUID assetID)
118 {
119 string sql = "SELECT * FROM assets WHERE id = :id";
120 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
121 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
122 {
123 cmd.Parameters.Add(m_database.CreateParameter("id", assetID));
124 conn.Open();
125 using (NpgsqlDataReader reader = cmd.ExecuteReader())
126 {
127 if (reader.Read())
128 {
129 AssetBase asset = new AssetBase(
130 DBGuid.FromDB(reader["id"]),
131 (string)reader["name"],
132 Convert.ToSByte(reader["assetType"]),
133 reader["creatorid"].ToString()
134 );
135 // Region Main
136 asset.Description = (string)reader["description"];
137 asset.Local = Convert.ToBoolean(reader["local"]);
138 asset.Temporary = Convert.ToBoolean(reader["temporary"]);
139 asset.Flags = (AssetFlags)(Convert.ToInt32(reader["asset_flags"]));
140 asset.Data = (byte[])reader["data"];
141 return asset;
142 }
143 return null; // throw new Exception("No rows to return");
144 }
145 }
146 }
147
148 /// <summary>
149 /// Create asset in m_database
150 /// </summary>
151 /// <param name="asset">the asset</param>
152 override public bool StoreAsset(AssetBase asset)
153 {
154
155 string sql =
156 @"UPDATE assets set name = :name, description = :description, " + "\"assetType\" " + @" = :assetType,
157 local = :local, temporary = :temporary, creatorid = :creatorid, data = :data
158 WHERE id=:id;
159
160 INSERT INTO assets
161 (id, name, description, " + "\"assetType\" " + @", local,
162 temporary, create_time, access_time, creatorid, asset_flags, data)
163 Select :id, :name, :description, :assetType, :local,
164 :temporary, :create_time, :access_time, :creatorid, :asset_flags, :data
165 Where not EXISTS(SELECT * FROM assets WHERE id=:id)
166 ";
167
168 string assetName = asset.Name;
169 if (asset.Name.Length > 64)
170 {
171 assetName = asset.Name.Substring(0, 64);
172 m_log.WarnFormat(
173 "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
174 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
175 }
176
177 string assetDescription = asset.Description;
178 if (asset.Description.Length > 64)
179 {
180 assetDescription = asset.Description.Substring(0, 64);
181 m_log.WarnFormat(
182 "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
183 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
184 }
185
186 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
187 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
188 {
189 int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
190 command.Parameters.Add(m_database.CreateParameter("id", asset.FullID));
191 command.Parameters.Add(m_database.CreateParameter("name", assetName));
192 command.Parameters.Add(m_database.CreateParameter("description", assetDescription));
193 command.Parameters.Add(m_database.CreateParameter("assetType", asset.Type));
194 command.Parameters.Add(m_database.CreateParameter("local", asset.Local));
195 command.Parameters.Add(m_database.CreateParameter("temporary", asset.Temporary));
196 command.Parameters.Add(m_database.CreateParameter("access_time", now));
197 command.Parameters.Add(m_database.CreateParameter("create_time", now));
198 command.Parameters.Add(m_database.CreateParameter("asset_flags", (int)asset.Flags));
199 command.Parameters.Add(m_database.CreateParameter("creatorid", asset.Metadata.CreatorID));
200 command.Parameters.Add(m_database.CreateParameter("data", asset.Data));
201 conn.Open();
202 try
203 {
204 command.ExecuteNonQuery();
205 }
206 catch(Exception e)
207 {
208 m_log.Error("[ASSET DB]: Error storing item :" + e.Message + " sql "+sql);
209 }
210 }
211 return true;
212 }
213
214
215// Commented out since currently unused - this probably should be called in GetAsset()
216// private void UpdateAccessTime(AssetBase asset)
217// {
218// using (AutoClosingSqlCommand cmd = m_database.Query("UPDATE assets SET access_time = :access_time WHERE id=:id"))
219// {
220// int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
221// cmd.Parameters.AddWithValue(":id", asset.FullID.ToString());
222// cmd.Parameters.AddWithValue(":access_time", now);
223// try
224// {
225// cmd.ExecuteNonQuery();
226// }
227// catch (Exception e)
228// {
229// m_log.Error(e.ToString());
230// }
231// }
232// }
233
234 /// <summary>
235 /// Check if asset exist in m_database
236 /// </summary>
237 /// <param name="uuid"></param>
238 /// <returns>true if exist.</returns>
239 override public bool ExistsAsset(UUID uuid)
240 {
241 if (GetAsset(uuid) != null)
242 {
243 return true;
244 }
245 return false;
246 }
247
248 /// <summary>
249 /// Returns a list of AssetMetadata objects. The list is a subset of
250 /// the entire data set offset by <paramref name="start" /> containing
251 /// <paramref name="count" /> elements.
252 /// </summary>
253 /// <param name="start">The number of results to discard from the total data set.</param>
254 /// <param name="count">The number of rows the returned list should contain.</param>
255 /// <returns>A list of AssetMetadata objects.</returns>
256 public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
257 {
258 List<AssetMetadata> retList = new List<AssetMetadata>(count);
259 string sql = @" SELECT id, name, description, " + "\"assetType\"" + @", temporary, creatorid
260 FROM assets
261 order by id
262 limit :stop
263 offset :start;";
264
265 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
266 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
267 {
268 cmd.Parameters.Add(m_database.CreateParameter("start", start));
269 cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1));
270 conn.Open();
271 using (NpgsqlDataReader reader = cmd.ExecuteReader())
272 {
273 while (reader.Read())
274 {
275 AssetMetadata metadata = new AssetMetadata();
276 metadata.FullID = DBGuid.FromDB(reader["id"]);
277 metadata.Name = (string)reader["name"];
278 metadata.Description = (string)reader["description"];
279 metadata.Type = Convert.ToSByte(reader["assetType"]);
280 metadata.Temporary = Convert.ToBoolean(reader["temporary"]);
281 metadata.CreatorID = (string)reader["creatorid"];
282 retList.Add(metadata);
283 }
284 }
285 }
286
287 return retList;
288 }
289
290 public override bool Delete(string id)
291 {
292 return false;
293 }
294 #endregion
295 }
296}
diff --git a/OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs b/OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs
new file mode 100644
index 0000000..d174112
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs
@@ -0,0 +1,254 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using OpenMetaverse;
32using OpenSim.Framework;
33using System.Reflection;
34using System.Text;
35using System.Data;
36using Npgsql;
37using NpgsqlTypes;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLAuthenticationData : IAuthenticationData
42 {
43 private string m_Realm;
44 private List<string> m_ColumnNames = null;
45 private int m_LastExpire = 0;
46 private string m_ConnectionString;
47 private PGSQLManager m_database;
48
49 protected virtual Assembly Assembly
50 {
51 get { return GetType().Assembly; }
52 }
53
54 public PGSQLAuthenticationData(string connectionString, string realm)
55 {
56 m_Realm = realm;
57 m_ConnectionString = connectionString;
58 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
59 {
60 conn.Open();
61 Migration m = new Migration(conn, GetType().Assembly, "AuthStore");
62 m_database = new PGSQLManager(m_ConnectionString);
63 m.Update();
64 }
65 }
66
67 public AuthenticationData Get(UUID principalID)
68 {
69 AuthenticationData ret = new AuthenticationData();
70 ret.Data = new Dictionary<string, object>();
71
72 string sql = string.Format("select * from {0} where uuid = :principalID", m_Realm);
73
74 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
75 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
76 {
77 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
78 conn.Open();
79 using (NpgsqlDataReader result = cmd.ExecuteReader())
80 {
81 if (result.Read())
82 {
83 ret.PrincipalID = principalID;
84
85 if (m_ColumnNames == null)
86 {
87 m_ColumnNames = new List<string>();
88
89 DataTable schemaTable = result.GetSchemaTable();
90 foreach (DataRow row in schemaTable.Rows)
91 m_ColumnNames.Add(row["ColumnName"].ToString());
92 }
93
94 foreach (string s in m_ColumnNames)
95 {
96 if (s == "UUID"||s == "uuid")
97 continue;
98
99 ret.Data[s] = result[s].ToString();
100 }
101 return ret;
102 }
103 }
104 }
105 return null;
106 }
107
108 public bool Store(AuthenticationData data)
109 {
110 if (data.Data.ContainsKey("UUID"))
111 data.Data.Remove("UUID");
112 if (data.Data.ContainsKey("uuid"))
113 data.Data.Remove("uuid");
114
115 /*
116 Dictionary<string, object> oAuth = new Dictionary<string, object>();
117
118 foreach (KeyValuePair<string, object> oDado in data.Data)
119 {
120 if (oDado.Key != oDado.Key.ToLower())
121 {
122 oAuth.Add(oDado.Key.ToLower(), oDado.Value);
123 }
124 }
125 foreach (KeyValuePair<string, object> oDado in data.Data)
126 {
127 if (!oAuth.ContainsKey(oDado.Key.ToLower())) {
128 oAuth.Add(oDado.Key.ToLower(), oDado.Value);
129 }
130 }
131 */
132 string[] fields = new List<string>(data.Data.Keys).ToArray();
133 StringBuilder updateBuilder = new StringBuilder();
134
135 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
136 using (NpgsqlCommand cmd = new NpgsqlCommand())
137 {
138 updateBuilder.AppendFormat("update {0} set ", m_Realm);
139
140 bool first = true;
141 foreach (string field in fields)
142 {
143 if (!first)
144 updateBuilder.Append(", ");
145 updateBuilder.AppendFormat("\"{0}\" = :{0}",field);
146
147 first = false;
148
149 cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field]));
150 }
151
152 updateBuilder.Append(" where uuid = :principalID");
153
154 cmd.CommandText = updateBuilder.ToString();
155 cmd.Connection = conn;
156 cmd.Parameters.Add(m_database.CreateParameter("principalID", data.PrincipalID));
157
158 conn.Open();
159 if (cmd.ExecuteNonQuery() < 1)
160 {
161 StringBuilder insertBuilder = new StringBuilder();
162
163 insertBuilder.AppendFormat("insert into {0} (uuid, \"", m_Realm);
164 insertBuilder.Append(String.Join("\", \"", fields));
165 insertBuilder.Append("\") values (:principalID, :");
166 insertBuilder.Append(String.Join(", :", fields));
167 insertBuilder.Append(")");
168
169 cmd.CommandText = insertBuilder.ToString();
170
171 if (cmd.ExecuteNonQuery() < 1)
172 {
173 return false;
174 }
175 }
176 }
177 return true;
178 }
179
180 public bool SetDataItem(UUID principalID, string item, string value)
181 {
182 string sql = string.Format("update {0} set {1} = :{1} where uuid = :UUID", m_Realm, item);
183 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
184 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
185 {
186 cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
187 conn.Open();
188 if (cmd.ExecuteNonQuery() > 0)
189 return true;
190 }
191 return false;
192 }
193
194 public bool SetToken(UUID principalID, string token, int lifetime)
195 {
196 if (System.Environment.TickCount - m_LastExpire > 30000)
197 DoExpire();
198
199 string sql = "insert into tokens (uuid, token, validity) values (:principalID, :token, :lifetime)";
200 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
201 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
202 {
203 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
204 cmd.Parameters.Add(m_database.CreateParameter("token", token));
205 cmd.Parameters.Add(m_database.CreateParameter("lifetime", DateTime.Now.AddMinutes(lifetime)));
206 conn.Open();
207
208 if (cmd.ExecuteNonQuery() > 0)
209 {
210 return true;
211 }
212 }
213 return false;
214 }
215
216 public bool CheckToken(UUID principalID, string token, int lifetime)
217 {
218 if (System.Environment.TickCount - m_LastExpire > 30000)
219 DoExpire();
220
221 DateTime validDate = DateTime.Now.AddMinutes(lifetime);
222 string sql = "update tokens set validity = :validDate where uuid = :principalID and token = :token and validity > (CURRENT_DATE + CURRENT_TIME)";
223
224 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
225 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
226 {
227 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
228 cmd.Parameters.Add(m_database.CreateParameter("token", token));
229 cmd.Parameters.Add(m_database.CreateParameter("validDate", validDate));
230 conn.Open();
231
232 if (cmd.ExecuteNonQuery() > 0)
233 {
234 return true;
235 }
236 }
237 return false;
238 }
239
240 private void DoExpire()
241 {
242 DateTime currentDateTime = DateTime.Now;
243 string sql = "delete from tokens where validity < :currentDateTime";
244 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
245 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
246 {
247 conn.Open();
248 cmd.Parameters.Add(m_database.CreateParameter("currentDateTime", currentDateTime));
249 cmd.ExecuteNonQuery();
250 }
251 m_LastExpire = System.Environment.TickCount;
252 }
253 }
254}
diff --git a/OpenSim/Data/PGSQL/PGSQLAvatarData.cs b/OpenSim/Data/PGSQL/PGSQLAvatarData.cs
new file mode 100644
index 0000000..d9c4905
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLAvatarData.cs
@@ -0,0 +1,72 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using Npgsql;
36using NpgsqlTypes;
37
38
39namespace OpenSim.Data.PGSQL
40{
41 /// <summary>
42 /// A PGSQL Interface for Avatar Storage
43 /// </summary>
44 public class PGSQLAvatarData : PGSQLGenericTableHandler<AvatarBaseData>,
45 IAvatarData
46 {
47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 public PGSQLAvatarData(string connectionString, string realm) :
50 base(connectionString, realm, "Avatar")
51 {
52 }
53
54 public bool Delete(UUID principalID, string name)
55 {
56 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
57 using (NpgsqlCommand cmd = new NpgsqlCommand())
58 {
59
60 cmd.CommandText = String.Format("DELETE FROM {0} where \"PrincipalID\" = :PrincipalID and \"Name\" = :Name", m_Realm);
61 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID));
62 cmd.Parameters.Add(m_database.CreateParameter("Name", name));
63 cmd.Connection = conn;
64 conn.Open();
65 if (cmd.ExecuteNonQuery() > 0)
66 return true;
67
68 return false;
69 }
70 }
71 }
72}
diff --git a/OpenSim/Data/PGSQL/PGSQLEstateData.cs b/OpenSim/Data/PGSQL/PGSQLEstateData.cs
new file mode 100644
index 0000000..5ad0eaa
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLEstateData.cs
@@ -0,0 +1,602 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using System.Data;
36using Npgsql;
37using NpgsqlTypes;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLEstateStore : IEstateDataStore
42 {
43 private const string _migrationStore = "EstateStore";
44
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private PGSQLManager _Database;
48 private string m_connectionString;
49 private FieldInfo[] _Fields;
50 private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
51
52 #region Public methods
53
54 public PGSQLEstateStore()
55 {
56 }
57
58 public PGSQLEstateStore(string connectionString)
59 {
60 Initialise(connectionString);
61 }
62
63 protected virtual Assembly Assembly
64 {
65 get { return GetType().Assembly; }
66 }
67
68 /// <summary>
69 /// Initialises the estatedata class.
70 /// </summary>
71 /// <param name="connectionString">connectionString.</param>
72 public void Initialise(string connectionString)
73 {
74 if (!string.IsNullOrEmpty(connectionString))
75 {
76 m_connectionString = connectionString;
77 _Database = new PGSQLManager(connectionString);
78 }
79
80 //Migration settings
81 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
82 {
83 conn.Open();
84 Migration m = new Migration(conn, GetType().Assembly, "EstateStore");
85 m.Update();
86 }
87
88 //Interesting way to get parameters! Maybe implement that also with other types
89 Type t = typeof(EstateSettings);
90 _Fields = t.GetFields(BindingFlags.NonPublic |
91 BindingFlags.Instance |
92 BindingFlags.DeclaredOnly);
93
94 foreach (FieldInfo f in _Fields)
95 {
96 if (f.Name.Substring(0, 2) == "m_")
97 _FieldMap[f.Name.Substring(2)] = f;
98 }
99 }
100
101 /// <summary>
102 /// Loads the estate settings.
103 /// </summary>
104 /// <param name="regionID">region ID.</param>
105 /// <returns></returns>
106 public EstateSettings LoadEstateSettings(UUID regionID, bool create)
107 {
108 EstateSettings es = new EstateSettings();
109
110 string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) +
111 "\" from estate_map left join estate_settings on estate_map.\"EstateID\" = estate_settings.\"EstateID\" " +
112 " where estate_settings.\"EstateID\" is not null and \"RegionID\" = :RegionID";
113
114 bool insertEstate = false;
115 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
116 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
117 {
118 cmd.Parameters.Add(_Database.CreateParameter("RegionID", regionID));
119 conn.Open();
120 using (NpgsqlDataReader reader = cmd.ExecuteReader())
121 {
122 if (reader.Read())
123 {
124 foreach (string name in FieldList)
125 {
126 FieldInfo f = _FieldMap[name];
127 object v = reader[name];
128 if (f.FieldType == typeof(bool))
129 {
130 f.SetValue(es, v);
131 }
132 else if (f.FieldType == typeof(UUID))
133 {
134 UUID estUUID = UUID.Zero;
135
136 UUID.TryParse(v.ToString(), out estUUID);
137
138 f.SetValue(es, estUUID);
139 }
140 else if (f.FieldType == typeof(string))
141 {
142 f.SetValue(es, v.ToString());
143 }
144 else if (f.FieldType == typeof(UInt32))
145 {
146 f.SetValue(es, Convert.ToUInt32(v));
147 }
148 else if (f.FieldType == typeof(Single))
149 {
150 f.SetValue(es, Convert.ToSingle(v));
151 }
152 else
153 f.SetValue(es, v);
154 }
155 }
156 else
157 {
158 insertEstate = true;
159 }
160 }
161 }
162
163 if (insertEstate && create)
164 {
165 DoCreate(es);
166 LinkRegion(regionID, (int)es.EstateID);
167 }
168
169 LoadBanList(es);
170
171 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
172 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
173 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
174
175 //Set event
176 es.OnSave += StoreEstateSettings;
177 return es;
178 }
179
180 public EstateSettings CreateNewEstate()
181 {
182 EstateSettings es = new EstateSettings();
183 es.OnSave += StoreEstateSettings;
184
185 DoCreate(es);
186
187 LoadBanList(es);
188
189 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
190 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
191 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
192
193 return es;
194 }
195
196 private void DoCreate(EstateSettings es)
197 {
198 List<string> names = new List<string>(FieldList);
199
200 names.Remove("EstateID");
201
202 string sql = string.Format("insert into estate_settings (\"{0}\") values ( :{1} )", String.Join("\",\"", names.ToArray()), String.Join(", :", names.ToArray()));
203
204 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
205 using (NpgsqlCommand insertCommand = new NpgsqlCommand(sql, conn))
206 {
207 insertCommand.CommandText = sql;
208
209 foreach (string name in names)
210 {
211 insertCommand.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
212 }
213 //NpgsqlParameter idParameter = new NpgsqlParameter("ID", SqlDbType.Int);
214 //idParameter.Direction = ParameterDirection.Output;
215 //insertCommand.Parameters.Add(idParameter);
216 conn.Open();
217
218 es.EstateID = 100;
219
220 if (insertCommand.ExecuteNonQuery() > 0)
221 {
222 insertCommand.CommandText = "Select cast(lastval() as int) as ID ;";
223
224 using (NpgsqlDataReader result = insertCommand.ExecuteReader())
225 {
226 if (result.Read())
227 {
228 es.EstateID = (uint)result.GetInt32(0);
229 }
230 }
231 }
232
233 }
234
235 //TODO check if this is needed??
236 es.Save();
237 }
238
239 /// <summary>
240 /// Stores the estate settings.
241 /// </summary>
242 /// <param name="es">estate settings</param>
243 public void StoreEstateSettings(EstateSettings es)
244 {
245 List<string> names = new List<string>(FieldList);
246
247 names.Remove("EstateID");
248
249 string sql = string.Format("UPDATE estate_settings SET ");
250 foreach (string name in names)
251 {
252 sql += "\"" + name + "\" = :" + name + ", ";
253 }
254 sql = sql.Remove(sql.LastIndexOf(","));
255 sql += " WHERE \"EstateID\" = :EstateID";
256
257 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
258 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
259 {
260 foreach (string name in names)
261 {
262 cmd.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
263 }
264
265 cmd.Parameters.Add(_Database.CreateParameter("EstateID", es.EstateID));
266 conn.Open();
267 cmd.ExecuteNonQuery();
268 }
269
270 SaveBanList(es);
271 SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
272 SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
273 SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
274 }
275
276 #endregion
277
278 #region Private methods
279
280 private string[] FieldList
281 {
282 get { return new List<string>(_FieldMap.Keys).ToArray(); }
283 }
284
285 private void LoadBanList(EstateSettings es)
286 {
287 es.ClearBans();
288
289 string sql = "select \"bannedUUID\" from estateban where \"EstateID\" = :EstateID";
290
291 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
292 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
293 {
294 NpgsqlParameter idParameter = new NpgsqlParameter("EstateID", DbType.Int32);
295 idParameter.Value = es.EstateID;
296 cmd.Parameters.Add(idParameter);
297 conn.Open();
298 using (NpgsqlDataReader reader = cmd.ExecuteReader())
299 {
300 while (reader.Read())
301 {
302 EstateBan eb = new EstateBan();
303
304 eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid;
305 eb.BannedHostAddress = "0.0.0.0";
306 eb.BannedHostIPMask = "0.0.0.0";
307 es.AddBan(eb);
308 }
309 }
310 }
311 }
312
313 private UUID[] LoadUUIDList(uint estateID, string table)
314 {
315 List<UUID> uuids = new List<UUID>();
316
317 string sql = string.Format("select uuid from {0} where \"EstateID\" = :EstateID", table);
318
319 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
320 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
321 {
322 cmd.Parameters.Add(_Database.CreateParameter("EstateID", estateID));
323 conn.Open();
324 using (NpgsqlDataReader reader = cmd.ExecuteReader())
325 {
326 while (reader.Read())
327 {
328 uuids.Add(new UUID((Guid)reader["uuid"])); //uuid);
329 }
330 }
331 }
332
333 return uuids.ToArray();
334 }
335
336 private void SaveBanList(EstateSettings es)
337 {
338 //Delete first
339 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
340 {
341 conn.Open();
342 using (NpgsqlCommand cmd = conn.CreateCommand())
343 {
344 cmd.CommandText = "delete from estateban where \"EstateID\" = :EstateID";
345 cmd.Parameters.AddWithValue("EstateID", (int)es.EstateID);
346 cmd.ExecuteNonQuery();
347
348 //Insert after
349 cmd.CommandText = "insert into estateban (\"EstateID\", \"bannedUUID\",\"bannedIp\", \"bannedIpHostMask\", \"bannedNameMask\") values ( :EstateID, :bannedUUID, '','','' )";
350 cmd.Parameters.AddWithValue("bannedUUID", Guid.Empty);
351 foreach (EstateBan b in es.EstateBans)
352 {
353 cmd.Parameters["bannedUUID"].Value = b.BannedUserID.Guid;
354 cmd.ExecuteNonQuery();
355 }
356 }
357 }
358 }
359
360 private void SaveUUIDList(uint estateID, string table, UUID[] data)
361 {
362 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
363 {
364 conn.Open();
365 using (NpgsqlCommand cmd = conn.CreateCommand())
366 {
367 cmd.Parameters.AddWithValue("EstateID", (int)estateID);
368 cmd.CommandText = string.Format("delete from {0} where \"EstateID\" = :EstateID", table);
369 cmd.ExecuteNonQuery();
370
371 cmd.CommandText = string.Format("insert into {0} (\"EstateID\", uuid) values ( :EstateID, :uuid )", table);
372 cmd.Parameters.AddWithValue("uuid", Guid.Empty);
373 foreach (UUID uuid in data)
374 {
375 cmd.Parameters["uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works
376 cmd.ExecuteNonQuery();
377 }
378 }
379 }
380 }
381
382 public EstateSettings LoadEstateSettings(int estateID)
383 {
384 EstateSettings es = new EstateSettings();
385 string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) + "\" from estate_settings where \"EstateID\" = :EstateID";
386 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
387 {
388 conn.Open();
389 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
390 {
391 cmd.Parameters.AddWithValue("EstateID", (int)estateID);
392 using (NpgsqlDataReader reader = cmd.ExecuteReader())
393 {
394 if (reader.Read())
395 {
396 foreach (string name in FieldList)
397 {
398 FieldInfo f = _FieldMap[name];
399 object v = reader[name];
400 if (f.FieldType == typeof(bool))
401 {
402 f.SetValue(es, Convert.ToInt32(v) != 0);
403 }
404 else if (f.FieldType == typeof(UUID))
405 {
406 f.SetValue(es, new UUID((Guid)v)); // uuid);
407 }
408 else if (f.FieldType == typeof(string))
409 {
410 f.SetValue(es, v.ToString());
411 }
412 else if (f.FieldType == typeof(UInt32))
413 {
414 f.SetValue(es, Convert.ToUInt32(v));
415 }
416 else if (f.FieldType == typeof(Single))
417 {
418 f.SetValue(es, Convert.ToSingle(v));
419 }
420 else
421 f.SetValue(es, v);
422 }
423 }
424
425 }
426 }
427 }
428 LoadBanList(es);
429
430 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
431 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
432 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
433
434 //Set event
435 es.OnSave += StoreEstateSettings;
436 return es;
437
438 }
439
440 public List<EstateSettings> LoadEstateSettingsAll()
441 {
442 List<EstateSettings> allEstateSettings = new List<EstateSettings>();
443
444 List<int> allEstateIds = GetEstatesAll();
445
446 foreach (int estateId in allEstateIds)
447 allEstateSettings.Add(LoadEstateSettings(estateId));
448
449 return allEstateSettings;
450 }
451
452 public List<int> GetEstates(string search)
453 {
454 List<int> result = new List<int>();
455 string sql = "select \"EstateID\" from estate_settings where lower(\"EstateName\") = lower(:EstateName)";
456 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
457 {
458 conn.Open();
459 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
460 {
461 cmd.Parameters.AddWithValue("EstateName", search);
462
463 using (IDataReader reader = cmd.ExecuteReader())
464 {
465 while (reader.Read())
466 {
467 result.Add(Convert.ToInt32(reader["EstateID"]));
468 }
469 reader.Close();
470 }
471 }
472 }
473
474 return result;
475 }
476
477 public List<int> GetEstatesAll()
478 {
479 List<int> result = new List<int>();
480 string sql = "select \"EstateID\" from estate_settings";
481 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
482 {
483 conn.Open();
484 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
485 {
486 using (IDataReader reader = cmd.ExecuteReader())
487 {
488 while (reader.Read())
489 {
490 result.Add(Convert.ToInt32(reader["EstateID"]));
491 }
492 reader.Close();
493 }
494 }
495 }
496
497 return result;
498 }
499
500 public List<int> GetEstatesByOwner(UUID ownerID)
501 {
502 List<int> result = new List<int>();
503 string sql = "select \"estateID\" from estate_settings where \"EstateOwner\" = :EstateOwner";
504 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
505 {
506 conn.Open();
507 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
508 {
509 cmd.Parameters.AddWithValue("EstateOwner", ownerID);
510
511 using (IDataReader reader = cmd.ExecuteReader())
512 {
513 while (reader.Read())
514 {
515 result.Add(Convert.ToInt32(reader["EstateID"]));
516 }
517 reader.Close();
518 }
519 }
520 }
521
522 return result;
523 }
524
525 public bool LinkRegion(UUID regionID, int estateID)
526 {
527 string deleteSQL = "delete from estate_map where \"RegionID\" = :RegionID";
528 string insertSQL = "insert into estate_map values (:RegionID, :EstateID)";
529 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
530 {
531 conn.Open();
532
533 NpgsqlTransaction transaction = conn.BeginTransaction();
534
535 try
536 {
537 using (NpgsqlCommand cmd = new NpgsqlCommand(deleteSQL, conn))
538 {
539 cmd.Transaction = transaction;
540 cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
541
542 cmd.ExecuteNonQuery();
543 }
544
545 using (NpgsqlCommand cmd = new NpgsqlCommand(insertSQL, conn))
546 {
547 cmd.Transaction = transaction;
548 cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
549 cmd.Parameters.AddWithValue("EstateID", estateID);
550
551 int ret = cmd.ExecuteNonQuery();
552
553 if (ret != 0)
554 transaction.Commit();
555 else
556 transaction.Rollback();
557
558 return (ret != 0);
559 }
560 }
561 catch (Exception ex)
562 {
563 m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message);
564 transaction.Rollback();
565 }
566 }
567 return false;
568 }
569
570 public List<UUID> GetRegions(int estateID)
571 {
572 List<UUID> result = new List<UUID>();
573 string sql = "select \"RegionID\" from estate_map where \"EstateID\" = :EstateID";
574 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
575 {
576 conn.Open();
577 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
578 {
579 cmd.Parameters.AddWithValue("EstateID", estateID);
580
581 using (IDataReader reader = cmd.ExecuteReader())
582 {
583 while (reader.Read())
584 {
585 result.Add(DBGuid.FromDB(reader["RegionID"]));
586 }
587 reader.Close();
588 }
589 }
590 }
591
592 return result;
593 }
594
595 public bool DeleteEstate(int estateID)
596 {
597 // TODO: Implementation!
598 return false;
599 }
600 #endregion
601 }
602}
diff --git a/OpenSim/Data/PGSQL/PGSQLFramework.cs b/OpenSim/Data/PGSQL/PGSQLFramework.cs
new file mode 100644
index 0000000..1028e4e
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLFramework.cs
@@ -0,0 +1,111 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Data;
32using System.Reflection;
33using OpenMetaverse;
34using OpenSim.Framework;
35using Npgsql;
36
37namespace OpenSim.Data.PGSQL
38{
39 /// <summary>
40 /// A database interface class to a user profile storage system
41 /// </summary>
42 public class PGSqlFramework
43 {
44 private static readonly log4net.ILog m_log =
45 log4net.LogManager.GetLogger(
46 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected string m_connectionString;
49 protected object m_dbLock = new object();
50
51 protected PGSqlFramework(string connectionString)
52 {
53 m_connectionString = connectionString;
54 InitializeMonoSecurity();
55 }
56
57 public void InitializeMonoSecurity()
58 {
59 if (!Util.IsPlatformMono)
60 {
61
62 if (AppDomain.CurrentDomain.GetData("MonoSecurityPostgresAdded") == null)
63 {
64 AppDomain.CurrentDomain.SetData("MonoSecurityPostgresAdded", "true");
65
66 AppDomain currentDomain = AppDomain.CurrentDomain;
67 currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandlerMonoSec);
68 }
69 }
70 }
71
72 private System.Reflection.Assembly ResolveEventHandlerMonoSec(object sender, ResolveEventArgs args)
73 {
74 Assembly MyAssembly = null;
75
76 if (args.Name.Substring(0, args.Name.IndexOf(",")) == "Mono.Security")
77 {
78 MyAssembly = Assembly.LoadFrom("lib/NET/Mono.Security.dll");
79 }
80
81 //Return the loaded assembly.
82 return MyAssembly;
83 }
84 //////////////////////////////////////////////////////////////
85 //
86 // All non queries are funneled through one connection
87 // to increase performance a little
88 //
89 protected int ExecuteNonQuery(NpgsqlCommand cmd)
90 {
91 lock (m_dbLock)
92 {
93 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
94 {
95 dbcon.Open();
96 cmd.Connection = dbcon;
97
98 try
99 {
100 return cmd.ExecuteNonQuery();
101 }
102 catch (Exception e)
103 {
104 m_log.Error(e.Message, e);
105 return 0;
106 }
107 }
108 }
109 }
110 }
111}
diff --git a/OpenSim/Data/PGSQL/PGSQLFriendsData.cs b/OpenSim/Data/PGSQL/PGSQLFriendsData.cs
new file mode 100644
index 0000000..4c1ee02
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLFriendsData.cs
@@ -0,0 +1,116 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Data;
32using OpenMetaverse;
33using OpenSim.Framework;
34using System.Reflection;
35using System.Text;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 public class PGSQLFriendsData : PGSQLGenericTableHandler<FriendsData>, IFriendsData
41 {
42 public PGSQLFriendsData(string connectionString, string realm)
43 : base(connectionString, realm, "FriendsStore")
44 {
45 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
46 {
47 conn.Open();
48 Migration m = new Migration(conn, GetType().Assembly, "FriendsStore");
49 m.Update();
50 }
51 }
52
53
54 public bool Delete(string principalID, string friend)
55 {
56 UUID princUUID = UUID.Zero;
57
58 bool ret = UUID.TryParse(principalID, out princUUID);
59
60 if (ret)
61 return Delete(princUUID, friend);
62 else
63 return false;
64 }
65
66 public bool Delete(UUID principalID, string friend)
67 {
68 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
69 using (NpgsqlCommand cmd = new NpgsqlCommand())
70 {
71 cmd.CommandText = String.Format("delete from {0} where \"PrincipalID\" = :PrincipalID and \"Friend\" = :Friend", m_Realm);
72 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID.ToString()));
73 cmd.Parameters.Add(m_database.CreateParameter("Friend", friend));
74 cmd.Connection = conn;
75 conn.Open();
76 cmd.ExecuteNonQuery();
77
78 return true;
79 }
80 }
81
82 public FriendsData[] GetFriends(string principalID)
83 {
84 UUID princUUID = UUID.Zero;
85
86 bool ret = UUID.TryParse(principalID, out princUUID);
87
88 if (ret)
89 return GetFriends(princUUID);
90 else
91 return new FriendsData[0];
92 }
93
94 public FriendsData[] GetFriends(UUID principalID)
95 {
96 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
97 using (NpgsqlCommand cmd = new NpgsqlCommand())
98 {
99
100 cmd.CommandText = String.Format("select a.*,case when b.\"Flags\" is null then '-1' else b.\"Flags\" end as \"TheirFlags\" from {0} as a " +
101 " left join {0} as b on a.\"PrincipalID\" = b.\"Friend\" and a.\"Friend\" = b.\"PrincipalID\" " +
102 " where a.\"PrincipalID\" = :PrincipalID", m_Realm);
103 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID.ToString()));
104 cmd.Connection = conn;
105 conn.Open();
106 return DoQuery(cmd);
107 }
108 }
109
110 public FriendsData[] GetFriends(Guid principalID)
111 {
112 return GetFriends(principalID);
113 }
114
115 }
116}
diff --git a/OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs b/OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs
new file mode 100644
index 0000000..2151568
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs
@@ -0,0 +1,519 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using System.Text;
37using Npgsql;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLGenericTableHandler<T> : PGSqlFramework where T : class, new()
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 protected string m_ConnectionString;
47 protected PGSQLManager m_database; //used for parameter type translation
48 protected Dictionary<string, FieldInfo> m_Fields =
49 new Dictionary<string, FieldInfo>();
50
51 protected Dictionary<string, string> m_FieldTypes = new Dictionary<string, string>();
52
53 protected List<string> m_ColumnNames = null;
54 protected string m_Realm;
55 protected FieldInfo m_DataField = null;
56
57 protected virtual Assembly Assembly
58 {
59 get { return GetType().Assembly; }
60 }
61
62 public PGSQLGenericTableHandler(string connectionString,
63 string realm, string storeName)
64 : base(connectionString)
65 {
66 m_Realm = realm;
67
68 m_ConnectionString = connectionString;
69
70 if (storeName != String.Empty)
71 {
72 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
73 {
74 conn.Open();
75 Migration m = new Migration(conn, GetType().Assembly, storeName);
76 m.Update();
77 }
78
79 }
80 m_database = new PGSQLManager(m_ConnectionString);
81
82 Type t = typeof(T);
83 FieldInfo[] fields = t.GetFields(BindingFlags.Public |
84 BindingFlags.Instance |
85 BindingFlags.DeclaredOnly);
86
87 LoadFieldTypes();
88
89 if (fields.Length == 0)
90 return;
91
92 foreach (FieldInfo f in fields)
93 {
94 if (f.Name != "Data")
95 m_Fields[f.Name] = f;
96 else
97 m_DataField = f;
98 }
99
100 }
101
102 private void LoadFieldTypes()
103 {
104 m_FieldTypes = new Dictionary<string, string>();
105
106 string query = string.Format(@"select column_name,data_type
107 from INFORMATION_SCHEMA.COLUMNS
108 where table_name = lower('{0}');
109
110 ", m_Realm);
111 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
112 using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
113 {
114 conn.Open();
115 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
116 {
117 while (rdr.Read())
118 {
119 // query produces 0 to many rows of single column, so always add the first item in each row
120 m_FieldTypes.Add((string)rdr[0], (string)rdr[1]);
121 }
122 }
123 }
124 }
125
126 private void CheckColumnNames(NpgsqlDataReader reader)
127 {
128 if (m_ColumnNames != null)
129 return;
130
131 m_ColumnNames = new List<string>();
132
133 DataTable schemaTable = reader.GetSchemaTable();
134
135 foreach (DataRow row in schemaTable.Rows)
136 {
137 if (row["ColumnName"] != null &&
138 (!m_Fields.ContainsKey(row["ColumnName"].ToString())))
139 m_ColumnNames.Add(row["ColumnName"].ToString());
140
141 }
142 }
143
144 // TODO GET CONSTRAINTS FROM POSTGRESQL
145 private List<string> GetConstraints()
146 {
147 List<string> constraints = new List<string>();
148 string query = string.Format(@"SELECT kcu.column_name
149 FROM information_schema.table_constraints tc
150 LEFT JOIN information_schema.key_column_usage kcu
151 ON tc.constraint_catalog = kcu.constraint_catalog
152 AND tc.constraint_schema = kcu.constraint_schema
153 AND tc.constraint_name = kcu.constraint_name
154
155 LEFT JOIN information_schema.referential_constraints rc
156 ON tc.constraint_catalog = rc.constraint_catalog
157 AND tc.constraint_schema = rc.constraint_schema
158 AND tc.constraint_name = rc.constraint_name
159
160 LEFT JOIN information_schema.constraint_column_usage ccu
161 ON rc.unique_constraint_catalog = ccu.constraint_catalog
162 AND rc.unique_constraint_schema = ccu.constraint_schema
163 AND rc.unique_constraint_name = ccu.constraint_name
164
165 where tc.table_name = lower('{0}')
166 and lower(tc.constraint_type) in ('primary key')
167 and kcu.column_name is not null
168 ;", m_Realm);
169
170 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
171 using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
172 {
173 conn.Open();
174 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
175 {
176 while (rdr.Read())
177 {
178 // query produces 0 to many rows of single column, so always add the first item in each row
179 constraints.Add((string)rdr[0]);
180 }
181 }
182 return constraints;
183 }
184 }
185
186 public virtual T[] Get(string field, string key)
187 {
188 return Get(new string[] { field }, new string[] { key });
189 }
190
191 public virtual T[] Get(string[] fields, string[] keys)
192 {
193 if (fields.Length != keys.Length)
194 return new T[0];
195
196 List<string> terms = new List<string>();
197
198 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
199 using (NpgsqlCommand cmd = new NpgsqlCommand())
200 {
201
202 for (int i = 0; i < fields.Length; i++)
203 {
204 if ( m_FieldTypes.ContainsKey(fields[i]) )
205 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
206 else
207 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
208
209 terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
210 }
211
212 string where = String.Join(" AND ", terms.ToArray());
213
214 string query = String.Format("SELECT * FROM {0} WHERE {1}",
215 m_Realm, where);
216
217 cmd.Connection = conn;
218 cmd.CommandText = query;
219 conn.Open();
220 return DoQuery(cmd);
221 }
222 }
223
224 protected T[] DoQuery(NpgsqlCommand cmd)
225 {
226 List<T> result = new List<T>();
227 if (cmd.Connection == null)
228 {
229 cmd.Connection = new NpgsqlConnection(m_connectionString);
230 }
231 if (cmd.Connection.State == ConnectionState.Closed)
232 {
233 cmd.Connection.Open();
234 }
235 using (NpgsqlDataReader reader = cmd.ExecuteReader())
236 {
237 if (reader == null)
238 return new T[0];
239
240 CheckColumnNames(reader);
241
242 while (reader.Read())
243 {
244 T row = new T();
245
246 foreach (string name in m_Fields.Keys)
247 {
248 if (m_Fields[name].GetValue(row) is bool)
249 {
250 int v = Convert.ToInt32(reader[name]);
251 m_Fields[name].SetValue(row, v != 0 ? true : false);
252 }
253 else if (m_Fields[name].GetValue(row) is UUID)
254 {
255 UUID uuid = UUID.Zero;
256
257 UUID.TryParse(reader[name].ToString(), out uuid);
258 m_Fields[name].SetValue(row, uuid);
259 }
260 else if (m_Fields[name].GetValue(row) is int)
261 {
262 int v = Convert.ToInt32(reader[name]);
263 m_Fields[name].SetValue(row, v);
264 }
265 else
266 {
267 m_Fields[name].SetValue(row, reader[name]);
268 }
269 }
270
271 if (m_DataField != null)
272 {
273 Dictionary<string, string> data =
274 new Dictionary<string, string>();
275
276 foreach (string col in m_ColumnNames)
277 {
278 data[col] = reader[col].ToString();
279
280 if (data[col] == null)
281 data[col] = String.Empty;
282 }
283
284 m_DataField.SetValue(row, data);
285 }
286
287 result.Add(row);
288 }
289 return result.ToArray();
290 }
291 }
292
293 public virtual T[] Get(string where)
294 {
295 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
296 using (NpgsqlCommand cmd = new NpgsqlCommand())
297 {
298
299 string query = String.Format("SELECT * FROM {0} WHERE {1}",
300 m_Realm, where);
301 cmd.Connection = conn;
302 cmd.CommandText = query;
303
304 //m_log.WarnFormat("[PGSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
305
306 conn.Open();
307 return DoQuery(cmd);
308 }
309 }
310
311 public virtual bool Store(T row)
312 {
313 List<string> constraintFields = GetConstraints();
314 List<KeyValuePair<string, string>> constraints = new List<KeyValuePair<string, string>>();
315
316 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
317 using (NpgsqlCommand cmd = new NpgsqlCommand())
318 {
319
320 StringBuilder query = new StringBuilder();
321 List<String> names = new List<String>();
322 List<String> values = new List<String>();
323
324 foreach (FieldInfo fi in m_Fields.Values)
325 {
326 names.Add(fi.Name);
327 values.Add(":" + fi.Name);
328 // Temporarily return more information about what field is unexpectedly null for
329 // http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the
330 // InventoryTransferModule or we may be required to substitute a DBNull here.
331 if (fi.GetValue(row) == null)
332 throw new NullReferenceException(
333 string.Format(
334 "[PGSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",
335 fi.Name, row));
336
337 if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name))
338 {
339 constraints.Add(new KeyValuePair<string, string>(fi.Name, fi.GetValue(row).ToString() ));
340 }
341 if (m_FieldTypes.ContainsKey(fi.Name))
342 cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row), m_FieldTypes[fi.Name]));
343 else
344 cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row)));
345 }
346
347 if (m_DataField != null)
348 {
349 Dictionary<string, string> data =
350 (Dictionary<string, string>)m_DataField.GetValue(row);
351
352 foreach (KeyValuePair<string, string> kvp in data)
353 {
354 if (constraintFields.Count > 0 && constraintFields.Contains(kvp.Key))
355 {
356 constraints.Add(new KeyValuePair<string, string>(kvp.Key, kvp.Key));
357 }
358 names.Add(kvp.Key);
359 values.Add(":" + kvp.Key);
360
361 if (m_FieldTypes.ContainsKey(kvp.Key))
362 cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value, m_FieldTypes[kvp.Key]));
363 else
364 cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value));
365 }
366
367 }
368
369 query.AppendFormat("UPDATE {0} SET ", m_Realm);
370 int i = 0;
371 for (i = 0; i < names.Count - 1; i++)
372 {
373 query.AppendFormat("\"{0}\" = {1}, ", names[i], values[i]);
374 }
375 query.AppendFormat("\"{0}\" = {1} ", names[i], values[i]);
376 if (constraints.Count > 0)
377 {
378 List<string> terms = new List<string>();
379 for (int j = 0; j < constraints.Count; j++)
380 {
381 terms.Add(String.Format(" \"{0}\" = :{0}", constraints[j].Key));
382 }
383 string where = String.Join(" AND ", terms.ToArray());
384 query.AppendFormat(" WHERE {0} ", where);
385
386 }
387 cmd.Connection = conn;
388 cmd.CommandText = query.ToString();
389
390 conn.Open();
391 if (cmd.ExecuteNonQuery() > 0)
392 {
393 //m_log.WarnFormat("[PGSQLGenericTable]: Updating {0}", m_Realm);
394 return true;
395 }
396 else
397 {
398 // assume record has not yet been inserted
399
400 query = new StringBuilder();
401 query.AppendFormat("INSERT INTO {0} (\"", m_Realm);
402 query.Append(String.Join("\",\"", names.ToArray()));
403 query.Append("\") values (" + String.Join(",", values.ToArray()) + ")");
404 cmd.Connection = conn;
405 cmd.CommandText = query.ToString();
406
407 // m_log.WarnFormat("[PGSQLGenericTable]: Inserting into {0} sql {1}", m_Realm, cmd.CommandText);
408
409 if (conn.State != ConnectionState.Open)
410 conn.Open();
411 if (cmd.ExecuteNonQuery() > 0)
412 return true;
413 }
414
415 return false;
416 }
417 }
418
419 public virtual bool Delete(string field, string key)
420 {
421 return Delete(new string[] { field }, new string[] { key });
422 }
423
424 public virtual bool Delete(string[] fields, string[] keys)
425 {
426 if (fields.Length != keys.Length)
427 return false;
428
429 List<string> terms = new List<string>();
430
431 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
432 using (NpgsqlCommand cmd = new NpgsqlCommand())
433 {
434 for (int i = 0; i < fields.Length; i++)
435 {
436 if (m_FieldTypes.ContainsKey(fields[i]))
437 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
438 else
439 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
440
441 terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
442 }
443
444 string where = String.Join(" AND ", terms.ToArray());
445
446 string query = String.Format("DELETE FROM {0} WHERE {1}", m_Realm, where);
447
448 cmd.Connection = conn;
449 cmd.CommandText = query;
450 conn.Open();
451
452 if (cmd.ExecuteNonQuery() > 0)
453 {
454 //m_log.Warn("[PGSQLGenericTable]: " + deleteCommand);
455 return true;
456 }
457 return false;
458 }
459 }
460 public long GetCount(string field, string key)
461 {
462 return GetCount(new string[] { field }, new string[] { key });
463 }
464
465 public long GetCount(string[] fields, string[] keys)
466 {
467 if (fields.Length != keys.Length)
468 return 0;
469
470 List<string> terms = new List<string>();
471
472 using (NpgsqlCommand cmd = new NpgsqlCommand())
473 {
474 for (int i = 0; i < fields.Length; i++)
475 {
476 cmd.Parameters.AddWithValue(fields[i], keys[i]);
477 terms.Add("\"" + fields[i] + "\" = :" + fields[i]);
478 }
479
480 string where = String.Join(" and ", terms.ToArray());
481
482 string query = String.Format("select count(*) from {0} where {1}",
483 m_Realm, where);
484
485 cmd.CommandText = query;
486
487 Object result = DoQueryScalar(cmd);
488
489 return Convert.ToInt64(result);
490 }
491 }
492
493 public long GetCount(string where)
494 {
495 using (NpgsqlCommand cmd = new NpgsqlCommand())
496 {
497 string query = String.Format("select count(*) from {0} where {1}",
498 m_Realm, where);
499
500 cmd.CommandText = query;
501
502 object result = DoQueryScalar(cmd);
503
504 return Convert.ToInt64(result);
505 }
506 }
507
508 public object DoQueryScalar(NpgsqlCommand cmd)
509 {
510 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_ConnectionString))
511 {
512 dbcon.Open();
513 cmd.Connection = dbcon;
514
515 return cmd.ExecuteScalar();
516 }
517 }
518 }
519}
diff --git a/OpenSim/Data/PGSQL/PGSQLGridUserData.cs b/OpenSim/Data/PGSQL/PGSQLGridUserData.cs
new file mode 100644
index 0000000..89319f3
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLGridUserData.cs
@@ -0,0 +1,68 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36
37namespace OpenSim.Data.PGSQL
38{
39 /// <summary>
40 /// A PGSQL Interface for Avatar Storage
41 /// </summary>
42 public class PGSQLGridUserData : PGSQLGenericTableHandler<GridUserData>,
43 IGridUserData
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public PGSQLGridUserData(string connectionString, string realm) :
48 base(connectionString, realm, "GridUserStore")
49 {
50 }
51
52 public new GridUserData Get(string userID)
53 {
54 GridUserData[] ret = Get("UserID", userID);
55
56 if (ret.Length == 0)
57 return null;
58
59 return ret[0];
60 }
61
62 public GridUserData[] GetAll(string userID)
63 {
64 return base.Get(String.Format("\"UserID\" LIKE '{0}%'", userID));
65 }
66
67 }
68}
diff --git a/OpenSim/Data/PGSQL/PGSQLGroupsData.cs b/OpenSim/Data/PGSQL/PGSQLGroupsData.cs
new file mode 100644
index 0000000..ed75b63
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLGroupsData.cs
@@ -0,0 +1,481 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenSim.Framework;
33using OpenMetaverse;
34using Npgsql;
35
36namespace OpenSim.Data.PGSQL
37{
38 public class PGSQLGroupsData : IGroupsData
39 {
40 private PGSqlGroupsGroupsHandler m_Groups;
41 private PGSqlGroupsMembershipHandler m_Membership;
42 private PGSqlGroupsRolesHandler m_Roles;
43 private PGSqlGroupsRoleMembershipHandler m_RoleMembership;
44 private PGSqlGroupsInvitesHandler m_Invites;
45 private PGSqlGroupsNoticesHandler m_Notices;
46 private PGSqlGroupsPrincipalsHandler m_Principals;
47
48 public PGSQLGroupsData(string connectionString, string realm)
49 {
50 m_Groups = new PGSqlGroupsGroupsHandler(connectionString, realm + "_groups", realm + "_Store");
51 m_Membership = new PGSqlGroupsMembershipHandler(connectionString, realm + "_membership");
52 m_Roles = new PGSqlGroupsRolesHandler(connectionString, realm + "_roles");
53 m_RoleMembership = new PGSqlGroupsRoleMembershipHandler(connectionString, realm + "_rolemembership");
54 m_Invites = new PGSqlGroupsInvitesHandler(connectionString, realm + "_invites");
55 m_Notices = new PGSqlGroupsNoticesHandler(connectionString, realm + "_notices");
56 m_Principals = new PGSqlGroupsPrincipalsHandler(connectionString, realm + "_principals");
57 }
58
59 #region groups table
60 public bool StoreGroup(GroupData data)
61 {
62 return m_Groups.Store(data);
63 }
64
65 public GroupData RetrieveGroup(UUID groupID)
66 {
67 GroupData[] groups = m_Groups.Get("GroupID", groupID.ToString());
68 if (groups.Length > 0)
69 return groups[0];
70
71 return null;
72 }
73
74 public GroupData RetrieveGroup(string name)
75 {
76 GroupData[] groups = m_Groups.Get("Name", name);
77 if (groups.Length > 0)
78 return groups[0];
79
80 return null;
81 }
82
83 public GroupData[] RetrieveGroups(string pattern)
84 {
85 if (string.IsNullOrEmpty(pattern)) // True for where clause
86 pattern = " true ORDER BY lower(\"Name\") LIMIT 100";
87 else
88 pattern = string.Format(" lower(\"Name\") LIKE lower('%{0}%') ORDER BY lower(\"Name\") LIMIT 100", pattern);
89
90 return m_Groups.Get(pattern);
91 }
92
93 public bool DeleteGroup(UUID groupID)
94 {
95 return m_Groups.Delete("GroupID", groupID.ToString());
96 }
97
98 public int GroupsCount()
99 {
100 return (int)m_Groups.GetCount(" \"Location\" = \"\"");
101 }
102
103 #endregion
104
105 #region membership table
106 public MembershipData[] RetrieveMembers(UUID groupID)
107 {
108 return m_Membership.Get("GroupID", groupID.ToString());
109 }
110
111 public MembershipData RetrieveMember(UUID groupID, string pricipalID)
112 {
113 MembershipData[] m = m_Membership.Get(new string[] { "GroupID", "PrincipalID" },
114 new string[] { groupID.ToString(), pricipalID });
115 if (m != null && m.Length > 0)
116 return m[0];
117
118 return null;
119 }
120
121 public MembershipData[] RetrieveMemberships(string pricipalID)
122 {
123 return m_Membership.Get("PrincipalID", pricipalID.ToString());
124 }
125
126 public bool StoreMember(MembershipData data)
127 {
128 return m_Membership.Store(data);
129 }
130
131 public bool DeleteMember(UUID groupID, string pricipalID)
132 {
133 return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" },
134 new string[] { groupID.ToString(), pricipalID });
135 }
136
137 public int MemberCount(UUID groupID)
138 {
139 return (int)m_Membership.GetCount("GroupID", groupID.ToString());
140 }
141 #endregion
142
143 #region roles table
144 public bool StoreRole(RoleData data)
145 {
146 return m_Roles.Store(data);
147 }
148
149 public RoleData RetrieveRole(UUID groupID, UUID roleID)
150 {
151 RoleData[] data = m_Roles.Get(new string[] { "GroupID", "RoleID" },
152 new string[] { groupID.ToString(), roleID.ToString() });
153
154 if (data != null && data.Length > 0)
155 return data[0];
156
157 return null;
158 }
159
160 public RoleData[] RetrieveRoles(UUID groupID)
161 {
162 //return m_Roles.RetrieveRoles(groupID);
163 return m_Roles.Get("GroupID", groupID.ToString());
164 }
165
166 public bool DeleteRole(UUID groupID, UUID roleID)
167 {
168 return m_Roles.Delete(new string[] { "GroupID", "RoleID" },
169 new string[] { groupID.ToString(), roleID.ToString() });
170 }
171
172 public int RoleCount(UUID groupID)
173 {
174 return (int)m_Roles.GetCount("GroupID", groupID.ToString());
175 }
176
177
178 #endregion
179
180 #region rolememberhip table
181 public RoleMembershipData[] RetrieveRolesMembers(UUID groupID)
182 {
183 RoleMembershipData[] data = m_RoleMembership.Get("GroupID", groupID.ToString());
184
185 return data;
186 }
187
188 public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID)
189 {
190 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID" },
191 new string[] { groupID.ToString(), roleID.ToString() });
192
193 return data;
194 }
195
196 public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID)
197 {
198 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "PrincipalID" },
199 new string[] { groupID.ToString(), principalID.ToString() });
200
201 return data;
202 }
203
204 public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID)
205 {
206 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID", "PrincipalID" },
207 new string[] { groupID.ToString(), roleID.ToString(), principalID.ToString() });
208
209 if (data != null && data.Length > 0)
210 return data[0];
211
212 return null;
213 }
214
215 public int RoleMemberCount(UUID groupID, UUID roleID)
216 {
217 return (int)m_RoleMembership.GetCount(new string[] { "GroupID", "RoleID" },
218 new string[] { groupID.ToString(), roleID.ToString() });
219 }
220
221 public bool StoreRoleMember(RoleMembershipData data)
222 {
223 return m_RoleMembership.Store(data);
224 }
225
226 public bool DeleteRoleMember(RoleMembershipData data)
227 {
228 return m_RoleMembership.Delete(new string[] { "GroupID", "RoleID", "PrincipalID"},
229 new string[] { data.GroupID.ToString(), data.RoleID.ToString(), data.PrincipalID });
230 }
231
232 public bool DeleteMemberAllRoles(UUID groupID, string principalID)
233 {
234 return m_RoleMembership.Delete(new string[] { "GroupID", "PrincipalID" },
235 new string[] { groupID.ToString(), principalID });
236 }
237
238 #endregion
239
240 #region principals table
241 public bool StorePrincipal(PrincipalData data)
242 {
243 return m_Principals.Store(data);
244 }
245
246 public PrincipalData RetrievePrincipal(string principalID)
247 {
248 PrincipalData[] p = m_Principals.Get("PrincipalID", principalID);
249 if (p != null && p.Length > 0)
250 return p[0];
251
252 return null;
253 }
254
255 public bool DeletePrincipal(string principalID)
256 {
257 return m_Principals.Delete("PrincipalID", principalID);
258 }
259 #endregion
260
261 #region invites table
262
263 public bool StoreInvitation(InvitationData data)
264 {
265 return m_Invites.Store(data);
266 }
267
268 public InvitationData RetrieveInvitation(UUID inviteID)
269 {
270 InvitationData[] invites = m_Invites.Get("InviteID", inviteID.ToString());
271
272 if (invites != null && invites.Length > 0)
273 return invites[0];
274
275 return null;
276 }
277
278 public InvitationData RetrieveInvitation(UUID groupID, string principalID)
279 {
280 InvitationData[] invites = m_Invites.Get(new string[] { "GroupID", "PrincipalID" },
281 new string[] { groupID.ToString(), principalID });
282
283 if (invites != null && invites.Length > 0)
284 return invites[0];
285
286 return null;
287 }
288
289 public bool DeleteInvite(UUID inviteID)
290 {
291 return m_Invites.Delete("InviteID", inviteID.ToString());
292 }
293
294 public void DeleteOldInvites()
295 {
296 m_Invites.DeleteOld();
297 }
298
299 #endregion
300
301 #region notices table
302
303 public bool StoreNotice(NoticeData data)
304 {
305 return m_Notices.Store(data);
306 }
307
308 public NoticeData RetrieveNotice(UUID noticeID)
309 {
310 NoticeData[] notices = m_Notices.Get("NoticeID", noticeID.ToString());
311
312 if (notices != null && notices.Length > 0)
313 return notices[0];
314
315 return null;
316 }
317
318 public NoticeData[] RetrieveNotices(UUID groupID)
319 {
320 NoticeData[] notices = m_Notices.Get("GroupID", groupID.ToString());
321
322 return notices;
323 }
324
325 public bool DeleteNotice(UUID noticeID)
326 {
327 return m_Notices.Delete("NoticeID", noticeID.ToString());
328 }
329
330 public void DeleteOldNotices()
331 {
332 m_Notices.DeleteOld();
333 }
334
335 #endregion
336
337 #region combinations
338 public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID)
339 {
340 // TODO
341 return null;
342 }
343 public MembershipData[] RetrievePrincipalGroupMemberships(string principalID)
344 {
345 // TODO
346 return null;
347 }
348
349 #endregion
350 }
351
352 public class PGSqlGroupsGroupsHandler : PGSQLGenericTableHandler<GroupData>
353 {
354 protected override Assembly Assembly
355 {
356 // WARNING! Moving migrations to this assembly!!!
357 get { return GetType().Assembly; }
358 }
359
360 public PGSqlGroupsGroupsHandler(string connectionString, string realm, string store)
361 : base(connectionString, realm, store)
362 {
363 }
364
365 }
366
367 public class PGSqlGroupsMembershipHandler : PGSQLGenericTableHandler<MembershipData>
368 {
369 protected override Assembly Assembly
370 {
371 // WARNING! Moving migrations to this assembly!!!
372 get { return GetType().Assembly; }
373 }
374
375 public PGSqlGroupsMembershipHandler(string connectionString, string realm)
376 : base(connectionString, realm, string.Empty)
377 {
378 }
379
380 }
381
382 public class PGSqlGroupsRolesHandler : PGSQLGenericTableHandler<RoleData>
383 {
384 protected override Assembly Assembly
385 {
386 // WARNING! Moving migrations to this assembly!!!
387 get { return GetType().Assembly; }
388 }
389
390 public PGSqlGroupsRolesHandler(string connectionString, string realm)
391 : base(connectionString, realm, string.Empty)
392 {
393 }
394
395 }
396
397 public class PGSqlGroupsRoleMembershipHandler : PGSQLGenericTableHandler<RoleMembershipData>
398 {
399 protected override Assembly Assembly
400 {
401 // WARNING! Moving migrations to this assembly!!!
402 get { return GetType().Assembly; }
403 }
404
405 public PGSqlGroupsRoleMembershipHandler(string connectionString, string realm)
406 : base(connectionString, realm, string.Empty)
407 {
408 }
409
410 }
411
412 public class PGSqlGroupsInvitesHandler : PGSQLGenericTableHandler<InvitationData>
413 {
414 protected override Assembly Assembly
415 {
416 // WARNING! Moving migrations to this assembly!!!
417 get { return GetType().Assembly; }
418 }
419
420 public PGSqlGroupsInvitesHandler(string connectionString, string realm)
421 : base(connectionString, realm, string.Empty)
422 {
423 }
424
425 public void DeleteOld()
426 {
427 uint now = (uint)Util.UnixTimeSinceEpoch();
428
429 using (NpgsqlCommand cmd = new NpgsqlCommand())
430 {
431 cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < :tstamp", m_Realm);
432 cmd.Parameters.AddWithValue("tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
433
434 ExecuteNonQuery(cmd);
435 }
436
437 }
438 }
439
440 public class PGSqlGroupsNoticesHandler : PGSQLGenericTableHandler<NoticeData>
441 {
442 protected override Assembly Assembly
443 {
444 // WARNING! Moving migrations to this assembly!!!
445 get { return GetType().Assembly; }
446 }
447
448 public PGSqlGroupsNoticesHandler(string connectionString, string realm)
449 : base(connectionString, realm, string.Empty)
450 {
451 }
452
453 public void DeleteOld()
454 {
455 uint now = (uint)Util.UnixTimeSinceEpoch();
456
457 using (NpgsqlCommand cmd = new NpgsqlCommand())
458 {
459 cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < :tstamp", m_Realm);
460 cmd.Parameters.AddWithValue("tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
461
462 ExecuteNonQuery(cmd);
463 }
464
465 }
466 }
467
468 public class PGSqlGroupsPrincipalsHandler : PGSQLGenericTableHandler<PrincipalData>
469 {
470 protected override Assembly Assembly
471 {
472 // WARNING! Moving migrations to this assembly!!!
473 get { return GetType().Assembly; }
474 }
475
476 public PGSqlGroupsPrincipalsHandler(string connectionString, string realm)
477 : base(connectionString, realm, string.Empty)
478 {
479 }
480 }
481}
diff --git a/OpenSim/Data/PGSQL/PGSQLHGTravelData.cs b/OpenSim/Data/PGSQL/PGSQLHGTravelData.cs
new file mode 100644
index 0000000..c71b15f
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLHGTravelData.cs
@@ -0,0 +1,80 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 /// <summary>
41 /// A PGSQL Interface for user grid data
42 /// </summary>
43 public class PGSQLHGTravelData : PGSQLGenericTableHandler<HGTravelingData>, IHGTravelingData
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public PGSQLHGTravelData(string connectionString, string realm) : base(connectionString, realm, "HGTravelStore") { }
48
49 public HGTravelingData Get(UUID sessionID)
50 {
51 HGTravelingData[] ret = Get("SessionID", sessionID.ToString());
52
53 if (ret.Length == 0)
54 return null;
55
56 return ret[0];
57 }
58
59 public HGTravelingData[] GetSessions(UUID userID)
60 {
61 return base.Get("UserID", userID.ToString());
62 }
63
64 public bool Delete(UUID sessionID)
65 {
66 return Delete("SessionID", sessionID.ToString());
67 }
68
69 public void DeleteOld()
70 {
71 using (NpgsqlCommand cmd = new NpgsqlCommand())
72 {
73 cmd.CommandText = String.Format(@"delete from {0} where ""TMStamp"" < CURRENT_DATE - INTERVAL '2 day'", m_Realm);
74
75 ExecuteNonQuery(cmd);
76 }
77
78 }
79 }
80}
diff --git a/OpenSim/Data/PGSQL/PGSQLInventoryData.cs b/OpenSim/Data/PGSQL/PGSQLInventoryData.cs
new file mode 100644
index 0000000..c999433
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLInventoryData.cs
@@ -0,0 +1,831 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using Npgsql;
36
37namespace OpenSim.Data.PGSQL
38{
39 /// <summary>
40 /// A PGSQL interface for the inventory server
41 /// </summary>
42 public class PGSQLInventoryData : IInventoryDataPlugin
43 {
44 private const string _migrationStore = "InventoryStore";
45
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// The database manager
50 /// </summary>
51 private PGSQLManager database;
52 private string m_connectionString;
53
54 #region IPlugin members
55
56 [Obsolete("Cannot be default-initialized!")]
57 public void Initialise()
58 {
59 m_log.Info("[PGSQLInventoryData]: " + Name + " cannot be default-initialized!");
60 throw new PluginNotInitialisedException(Name);
61 }
62
63 /// <summary>
64 /// Loads and initialises the PGSQL inventory storage interface
65 /// </summary>
66 /// <param name="connectionString">connect string</param>
67 /// <remarks>use PGSQL_connection.ini</remarks>
68 public void Initialise(string connectionString)
69 {
70 m_connectionString = connectionString;
71 database = new PGSQLManager(connectionString);
72
73 //New migrations check of store
74 database.CheckMigration(_migrationStore);
75 }
76
77 /// <summary>
78 /// The name of this DB provider
79 /// </summary>
80 /// <returns>A string containing the name of the DB provider</returns>
81 public string Name
82 {
83 get { return "PGSQL Inventory Data Interface"; }
84 }
85
86 /// <summary>
87 /// Closes this DB provider
88 /// </summary>
89 public void Dispose()
90 {
91 database = null;
92 }
93
94 /// <summary>
95 /// Returns the version of this DB provider
96 /// </summary>
97 /// <returns>A string containing the DB provider</returns>
98 public string Version
99 {
100 get { return database.getVersion(); }
101 }
102
103 #endregion
104
105 #region Folder methods
106
107 /// <summary>
108 /// Returns a list of the root folders within a users inventory
109 /// </summary>
110 /// <param name="user">The user whos inventory is to be searched</param>
111 /// <returns>A list of folder objects</returns>
112 public List<InventoryFolderBase> getUserRootFolders(UUID user)
113 {
114 if (user == UUID.Zero)
115 return new List<InventoryFolderBase>();
116
117 return getInventoryFolders(UUID.Zero, user);
118 }
119
120 /// <summary>
121 /// see InventoryItemBase.getUserRootFolder
122 /// </summary>
123 /// <param name="user">the User UUID</param>
124 /// <returns></returns>
125 public InventoryFolderBase getUserRootFolder(UUID user)
126 {
127 List<InventoryFolderBase> items = getUserRootFolders(user);
128
129 InventoryFolderBase rootFolder = null;
130
131 // There should only ever be one root folder for a user. However, if there's more
132 // than one we'll simply use the first one rather than failing. It would be even
133 // nicer to print some message to this effect, but this feels like it's too low a
134 // to put such a message out, and it's too minor right now to spare the time to
135 // suitably refactor.
136 if (items.Count > 0)
137 {
138 rootFolder = items[0];
139 }
140
141 return rootFolder;
142 }
143
144 /// <summary>
145 /// Returns a list of folders in a users inventory contained within the specified folder
146 /// </summary>
147 /// <param name="parentID">The folder to search</param>
148 /// <returns>A list of inventory folders</returns>
149 public List<InventoryFolderBase> getInventoryFolders(UUID parentID)
150 {
151 return getInventoryFolders(parentID, UUID.Zero);
152 }
153
154 /// <summary>
155 /// Returns a specified inventory folder
156 /// </summary>
157 /// <param name="folderID">The folder to return</param>
158 /// <returns>A folder class</returns>
159 public InventoryFolderBase getInventoryFolder(UUID folderID)
160 {
161 string sql = "SELECT * FROM inventoryfolders WHERE \"folderID\" = :folderID";
162 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
163 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
164 {
165 cmd.Parameters.Add(database.CreateParameter("folderID", folderID));
166 conn.Open();
167 using (NpgsqlDataReader reader = cmd.ExecuteReader())
168 {
169 if (reader.Read())
170 {
171 return readInventoryFolder(reader);
172 }
173 }
174 }
175 m_log.InfoFormat("[INVENTORY DB] : Found no inventory folder with ID : {0}", folderID);
176 return null;
177 }
178
179 /// <summary>
180 /// Returns all child folders in the hierarchy from the parent folder and down.
181 /// Does not return the parent folder itself.
182 /// </summary>
183 /// <param name="parentID">The folder to get subfolders for</param>
184 /// <returns>A list of inventory folders</returns>
185 public List<InventoryFolderBase> getFolderHierarchy(UUID parentID)
186 {
187 //Note maybe change this to use a Dataset that loading in all folders of a user and then go throw it that way.
188 //Note this is changed so it opens only one connection to the database and not everytime it wants to get data.
189
190 /* NOTE: the implementation below is very inefficient (makes a separate request to get subfolders for
191 * every found folder, recursively). Inventory code for other DBs has been already rewritten to get ALL
192 * inventory for a specific user at once.
193 *
194 * Meanwhile, one little thing is corrected: getFolderHierarchy(UUID.Zero) doesn't make sense and should never
195 * be used, so check for that and return an empty list.
196 */
197
198 List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
199
200 if (parentID == UUID.Zero)
201 return folders;
202
203 string sql = "SELECT * FROM inventoryfolders WHERE \"parentFolderID\" = :parentID";
204 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
205 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
206 {
207 cmd.Parameters.Add(database.CreateParameter("parentID", parentID));
208 conn.Open();
209 folders.AddRange(getInventoryFolders(cmd));
210
211 List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
212
213 foreach (InventoryFolderBase folderBase in folders)
214 {
215 tempFolders.AddRange(getFolderHierarchy(folderBase.ID, cmd));
216 }
217 if (tempFolders.Count > 0)
218 {
219 folders.AddRange(tempFolders);
220 }
221 }
222 return folders;
223 }
224
225 /// <summary>
226 /// Creates a new inventory folder
227 /// </summary>
228 /// <param name="folder">Folder to create</param>
229 public void addInventoryFolder(InventoryFolderBase folder)
230 {
231 string sql = "INSERT INTO inventoryfolders (\"folderID\", \"agentID\", \"parentFolderID\", \"folderName\", type, version) " +
232 " VALUES (:folderID, :agentID, :parentFolderID, :folderName, :type, :version);";
233
234 string folderName = folder.Name;
235 if (folderName.Length > 64)
236 {
237 folderName = folderName.Substring(0, 64);
238 m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on add");
239 }
240 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
241 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
242 {
243 cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
244 cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
245 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
246 cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
247 cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
248 cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
249 conn.Open();
250 try
251 {
252 cmd.ExecuteNonQuery();
253 }
254 catch (Exception e)
255 {
256 m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
257 }
258 }
259 }
260
261 /// <summary>
262 /// Updates an inventory folder
263 /// </summary>
264 /// <param name="folder">Folder to update</param>
265 public void updateInventoryFolder(InventoryFolderBase folder)
266 {
267 string sql = @"UPDATE inventoryfolders SET ""agentID"" = :agentID,
268 ""parentFolderID"" = :parentFolderID,
269 ""folderName"" = :folderName,
270 type = :type,
271 version = :version
272 WHERE folderID = :folderID";
273
274 string folderName = folder.Name;
275 if (folderName.Length > 64)
276 {
277 folderName = folderName.Substring(0, 64);
278 m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on update");
279 }
280 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
281 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
282 {
283 cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
284 cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
285 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
286 cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
287 cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
288 cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
289 conn.Open();
290 try
291 {
292 cmd.ExecuteNonQuery();
293 }
294 catch (Exception e)
295 {
296 m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
297 }
298 }
299 }
300
301 /// <summary>
302 /// Updates an inventory folder
303 /// </summary>
304 /// <param name="folder">Folder to update</param>
305 public void moveInventoryFolder(InventoryFolderBase folder)
306 {
307 string sql = @"UPDATE inventoryfolders SET ""parentFolderID"" = :parentFolderID WHERE ""folderID"" = :folderID";
308 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
309 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
310 {
311 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
312 cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
313 conn.Open();
314 try
315 {
316 cmd.ExecuteNonQuery();
317 }
318 catch (Exception e)
319 {
320 m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
321 }
322 }
323 }
324
325 /// <summary>
326 /// Delete an inventory folder
327 /// </summary>
328 /// <param name="folderID">Id of folder to delete</param>
329 public void deleteInventoryFolder(UUID folderID)
330 {
331 string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID";
332
333 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
334 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
335 {
336 List<InventoryFolderBase> subFolders;
337 cmd.Parameters.Add(database.CreateParameter("parentID", UUID.Zero));
338 conn.Open();
339 subFolders = getFolderHierarchy(folderID, cmd);
340
341
342 //Delete all sub-folders
343 foreach (InventoryFolderBase f in subFolders)
344 {
345 DeleteOneFolder(f.ID, conn);
346 DeleteItemsInFolder(f.ID, conn);
347 }
348
349 //Delete the actual row
350 DeleteOneFolder(folderID, conn);
351 DeleteItemsInFolder(folderID, conn);
352 }
353 }
354
355 #endregion
356
357 #region Item Methods
358
359 /// <summary>
360 /// Returns a list of items in a specified folder
361 /// </summary>
362 /// <param name="folderID">The folder to search</param>
363 /// <returns>A list containing inventory items</returns>
364 public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
365 {
366 string sql = @"SELECT * FROM inventoryitems WHERE ""parentFolderID"" = :parentFolderID";
367 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
368 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
369 {
370 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folderID));
371 conn.Open();
372 List<InventoryItemBase> items = new List<InventoryItemBase>();
373
374 using (NpgsqlDataReader reader = cmd.ExecuteReader())
375 {
376 while (reader.Read())
377 {
378 items.Add(readInventoryItem(reader));
379 }
380 }
381 return items;
382 }
383 }
384
385 /// <summary>
386 /// Returns a specified inventory item
387 /// </summary>
388 /// <param name="itemID">The item ID</param>
389 /// <returns>An inventory item</returns>
390 public InventoryItemBase getInventoryItem(UUID itemID)
391 {
392 string sql = @"SELECT * FROM inventoryitems WHERE ""inventoryID"" = :inventoryID";
393 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
394 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
395 {
396 cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
397 conn.Open();
398 using (NpgsqlDataReader reader = cmd.ExecuteReader())
399 {
400 if (reader.Read())
401 {
402 return readInventoryItem(reader);
403 }
404 }
405 }
406
407 m_log.InfoFormat("[INVENTORY DB]: Found no inventory item with ID : {0}", itemID);
408 return null;
409 }
410
411 /// <summary>
412 /// Adds a specified item to the database
413 /// </summary>
414 /// <param name="item">The inventory item</param>
415 public void addInventoryItem(InventoryItemBase item)
416 {
417 if (getInventoryItem(item.ID) != null)
418 {
419 updateInventoryItem(item);
420 return;
421 }
422
423 string sql = @"INSERT INTO inventoryitems
424 (""inventoryID"", ""assetID"", ""assetType"", ""parentFolderID"", ""avatarID"", ""inventoryName"",
425 ""inventoryDescription"", ""inventoryNextPermissions"", ""inventoryCurrentPermissions"",
426 ""invType"", ""creatorID"", ""inventoryBasePermissions"", ""inventoryEveryOnePermissions"", ""inventoryGroupPermissions"",
427 ""salePrice"", ""SaleType"", ""creationDate"", ""groupID"", ""groupOwned"", flags)
428 VALUES
429 (:inventoryID, :assetID, :assetType, :parentFolderID, :avatarID, :inventoryName, :inventoryDescription,
430 :inventoryNextPermissions, :inventoryCurrentPermissions, :invType, :creatorID,
431 :inventoryBasePermissions, :inventoryEveryOnePermissions, :inventoryGroupPermissions, :SalePrice, :SaleType,
432 :creationDate, :groupID, :groupOwned, :flags)";
433
434 string itemName = item.Name;
435 if (item.Name.Length > 64)
436 {
437 itemName = item.Name.Substring(0, 64);
438 m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters");
439 }
440
441 string itemDesc = item.Description;
442 if (item.Description.Length > 128)
443 {
444 itemDesc = item.Description.Substring(0, 128);
445 m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters");
446 }
447
448 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
449 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
450 {
451 command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
452 command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
453 command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
454 command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
455 command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
456 command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
457 command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
458 command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
459 command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
460 command.Parameters.Add(database.CreateParameter("invType", item.InvType));
461 command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
462 command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
463 command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
464 command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
465 command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice));
466 command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType));
467 command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
468 command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
469 command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
470 command.Parameters.Add(database.CreateParameter("flags", item.Flags));
471 conn.Open();
472 try
473 {
474 command.ExecuteNonQuery();
475 }
476 catch (Exception e)
477 {
478 m_log.Error("[INVENTORY DB]: Error inserting item :" + e.Message);
479 }
480 }
481
482 sql = @"UPDATE inventoryfolders SET version = version + 1 WHERE ""folderID"" = @folderID";
483 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
484 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
485 {
486 command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString()));
487 conn.Open();
488 try
489 {
490 command.ExecuteNonQuery();
491 }
492 catch (Exception e)
493 {
494 m_log.Error("[INVENTORY DB] Error updating inventory folder for new item :" + e.Message);
495 }
496 }
497 }
498
499 /// <summary>
500 /// Updates the specified inventory item
501 /// </summary>
502 /// <param name="item">Inventory item to update</param>
503 public void updateInventoryItem(InventoryItemBase item)
504 {
505 string sql = @"UPDATE inventoryitems SET ""assetID"" = :assetID,
506 ""assetType"" = :assetType,
507 ""parentFolderID"" = :parentFolderID,
508 ""avatarID"" = :avatarID,
509 ""inventoryName"" = :inventoryName,
510 ""inventoryDescription"" = :inventoryDescription,
511 ""inventoryNextPermissions"" = :inventoryNextPermissions,
512 ""inventoryCurrentPermissions"" = :inventoryCurrentPermissions,
513 ""invType"" = :invType,
514 ""creatorID"" = :creatorID,
515 ""inventoryBasePermissions"" = :inventoryBasePermissions,
516 ""inventoryEveryOnePermissions"" = :inventoryEveryOnePermissions,
517 ""inventoryGroupPermissions"" = :inventoryGroupPermissions,
518 ""salePrice"" = :SalePrice,
519 ""saleType"" = :SaleType,
520 ""creationDate"" = :creationDate,
521 ""groupID"" = :groupID,
522 ""groupOwned"" = :groupOwned,
523 flags = :flags
524 WHERE ""inventoryID"" = :inventoryID";
525
526 string itemName = item.Name;
527 if (item.Name.Length > 64)
528 {
529 itemName = item.Name.Substring(0, 64);
530 m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters on update");
531 }
532
533 string itemDesc = item.Description;
534 if (item.Description.Length > 128)
535 {
536 itemDesc = item.Description.Substring(0, 128);
537 m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update");
538 }
539
540 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
541 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
542 {
543 command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
544 command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
545 command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
546 command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
547 command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
548 command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
549 command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
550 command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
551 command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
552 command.Parameters.Add(database.CreateParameter("invType", item.InvType));
553 command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
554 command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
555 command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
556 command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
557 command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice));
558 command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType));
559 command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
560 command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
561 command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
562 command.Parameters.Add(database.CreateParameter("flags", item.Flags));
563 conn.Open();
564 try
565 {
566 command.ExecuteNonQuery();
567 }
568 catch (Exception e)
569 {
570 m_log.Error("[INVENTORY DB]: Error updating item :" + e.Message);
571 }
572 }
573 }
574
575 // See IInventoryDataPlugin
576
577 /// <summary>
578 /// Delete an item in inventory database
579 /// </summary>
580 /// <param name="itemID">the item UUID</param>
581 public void deleteInventoryItem(UUID itemID)
582 {
583 string sql = @"DELETE FROM inventoryitems WHERE ""inventoryID""=:inventoryID";
584 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
585 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
586 {
587 cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
588 try
589 {
590 conn.Open();
591 cmd.ExecuteNonQuery();
592 }
593 catch (Exception e)
594 {
595 m_log.Error("[INVENTORY DB]: Error deleting item :" + e.Message);
596 }
597 }
598 }
599
600 public InventoryItemBase queryInventoryItem(UUID itemID)
601 {
602 return getInventoryItem(itemID);
603 }
604
605 public InventoryFolderBase queryInventoryFolder(UUID folderID)
606 {
607 return getInventoryFolder(folderID);
608 }
609
610 /// <summary>
611 /// Returns all activated gesture-items in the inventory of the specified avatar.
612 /// </summary>
613 /// <param name="avatarID">The <see cref="UUID"/> of the avatar</param>
614 /// <returns>
615 /// The list of gestures (<see cref="InventoryItemBase"/>s)
616 /// </returns>
617 public List<InventoryItemBase> fetchActiveGestures(UUID avatarID)
618 {
619 string sql = @"SELECT * FROM inventoryitems WHERE ""avatarID"" = :uuid AND ""assetType"" = :assetType and flags = 1";
620 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
621 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
622 {
623 cmd.Parameters.Add(database.CreateParameter("uuid", avatarID));
624 cmd.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture));
625 conn.Open();
626 using (NpgsqlDataReader reader = cmd.ExecuteReader())
627 {
628 List<InventoryItemBase> gestureList = new List<InventoryItemBase>();
629 while (reader.Read())
630 {
631 gestureList.Add(readInventoryItem(reader));
632 }
633 return gestureList;
634 }
635 }
636 }
637
638 #endregion
639
640 #region Private methods
641
642 /// <summary>
643 /// Delete an item in inventory database
644 /// </summary>
645 /// <param name="folderID">the item ID</param>
646 /// <param name="connection">connection to the database</param>
647 private void DeleteItemsInFolder(UUID folderID, NpgsqlConnection connection)
648 {
649 using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryitems WHERE ""folderID""=:folderID", connection))
650 {
651 command.Parameters.Add(database.CreateParameter("folderID", folderID));
652
653 try
654 {
655 command.ExecuteNonQuery();
656 }
657 catch (Exception e)
658 {
659 m_log.Error("[INVENTORY DB] Error deleting item :" + e.Message);
660 }
661 }
662 }
663
664 /// <summary>
665 /// Gets the folder hierarchy in a loop.
666 /// </summary>
667 /// <param name="parentID">parent ID.</param>
668 /// <param name="command">SQL command/connection to database</param>
669 /// <returns></returns>
670 private static List<InventoryFolderBase> getFolderHierarchy(UUID parentID, NpgsqlCommand command)
671 {
672 command.Parameters["parentID"].Value = parentID.Guid; //.ToString();
673
674 List<InventoryFolderBase> folders = getInventoryFolders(command);
675
676 if (folders.Count > 0)
677 {
678 List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
679
680 foreach (InventoryFolderBase folderBase in folders)
681 {
682 tempFolders.AddRange(getFolderHierarchy(folderBase.ID, command));
683 }
684
685 if (tempFolders.Count > 0)
686 {
687 folders.AddRange(tempFolders);
688 }
689 }
690 return folders;
691 }
692
693 /// <summary>
694 /// Gets the inventory folders.
695 /// </summary>
696 /// <param name="parentID">parentID, use UUID.Zero to get root</param>
697 /// <param name="user">user id, use UUID.Zero, if you want all folders from a parentID.</param>
698 /// <returns></returns>
699 private List<InventoryFolderBase> getInventoryFolders(UUID parentID, UUID user)
700 {
701 string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID AND ""agentID"" = :uuid";
702 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
703 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
704 {
705 if (user == UUID.Zero)
706 {
707 command.Parameters.Add(database.CreateParameter("uuid", "%"));
708 }
709 else
710 {
711 command.Parameters.Add(database.CreateParameter("uuid", user));
712 }
713 command.Parameters.Add(database.CreateParameter("parentID", parentID));
714 conn.Open();
715 return getInventoryFolders(command);
716 }
717 }
718
719 /// <summary>
720 /// Gets the inventory folders.
721 /// </summary>
722 /// <param name="command">SQLcommand.</param>
723 /// <returns></returns>
724 private static List<InventoryFolderBase> getInventoryFolders(NpgsqlCommand command)
725 {
726 using (NpgsqlDataReader reader = command.ExecuteReader())
727 {
728
729 List<InventoryFolderBase> items = new List<InventoryFolderBase>();
730 while (reader.Read())
731 {
732 items.Add(readInventoryFolder(reader));
733 }
734 return items;
735 }
736 }
737
738 /// <summary>
739 /// Reads a list of inventory folders returned by a query.
740 /// </summary>
741 /// <param name="reader">A PGSQL Data Reader</param>
742 /// <returns>A List containing inventory folders</returns>
743 protected static InventoryFolderBase readInventoryFolder(NpgsqlDataReader reader)
744 {
745 try
746 {
747 InventoryFolderBase folder = new InventoryFolderBase();
748 folder.Owner = DBGuid.FromDB(reader["agentID"]);
749 folder.ParentID = DBGuid.FromDB(reader["parentFolderID"]);
750 folder.ID = DBGuid.FromDB(reader["folderID"]);
751 folder.Name = (string)reader["folderName"];
752 folder.Type = (short)reader["type"];
753 folder.Version = Convert.ToUInt16(reader["version"]);
754
755 return folder;
756 }
757 catch (Exception e)
758 {
759 m_log.Error("[INVENTORY DB] Error reading inventory folder :" + e.Message);
760 }
761
762 return null;
763 }
764
765 /// <summary>
766 /// Reads a one item from an SQL result
767 /// </summary>
768 /// <param name="reader">The SQL Result</param>
769 /// <returns>the item read</returns>
770 private static InventoryItemBase readInventoryItem(IDataRecord reader)
771 {
772 try
773 {
774 InventoryItemBase item = new InventoryItemBase();
775
776 item.ID = DBGuid.FromDB(reader["inventoryID"]);
777 item.AssetID = DBGuid.FromDB(reader["assetID"]);
778 item.AssetType = Convert.ToInt32(reader["assetType"].ToString());
779 item.Folder = DBGuid.FromDB(reader["parentFolderID"]);
780 item.Owner = DBGuid.FromDB(reader["avatarID"]);
781 item.Name = reader["inventoryName"].ToString();
782 item.Description = reader["inventoryDescription"].ToString();
783 item.NextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]);
784 item.CurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]);
785 item.InvType = Convert.ToInt32(reader["invType"].ToString());
786 item.CreatorId = reader["creatorID"].ToString();
787 item.BasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]);
788 item.EveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]);
789 item.GroupPermissions = Convert.ToUInt32(reader["inventoryGroupPermissions"]);
790 item.SalePrice = Convert.ToInt32(reader["salePrice"]);
791 item.SaleType = Convert.ToByte(reader["saleType"]);
792 item.CreationDate = Convert.ToInt32(reader["creationDate"]);
793 item.GroupID = DBGuid.FromDB(reader["groupID"]);
794 item.GroupOwned = Convert.ToBoolean(reader["groupOwned"]);
795 item.Flags = Convert.ToUInt32(reader["flags"]);
796
797 return item;
798 }
799 catch (NpgsqlException e)
800 {
801 m_log.Error("[INVENTORY DB]: Error reading inventory item :" + e.Message);
802 }
803
804 return null;
805 }
806
807 /// <summary>
808 /// Delete a folder in inventory databasae
809 /// </summary>
810 /// <param name="folderID">the folder UUID</param>
811 /// <param name="connection">connection to database</param>
812 private void DeleteOneFolder(UUID folderID, NpgsqlConnection connection)
813 {
814 try
815 {
816 using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryfolders WHERE ""folderID""=:folderID and type=-1", connection))
817 {
818 command.Parameters.Add(database.CreateParameter("folderID", folderID));
819
820 command.ExecuteNonQuery();
821 }
822 }
823 catch (NpgsqlException e)
824 {
825 m_log.Error("[INVENTORY DB]: Error deleting folder :" + e.Message);
826 }
827 }
828
829 #endregion
830 }
831}
diff --git a/OpenSim/Data/PGSQL/PGSQLManager.cs b/OpenSim/Data/PGSQL/PGSQLManager.cs
new file mode 100644
index 0000000..97f40b2
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLManager.cs
@@ -0,0 +1,350 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.IO;
32using System.Reflection;
33using OpenSim.Framework;
34using log4net;
35using OpenMetaverse;
36using Npgsql;
37using NpgsqlTypes;
38
39namespace OpenSim.Data.PGSQL
40{
41 /// <summary>
42 /// A management class for the MS SQL Storage Engine
43 /// </summary>
44 public class PGSQLManager
45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// Connection string for ADO.net
50 /// </summary>
51 private readonly string connectionString;
52
53 /// <summary>
54 /// Initialize the manager and set the connectionstring
55 /// </summary>
56 /// <param name="connection"></param>
57 public PGSQLManager(string connection)
58 {
59 connectionString = connection;
60 InitializeMonoSecurity();
61 }
62
63 public void InitializeMonoSecurity()
64 {
65 if (!Util.IsPlatformMono)
66 {
67 if (AppDomain.CurrentDomain.GetData("MonoSecurityPostgresAdded") == null)
68 {
69 AppDomain.CurrentDomain.SetData("MonoSecurityPostgresAdded", "true");
70
71 AppDomain currentDomain = AppDomain.CurrentDomain;
72 currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandlerMonoSec);
73 }
74 }
75 }
76
77 private System.Reflection.Assembly ResolveEventHandlerMonoSec(object sender, ResolveEventArgs args)
78 {
79 Assembly MyAssembly = null;
80
81 if (args.Name.Substring(0, args.Name.IndexOf(",")) == "Mono.Security")
82 {
83 MyAssembly = Assembly.LoadFrom("lib/NET/Mono.Security.dll");
84 }
85
86 //Return the loaded assembly.
87 return MyAssembly;
88 }
89
90 /// <summary>
91 /// Type conversion to a SQLDbType functions
92 /// </summary>
93 /// <param name="type"></param>
94 /// <returns></returns>
95 internal NpgsqlDbType DbtypeFromType(Type type)
96 {
97 if (type == typeof(string))
98 {
99 return NpgsqlDbType.Varchar;
100 }
101 if (type == typeof(double))
102 {
103 return NpgsqlDbType.Double;
104 }
105 if (type == typeof(Single))
106 {
107 return NpgsqlDbType.Double;
108 }
109 if (type == typeof(int))
110 {
111 return NpgsqlDbType.Integer;
112 }
113 if (type == typeof(bool))
114 {
115 return NpgsqlDbType.Boolean;
116 }
117 if (type == typeof(UUID))
118 {
119 return NpgsqlDbType.Uuid;
120 }
121 if (type == typeof(byte))
122 {
123 return NpgsqlDbType.Smallint;
124 }
125 if (type == typeof(sbyte))
126 {
127 return NpgsqlDbType.Integer;
128 }
129 if (type == typeof(Byte[]))
130 {
131 return NpgsqlDbType.Bytea;
132 }
133 if (type == typeof(uint) || type == typeof(ushort))
134 {
135 return NpgsqlDbType.Integer;
136 }
137 if (type == typeof(ulong))
138 {
139 return NpgsqlDbType.Bigint;
140 }
141 if (type == typeof(DateTime))
142 {
143 return NpgsqlDbType.Timestamp;
144 }
145
146 return NpgsqlDbType.Varchar;
147 }
148
149 internal NpgsqlDbType DbtypeFromString(Type type, string PGFieldType)
150 {
151 if (PGFieldType == "")
152 {
153 return DbtypeFromType(type);
154 }
155
156 if (PGFieldType == "character varying")
157 {
158 return NpgsqlDbType.Varchar;
159 }
160 if (PGFieldType == "double precision")
161 {
162 return NpgsqlDbType.Double;
163 }
164 if (PGFieldType == "integer")
165 {
166 return NpgsqlDbType.Integer;
167 }
168 if (PGFieldType == "smallint")
169 {
170 return NpgsqlDbType.Smallint;
171 }
172 if (PGFieldType == "boolean")
173 {
174 return NpgsqlDbType.Boolean;
175 }
176 if (PGFieldType == "uuid")
177 {
178 return NpgsqlDbType.Uuid;
179 }
180 if (PGFieldType == "bytea")
181 {
182 return NpgsqlDbType.Bytea;
183 }
184
185 return DbtypeFromType(type);
186 }
187
188 /// <summary>
189 /// Creates value for parameter.
190 /// </summary>
191 /// <param name="value">The value.</param>
192 /// <returns></returns>
193 private static object CreateParameterValue(object value)
194 {
195 Type valueType = value.GetType();
196
197 if (valueType == typeof(UUID)) //TODO check if this works
198 {
199 return ((UUID) value).Guid;
200 }
201 if (valueType == typeof(UUID))
202 {
203 return ((UUID)value).Guid;
204 }
205 if (valueType == typeof(bool))
206 {
207 return (bool)value;
208 }
209 if (valueType == typeof(Byte[]))
210 {
211 return value;
212 }
213 if (valueType == typeof(int))
214 {
215 return value;
216 }
217 return value;
218 }
219
220 /// <summary>
221 /// Create value for parameter based on PGSQL Schema
222 /// </summary>
223 /// <param name="value"></param>
224 /// <param name="PGFieldType"></param>
225 /// <returns></returns>
226 internal static object CreateParameterValue(object value, string PGFieldType)
227 {
228 if (PGFieldType == "uuid")
229 {
230 UUID uidout;
231 UUID.TryParse(value.ToString(), out uidout);
232 return uidout;
233 }
234 if (PGFieldType == "integer")
235 {
236 int intout;
237 int.TryParse(value.ToString(), out intout);
238 return intout;
239 }
240 if (PGFieldType == "boolean")
241 {
242 return (value.ToString() == "true");
243 }
244 if (PGFieldType == "timestamp with time zone")
245 {
246 return (DateTime)value;
247 }
248 if (PGFieldType == "timestamp without time zone")
249 {
250 return (DateTime)value;
251 }
252 return CreateParameterValue(value);
253 }
254
255 /// <summary>
256 /// Create a parameter for a command
257 /// </summary>
258 /// <param name="parameterName">Name of the parameter.</param>
259 /// <param name="parameterObject">parameter object.</param>
260 /// <returns></returns>
261 internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject)
262 {
263 return CreateParameter(parameterName, parameterObject, false);
264 }
265
266 /// <summary>
267 /// Creates the parameter for a command.
268 /// </summary>
269 /// <param name="parameterName">Name of the parameter.</param>
270 /// <param name="parameterObject">parameter object.</param>
271 /// <param name="parameterOut">if set to <c>true</c> parameter is a output parameter</param>
272 /// <returns></returns>
273 internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, bool parameterOut)
274 {
275 //Tweak so we dont always have to add : sign
276 if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":","");
277
278 //HACK if object is null, it is turned into a string, there are no nullable type till now
279 if (parameterObject == null) parameterObject = "";
280
281 NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromType(parameterObject.GetType()));
282
283 if (parameterOut)
284 {
285 parameter.Direction = ParameterDirection.Output;
286 }
287 else
288 {
289 parameter.Direction = ParameterDirection.Input;
290 parameter.Value = CreateParameterValue(parameterObject);
291 }
292
293 return parameter;
294 }
295
296 /// <summary>
297 /// Create a parameter with PGSQL schema type
298 /// </summary>
299 /// <param name="parameterName"></param>
300 /// <param name="parameterObject"></param>
301 /// <param name="PGFieldType"></param>
302 /// <returns></returns>
303 internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, string PGFieldType)
304 {
305 //Tweak so we dont always have to add : sign
306 if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":", "");
307
308 //HACK if object is null, it is turned into a string, there are no nullable type till now
309 if (parameterObject == null) parameterObject = "";
310
311 NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromString(parameterObject.GetType(), PGFieldType));
312
313 parameter.Direction = ParameterDirection.Input;
314 parameter.Value = CreateParameterValue(parameterObject, PGFieldType);
315
316 return parameter;
317 }
318
319 /// <summary>
320 /// Checks if we need to do some migrations to the database
321 /// </summary>
322 /// <param name="migrationStore">migrationStore.</param>
323 public void CheckMigration(string migrationStore)
324 {
325 using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
326 {
327 connection.Open();
328 Assembly assem = GetType().Assembly;
329 PGSQLMigration migration = new PGSQLMigration(connection, assem, migrationStore);
330
331 migration.Update();
332 }
333 }
334
335 /// <summary>
336 /// Returns the version of this DB provider
337 /// </summary>
338 /// <returns>A string containing the DB provider</returns>
339 public string getVersion()
340 {
341 Module module = GetType().Module;
342 // string dllName = module.Assembly.ManifestModule.Name;
343 Version dllVersion = module.Assembly.GetName().Version;
344
345 return
346 string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
347 dllVersion.Revision);
348 }
349 }
350}
diff --git a/OpenSim/Data/PGSQL/PGSQLMigration.cs b/OpenSim/Data/PGSQL/PGSQLMigration.cs
new file mode 100644
index 0000000..709fde0
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLMigration.cs
@@ -0,0 +1,102 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using Npgsql;
29using System;
30using System.Data;
31using System.Data.Common;
32using System.Reflection;
33
34namespace OpenSim.Data.PGSQL
35{
36 public class PGSQLMigration : Migration
37 {
38 public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string type)
39 : base(conn, assem, type)
40 {
41 }
42
43 public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string subtype, string type)
44 : base(conn, assem, subtype, type)
45 {
46 }
47
48 protected override int FindVersion(DbConnection conn, string type)
49 {
50 int version = 0;
51 NpgsqlConnection lcConn = (NpgsqlConnection)conn;
52
53 using (NpgsqlCommand cmd = lcConn.CreateCommand())
54 {
55 try
56 {
57 cmd.CommandText = "select version from migrations where name = '" + type + "' " +
58 " order by version desc limit 1"; //Must be
59 using (NpgsqlDataReader reader = cmd.ExecuteReader())
60 {
61 if (reader.Read())
62 {
63 version = Convert.ToInt32(reader["version"]);
64 }
65 reader.Close();
66 }
67 }
68 catch
69 {
70 // Return -1 to indicate table does not exist
71 return -1;
72 }
73 }
74 return version;
75 }
76
77 protected override void ExecuteScript(DbConnection conn, string[] script)
78 {
79 if (!(conn is NpgsqlConnection))
80 {
81 base.ExecuteScript(conn, script);
82 return;
83 }
84
85 foreach (string sql in script)
86 {
87 try
88 {
89 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, (NpgsqlConnection)conn))
90 {
91 cmd.ExecuteNonQuery();
92 }
93 }
94 catch (Exception)
95 {
96 throw new Exception(sql);
97
98 }
99 }
100 }
101 }
102}
diff --git a/OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs b/OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs
new file mode 100644
index 0000000..82e5ed8
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs
@@ -0,0 +1,56 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenSim.Framework;
33using OpenMetaverse;
34using Npgsql;
35
36namespace OpenSim.Data.PGSQL
37{
38 public class PGSQLOfflineIMData : PGSQLGenericTableHandler<OfflineIMData>, IOfflineIMData
39 {
40 public PGSQLOfflineIMData(string connectionString, string realm)
41 : base(connectionString, realm, "IM_Store")
42 {
43 }
44
45 public void DeleteOld()
46 {
47 using (NpgsqlCommand cmd = new NpgsqlCommand())
48 {
49 cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < CURRENT_DATE - INTERVAL '2 week'", m_Realm);
50
51 ExecuteNonQuery(cmd);
52 }
53
54 }
55 }
56}
diff --git a/OpenSim/Data/PGSQL/PGSQLPresenceData.cs b/OpenSim/Data/PGSQL/PGSQLPresenceData.cs
new file mode 100644
index 0000000..666de07
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLPresenceData.cs
@@ -0,0 +1,115 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 /// <summary>
41 /// A PGSQL Interface for the Presence Server
42 /// </summary>
43 public class PGSQLPresenceData : PGSQLGenericTableHandler<PresenceData>,
44 IPresenceData
45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 public PGSQLPresenceData(string connectionString, string realm) :
49 base(connectionString, realm, "Presence")
50 {
51 }
52
53 public PresenceData Get(UUID sessionID)
54 {
55 PresenceData[] ret = Get("SessionID", sessionID.ToString());
56
57 if (ret.Length == 0)
58 return null;
59
60 return ret[0];
61 }
62
63 public void LogoutRegionAgents(UUID regionID)
64 {
65 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
66 using (NpgsqlCommand cmd = new NpgsqlCommand())
67 {
68
69 cmd.CommandText = String.Format(@"DELETE FROM {0} WHERE ""RegionID""=:RegionID", m_Realm);
70
71 cmd.Parameters.Add(m_database.CreateParameter("RegionID", regionID));
72 cmd.Connection = conn;
73 conn.Open();
74 cmd.ExecuteNonQuery();
75 }
76 }
77
78 public bool ReportAgent(UUID sessionID, UUID regionID)
79 {
80 PresenceData[] pd = Get("SessionID", sessionID.ToString());
81 if (pd.Length == 0)
82 return false;
83
84 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
85 using (NpgsqlCommand cmd = new NpgsqlCommand())
86 {
87
88 cmd.CommandText = String.Format(@"UPDATE {0} SET
89 ""RegionID"" = :RegionID
90 WHERE ""SessionID"" = :SessionID", m_Realm);
91
92 cmd.Parameters.Add(m_database.CreateParameter("SessionID", sessionID));
93 cmd.Parameters.Add(m_database.CreateParameter("RegionID", regionID));
94 cmd.Connection = conn;
95 conn.Open();
96 if (cmd.ExecuteNonQuery() == 0)
97 return false;
98 }
99 return true;
100 }
101
102 public bool VerifyAgent(UUID agentId, UUID secureSessionID)
103 {
104 PresenceData[] ret = Get("SecureSessionID", secureSessionID.ToString());
105
106 if (ret.Length == 0)
107 return false;
108
109 if(ret[0].UserID != agentId.ToString())
110 return false;
111
112 return true;
113 }
114 }
115}
diff --git a/OpenSim/Data/PGSQL/PGSQLRegionData.cs b/OpenSim/Data/PGSQL/PGSQLRegionData.cs
new file mode 100644
index 0000000..8a46559
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLRegionData.cs
@@ -0,0 +1,392 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Drawing;
32using System.IO;
33using System.Reflection;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using RegionFlags = OpenSim.Framework.RegionFlags;
40using Npgsql;
41
42namespace OpenSim.Data.PGSQL
43{
44 /// <summary>
45 /// A PGSQL Interface for the Region Server.
46 /// </summary>
47 public class PGSQLRegionData : IRegionData
48 {
49 private string m_Realm;
50 private List<string> m_ColumnNames = null;
51 private string m_ConnectionString;
52 private PGSQLManager m_database;
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 protected Dictionary<string, string> m_FieldTypes = new Dictionary<string, string>();
56
57 protected virtual Assembly Assembly
58 {
59 get { return GetType().Assembly; }
60 }
61
62 public PGSQLRegionData(string connectionString, string realm)
63 {
64 m_Realm = realm;
65 m_ConnectionString = connectionString;
66 m_database = new PGSQLManager(connectionString);
67
68 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
69 {
70 conn.Open();
71 Migration m = new Migration(conn, GetType().Assembly, "GridStore");
72 m.Update();
73 }
74 LoadFieldTypes();
75 }
76
77 private void LoadFieldTypes()
78 {
79 m_FieldTypes = new Dictionary<string, string>();
80
81 string query = string.Format(@"select column_name,data_type
82 from INFORMATION_SCHEMA.COLUMNS
83 where table_name = lower('{0}');
84
85 ", m_Realm);
86 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
87 using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
88 {
89 conn.Open();
90 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
91 {
92 while (rdr.Read())
93 {
94 // query produces 0 to many rows of single column, so always add the first item in each row
95 m_FieldTypes.Add((string)rdr[0], (string)rdr[1]);
96 }
97 }
98 }
99 }
100
101 public List<RegionData> Get(string regionName, UUID scopeID)
102 {
103 string sql = "select * from "+m_Realm+" where lower(\"regionName\") like lower(:regionName) ";
104 if (scopeID != UUID.Zero)
105 sql += " and \"ScopeID\" = :scopeID";
106 sql += " order by lower(\"regionName\")";
107
108 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
109 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
110 {
111 cmd.Parameters.Add(m_database.CreateParameter("regionName", regionName));
112 if (scopeID != UUID.Zero)
113 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
114 conn.Open();
115 return RunCommand(cmd);
116 }
117 }
118
119 public RegionData Get(int posX, int posY, UUID scopeID)
120 {
121 string sql = "select * from "+m_Realm+" where \"locX\" = :posX and \"locY\" = :posY";
122 if (scopeID != UUID.Zero)
123 sql += " and \"ScopeID\" = :scopeID";
124
125 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
126 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
127 {
128 cmd.Parameters.Add(m_database.CreateParameter("posX", posX));
129 cmd.Parameters.Add(m_database.CreateParameter("posY", posY));
130 if (scopeID != UUID.Zero)
131 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
132 conn.Open();
133 List<RegionData> ret = RunCommand(cmd);
134 if (ret.Count == 0)
135 return null;
136
137 return ret[0];
138 }
139 }
140
141 public RegionData Get(UUID regionID, UUID scopeID)
142 {
143 string sql = "select * from "+m_Realm+" where uuid = :regionID";
144 if (scopeID != UUID.Zero)
145 sql += " and \"ScopeID\" = :scopeID";
146 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
147 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
148 {
149 cmd.Parameters.Add(m_database.CreateParameter("regionID", regionID));
150 if (scopeID != UUID.Zero)
151 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
152 conn.Open();
153 List<RegionData> ret = RunCommand(cmd);
154 if (ret.Count == 0)
155 return null;
156
157 return ret[0];
158 }
159 }
160
161 public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
162 {
163 string sql = "select * from "+m_Realm+" where \"locX\" between :startX and :endX and \"locY\" between :startY and :endY";
164 if (scopeID != UUID.Zero)
165 sql += " and \"ScopeID\" = :scopeID";
166
167 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
168 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
169 {
170 cmd.Parameters.Add(m_database.CreateParameter("startX", startX));
171 cmd.Parameters.Add(m_database.CreateParameter("startY", startY));
172 cmd.Parameters.Add(m_database.CreateParameter("endX", endX));
173 cmd.Parameters.Add(m_database.CreateParameter("endY", endY));
174 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
175 conn.Open();
176 return RunCommand(cmd);
177 }
178 }
179
180 public List<RegionData> RunCommand(NpgsqlCommand cmd)
181 {
182 List<RegionData> retList = new List<RegionData>();
183
184 NpgsqlDataReader result = cmd.ExecuteReader();
185
186 while (result.Read())
187 {
188 RegionData ret = new RegionData();
189 ret.Data = new Dictionary<string, object>();
190
191 UUID regionID;
192 UUID.TryParse(result["uuid"].ToString(), out regionID);
193 ret.RegionID = regionID;
194 UUID scope;
195 UUID.TryParse(result["ScopeID"].ToString(), out scope);
196 ret.ScopeID = scope;
197 ret.RegionName = result["regionName"].ToString();
198 ret.posX = Convert.ToInt32(result["locX"]);
199 ret.posY = Convert.ToInt32(result["locY"]);
200 ret.sizeX = Convert.ToInt32(result["sizeX"]);
201 ret.sizeY = Convert.ToInt32(result["sizeY"]);
202
203 if (m_ColumnNames == null)
204 {
205 m_ColumnNames = new List<string>();
206
207 DataTable schemaTable = result.GetSchemaTable();
208 foreach (DataRow row in schemaTable.Rows)
209 m_ColumnNames.Add(row["ColumnName"].ToString());
210 }
211
212 foreach (string s in m_ColumnNames)
213 {
214 if (s == "uuid")
215 continue;
216 if (s == "ScopeID")
217 continue;
218 if (s == "regionName")
219 continue;
220 if (s == "locX")
221 continue;
222 if (s == "locY")
223 continue;
224
225 ret.Data[s] = result[s].ToString();
226 }
227
228 retList.Add(ret);
229 }
230 return retList;
231 }
232
233 public bool Store(RegionData data)
234 {
235 if (data.Data.ContainsKey("uuid"))
236 data.Data.Remove("uuid");
237 if (data.Data.ContainsKey("ScopeID"))
238 data.Data.Remove("ScopeID");
239 if (data.Data.ContainsKey("regionName"))
240 data.Data.Remove("regionName");
241 if (data.Data.ContainsKey("posX"))
242 data.Data.Remove("posX");
243 if (data.Data.ContainsKey("posY"))
244 data.Data.Remove("posY");
245 if (data.Data.ContainsKey("sizeX"))
246 data.Data.Remove("sizeX");
247 if (data.Data.ContainsKey("sizeY"))
248 data.Data.Remove("sizeY");
249 if (data.Data.ContainsKey("locX"))
250 data.Data.Remove("locX");
251 if (data.Data.ContainsKey("locY"))
252 data.Data.Remove("locY");
253
254 string[] fields = new List<string>(data.Data.Keys).ToArray();
255
256 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
257 using (NpgsqlCommand cmd = new NpgsqlCommand())
258 {
259
260 string update = "update " + m_Realm + " set \"locX\"=:posX, \"locY\"=:posY, \"sizeX\"=:sizeX, \"sizeY\"=:sizeY ";
261
262 foreach (string field in fields)
263 {
264
265 update += ", ";
266 update += " \"" + field + "\" = :" + field;
267
268 if (m_FieldTypes.ContainsKey(field))
269 cmd.Parameters.Add(m_database.CreateParameter(field, data.Data[field], m_FieldTypes[field]));
270 else
271 cmd.Parameters.Add(m_database.CreateParameter(field, data.Data[field]));
272 }
273
274 update += " where uuid = :regionID";
275
276 if (data.ScopeID != UUID.Zero)
277 update += " and \"ScopeID\" = :scopeID";
278
279 cmd.CommandText = update;
280 cmd.Connection = conn;
281 cmd.Parameters.Add(m_database.CreateParameter("regionID", data.RegionID));
282 cmd.Parameters.Add(m_database.CreateParameter("regionName", data.RegionName));
283 cmd.Parameters.Add(m_database.CreateParameter("scopeID", data.ScopeID));
284 cmd.Parameters.Add(m_database.CreateParameter("posX", data.posX));
285 cmd.Parameters.Add(m_database.CreateParameter("posY", data.posY));
286 cmd.Parameters.Add(m_database.CreateParameter("sizeX", data.sizeX));
287 cmd.Parameters.Add(m_database.CreateParameter("sizeY", data.sizeY));
288 conn.Open();
289 try
290 {
291 if (cmd.ExecuteNonQuery() < 1)
292 {
293 string insert = "insert into " + m_Realm + " (uuid, \"ScopeID\", \"locX\", \"locY\", \"sizeX\", \"sizeY\", \"regionName\", \"" +
294 String.Join("\", \"", fields) +
295 "\") values (:regionID, :scopeID, :posX, :posY, :sizeX, :sizeY, :regionName, :" + String.Join(", :", fields) + ")";
296
297 cmd.CommandText = insert;
298
299 try
300 {
301 if (cmd.ExecuteNonQuery() < 1)
302 {
303 return false;
304 }
305 }
306 catch (Exception ex)
307 {
308 m_log.Warn("[PGSQL Grid]: Error inserting into Regions table: " + ex.Message + ", INSERT sql: " + insert);
309 }
310 }
311 }
312 catch (Exception ex)
313 {
314 m_log.Warn("[PGSQL Grid]: Error updating Regions table: " + ex.Message + ", UPDATE sql: " + update);
315 }
316 }
317
318 return true;
319 }
320
321 public bool SetDataItem(UUID regionID, string item, string value)
322 {
323 string sql = "update " + m_Realm +
324 " set \"" + item + "\" = :" + item + " where uuid = :UUID";
325
326 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
327 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
328 {
329 cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
330 cmd.Parameters.Add(m_database.CreateParameter("UUID", regionID));
331 conn.Open();
332 if (cmd.ExecuteNonQuery() > 0)
333 return true;
334 }
335 return false;
336 }
337
338 public bool Delete(UUID regionID)
339 {
340 string sql = "delete from " + m_Realm +
341 " where uuid = :UUID";
342 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
343 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
344 {
345 cmd.Parameters.Add(m_database.CreateParameter("UUID", regionID));
346 conn.Open();
347 if (cmd.ExecuteNonQuery() > 0)
348 return true;
349 }
350 return false;
351 }
352
353 public List<RegionData> GetDefaultRegions(UUID scopeID)
354 {
355 return Get((int)RegionFlags.DefaultRegion, scopeID);
356 }
357
358 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
359 {
360 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
361 }
362
363 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
364 {
365 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
366 RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y);
367 regions.Sort(distanceComparer);
368
369 return regions;
370 }
371
372 public List<RegionData> GetHyperlinks(UUID scopeID)
373 {
374 return Get((int)RegionFlags.Hyperlink, scopeID);
375 }
376
377 private List<RegionData> Get(int regionFlags, UUID scopeID)
378 {
379 string sql = "SELECT * FROM " + m_Realm + " WHERE (flags & " + regionFlags.ToString() + ") <> 0";
380 if (scopeID != UUID.Zero)
381 sql += " AND \"ScopeID\" = :scopeID";
382
383 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
384 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
385 {
386 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
387 conn.Open();
388 return RunCommand(cmd);
389 }
390 }
391 }
392}
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
new file mode 100644
index 0000000..3924799
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
@@ -0,0 +1,2252 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Drawing;
32using System.IO;
33using System.Reflection;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using Npgsql;
40
41namespace OpenSim.Data.PGSQL
42{
43 /// <summary>
44 /// A PGSQL Interface for the Region Server.
45 /// </summary>
46 public class PGSQLSimulationData : ISimulationDataStore
47 {
48 private const string _migrationStore = "RegionStore";
49
50 // private static FileSystemDataStore Instance = new FileSystemDataStore();
51 private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 /// <summary>
54 /// The database manager
55 /// </summary>
56 private PGSQLManager _Database;
57 private string m_connectionString;
58 protected virtual Assembly Assembly
59 {
60 get { return GetType().Assembly; }
61 }
62
63 public PGSQLSimulationData()
64 {
65 }
66
67 public PGSQLSimulationData(string connectionString)
68 {
69 Initialise(connectionString);
70 }
71
72 /// <summary>
73 /// Initialises the region datastore
74 /// </summary>
75 /// <param name="connectionString">The connection string.</param>
76 public void Initialise(string connectionString)
77 {
78 m_connectionString = connectionString;
79 _Database = new PGSQLManager(connectionString);
80
81 using (NpgsqlConnection conn = new NpgsqlConnection(connectionString))
82 {
83 conn.Open();
84 //New Migration settings
85 Migration m = new Migration(conn, Assembly, "RegionStore");
86 m.Update();
87 }
88 }
89
90 /// <summary>
91 /// Dispose the database
92 /// </summary>
93 public void Dispose() { }
94
95 #region SceneObjectGroup region for loading and Store of the scene.
96
97 /// <summary>
98 /// Loads the objects present in the region.
99 /// </summary>
100 /// <param name="regionUUID">The region UUID.</param>
101 /// <returns></returns>
102 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
103 {
104 UUID lastGroupID = UUID.Zero;
105
106 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>();
107 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
108 SceneObjectGroup grp = null;
109
110 string sql = @"SELECT *,
111 CASE WHEN prims.""UUID"" = prims.""SceneGroupID"" THEN 0 ELSE 1 END as sort
112 FROM prims
113 LEFT JOIN primshapes ON prims.""UUID"" = primshapes.""UUID""
114 WHERE ""RegionUUID"" = :RegionUUID
115 ORDER BY ""SceneGroupID"" asc, sort asc, ""LinkNumber"" asc";
116
117 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
118 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
119 {
120 command.Parameters.Add(_Database.CreateParameter("regionUUID", regionUUID));
121 conn.Open();
122 using (NpgsqlDataReader reader = command.ExecuteReader())
123 {
124 while (reader.Read())
125 {
126 SceneObjectPart sceneObjectPart = BuildPrim(reader);
127 if (reader["Shape"] is DBNull)
128 sceneObjectPart.Shape = PrimitiveBaseShape.Default;
129 else
130 sceneObjectPart.Shape = BuildShape(reader);
131
132 prims[sceneObjectPart.UUID] = sceneObjectPart;
133
134 UUID groupID = new UUID((Guid)reader["SceneGroupID"]);
135
136 if (groupID != lastGroupID) // New SOG
137 {
138 if (grp != null)
139 objects[grp.UUID] = grp;
140
141 lastGroupID = groupID;
142
143 // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are
144 // recorded as the root prim (for which the UUID must equal the persisted group UUID). In
145 // this case, force the UUID to be the same as the group UUID so that at least these can be
146 // deleted (we need to change the UUID so that any other prims in the linkset can also be
147 // deleted).
148 if (sceneObjectPart.UUID != groupID && groupID != UUID.Zero)
149 {
150 _Log.WarnFormat(
151 "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID",
152 sceneObjectPart.Name, sceneObjectPart.UUID, sceneObjectPart.GroupPosition, groupID);
153
154 sceneObjectPart.UUID = groupID;
155 }
156
157 grp = new SceneObjectGroup(sceneObjectPart);
158 }
159 else
160 {
161 // Black magic to preserve link numbers
162 // Why is this needed, fix this in AddPart method.
163 int link = sceneObjectPart.LinkNum;
164
165 grp.AddPart(sceneObjectPart);
166
167 if (link != 0)
168 sceneObjectPart.LinkNum = link;
169 }
170 }
171 }
172 }
173
174 if (grp != null)
175 objects[grp.UUID] = grp;
176
177 // Instead of attempting to LoadItems on every prim,
178 // most of which probably have no items... get a
179 // list from DB of all prims which have items and
180 // LoadItems only on those
181 List<SceneObjectPart> primsWithInventory = new List<SceneObjectPart>();
182 string qry = "select distinct \"primID\" from primitems";
183 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
184 using (NpgsqlCommand command = new NpgsqlCommand(qry, conn))
185 {
186 conn.Open();
187 using (NpgsqlDataReader itemReader = command.ExecuteReader())
188 {
189 while (itemReader.Read())
190 {
191 if (!(itemReader["primID"] is DBNull))
192 {
193 UUID primID = new UUID(itemReader["primID"].ToString());
194 if (prims.ContainsKey(primID))
195 {
196 primsWithInventory.Add(prims[primID]);
197 }
198 }
199 }
200 }
201 }
202
203 LoadItems(primsWithInventory);
204
205 _Log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
206
207 return new List<SceneObjectGroup>(objects.Values);
208 }
209
210 /// <summary>
211 /// Load in the prim's persisted inventory.
212 /// </summary>
213 /// <param name="allPrims">all prims with inventory on a region</param>
214 private void LoadItems(List<SceneObjectPart> allPrimsWithInventory)
215 {
216 string sql = @"SELECT * FROM primitems WHERE ""primID"" = :PrimID";
217 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
218 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
219 {
220 conn.Open();
221 foreach (SceneObjectPart objectPart in allPrimsWithInventory)
222 {
223 command.Parameters.Clear();
224 command.Parameters.Add(_Database.CreateParameter("PrimID", objectPart.UUID));
225
226 List<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
227
228 using (NpgsqlDataReader reader = command.ExecuteReader())
229 {
230 while (reader.Read())
231 {
232 TaskInventoryItem item = BuildItem(reader);
233
234 item.ParentID = objectPart.UUID; // Values in database are
235 // often wrong
236 inventory.Add(item);
237 }
238 }
239
240 objectPart.Inventory.RestoreInventoryItems(inventory);
241 }
242 }
243 }
244
245 /// <summary>
246 /// Stores all object's details apart from inventory
247 /// </summary>
248 /// <param name="obj"></param>
249 /// <param name="regionUUID"></param>
250 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
251 {
252 uint flags = obj.RootPart.GetEffectiveObjectFlags();
253 // Eligibility check
254 //
255 if ((flags & (uint)PrimFlags.Temporary) != 0)
256 return;
257 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
258 return;
259
260 //_Log.DebugFormat("[PGSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length);
261
262 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
263 {
264 conn.Open();
265 NpgsqlTransaction transaction = conn.BeginTransaction();
266
267 try
268 {
269 foreach (SceneObjectPart sceneObjectPart in obj.Parts)
270 {
271 //Update prim
272 using (NpgsqlCommand sqlCommand = conn.CreateCommand())
273 {
274 sqlCommand.Transaction = transaction;
275 try
276 {
277 StoreSceneObjectPrim(sceneObjectPart, sqlCommand, obj.UUID, regionUUID);
278 }
279 catch (NpgsqlException sqlEx)
280 {
281 _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrim SQL error: {0} at line {1}", sqlEx.Message, sqlEx.Line);
282 throw;
283 }
284 }
285
286 //Update primshapes
287 using (NpgsqlCommand sqlCommand = conn.CreateCommand())
288 {
289 sqlCommand.Transaction = transaction;
290 try
291 {
292 StoreSceneObjectPrimShapes(sceneObjectPart, sqlCommand, obj.UUID, regionUUID);
293 }
294 catch (NpgsqlException sqlEx)
295 {
296 _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrimShapes SQL error: {0} at line {1}", sqlEx.Message, sqlEx.Line);
297 throw;
298 }
299 }
300 }
301
302 transaction.Commit();
303 }
304 catch (Exception ex)
305 {
306 _Log.ErrorFormat("[REGION DB]: Store SceneObjectGroup error: {0}, Rolling back...", ex.Message);
307 try
308 {
309 transaction.Rollback();
310 }
311 catch (Exception ex2)
312 {
313 //Show error
314 _Log.InfoFormat("[REGION DB]: Rollback of SceneObjectGroup store transaction failed with error: {0}", ex2.Message);
315
316 }
317 }
318 }
319 }
320
321 /// <summary>
322 /// Stores the prim of the sceneobjectpart.
323 /// </summary>
324 /// <param name="sceneObjectPart">The sceneobjectpart or prim.</param>
325 /// <param name="sqlCommand">The SQL command with the transaction.</param>
326 /// <param name="sceneGroupID">The scenegroup UUID.</param>
327 /// <param name="regionUUID">The region UUID.</param>
328 private void StoreSceneObjectPrim(SceneObjectPart sceneObjectPart, NpgsqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID)
329 {
330 //Big query to update or insert a new prim.
331
332 string queryPrims = @"
333 UPDATE prims SET
334 ""CreationDate"" = :CreationDate, ""Name"" = :Name, ""Text"" = :Text, ""Description"" = :Description, ""SitName"" = :SitName,
335 ""TouchName"" = :TouchName, ""ObjectFlags"" = :ObjectFlags, ""OwnerMask"" = :OwnerMask, ""NextOwnerMask"" = :NextOwnerMask, ""GroupMask"" = :GroupMask,
336 ""EveryoneMask"" = :EveryoneMask, ""BaseMask"" = :BaseMask, ""PositionX"" = :PositionX, ""PositionY"" = :PositionY, ""PositionZ"" = :PositionZ,
337 ""GroupPositionX"" = :GroupPositionX, ""GroupPositionY"" = :GroupPositionY, ""GroupPositionZ"" = :GroupPositionZ, ""VelocityX"" = :VelocityX,
338 ""VelocityY"" = :VelocityY, ""VelocityZ"" = :VelocityZ, ""AngularVelocityX"" = :AngularVelocityX, ""AngularVelocityY"" = :AngularVelocityY,
339 ""AngularVelocityZ"" = :AngularVelocityZ, ""AccelerationX"" = :AccelerationX, ""AccelerationY"" = :AccelerationY,
340 ""AccelerationZ"" = :AccelerationZ, ""RotationX"" = :RotationX, ""RotationY"" = :RotationY, ""RotationZ"" = :RotationZ, ""RotationW"" = :RotationW,
341 ""SitTargetOffsetX"" = :SitTargetOffsetX, ""SitTargetOffsetY"" = :SitTargetOffsetY, ""SitTargetOffsetZ"" = :SitTargetOffsetZ,
342 ""SitTargetOrientW"" = :SitTargetOrientW, ""SitTargetOrientX"" = :SitTargetOrientX, ""SitTargetOrientY"" = :SitTargetOrientY,
343 ""SitTargetOrientZ"" = :SitTargetOrientZ, ""RegionUUID"" = :RegionUUID, ""CreatorID"" = :CreatorID, ""OwnerID"" = :OwnerID, ""GroupID"" = :GroupID,
344 ""LastOwnerID"" = :LastOwnerID, ""SceneGroupID"" = :SceneGroupID, ""PayPrice"" = :PayPrice, ""PayButton1"" = :PayButton1, ""PayButton2"" = :PayButton2,
345 ""PayButton3"" = :PayButton3, ""PayButton4"" = :PayButton4, ""LoopedSound"" = :LoopedSound, ""LoopedSoundGain"" = :LoopedSoundGain,
346 ""TextureAnimation"" = :TextureAnimation, ""OmegaX"" = :OmegaX, ""OmegaY"" = :OmegaY, ""OmegaZ"" = :OmegaZ, ""CameraEyeOffsetX"" = :CameraEyeOffsetX,
347 ""CameraEyeOffsetY"" = :CameraEyeOffsetY, ""CameraEyeOffsetZ"" = :CameraEyeOffsetZ, ""CameraAtOffsetX"" = :CameraAtOffsetX,
348 ""CameraAtOffsetY"" = :CameraAtOffsetY, ""CameraAtOffsetZ"" = :CameraAtOffsetZ, ""ForceMouselook"" = :ForceMouselook,
349 ""ScriptAccessPin"" = :ScriptAccessPin, ""AllowedDrop"" = :AllowedDrop, ""DieAtEdge"" = :DieAtEdge, ""SalePrice"" = :SalePrice,
350 ""SaleType"" = :SaleType, ""ColorR"" = :ColorR, ""ColorG"" = :ColorG, ""ColorB"" = :ColorB, ""ColorA"" = :ColorA, ""ParticleSystem"" = :ParticleSystem,
351 ""ClickAction"" = :ClickAction, ""Material"" = :Material, ""CollisionSound"" = :CollisionSound, ""CollisionSoundVolume"" = :CollisionSoundVolume, ""PassTouches"" = :PassTouches,
352 ""LinkNumber"" = :LinkNumber, ""MediaURL"" = :MediaURL, ""DynAttrs"" = :DynAttrs,
353 ""PhysicsShapeType"" = :PhysicsShapeType, ""Density"" = :Density, ""GravityModifier"" = :GravityModifier, ""Friction"" = :Friction, ""Restitution"" = :Restitution
354 WHERE ""UUID"" = :UUID ;
355
356 INSERT INTO
357 prims (
358 ""UUID"", ""CreationDate"", ""Name"", ""Text"", ""Description"", ""SitName"", ""TouchName"", ""ObjectFlags"", ""OwnerMask"", ""NextOwnerMask"", ""GroupMask"",
359 ""EveryoneMask"", ""BaseMask"", ""PositionX"", ""PositionY"", ""PositionZ"", ""GroupPositionX"", ""GroupPositionY"", ""GroupPositionZ"", ""VelocityX"",
360 ""VelocityY"", ""VelocityZ"", ""AngularVelocityX"", ""AngularVelocityY"", ""AngularVelocityZ"", ""AccelerationX"", ""AccelerationY"", ""AccelerationZ"",
361 ""RotationX"", ""RotationY"", ""RotationZ"", ""RotationW"", ""SitTargetOffsetX"", ""SitTargetOffsetY"", ""SitTargetOffsetZ"", ""SitTargetOrientW"",
362 ""SitTargetOrientX"", ""SitTargetOrientY"", ""SitTargetOrientZ"", ""RegionUUID"", ""CreatorID"", ""OwnerID"", ""GroupID"", ""LastOwnerID"", ""SceneGroupID"",
363 ""PayPrice"", ""PayButton1"", ""PayButton2"", ""PayButton3"", ""PayButton4"", ""LoopedSound"", ""LoopedSoundGain"", ""TextureAnimation"", ""OmegaX"",
364 ""OmegaY"", ""OmegaZ"", ""CameraEyeOffsetX"", ""CameraEyeOffsetY"", ""CameraEyeOffsetZ"", ""CameraAtOffsetX"", ""CameraAtOffsetY"", ""CameraAtOffsetZ"",
365 ""ForceMouselook"", ""ScriptAccessPin"", ""AllowedDrop"", ""DieAtEdge"", ""SalePrice"", ""SaleType"", ""ColorR"", ""ColorG"", ""ColorB"", ""ColorA"",
366 ""ParticleSystem"", ""ClickAction"", ""Material"", ""CollisionSound"", ""CollisionSoundVolume"", ""PassTouches"", ""LinkNumber"", ""MediaURL"", ""DynAttrs"",
367 ""PhysicsShapeType"", ""Density"", ""GravityModifier"", ""Friction"", ""Restitution""
368 ) Select
369 :UUID, :CreationDate, :Name, :Text, :Description, :SitName, :TouchName, :ObjectFlags, :OwnerMask, :NextOwnerMask, :GroupMask,
370 :EveryoneMask, :BaseMask, :PositionX, :PositionY, :PositionZ, :GroupPositionX, :GroupPositionY, :GroupPositionZ, :VelocityX,
371 :VelocityY, :VelocityZ, :AngularVelocityX, :AngularVelocityY, :AngularVelocityZ, :AccelerationX, :AccelerationY, :AccelerationZ,
372 :RotationX, :RotationY, :RotationZ, :RotationW, :SitTargetOffsetX, :SitTargetOffsetY, :SitTargetOffsetZ, :SitTargetOrientW,
373 :SitTargetOrientX, :SitTargetOrientY, :SitTargetOrientZ, :RegionUUID, :CreatorID, :OwnerID, :GroupID, :LastOwnerID, :SceneGroupID,
374 :PayPrice, :PayButton1, :PayButton2, :PayButton3, :PayButton4, :LoopedSound, :LoopedSoundGain, :TextureAnimation, :OmegaX,
375 :OmegaY, :OmegaZ, :CameraEyeOffsetX, :CameraEyeOffsetY, :CameraEyeOffsetZ, :CameraAtOffsetX, :CameraAtOffsetY, :CameraAtOffsetZ,
376 :ForceMouselook, :ScriptAccessPin, :AllowedDrop, :DieAtEdge, :SalePrice, :SaleType, :ColorR, :ColorG, :ColorB, :ColorA,
377 :ParticleSystem, :ClickAction, :Material, :CollisionSound, :CollisionSoundVolume, :PassTouches, :LinkNumber, :MediaURL, :DynAttrs,
378 :PhysicsShapeType, :Density, :GravityModifier, :Friction, :Restitution
379 where not EXISTS (SELECT ""UUID"" FROM prims WHERE ""UUID"" = :UUID);
380 ";
381
382 //Set commandtext.
383 sqlCommand.CommandText = queryPrims;
384 //Add parameters
385 sqlCommand.Parameters.AddRange(CreatePrimParameters(sceneObjectPart, sceneGroupID, regionUUID));
386
387 //Execute the query. If it fails then error is trapped in calling function
388 sqlCommand.ExecuteNonQuery();
389 }
390
391 /// <summary>
392 /// Stores the scene object prim shapes.
393 /// </summary>
394 /// <param name="sceneObjectPart">The sceneobjectpart containing prim shape.</param>
395 /// <param name="sqlCommand">The SQL command with the transaction.</param>
396 /// <param name="sceneGroupID">The scenegroup UUID.</param>
397 /// <param name="regionUUID">The region UUID.</param>
398 private void StoreSceneObjectPrimShapes(SceneObjectPart sceneObjectPart, NpgsqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID)
399 {
400 //Big query to or insert or update primshapes
401
402 string queryPrimShapes = @"
403 UPDATE primshapes SET
404 ""Shape"" = :Shape, ""ScaleX"" = :ScaleX, ""ScaleY"" = :ScaleY, ""ScaleZ"" = :ScaleZ, ""PCode"" = :PCode, ""PathBegin"" = :PathBegin,
405 ""PathEnd"" = :PathEnd, ""PathScaleX"" = :PathScaleX, ""PathScaleY"" = :PathScaleY, ""PathShearX"" = :PathShearX, ""PathShearY"" = :PathShearY,
406 ""PathSkew"" = :PathSkew, ""PathCurve"" = :PathCurve, ""PathRadiusOffset"" = :PathRadiusOffset, ""PathRevolutions"" = :PathRevolutions,
407 ""PathTaperX"" = :PathTaperX, ""PathTaperY"" = :PathTaperY, ""PathTwist"" = :PathTwist, ""PathTwistBegin"" = :PathTwistBegin,
408 ""ProfileBegin"" = :ProfileBegin, ""ProfileEnd"" = :ProfileEnd, ""ProfileCurve"" = :ProfileCurve, ""ProfileHollow"" = :ProfileHollow,
409 ""Texture"" = :Texture, ""ExtraParams"" = :ExtraParams, ""State"" = :State, ""Media"" = :Media
410 WHERE ""UUID"" = :UUID ;
411
412 INSERT INTO
413 primshapes (
414 ""UUID"", ""Shape"", ""ScaleX"", ""ScaleY"", ""ScaleZ"", ""PCode"", ""PathBegin"", ""PathEnd"", ""PathScaleX"", ""PathScaleY"", ""PathShearX"", ""PathShearY"",
415 ""PathSkew"", ""PathCurve"", ""PathRadiusOffset"", ""PathRevolutions"", ""PathTaperX"", ""PathTaperY"", ""PathTwist"", ""PathTwistBegin"", ""ProfileBegin"",
416 ""ProfileEnd"", ""ProfileCurve"", ""ProfileHollow"", ""Texture"", ""ExtraParams"", ""State"", ""Media""
417 )
418 Select
419 :UUID, :Shape, :ScaleX, :ScaleY, :ScaleZ, :PCode, :PathBegin, :PathEnd, :PathScaleX, :PathScaleY, :PathShearX, :PathShearY,
420 :PathSkew, :PathCurve, :PathRadiusOffset, :PathRevolutions, :PathTaperX, :PathTaperY, :PathTwist, :PathTwistBegin, :ProfileBegin,
421 :ProfileEnd, :ProfileCurve, :ProfileHollow, :Texture, :ExtraParams, :State, :Media
422 where not EXISTS (SELECT ""UUID"" FROM primshapes WHERE ""UUID"" = :UUID);
423 ";
424
425 //Set commandtext.
426 sqlCommand.CommandText = queryPrimShapes;
427
428 //Add parameters
429 sqlCommand.Parameters.AddRange(CreatePrimShapeParameters(sceneObjectPart, sceneGroupID, regionUUID));
430
431 //Execute the query. If it fails then error is trapped in calling function
432 sqlCommand.ExecuteNonQuery();
433
434 }
435
436 /// <summary>
437 /// Removes a object from the database.
438 /// Meaning removing it from tables Prims, PrimShapes and PrimItems
439 /// </summary>
440 /// <param name="objectID">id of scenegroup</param>
441 /// <param name="regionUUID">regionUUID (is this used anyway</param>
442 public void RemoveObject(UUID objectID, UUID regionUUID)
443 {
444 //_Log.InfoFormat("[PGSQL]: Removing obj: {0} from region: {1}", objectID, regionUUID);
445
446 //Remove from prims and primsitem table
447 string sqlPrims = @"DELETE FROM PRIMS WHERE ""SceneGroupID"" = :objectID";
448 string sqlPrimItems = @"DELETE FROM PRIMITEMS WHERE ""primID"" in (SELECT ""UUID"" FROM PRIMS WHERE ""SceneGroupID"" = :objectID)";
449 string sqlPrimShapes = @"DELETE FROM PRIMSHAPES WHERE ""UUID"" in (SELECT ""UUID"" FROM PRIMS WHERE ""SceneGroupID"" = :objectID)";
450
451 lock (_Database)
452 {
453 //Using the non transaction mode.
454 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
455 using (NpgsqlCommand cmd = new NpgsqlCommand())
456 {
457 cmd.Connection = conn;
458 cmd.CommandText = sqlPrimShapes;
459 conn.Open();
460 cmd.Parameters.Add(_Database.CreateParameter("objectID", objectID));
461 cmd.ExecuteNonQuery();
462
463 cmd.CommandText = sqlPrimItems;
464 cmd.ExecuteNonQuery();
465
466 cmd.CommandText = sqlPrims;
467 cmd.ExecuteNonQuery();
468 }
469 }
470 }
471
472 /// <summary>
473 /// Store the inventory of a prim. Warning deletes everything first and then adds all again.
474 /// </summary>
475 /// <param name="primID"></param>
476 /// <param name="items"></param>
477 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
478 {
479 //_Log.InfoFormat("[REGION DB: Persisting Prim Inventory with prim ID {0}", primID);
480
481 //Statement from PGSQL section!
482 // For now, we're just going to crudely remove all the previous inventory items
483 // no matter whether they have changed or not, and replace them with the current set.
484
485 //Delete everything from PrimID
486 //TODO add index on PrimID in DB, if not already exist
487
488 string sql = @"delete from primitems where ""primID"" = :primID";
489 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
490 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
491 {
492 cmd.Parameters.Add(_Database.CreateParameter("primID", primID));
493 conn.Open();
494 cmd.ExecuteNonQuery();
495 }
496
497 sql =
498 @"INSERT INTO primitems (
499 ""itemID"",""primID"",""assetID"",""parentFolderID"",""invType"",""assetType"",""name"",""description"",""creationDate"",""creatorID"",""ownerID"",""lastOwnerID"",""groupID"",
500 ""nextPermissions"",""currentPermissions"",""basePermissions"",""everyonePermissions"",""groupPermissions"",""flags"")
501 VALUES (:itemID,:primID,:assetID,:parentFolderID,:invType,:assetType,:name,:description,:creationDate,:creatorID,:ownerID,
502 :lastOwnerID,:groupID,:nextPermissions,:currentPermissions,:basePermissions,:everyonePermissions,:groupPermissions,:flags)";
503
504 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
505 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
506 {
507 conn.Open();
508 foreach (TaskInventoryItem taskItem in items)
509 {
510 cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem));
511 cmd.ExecuteNonQuery();
512 cmd.Parameters.Clear();
513 }
514 }
515 }
516
517 #endregion
518
519 /// <summary>
520 /// Loads the terrain map.
521 /// </summary>
522 /// <param name="regionID">regionID.</param>
523 /// <returns></returns>
524 public double[,] LoadTerrain(UUID regionID)
525 {
526 double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
527 terrain.Initialize();
528
529 string sql = @"select ""RegionUUID"", ""Revision"", ""Heightfield"" from terrain
530 where ""RegionUUID"" = :RegionUUID order by ""Revision"" desc limit 1; ";
531
532 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
533 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
534 {
535 // PGSqlParameter param = new PGSqlParameter();
536 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
537 conn.Open();
538 using (NpgsqlDataReader reader = cmd.ExecuteReader())
539 {
540 int rev;
541 if (reader.Read())
542 {
543 MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
544 BinaryReader br = new BinaryReader(str);
545 for (int x = 0; x < (int)Constants.RegionSize; x++)
546 {
547 for (int y = 0; y < (int)Constants.RegionSize; y++)
548 {
549 terrain[x, y] = br.ReadDouble();
550 }
551 }
552 rev = (int)reader["Revision"];
553 }
554 else
555 {
556 _Log.Info("[REGION DB]: No terrain found for region");
557 return null;
558 }
559 _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
560 }
561 }
562
563 return terrain;
564 }
565
566 /// <summary>
567 /// Stores the terrain map to DB.
568 /// </summary>
569 /// <param name="terrain">terrain map data.</param>
570 /// <param name="regionID">regionID.</param>
571 public void StoreTerrain(double[,] terrain, UUID regionID)
572 {
573 int revision = Util.UnixTimeSinceEpoch();
574
575 //Delete old terrain map
576 string sql = @"delete from terrain where ""RegionUUID""=:RegionUUID";
577 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
578 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
579 {
580 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
581 conn.Open();
582 cmd.ExecuteNonQuery();
583 }
584
585 _Log.Info("[REGION DB]: Deleted terrain revision r " + revision);
586
587 sql = @"insert into terrain(""RegionUUID"", ""Revision"", ""Heightfield"") values(:RegionUUID, :Revision, :Heightfield)";
588
589 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
590 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
591 {
592 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
593 cmd.Parameters.Add(_Database.CreateParameter("Revision", revision));
594 cmd.Parameters.Add(_Database.CreateParameter("Heightfield", serializeTerrain(terrain)));
595 conn.Open();
596 cmd.ExecuteNonQuery();
597 }
598
599 _Log.Info("[REGION DB]: Stored terrain revision r " + revision);
600 }
601
602 /// <summary>
603 /// Loads all the land objects of a region.
604 /// </summary>
605 /// <param name="regionUUID">The region UUID.</param>
606 /// <returns></returns>
607 public List<LandData> LoadLandObjects(UUID regionUUID)
608 {
609 List<LandData> LandDataForRegion = new List<LandData>();
610
611 string sql = @"select * from land where ""RegionUUID"" = :RegionUUID";
612
613 //Retrieve all land data from region
614 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
615 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
616 {
617 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID));
618 conn.Open();
619 using (NpgsqlDataReader readerLandData = cmd.ExecuteReader())
620 {
621 while (readerLandData.Read())
622 {
623 LandDataForRegion.Add(BuildLandData(readerLandData));
624 }
625 }
626 }
627
628 //Retrieve all accesslist data for all landdata
629 foreach (LandData LandData in LandDataForRegion)
630 {
631 sql = @"select * from landaccesslist where ""LandUUID"" = :LandUUID";
632 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
633 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
634 {
635 cmd.Parameters.Add(_Database.CreateParameter("LandUUID", LandData.GlobalID));
636 conn.Open();
637 using (NpgsqlDataReader readerAccessList = cmd.ExecuteReader())
638 {
639 while (readerAccessList.Read())
640 {
641 LandData.ParcelAccessList.Add(BuildLandAccessData(readerAccessList));
642 }
643 }
644 }
645 }
646
647 //Return data
648 return LandDataForRegion;
649 }
650
651 /// <summary>
652 /// Stores land object with landaccess list.
653 /// </summary>
654 /// <param name="parcel">parcel data.</param>
655 public void StoreLandObject(ILandObject parcel)
656 {
657 //As this is only one record in land table I just delete all and then add a new record.
658 //As the delete landaccess is already in the pgsql code
659
660 //Delete old values
661 RemoveLandObject(parcel.LandData.GlobalID);
662
663 //Insert new values
664 string sql = @"INSERT INTO land
665 (""UUID"",""RegionUUID"",""LocalLandID"",""Bitmap"",""Name"",""Description"",""OwnerUUID"",""IsGroupOwned"",""Area"",""AuctionID"",""Category"",""ClaimDate"",""ClaimPrice"",
666 ""GroupUUID"",""SalePrice"",""LandStatus"",""LandFlags"",""LandingType"",""MediaAutoScale"",""MediaTextureUUID"",""MediaURL"",""MusicURL"",""PassHours"",""PassPrice"",
667 ""SnapshotUUID"",""UserLocationX"",""UserLocationY"",""UserLocationZ"",""UserLookAtX"",""UserLookAtY"",""UserLookAtZ"",""AuthbuyerID"",""OtherCleanTime"")
668 VALUES
669 (:UUID,:RegionUUID,:LocalLandID,:Bitmap,:Name,:Description,:OwnerUUID,:IsGroupOwned,:Area,:AuctionID,:Category,:ClaimDate,:ClaimPrice,
670 :GroupUUID,:SalePrice,:LandStatus,:LandFlags,:LandingType,:MediaAutoScale,:MediaTextureUUID,:MediaURL,:MusicURL,:PassHours,:PassPrice,
671 :SnapshotUUID,:UserLocationX,:UserLocationY,:UserLocationZ,:UserLookAtX,:UserLookAtY,:UserLookAtZ,:AuthbuyerID,:OtherCleanTime)";
672
673 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
674 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
675 {
676 cmd.Parameters.AddRange(CreateLandParameters(parcel.LandData, parcel.RegionUUID));
677 conn.Open();
678 cmd.ExecuteNonQuery();
679 }
680
681 sql = @"INSERT INTO landaccesslist (""LandUUID"",""AccessUUID"",""LandFlags"",""Expires"") VALUES (:LandUUID,:AccessUUID,:Flags,:Expires)";
682
683 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
684 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
685 {
686 conn.Open();
687 foreach (LandAccessEntry parcelAccessEntry in parcel.LandData.ParcelAccessList)
688 {
689 cmd.Parameters.AddRange(CreateLandAccessParameters(parcelAccessEntry, parcel.RegionUUID));
690
691 cmd.ExecuteNonQuery();
692 cmd.Parameters.Clear();
693 }
694 }
695 }
696
697 /// <summary>
698 /// Removes a land object from DB.
699 /// </summary>
700 /// <param name="globalID">UUID of landobject</param>
701 public void RemoveLandObject(UUID globalID)
702 {
703 string sql = @"delete from land where ""UUID""=:UUID";
704 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
705 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
706 {
707 cmd.Parameters.Add(_Database.CreateParameter("UUID", globalID));
708 conn.Open();
709 cmd.ExecuteNonQuery();
710 }
711 sql = @"delete from landaccesslist where ""LandUUID""=:UUID";
712 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
713 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
714 {
715 cmd.Parameters.Add(_Database.CreateParameter("UUID", globalID));
716 conn.Open();
717 cmd.ExecuteNonQuery();
718 }
719 }
720 public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
721 {
722 RegionLightShareData nWP = new RegionLightShareData();
723 nWP.OnSave += StoreRegionWindlightSettings;
724
725 string sql = @"select * from regionwindlight where ""region_id"" = :regionID";
726
727 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
728 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
729 {
730 cmd.Parameters.Add(_Database.CreateParameter("regionID", regionUUID.ToString() ));
731 conn.Open();
732 using (NpgsqlDataReader result = cmd.ExecuteReader())
733 {
734 if (!result.Read())
735 {
736 //No result, so store our default windlight profile and return it
737 nWP.regionID = regionUUID;
738 StoreRegionWindlightSettings(nWP);
739 return nWP;
740 }
741 else
742 {
743 nWP.regionID = DBGuid.FromDB(result["region_id"]);
744 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
745 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
746 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
747 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
748 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
749 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
750 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
751 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
752 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
753 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
754 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
755 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
756 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
757 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
758 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
759 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
760 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
761 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
762 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
763 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
764 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
765 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
766 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
767 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
768 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
769 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
770 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
771 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
772 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
773 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
774 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
775 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
776 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
777 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
778 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
779 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
780 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
781 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
782 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
783 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
784 nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
785 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
786 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
787 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
788 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
789 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
790 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
791 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
792 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
793 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
794 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
795 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
796 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
797 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
798 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
799 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
800 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
801 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
802 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
803 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
804 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
805 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
806 nWP.valid = true;
807 }
808 }
809 }
810 return nWP;
811 }
812
813 public void RemoveRegionWindlightSettings(UUID regionID)
814 {
815 string sql = @"delete from regionwindlight where ""region_id"" = :region_id";
816 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
817 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
818 {
819 conn.Open();
820 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionID.ToString()));
821 cmd.ExecuteNonQuery();
822 }
823 }
824
825 public void StoreRegionWindlightSettings(RegionLightShareData wl)
826 {
827 string sql = @"select count (region_id) from regionwindlight where ""region_id"" = :region_id ;";
828 bool exists = false;
829 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
830 {
831 conn.Open();
832 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
833 {
834 cmd.Parameters.Add(_Database.CreateParameter("region_id", wl.regionID.ToString() ));
835 exists = cmd.ExecuteNonQuery() > 0;
836 }
837 }
838 if (exists)
839 {
840 RemoveRegionWindlightSettings(wl.regionID);
841 }
842
843 // sql insert
844 sql = @"INSERT INTO regionwindlight
845 (region_id
846 ,water_color_r
847 ,water_color_g
848 ,water_color_b
849 ,water_fog_density_exponent
850 ,underwater_fog_modifier
851 ,reflection_wavelet_scale_1
852 ,reflection_wavelet_scale_2
853 ,reflection_wavelet_scale_3
854 ,fresnel_scale
855 ,fresnel_offset
856 ,refract_scale_above
857 ,refract_scale_below
858 ,blur_multiplier
859 ,big_wave_direction_x
860 ,big_wave_direction_y
861 ,little_wave_direction_x
862 ,little_wave_direction_y
863 ,normal_map_texture
864 ,horizon_r
865 ,horizon_g
866 ,horizon_b
867 ,horizon_i
868 ,haze_horizon
869 ,blue_density_r
870 ,blue_density_g
871 ,blue_density_b
872 ,blue_density_i
873 ,haze_density
874 ,density_multiplier
875 ,distance_multiplier
876 ,max_altitude
877 ,sun_moon_color_r
878 ,sun_moon_color_g
879 ,sun_moon_color_b
880 ,sun_moon_color_i
881 ,sun_moon_position
882 ,ambient_r
883 ,ambient_g
884 ,ambient_b
885 ,ambient_i
886 ,east_angle
887 ,sun_glow_focus
888 ,sun_glow_size
889 ,scene_gamma
890 ,star_brightness
891 ,cloud_color_r
892 ,cloud_color_g
893 ,cloud_color_b
894 ,cloud_color_i
895 ,cloud_x
896 ,cloud_y
897 ,cloud_density
898 ,cloud_coverage
899 ,cloud_scale
900 ,cloud_detail_x
901 ,cloud_detail_y
902 ,cloud_detail_density
903 ,cloud_scroll_x
904 ,cloud_scroll_x_lock
905 ,cloud_scroll_y
906 ,cloud_scroll_y_lock
907 ,draw_classic_clouds)
908 VALUES
909 (:region_id
910 ,:water_color_r
911 ,:water_color_g
912 ,:water_color_b
913 ,:water_fog_density_exponent
914 ,:underwater_fog_modifier
915 ,:reflection_wavelet_scale_1
916 ,:reflection_wavelet_scale_2
917 ,:reflection_wavelet_scale_3
918 ,:fresnel_scale
919 ,:fresnel_offset
920 ,:refract_scale_above
921 ,:refract_scale_below
922 ,:blur_multiplier
923 ,:big_wave_direction_x
924 ,:big_wave_direction_y
925 ,:little_wave_direction_x
926 ,:little_wave_direction_y
927 ,:normal_map_texture
928 ,:horizon_r
929 ,:horizon_g
930 ,:horizon_b
931 ,:horizon_i
932 ,:haze_horizon
933 ,:blue_density_r
934 ,:blue_density_g
935 ,:blue_density_b
936 ,:blue_density_i
937 ,:haze_density
938 ,:density_multiplier
939 ,:distance_multiplier
940 ,:max_altitude
941 ,:sun_moon_color_r
942 ,:sun_moon_color_g
943 ,:sun_moon_color_b
944 ,:sun_moon_color_i
945 ,:sun_moon_position
946 ,:ambient_r
947 ,:ambient_g
948 ,:ambient_b
949 ,:ambient_i
950 ,:east_angle
951 ,:sun_glow_focus
952 ,:sun_glow_size
953 ,:scene_gamma
954 ,:star_brightness
955 ,:cloud_color_r
956 ,:cloud_color_g
957 ,:cloud_color_b
958 ,:cloud_color_i
959 ,:cloud_x
960 ,:cloud_y
961 ,:cloud_density
962 ,:cloud_coverage
963 ,:cloud_scale
964 ,:cloud_detail_x
965 ,:cloud_detail_y
966 ,:cloud_detail_density
967 ,:cloud_scroll_x
968 ,:cloud_scroll_x_lock
969 ,:cloud_scroll_y
970 ,:cloud_scroll_y_lock
971 ,:draw_classic_clouds);";
972
973 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
974 {
975 conn.Open();
976 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
977 {
978 cmd.Parameters.Add(_Database.CreateParameter("region_id", wl.regionID));
979 cmd.Parameters.Add(_Database.CreateParameter("water_color_r", wl.waterColor.X));
980 cmd.Parameters.Add(_Database.CreateParameter("water_color_g", wl.waterColor.Y));
981 cmd.Parameters.Add(_Database.CreateParameter("water_color_b", wl.waterColor.Z));
982 cmd.Parameters.Add(_Database.CreateParameter("water_fog_density_exponent", wl.waterFogDensityExponent));
983 cmd.Parameters.Add(_Database.CreateParameter("underwater_fog_modifier", wl.underwaterFogModifier));
984 cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X));
985 cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y));
986 cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z));
987 cmd.Parameters.Add(_Database.CreateParameter("fresnel_scale", wl.fresnelScale));
988 cmd.Parameters.Add(_Database.CreateParameter("fresnel_offset", wl.fresnelOffset));
989 cmd.Parameters.Add(_Database.CreateParameter("refract_scale_above", wl.refractScaleAbove));
990 cmd.Parameters.Add(_Database.CreateParameter("refract_scale_below", wl.refractScaleBelow));
991 cmd.Parameters.Add(_Database.CreateParameter("blur_multiplier", wl.blurMultiplier));
992 cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_x", wl.bigWaveDirection.X));
993 cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_y", wl.bigWaveDirection.Y));
994 cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_x", wl.littleWaveDirection.X));
995 cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_y", wl.littleWaveDirection.Y));
996 cmd.Parameters.Add(_Database.CreateParameter("normal_map_texture", wl.normalMapTexture));
997 cmd.Parameters.Add(_Database.CreateParameter("horizon_r", wl.horizon.X));
998 cmd.Parameters.Add(_Database.CreateParameter("horizon_g", wl.horizon.Y));
999 cmd.Parameters.Add(_Database.CreateParameter("horizon_b", wl.horizon.Z));
1000 cmd.Parameters.Add(_Database.CreateParameter("horizon_i", wl.horizon.W));
1001 cmd.Parameters.Add(_Database.CreateParameter("haze_horizon", wl.hazeHorizon));
1002 cmd.Parameters.Add(_Database.CreateParameter("blue_density_r", wl.blueDensity.X));
1003 cmd.Parameters.Add(_Database.CreateParameter("blue_density_g", wl.blueDensity.Y));
1004 cmd.Parameters.Add(_Database.CreateParameter("blue_density_b", wl.blueDensity.Z));
1005 cmd.Parameters.Add(_Database.CreateParameter("blue_density_i", wl.blueDensity.W));
1006 cmd.Parameters.Add(_Database.CreateParameter("haze_density", wl.hazeDensity));
1007 cmd.Parameters.Add(_Database.CreateParameter("density_multiplier", wl.densityMultiplier));
1008 cmd.Parameters.Add(_Database.CreateParameter("distance_multiplier", wl.distanceMultiplier));
1009 cmd.Parameters.Add(_Database.CreateParameter("max_altitude", wl.maxAltitude));
1010 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_r", wl.sunMoonColor.X));
1011 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_g", wl.sunMoonColor.Y));
1012 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_b", wl.sunMoonColor.Z));
1013 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_i", wl.sunMoonColor.W));
1014 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_position", wl.sunMoonPosition));
1015 cmd.Parameters.Add(_Database.CreateParameter("ambient_r", wl.ambient.X));
1016 cmd.Parameters.Add(_Database.CreateParameter("ambient_g", wl.ambient.Y));
1017 cmd.Parameters.Add(_Database.CreateParameter("ambient_b", wl.ambient.Z));
1018 cmd.Parameters.Add(_Database.CreateParameter("ambient_i", wl.ambient.W));
1019 cmd.Parameters.Add(_Database.CreateParameter("east_angle", wl.eastAngle));
1020 cmd.Parameters.Add(_Database.CreateParameter("sun_glow_focus", wl.sunGlowFocus));
1021 cmd.Parameters.Add(_Database.CreateParameter("sun_glow_size", wl.sunGlowSize));
1022 cmd.Parameters.Add(_Database.CreateParameter("scene_gamma", wl.sceneGamma));
1023 cmd.Parameters.Add(_Database.CreateParameter("star_brightness", wl.starBrightness));
1024 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_r", wl.cloudColor.X));
1025 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_g", wl.cloudColor.Y));
1026 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_b", wl.cloudColor.Z));
1027 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_i", wl.cloudColor.W));
1028 cmd.Parameters.Add(_Database.CreateParameter("cloud_x", wl.cloudXYDensity.X));
1029 cmd.Parameters.Add(_Database.CreateParameter("cloud_y", wl.cloudXYDensity.Y));
1030 cmd.Parameters.Add(_Database.CreateParameter("cloud_density", wl.cloudXYDensity.Z));
1031 cmd.Parameters.Add(_Database.CreateParameter("cloud_coverage", wl.cloudCoverage));
1032 cmd.Parameters.Add(_Database.CreateParameter("cloud_scale", wl.cloudScale));
1033 cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_x", wl.cloudDetailXYDensity.X));
1034 cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_y", wl.cloudDetailXYDensity.Y));
1035 cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_density", wl.cloudDetailXYDensity.Z));
1036 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x", wl.cloudScrollX));
1037 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x_lock", wl.cloudScrollXLock));
1038 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y", wl.cloudScrollY));
1039 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y_lock", wl.cloudScrollYLock));
1040 cmd.Parameters.Add(_Database.CreateParameter("draw_classic_clouds", wl.drawClassicClouds));
1041
1042 cmd.ExecuteNonQuery();
1043 }
1044 }
1045 #region update
1046 // }
1047 // else
1048 // {
1049 // // sql update
1050 // sql = @"UPDATE [OpenSim].[dbo].[regionwindlight]
1051 // SET [region_id] = @region_id
1052 // ,[water_color_r] = @water_color_r
1053 // ,[water_color_g] = @water_color_g
1054 // ,[water_color_b] = @water_color_b
1055 // ,[water_fog_density_exponent] = @water_fog_density_exponent
1056 // ,[underwater_fog_modifier] = @underwater_fog_modifier
1057 // ,[reflection_wavelet_scale_1] = @reflection_wavelet_scale_1
1058 // ,[reflection_wavelet_scale_2] = @reflection_wavelet_scale_2
1059 // ,[reflection_wavelet_scale_3] = @reflection_wavelet_scale_3
1060 // ,[fresnel_scale] = @fresnel_scale
1061 // ,[fresnel_offset] = @fresnel_offset
1062 // ,[refract_scale_above] = @refract_scale_above
1063 // ,[refract_scale_below] = @refract_scale_below
1064 // ,[blur_multiplier] = @blur_multiplier
1065 // ,[big_wave_direction_x] = @big_wave_direction_x
1066 // ,[big_wave_direction_y] = @big_wave_direction_y
1067 // ,[little_wave_direction_x] = @little_wave_direction_x
1068 // ,[little_wave_direction_y] = @little_wave_direction_y
1069 // ,[normal_map_texture] = @normal_map_texture
1070 // ,[horizon_r] = @horizon_r
1071 // ,[horizon_g] = @horizon_g
1072 // ,[horizon_b] = @horizon_b
1073 // ,[horizon_i] = @horizon_i
1074 // ,[haze_horizon] = @haze_horizon
1075 // ,[blue_density_r] = @blue_density_r
1076 // ,[blue_density_g] = @blue_density_g
1077 // ,[blue_density_b] = @blue_density_b
1078 // ,[blue_density_i] = @blue_density_i
1079 // ,[haze_density] = @haze_density
1080 // ,[density_multiplier] = @density_multiplier
1081 // ,[distance_multiplier] = @distance_multiplier
1082 // ,[max_altitude] = @max_altitude
1083 // ,[sun_moon_color_r] = @sun_moon_color_r
1084 // ,[sun_moon_color_g] = @sun_moon_color_g
1085 // ,[sun_moon_color_b] = @sun_moon_color_b
1086 // ,[sun_moon_color_i] = @sun_moon_color_i
1087 // ,[sun_moon_position] = @sun_moon_position
1088 // ,[ambient_r] = @ambient_r
1089 // ,[ambient_g] = @ambient_g
1090 // ,[ambient_b] = @ambient_b
1091 // ,[ambient_i] = @ambient_i
1092 // ,[east_angle] = @east_angle
1093 // ,[sun_glow_focus] = @sun_glow_focus
1094 // ,[sun_glow_size] = @sun_glow_size
1095 // ,[scene_gamma] = @scene_gamma
1096 // ,[star_brightness] = @star_brightness
1097 // ,[cloud_color_r] = @cloud_color_r
1098 // ,[cloud_color_g] = @cloud_color_g
1099 // ,[cloud_color_b] = @cloud_color_b
1100 // ,[cloud_color_i] = @cloud_color_i
1101 // ,[cloud_x] = @cloud_x
1102 // ,[cloud_y] = @cloud_y
1103 // ,[cloud_density] = @cloud_density
1104 // ,[cloud_coverage] = @cloud_coverage
1105 // ,[cloud_scale] = @cloud_scale
1106 // ,[cloud_detail_x] = @cloud_detail_x
1107 // ,[cloud_detail_y] = @cloud_detail_y
1108 // ,[cloud_detail_density] = @cloud_detail_density
1109 // ,[cloud_scroll_x] = @cloud_scroll_x
1110 // ,[cloud_scroll_x_lock] = @cloud_scroll_x_lock
1111 // ,[cloud_scroll_y] = @cloud_scroll_y
1112 // ,[cloud_scroll_y_lock] = @cloud_scroll_y_lock
1113 // ,[draw_classic_clouds] = @draw_classic_clouds
1114 // WHERE region_id = @region_id";
1115 // using (SqlConnection conn = new SqlConnection(m_connectionString))
1116 // {
1117 // conn.Open();
1118 // using (SqlCommand cmd = new SqlCommand(sql, conn))
1119 // {
1120 // cmd.Parameters.AddWithValue("region_id", wl.regionID);
1121 // cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
1122 // cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
1123 // cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
1124 // cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
1125 // cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
1126 // cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
1127 // cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
1128 // cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
1129 // cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
1130 // cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
1131 // cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
1132 // cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
1133 // cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
1134 // cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
1135 // cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
1136 // cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
1137 // cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
1138 // cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
1139 // cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
1140 // cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
1141 // cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
1142 // cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
1143 // cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
1144 // cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
1145 // cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
1146 // cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
1147 // cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
1148 // cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
1149 // cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
1150 // cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
1151 // cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
1152 // cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
1153 // cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
1154 // cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
1155 // cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
1156 // cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
1157 // cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
1158 // cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
1159 // cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
1160 // cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
1161 // cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
1162 // cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
1163 // cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
1164 // cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
1165 // cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
1166 // cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
1167 // cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
1168 // cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
1169 // cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
1170 // cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
1171 // cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
1172 // cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
1173 // cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
1174 // cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
1175 // cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
1176 // cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
1177 // cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
1178 // cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
1179 // cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
1180 // cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
1181 // cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
1182 // cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
1183
1184 // cmd.ExecuteNonQuery();
1185 // }
1186 // }
1187 // }
1188 #endregion
1189 }
1190
1191 #region Environment Settings
1192 public string LoadRegionEnvironmentSettings(UUID regionUUID)
1193 {
1194 string sql = "select * from regionenvironment where region_id = :region_id";
1195 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1196 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1197 {
1198 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1199 conn.Open();
1200 using (NpgsqlDataReader result = cmd.ExecuteReader())
1201 {
1202 if (!result.Read())
1203 {
1204 return String.Empty;
1205 }
1206 else
1207 {
1208 return Convert.ToString(result["llsd_settings"]);
1209 }
1210 }
1211 }
1212 }
1213
1214 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
1215 {
1216 {
1217 string sql = "DELETE FROM regionenvironment WHERE region_id = :region_id ;";
1218
1219 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1220 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1221 {
1222 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1223 conn.Open();
1224 cmd.ExecuteNonQuery();
1225 }
1226
1227 sql = "INSERT INTO regionenvironment (region_id, llsd_settings) VALUES (:region_id, :llsd_settings) ;";
1228
1229 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1230 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1231 {
1232 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1233 cmd.Parameters.Add(_Database.CreateParameter("llsd_settings", settings));
1234
1235 conn.Open();
1236 cmd.ExecuteNonQuery();
1237 }
1238 }
1239 }
1240
1241 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
1242 {
1243 string sql = "delete from regionenvironment where region_id = :region_id ;";
1244 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1245 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1246 {
1247 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1248
1249 conn.Open();
1250 cmd.ExecuteNonQuery();
1251 }
1252 }
1253 #endregion
1254
1255 /// <summary>
1256 /// Loads the settings of a region.
1257 /// </summary>
1258 /// <param name="regionUUID">The region UUID.</param>
1259 /// <returns></returns>
1260 public RegionSettings LoadRegionSettings(UUID regionUUID)
1261 {
1262 string sql = @"select * from regionsettings where ""regionUUID"" = :regionUUID";
1263 RegionSettings regionSettings;
1264 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1265 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1266 {
1267 cmd.Parameters.Add(_Database.CreateParameter("regionUUID", regionUUID));
1268 conn.Open();
1269 using (NpgsqlDataReader reader = cmd.ExecuteReader())
1270 {
1271 if (reader.Read())
1272 {
1273 regionSettings = BuildRegionSettings(reader);
1274 regionSettings.OnSave += StoreRegionSettings;
1275
1276 return regionSettings;
1277 }
1278 }
1279 }
1280
1281 //If we reach this point then there are new region settings for that region
1282 regionSettings = new RegionSettings();
1283 regionSettings.RegionUUID = regionUUID;
1284 regionSettings.OnSave += StoreRegionSettings;
1285
1286 //Store new values
1287 StoreNewRegionSettings(regionSettings);
1288
1289 LoadSpawnPoints(regionSettings);
1290
1291 return regionSettings;
1292 }
1293
1294 /// <summary>
1295 /// Store region settings, need to check if the check is really necesary. If we can make something for creating new region.
1296 /// </summary>
1297 /// <param name="regionSettings">region settings.</param>
1298 public void StoreRegionSettings(RegionSettings regionSettings)
1299 {
1300 //Little check if regionUUID already exist in DB
1301 string regionUUID;
1302 string sql = @"SELECT ""regionUUID"" FROM regionsettings WHERE ""regionUUID"" = :regionUUID";
1303 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1304 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1305 {
1306 cmd.Parameters.Add(_Database.CreateParameter("regionUUID", regionSettings.RegionUUID));
1307 conn.Open();
1308 regionUUID = cmd.ExecuteScalar().ToString();
1309 }
1310
1311 if (string.IsNullOrEmpty(regionUUID))
1312 {
1313 StoreNewRegionSettings(regionSettings);
1314 }
1315 else
1316 {
1317 //This method only updates region settings!!! First call LoadRegionSettings to create new region settings in DB
1318 sql =
1319 @"UPDATE regionsettings SET block_terraform = :block_terraform ,block_fly = :block_fly ,allow_damage = :allow_damage
1320,restrict_pushing = :restrict_pushing ,allow_land_resell = :allow_land_resell ,allow_land_join_divide = :allow_land_join_divide
1321,block_show_in_search = :block_show_in_search ,agent_limit = :agent_limit ,object_bonus = :object_bonus ,maturity = :maturity
1322,disable_scripts = :disable_scripts ,disable_collisions = :disable_collisions ,disable_physics = :disable_physics
1323,terrain_texture_1 = :terrain_texture_1 ,terrain_texture_2 = :terrain_texture_2 ,terrain_texture_3 = :terrain_texture_3
1324,terrain_texture_4 = :terrain_texture_4 ,elevation_1_nw = :elevation_1_nw ,elevation_2_nw = :elevation_2_nw
1325,elevation_1_ne = :elevation_1_ne ,elevation_2_ne = :elevation_2_ne ,elevation_1_se = :elevation_1_se ,elevation_2_se = :elevation_2_se
1326,elevation_1_sw = :elevation_1_sw ,elevation_2_sw = :elevation_2_sw ,water_height = :water_height ,terrain_raise_limit = :terrain_raise_limit
1327,terrain_lower_limit = :terrain_lower_limit ,use_estate_sun = :use_estate_sun ,fixed_sun = :fixed_sun ,sun_position = :sun_position
1328,covenant = :covenant ,covenant_datetime = :covenant_datetime, sunvectorx = :sunvectorx, sunvectory = :sunvectory, sunvectorz = :sunvectorz,
1329""Sandbox"" = :Sandbox, loaded_creation_datetime = :loaded_creation_datetime, loaded_creation_id = :loaded_creation_id, ""map_tile_ID"" = :TerrainImageID,
1330""TelehubObject"" = :telehubobject, ""parcel_tile_ID"" = :ParcelImageID
1331 WHERE ""regionUUID"" = :regionUUID";
1332
1333 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1334 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1335 {
1336 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
1337 conn.Open();
1338 cmd.ExecuteNonQuery();
1339 }
1340 }
1341 SaveSpawnPoints(regionSettings);
1342 }
1343
1344 public void Shutdown()
1345 {
1346 //Not used??
1347 }
1348
1349 #region Private Methods
1350
1351 /// <summary>
1352 /// Serializes the terrain data for storage in DB.
1353 /// </summary>
1354 /// <param name="val">terrain data</param>
1355 /// <returns></returns>
1356 private static Array serializeTerrain(double[,] val)
1357 {
1358 MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) * sizeof(double));
1359 BinaryWriter bw = new BinaryWriter(str);
1360
1361 // TODO: COMPATIBILITY - Add byte-order conversions
1362 for (int x = 0; x < (int)Constants.RegionSize; x++)
1363 for (int y = 0; y < (int)Constants.RegionSize; y++)
1364 {
1365 double height = val[x, y];
1366 if (height == 0.0)
1367 height = double.Epsilon;
1368
1369 bw.Write(height);
1370 }
1371
1372 return str.ToArray();
1373 }
1374
1375 /// <summary>
1376 /// Stores new regionsettings.
1377 /// </summary>
1378 /// <param name="regionSettings">The region settings.</param>
1379 private void StoreNewRegionSettings(RegionSettings regionSettings)
1380 {
1381 string sql = @"INSERT INTO regionsettings
1382 (""regionUUID"",block_terraform,block_fly,allow_damage,restrict_pushing,allow_land_resell,allow_land_join_divide,
1383 block_show_in_search,agent_limit,object_bonus,maturity,disable_scripts,disable_collisions,disable_physics,
1384 terrain_texture_1,terrain_texture_2,terrain_texture_3,terrain_texture_4,elevation_1_nw,elevation_2_nw,elevation_1_ne,
1385 elevation_2_ne,elevation_1_se,elevation_2_se,elevation_1_sw,elevation_2_sw,water_height,terrain_raise_limit,
1386 terrain_lower_limit,use_estate_sun,fixed_sun,sun_position,covenant,covenant_datetime,sunvectorx, sunvectory, sunvectorz,
1387 ""Sandbox"", loaded_creation_datetime, loaded_creation_id
1388 )
1389 VALUES
1390 (:regionUUID,:block_terraform,:block_fly,:allow_damage,:restrict_pushing,:allow_land_resell,:allow_land_join_divide,
1391 :block_show_in_search,:agent_limit,:object_bonus,:maturity,:disable_scripts,:disable_collisions,:disable_physics,
1392 :terrain_texture_1,:terrain_texture_2,:terrain_texture_3,:terrain_texture_4,:elevation_1_nw,:elevation_2_nw,:elevation_1_ne,
1393 :elevation_2_ne,:elevation_1_se,:elevation_2_se,:elevation_1_sw,:elevation_2_sw,:water_height,:terrain_raise_limit,
1394 :terrain_lower_limit,:use_estate_sun,:fixed_sun,:sun_position,:covenant, :covenant_datetime, :sunvectorx,:sunvectory,
1395 :sunvectorz, :Sandbox, :loaded_creation_datetime, :loaded_creation_id )";
1396
1397 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1398 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1399 {
1400 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
1401 conn.Open();
1402 cmd.ExecuteNonQuery();
1403 }
1404 }
1405
1406 #region Private DataRecord conversion methods
1407
1408 /// <summary>
1409 /// Builds the region settings from a datarecod.
1410 /// </summary>
1411 /// <param name="row">datarecord with regionsettings.</param>
1412 /// <returns></returns>
1413 private static RegionSettings BuildRegionSettings(IDataRecord row)
1414 {
1415 //TODO change this is some more generic code so we doesnt have to change it every time a new field is added?
1416 RegionSettings newSettings = new RegionSettings();
1417
1418 newSettings.RegionUUID = new UUID((Guid)row["regionUUID"]);
1419 newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]);
1420 newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]);
1421 newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]);
1422 newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]);
1423 newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]);
1424 newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]);
1425 newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]);
1426 newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]);
1427 newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]);
1428 newSettings.Maturity = Convert.ToInt32(row["maturity"]);
1429 newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]);
1430 newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]);
1431 newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]);
1432 newSettings.TerrainTexture1 = new UUID((Guid)row["terrain_texture_1"]);
1433 newSettings.TerrainTexture2 = new UUID((Guid)row["terrain_texture_2"]);
1434 newSettings.TerrainTexture3 = new UUID((Guid)row["terrain_texture_3"]);
1435 newSettings.TerrainTexture4 = new UUID((Guid)row["terrain_texture_4"]);
1436 newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]);
1437 newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]);
1438 newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]);
1439 newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]);
1440 newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]);
1441 newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]);
1442 newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]);
1443 newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]);
1444 newSettings.WaterHeight = Convert.ToDouble(row["water_height"]);
1445 newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
1446 newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
1447 newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
1448 newSettings.Sandbox = Convert.ToBoolean(row["Sandbox"]);
1449 newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]);
1450 newSettings.SunPosition = Convert.ToDouble(row["sun_position"]);
1451 newSettings.SunVector = new Vector3(
1452 Convert.ToSingle(row["sunvectorx"]),
1453 Convert.ToSingle(row["sunvectory"]),
1454 Convert.ToSingle(row["sunvectorz"])
1455 );
1456 newSettings.Covenant = new UUID((Guid)row["covenant"]);
1457 newSettings.CovenantChangedDateTime = Convert.ToInt32(row["covenant_datetime"]);
1458 newSettings.LoadedCreationDateTime = Convert.ToInt32(row["loaded_creation_datetime"]);
1459
1460 if (row["loaded_creation_id"] is DBNull)
1461 newSettings.LoadedCreationID = "";
1462 else
1463 newSettings.LoadedCreationID = (String)row["loaded_creation_id"];
1464
1465 newSettings.TerrainImageID = new UUID((string)row["map_tile_ID"]);
1466 newSettings.ParcelImageID = new UUID((Guid)row["parcel_tile_ID"]);
1467 newSettings.TelehubObject = new UUID((Guid)row["TelehubObject"]);
1468
1469 return newSettings;
1470 }
1471
1472 /// <summary>
1473 /// Builds the land data from a datarecord.
1474 /// </summary>
1475 /// <param name="row">datarecord with land data</param>
1476 /// <returns></returns>
1477 private static LandData BuildLandData(IDataRecord row)
1478 {
1479 LandData newData = new LandData();
1480
1481 newData.GlobalID = new UUID((Guid)row["UUID"]);
1482 newData.LocalID = Convert.ToInt32(row["LocalLandID"]);
1483
1484 // Bitmap is a byte[512]
1485 newData.Bitmap = (Byte[])row["Bitmap"];
1486
1487 newData.Name = (string)row["Name"];
1488 newData.Description = (string)row["Description"];
1489 newData.OwnerID = new UUID((Guid)row["OwnerUUID"]);
1490 newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]);
1491 newData.Area = Convert.ToInt32(row["Area"]);
1492 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
1493 newData.Category = (ParcelCategory)Convert.ToInt32(row["Category"]);
1494 //Enum libsecondlife.Parcel.ParcelCategory
1495 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
1496 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
1497 newData.GroupID = new UUID((Guid)row["GroupUUID"]);
1498 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
1499 newData.Status = (ParcelStatus)Convert.ToInt32(row["LandStatus"]);
1500 //Enum. libsecondlife.Parcel.ParcelStatus
1501 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
1502 newData.LandingType = Convert.ToByte(row["LandingType"]);
1503 newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]);
1504 newData.MediaID = new UUID((Guid)row["MediaTextureUUID"]);
1505 newData.MediaURL = (string)row["MediaURL"];
1506 newData.MusicURL = (string)row["MusicURL"];
1507 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1508 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1509
1510 // UUID authedbuyer;
1511 // UUID snapshotID;
1512 //
1513 // if (UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer))
1514 // newData.AuthBuyerID = authedbuyer;
1515 //
1516 // if (UUID.TryParse((string)row["SnapshotUUID"], out snapshotID))
1517 // newData.SnapshotID = snapshotID;
1518 newData.AuthBuyerID = new UUID((Guid)row["AuthBuyerID"]);
1519 newData.SnapshotID = new UUID((Guid)row["SnapshotUUID"]);
1520
1521 newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]);
1522
1523 try
1524 {
1525 newData.UserLocation =
1526 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1527 Convert.ToSingle(row["UserLocationZ"]));
1528 newData.UserLookAt =
1529 new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
1530 Convert.ToSingle(row["UserLookAtZ"]));
1531 }
1532 catch (InvalidCastException)
1533 {
1534 newData.UserLocation = Vector3.Zero;
1535 newData.UserLookAt = Vector3.Zero;
1536 _Log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name);
1537 }
1538
1539 newData.ParcelAccessList = new List<LandAccessEntry>();
1540 newData.MediaDescription = (string)row["MediaDescription"];
1541 newData.MediaType = (string)row["MediaType"];
1542 newData.MediaWidth = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[0]);
1543 newData.MediaHeight = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[1]);
1544 newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]);
1545 newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]);
1546 newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]);
1547
1548 return newData;
1549 }
1550
1551 /// <summary>
1552 /// Builds the landaccess data from a data record.
1553 /// </summary>
1554 /// <param name="row">datarecord with landaccess data</param>
1555 /// <returns></returns>
1556 private static LandAccessEntry BuildLandAccessData(IDataRecord row)
1557 {
1558 LandAccessEntry entry = new LandAccessEntry();
1559 entry.AgentID = new UUID((Guid)row["AccessUUID"]);
1560 entry.Flags = (AccessList)Convert.ToInt32(row["Flags"]);
1561 entry.Expires = Convert.ToInt32(row["Expires"]);
1562 return entry;
1563 }
1564
1565 /// <summary>
1566 /// Builds the prim from a datarecord.
1567 /// </summary>
1568 /// <param name="primRow">datarecord</param>
1569 /// <returns></returns>
1570 private static SceneObjectPart BuildPrim(IDataRecord primRow)
1571 {
1572 SceneObjectPart prim = new SceneObjectPart();
1573
1574 prim.UUID = new UUID((Guid)primRow["UUID"]);
1575 // explicit conversion of integers is required, which sort
1576 // of sucks. No idea if there is a shortcut here or not.
1577 prim.CreationDate = Convert.ToInt32(primRow["CreationDate"]);
1578 prim.Name = (string)primRow["Name"];
1579 // various text fields
1580 prim.Text = (string)primRow["Text"];
1581 prim.Color = Color.FromArgb(Convert.ToInt32(primRow["ColorA"]),
1582 Convert.ToInt32(primRow["ColorR"]),
1583 Convert.ToInt32(primRow["ColorG"]),
1584 Convert.ToInt32(primRow["ColorB"]));
1585 prim.Description = (string)primRow["Description"];
1586 prim.SitName = (string)primRow["SitName"];
1587 prim.TouchName = (string)primRow["TouchName"];
1588 // permissions
1589 prim.Flags = (PrimFlags)Convert.ToUInt32(primRow["ObjectFlags"]);
1590 //prim.creatorID = new UUID((Guid)primRow["creatorID"]);
1591 prim.CreatorIdentification = (string)primRow["CreatorID"].ToString();
1592 prim.OwnerID = new UUID((Guid)primRow["OwnerID"]);
1593 prim.GroupID = new UUID((Guid)primRow["GroupID"]);
1594 prim.LastOwnerID = new UUID((Guid)primRow["LastOwnerID"]);
1595 prim.OwnerMask = Convert.ToUInt32(primRow["OwnerMask"]);
1596 prim.NextOwnerMask = Convert.ToUInt32(primRow["NextOwnerMask"]);
1597 prim.GroupMask = Convert.ToUInt32(primRow["GroupMask"]);
1598 prim.EveryoneMask = Convert.ToUInt32(primRow["EveryoneMask"]);
1599 prim.BaseMask = Convert.ToUInt32(primRow["BaseMask"]);
1600 // vectors
1601 prim.OffsetPosition = new Vector3(
1602 Convert.ToSingle(primRow["PositionX"]),
1603 Convert.ToSingle(primRow["PositionY"]),
1604 Convert.ToSingle(primRow["PositionZ"]));
1605
1606 prim.GroupPosition = new Vector3(
1607 Convert.ToSingle(primRow["GroupPositionX"]),
1608 Convert.ToSingle(primRow["GroupPositionY"]),
1609 Convert.ToSingle(primRow["GroupPositionZ"]));
1610
1611 prim.Velocity = new Vector3(
1612 Convert.ToSingle(primRow["VelocityX"]),
1613 Convert.ToSingle(primRow["VelocityY"]),
1614 Convert.ToSingle(primRow["VelocityZ"]));
1615
1616 prim.AngularVelocity = new Vector3(
1617 Convert.ToSingle(primRow["AngularVelocityX"]),
1618 Convert.ToSingle(primRow["AngularVelocityY"]),
1619 Convert.ToSingle(primRow["AngularVelocityZ"]));
1620
1621 prim.Acceleration = new Vector3(
1622 Convert.ToSingle(primRow["AccelerationX"]),
1623 Convert.ToSingle(primRow["AccelerationY"]),
1624 Convert.ToSingle(primRow["AccelerationZ"]));
1625
1626 // quaternions
1627 prim.RotationOffset = new Quaternion(
1628 Convert.ToSingle(primRow["RotationX"]),
1629 Convert.ToSingle(primRow["RotationY"]),
1630 Convert.ToSingle(primRow["RotationZ"]),
1631 Convert.ToSingle(primRow["RotationW"]));
1632
1633 prim.SitTargetPositionLL = new Vector3(
1634 Convert.ToSingle(primRow["SitTargetOffsetX"]),
1635 Convert.ToSingle(primRow["SitTargetOffsetY"]),
1636 Convert.ToSingle(primRow["SitTargetOffsetZ"]));
1637
1638 prim.SitTargetOrientationLL = new Quaternion(
1639 Convert.ToSingle(primRow["SitTargetOrientX"]),
1640 Convert.ToSingle(primRow["SitTargetOrientY"]),
1641 Convert.ToSingle(primRow["SitTargetOrientZ"]),
1642 Convert.ToSingle(primRow["SitTargetOrientW"]));
1643
1644 prim.PayPrice[0] = Convert.ToInt32(primRow["PayPrice"]);
1645 prim.PayPrice[1] = Convert.ToInt32(primRow["PayButton1"]);
1646 prim.PayPrice[2] = Convert.ToInt32(primRow["PayButton2"]);
1647 prim.PayPrice[3] = Convert.ToInt32(primRow["PayButton3"]);
1648 prim.PayPrice[4] = Convert.ToInt32(primRow["PayButton4"]);
1649
1650 prim.Sound = new UUID((Guid)primRow["LoopedSound"]);
1651 prim.SoundGain = Convert.ToSingle(primRow["LoopedSoundGain"]);
1652 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1653
1654 if (!(primRow["TextureAnimation"] is DBNull))
1655 prim.TextureAnimation = (Byte[])primRow["TextureAnimation"];
1656 if (!(primRow["ParticleSystem"] is DBNull))
1657 prim.ParticleSystem = (Byte[])primRow["ParticleSystem"];
1658
1659 prim.AngularVelocity = new Vector3(
1660 Convert.ToSingle(primRow["OmegaX"]),
1661 Convert.ToSingle(primRow["OmegaY"]),
1662 Convert.ToSingle(primRow["OmegaZ"]));
1663
1664 prim.SetCameraEyeOffset(new Vector3(
1665 Convert.ToSingle(primRow["CameraEyeOffsetX"]),
1666 Convert.ToSingle(primRow["CameraEyeOffsetY"]),
1667 Convert.ToSingle(primRow["CameraEyeOffsetZ"])
1668 ));
1669
1670 prim.SetCameraAtOffset(new Vector3(
1671 Convert.ToSingle(primRow["CameraAtOffsetX"]),
1672 Convert.ToSingle(primRow["CameraAtOffsetY"]),
1673 Convert.ToSingle(primRow["CameraAtOffsetZ"])
1674 ));
1675
1676 if (Convert.ToInt16(primRow["ForceMouselook"]) != 0)
1677 prim.SetForceMouselook(true);
1678
1679 prim.ScriptAccessPin = Convert.ToInt32(primRow["ScriptAccessPin"]);
1680
1681 if (Convert.ToInt16(primRow["AllowedDrop"]) != 0)
1682 prim.AllowedDrop = true;
1683
1684 if (Convert.ToInt16(primRow["DieAtEdge"]) != 0)
1685 prim.DIE_AT_EDGE = true;
1686
1687 prim.SalePrice = Convert.ToInt32(primRow["SalePrice"]);
1688 prim.ObjectSaleType = Convert.ToByte(primRow["SaleType"]);
1689
1690 prim.Material = Convert.ToByte(primRow["Material"]);
1691
1692 if (!(primRow["ClickAction"] is DBNull))
1693 prim.ClickAction = Convert.ToByte(primRow["ClickAction"]);
1694
1695 prim.CollisionSound = new UUID((Guid)primRow["CollisionSound"]);
1696 prim.CollisionSoundVolume = Convert.ToSingle(primRow["CollisionSoundVolume"]);
1697
1698 prim.PassTouches = (bool)primRow["PassTouches"];
1699
1700 if (!(primRow["MediaURL"] is System.DBNull))
1701 prim.MediaUrl = (string)primRow["MediaURL"];
1702
1703 if (!(primRow["DynAttrs"] is System.DBNull) && (string)primRow["DynAttrs"] != "")
1704 prim.DynAttrs = DAMap.FromXml((string)primRow["DynAttrs"]);
1705 else
1706 prim.DynAttrs = new DAMap();
1707
1708 prim.PhysicsShapeType = Convert.ToByte(primRow["PhysicsShapeType"]);
1709 prim.Density = Convert.ToSingle(primRow["Density"]);
1710 prim.GravityModifier = Convert.ToSingle(primRow["GravityModifier"]);
1711 prim.Friction = Convert.ToSingle(primRow["Friction"]);
1712 prim.Restitution = Convert.ToSingle(primRow["Restitution"]);
1713
1714 return prim;
1715 }
1716
1717 /// <summary>
1718 /// Builds the prim shape from a datarecord.
1719 /// </summary>
1720 /// <param name="shapeRow">The row.</param>
1721 /// <returns></returns>
1722 private static PrimitiveBaseShape BuildShape(IDataRecord shapeRow)
1723 {
1724 PrimitiveBaseShape baseShape = new PrimitiveBaseShape();
1725
1726 baseShape.Scale = new Vector3(
1727 (float)Convert.ToDouble(shapeRow["ScaleX"]),
1728 (float)Convert.ToDouble(shapeRow["ScaleY"]),
1729 (float)Convert.ToDouble(shapeRow["ScaleZ"]));
1730
1731 // paths
1732 baseShape.PCode = Convert.ToByte(shapeRow["PCode"]);
1733 baseShape.PathBegin = Convert.ToUInt16(shapeRow["PathBegin"]);
1734 baseShape.PathEnd = Convert.ToUInt16(shapeRow["PathEnd"]);
1735 baseShape.PathScaleX = Convert.ToByte(shapeRow["PathScaleX"]);
1736 baseShape.PathScaleY = Convert.ToByte(shapeRow["PathScaleY"]);
1737 baseShape.PathShearX = Convert.ToByte(shapeRow["PathShearX"]);
1738 baseShape.PathShearY = Convert.ToByte(shapeRow["PathShearY"]);
1739 baseShape.PathSkew = Convert.ToSByte(shapeRow["PathSkew"]);
1740 baseShape.PathCurve = Convert.ToByte(shapeRow["PathCurve"]);
1741 baseShape.PathRadiusOffset = Convert.ToSByte(shapeRow["PathRadiusOffset"]);
1742 baseShape.PathRevolutions = Convert.ToByte(shapeRow["PathRevolutions"]);
1743 baseShape.PathTaperX = Convert.ToSByte(shapeRow["PathTaperX"]);
1744 baseShape.PathTaperY = Convert.ToSByte(shapeRow["PathTaperY"]);
1745 baseShape.PathTwist = Convert.ToSByte(shapeRow["PathTwist"]);
1746 baseShape.PathTwistBegin = Convert.ToSByte(shapeRow["PathTwistBegin"]);
1747 // profile
1748 baseShape.ProfileBegin = Convert.ToUInt16(shapeRow["ProfileBegin"]);
1749 baseShape.ProfileEnd = Convert.ToUInt16(shapeRow["ProfileEnd"]);
1750 baseShape.ProfileCurve = Convert.ToByte(shapeRow["ProfileCurve"]);
1751 baseShape.ProfileHollow = Convert.ToUInt16(shapeRow["ProfileHollow"]);
1752
1753 byte[] textureEntry = (byte[])shapeRow["Texture"];
1754 baseShape.TextureEntry = textureEntry;
1755
1756 baseShape.ExtraParams = (byte[])shapeRow["ExtraParams"];
1757
1758 try
1759 {
1760 baseShape.State = Convert.ToByte(shapeRow["State"]);
1761 }
1762 catch (InvalidCastException)
1763 {
1764 }
1765
1766 if (!(shapeRow["Media"] is System.DBNull))
1767 {
1768 baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
1769 }
1770
1771 return baseShape;
1772 }
1773
1774 /// <summary>
1775 /// Build a prim inventory item from the persisted data.
1776 /// </summary>
1777 /// <param name="inventoryRow"></param>
1778 /// <returns></returns>
1779 private static TaskInventoryItem BuildItem(IDataRecord inventoryRow)
1780 {
1781 TaskInventoryItem taskItem = new TaskInventoryItem();
1782
1783 taskItem.ItemID = new UUID((Guid)inventoryRow["itemID"]);
1784 taskItem.ParentPartID = new UUID((Guid)inventoryRow["primID"]);
1785 taskItem.AssetID = new UUID((Guid)inventoryRow["assetID"]);
1786 taskItem.ParentID = new UUID((Guid)inventoryRow["parentFolderID"]);
1787
1788 taskItem.InvType = Convert.ToInt32(inventoryRow["invType"]);
1789 taskItem.Type = Convert.ToInt32(inventoryRow["assetType"]);
1790
1791 taskItem.Name = (string)inventoryRow["name"];
1792 taskItem.Description = (string)inventoryRow["description"];
1793 taskItem.CreationDate = Convert.ToUInt32(inventoryRow["creationDate"]);
1794 //taskItem.creatorID = new UUID((Guid)inventoryRow["creatorID"]);
1795 taskItem.CreatorIdentification = (string)inventoryRow["creatorID"].ToString();
1796 taskItem.OwnerID = new UUID((Guid)inventoryRow["ownerID"]);
1797 taskItem.LastOwnerID = new UUID((Guid)inventoryRow["lastOwnerID"]);
1798 taskItem.GroupID = new UUID((Guid)inventoryRow["groupID"]);
1799
1800 taskItem.NextPermissions = Convert.ToUInt32(inventoryRow["nextPermissions"]);
1801 taskItem.CurrentPermissions = Convert.ToUInt32(inventoryRow["currentPermissions"]);
1802 taskItem.BasePermissions = Convert.ToUInt32(inventoryRow["basePermissions"]);
1803 taskItem.EveryonePermissions = Convert.ToUInt32(inventoryRow["everyonePermissions"]);
1804 taskItem.GroupPermissions = Convert.ToUInt32(inventoryRow["groupPermissions"]);
1805 taskItem.Flags = Convert.ToUInt32(inventoryRow["flags"]);
1806
1807 return taskItem;
1808 }
1809
1810 #endregion
1811
1812 #region Create parameters methods
1813
1814 /// <summary>
1815 /// Creates the prim inventory parameters.
1816 /// </summary>
1817 /// <param name="taskItem">item in inventory.</param>
1818 /// <returns></returns>
1819 private NpgsqlParameter[] CreatePrimInventoryParameters(TaskInventoryItem taskItem)
1820 {
1821 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1822
1823 parameters.Add(_Database.CreateParameter("itemID", taskItem.ItemID));
1824 parameters.Add(_Database.CreateParameter("primID", taskItem.ParentPartID));
1825 parameters.Add(_Database.CreateParameter("assetID", taskItem.AssetID));
1826 parameters.Add(_Database.CreateParameter("parentFolderID", taskItem.ParentID));
1827 parameters.Add(_Database.CreateParameter("invType", taskItem.InvType));
1828 parameters.Add(_Database.CreateParameter("assetType", taskItem.Type));
1829
1830 parameters.Add(_Database.CreateParameter("name", taskItem.Name));
1831 parameters.Add(_Database.CreateParameter("description", taskItem.Description));
1832 parameters.Add(_Database.CreateParameter("creationDate", taskItem.CreationDate));
1833 parameters.Add(_Database.CreateParameter("creatorID", taskItem.CreatorID));
1834 parameters.Add(_Database.CreateParameter("ownerID", taskItem.OwnerID));
1835 parameters.Add(_Database.CreateParameter("lastOwnerID", taskItem.LastOwnerID));
1836 parameters.Add(_Database.CreateParameter("groupID", taskItem.GroupID));
1837 parameters.Add(_Database.CreateParameter("nextPermissions", taskItem.NextPermissions));
1838 parameters.Add(_Database.CreateParameter("currentPermissions", taskItem.CurrentPermissions));
1839 parameters.Add(_Database.CreateParameter("basePermissions", taskItem.BasePermissions));
1840 parameters.Add(_Database.CreateParameter("everyonePermissions", taskItem.EveryonePermissions));
1841 parameters.Add(_Database.CreateParameter("groupPermissions", taskItem.GroupPermissions));
1842 parameters.Add(_Database.CreateParameter("flags", taskItem.Flags));
1843
1844 return parameters.ToArray();
1845 }
1846
1847 /// <summary>
1848 /// Creates the region setting parameters.
1849 /// </summary>
1850 /// <param name="settings">regionsettings.</param>
1851 /// <returns></returns>
1852 private NpgsqlParameter[] CreateRegionSettingParameters(RegionSettings settings)
1853 {
1854 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1855
1856 parameters.Add(_Database.CreateParameter("regionUUID", settings.RegionUUID));
1857 parameters.Add(_Database.CreateParameter("block_terraform", settings.BlockTerraform));
1858 parameters.Add(_Database.CreateParameter("block_fly", settings.BlockFly));
1859 parameters.Add(_Database.CreateParameter("allow_damage", settings.AllowDamage));
1860 parameters.Add(_Database.CreateParameter("restrict_pushing", settings.RestrictPushing));
1861 parameters.Add(_Database.CreateParameter("allow_land_resell", settings.AllowLandResell));
1862 parameters.Add(_Database.CreateParameter("allow_land_join_divide", settings.AllowLandJoinDivide));
1863 parameters.Add(_Database.CreateParameter("block_show_in_search", settings.BlockShowInSearch));
1864 parameters.Add(_Database.CreateParameter("agent_limit", settings.AgentLimit));
1865 parameters.Add(_Database.CreateParameter("object_bonus", settings.ObjectBonus));
1866 parameters.Add(_Database.CreateParameter("maturity", settings.Maturity));
1867 parameters.Add(_Database.CreateParameter("disable_scripts", settings.DisableScripts));
1868 parameters.Add(_Database.CreateParameter("disable_collisions", settings.DisableCollisions));
1869 parameters.Add(_Database.CreateParameter("disable_physics", settings.DisablePhysics));
1870 parameters.Add(_Database.CreateParameter("terrain_texture_1", settings.TerrainTexture1));
1871 parameters.Add(_Database.CreateParameter("terrain_texture_2", settings.TerrainTexture2));
1872 parameters.Add(_Database.CreateParameter("terrain_texture_3", settings.TerrainTexture3));
1873 parameters.Add(_Database.CreateParameter("terrain_texture_4", settings.TerrainTexture4));
1874 parameters.Add(_Database.CreateParameter("elevation_1_nw", settings.Elevation1NW));
1875 parameters.Add(_Database.CreateParameter("elevation_2_nw", settings.Elevation2NW));
1876 parameters.Add(_Database.CreateParameter("elevation_1_ne", settings.Elevation1NE));
1877 parameters.Add(_Database.CreateParameter("elevation_2_ne", settings.Elevation2NE));
1878 parameters.Add(_Database.CreateParameter("elevation_1_se", settings.Elevation1SE));
1879 parameters.Add(_Database.CreateParameter("elevation_2_se", settings.Elevation2SE));
1880 parameters.Add(_Database.CreateParameter("elevation_1_sw", settings.Elevation1SW));
1881 parameters.Add(_Database.CreateParameter("elevation_2_sw", settings.Elevation2SW));
1882 parameters.Add(_Database.CreateParameter("water_height", settings.WaterHeight));
1883 parameters.Add(_Database.CreateParameter("terrain_raise_limit", settings.TerrainRaiseLimit));
1884 parameters.Add(_Database.CreateParameter("terrain_lower_limit", settings.TerrainLowerLimit));
1885 parameters.Add(_Database.CreateParameter("use_estate_sun", settings.UseEstateSun));
1886 parameters.Add(_Database.CreateParameter("Sandbox", settings.Sandbox));
1887 parameters.Add(_Database.CreateParameter("fixed_sun", settings.FixedSun));
1888 parameters.Add(_Database.CreateParameter("sun_position", settings.SunPosition));
1889 parameters.Add(_Database.CreateParameter("sunvectorx", settings.SunVector.X));
1890 parameters.Add(_Database.CreateParameter("sunvectory", settings.SunVector.Y));
1891 parameters.Add(_Database.CreateParameter("sunvectorz", settings.SunVector.Z));
1892 parameters.Add(_Database.CreateParameter("covenant", settings.Covenant));
1893 parameters.Add(_Database.CreateParameter("covenant_datetime", settings.CovenantChangedDateTime));
1894 parameters.Add(_Database.CreateParameter("Loaded_Creation_DateTime", settings.LoadedCreationDateTime));
1895 parameters.Add(_Database.CreateParameter("Loaded_Creation_ID", settings.LoadedCreationID));
1896 parameters.Add(_Database.CreateParameter("TerrainImageID", settings.TerrainImageID));
1897 parameters.Add(_Database.CreateParameter("ParcelImageID", settings.ParcelImageID));
1898 parameters.Add(_Database.CreateParameter("TelehubObject", settings.TelehubObject));
1899
1900 return parameters.ToArray();
1901 }
1902
1903 /// <summary>
1904 /// Creates the land parameters.
1905 /// </summary>
1906 /// <param name="land">land parameters.</param>
1907 /// <param name="regionUUID">region UUID.</param>
1908 /// <returns></returns>
1909 private NpgsqlParameter[] CreateLandParameters(LandData land, UUID regionUUID)
1910 {
1911 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1912
1913 parameters.Add(_Database.CreateParameter("UUID", land.GlobalID));
1914 parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID));
1915 parameters.Add(_Database.CreateParameter("LocalLandID", land.LocalID));
1916
1917 // Bitmap is a byte[512]
1918 parameters.Add(_Database.CreateParameter("Bitmap", land.Bitmap));
1919
1920 parameters.Add(_Database.CreateParameter("Name", land.Name));
1921 parameters.Add(_Database.CreateParameter("Description", land.Description));
1922 parameters.Add(_Database.CreateParameter("OwnerUUID", land.OwnerID));
1923 parameters.Add(_Database.CreateParameter("IsGroupOwned", land.IsGroupOwned));
1924 parameters.Add(_Database.CreateParameter("Area", land.Area));
1925 parameters.Add(_Database.CreateParameter("AuctionID", land.AuctionID)); //Unemplemented
1926 parameters.Add(_Database.CreateParameter("Category", (int)land.Category)); //Enum libsecondlife.Parcel.ParcelCategory
1927 parameters.Add(_Database.CreateParameter("ClaimDate", land.ClaimDate));
1928 parameters.Add(_Database.CreateParameter("ClaimPrice", land.ClaimPrice));
1929 parameters.Add(_Database.CreateParameter("GroupUUID", land.GroupID));
1930 parameters.Add(_Database.CreateParameter("SalePrice", land.SalePrice));
1931 parameters.Add(_Database.CreateParameter("LandStatus", (int)land.Status)); //Enum. libsecondlife.Parcel.ParcelStatus
1932 parameters.Add(_Database.CreateParameter("LandFlags", land.Flags));
1933 parameters.Add(_Database.CreateParameter("LandingType", Convert.ToInt32( land.LandingType) ));
1934 parameters.Add(_Database.CreateParameter("MediaAutoScale", Convert.ToInt32( land.MediaAutoScale )));
1935 parameters.Add(_Database.CreateParameter("MediaTextureUUID", land.MediaID));
1936 parameters.Add(_Database.CreateParameter("MediaURL", land.MediaURL));
1937 parameters.Add(_Database.CreateParameter("MusicURL", land.MusicURL));
1938 parameters.Add(_Database.CreateParameter("PassHours", land.PassHours));
1939 parameters.Add(_Database.CreateParameter("PassPrice", land.PassPrice));
1940 parameters.Add(_Database.CreateParameter("SnapshotUUID", land.SnapshotID));
1941 parameters.Add(_Database.CreateParameter("UserLocationX", land.UserLocation.X));
1942 parameters.Add(_Database.CreateParameter("UserLocationY", land.UserLocation.Y));
1943 parameters.Add(_Database.CreateParameter("UserLocationZ", land.UserLocation.Z));
1944 parameters.Add(_Database.CreateParameter("UserLookAtX", land.UserLookAt.X));
1945 parameters.Add(_Database.CreateParameter("UserLookAtY", land.UserLookAt.Y));
1946 parameters.Add(_Database.CreateParameter("UserLookAtZ", land.UserLookAt.Z));
1947 parameters.Add(_Database.CreateParameter("AuthBuyerID", land.AuthBuyerID));
1948 parameters.Add(_Database.CreateParameter("OtherCleanTime", land.OtherCleanTime));
1949
1950 return parameters.ToArray();
1951 }
1952
1953 /// <summary>
1954 /// Creates the land access parameters.
1955 /// </summary>
1956 /// <param name="parcelAccessEntry">parcel access entry.</param>
1957 /// <param name="parcelID">parcel ID.</param>
1958 /// <returns></returns>
1959 private NpgsqlParameter[] CreateLandAccessParameters(LandAccessEntry parcelAccessEntry, UUID parcelID)
1960 {
1961 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1962
1963 parameters.Add(_Database.CreateParameter("LandUUID", parcelID));
1964 parameters.Add(_Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID));
1965 parameters.Add(_Database.CreateParameter("Flags", parcelAccessEntry.Flags));
1966 parameters.Add(_Database.CreateParameter("Expires", parcelAccessEntry.Expires));
1967
1968 return parameters.ToArray();
1969 }
1970
1971 /// <summary>
1972 /// Creates the prim parameters for storing in DB.
1973 /// </summary>
1974 /// <param name="prim">Basic data of SceneObjectpart prim.</param>
1975 /// <param name="sceneGroupID">The scenegroup ID.</param>
1976 /// <param name="regionUUID">The region ID.</param>
1977 /// <returns></returns>
1978 private NpgsqlParameter[] CreatePrimParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1979 {
1980 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1981
1982 parameters.Add(_Database.CreateParameter("UUID", prim.UUID));
1983 parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID));
1984 parameters.Add(_Database.CreateParameter("CreationDate", prim.CreationDate));
1985 parameters.Add(_Database.CreateParameter("Name", prim.Name));
1986 parameters.Add(_Database.CreateParameter("SceneGroupID", sceneGroupID));
1987 // the UUID of the root part for this SceneObjectGroup
1988 // various text fields
1989 parameters.Add(_Database.CreateParameter("Text", prim.Text));
1990 parameters.Add(_Database.CreateParameter("ColorR", prim.Color.R));
1991 parameters.Add(_Database.CreateParameter("ColorG", prim.Color.G));
1992 parameters.Add(_Database.CreateParameter("ColorB", prim.Color.B));
1993 parameters.Add(_Database.CreateParameter("ColorA", prim.Color.A));
1994 parameters.Add(_Database.CreateParameter("Description", prim.Description));
1995 parameters.Add(_Database.CreateParameter("SitName", prim.SitName));
1996 parameters.Add(_Database.CreateParameter("TouchName", prim.TouchName));
1997 // permissions
1998 parameters.Add(_Database.CreateParameter("ObjectFlags", (uint)prim.Flags));
1999 parameters.Add(_Database.CreateParameter("CreatorID", prim.CreatorID));
2000 parameters.Add(_Database.CreateParameter("OwnerID", prim.OwnerID));
2001 parameters.Add(_Database.CreateParameter("GroupID", prim.GroupID));
2002 parameters.Add(_Database.CreateParameter("LastOwnerID", prim.LastOwnerID));
2003 parameters.Add(_Database.CreateParameter("OwnerMask", prim.OwnerMask));
2004 parameters.Add(_Database.CreateParameter("NextOwnerMask", prim.NextOwnerMask));
2005 parameters.Add(_Database.CreateParameter("GroupMask", prim.GroupMask));
2006 parameters.Add(_Database.CreateParameter("EveryoneMask", prim.EveryoneMask));
2007 parameters.Add(_Database.CreateParameter("BaseMask", prim.BaseMask));
2008 // vectors
2009 parameters.Add(_Database.CreateParameter("PositionX", prim.OffsetPosition.X));
2010 parameters.Add(_Database.CreateParameter("PositionY", prim.OffsetPosition.Y));
2011 parameters.Add(_Database.CreateParameter("PositionZ", prim.OffsetPosition.Z));
2012 parameters.Add(_Database.CreateParameter("GroupPositionX", prim.GroupPosition.X));
2013 parameters.Add(_Database.CreateParameter("GroupPositionY", prim.GroupPosition.Y));
2014 parameters.Add(_Database.CreateParameter("GroupPositionZ", prim.GroupPosition.Z));
2015 parameters.Add(_Database.CreateParameter("VelocityX", prim.Velocity.X));
2016 parameters.Add(_Database.CreateParameter("VelocityY", prim.Velocity.Y));
2017 parameters.Add(_Database.CreateParameter("VelocityZ", prim.Velocity.Z));
2018 parameters.Add(_Database.CreateParameter("AngularVelocityX", prim.AngularVelocity.X));
2019 parameters.Add(_Database.CreateParameter("AngularVelocityY", prim.AngularVelocity.Y));
2020 parameters.Add(_Database.CreateParameter("AngularVelocityZ", prim.AngularVelocity.Z));
2021 parameters.Add(_Database.CreateParameter("AccelerationX", prim.Acceleration.X));
2022 parameters.Add(_Database.CreateParameter("AccelerationY", prim.Acceleration.Y));
2023 parameters.Add(_Database.CreateParameter("AccelerationZ", prim.Acceleration.Z));
2024 // quaternions
2025 parameters.Add(_Database.CreateParameter("RotationX", prim.RotationOffset.X));
2026 parameters.Add(_Database.CreateParameter("RotationY", prim.RotationOffset.Y));
2027 parameters.Add(_Database.CreateParameter("RotationZ", prim.RotationOffset.Z));
2028 parameters.Add(_Database.CreateParameter("RotationW", prim.RotationOffset.W));
2029
2030 // Sit target
2031 Vector3 sitTargetPos = prim.SitTargetPositionLL;
2032 parameters.Add(_Database.CreateParameter("SitTargetOffsetX", sitTargetPos.X));
2033 parameters.Add(_Database.CreateParameter("SitTargetOffsetY", sitTargetPos.Y));
2034 parameters.Add(_Database.CreateParameter("SitTargetOffsetZ", sitTargetPos.Z));
2035
2036 Quaternion sitTargetOrient = prim.SitTargetOrientationLL;
2037 parameters.Add(_Database.CreateParameter("SitTargetOrientW", sitTargetOrient.W));
2038 parameters.Add(_Database.CreateParameter("SitTargetOrientX", sitTargetOrient.X));
2039 parameters.Add(_Database.CreateParameter("SitTargetOrientY", sitTargetOrient.Y));
2040 parameters.Add(_Database.CreateParameter("SitTargetOrientZ", sitTargetOrient.Z));
2041
2042 parameters.Add(_Database.CreateParameter("PayPrice", prim.PayPrice[0]));
2043 parameters.Add(_Database.CreateParameter("PayButton1", prim.PayPrice[1]));
2044 parameters.Add(_Database.CreateParameter("PayButton2", prim.PayPrice[2]));
2045 parameters.Add(_Database.CreateParameter("PayButton3", prim.PayPrice[3]));
2046 parameters.Add(_Database.CreateParameter("PayButton4", prim.PayPrice[4]));
2047
2048 if ((prim.SoundFlags & 1) != 0) // Looped
2049 {
2050 parameters.Add(_Database.CreateParameter("LoopedSound", prim.Sound));
2051 parameters.Add(_Database.CreateParameter("LoopedSoundGain", prim.SoundGain));
2052 }
2053 else
2054 {
2055 parameters.Add(_Database.CreateParameter("LoopedSound", UUID.Zero));
2056 parameters.Add(_Database.CreateParameter("LoopedSoundGain", 0.0f));
2057 }
2058
2059 parameters.Add(_Database.CreateParameter("TextureAnimation", prim.TextureAnimation));
2060 parameters.Add(_Database.CreateParameter("ParticleSystem", prim.ParticleSystem));
2061
2062 parameters.Add(_Database.CreateParameter("OmegaX", prim.AngularVelocity.X));
2063 parameters.Add(_Database.CreateParameter("OmegaY", prim.AngularVelocity.Y));
2064 parameters.Add(_Database.CreateParameter("OmegaZ", prim.AngularVelocity.Z));
2065
2066 parameters.Add(_Database.CreateParameter("CameraEyeOffsetX", prim.GetCameraEyeOffset().X));
2067 parameters.Add(_Database.CreateParameter("CameraEyeOffsetY", prim.GetCameraEyeOffset().Y));
2068 parameters.Add(_Database.CreateParameter("CameraEyeOffsetZ", prim.GetCameraEyeOffset().Z));
2069
2070 parameters.Add(_Database.CreateParameter("CameraAtOffsetX", prim.GetCameraAtOffset().X));
2071 parameters.Add(_Database.CreateParameter("CameraAtOffsetY", prim.GetCameraAtOffset().Y));
2072 parameters.Add(_Database.CreateParameter("CameraAtOffsetZ", prim.GetCameraAtOffset().Z));
2073
2074 if (prim.GetForceMouselook())
2075 parameters.Add(_Database.CreateParameter("ForceMouselook", 1));
2076 else
2077 parameters.Add(_Database.CreateParameter("ForceMouselook", 0));
2078
2079 parameters.Add(_Database.CreateParameter("ScriptAccessPin", prim.ScriptAccessPin));
2080
2081 if (prim.AllowedDrop)
2082 parameters.Add(_Database.CreateParameter("AllowedDrop", 1));
2083 else
2084 parameters.Add(_Database.CreateParameter("AllowedDrop", 0));
2085
2086 if (prim.DIE_AT_EDGE)
2087 parameters.Add(_Database.CreateParameter("DieAtEdge", 1));
2088 else
2089 parameters.Add(_Database.CreateParameter("DieAtEdge", 0));
2090
2091 parameters.Add(_Database.CreateParameter("SalePrice", prim.SalePrice));
2092 parameters.Add(_Database.CreateParameter("SaleType", prim.ObjectSaleType));
2093
2094 byte clickAction = prim.ClickAction;
2095 parameters.Add(_Database.CreateParameter("ClickAction", clickAction));
2096
2097 parameters.Add(_Database.CreateParameter("Material", prim.Material));
2098
2099 parameters.Add(_Database.CreateParameter("CollisionSound", prim.CollisionSound));
2100 parameters.Add(_Database.CreateParameter("CollisionSoundVolume", prim.CollisionSoundVolume));
2101
2102 parameters.Add(_Database.CreateParameter("PassTouches", prim.PassTouches));
2103
2104 parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
2105 parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
2106
2107 if (prim.DynAttrs.CountNamespaces > 0)
2108 parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
2109 else
2110 parameters.Add(_Database.CreateParameter("DynAttrs", null));
2111
2112 parameters.Add(_Database.CreateParameter("PhysicsShapeType", prim.PhysicsShapeType));
2113 parameters.Add(_Database.CreateParameter("Density", (double)prim.Density));
2114 parameters.Add(_Database.CreateParameter("GravityModifier", (double)prim.GravityModifier));
2115 parameters.Add(_Database.CreateParameter("Friction", (double)prim.Friction));
2116 parameters.Add(_Database.CreateParameter("Restitution", (double)prim.Restitution));
2117
2118 return parameters.ToArray();
2119 }
2120
2121 /// <summary>
2122 /// Creates the primshape parameters for stroing in DB.
2123 /// </summary>
2124 /// <param name="prim">Basic data of SceneObjectpart prim.</param>
2125 /// <param name="sceneGroupID">The scene group ID.</param>
2126 /// <param name="regionUUID">The region UUID.</param>
2127 /// <returns></returns>
2128 private NpgsqlParameter[] CreatePrimShapeParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
2129 {
2130 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
2131
2132 PrimitiveBaseShape s = prim.Shape;
2133 parameters.Add(_Database.CreateParameter("UUID", prim.UUID));
2134 // shape is an enum
2135 parameters.Add(_Database.CreateParameter("Shape", 0));
2136 // vectors
2137 parameters.Add(_Database.CreateParameter("ScaleX", s.Scale.X));
2138 parameters.Add(_Database.CreateParameter("ScaleY", s.Scale.Y));
2139 parameters.Add(_Database.CreateParameter("ScaleZ", s.Scale.Z));
2140 // paths
2141 parameters.Add(_Database.CreateParameter("PCode", s.PCode));
2142 parameters.Add(_Database.CreateParameter("PathBegin", s.PathBegin));
2143 parameters.Add(_Database.CreateParameter("PathEnd", s.PathEnd));
2144 parameters.Add(_Database.CreateParameter("PathScaleX", s.PathScaleX));
2145 parameters.Add(_Database.CreateParameter("PathScaleY", s.PathScaleY));
2146 parameters.Add(_Database.CreateParameter("PathShearX", s.PathShearX));
2147 parameters.Add(_Database.CreateParameter("PathShearY", s.PathShearY));
2148 parameters.Add(_Database.CreateParameter("PathSkew", s.PathSkew));
2149 parameters.Add(_Database.CreateParameter("PathCurve", s.PathCurve));
2150 parameters.Add(_Database.CreateParameter("PathRadiusOffset", s.PathRadiusOffset));
2151 parameters.Add(_Database.CreateParameter("PathRevolutions", s.PathRevolutions));
2152 parameters.Add(_Database.CreateParameter("PathTaperX", s.PathTaperX));
2153 parameters.Add(_Database.CreateParameter("PathTaperY", s.PathTaperY));
2154 parameters.Add(_Database.CreateParameter("PathTwist", s.PathTwist));
2155 parameters.Add(_Database.CreateParameter("PathTwistBegin", s.PathTwistBegin));
2156 // profile
2157 parameters.Add(_Database.CreateParameter("ProfileBegin", s.ProfileBegin));
2158 parameters.Add(_Database.CreateParameter("ProfileEnd", s.ProfileEnd));
2159 parameters.Add(_Database.CreateParameter("ProfileCurve", s.ProfileCurve));
2160 parameters.Add(_Database.CreateParameter("ProfileHollow", s.ProfileHollow));
2161 parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
2162 parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
2163 parameters.Add(_Database.CreateParameter("State", s.State));
2164
2165 if (null == s.Media)
2166 {
2167 parameters.Add(_Database.CreateParameter("Media", DBNull.Value));
2168 }
2169 else
2170 {
2171 parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml()));
2172 }
2173
2174 return parameters.ToArray();
2175 }
2176
2177 #endregion
2178
2179 #endregion
2180
2181 private void LoadSpawnPoints(RegionSettings rs)
2182 {
2183 rs.ClearSpawnPoints();
2184
2185 string sql = @"SELECT ""Yaw"", ""Pitch"", ""Distance"" FROM spawn_points WHERE ""RegionUUID"" = :RegionUUID";
2186
2187 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
2188 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
2189 {
2190 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", rs.RegionUUID));
2191 conn.Open();
2192 using (NpgsqlDataReader reader = cmd.ExecuteReader())
2193 {
2194 if (reader.Read())
2195 {
2196 SpawnPoint sp = new SpawnPoint();
2197
2198 sp.Yaw = (float)reader["Yaw"];
2199 sp.Pitch = (float)reader["Pitch"];
2200 sp.Distance = (float)reader["Distance"];
2201
2202 rs.AddSpawnPoint(sp);
2203 }
2204 }
2205 }
2206 }
2207
2208 private void SaveSpawnPoints(RegionSettings rs)
2209 {
2210 string sql = @"DELETE FROM spawn_points WHERE ""RegionUUID"" = :RegionUUID";
2211 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
2212 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
2213 {
2214 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", rs.RegionUUID));
2215 conn.Open();
2216 cmd.ExecuteNonQuery();
2217 }
2218 foreach (SpawnPoint p in rs.SpawnPoints())
2219 {
2220 sql = @"INSERT INTO spawn_points (""RegionUUID"", ""Yaw"", ""Pitch"", ""Distance"") VALUES (:RegionUUID, :Yaw, :Pitch, :Distance)";
2221 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
2222 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
2223 {
2224 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", rs.RegionUUID));
2225 cmd.Parameters.Add(_Database.CreateParameter("Yaw", p.Yaw));
2226 cmd.Parameters.Add(_Database.CreateParameter("Pitch", p.Pitch));
2227 cmd.Parameters.Add(_Database.CreateParameter("Distance", p.Distance));
2228 conn.Open();
2229 cmd.ExecuteNonQuery();
2230 }
2231 }
2232 }
2233
2234 public UUID[] GetObjectIDs(UUID regionID)
2235 {
2236 return new UUID[0];
2237 }
2238
2239 public void SaveExtra(UUID regionID, string name, string value)
2240 {
2241 }
2242
2243 public void RemoveExtra(UUID regionID, string name)
2244 {
2245 }
2246
2247 public Dictionary<string, string> GetExtra(UUID regionID)
2248 {
2249 return null;
2250 }
2251 }
2252}
diff --git a/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs b/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
new file mode 100644
index 0000000..a5868fe
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
@@ -0,0 +1,330 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Data;
32using OpenMetaverse;
33using OpenSim.Framework;
34using System.Text;
35using Npgsql;
36using log4net;
37using System.Reflection;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLUserAccountData : PGSQLGenericTableHandler<UserAccountData>,IUserAccountData
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45
46 public PGSQLUserAccountData(string connectionString, string realm) :
47 base(connectionString, realm, "UserAccount")
48 {
49 }
50
51 /*
52 private string m_Realm;
53 private List<string> m_ColumnNames = null;
54 private PGSQLManager m_database;
55
56 public PGSQLUserAccountData(string connectionString, string realm) :
57 base(connectionString, realm, "UserAccount")
58 {
59 m_Realm = realm;
60 m_ConnectionString = connectionString;
61 m_database = new PGSQLManager(connectionString);
62
63 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
64 {
65 conn.Open();
66 Migration m = new Migration(conn, GetType().Assembly, "UserAccount");
67 m.Update();
68 }
69 }
70 */
71 /*
72 public List<UserAccountData> Query(UUID principalID, UUID scopeID, string query)
73 {
74 return null;
75 }
76 */
77 /*
78 public override UserAccountData[] Get(string[] fields, string[] keys)
79 {
80 UserAccountData[] retUA = base.Get(fields,keys);
81
82 if (retUA.Length > 0)
83 {
84 Dictionary<string, string> data = retUA[0].Data;
85 Dictionary<string, string> data2 = new Dictionary<string, string>();
86
87 foreach (KeyValuePair<string,string> chave in data)
88 {
89 string s2 = chave.Key;
90
91 data2[s2] = chave.Value;
92
93 if (!m_FieldTypes.ContainsKey(chave.Key))
94 {
95 string tipo = "";
96 m_FieldTypes.TryGetValue(chave.Key, out tipo);
97 m_FieldTypes.Add(s2, tipo);
98 }
99 }
100 foreach (KeyValuePair<string, string> chave in data2)
101 {
102 if (!retUA[0].Data.ContainsKey(chave.Key))
103 retUA[0].Data.Add(chave.Key, chave.Value);
104 }
105 }
106
107 return retUA;
108 }
109 */
110 /*
111 public UserAccountData Get(UUID principalID, UUID scopeID)
112 {
113 UserAccountData ret = new UserAccountData();
114 ret.Data = new Dictionary<string, string>();
115
116 string sql = string.Format(@"select * from {0} where ""PrincipalID"" = :principalID", m_Realm);
117 if (scopeID != UUID.Zero)
118 sql += @" and ""ScopeID"" = :scopeID";
119
120 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
121 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
122 {
123 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
124 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
125
126 conn.Open();
127 using (NpgsqlDataReader result = cmd.ExecuteReader())
128 {
129 if (result.Read())
130 {
131 ret.PrincipalID = principalID;
132 UUID scope;
133 UUID.TryParse(result["scopeid"].ToString(), out scope);
134 ret.ScopeID = scope;
135
136 if (m_ColumnNames == null)
137 {
138 m_ColumnNames = new List<string>();
139
140 DataTable schemaTable = result.GetSchemaTable();
141 foreach (DataRow row in schemaTable.Rows)
142 m_ColumnNames.Add(row["ColumnName"].ToString());
143 }
144
145 foreach (string s in m_ColumnNames)
146 {
147 string s2 = s;
148 if (s2 == "uuid")
149 continue;
150 if (s2 == "scopeid")
151 continue;
152
153 ret.Data[s] = result[s].ToString();
154 }
155 return ret;
156 }
157 }
158 }
159 return null;
160 }
161
162
163 public override bool Store(UserAccountData data)
164 {
165 if (data.Data.ContainsKey("PrincipalID"))
166 data.Data.Remove("PrincipalID");
167 if (data.Data.ContainsKey("ScopeID"))
168 data.Data.Remove("ScopeID");
169
170 string[] fields = new List<string>(data.Data.Keys).ToArray();
171
172 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
173 using (NpgsqlCommand cmd = new NpgsqlCommand())
174 {
175 m_log.DebugFormat("[USER]: Try to update user {0} {1}", data.FirstName, data.LastName);
176
177 StringBuilder updateBuilder = new StringBuilder();
178 updateBuilder.AppendFormat("update {0} set ", m_Realm);
179 bool first = true;
180 foreach (string field in fields)
181 {
182 if (!first)
183 updateBuilder.Append(", ");
184 updateBuilder.AppendFormat("\"{0}\" = :{0}", field);
185
186 first = false;
187 if (m_FieldTypes.ContainsKey(field))
188 cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field], m_FieldTypes[field]));
189 else
190 cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field]));
191 }
192
193 updateBuilder.Append(" where \"PrincipalID\" = :principalID");
194
195 if (data.ScopeID != UUID.Zero)
196 updateBuilder.Append(" and \"ScopeID\" = :scopeID");
197
198 cmd.CommandText = updateBuilder.ToString();
199 cmd.Connection = conn;
200 cmd.Parameters.Add(m_database.CreateParameter("principalID", data.PrincipalID));
201 cmd.Parameters.Add(m_database.CreateParameter("scopeID", data.ScopeID));
202
203 m_log.DebugFormat("[USER]: SQL update user {0} ", cmd.CommandText);
204
205 conn.Open();
206
207 m_log.DebugFormat("[USER]: CON opened update user {0} ", cmd.CommandText);
208
209 int conta = 0;
210 try
211 {
212 conta = cmd.ExecuteNonQuery();
213 }
214 catch (Exception e){
215 m_log.ErrorFormat("[USER]: ERROR opened update user {0} ", e.Message);
216 }
217
218
219 if (conta < 1)
220 {
221 m_log.DebugFormat("[USER]: Try to insert user {0} {1}", data.FirstName, data.LastName);
222
223 StringBuilder insertBuilder = new StringBuilder();
224 insertBuilder.AppendFormat(@"insert into {0} (""PrincipalID"", ""ScopeID"", ""FirstName"", ""LastName"", """, m_Realm);
225 insertBuilder.Append(String.Join(@""", """, fields));
226 insertBuilder.Append(@""") values (:principalID, :scopeID, :FirstName, :LastName, :");
227 insertBuilder.Append(String.Join(", :", fields));
228 insertBuilder.Append(");");
229
230 cmd.Parameters.Add(m_database.CreateParameter("FirstName", data.FirstName));
231 cmd.Parameters.Add(m_database.CreateParameter("LastName", data.LastName));
232
233 cmd.CommandText = insertBuilder.ToString();
234
235 if (cmd.ExecuteNonQuery() < 1)
236 {
237 return false;
238 }
239 }
240 else
241 m_log.DebugFormat("[USER]: User {0} {1} exists", data.FirstName, data.LastName);
242 }
243 return true;
244 }
245
246
247 public bool Store(UserAccountData data, UUID principalID, string token)
248 {
249 return false;
250 }
251
252
253 public bool SetDataItem(UUID principalID, string item, string value)
254 {
255 string sql = string.Format(@"update {0} set {1} = :{1} where ""UUID"" = :UUID", m_Realm, item);
256 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
257 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
258 {
259 if (m_FieldTypes.ContainsKey(item))
260 cmd.Parameters.Add(m_database.CreateParameter("" + item, value, m_FieldTypes[item]));
261 else
262 cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
263
264 cmd.Parameters.Add(m_database.CreateParameter("UUID", principalID));
265 conn.Open();
266
267 if (cmd.ExecuteNonQuery() > 0)
268 return true;
269 }
270 return false;
271 }
272 */
273 /*
274 public UserAccountData[] Get(string[] keys, string[] vals)
275 {
276 return null;
277 }
278 */
279
280 public UserAccountData[] GetUsers(UUID scopeID, string query)
281 {
282 string[] words = query.Split(new char[] { ' ' });
283
284 for (int i = 0; i < words.Length; i++)
285 {
286 if (words[i].Length < 3)
287 {
288 if (i != words.Length - 1)
289 Array.Copy(words, i + 1, words, i, words.Length - i - 1);
290 Array.Resize(ref words, words.Length - 1);
291 }
292 }
293
294 if (words.Length == 0)
295 return new UserAccountData[0];
296
297 if (words.Length > 2)
298 return new UserAccountData[0];
299
300 string sql = "";
301
302 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
303 using (NpgsqlCommand cmd = new NpgsqlCommand())
304 {
305 if (words.Length == 1)
306 {
307 sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""='00000000-0000-0000-0000-000000000000') and (""FirstName"" ilike :search or ""LastName"" ilike :search)", m_Realm);
308 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
309 cmd.Parameters.Add(m_database.CreateParameter("search", "%" + words[0] + "%"));
310 }
311 else
312 {
313 sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""='00000000-0000-0000-0000-000000000000') and (""FirstName"" ilike :searchFirst or ""LastName"" ilike :searchLast)", m_Realm);
314 cmd.Parameters.Add(m_database.CreateParameter("searchFirst", "%" + words[0] + "%"));
315 cmd.Parameters.Add(m_database.CreateParameter("searchLast", "%" + words[1] + "%"));
316 cmd.Parameters.Add(m_database.CreateParameter("ScopeID", scopeID.ToString()));
317 }
318 cmd.Connection = conn;
319 cmd.CommandText = sql;
320 conn.Open();
321 return DoQuery(cmd);
322 }
323 }
324
325 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
326 {
327 return null;
328 }
329 }
330}
diff --git a/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs b/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs
new file mode 100644
index 0000000..e3cbf7f
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs
@@ -0,0 +1,1075 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Data;
30using System.Reflection;
31using OpenSim.Data;
32using OpenSim.Framework;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using log4net;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 public class UserProfilesData: IProfilesData
41 {
42 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 #region Properites
45 string ConnectionString
46 {
47 get; set;
48 }
49
50 protected object Lock
51 {
52 get; set;
53 }
54
55 protected virtual Assembly Assembly
56 {
57 get { return GetType().Assembly; }
58 }
59
60 #endregion Properties
61
62 #region class Member Functions
63 public UserProfilesData(string connectionString)
64 {
65 ConnectionString = connectionString;
66 Init();
67 }
68
69 void Init()
70 {
71 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
72 {
73 dbcon.Open();
74
75 Migration m = new Migration(dbcon, Assembly, "UserProfiles");
76 m.Update();
77 }
78 }
79 #endregion Member Functions
80
81 #region Classifieds Queries
82 /// <summary>
83 /// Gets the classified records.
84 /// </summary>
85 /// <returns>
86 /// Array of classified records
87 /// </returns>
88 /// <param name='creatorId'>
89 /// Creator identifier.
90 /// </param>
91 public OSDArray GetClassifiedRecords(UUID creatorId)
92 {
93 OSDArray data = new OSDArray();
94
95 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
96 {
97 string query = @"SELECT ""classifieduuid"", ""name"" FROM classifieds WHERE ""creatoruuid"" = :Id";
98 dbcon.Open();
99 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
100 {
101 cmd.Parameters.AddWithValue("Id", creatorId);
102 using( NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default))
103 {
104 if(reader.HasRows)
105 {
106 while (reader.Read())
107 {
108 OSDMap n = new OSDMap();
109 UUID Id = UUID.Zero;
110
111 string Name = null;
112 try
113 {
114 UUID.TryParse(Convert.ToString( reader["classifieduuid"]), out Id);
115 Name = Convert.ToString(reader["name"]);
116 }
117 catch (Exception e)
118 {
119 m_log.DebugFormat("[PROFILES_DATA]" +
120 ": UserAccount exception {0}", e.Message);
121 }
122 n.Add("classifieduuid", OSD.FromUUID(Id));
123 n.Add("name", OSD.FromString(Name));
124 data.Add(n);
125 }
126 }
127 }
128 }
129 }
130 return data;
131 }
132
133 public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
134 {
135 string query = @"INSERT INTO classifieds ( ""classifieduuid"",""creatoruuid"", ""creationdate"", ""expirationdate"", ""category"",
136 ""name"", ""description"", ""parceluuid"", ""parentestate"", ""snapshotuuid"", ""simname"",
137 ""posglobal"", ""parcelname"", ""classifiedflags"", ""priceforlisting"")
138 Select :ClassifiedId, :CreatorId, :CreatedDate, :ExpirationDate, :Category,
139 :Name, :Description, :ParcelId, :ParentEstate, :SnapshotId, :SimName
140 :GlobalPos, :ParcelName, :Flags, :ListingPrice
141 Where not exists( Select ""classifieduuid"" from classifieds where ""classifieduuid"" = :ClassifiedId );
142
143 update classifieds
144 set category =:Category,
145 expirationdate = :ExpirationDate,
146 name = :Name,
147 description = :Description,
148 parentestate = :ParentEstate,
149 posglobal = :GlobalPos,
150 parcelname = :ParcelName,
151 classifiedflags = :Flags,
152 priceforlisting = :ListingPrice,
153 snapshotuuid = :SnapshotId
154 where classifieduuid = :ClassifiedId ;
155 ";
156
157 if(string.IsNullOrEmpty(ad.ParcelName))
158 ad.ParcelName = "Unknown";
159 if(ad.ParcelId == null)
160 ad.ParcelId = UUID.Zero;
161 if(string.IsNullOrEmpty(ad.Description))
162 ad.Description = "No Description";
163
164 DateTime epoch = new DateTime(1970, 1, 1);
165 DateTime now = DateTime.Now;
166 TimeSpan epochnow = now - epoch;
167 TimeSpan duration;
168 DateTime expiration;
169 TimeSpan epochexp;
170
171 if(ad.Flags == 2)
172 {
173 duration = new TimeSpan(7,0,0,0);
174 expiration = now.Add(duration);
175 epochexp = expiration - epoch;
176 }
177 else
178 {
179 duration = new TimeSpan(365,0,0,0);
180 expiration = now.Add(duration);
181 epochexp = expiration - epoch;
182 }
183 ad.CreationDate = (int)epochnow.TotalSeconds;
184 ad.ExpirationDate = (int)epochexp.TotalSeconds;
185
186 try
187 {
188 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
189 {
190 dbcon.Open();
191 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
192 {
193 cmd.Parameters.AddWithValue("ClassifiedId", ad.ClassifiedId.ToString());
194 cmd.Parameters.AddWithValue("CreatorId", ad.CreatorId.ToString());
195 cmd.Parameters.AddWithValue("CreatedDate", ad.CreationDate.ToString());
196 cmd.Parameters.AddWithValue("ExpirationDate", ad.ExpirationDate.ToString());
197 cmd.Parameters.AddWithValue("Category", ad.Category.ToString());
198 cmd.Parameters.AddWithValue("Name", ad.Name.ToString());
199 cmd.Parameters.AddWithValue("Description", ad.Description.ToString());
200 cmd.Parameters.AddWithValue("ParcelId", ad.ParcelId.ToString());
201 cmd.Parameters.AddWithValue("ParentEstate", ad.ParentEstate.ToString());
202 cmd.Parameters.AddWithValue("SnapshotId", ad.SnapshotId.ToString ());
203 cmd.Parameters.AddWithValue("SimName", ad.SimName.ToString());
204 cmd.Parameters.AddWithValue("GlobalPos", ad.GlobalPos.ToString());
205 cmd.Parameters.AddWithValue("ParcelName", ad.ParcelName.ToString());
206 cmd.Parameters.AddWithValue("Flags", ad.Flags.ToString());
207 cmd.Parameters.AddWithValue("ListingPrice", ad.Price.ToString ());
208
209 cmd.ExecuteNonQuery();
210 }
211 }
212 }
213 catch (Exception e)
214 {
215 m_log.DebugFormat("[PROFILES_DATA]" +
216 ": ClassifiedesUpdate exception {0}", e.Message);
217 result = e.Message;
218 return false;
219 }
220 return true;
221 }
222
223
224 public bool DeleteClassifiedRecord(UUID recordId)
225 {
226 string query = string.Empty;
227
228 query = @"DELETE FROM classifieds WHERE classifieduuid = :ClasifiedId ;";
229
230 try
231 {
232 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
233 {
234 dbcon.Open();
235
236 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
237 {
238 cmd.Parameters.AddWithValue("ClassifiedId", recordId.ToString());
239
240 lock(Lock)
241 {
242 cmd.ExecuteNonQuery();
243 }
244 }
245 }
246 }
247 catch (Exception e)
248 {
249 m_log.DebugFormat("[PROFILES_DATA]" +
250 ": DeleteClassifiedRecord exception {0}", e.Message);
251 return false;
252 }
253 return true;
254 }
255
256 public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
257 {
258 string query = string.Empty;
259
260 query += "SELECT * FROM classifieds WHERE ";
261 query += "classifieduuid = :AdId";
262
263 try
264 {
265 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
266 {
267 dbcon.Open();
268 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
269 {
270 cmd.Parameters.AddWithValue("AdId", ad.ClassifiedId.ToString());
271
272 using (NpgsqlDataReader reader = cmd.ExecuteReader())
273 {
274 if(reader.Read ())
275 {
276 ad.CreatorId = GetUUID(reader["creatoruuid"]);
277 ad.ParcelId = GetUUID(reader["parceluuid"]);
278 ad.SnapshotId = GetUUID(reader["snapshotuuid"]);
279 ad.CreationDate = Convert.ToInt32(reader["creationdate"]);
280 ad.ExpirationDate = Convert.ToInt32(reader["expirationdate"]);
281 ad.ParentEstate = Convert.ToInt32(reader["parentestate"]);
282 ad.Flags = (byte)Convert.ToInt16(reader["classifiedflags"]);
283 ad.Category = Convert.ToInt32(reader["category"]);
284 ad.Price = Convert.ToInt16(reader["priceforlisting"]);
285 ad.Name = reader["name"].ToString();
286 ad.Description = reader["description"].ToString();
287 ad.SimName = reader["simname"].ToString();
288 ad.GlobalPos = reader["posglobal"].ToString();
289 ad.ParcelName = reader["parcelname"].ToString();
290
291 }
292 }
293 }
294 dbcon.Close();
295 }
296 }
297 catch (Exception e)
298 {
299 m_log.DebugFormat("[PROFILES_DATA]" +
300 ": GetPickInfo exception {0}", e.Message);
301 }
302 return true;
303 }
304
305 public static UUID GetUUID( object uuidValue ) {
306
307 UUID ret = UUID.Zero;
308
309 UUID.TryParse(uuidValue.ToString(), out ret);
310
311 return ret;
312 }
313
314
315 #endregion Classifieds Queries
316
317 #region Picks Queries
318 public OSDArray GetAvatarPicks(UUID avatarId)
319 {
320 string query = string.Empty;
321
322 query += "SELECT \"pickuuid\",\"name\" FROM userpicks WHERE ";
323 query += "creatoruuid = :Id";
324 OSDArray data = new OSDArray();
325
326 try
327 {
328 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
329 {
330 dbcon.Open();
331 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
332 {
333 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
334
335 using (NpgsqlDataReader reader = cmd.ExecuteReader())
336 {
337 if(reader.HasRows)
338 {
339 while (reader.Read())
340 {
341 OSDMap record = new OSDMap();
342
343 record.Add("pickuuid",OSD.FromString((string)reader["pickuuid"]));
344 record.Add("name",OSD.FromString((string)reader["name"]));
345 data.Add(record);
346 }
347 }
348 }
349 }
350 }
351 }
352 catch (Exception e)
353 {
354 m_log.DebugFormat("[PROFILES_DATA]" +
355 ": GetAvatarPicks exception {0}", e.Message);
356 }
357 return data;
358 }
359
360 public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
361 {
362 string query = string.Empty;
363 UserProfilePick pick = new UserProfilePick();
364
365 query += "SELECT * FROM userpicks WHERE ";
366 query += "creatoruuid = :CreatorId AND ";
367 query += "pickuuid = :PickId";
368
369 try
370 {
371 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
372 {
373 dbcon.Open();
374 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
375 {
376 cmd.Parameters.AddWithValue("CreatorId", avatarId.ToString());
377 cmd.Parameters.AddWithValue("PickId", pickId.ToString());
378
379 using (NpgsqlDataReader reader = cmd.ExecuteReader())
380 {
381 if(reader.HasRows)
382 {
383 reader.Read();
384
385 string description = (string)reader["description"];
386
387 if (string.IsNullOrEmpty(description))
388 description = "No description given.";
389
390 UUID.TryParse((string)reader["pickuuid"], out pick.PickId);
391 UUID.TryParse((string)reader["creatoruuid"], out pick.CreatorId);
392 UUID.TryParse((string)reader["parceluuid"], out pick.ParcelId);
393 UUID.TryParse((string)reader["snapshotuuid"], out pick.SnapshotId);
394 pick.GlobalPos = (string)reader["posglobal"];
395 bool.TryParse((string)reader["toppick"], out pick.TopPick);
396 bool.TryParse((string)reader["enabled"], out pick.Enabled);
397 pick.Name = (string)reader["name"];
398 pick.Desc = description;
399 pick.User = (string)reader["user"];
400 pick.OriginalName = (string)reader["originalname"];
401 pick.SimName = (string)reader["simname"];
402 pick.SortOrder = (int)reader["sortorder"];
403 }
404 }
405 }
406 dbcon.Close();
407 }
408 }
409 catch (Exception e)
410 {
411 m_log.DebugFormat("[PROFILES_DATA]" +
412 ": GetPickInfo exception {0}", e.Message);
413 }
414 return pick;
415 }
416
417 public bool UpdatePicksRecord(UserProfilePick pick)
418 {
419 string query = string.Empty;
420
421 query = @"INSERT INTO userpicks VALUES ( :PickId, :CreatorId, :TopPick, :ParcelId,:Name, :Desc, :SnapshotId,:User,
422 :Original, :SimName, :GlobalPos, :SortOrder, :Enabled)
423 where not exists ( select pickid from userpicks where pickid = :pickid);
424
425 Update userpicks
426 set parceluuid = :ParcelId,
427 name = :Name,
428 description = :Desc,
429 snapshotuuid = :SnapshotId,
430 pickuuid = :PickId,
431 posglobal = :GlobalPos
432 where pickid = :PickId;
433 ";
434
435 try
436 {
437 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
438 {
439 dbcon.Open();
440 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
441 {
442 cmd.Parameters.AddWithValue("PickId", pick.PickId.ToString());
443 cmd.Parameters.AddWithValue("CreatorId", pick.CreatorId.ToString());
444 cmd.Parameters.AddWithValue("TopPick", pick.TopPick.ToString());
445 cmd.Parameters.AddWithValue("ParcelId", pick.ParcelId.ToString());
446 cmd.Parameters.AddWithValue("Name", pick.Name.ToString());
447 cmd.Parameters.AddWithValue("Desc", pick.Desc.ToString());
448 cmd.Parameters.AddWithValue("SnapshotId", pick.SnapshotId.ToString());
449 cmd.Parameters.AddWithValue("User", pick.User.ToString());
450 cmd.Parameters.AddWithValue("Original", pick.OriginalName.ToString());
451 cmd.Parameters.AddWithValue("SimName",pick.SimName.ToString());
452 cmd.Parameters.AddWithValue("GlobalPos", pick.GlobalPos);
453 cmd.Parameters.AddWithValue("SortOrder", pick.SortOrder.ToString ());
454 cmd.Parameters.AddWithValue("Enabled", pick.Enabled.ToString());
455
456 cmd.ExecuteNonQuery();
457 }
458 }
459 }
460 catch (Exception e)
461 {
462 m_log.DebugFormat("[PROFILES_DATA]" +
463 ": UpdateAvatarNotes exception {0}", e.Message);
464 return false;
465 }
466 return true;
467 }
468
469 public bool DeletePicksRecord(UUID pickId)
470 {
471 string query = string.Empty;
472
473 query += "DELETE FROM userpicks WHERE ";
474 query += "pickuuid = :PickId";
475
476 try
477 {
478 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
479 {
480 dbcon.Open();
481
482 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
483 {
484 cmd.Parameters.AddWithValue("PickId", pickId.ToString());
485
486 cmd.ExecuteNonQuery();
487 }
488 }
489 }
490 catch (Exception e)
491 {
492 m_log.DebugFormat("[PROFILES_DATA]" +
493 ": DeleteUserPickRecord exception {0}", e.Message);
494 return false;
495 }
496 return true;
497 }
498 #endregion Picks Queries
499
500 #region Avatar Notes Queries
501 public bool GetAvatarNotes(ref UserProfileNotes notes)
502 { // WIP
503 string query = string.Empty;
504
505 query += "SELECT \"notes\" FROM usernotes WHERE ";
506 query += "useruuid = :Id AND ";
507 query += "targetuuid = :TargetId";
508 OSDArray data = new OSDArray();
509
510 try
511 {
512 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
513 {
514 dbcon.Open();
515 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
516 {
517 cmd.Parameters.AddWithValue("Id", notes.UserId.ToString());
518 cmd.Parameters.AddWithValue("TargetId", notes.TargetId.ToString());
519
520 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
521 {
522 if(reader.HasRows)
523 {
524 reader.Read();
525 notes.Notes = OSD.FromString((string)reader["notes"]);
526 }
527 }
528 }
529 }
530 }
531 catch (Exception e)
532 {
533 m_log.DebugFormat("[PROFILES_DATA]" +
534 ": GetAvatarNotes exception {0}", e.Message);
535 }
536 return true;
537 }
538
539 public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
540 {
541 string query = string.Empty;
542 bool remove;
543
544 if(string.IsNullOrEmpty(note.Notes))
545 {
546 remove = true;
547 query += "DELETE FROM usernotes WHERE ";
548 query += "useruuid=:UserId AND ";
549 query += "targetuuid=:TargetId";
550 }
551 else
552 {
553 remove = false;
554 query = @"INSERT INTO usernotes VALUES ( :UserId, :TargetId, :Notes )
555 where not exists ( Select useruuid from usernotes where useruuid = :UserId and targetuuid = :TargetId );
556
557 update usernotes
558 set notes = :Notes
559 where useruuid = :UserId
560 and targetuuid = :TargetId;
561 ";
562 }
563
564 try
565 {
566 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
567 {
568 dbcon.Open();
569 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
570 {
571 if(!remove)
572 cmd.Parameters.AddWithValue("Notes", note.Notes);
573 cmd.Parameters.AddWithValue("TargetId", note.TargetId.ToString ());
574 cmd.Parameters.AddWithValue("UserId", note.UserId.ToString());
575
576 cmd.ExecuteNonQuery();
577 }
578 }
579 }
580 catch (Exception e)
581 {
582 m_log.DebugFormat("[PROFILES_DATA]" +
583 ": UpdateAvatarNotes exception {0}", e.Message);
584 return false;
585 }
586 return true;
587
588 }
589 #endregion Avatar Notes Queries
590
591 #region Avatar Properties
592 public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
593 {
594 string query = string.Empty;
595
596 query += "SELECT * FROM userprofile WHERE ";
597 query += "useruuid = :Id";
598
599 try
600 {
601 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
602 {
603 dbcon.Open();
604 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
605 {
606 cmd.Parameters.AddWithValue("Id", props.UserId.ToString());
607
608 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
609 {
610 if(reader.HasRows)
611 {
612 m_log.DebugFormat("[PROFILES_DATA]" +
613 ": Getting data for {0}.", props.UserId);
614 reader.Read();
615 props.WebUrl = (string)reader["profileURL"];
616 UUID.TryParse((string)reader["profileImage"], out props.ImageId);
617 props.AboutText = (string)reader["profileAboutText"];
618 UUID.TryParse((string)reader["profileFirstImage"], out props.FirstLifeImageId);
619 props.FirstLifeText = (string)reader["profileFirstText"];
620 UUID.TryParse((string)reader["profilePartner"], out props.PartnerId);
621 props.WantToMask = (int)reader["profileWantToMask"];
622 props.WantToText = (string)reader["profileWantToText"];
623 props.SkillsMask = (int)reader["profileSkillsMask"];
624 props.SkillsText = (string)reader["profileSkillsText"];
625 props.Language = (string)reader["profileLanguages"];
626 }
627 else
628 {
629 m_log.DebugFormat("[PROFILES_DATA]" +
630 ": No data for {0}", props.UserId);
631
632 props.WebUrl = string.Empty;
633 props.ImageId = UUID.Zero;
634 props.AboutText = string.Empty;
635 props.FirstLifeImageId = UUID.Zero;
636 props.FirstLifeText = string.Empty;
637 props.PartnerId = UUID.Zero;
638 props.WantToMask = 0;
639 props.WantToText = string.Empty;
640 props.SkillsMask = 0;
641 props.SkillsText = string.Empty;
642 props.Language = string.Empty;
643 props.PublishProfile = false;
644 props.PublishMature = false;
645
646 query = "INSERT INTO userprofile (";
647 query += "useruuid, ";
648 query += "profilePartner, ";
649 query += "profileAllowPublish, ";
650 query += "profileMaturePublish, ";
651 query += "profileURL, ";
652 query += "profileWantToMask, ";
653 query += "profileWantToText, ";
654 query += "profileSkillsMask, ";
655 query += "profileSkillsText, ";
656 query += "profileLanguages, ";
657 query += "profileImage, ";
658 query += "profileAboutText, ";
659 query += "profileFirstImage, ";
660 query += "profileFirstText) VALUES (";
661 query += ":userId, ";
662 query += ":profilePartner, ";
663 query += ":profileAllowPublish, ";
664 query += ":profileMaturePublish, ";
665 query += ":profileURL, ";
666 query += ":profileWantToMask, ";
667 query += ":profileWantToText, ";
668 query += ":profileSkillsMask, ";
669 query += ":profileSkillsText, ";
670 query += ":profileLanguages, ";
671 query += ":profileImage, ";
672 query += ":profileAboutText, ";
673 query += ":profileFirstImage, ";
674 query += ":profileFirstText)";
675
676 dbcon.Close();
677 dbcon.Open();
678
679 using (NpgsqlCommand put = new NpgsqlCommand(query, dbcon))
680 {
681 put.Parameters.AddWithValue("userId", props.UserId.ToString());
682 put.Parameters.AddWithValue("profilePartner", props.PartnerId.ToString());
683 put.Parameters.AddWithValue("profileAllowPublish", props.PublishProfile);
684 put.Parameters.AddWithValue("profileMaturePublish", props.PublishMature);
685 put.Parameters.AddWithValue("profileURL", props.WebUrl);
686 put.Parameters.AddWithValue("profileWantToMask", props.WantToMask);
687 put.Parameters.AddWithValue("profileWantToText", props.WantToText);
688 put.Parameters.AddWithValue("profileSkillsMask", props.SkillsMask);
689 put.Parameters.AddWithValue("profileSkillsText", props.SkillsText);
690 put.Parameters.AddWithValue("profileLanguages", props.Language);
691 put.Parameters.AddWithValue("profileImage", props.ImageId.ToString());
692 put.Parameters.AddWithValue("profileAboutText", props.AboutText);
693 put.Parameters.AddWithValue("profileFirstImage", props.FirstLifeImageId.ToString());
694 put.Parameters.AddWithValue("profileFirstText", props.FirstLifeText);
695
696 put.ExecuteNonQuery();
697 }
698 }
699 }
700 }
701 }
702 }
703 catch (Exception e)
704 {
705 m_log.DebugFormat("[PROFILES_DATA]" +
706 ": Requst properties exception {0}", e.Message);
707 result = e.Message;
708 return false;
709 }
710 return true;
711 }
712
713 public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
714 {
715 string query = string.Empty;
716
717 query += "UPDATE userprofile SET ";
718 query += "profilePartner=:profilePartner, ";
719 query += "profileURL=:profileURL, ";
720 query += "profileImage=:image, ";
721 query += "profileAboutText=:abouttext,";
722 query += "profileFirstImage=:firstlifeimage,";
723 query += "profileFirstText=:firstlifetext ";
724 query += "WHERE useruuid=:uuid";
725
726 try
727 {
728 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
729 {
730 dbcon.Open();
731 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
732 {
733 cmd.Parameters.AddWithValue("profileURL", props.WebUrl);
734 cmd.Parameters.AddWithValue("profilePartner", props.PartnerId.ToString());
735 cmd.Parameters.AddWithValue("image", props.ImageId.ToString());
736 cmd.Parameters.AddWithValue("abouttext", props.AboutText);
737 cmd.Parameters.AddWithValue("firstlifeimage", props.FirstLifeImageId.ToString());
738 cmd.Parameters.AddWithValue("firstlifetext", props.FirstLifeText);
739 cmd.Parameters.AddWithValue("uuid", props.UserId.ToString());
740
741 cmd.ExecuteNonQuery();
742 }
743 }
744 }
745 catch (Exception e)
746 {
747 m_log.DebugFormat("[PROFILES_DATA]" +
748 ": AgentPropertiesUpdate exception {0}", e.Message);
749
750 return false;
751 }
752 return true;
753 }
754 #endregion Avatar Properties
755
756 #region Avatar Interests
757 public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
758 {
759 string query = string.Empty;
760
761 query += "UPDATE userprofile SET ";
762 query += "profileWantToMask=:WantMask, ";
763 query += "profileWantToText=:WantText,";
764 query += "profileSkillsMask=:SkillsMask,";
765 query += "profileSkillsText=:SkillsText, ";
766 query += "profileLanguages=:Languages ";
767 query += "WHERE useruuid=:uuid";
768
769 try
770 {
771 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
772 {
773 dbcon.Open();
774 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
775 {
776 cmd.Parameters.AddWithValue("WantMask", up.WantToMask);
777 cmd.Parameters.AddWithValue("WantText", up.WantToText);
778 cmd.Parameters.AddWithValue("SkillsMask", up.SkillsMask);
779 cmd.Parameters.AddWithValue("SkillsText", up.SkillsText);
780 cmd.Parameters.AddWithValue("Languages", up.Language);
781 cmd.Parameters.AddWithValue("uuid", up.UserId.ToString());
782
783 cmd.ExecuteNonQuery();
784 }
785 }
786 }
787 catch (Exception e)
788 {
789 m_log.DebugFormat("[PROFILES_DATA]" +
790 ": AgentInterestsUpdate exception {0}", e.Message);
791 result = e.Message;
792 return false;
793 }
794 return true;
795 }
796 #endregion Avatar Interests
797
798 public OSDArray GetUserImageAssets(UUID avatarId)
799 {
800 OSDArray data = new OSDArray();
801 string query = "SELECT \"snapshotuuid\" FROM {0} WHERE \"creatoruuid\" = :Id";
802
803 // Get classified image assets
804
805
806 try
807 {
808 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
809 {
810 dbcon.Open();
811
812 using (NpgsqlCommand cmd = new NpgsqlCommand(string.Format (query,"\"classifieds\""), dbcon))
813 {
814 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
815
816 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
817 {
818 if(reader.HasRows)
819 {
820 while (reader.Read())
821 {
822 data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
823 }
824 }
825 }
826 }
827
828 dbcon.Close();
829 dbcon.Open();
830
831 using (NpgsqlCommand cmd = new NpgsqlCommand(string.Format (query,"\"userpicks\""), dbcon))
832 {
833 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
834
835 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
836 {
837 if(reader.HasRows)
838 {
839 while (reader.Read())
840 {
841 data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
842 }
843 }
844 }
845 }
846
847 dbcon.Close();
848 dbcon.Open();
849
850 query = "SELECT \"profileImage\", \"profileFirstImage\" FROM \"userprofile\" WHERE \"useruuid\" = :Id";
851
852 using (NpgsqlCommand cmd = new NpgsqlCommand(string.Format (query,"\"userpicks\""), dbcon))
853 {
854 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
855
856 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
857 {
858 if(reader.HasRows)
859 {
860 while (reader.Read())
861 {
862 data.Add(new OSDString((string)reader["profileImage"].ToString ()));
863 data.Add(new OSDString((string)reader["profileFirstImage"].ToString ()));
864 }
865 }
866 }
867 }
868 }
869 }
870 catch (Exception e)
871 {
872 m_log.DebugFormat("[PROFILES_DATA]" +
873 ": GetAvatarNotes exception {0}", e.Message);
874 }
875 return data;
876 }
877
878 #region User Preferences
879 public OSDArray GetUserPreferences(UUID avatarId)
880 {
881 string query = string.Empty;
882
883 query += "SELECT imviaemail,visible,email FROM ";
884 query += "usersettings WHERE ";
885 query += "useruuid = :Id";
886
887 OSDArray data = new OSDArray();
888
889 try
890 {
891 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
892 {
893 dbcon.Open();
894 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
895 {
896 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
897
898 using (NpgsqlDataReader reader = cmd.ExecuteReader())
899 {
900 if(reader.HasRows)
901 {
902 reader.Read();
903 OSDMap record = new OSDMap();
904
905 record.Add("imviaemail",OSD.FromString((string)reader["imviaemail"]));
906 record.Add("visible",OSD.FromString((string)reader["visible"]));
907 record.Add("email",OSD.FromString((string)reader["email"]));
908 data.Add(record);
909 }
910 else
911 {
912 using (NpgsqlCommand put = new NpgsqlCommand(query, dbcon))
913 {
914 query = "INSERT INTO usersettings VALUES ";
915 query += "(:Id,'false','false', '')";
916
917 lock(Lock)
918 {
919 put.ExecuteNonQuery();
920 }
921 }
922 }
923 }
924 }
925 }
926 }
927 catch (Exception e)
928 {
929 m_log.DebugFormat("[PROFILES_DATA]" +
930 ": Get preferences exception {0}", e.Message);
931 }
932 return data;
933 }
934
935 public bool UpdateUserPreferences(bool emailIm, bool visible, UUID avatarId )
936 {
937 string query = string.Empty;
938
939 query += "UPDATE userpsettings SET ";
940 query += "imviaemail=:ImViaEmail, ";
941 query += "visible=:Visible,";
942 query += "WHERE useruuid=:uuid";
943
944 try
945 {
946 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
947 {
948 dbcon.Open();
949 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
950 {
951 cmd.Parameters.AddWithValue("ImViaEmail", emailIm.ToString().ToLower ());
952 cmd.Parameters.AddWithValue("WantText", visible.ToString().ToLower ());
953 cmd.Parameters.AddWithValue("uuid", avatarId.ToString());
954
955 lock(Lock)
956 {
957 cmd.ExecuteNonQuery();
958 }
959 }
960 }
961 }
962 catch (Exception e)
963 {
964 m_log.DebugFormat("[PROFILES_DATA]" +
965 ": AgentInterestsUpdate exception {0}", e.Message);
966 return false;
967 }
968 return true;
969 }
970 #endregion User Preferences
971
972 #region Integration
973 public bool GetUserAppData(ref UserAppData props, ref string result)
974 {
975 string query = string.Empty;
976
977 query += "SELECT * FROM userdata WHERE ";
978 query += "\"UserId\" = :Id AND ";
979 query += "\"TagId\" = :TagId";
980
981 try
982 {
983 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
984 {
985 dbcon.Open();
986 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
987 {
988 cmd.Parameters.AddWithValue("Id", props.UserId.ToString());
989 cmd.Parameters.AddWithValue (":TagId", props.TagId.ToString());
990
991 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
992 {
993 if(reader.HasRows)
994 {
995 reader.Read();
996 props.DataKey = (string)reader["DataKey"];
997 props.DataVal = (string)reader["DataVal"];
998 }
999 else
1000 {
1001 query += "INSERT INTO userdata VALUES ( ";
1002 query += ":UserId,";
1003 query += ":TagId,";
1004 query += ":DataKey,";
1005 query += ":DataVal) ";
1006
1007 using (NpgsqlCommand put = new NpgsqlCommand(query, dbcon))
1008 {
1009 put.Parameters.AddWithValue("Id", props.UserId.ToString());
1010 put.Parameters.AddWithValue("TagId", props.TagId.ToString());
1011 put.Parameters.AddWithValue("DataKey", props.DataKey.ToString());
1012 put.Parameters.AddWithValue("DataVal", props.DataVal.ToString());
1013
1014 lock(Lock)
1015 {
1016 put.ExecuteNonQuery();
1017 }
1018 }
1019 }
1020 }
1021 }
1022 }
1023 }
1024 catch (Exception e)
1025 {
1026 m_log.DebugFormat("[PROFILES_DATA]" +
1027 ": Requst application data exception {0}", e.Message);
1028 result = e.Message;
1029 return false;
1030 }
1031 return true;
1032 }
1033
1034 public bool SetUserAppData(UserAppData props, ref string result)
1035 {
1036 string query = string.Empty;
1037
1038 query += "UPDATE userdata SET ";
1039 query += "\"TagId\" = :TagId, ";
1040 query += "\"DataKey\" = :DataKey, ";
1041 query += "\"DataVal\" = :DataVal WHERE ";
1042 query += "\"UserId\" = :UserId AND ";
1043 query += "\"TagId\" = :TagId";
1044
1045 try
1046 {
1047 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
1048 {
1049 dbcon.Open();
1050 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
1051 {
1052 cmd.Parameters.AddWithValue("UserId", props.UserId.ToString());
1053 cmd.Parameters.AddWithValue("TagId", props.TagId.ToString ());
1054 cmd.Parameters.AddWithValue("DataKey", props.DataKey.ToString ());
1055 cmd.Parameters.AddWithValue("DataVal", props.DataKey.ToString ());
1056
1057 lock(Lock)
1058 {
1059 cmd.ExecuteNonQuery();
1060 }
1061 }
1062 }
1063 }
1064 catch (Exception e)
1065 {
1066 m_log.DebugFormat("[PROFILES_DATA]" +
1067 ": SetUserData exception {0}", e.Message);
1068 return false;
1069 }
1070 return true;
1071 }
1072 #endregion Integration
1073 }
1074}
1075
diff --git a/OpenSim/Data/PGSQL/PGSQLXAssetData.cs b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs
new file mode 100644
index 0000000..e959619
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs
@@ -0,0 +1,535 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.IO;
32using System.IO.Compression;
33using System.Reflection;
34using System.Security.Cryptography;
35using System.Text;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Data;
40using Npgsql;
41
42namespace OpenSim.Data.PGSQL
43{
44 public class PGSQLXAssetData : IXAssetDataPlugin
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected virtual Assembly Assembly
49 {
50 get { return GetType().Assembly; }
51 }
52
53 /// <summary>
54 /// Number of days that must pass before we update the access time on an asset when it has been fetched.
55 /// </summary>
56 private const int DaysBetweenAccessTimeUpdates = 30;
57
58 private bool m_enableCompression = false;
59 private string m_connectionString;
60 private object m_dbLock = new object();
61
62 /// <summary>
63 /// We can reuse this for all hashing since all methods are single-threaded through m_dbBLock
64 /// </summary>
65 private HashAlgorithm hasher = new SHA256CryptoServiceProvider();
66
67 #region IPlugin Members
68
69 public string Version { get { return "1.0.0.0"; } }
70
71 /// <summary>
72 /// <para>Initialises Asset interface</para>
73 /// <para>
74 /// <list type="bullet">
75 /// <item>Loads and initialises the PGSQL storage plugin.</item>
76 /// <item>Warns and uses the obsolete pgsql_connection.ini if connect string is empty.</item>
77 /// <item>Check for migration</item>
78 /// </list>
79 /// </para>
80 /// </summary>
81 /// <param name="connect">connect string</param>
82 public void Initialise(string connect)
83 {
84 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
85 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
86 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
87 m_log.ErrorFormat("[PGSQL XASSETDATA]: THIS PLUGIN IS STRICTLY EXPERIMENTAL.");
88 m_log.ErrorFormat("[PGSQL XASSETDATA]: DO NOT USE FOR ANY DATA THAT YOU DO NOT MIND LOSING.");
89 m_log.ErrorFormat("[PGSQL XASSETDATA]: DATABASE TABLES CAN CHANGE AT ANY TIME, CAUSING EXISTING DATA TO BE LOST.");
90 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
91 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
92 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
93
94 m_connectionString = connect;
95
96 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
97 {
98 dbcon.Open();
99 Migration m = new Migration(dbcon, Assembly, "XAssetStore");
100 m.Update();
101 }
102 }
103
104 public void Initialise()
105 {
106 throw new NotImplementedException();
107 }
108
109 public void Dispose() { }
110
111 /// <summary>
112 /// The name of this DB provider
113 /// </summary>
114 public string Name
115 {
116 get { return "PGSQL XAsset storage engine"; }
117 }
118
119 #endregion
120
121 #region IAssetDataPlugin Members
122
123 /// <summary>
124 /// Fetch Asset <paramref name="assetID"/> from database
125 /// </summary>
126 /// <param name="assetID">Asset UUID to fetch</param>
127 /// <returns>Return the asset</returns>
128 /// <remarks>On failure : throw an exception and attempt to reconnect to database</remarks>
129 public AssetBase GetAsset(UUID assetID)
130 {
131// m_log.DebugFormat("[PGSQL XASSET DATA]: Looking for asset {0}", assetID);
132
133 AssetBase asset = null;
134 lock (m_dbLock)
135 {
136 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
137 {
138 dbcon.Open();
139
140 using (NpgsqlCommand cmd = new NpgsqlCommand(
141 @"SELECT ""Name"", ""Description"", ""AccessTime"", ""AssetType"", ""Local"", ""Temporary"", ""AssetFlags"", ""CreatorID"", ""Data""
142 FROM XAssetsMeta
143 JOIN XAssetsData ON XAssetsMeta.Hash = XAssetsData.Hash WHERE ""ID""=:ID",
144 dbcon))
145 {
146 cmd.Parameters.AddWithValue("ID", assetID.ToString());
147
148 try
149 {
150 using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
151 {
152 if (dbReader.Read())
153 {
154 asset = new AssetBase(assetID, (string)dbReader["Name"], (sbyte)dbReader["AssetType"], dbReader["CreatorID"].ToString());
155 asset.Data = (byte[])dbReader["Data"];
156 asset.Description = (string)dbReader["Description"];
157
158 string local = dbReader["Local"].ToString();
159 if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase))
160 asset.Local = true;
161 else
162 asset.Local = false;
163
164 asset.Temporary = Convert.ToBoolean(dbReader["Temporary"]);
165 asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
166
167 if (m_enableCompression)
168 {
169 using (GZipStream decompressionStream = new GZipStream(new MemoryStream(asset.Data), CompressionMode.Decompress))
170 {
171 MemoryStream outputStream = new MemoryStream();
172 WebUtil.CopyStream(decompressionStream, outputStream, int.MaxValue);
173 // int compressedLength = asset.Data.Length;
174 asset.Data = outputStream.ToArray();
175
176 // m_log.DebugFormat(
177 // "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}",
178 // asset.ID, asset.Name, asset.Data.Length, compressedLength);
179 }
180 }
181
182 UpdateAccessTime(asset.Metadata, (int)dbReader["AccessTime"]);
183 }
184 }
185 }
186 catch (Exception e)
187 {
188 m_log.Error(string.Format("[PGSQL XASSET DATA]: Failure fetching asset {0}", assetID), e);
189 }
190 }
191 }
192 }
193
194 return asset;
195 }
196
197 /// <summary>
198 /// Create an asset in database, or update it if existing.
199 /// </summary>
200 /// <param name="asset">Asset UUID to create</param>
201 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
202 public void StoreAsset(AssetBase asset)
203 {
204// m_log.DebugFormat("[XASSETS DB]: Storing asset {0} {1}", asset.Name, asset.ID);
205
206 lock (m_dbLock)
207 {
208 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
209 {
210 dbcon.Open();
211
212 using (NpgsqlTransaction transaction = dbcon.BeginTransaction())
213 {
214 string assetName = asset.Name;
215 if (asset.Name.Length > 64)
216 {
217 assetName = asset.Name.Substring(0, 64);
218 m_log.WarnFormat(
219 "[XASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
220 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
221 }
222
223 string assetDescription = asset.Description;
224 if (asset.Description.Length > 64)
225 {
226 assetDescription = asset.Description.Substring(0, 64);
227 m_log.WarnFormat(
228 "[XASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
229 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
230 }
231
232 if (m_enableCompression)
233 {
234 MemoryStream outputStream = new MemoryStream();
235
236 using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress, false))
237 {
238 // Console.WriteLine(WebUtil.CopyTo(new MemoryStream(asset.Data), compressionStream, int.MaxValue));
239 // We have to close the compression stream in order to make sure it writes everything out to the underlying memory output stream.
240 compressionStream.Close();
241 byte[] compressedData = outputStream.ToArray();
242 asset.Data = compressedData;
243 }
244 }
245
246 byte[] hash = hasher.ComputeHash(asset.Data);
247
248// m_log.DebugFormat(
249// "[XASSET DB]: Compressed data size for {0} {1}, hash {2} is {3}",
250// asset.ID, asset.Name, hash, compressedData.Length);
251
252 try
253 {
254 using (NpgsqlCommand cmd =
255 new NpgsqlCommand(
256 @"insert INTO XAssetsMeta(""ID"", ""Hash"", ""Name"", ""Description"", ""AssetType"", ""Local"", ""Temporary"", ""CreateTime"", ""AccessTime"", ""AssetFlags"", ""CreatorID"")
257 Select :ID, :Hash, :Name, :Description, :AssetType, :Local, :Temporary, :CreateTime, :AccessTime, :AssetFlags, :CreatorID
258 where not exists( Select ""ID"" from XAssetsMeta where ""ID"" = :ID ;
259
260 update XAssetsMeta
261 set ""ID"" = :ID, ""Hash"" = :Hash, ""Name"" = :Name, ""Description"" = :Description,
262 ""AssetType"" = :AssetType, ""Local"" = :Local, ""Temporary"" = :Temporary, ""CreateTime"" = :CreateTime,
263 ""AccessTime"" = :AccessTime, ""AssetFlags"" = :AssetFlags, ""CreatorID"" = :CreatorID
264 where ""ID"" = :ID;
265 ",
266 dbcon))
267 {
268 // create unix epoch time
269 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
270 cmd.Parameters.AddWithValue("ID", asset.ID);
271 cmd.Parameters.AddWithValue("Hash", hash);
272 cmd.Parameters.AddWithValue("Name", assetName);
273 cmd.Parameters.AddWithValue("Description", assetDescription);
274 cmd.Parameters.AddWithValue("AssetType", asset.Type);
275 cmd.Parameters.AddWithValue("Local", asset.Local);
276 cmd.Parameters.AddWithValue("Temporary", asset.Temporary);
277 cmd.Parameters.AddWithValue("CreateTime", now);
278 cmd.Parameters.AddWithValue("AccessTime", now);
279 cmd.Parameters.AddWithValue("CreatorID", asset.Metadata.CreatorID);
280 cmd.Parameters.AddWithValue("AssetFlags", (int)asset.Flags);
281 cmd.ExecuteNonQuery();
282 }
283 }
284 catch (Exception e)
285 {
286 m_log.ErrorFormat("[ASSET DB]: PGSQL failure creating asset metadata {0} with name \"{1}\". Error: {2}",
287 asset.FullID, asset.Name, e.Message);
288
289 transaction.Rollback();
290
291 return;
292 }
293
294 if (!ExistsData(dbcon, transaction, hash))
295 {
296 try
297 {
298 using (NpgsqlCommand cmd =
299 new NpgsqlCommand(
300 @"INSERT INTO XAssetsData(""Hash"", ""Data"") VALUES(:Hash, :Data)",
301 dbcon))
302 {
303 cmd.Parameters.AddWithValue("Hash", hash);
304 cmd.Parameters.AddWithValue("Data", asset.Data);
305 cmd.ExecuteNonQuery();
306 }
307 }
308 catch (Exception e)
309 {
310 m_log.ErrorFormat("[XASSET DB]: PGSQL failure creating asset data {0} with name \"{1}\". Error: {2}",
311 asset.FullID, asset.Name, e.Message);
312
313 transaction.Rollback();
314
315 return;
316 }
317 }
318
319 transaction.Commit();
320 }
321 }
322 }
323 }
324
325 /// <summary>
326 /// Updates the access time of the asset if it was accessed above a given threshhold amount of time.
327 /// </summary>
328 /// <remarks>
329 /// This gives us some insight into assets which haven't ben accessed for a long period. This is only done
330 /// over the threshold time to avoid excessive database writes as assets are fetched.
331 /// </remarks>
332 /// <param name='asset'></param>
333 /// <param name='accessTime'></param>
334 private void UpdateAccessTime(AssetMetadata assetMetadata, int accessTime)
335 {
336 DateTime now = DateTime.UtcNow;
337
338 if ((now - Utils.UnixTimeToDateTime(accessTime)).TotalDays < DaysBetweenAccessTimeUpdates)
339 return;
340
341 lock (m_dbLock)
342 {
343 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
344 {
345 dbcon.Open();
346 NpgsqlCommand cmd =
347 new NpgsqlCommand(@"update XAssetsMeta set ""AccessTime""=:AccessTime where ID=:ID", dbcon);
348
349 try
350 {
351 using (cmd)
352 {
353 // create unix epoch time
354 cmd.Parameters.AddWithValue("ID", assetMetadata.ID);
355 cmd.Parameters.AddWithValue("AccessTime", (int)Utils.DateTimeToUnixTime(now));
356 cmd.ExecuteNonQuery();
357 }
358 }
359 catch (Exception e)
360 {
361 m_log.ErrorFormat(
362 "[XASSET PGSQL DB]: Failure updating access_time for asset {0} with name {1} : {2}",
363 assetMetadata.ID, assetMetadata.Name, e.Message);
364 }
365 }
366 }
367 }
368
369 /// <summary>
370 /// We assume we already have the m_dbLock.
371 /// </summary>
372 /// TODO: need to actually use the transaction.
373 /// <param name="dbcon"></param>
374 /// <param name="transaction"></param>
375 /// <param name="hash"></param>
376 /// <returns></returns>
377 private bool ExistsData(NpgsqlConnection dbcon, NpgsqlTransaction transaction, byte[] hash)
378 {
379// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
380
381 bool exists = false;
382
383 using (NpgsqlCommand cmd = new NpgsqlCommand(@"SELECT ""Hash"" FROM XAssetsData WHERE ""Hash""=:Hash", dbcon))
384 {
385 cmd.Parameters.AddWithValue("Hash", hash);
386
387 try
388 {
389 using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
390 {
391 if (dbReader.Read())
392 {
393// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
394 exists = true;
395 }
396 }
397 }
398 catch (Exception e)
399 {
400 m_log.ErrorFormat(
401 "[XASSETS DB]: PGSql failure in ExistsData fetching hash {0}. Exception {1}{2}",
402 hash, e.Message, e.StackTrace);
403 }
404 }
405
406 return exists;
407 }
408
409 /// <summary>
410 /// Check if the asset exists in the database
411 /// </summary>
412 /// <param name="uuid">The asset UUID</param>
413 /// <returns>true if it exists, false otherwise.</returns>
414 public bool ExistsAsset(UUID uuid)
415 {
416// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
417
418 bool assetExists = false;
419
420 lock (m_dbLock)
421 {
422 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
423 {
424 dbcon.Open();
425 using (NpgsqlCommand cmd = new NpgsqlCommand(@"SELECT ""ID"" FROM XAssetsMeta WHERE ""ID""=:ID", dbcon))
426 {
427 cmd.Parameters.AddWithValue("ID", uuid.ToString());
428
429 try
430 {
431 using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
432 {
433 if (dbReader.Read())
434 {
435// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
436 assetExists = true;
437 }
438 }
439 }
440 catch (Exception e)
441 {
442 m_log.Error(string.Format("[XASSETS DB]: PGSql failure fetching asset {0}", uuid), e);
443 }
444 }
445 }
446 }
447
448 return assetExists;
449 }
450
451
452 /// <summary>
453 /// Returns a list of AssetMetadata objects. The list is a subset of
454 /// the entire data set offset by <paramref name="start" /> containing
455 /// <paramref name="count" /> elements.
456 /// </summary>
457 /// <param name="start">The number of results to discard from the total data set.</param>
458 /// <param name="count">The number of rows the returned list should contain.</param>
459 /// <returns>A list of AssetMetadata objects.</returns>
460 public List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
461 {
462 List<AssetMetadata> retList = new List<AssetMetadata>(count);
463
464 lock (m_dbLock)
465 {
466 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
467 {
468 dbcon.Open();
469 NpgsqlCommand cmd = new NpgsqlCommand( @"SELECT ""Name"", ""Description"", ""AccessTime"", ""AssetType"", ""Temporary"", ""ID"", ""AssetFlags"", ""CreatorID""
470 FROM XAssetsMeta
471 LIMIT :start, :count", dbcon);
472 cmd.Parameters.AddWithValue("start", start);
473 cmd.Parameters.AddWithValue("count", count);
474
475 try
476 {
477 using (NpgsqlDataReader dbReader = cmd.ExecuteReader())
478 {
479 while (dbReader.Read())
480 {
481 AssetMetadata metadata = new AssetMetadata();
482 metadata.Name = (string)dbReader["Name"];
483 metadata.Description = (string)dbReader["Description"];
484 metadata.Type = (sbyte)dbReader["AssetType"];
485 metadata.Temporary = Convert.ToBoolean(dbReader["Temporary"]); // Not sure if this is correct.
486 metadata.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
487 metadata.FullID = DBGuid.FromDB(dbReader["ID"]);
488 metadata.CreatorID = dbReader["CreatorID"].ToString();
489
490 // We'll ignore this for now - it appears unused!
491// metadata.SHA1 = dbReader["hash"]);
492
493 UpdateAccessTime(metadata, (int)dbReader["AccessTime"]);
494
495 retList.Add(metadata);
496 }
497 }
498 }
499 catch (Exception e)
500 {
501 m_log.Error("[XASSETS DB]: PGSql failure fetching asset set" + Environment.NewLine + e.ToString());
502 }
503 }
504 }
505
506 return retList;
507 }
508
509 public bool Delete(string id)
510 {
511// m_log.DebugFormat("[XASSETS DB]: Deleting asset {0}", id);
512
513 lock (m_dbLock)
514 {
515 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
516 {
517 dbcon.Open();
518
519 using (NpgsqlCommand cmd = new NpgsqlCommand(@"delete from XAssetsMeta where ""ID""=:ID", dbcon))
520 {
521 cmd.Parameters.AddWithValue("ID", id);
522 cmd.ExecuteNonQuery();
523 }
524
525 // TODO: How do we deal with data from deleted assets? Probably not easily reapable unless we
526 // keep a reference count (?)
527 }
528 }
529
530 return true;
531 }
532
533 #endregion
534 }
535}
diff --git a/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs b/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs
new file mode 100644
index 0000000..a22b882
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs
@@ -0,0 +1,330 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Data;
32using OpenMetaverse;
33using OpenSim.Framework;
34using System.Reflection;
35using System.Text;
36using log4net;
37using Npgsql;
38using NpgsqlTypes;
39
40namespace OpenSim.Data.PGSQL
41{
42 public class PGSQLXInventoryData : IXInventoryData
43 {
44// private static readonly ILog m_log = LogManager.GetLogger(
45// MethodBase.GetCurrentMethod().DeclaringType);
46
47 private PGSQLFolderHandler m_Folders;
48 private PGSQLItemHandler m_Items;
49
50 public PGSQLXInventoryData(string conn, string realm)
51 {
52 m_Folders = new PGSQLFolderHandler(
53 conn, "inventoryfolders", "InventoryStore");
54 m_Items = new PGSQLItemHandler(
55 conn, "inventoryitems", String.Empty);
56 }
57
58 public static UUID str2UUID(string strUUID)
59 {
60 UUID newUUID = UUID.Zero;
61
62 UUID.TryParse(strUUID, out newUUID);
63
64 return newUUID;
65 }
66
67 public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
68 {
69 return m_Folders.Get(fields, vals);
70 }
71
72 public XInventoryItem[] GetItems(string[] fields, string[] vals)
73 {
74 return m_Items.Get(fields, vals);
75 }
76
77 public bool StoreFolder(XInventoryFolder folder)
78 {
79 if (folder.folderName.Length > 64)
80 folder.folderName = folder.folderName.Substring(0, 64);
81 return m_Folders.Store(folder);
82 }
83
84 public bool StoreItem(XInventoryItem item)
85 {
86 if (item.inventoryName.Length > 64)
87 item.inventoryName = item.inventoryName.Substring(0, 64);
88 if (item.inventoryDescription.Length > 128)
89 item.inventoryDescription = item.inventoryDescription.Substring(0, 128);
90
91 return m_Items.Store(item);
92 }
93
94 public bool DeleteFolders(string field, string val)
95 {
96 return m_Folders.Delete(field, val);
97 }
98
99 public bool DeleteFolders(string[] fields, string[] vals)
100 {
101 return m_Folders.Delete(fields, vals);
102 }
103
104 public bool DeleteItems(string field, string val)
105 {
106 return m_Items.Delete(field, val);
107 }
108
109 public bool DeleteItems(string[] fields, string[] vals)
110 {
111 return m_Items.Delete(fields, vals);
112 }
113
114 public bool MoveItem(string id, string newParent)
115 {
116 return m_Items.MoveItem(id, newParent);
117 }
118
119 public bool MoveFolder(string id, string newParent)
120 {
121 return m_Folders.MoveFolder(id, newParent);
122 }
123
124 public XInventoryItem[] GetActiveGestures(UUID principalID)
125 {
126 return m_Items.GetActiveGestures(principalID.ToString());
127 }
128
129 public int GetAssetPermissions(UUID principalID, UUID assetID)
130 {
131 return m_Items.GetAssetPermissions(principalID, assetID);
132 }
133 }
134
135 public class PGSQLItemHandler : PGSQLInventoryHandler<XInventoryItem>
136 {
137 public PGSQLItemHandler(string c, string t, string m) :
138 base(c, t, m)
139 {
140 }
141
142 public bool MoveItem(string id, string newParent)
143 {
144 XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
145 if (retrievedItems.Length == 0)
146 return false;
147
148 UUID oldParent = retrievedItems[0].parentFolderID;
149
150 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
151 {
152 using (NpgsqlCommand cmd = new NpgsqlCommand())
153 {
154 cmd.CommandText = String.Format(@"update {0} set ""parentFolderID"" = :ParentFolderID where ""inventoryID"" = :InventoryID", m_Realm);
155 cmd.Parameters.Add(m_database.CreateParameter("ParentFolderID", newParent));
156 cmd.Parameters.Add(m_database.CreateParameter("InventoryID", id ));
157 cmd.Connection = conn;
158 conn.Open();
159
160 if (cmd.ExecuteNonQuery() == 0)
161 return false;
162 }
163 }
164
165 IncrementFolderVersion(oldParent);
166 IncrementFolderVersion(newParent);
167
168 return true;
169 }
170
171 public XInventoryItem[] GetActiveGestures(string principalID)
172 {
173 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
174 {
175 using (NpgsqlCommand cmd = new NpgsqlCommand())
176 {
177 cmd.CommandText = String.Format(@"select * from inventoryitems where ""avatarID"" = :uuid and ""assetType"" = :type and ""flags"" = 1", m_Realm);
178
179 UUID princID = UUID.Zero;
180 UUID.TryParse(principalID, out princID);
181
182 cmd.Parameters.Add(m_database.CreateParameter("uuid", principalID));
183 cmd.Parameters.Add(m_database.CreateParameter("type", (int)AssetType.Gesture));
184 cmd.Connection = conn;
185 conn.Open();
186 return DoQuery(cmd);
187 }
188 }
189 }
190
191 public int GetAssetPermissions(UUID principalID, UUID assetID)
192 {
193 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
194 {
195 using (NpgsqlCommand cmd = new NpgsqlCommand())
196 {
197 cmd.CommandText = String.Format(@"select bit_or(""inventoryCurrentPermissions"") as ""inventoryCurrentPermissions""
198 from inventoryitems
199 where ""avatarID"" = :PrincipalID
200 and ""assetID"" = :AssetID
201 group by ""assetID"" ", m_Realm);
202
203 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID));
204 cmd.Parameters.Add(m_database.CreateParameter("AssetID", assetID));
205 cmd.Connection = conn;
206 conn.Open();
207 using (NpgsqlDataReader reader = cmd.ExecuteReader())
208 {
209
210 int perms = 0;
211
212 if (reader.Read())
213 {
214 perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
215 }
216
217 return perms;
218 }
219
220 }
221 }
222 }
223
224 public override bool Store(XInventoryItem item)
225 {
226 if (!base.Store(item))
227 return false;
228
229 IncrementFolderVersion(item.parentFolderID);
230
231 return true;
232 }
233 }
234
235 public class PGSQLFolderHandler : PGSQLInventoryHandler<XInventoryFolder>
236 {
237 public PGSQLFolderHandler(string c, string t, string m) :
238 base(c, t, m)
239 {
240 }
241
242 public bool MoveFolder(string id, string newParentFolderID)
243 {
244 XInventoryFolder[] folders = Get(new string[] { "folderID" }, new string[] { id });
245
246 if (folders.Length == 0)
247 return false;
248
249 UUID oldParentFolderUUID = folders[0].parentFolderID;
250
251 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
252 {
253 using (NpgsqlCommand cmd = new NpgsqlCommand())
254 {
255 UUID foldID = UUID.Zero;
256 UUID.TryParse(id, out foldID);
257
258 UUID newPar = UUID.Zero;
259 UUID.TryParse(newParentFolderID, out newPar);
260
261 cmd.CommandText = String.Format(@"update {0} set ""parentFolderID"" = :ParentFolderID where ""folderID"" = :folderID", m_Realm);
262 cmd.Parameters.Add(m_database.CreateParameter("ParentFolderID", newPar));
263 cmd.Parameters.Add(m_database.CreateParameter("folderID", foldID));
264 cmd.Connection = conn;
265 conn.Open();
266
267 if (cmd.ExecuteNonQuery() == 0)
268 return false;
269 }
270 }
271
272 IncrementFolderVersion(oldParentFolderUUID);
273 IncrementFolderVersion(newParentFolderID);
274
275 return true;
276 }
277
278 public override bool Store(XInventoryFolder folder)
279 {
280 if (!base.Store(folder))
281 return false;
282
283 IncrementFolderVersion(folder.parentFolderID);
284
285 return true;
286 }
287 }
288
289 public class PGSQLInventoryHandler<T> : PGSQLGenericTableHandler<T> where T: class, new()
290 {
291 public PGSQLInventoryHandler(string c, string t, string m) : base(c, t, m) {}
292
293 protected bool IncrementFolderVersion(UUID folderID)
294 {
295 return IncrementFolderVersion(folderID.ToString());
296 }
297
298 protected bool IncrementFolderVersion(string folderID)
299 {
300// m_log.DebugFormat("[PGSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
301// Util.PrintCallStack();
302
303 string sql = @"update inventoryfolders set version=version+1 where ""folderID"" = :folderID";
304
305 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
306 {
307 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
308 {
309 UUID foldID = UUID.Zero;
310 UUID.TryParse(folderID, out foldID);
311
312 conn.Open();
313
314 cmd.Parameters.Add( m_database.CreateParameter("folderID", foldID) );
315
316 try
317 {
318 cmd.ExecuteNonQuery();
319 }
320 catch (Exception)
321 {
322 return false;
323 }
324 }
325 }
326
327 return true;
328 }
329 }
330}
diff --git a/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..27d0679
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
@@ -0,0 +1,65 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using System.Runtime.InteropServices;
30
31// General information about an assembly is controlled through the following
32// set of attributes. Change these attribute values to modify the information
33// associated with an assembly.
34
35[assembly : AssemblyTitle("OpenSim.Data.PGSQL")]
36[assembly : AssemblyDescription("")]
37[assembly : AssemblyConfiguration("")]
38[assembly : AssemblyCompany("http://opensimulator.org")]
39[assembly : AssemblyProduct("OpenSim.Data.PGSQL")]
40[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
41[assembly : AssemblyTrademark("")]
42[assembly : AssemblyCulture("")]
43
44// Setting ComVisible to false makes the types in this assembly not visible
45// to COM components. If you need to access a type in this assembly from
46// COM, set the ComVisible attribute to true on that type.
47
48[assembly : ComVisible(false)]
49
50// The following GUID is for the ID of the typelib if this project is exposed to COM
51
52[assembly : Guid("0e1c1ca4-2cf2-4315-b0e7-432c02feea8a")]
53
54// Version information for an assembly consists of the following four values:
55//
56// Major Version
57// Minor Version
58// Build Number
59// Revision
60//
61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below:
63
64[assembly : AssemblyVersion("0.7.6.*")]
65
diff --git a/OpenSim/Data/PGSQL/Resources/AssetStore.migrations b/OpenSim/Data/PGSQL/Resources/AssetStore.migrations
new file mode 100644
index 0000000..b6db585
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/AssetStore.migrations
@@ -0,0 +1,94 @@
1:VERSION 1
2
3CREATE TABLE assets (
4 "id" varchar(36) NOT NULL PRIMARY KEY,
5 "name" varchar(64) NOT NULL,
6 "description" varchar(64) NOT NULL,
7 "assetType" smallint NOT NULL,
8 "local" smallint NOT NULL,
9 "temporary" smallint NOT NULL,
10 "data" bytea NOT NULL
11) ;
12
13:VERSION 2
14
15BEGIN TRANSACTION;
16
17CREATE TABLE Tmp_assets
18 (
19 "id" varchar(36) NOT NULL,
20 "name" varchar(64) NOT NULL,
21 "description" varchar(64) NOT NULL,
22 "assetType" smallint NOT NULL,
23 "local" boolean NOT NULL,
24 "temporary" boolean NOT NULL,
25 "data" bytea NOT NULL
26 ) ;
27
28INSERT INTO Tmp_assets ("id", "name", "description", "assetType", "local", "temporary", "data")
29 SELECT "id", "name", "description", "assetType", case when "local" = 1 then true else false end, case when "temporary" = 1 then true else false end, "data"
30 FROM assets ;
31
32DROP TABLE assets;
33
34Alter table Tmp_assets
35 rename to assets;
36
37ALTER TABLE assets ADD PRIMARY KEY ("id");
38
39COMMIT;
40
41
42:VERSION 3
43
44BEGIN TRANSACTION;
45
46ALTER TABLE assets add "create_time" integer default 0;
47ALTER TABLE assets add "access_time" integer default 0;
48
49COMMIT;
50
51
52:VERSION 4
53
54BEGIN TRANSACTION;
55
56CREATE TABLE Tmp_assets
57 (
58 "id" uuid NOT NULL,
59 "name" varchar(64) NOT NULL,
60 "description" varchar(64) NOT NULL,
61 "assetType" smallint NOT NULL,
62 "local" boolean NOT NULL,
63 "temporary" boolean NOT NULL,
64 "data" bytea NOT NULL,
65 "create_time" int NULL,
66 "access_time" int NULL
67 ) ;
68
69
70INSERT INTO Tmp_assets ("id", "name", "description", "assetType", "local", "temporary", "data", "create_time", "access_time")
71 SELECT cast("id" as uuid), "name", "description", "assetType", "local", "temporary", "data", "create_time", "access_time"
72 FROM assets ;
73
74DROP TABLE assets;
75
76Alter table Tmp_assets
77 rename to assets;
78
79 ALTER TABLE assets ADD PRIMARY KEY ("id");
80
81COMMIT;
82
83
84:VERSION 5
85
86DELETE FROM assets WHERE "id" = 'dc4b9f0b-d008-45c6-96a4-01dd947ac621';
87
88:VERSION 6
89
90ALTER TABLE assets ADD "asset_flags" INTEGER NOT NULL DEFAULT 0;
91
92:VERSION 7
93
94alter table assets add "creatorid" varchar(36) not null default '';
diff --git a/OpenSim/Data/PGSQL/Resources/AuthStore.migrations b/OpenSim/Data/PGSQL/Resources/AuthStore.migrations
new file mode 100644
index 0000000..a1f5b61
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/AuthStore.migrations
@@ -0,0 +1,32 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE auth (
6 uuid uuid NOT NULL default '00000000-0000-0000-0000-000000000000',
7 "passwordHash" varchar(32) NOT NULL,
8 "passwordSalt" varchar(32) NOT NULL,
9 "webLoginKey" varchar(255) NOT NULL,
10 "accountType" VARCHAR(32) NOT NULL DEFAULT 'UserAccount'
11) ;
12
13CREATE TABLE tokens (
14 uuid uuid NOT NULL default '00000000-0000-0000-0000-000000000000',
15 token varchar(255) NOT NULL,
16 validity TIMESTAMP NOT NULL )
17 ;
18
19COMMIT;
20
21:VERSION 2
22
23BEGIN TRANSACTION;
24
25 INSERT INTO auth (uuid, "passwordHash", "passwordSalt", "webLoginKey", "accountType")
26 SELECT uuid AS UUID, passwordHash AS passwordHash, passwordSalt AS passwordSalt, webLoginKey AS webLoginKey, 'UserAccount' as accountType
27 FROM users
28 where exists ( Select * from information_schema.tables where table_name = 'users' )
29 ;
30
31COMMIT;
32
diff --git a/OpenSim/Data/PGSQL/Resources/Avatar.migrations b/OpenSim/Data/PGSQL/Resources/Avatar.migrations
new file mode 100644
index 0000000..160086d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/Avatar.migrations
@@ -0,0 +1,59 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE Avatars (
6"PrincipalID" uuid NOT NULL PRIMARY KEY,
7"Name" varchar(32) NOT NULL,
8"Value" varchar(255) NOT NULL DEFAULT ''
9);
10
11
12COMMIT;
13
14:VERSION 2
15
16BEGIN TRANSACTION;
17
18CREATE TABLE Tmp_Avatars
19 (
20 "PrincipalID" uuid NOT NULL,
21 "Name" varchar(32) NOT NULL,
22 "Value" text NOT NULL DEFAULT ''
23 ) ;
24
25 INSERT INTO Tmp_Avatars ("PrincipalID", "Name", "Value")
26 SELECT "PrincipalID", cast("Name" as text), "Value"
27 FROM Avatars ;
28
29DROP TABLE Avatars;
30
31Alter table Tmp_Avatars
32 rename to Avatars;
33
34COMMIT;
35
36:VERSION 3
37
38BEGIN TRANSACTION;
39
40CREATE TABLE Tmp_Avatars
41 (
42 "PrincipalID" uuid NOT NULL,
43 "Name" varchar(32) NOT NULL,
44 "Value" text NOT NULL DEFAULT ''
45);
46
47ALTER TABLE Tmp_Avatars ADD PRIMARY KEY ("PrincipalID", "Name");
48
49
50INSERT INTO Tmp_Avatars ("PrincipalID", "Name", "Value")
51 SELECT "PrincipalID", "Name", cast("Value" as text) FROM Avatars ;
52
53DROP TABLE Avatars;
54
55Alter table Tmp_Avatars
56 rename to Avatars;
57
58COMMIT;
59
diff --git a/OpenSim/Data/PGSQL/Resources/EstateStore.migrations b/OpenSim/Data/PGSQL/Resources/EstateStore.migrations
new file mode 100644
index 0000000..59270f8
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/EstateStore.migrations
@@ -0,0 +1,307 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE estate_managers(
6 "EstateID" int NOT NULL Primary Key,
7 uuid varchar(36) NOT NULL
8 );
9
10CREATE TABLE estate_groups(
11 "EstateID" int NOT NULL,
12 uuid varchar(36) NOT NULL
13 );
14
15
16CREATE TABLE estate_users(
17 "EstateID" int NOT NULL,
18 uuid varchar(36) NOT NULL
19 );
20
21
22CREATE TABLE estateban(
23 "EstateID" int NOT NULL,
24 "bannedUUID" varchar(36) NOT NULL,
25 "bannedIp" varchar(16) NOT NULL,
26 "bannedIpHostMask" varchar(16) NOT NULL,
27 "bannedNameMask" varchar(64) NULL DEFAULT NULL
28 );
29
30Create Sequence estate_settings_id increment by 100 start with 100;
31
32CREATE TABLE estate_settings(
33 "EstateID" integer DEFAULT nextval('estate_settings_id') NOT NULL,
34 "EstateName" varchar(64) NULL DEFAULT (NULL),
35 "AbuseEmailToEstateOwner" boolean NOT NULL,
36 "DenyAnonymous" boolean NOT NULL,
37 "ResetHomeOnTeleport" boolean NOT NULL,
38 "FixedSun" boolean NOT NULL,
39 "DenyTransacted" boolean NOT NULL,
40 "BlockDwell" boolean NOT NULL,
41 "DenyIdentified" boolean NOT NULL,
42 "AllowVoice" boolean NOT NULL,
43 "UseGlobalTime" boolean NOT NULL,
44 "PricePerMeter" int NOT NULL,
45 "TaxFree" boolean NOT NULL,
46 "AllowDirectTeleport" boolean NOT NULL,
47 "RedirectGridX" int NOT NULL,
48 "RedirectGridY" int NOT NULL,
49 "ParentEstateID" int NOT NULL,
50 "SunPosition" double precision NOT NULL,
51 "EstateSkipScripts" boolean NOT NULL,
52 "BillableFactor" double precision NOT NULL,
53 "PublicAccess" boolean NOT NULL,
54 "AbuseEmail" varchar(255) NOT NULL,
55 "EstateOwner" varchar(36) NOT NULL,
56 "DenyMinors" boolean NOT NULL
57 );
58
59
60CREATE TABLE estate_map(
61 "RegionID" varchar(36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
62 "EstateID" int NOT NULL
63 );
64
65COMMIT;
66
67:VERSION 2
68
69BEGIN TRANSACTION;
70
71CREATE INDEX IX_estate_managers ON estate_managers
72 (
73 "EstateID"
74 );
75
76
77CREATE INDEX IX_estate_groups ON estate_groups
78 (
79 "EstateID"
80 );
81
82
83CREATE INDEX IX_estate_users ON estate_users
84 (
85 "EstateID"
86 );
87
88COMMIT;
89
90:VERSION 3
91
92BEGIN TRANSACTION;
93
94CREATE TABLE Tmp_estateban
95 (
96 "EstateID" int NOT NULL,
97 "bannedUUID" varchar(36) NOT NULL,
98 "bannedIp" varchar(16) NULL,
99 "bannedIpHostMask" varchar(16) NULL,
100 "bannedNameMask" varchar(64) NULL
101 );
102
103 INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask")
104 SELECT "EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban;
105
106DROP TABLE estateban;
107
108Alter table Tmp_estateban
109 rename to estateban;
110
111CREATE INDEX IX_estateban ON estateban
112 (
113 "EstateID"
114 );
115
116COMMIT;
117
118
119:VERSION 4
120
121BEGIN TRANSACTION;
122
123CREATE TABLE Tmp_estate_managers
124 (
125 "EstateID" int NOT NULL,
126 uuid uuid NOT NULL
127 );
128
129INSERT INTO Tmp_estate_managers ("EstateID", uuid)
130 SELECT "EstateID", cast(uuid as uuid) FROM estate_managers;
131
132DROP TABLE estate_managers;
133
134Alter table Tmp_estate_managers
135 rename to estate_managers;
136
137CREATE INDEX IX_estate_managers ON estate_managers
138 (
139 "EstateID"
140 );
141
142COMMIT;
143
144
145:VERSION 5
146
147BEGIN TRANSACTION;
148
149CREATE TABLE Tmp_estate_groups
150 (
151 "EstateID" int NOT NULL,
152 uuid uuid NOT NULL
153 ) ;
154
155 INSERT INTO Tmp_estate_groups ("EstateID", uuid)
156 SELECT "EstateID", cast(uuid as uuid) FROM estate_groups;
157
158DROP TABLE estate_groups;
159
160Alter table Tmp_estate_groups
161 rename to estate_groups;
162
163CREATE INDEX IX_estate_groups ON estate_groups
164 (
165 "EstateID"
166 );
167
168COMMIT;
169
170
171:VERSION 6
172
173BEGIN TRANSACTION;
174
175CREATE TABLE Tmp_estate_users
176 (
177 "EstateID" int NOT NULL,
178 uuid uuid NOT NULL
179 );
180
181INSERT INTO Tmp_estate_users ("EstateID", uuid)
182 SELECT "EstateID", cast(uuid as uuid) FROM estate_users ;
183
184DROP TABLE estate_users;
185
186Alter table Tmp_estate_users
187 rename to estate_users;
188
189CREATE INDEX IX_estate_users ON estate_users
190 (
191 "EstateID"
192 );
193
194COMMIT;
195
196
197:VERSION 7
198
199BEGIN TRANSACTION;
200
201CREATE TABLE Tmp_estateban
202 (
203 "EstateID" int NOT NULL,
204 "bannedUUID" uuid NOT NULL,
205 "bannedIp" varchar(16) NULL,
206 "bannedIpHostMask" varchar(16) NULL,
207 "bannedNameMask" varchar(64) NULL
208 );
209
210INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask")
211 SELECT "EstateID", cast("bannedUUID" as uuid), "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban ;
212
213DROP TABLE estateban;
214
215Alter table Tmp_estateban
216 rename to estateban;
217
218CREATE INDEX IX_estateban ON estateban
219 (
220 "EstateID"
221 );
222
223COMMIT;
224
225
226:VERSION 8
227
228BEGIN TRANSACTION;
229
230CREATE TABLE Tmp_estate_settings
231 (
232 "EstateID" integer default nextval('estate_settings_id') NOT NULL,
233 "EstateName" varchar(64) NULL DEFAULT (NULL),
234 "AbuseEmailToEstateOwner" boolean NOT NULL,
235 "DenyAnonymous" boolean NOT NULL,
236 "ResetHomeOnTeleport" boolean NOT NULL,
237 "FixedSun" boolean NOT NULL,
238 "DenyTransacted" boolean NOT NULL,
239 "BlockDwell" boolean NOT NULL,
240 "DenyIdentified" boolean NOT NULL,
241 "AllowVoice" boolean NOT NULL,
242 "UseGlobalTime" boolean NOT NULL,
243 "PricePerMeter" int NOT NULL,
244 "TaxFree" boolean NOT NULL,
245 "AllowDirectTeleport" boolean NOT NULL,
246 "RedirectGridX" int NOT NULL,
247 "RedirectGridY" int NOT NULL,
248 "ParentEstateID" int NOT NULL,
249 "SunPosition" double precision NOT NULL,
250 "EstateSkipScripts" boolean NOT NULL,
251 "BillableFactor" double precision NOT NULL,
252 "PublicAccess" boolean NOT NULL,
253 "AbuseEmail" varchar(255) NOT NULL,
254 "EstateOwner" uuid NOT NULL,
255 "DenyMinors" boolean NOT NULL
256 );
257
258INSERT INTO Tmp_estate_settings ("EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", "EstateOwner", "DenyMinors")
259 SELECT "EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", cast("EstateOwner" as uuid), "DenyMinors" FROM estate_settings ;
260
261DROP TABLE estate_settings;
262
263
264Alter table Tmp_estate_settings
265 rename to estate_settings;
266
267
268Create index on estate_settings (lower("EstateName"));
269
270COMMIT;
271
272
273:VERSION 9
274
275BEGIN TRANSACTION;
276
277CREATE TABLE Tmp_estate_map
278 (
279 "RegionID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
280 "EstateID" int NOT NULL
281 );
282
283INSERT INTO Tmp_estate_map ("RegionID", "EstateID")
284 SELECT cast("RegionID" as uuid), "EstateID" FROM estate_map ;
285
286DROP TABLE estate_map;
287
288Alter table Tmp_estate_map
289 rename to estate_map;
290
291COMMIT;
292
293:VERSION 10
294
295BEGIN TRANSACTION;
296ALTER TABLE estate_settings ADD COLUMN "AllowLandmark" boolean NOT NULL default true;
297ALTER TABLE estate_settings ADD COLUMN "AllowParcelChanges" boolean NOT NULL default true;
298ALTER TABLE estate_settings ADD COLUMN "AllowSetHome" boolean NOT NULL default true;
299COMMIT;
300
301:VERSION 11
302
303Begin transaction;
304
305
306Commit;
307
diff --git a/OpenSim/Data/PGSQL/Resources/FriendsStore.migrations b/OpenSim/Data/PGSQL/Resources/FriendsStore.migrations
new file mode 100644
index 0000000..a87199b
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/FriendsStore.migrations
@@ -0,0 +1,44 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE Friends (
6"PrincipalID" uuid NOT NULL,
7"Friend" varchar(255) NOT NULL,
8"Flags" char(16) NOT NULL DEFAULT '0',
9"Offered" varchar(32) NOT NULL DEFAULT 0);
10
11
12COMMIT;
13
14:VERSION 2
15
16BEGIN TRANSACTION;
17
18INSERT INTO Friends ("PrincipalID", "Friend", "Flags", "Offered")
19SELECT "ownerID", "friendID", "friendPerms", 0 FROM userfriends;
20
21COMMIT;
22
23:VERSION 3
24
25BEGIN TRANSACTION;
26
27CREATE TABLE Tmp_Friends
28 ("PrincipalID" varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
29 "Friend" varchar(255) NOT NULL,
30 "Flags" char(16) NOT NULL DEFAULT '0',
31 "Offered" varchar(32) NOT NULL DEFAULT 0) ;
32
33INSERT INTO Tmp_Friends ("PrincipalID", "Friend", "Flags", "Offered")
34 SELECT cast("PrincipalID" as varchar(255)), "Friend", "Flags", "Offered" FROM Friends ;
35
36DROP TABLE Friends;
37
38Alter table Tmp_Friends
39 rename to Friends;
40
41ALTER TABLE Friends ADD PRIMARY KEY("PrincipalID", "Friend");
42
43
44COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/GridStore.migrations b/OpenSim/Data/PGSQL/Resources/GridStore.migrations
new file mode 100644
index 0000000..0ab8d2b
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/GridStore.migrations
@@ -0,0 +1,242 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE regions(
6 "regionHandle" varchar(255) NULL,
7 "regionName" varchar(255) NULL,
8 uuid varchar(255) NOT NULL PRIMARY KEY,
9 "regionRecvKey" varchar(255) NULL,
10 "regionSecret" varchar(255) NULL,
11 "regionSendKey" varchar(255) NULL,
12 "regionDataURI" varchar(255) NULL,
13 "serverIP" varchar(255) NULL,
14 "serverPort" varchar(255) NULL,
15 "serverURI" varchar(255) NULL,
16 "locX" varchar(255) NULL,
17 "locY" varchar(255) NULL,
18 "locZ" varchar(255) NULL,
19 "eastOverrideHandle" varchar(255) NULL,
20 "westOverrideHandle" varchar(255) NULL,
21 "southOverrideHandle" varchar(255) NULL,
22 "northOverrideHandle" varchar(255) NULL,
23 "regionAssetURI" varchar(255) NULL,
24 "regionAssetRecvKey" varchar(255) NULL,
25 "regionAssetSendKey" varchar(255) NULL,
26 "regionUserURI" varchar(255) NULL,
27 "regionUserRecvKey" varchar(255) NULL,
28 "regionUserSendKey" varchar(255) NULL,
29 "regionMapTexture" varchar(255) NULL,
30 "serverHttpPort" varchar(255) NULL,
31 "serverRemotingPort" varchar(255) NULL,
32 "owner_uuid" varchar(36) NULL
33);
34
35COMMIT;
36
37
38:VERSION 2
39
40BEGIN TRANSACTION;
41
42CREATE TABLE Tmp_regions
43 (
44 uuid varchar(36) NOT NULL,
45 "regionHandle" bigint NULL,
46 "regionName" varchar(20) NULL,
47 "regionRecvKey" varchar(128) NULL,
48 "regionSendKey" varchar(128) NULL,
49 "regionSecret" varchar(128) NULL,
50 "regionDataURI" varchar(128) NULL,
51 "serverIP" varchar(64) NULL,
52 "serverPort" int NULL,
53 "serverURI" varchar(255) NULL,
54 "locX" int NULL,
55 "locY" int NULL,
56 "locZ" int NULL,
57 "eastOverrideHandle" bigint NULL,
58 "westOverrideHandle" bigint NULL,
59 "southOverrideHandle" bigint NULL,
60 "northOverrideHandle" bigint NULL,
61 "regionAssetURI" varchar(255) NULL,
62 "regionAssetRecvKey" varchar(128) NULL,
63 "regionAssetSendKey" varchar(128) NULL,
64 "regionUserURI" varchar(255) NULL,
65 "regionUserRecvKey" varchar(128) NULL,
66 "regionUserSendKey" varchar(128) NULL,
67 "regionMapTexture" varchar(36) NULL,
68 "serverHttpPort" int NULL,
69 "serverRemotingPort" int NULL,
70 "owner_uuid" varchar(36) NULL,
71 "originUUID" varchar(36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000')
72 );
73
74INSERT INTO Tmp_regions (uuid, "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", "regionMapTexture", "serverHttpPort", "serverRemotingPort", "owner_uuid")
75 SELECT cast(uuid as varchar(36)), cast("regionHandle" as bigint), cast("regionName" as varchar(20)), cast("regionRecvKey" as varchar(128)), cast("regionSendKey" as varchar(128)), cast("regionSecret" as varchar(128)), cast("regionDataURI" as varchar(128)), cast("serverIP" as varchar(64)), cast("serverPort" as int), "serverURI", cast("locX" as int), cast("locY" as int), cast("locZ" as int), cast("eastOverrideHandle" as bigint), cast("westOverrideHandle" as bigint),
76 cast("southOverrideHandle" as bigint), cast("northOverrideHandle" as bigint), "regionAssetURI", cast("regionAssetRecvKey" as varchar(128)), cast("regionAssetSendKey" as varchar(128)), "regionUserURI", cast("regionUserRecvKey" as varchar(128)), cast("regionUserSendKey" as varchar(128)), cast("regionMapTexture" as varchar(36)),
77 cast("serverHttpPort" as int), cast("serverRemotingPort" as int), "owner_uuid"
78 FROM regions;
79
80DROP TABLE regions;
81
82alter table Tmp_regions
83 rename to regions;
84
85COMMIT;
86
87:VERSION 3
88
89BEGIN TRANSACTION;
90
91CREATE INDEX IX_regions_name ON regions
92 (
93 "regionName"
94 );
95
96CREATE INDEX IX_regions_handle ON regions
97 (
98 "regionHandle"
99 );
100
101
102CREATE INDEX IX_regions_override ON regions
103 (
104 "eastOverrideHandle",
105 "westOverrideHandle",
106 "southOverrideHandle",
107 "northOverrideHandle"
108 );
109
110COMMIT;
111
112
113:VERSION 4
114
115/* To prevent any potential data loss issues, you should review this script in detail before running it outside the cotext of the database designer.*/
116BEGIN TRANSACTION;
117
118CREATE TABLE Tmp_regions
119 (
120 uuid uuid NOT NULL,
121 "regionHandle" bigint NULL,
122 "regionName" varchar(20) NULL,
123 "regionRecvKey" varchar(128) NULL,
124 "regionSendKey" varchar(128) NULL,
125 "regionSecret" varchar(128) NULL,
126 "regionDataURI" varchar(128) NULL,
127 "serverIP" varchar(64) NULL,
128 "serverPort" int NULL,
129 "serverURI" varchar(255) NULL,
130 "locX" int NULL,
131 "locY" int NULL,
132 "locZ" int NULL,
133 "eastOverrideHandle" bigint NULL,
134 "westOverrideHandle" bigint NULL,
135 "southOverrideHandle" bigint NULL,
136 "northOverrideHandle" bigint NULL,
137 "regionAssetURI" varchar(255) NULL,
138 "regionAssetRecvKey" varchar(128) NULL,
139 "regionAssetSendKey" varchar(128) NULL,
140 "regionUserURI" varchar(255) NULL,
141 "regionUserRecvKey" varchar(128) NULL,
142 "regionUserSendKey" varchar(128) NULL,
143 "regionMapTexture" uuid NULL,
144 "serverHttpPort" int NULL,
145 "serverRemotingPort" int NULL,
146 "owner_uuid" uuid NOT NULL,
147 "originUUID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000')
148 );
149
150
151INSERT INTO Tmp_regions (uuid, "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", "regionMapTexture", "serverHttpPort", "serverRemotingPort", "owner_uuid", "originUUID")
152 SELECT cast(uuid as uuid), "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", cast("regionMapTexture" as uuid), "serverHttpPort", "serverRemotingPort", cast( "owner_uuid" as uuid), cast("originUUID" as uuid) FROM regions ;
153
154
155DROP TABLE regions;
156
157alter table Tmp_regions rename to regions;
158
159ALTER TABLE regions ADD CONSTRAINT
160 PK__regions__uuid PRIMARY KEY
161 (
162 uuid
163 );
164
165CREATE INDEX IX_regions_name ON regions
166 (
167 "regionName"
168 );
169
170CREATE INDEX IX_regions_handle ON regions
171 (
172 "regionHandle"
173 );
174
175CREATE INDEX IX_regions_override ON regions
176 (
177 "eastOverrideHandle",
178 "westOverrideHandle",
179 "southOverrideHandle",
180 "northOverrideHandle"
181 );
182
183COMMIT;
184
185
186:VERSION 5
187
188BEGIN TRANSACTION;
189
190ALTER TABLE regions ADD access int default 0;
191
192COMMIT;
193
194
195:VERSION 6
196
197BEGIN TRANSACTION;
198
199ALTER TABLE regions ADD "ScopeID" uuid default '00000000-0000-0000-0000-000000000000';
200ALTER TABLE regions alter column "owner_uuid" set DEFAULT ('00000000-0000-0000-0000-000000000000');
201ALTER TABLE regions ADD "sizeX" integer not null default 0;
202ALTER TABLE regions ADD "sizeY" integer not null default 0;
203
204COMMIT;
205
206
207:VERSION 7
208
209BEGIN TRANSACTION;
210
211ALTER TABLE regions ADD "flags" integer NOT NULL DEFAULT 0;
212CREATE INDEX flags ON regions("flags");
213ALTER TABLE regions ADD "last_seen" integer NOT NULL DEFAULT 0;
214ALTER TABLE regions ADD "PrincipalID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
215ALTER TABLE regions ADD "Token" varchar(255) NOT NULL DEFAULT 0;
216
217COMMIT;
218
219:VERSION 8
220
221BEGIN TRANSACTION;
222ALTER TABLE regions ALTER COLUMN "regionName" type VarChar(128) ;
223
224DROP INDEX IX_regions_name;
225ALTER TABLE regions ALTER COLUMN "regionName" type VarChar(128),
226 ALTER COLUMN "regionName" SET NOT NULL;
227
228CREATE INDEX IX_regions_name ON regions
229 (
230 "regionName"
231 );
232
233COMMIT;
234
235:VERSION 9
236
237BEGIN TRANSACTION;
238
239ALTER TABLE regions ADD "parcelMapTexture" uuid NULL;
240
241COMMIT;
242
diff --git a/OpenSim/Data/PGSQL/Resources/GridUserStore.migrations b/OpenSim/Data/PGSQL/Resources/GridUserStore.migrations
new file mode 100644
index 0000000..d37c4f6d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/GridUserStore.migrations
@@ -0,0 +1,60 @@
1:VERSION 1 # --------------------------
2
3BEGIN TRANSACTION;
4
5CREATE TABLE GridUser (
6 "UserID" VARCHAR(255) NOT NULL Primary Key,
7 "HomeRegionID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
8 "HomePosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
9 "HomeLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
10 "LastRegionID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
11 "LastPosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
12 "LastLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
13 "Online" CHAR(5) NOT NULL DEFAULT 'false',
14 "Login" CHAR(16) NOT NULL DEFAULT '0',
15 "Logout" CHAR(16) NOT NULL DEFAULT '0'
16) ;
17
18COMMIT;
19
20:VERSION 2 # --------------------------
21
22BEGIN TRANSACTION;
23
24CREATE TABLE GridUser_tmp (
25 "UserID" VARCHAR(255) NOT NULL PRIMARY KEY,
26 "HomeRegionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
27 "HomePosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
28 "HomeLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
29 "LastRegionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
30 "LastPosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
31 "LastLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
32 "Online" CHAR(5) NOT NULL DEFAULT 'false',
33 "Login" CHAR(16) NOT NULL DEFAULT '0',
34 "Logout" CHAR(16) NOT NULL DEFAULT '0'
35 );
36
37COMMIT;
38
39
40INSERT INTO GridUser_tmp ("UserID"
41 ,"HomeRegionID"
42 ,"HomePosition"
43 ,"HomeLookAt"
44 ,"LastRegionID"
45 ,"LastPosition"
46 ,"LastLookAt"
47 ,"Online"
48 ,"Login"
49 ,"Logout")
50 SELECT "UserID", cast("HomeRegionID" as uuid), "HomePosition" ,"HomeLookAt" , cast("LastRegionID" as uuid),
51 "LastPosition"
52 ,"LastLookAt"
53 ,"Online"
54 ,"Login"
55 ,"Logout" FROM GridUser;
56
57DROP TABLE GridUser;
58
59alter table GridUser_tmp rename to GridUser;
60
diff --git a/OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations b/OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations
new file mode 100644
index 0000000..adf126d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations
@@ -0,0 +1,17 @@
1:VERSION 1 # --------------------------
2
3BEGIN;
4
5CREATE TABLE hg_traveling_data (
6 "SessionID" VARCHAR(36) NOT NULL Primary Key,
7 "UserID" VARCHAR(36) NOT NULL,
8 "GridExternalName" VARCHAR(255) NOT NULL DEFAULT '',
9 "ServiceToken" VARCHAR(255) NOT NULL DEFAULT '',
10 "ClientIPAddress" VARCHAR(16) NOT NULL DEFAULT '',
11 "MyIPAddress" VARCHAR(16) NOT NULL DEFAULT '',
12 "TMStamp" timestamp NOT NULL default now()
13);
14
15
16COMMIT;
17
diff --git a/OpenSim/Data/PGSQL/Resources/IM_Store.migrations b/OpenSim/Data/PGSQL/Resources/IM_Store.migrations
new file mode 100644
index 0000000..70dc011
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/IM_Store.migrations
@@ -0,0 +1,26 @@
1:VERSION 1 # --------------------------
2
3BEGIN Transaction;
4
5Create Sequence im_offiline_id increment by 1 start with 1;
6
7CREATE TABLE im_offline (
8 "ID" integer PRIMARY KEY NOT NULL DEFAULT nextval('im_offiline_id') ,
9 "PrincipalID" char(36) NOT NULL default '',
10 "Message" text NOT NULL,
11 "TMStamp" timestamp NOT NULL default now()
12);
13
14COMMIT;
15
16:VERSION 2 # --------------------------
17
18BEGIN;
19
20/*
21INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
22DROP TABLE `diva_im_offline`;
23DELETE FROM `migrations` WHERE name='diva_im_Store';
24*/
25
26COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/InventoryStore.migrations b/OpenSim/Data/PGSQL/Resources/InventoryStore.migrations
new file mode 100644
index 0000000..8f7982a
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/InventoryStore.migrations
@@ -0,0 +1,220 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE inventoryfolders (
6 "folderID" varchar(36) NOT NULL default '' PRIMARY KEY,
7 "agentID" varchar(36) default NULL,
8 "parentFolderID" varchar(36) default NULL,
9 "folderName" varchar(64) default NULL,
10 "type" smallint NOT NULL default 0,
11 "version" int NOT NULL default 0
12);
13
14
15CREATE INDEX owner ON inventoryfolders
16(
17 "agentID" ASC
18);
19
20CREATE INDEX parent ON inventoryfolders
21(
22 "parentFolderID" ASC
23);
24
25
26CREATE TABLE inventoryitems (
27 "inventoryID" varchar(36) NOT NULL default '' Primary Key,
28 "assetID" varchar(36) default NULL,
29 "assetType" int default NULL,
30 "parentFolderID" varchar(36) default NULL,
31 "avatarID" varchar(36) default NULL,
32 "inventoryName" varchar(64) default NULL,
33 "inventoryDescription" varchar(128) default NULL,
34 "inventoryNextPermissions" int default NULL,
35 "inventoryCurrentPermissions" int default NULL,
36 "invType" int default NULL,
37 "creatorID" varchar(36) default NULL,
38 "inventoryBasePermissions" int NOT NULL default 0,
39 "inventoryEveryOnePermissions" int NOT NULL default 0,
40 "salePrice" int default NULL,
41 "saleType" smallint default NULL,
42 "creationDate" int default NULL,
43 "groupID" varchar(36) default NULL,
44 "groupOwned" boolean default NULL,
45 "flags" int default NULL
46);
47
48
49CREATE INDEX ii_owner ON inventoryitems
50(
51 "avatarID" ASC
52);
53
54CREATE INDEX ii_folder ON inventoryitems
55(
56 "parentFolderID" ASC
57);
58
59COMMIT;
60
61
62:VERSION 2
63
64BEGIN TRANSACTION;
65
66ALTER TABLE inventoryitems ADD "inventoryGroupPermissions" INTEGER NOT NULL default 0;
67
68COMMIT;
69
70:VERSION 3
71
72/* To prevent any potential data loss issues, you should review this script in detail before running it outside the cotext of the database designer.*/
73BEGIN TRANSACTION;
74
75CREATE TABLE Tmp_inventoryfolders
76 (
77 "folderID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
78 "agentID" uuid NULL DEFAULT (NULL),
79 "parentFolderID" uuid NULL DEFAULT (NULL),
80 "folderName" varchar(64) NULL DEFAULT (NULL),
81 "type" smallint NOT NULL DEFAULT ((0)),
82 "version" int NOT NULL DEFAULT ((0))
83 );
84
85 INSERT INTO Tmp_inventoryfolders ("folderID", "agentID", "parentFolderID", "folderName", type, version)
86 SELECT cast("folderID" as uuid), cast("agentID" as uuid), cast("parentFolderID" as uuid), "folderName", "type", "version"
87 FROM inventoryfolders;
88
89DROP TABLE inventoryfolders;
90
91alter table Tmp_inventoryfolders rename to inventoryfolders;
92
93ALTER TABLE inventoryfolders ADD CONSTRAINT
94 PK__inventor__C2FABFB3173876EA PRIMARY KEY
95 (
96 "folderID"
97 );
98
99CREATE INDEX owner ON inventoryfolders
100 (
101 "agentID"
102 );
103
104CREATE INDEX parent ON inventoryfolders
105 (
106 "parentFolderID"
107 );
108
109COMMIT;
110
111
112:VERSION 4
113
114BEGIN TRANSACTION;
115
116CREATE TABLE Tmp_inventoryitems
117 (
118 "inventoryID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
119 "assetID" uuid NULL DEFAULT (NULL),
120 "assetType" int NULL DEFAULT (NULL),
121 "parentFolderID" uuid NULL DEFAULT (NULL),
122 "avatarID" uuid NULL DEFAULT (NULL),
123 "inventoryName" varchar(64) NULL DEFAULT (NULL),
124 "inventoryDescription" varchar(128) NULL DEFAULT (NULL),
125 "inventoryNextPermissions" int NULL DEFAULT (NULL),
126 "inventoryCurrentPermissions" int NULL DEFAULT (NULL),
127 "invType" int NULL DEFAULT (NULL),
128 "creatorID" uuid NULL DEFAULT (NULL),
129 "inventoryBasePermissions" int NOT NULL DEFAULT ((0)),
130 "inventoryEveryOnePermissions" int NOT NULL DEFAULT ((0)),
131 "salePrice" int NULL DEFAULT (NULL),
132 "SaleType" smallint NULL DEFAULT (NULL),
133 "creationDate" int NULL DEFAULT (NULL),
134 "groupID" uuid NULL DEFAULT (NULL),
135 "groupOwned" boolean NULL DEFAULT (NULL),
136 "flags" int NULL DEFAULT (NULL),
137 "inventoryGroupPermissions" int NOT NULL DEFAULT ((0))
138 );
139
140
141 INSERT INTO Tmp_inventoryitems ("inventoryID", "assetID", "assetType", "parentFolderID", "avatarID", "inventoryName", "inventoryDescription", "inventoryNextPermissions", "inventoryCurrentPermissions", "invType", "creatorID", "inventoryBasePermissions", "inventoryEveryOnePermissions", "salePrice", "SaleType", "creationDate", "groupID", "groupOwned", "flags", "inventoryGroupPermissions")
142 SELECT cast("inventoryID" as uuid), cast("assetID" as uuid), "assetType", cast("parentFolderID" as uuid), cast("avatarID" as uuid), "inventoryName", "inventoryDescription", "inventoryNextPermissions", "inventoryCurrentPermissions", "invType", cast("creatorID" as uuid), "inventoryBasePermissions", "inventoryEveryOnePermissions", "salePrice", "SaleType", "creationDate", cast("groupID" as uuid), "groupOwned", "flags", "inventoryGroupPermissions"
143 FROM inventoryitems ;
144
145DROP TABLE inventoryitems;
146
147alter table Tmp_inventoryitems rename to inventoryitems;
148
149ALTER TABLE inventoryitems ADD CONSTRAINT
150 PK__inventor__C4B7BC2220C1E124 PRIMARY KEY
151 (
152 "inventoryID"
153 );
154
155
156CREATE INDEX ii2_owner ON inventoryitems
157 (
158 "avatarID"
159 );
160
161CREATE INDEX ii2_folder ON inventoryitems
162 (
163 "parentFolderID"
164 );
165
166COMMIT;
167
168:VERSION 5
169
170
171BEGIN TRANSACTION;
172
173-- # Restoring defaults:
174-- # NOTE: "inventoryID" does NOT need one: it's NOT NULL PK and a unique Guid must be provided every time anyway!
175
176alter table inventoryitems
177 alter column "inventoryBasePermissions" set default 0;
178alter table inventoryitems
179 alter column "inventoryEveryOnePermissions" set default 0;
180alter table inventoryitems
181 alter column "inventoryGroupPermissions" set default 0 ;
182
183COMMIT ;
184
185:VERSION 7
186
187BEGIN TRANSACTION;
188
189-- # "creatorID" goes back to VARCHAR(36) (???)
190
191alter table inventoryitems
192 alter column "creatorID" type varchar(36);
193
194COMMIT ;
195
196:VERSION 8
197
198ALTER TABLE inventoryitems
199 alter column "creatorID" set DEFAULT '00000000-0000-0000-0000-000000000000';
200
201
202:VERSION 9
203
204BEGIN TRANSACTION;
205
206--# "creatorID" goes up to VARCHAR(255)
207
208alter table inventoryitems
209 alter column "creatorID" type varchar(255);
210
211Commit;
212
213:VERSION 10
214
215BEGIN TRANSACTION;
216
217Alter table inventoryitems Rename Column "SaleType" to "saleType";
218
219Commit;
220
diff --git a/OpenSim/Data/PGSQL/Resources/LogStore.migrations b/OpenSim/Data/PGSQL/Resources/LogStore.migrations
new file mode 100644
index 0000000..83727c6
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/LogStore.migrations
@@ -0,0 +1,16 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE logs (
6 "logID" int NOT NULL Primary Key,
7 "target" varchar(36) default NULL,
8 "server" varchar(64) default NULL,
9 "method" varchar(64) default NULL,
10 "arguments" varchar(255) default NULL,
11 "priority" int default NULL,
12 "message" text
13);
14
15COMMIT;
16
diff --git a/OpenSim/Data/PGSQL/Resources/Presence.migrations b/OpenSim/Data/PGSQL/Resources/Presence.migrations
new file mode 100644
index 0000000..684faa2
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/Presence.migrations
@@ -0,0 +1,30 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE Presence (
6"UserID" varchar(255) NOT NULL,
7"RegionID" uuid NOT NULL,
8"SessionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
9"SecureSessionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
10);
11
12
13COMMIT;
14
15:VERSION 2
16
17BEGIN TRANSACTION;
18
19CREATE UNIQUE INDEX SessionID ON Presence("SessionID");
20CREATE INDEX UserID ON Presence("UserID");
21
22COMMIT;
23
24:VERSION 2
25
26BEGIN TRANSACTION;
27
28ALTER TABLE Presence ADD "LastSeen" Timestamp;
29
30COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/RegionStore.migrations b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations
new file mode 100644
index 0000000..1e33027
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations
@@ -0,0 +1,1154 @@
1begin transaction ;
2:VERSION 1
3
4CREATE TABLE prims(
5 "UUID" varchar(255) NOT NULL Primary key,
6 "RegionUUID" varchar(255) NULL,
7 "ParentID" int NULL,
8 "CreationDate" int NULL,
9 "Name" varchar(255) NULL,
10 "SceneGroupID" varchar(255) NULL,
11 "Text" varchar(255) NULL,
12 "Description" varchar(255) NULL,
13 "SitName" varchar(255) NULL,
14 "TouchName" varchar(255) NULL,
15 "ObjectFlags" int NULL,
16 "CreatorID" varchar(255) NULL,
17 "OwnerID" varchar(255) NULL,
18 "GroupID" varchar(255) NULL,
19 "LastOwnerID" varchar(255) NULL,
20 "OwnerMask" int NULL,
21 "NextOwnerMask" int NULL,
22 "GroupMask" int NULL,
23 "EveryoneMask" int NULL,
24 "BaseMask" int NULL,
25 "PositionX" double precision NULL,
26 "PositionY" double precision NULL,
27 "PositionZ" double precision NULL,
28 "GroupPositionX" double precision NULL,
29 "GroupPositionY" double precision NULL,
30 "GroupPositionZ" double precision NULL,
31 "VelocityX" double precision NULL,
32 "VelocityY" double precision NULL,
33 "VelocityZ" double precision NULL,
34 "AngularVelocityX" double precision NULL,
35 "AngularVelocityY" double precision NULL,
36 "AngularVelocityZ" double precision NULL,
37 "AccelerationX" double precision NULL,
38 "AccelerationY" double precision NULL,
39 "AccelerationZ" double precision NULL,
40 "RotationX" double precision NULL,
41 "RotationY" double precision NULL,
42 "RotationZ" double precision NULL,
43 "RotationW" double precision NULL,
44 "SitTargetOffsetX" double precision NULL,
45 "SitTargetOffsetY" double precision NULL,
46 "SitTargetOffsetZ" double precision NULL,
47 "SitTargetOrientW" double precision NULL,
48 "SitTargetOrientX" double precision NULL,
49 "SitTargetOrientY" double precision NULL,
50 "SitTargetOrientZ" double precision NULL
51 );
52
53CREATE TABLE primshapes(
54 "UUID" varchar(255) NOT NULL primary key,
55 "Shape" int NULL,
56 "ScaleX" double precision NULL,
57 "ScaleY" double precision NULL,
58 "ScaleZ" double precision NULL,
59 "PCode" int NULL,
60 "PathBegin" int NULL,
61 "PathEnd" int NULL,
62 "PathScaleX" int NULL,
63 "PathScaleY" int NULL,
64 "PathShearX" int NULL,
65 "PathShearY" int NULL,
66 "PathSkew" int NULL,
67 "PathCurve" int NULL,
68 "PathRadiusOffset" int NULL,
69 "PathRevolutions" int NULL,
70 "PathTaperX" int NULL,
71 "PathTaperY" int NULL,
72 "PathTwist" int NULL,
73 "PathTwistBegin" int NULL,
74 "ProfileBegin" int NULL,
75 "ProfileEnd" int NULL,
76 "ProfileCurve" int NULL,
77 "ProfileHollow" int NULL,
78 "State" int NULL,
79 "Texture" bytea NULL,
80 "ExtraParams" bytea NULL
81 );
82
83CREATE TABLE primitems(
84 "itemID" varchar(255) NOT NULL primary key,
85 "primID" varchar(255) NULL,
86 "assetID" varchar(255) NULL,
87 "parentFolderID" varchar(255) NULL,
88 "invType" int NULL,
89 "assetType" int NULL,
90 "name" varchar(255) NULL,
91 "description" varchar(255) NULL,
92 "creationDate" varchar(255) NULL,
93 "creatorID" varchar(255) NULL,
94 "ownerID" varchar(255) NULL,
95 "lastOwnerID" varchar(255) NULL,
96 "groupID" varchar(255) NULL,
97 "nextPermissions" int NULL,
98 "currentPermissions" int NULL,
99 "basePermissions" int NULL,
100 "everyonePermissions" int NULL,
101 "groupPermissions" int NULL
102 );
103
104CREATE TABLE terrain(
105 "RegionUUID" varchar(255) NULL,
106 "Revision" int NULL,
107 "Heightfield" bytea NULL
108);
109
110
111CREATE TABLE land(
112 "UUID" varchar(255) NOT NULL primary key,
113 "RegionUUID" varchar(255) NULL,
114 "LocalLandID" int NULL,
115 "Bitmap" bytea NULL,
116 "Name" varchar(255) NULL,
117 "Description" varchar(255) NULL,
118 "OwnerUUID" varchar(255) NULL,
119 "IsGroupOwned" boolean NULL,
120 "Area" int NULL,
121 "AuctionID" int NULL,
122 "Category" int NULL,
123 "ClaimDate" int NULL,
124 "ClaimPrice" int NULL,
125 "GroupUUID" varchar(255) NULL,
126 "SalePrice" int NULL,
127 "LandStatus" int NULL,
128 "LandFlags" int NULL,
129 "LandingType" int NULL,
130 "MediaAutoScale" int NULL,
131 "MediaTextureUUID" varchar(255) NULL,
132 "MediaURL" varchar(255) NULL,
133 "MusicURL" varchar(255) NULL,
134 "PassHours" double precision NULL,
135 "PassPrice" int NULL,
136 "SnapshotUUID" varchar(255) NULL,
137 "UserLocationX" double precision NULL,
138 "UserLocationY" double precision NULL,
139 "UserLocationZ" double precision NULL,
140 "UserLookAtX" double precision NULL,
141 "UserLookAtY" double precision NULL,
142 "UserLookAtZ" double precision NULL
143);
144
145Create index on land (lower("Name"));
146
147CREATE TABLE landaccesslist(
148 "LandUUID" varchar(255) NULL,
149 "AccessUUID" varchar(255) NULL,
150 "Flags" int NULL
151);
152
153COMMIT;
154
155:VERSION 2
156
157BEGIN TRANSACTION;
158
159CREATE TABLE regionban (
160 "regionUUID" VARCHAR(36) NOT NULL,
161 "bannedUUID" VARCHAR(36) NOT NULL,
162 "bannedIp" VARCHAR(16) NOT NULL,
163 "bannedIpHostMask" VARCHAR(16) NOT NULL
164 );
165
166create table regionsettings (
167 "regionUUID" varchar(36) not null primary key,
168 "block_terraform" boolean not null,
169 "block_fly" boolean not null,
170 "allow_damage" boolean not null,
171 "restrict_pushing" boolean not null,
172 "allow_land_resell" boolean not null,
173 "allow_land_join_divide" boolean not null,
174 "block_show_in_search" boolean not null,
175 "agent_limit" int not null,
176 "object_bonus" double precision not null,
177 "maturity" int not null,
178 "disable_scripts" boolean not null,
179 "disable_collisions" boolean not null,
180 "disable_physics" boolean not null,
181 "terrain_texture_1" varchar(36) not null,
182 "terrain_texture_2" varchar(36) not null,
183 "terrain_texture_3" varchar(36) not null,
184 "terrain_texture_4" varchar(36) not null,
185 "elevation_1_nw" double precision not null,
186 "elevation_2_nw" double precision not null,
187 "elevation_1_ne" double precision not null,
188 "elevation_2_ne" double precision not null,
189 "elevation_1_se" double precision not null,
190 "elevation_2_se" double precision not null,
191 "elevation_1_sw" double precision not null,
192 "elevation_2_sw" double precision not null,
193 "water_height" double precision not null,
194 "terrain_raise_limit" double precision not null,
195 "terrain_lower_limit" double precision not null,
196 "use_estate_sun" boolean not null,
197 "fixed_sun" boolean not null,
198 "sun_position" double precision not null,
199 "covenant" varchar(36) default NULL,
200 "Sandbox" boolean NOT NULL
201 );
202
203COMMIT;
204
205:VERSION 3
206
207BEGIN TRANSACTION;
208
209CREATE TABLE Tmp_prims
210 (
211 "UUID" varchar(36) NOT NULL ,
212 "RegionUUID" varchar(36) NULL,
213 "ParentID" int NULL,
214 "CreationDate" int NULL,
215 "Name" varchar(255) NULL,
216 "SceneGroupID" varchar(36) NULL,
217 "Text" varchar(255) NULL,
218 "Description" varchar(255) NULL,
219 "SitName" varchar(255) NULL,
220 "TouchName" varchar(255) NULL,
221 "ObjectFlags" int NULL,
222 "CreatorID" varchar(36) NULL,
223 "OwnerID" varchar(36) NULL,
224 "GroupID" varchar(36) NULL,
225 "LastOwnerID" varchar(36) NULL,
226 "OwnerMask" int NULL,
227 "NextOwnerMask" int NULL,
228 "GroupMask" int NULL,
229 "EveryoneMask" int NULL,
230 "BaseMask" int NULL,
231 "PositionX" double precision NULL,
232 "PositionY" double precision NULL,
233 "PositionZ" double precision NULL,
234 "GroupPositionX" double precision NULL,
235 "GroupPositionY" double precision NULL,
236 "GroupPositionZ" double precision NULL,
237 "VelocityX" double precision NULL,
238 "VelocityY" double precision NULL,
239 "VelocityZ" double precision NULL,
240 "AngularVelocityX" double precision NULL,
241 "AngularVelocityY" double precision NULL,
242 "AngularVelocityZ" double precision NULL,
243 "AccelerationX" double precision NULL,
244 "AccelerationY" double precision NULL,
245 "AccelerationZ" double precision NULL,
246 "RotationX" double precision NULL,
247 "RotationY" double precision NULL,
248 "RotationZ" double precision NULL,
249 "RotationW" double precision NULL,
250 "SitTargetOffsetX" double precision NULL,
251 "SitTargetOffsetY" double precision NULL,
252 "SitTargetOffsetZ" double precision NULL,
253 "SitTargetOrientW" double precision NULL,
254 "SitTargetOrientX" double precision NULL,
255 "SitTargetOrientY" double precision NULL,
256 "SitTargetOrientZ" double precision NULL
257 );
258
259INSERT INTO Tmp_prims ("UUID", "RegionUUID", "ParentID", "CreationDate", "Name", "SceneGroupID", "Text", "Description", "SitName", "TouchName", "ObjectFlags", "CreatorID", "OwnerID", "GroupID", "LastOwnerID", "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ")
260 SELECT cast("UUID" as varchar(36)), cast("RegionUUID" as varchar(36)), "ParentID", "CreationDate", "Name", cast("SceneGroupID" as varchar(36)), "Text", "Description", "SitName", "TouchName", "ObjectFlags", cast("CreatorID" as varchar(36)), cast("OwnerID" as varchar(36)), cast( "GroupID" as varchar(36)), cast("LastOwnerID" as varchar(36)), "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ"
261 FROM prims ;
262
263DROP TABLE prims;
264
265alter table Tmp_prims rename to prims;
266
267
268ALTER TABLE prims ADD CONSTRAINT
269 PK__prims__10566F31 PRIMARY KEY
270 (
271 "UUID"
272 );
273
274COMMIT;
275
276:VERSION 4
277
278BEGIN TRANSACTION;
279
280CREATE TABLE Tmp_primitems
281 (
282 "itemID" varchar(36) NOT NULL,
283 "primID" varchar(36) NULL,
284 "assetID" varchar(36) NULL,
285 "parentFolderID" varchar(36) NULL,
286 "invType" int NULL,
287 "assetType" int NULL,
288 "name" varchar(255) NULL,
289 "description" varchar(255) NULL,
290 "creationDate" varchar(255) NULL,
291 "creatorID" varchar(36) NULL,
292 "ownerID" varchar(36) NULL,
293 "lastOwnerID" varchar(36) NULL,
294 "groupID" varchar(36) NULL,
295 "nextPermissions" int NULL,
296 "currentPermissions" int NULL,
297 "basePermissions" int NULL,
298 "everyonePermissions" int NULL,
299 "groupPermissions" int NULL
300 );
301
302INSERT INTO Tmp_primitems ("itemID", "primID", "assetID", "parentFolderID", "invType", "assetType", "name", "description", "creationDate", "creatorID", "ownerID", "lastOwnerID", "groupID", "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions")
303 SELECT cast("itemID" as varchar(36)), cast("primID" as varchar(36)), cast("assetID" as varchar(36)), cast( "parentFolderID" as varchar(36)), "invType", "assetType", "name", "description", "creationDate", cast( "creatorID" as varchar(36)), cast("ownerID" as varchar(36)), cast("lastOwnerID" as varchar(36)), cast("groupID" as varchar(36)), "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions"
304 from primitems;
305
306DROP TABLE primitems;
307
308alter table Tmp_primitems rename to primitems;
309
310ALTER TABLE primitems ADD CONSTRAINT
311 PK__primitems__0A688BB1 PRIMARY KEY
312 (
313 "itemID"
314 );
315
316
317COMMIT;
318
319
320:VERSION 5
321
322BEGIN TRANSACTION;
323
324CREATE TABLE Tmp_primshapes
325 (
326 "UUID" varchar(36) NOT NULL,
327 "Shape" int NULL,
328 "ScaleX" double precision NULL,
329 "ScaleY" double precision NULL,
330 "ScaleZ" double precision NULL,
331 "PCode" int NULL,
332 "PathBegin" int NULL,
333 "PathEnd" int NULL,
334 "PathScaleX" int NULL,
335 "PathScaleY" int NULL,
336 "PathShearX" int NULL,
337 "PathShearY" int NULL,
338 "PathSkew" int NULL,
339 "PathCurve" int NULL,
340 "PathRadiusOffset" int NULL,
341 "PathRevolutions" int NULL,
342 "PathTaperX" int NULL,
343 "PathTaperY" int NULL,
344 "PathTwist" int NULL,
345 "PathTwistBegin" int NULL,
346 "ProfileBegin" int NULL,
347 "ProfileEnd" int NULL,
348 "ProfileCurve" int NULL,
349 "ProfileHollow" int NULL,
350 "State" int NULL,
351 "Texture" bytea NULL,
352 "ExtraParams" bytea NULL
353 ) ;
354
355INSERT INTO Tmp_primshapes ("UUID", "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams")
356 SELECT cast("UUID" as varchar(36)), "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams"
357 FROM primshapes;
358
359DROP TABLE primshapes;
360
361alter table Tmp_primshapes rename to primshapes;
362
363ALTER TABLE primshapes ADD CONSTRAINT
364 PK__primshapes__0880433F PRIMARY KEY
365 (
366 "UUID"
367 ) ;
368
369COMMIT;
370
371
372:VERSION 6
373
374BEGIN TRANSACTION;
375
376ALTER TABLE prims ADD "PayPrice" int not null default 0;
377ALTER TABLE prims ADD "PayButton1" int not null default 0;
378ALTER TABLE prims ADD "PayButton2" int not null default 0;
379ALTER TABLE prims ADD "PayButton3" int not null default 0;
380ALTER TABLE prims ADD "PayButton4" int not null default 0;
381ALTER TABLE prims ADD "LoopedSound" varchar(36) not null default '00000000-0000-0000-0000-000000000000';
382ALTER TABLE prims ADD "LoopedSoundGain" double precision not null default 0.0;
383ALTER TABLE prims ADD "TextureAnimation" bytea;
384ALTER TABLE prims ADD "OmegaX" double precision not null default 0.0;
385ALTER TABLE prims ADD "OmegaY" double precision not null default 0.0;
386ALTER TABLE prims ADD "OmegaZ" double precision not null default 0.0;
387ALTER TABLE prims ADD "CameraEyeOffsetX" double precision not null default 0.0;
388ALTER TABLE prims ADD "CameraEyeOffsetY" double precision not null default 0.0;
389ALTER TABLE prims ADD "CameraEyeOffsetZ" double precision not null default 0.0;
390ALTER TABLE prims ADD "CameraAtOffsetX" double precision not null default 0.0;
391ALTER TABLE prims ADD "CameraAtOffsetY" double precision not null default 0.0;
392ALTER TABLE prims ADD "CameraAtOffsetZ" double precision not null default 0.0;
393ALTER TABLE prims ADD "ForceMouselook" smallint not null default 0;
394ALTER TABLE prims ADD "ScriptAccessPin" int not null default 0;
395ALTER TABLE prims ADD "AllowedDrop" smallint not null default 0;
396ALTER TABLE prims ADD "DieAtEdge" smallint not null default 0;
397ALTER TABLE prims ADD "SalePrice" int not null default 10;
398ALTER TABLE prims ADD "SaleType" smallint not null default 0;
399
400ALTER TABLE primitems add "flags" integer not null default 0;
401
402ALTER TABLE land ADD "AuthbuyerID" varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000';
403
404CREATE index prims_regionuuid on prims("RegionUUID");
405CREATE index prims_parentid on prims("ParentID");
406
407CREATE index primitems_primid on primitems("primID");
408
409COMMIT;
410
411
412:VERSION 7
413
414BEGIN TRANSACTION;
415
416ALTER TABLE prims ADD "ColorR" int not null default 0;
417ALTER TABLE prims ADD "ColorG" int not null default 0;
418ALTER TABLE prims ADD "ColorB" int not null default 0;
419ALTER TABLE prims ADD "ColorA" int not null default 0;
420ALTER TABLE prims ADD "ParticleSystem" bytea;
421ALTER TABLE prims ADD "ClickAction" smallint NOT NULL default 0;
422
423COMMIT;
424
425
426:VERSION 8
427
428BEGIN TRANSACTION;
429
430ALTER TABLE land ADD "OtherCleanTime" integer NOT NULL default 0;
431ALTER TABLE land ADD "Dwell" integer NOT NULL default 0;
432
433COMMIT;
434
435:VERSION 9
436
437BEGIN TRANSACTION;
438
439ALTER TABLE prims ADD "Material" smallint NOT NULL default 3;
440
441COMMIT;
442
443
444:VERSION 10
445
446BEGIN TRANSACTION;
447
448ALTER TABLE regionsettings ADD "sunvectorx" double precision NOT NULL default 0;
449ALTER TABLE regionsettings ADD "sunvectory" double precision NOT NULL default 0;
450ALTER TABLE regionsettings ADD "sunvectorz" double precision NOT NULL default 0;
451
452COMMIT;
453
454
455:VERSION 11
456
457BEGIN TRANSACTION;
458
459ALTER TABLE prims ADD "CollisionSound" char(36) not null default '00000000-0000-0000-0000-000000000000';
460ALTER TABLE prims ADD "CollisionSoundVolume" double precision not null default 0.0;
461
462COMMIT;
463
464
465:VERSION 12
466
467BEGIN TRANSACTION;
468
469ALTER TABLE prims ADD "LinkNumber" integer not null default 0;
470
471COMMIT;
472
473
474:VERSION 13
475
476BEGIN TRANSACTION;
477
478CREATE TABLE Tmp_prims
479 (
480 "UUID" uuid NOT NULL,
481 "RegionUUID" uuid NULL,
482 "ParentID" int NULL,
483 "CreationDate" int NULL,
484 "Name" varchar(255) NULL,
485 "SceneGroupID" uuid NULL,
486 "Text" varchar(255) NULL,
487 "Description" varchar(255) NULL,
488 "SitName" varchar(255) NULL,
489 "TouchName" varchar(255) NULL,
490 "ObjectFlags" int NULL,
491 "CreatorID" uuid NULL,
492 "OwnerID" uuid NULL,
493 "GroupID" uuid NULL,
494 "LastOwnerID" uuid NULL,
495 "OwnerMask" int NULL,
496 "NextOwnerMask" int NULL,
497 "GroupMask" int NULL,
498 "EveryoneMask" int NULL,
499 "BaseMask" int NULL,
500 "PositionX" double precision NULL,
501 "PositionY" double precision NULL,
502 "PositionZ" double precision NULL,
503 "GroupPositionX" double precision NULL,
504 "GroupPositionY" double precision NULL,
505 "GroupPositionZ" double precision NULL,
506 "VelocityX" double precision NULL,
507 "VelocityY" double precision NULL,
508 "VelocityZ" double precision NULL,
509 "AngularVelocityX" double precision NULL,
510 "AngularVelocityY" double precision NULL,
511 "AngularVelocityZ" double precision NULL,
512 "AccelerationX" double precision NULL,
513 "AccelerationY" double precision NULL,
514 "AccelerationZ" double precision NULL,
515 "RotationX" double precision NULL,
516 "RotationY" double precision NULL,
517 "RotationZ" double precision NULL,
518 "RotationW" double precision NULL,
519 "SitTargetOffsetX" double precision NULL,
520 "SitTargetOffsetY" double precision NULL,
521 "SitTargetOffsetZ" double precision NULL,
522 "SitTargetOrientW" double precision NULL,
523 "SitTargetOrientX" double precision NULL,
524 "SitTargetOrientY" double precision NULL,
525 "SitTargetOrientZ" double precision NULL,
526 "PayPrice" int NOT NULL DEFAULT ((0)),
527 "PayButton1" int NOT NULL DEFAULT ((0)),
528 "PayButton2" int NOT NULL DEFAULT ((0)),
529 "PayButton3" int NOT NULL DEFAULT ((0)),
530 "PayButton4" int NOT NULL DEFAULT ((0)),
531 "LoopedSound" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
532 "LoopedSoundGain" double precision NOT NULL DEFAULT ((0.0)),
533 "TextureAnimation" bytea NULL,
534 "OmegaX" double precision NOT NULL DEFAULT ((0.0)),
535 "OmegaY" double precision NOT NULL DEFAULT ((0.0)),
536 "OmegaZ" double precision NOT NULL DEFAULT ((0.0)),
537 "CameraEyeOffsetX" double precision NOT NULL DEFAULT ((0.0)),
538 "CameraEyeOffsetY" double precision NOT NULL DEFAULT ((0.0)),
539 "CameraEyeOffsetZ" double precision NOT NULL DEFAULT ((0.0)),
540 "CameraAtOffsetX" double precision NOT NULL DEFAULT ((0.0)),
541 "CameraAtOffsetY" double precision NOT NULL DEFAULT ((0.0)),
542 "CameraAtOffsetZ" double precision NOT NULL DEFAULT ((0.0)),
543 "ForceMouselook" smallint NOT NULL DEFAULT ((0)),
544 "ScriptAccessPin" int NOT NULL DEFAULT ((0)),
545 "AllowedDrop" smallint NOT NULL DEFAULT ((0)),
546 "DieAtEdge" smallint NOT NULL DEFAULT ((0)),
547 "SalePrice" int NOT NULL DEFAULT ((10)),
548 "SaleType" smallint NOT NULL DEFAULT ((0)),
549 "ColorR" int NOT NULL DEFAULT ((0)),
550 "ColorG" int NOT NULL DEFAULT ((0)),
551 "ColorB" int NOT NULL DEFAULT ((0)),
552 "ColorA" int NOT NULL DEFAULT ((0)),
553 "ParticleSystem" bytea NULL,
554 "ClickAction" smallint NOT NULL DEFAULT ((0)),
555 "Material" smallint NOT NULL DEFAULT ((3)),
556 "CollisionSound" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
557 "CollisionSoundVolume" double precision NOT NULL DEFAULT ((0.0)),
558 "LinkNumber" int NOT NULL DEFAULT ((0))
559 );
560
561INSERT INTO Tmp_prims ("UUID", "RegionUUID", "ParentID", "CreationDate", "Name", "SceneGroupID", "Text", "Description", "SitName", "TouchName", "ObjectFlags", "CreatorID", "OwnerID", "GroupID", "LastOwnerID", "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ", "PayPrice", "PayButton1", "PayButton2", "PayButton3", "PayButton4", "LoopedSound", "LoopedSoundGain", "TextureAnimation", "OmegaX", "OmegaY", "OmegaZ", "CameraEyeOffsetX", "CameraEyeOffsetY", "CameraEyeOffsetZ", "CameraAtOffsetX", "CameraAtOffsetY", "CameraAtOffsetZ", "ForceMouselook", "ScriptAccessPin", "AllowedDrop", "DieAtEdge", "SalePrice", "SaleType", "ColorR", "ColorG", "ColorB", "ColorA", "ParticleSystem", "ClickAction", "Material", "CollisionSound", "CollisionSoundVolume", "LinkNumber")
562 SELECT cast("UUID" as uuid), cast("RegionUUID" as uuid), "ParentID", "CreationDate", "Name", cast("SceneGroupID" as uuid), "Text", "Description", "SitName", "TouchName", "ObjectFlags", cast("CreatorID" as uuid), cast("OwnerID" as uuid), cast("GroupID" as uuid), cast("LastOwnerID" as uuid), "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ", "PayPrice", "PayButton1", "PayButton2", "PayButton3", "PayButton4", cast("LoopedSound" as uuid), "LoopedSoundGain", "TextureAnimation", "OmegaX", "OmegaY", "OmegaZ", "CameraEyeOffsetX", "CameraEyeOffsetY", "CameraEyeOffsetZ", "CameraAtOffsetX", "CameraAtOffsetY", "CameraAtOffsetZ", "ForceMouselook", "ScriptAccessPin", "AllowedDrop", "DieAtEdge", "SalePrice", "SaleType", "ColorR", "ColorG", "ColorB", "ColorA", "ParticleSystem", "ClickAction", "Material", cast("CollisionSound" as uuid), "CollisionSoundVolume", "LinkNumber"
563 FROM prims ;
564
565DROP TABLE prims;
566
567alter table Tmp_prims rename to prims;
568
569ALTER TABLE prims ADD CONSTRAINT
570 PK__prims__10566F31 PRIMARY KEY
571 (
572 "UUID"
573 );
574
575
576CREATE INDEX prims_regionuuid ON prims
577 (
578 "RegionUUID"
579 );
580
581CREATE INDEX prims_parentid ON prims
582 (
583 "ParentID"
584 );
585
586COMMIT;
587
588
589:VERSION 14
590
591BEGIN TRANSACTION;
592
593CREATE TABLE Tmp_primshapes
594 (
595 "UUID" uuid NOT NULL,
596 "Shape" int NULL,
597 "ScaleX" double precision NULL,
598 "ScaleY" double precision NULL,
599 "ScaleZ" double precision NULL,
600 "PCode" int NULL,
601 "PathBegin" int NULL,
602 "PathEnd" int NULL,
603 "PathScaleX" int NULL,
604 "PathScaleY" int NULL,
605 "PathShearX" int NULL,
606 "PathShearY" int NULL,
607 "PathSkew" int NULL,
608 "PathCurve" int NULL,
609 "PathRadiusOffset" int NULL,
610 "PathRevolutions" int NULL,
611 "PathTaperX" int NULL,
612 "PathTaperY" int NULL,
613 "PathTwist" int NULL,
614 "PathTwistBegin" int NULL,
615 "ProfileBegin" int NULL,
616 "ProfileEnd" int NULL,
617 "ProfileCurve" int NULL,
618 "ProfileHollow" int NULL,
619 "State" int NULL,
620 "Texture" bytea NULL,
621 "ExtraParams" bytea NULL
622 );
623
624INSERT INTO Tmp_primshapes ("UUID", "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams")
625 SELECT cast("UUID" as uuid), "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams"
626 FROM primshapes;
627
628DROP TABLE primshapes;
629
630alter table Tmp_primshapes rename to primshapes;
631
632ALTER TABLE primshapes ADD CONSTRAINT
633 PK__primshapes__0880433F PRIMARY KEY
634 (
635 "UUID"
636 );
637
638COMMIT;
639
640
641:VERSION 15
642
643BEGIN TRANSACTION;
644
645CREATE TABLE Tmp_primitems
646 (
647 "itemID" uuid NOT NULL,
648 "primID" uuid NULL,
649 "assetID" uuid NULL,
650 "parentFolderID" uuid NULL,
651 "invType" int NULL,
652 "assetType" int NULL,
653 "name" varchar(255) NULL,
654 "description" varchar(255) NULL,
655 "creationDate" varchar(255) NULL,
656 "creatorID" uuid NULL,
657 "ownerID" uuid NULL,
658 "lastOwnerID" uuid NULL,
659 "groupID" uuid NULL,
660 "nextPermissions" int NULL,
661 "currentPermissions" int NULL,
662 "basePermissions" int NULL,
663 "everyonePermissions" int NULL,
664 "groupPermissions" int NULL,
665 flags int NOT NULL DEFAULT ((0))
666 );
667
668INSERT INTO Tmp_primitems ("itemID", "primID", "assetID", "parentFolderID", "invType", "assetType", "name", "description", "creationDate", "creatorID", "ownerID", "lastOwnerID", "groupID", "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions", flags)
669 SELECT cast("itemID" as uuid), cast("primID" as uuid), cast("assetID" as uuid), cast("parentFolderID" as uuid), "invType", "assetType", "name", "description", "creationDate", cast("creatorID" as uuid), cast("ownerID" as uuid), cast("lastOwnerID" as uuid), cast("groupID" as uuid), "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions", flags
670 FROM primitems ;
671
672DROP TABLE primitems;
673
674alter table Tmp_primitems rename to primitems;
675
676ALTER TABLE primitems ADD CONSTRAINT
677 PK__primitems__0A688BB1 PRIMARY KEY
678 (
679 "itemID"
680 );
681
682CREATE INDEX primitems_primid ON primitems
683 (
684 "primID"
685 ) ;
686
687COMMIT;
688
689
690:VERSION 16
691
692
693BEGIN TRANSACTION;
694
695CREATE TABLE Tmp_terrain
696 (
697 "RegionUUID" uuid NULL,
698 "Revision" int NULL,
699 "Heightfield" bytea NULL
700 );
701
702INSERT INTO Tmp_terrain ("RegionUUID", "Revision", "Heightfield")
703 SELECT cast("RegionUUID" as uuid), "Revision", "Heightfield"
704 FROM terrain ;
705
706DROP TABLE terrain;
707
708alter table Tmp_terrain rename to terrain;
709
710COMMIT;
711
712
713:VERSION 17
714
715BEGIN TRANSACTION;
716
717CREATE TABLE Tmp_land
718 (
719 "UUID" uuid NOT NULL,
720 "RegionUUID" uuid NULL,
721 "LocalLandID" int NULL,
722 "Bitmap" bytea NULL,
723 "Name" varchar(255) NULL,
724 "Description" varchar(255) NULL,
725 "OwnerUUID" uuid NULL,
726 "IsGroupOwned" boolean NULL,
727 "Area" int NULL,
728 "AuctionID" int NULL,
729 "Category" int NULL,
730 "ClaimDate" int NULL,
731 "ClaimPrice" int NULL,
732 "GroupUUID" uuid NULL,
733 "SalePrice" int NULL,
734 "LandStatus" int NULL,
735 "LandFlags" int NULL,
736 "LandingType" int NULL,
737 "MediaAutoScale" int NULL,
738 "MediaTextureUUID" uuid NULL,
739 "MediaURL" varchar(255) NULL,
740 "MusicURL" varchar(255) NULL,
741 "PassHours" double precision NULL,
742 "PassPrice" int NULL,
743 "SnapshotUUID" uuid NULL,
744 "UserLocationX" double precision NULL,
745 "UserLocationY" double precision NULL,
746 "UserLocationZ" double precision NULL,
747 "UserLookAtX" double precision NULL,
748 "UserLookAtY" double precision NULL,
749 "UserLookAtZ" double precision NULL,
750 "AuthbuyerID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
751 "OtherCleanTime" int NOT NULL DEFAULT ((0)),
752 "Dwell" int NOT NULL DEFAULT ((0))
753 );
754
755INSERT INTO Tmp_land ("UUID", "RegionUUID", "LocalLandID", "Bitmap", "Name", "Description", "OwnerUUID", "IsGroupOwned", "Area", "AuctionID", "Category", "ClaimDate", "ClaimPrice", "GroupUUID", "SalePrice", "LandStatus", "LandFlags", "LandingType", "MediaAutoScale", "MediaTextureUUID", "MediaURL", "MusicURL", "PassHours", "PassPrice", "SnapshotUUID", "UserLocationX", "UserLocationY", "UserLocationZ", "UserLookAtX", "UserLookAtY", "UserLookAtZ", "AuthbuyerID", "OtherCleanTime", "Dwell")
756 SELECT cast("UUID" as uuid), cast("RegionUUID" as uuid), "LocalLandID", "Bitmap", "Name", "Description", cast("OwnerUUID" as uuid), "IsGroupOwned", "Area", "AuctionID", "Category", "ClaimDate", "ClaimPrice", cast("GroupUUID" as uuid), "SalePrice", "LandStatus", "LandFlags", "LandingType", "MediaAutoScale", cast("MediaTextureUUID" as uuid), "MediaURL", "MusicURL", "PassHours", "PassPrice", cast("SnapshotUUID" as uuid), "UserLocationX", "UserLocationY", "UserLocationZ", "UserLookAtX", "UserLookAtY", "UserLookAtZ", cast("AuthbuyerID" as uuid), "OtherCleanTime", "Dwell"
757 FROM land ;
758
759DROP TABLE land;
760
761alter table Tmp_land rename to land;
762
763ALTER TABLE land ADD CONSTRAINT
764 PK__land__65A475E71BFD2C07 PRIMARY KEY
765 (
766 "UUID"
767 );
768
769Create index on land (lower("Name"));
770
771COMMIT;
772
773
774
775:VERSION 18
776
777BEGIN TRANSACTION;
778
779CREATE TABLE Tmp_landaccesslist
780 (
781 "LandUUID" uuid NULL,
782 "AccessUUID" uuid NULL,
783 "Flags" int NULL
784 );
785
786INSERT INTO Tmp_landaccesslist ("LandUUID", "AccessUUID", "Flags")
787 SELECT cast("LandUUID" as uuid), cast("AccessUUID" as uuid), "Flags"
788 FROM landaccesslist ;
789
790DROP TABLE landaccesslist;
791
792alter table Tmp_landaccesslist rename to landaccesslist;
793
794COMMIT;
795
796
797
798:VERSION 19
799
800BEGIN TRANSACTION;
801
802CREATE TABLE Tmp_regionban
803 (
804 "regionUUID" uuid NOT NULL,
805 "bannedUUID" uuid NOT NULL,
806 "bannedIp" varchar(16) NOT NULL,
807 "bannedIpHostMask" varchar(16) NOT NULL
808 );
809
810INSERT INTO Tmp_regionban ("regionUUID", "bannedUUID", "bannedIp", "bannedIpHostMask")
811 SELECT cast("regionUUID" as uuid), cast("bannedUUID" as uuid), "bannedIp", "bannedIpHostMask"
812 FROM regionban ;
813
814DROP TABLE regionban;
815
816alter table Tmp_regionban rename to regionban;
817
818COMMIT;
819
820
821:VERSION 20
822
823BEGIN TRANSACTION;
824
825CREATE TABLE Tmp_regionsettings
826 (
827 "regionUUID" uuid NOT NULL,
828 "block_terraform" boolean NOT NULL,
829 "block_fly" boolean NOT NULL,
830 "allow_damage" boolean NOT NULL,
831 "restrict_pushing" boolean NOT NULL,
832 "allow_land_resell" boolean NOT NULL,
833 "allow_land_join_divide" boolean NOT NULL,
834 "block_show_in_search" boolean NOT NULL,
835 "agent_limit" int NOT NULL,
836 "object_bonus" double precision NOT NULL,
837 "maturity" int NOT NULL,
838 "disable_scripts" boolean NOT NULL,
839 "disable_collisions" boolean NOT NULL,
840 "disable_physics" boolean NOT NULL,
841 "terrain_texture_1" uuid NOT NULL,
842 "terrain_texture_2" uuid NOT NULL,
843 "terrain_texture_3" uuid NOT NULL,
844 "terrain_texture_4" uuid NOT NULL,
845 "elevation_1_nw" double precision NOT NULL,
846 "elevation_2_nw" double precision NOT NULL,
847 "elevation_1_ne" double precision NOT NULL,
848 "elevation_2_ne" double precision NOT NULL,
849 "elevation_1_se" double precision NOT NULL,
850 "elevation_2_se" double precision NOT NULL,
851 "elevation_1_sw" double precision NOT NULL,
852 "elevation_2_sw" double precision NOT NULL,
853 "water_height" double precision NOT NULL,
854 "terrain_raise_limit" double precision NOT NULL,
855 "terrain_lower_limit" double precision NOT NULL,
856 "use_estate_sun" boolean NOT NULL,
857 "fixed_sun" boolean NOT NULL,
858 "sun_position" double precision NOT NULL,
859 "covenant" uuid NULL DEFAULT (NULL),
860 "Sandbox" boolean NOT NULL,
861 "sunvectorx" double precision NOT NULL DEFAULT ((0)),
862 "sunvectory" double precision NOT NULL DEFAULT ((0)),
863 "sunvectorz" double precision NOT NULL DEFAULT ((0))
864 );
865
866INSERT INTO Tmp_regionsettings ("regionUUID", "block_terraform", "block_fly", "allow_damage", "restrict_pushing", "allow_land_resell", "allow_land_join_divide", "block_show_in_search", "agent_limit", "object_bonus", "maturity", "disable_scripts", "disable_collisions", "disable_physics", "terrain_texture_1", "terrain_texture_2", "terrain_texture_3", "terrain_texture_4", "elevation_1_nw", "elevation_2_nw", "elevation_1_ne", "elevation_2_ne", "elevation_1_se", "elevation_2_se", "elevation_1_sw", "elevation_2_sw", "water_height", "terrain_raise_limit", "terrain_lower_limit", "use_estate_sun", "fixed_sun", "sun_position", "covenant", "Sandbox", "sunvectorx", "sunvectory", "sunvectorz")
867 SELECT cast("regionUUID" as uuid), "block_terraform", "block_fly", "allow_damage", "restrict_pushing", "allow_land_resell", "allow_land_join_divide", "block_show_in_search", "agent_limit", "object_bonus", "maturity", "disable_scripts", "disable_collisions", "disable_physics", cast("terrain_texture_1" as uuid), cast("terrain_texture_2" as uuid), cast("terrain_texture_3" as uuid), cast("terrain_texture_4" as uuid), "elevation_1_nw", "elevation_2_nw", "elevation_1_ne", "elevation_2_ne", "elevation_1_se", "elevation_2_se", "elevation_1_sw", "elevation_2_sw", "water_height", "terrain_raise_limit", "terrain_lower_limit", "use_estate_sun", "fixed_sun", "sun_position", cast("covenant" as uuid), "Sandbox", "sunvectorx", "sunvectory", "sunvectorz"
868 FROM regionsettings ;
869
870DROP TABLE regionsettings;
871
872alter table Tmp_regionsettings rename to regionsettings;
873
874ALTER TABLE regionsettings ADD CONSTRAINT
875 PK__regionse__5B35159D21B6055D PRIMARY KEY
876 (
877 "regionUUID"
878 );
879
880COMMIT;
881
882
883:VERSION 21
884
885BEGIN TRANSACTION;
886
887ALTER TABLE prims ADD "PassTouches" boolean not null default false;
888
889COMMIT;
890
891
892:VERSION 22
893
894BEGIN TRANSACTION;
895
896ALTER TABLE regionsettings ADD "loaded_creation_date" varchar(20) ;
897ALTER TABLE regionsettings ADD "loaded_creation_time" varchar(20) ;
898ALTER TABLE regionsettings ADD "loaded_creation_id" varchar(64) ;
899
900COMMIT;
901
902:VERSION 23
903
904BEGIN TRANSACTION;
905
906ALTER TABLE regionsettings DROP COLUMN "loaded_creation_date";
907ALTER TABLE regionsettings DROP COLUMN "loaded_creation_time";
908ALTER TABLE regionsettings ADD "loaded_creation_datetime" int NOT NULL default 0;
909
910COMMIT;
911
912:VERSION 24
913
914BEGIN TRANSACTION;
915
916ALTER TABLE prims ADD "MediaURL" varchar(255);
917ALTER TABLE primshapes ADD "Media" TEXT NULL;
918
919COMMIT;
920
921:VERSION 25
922
923BEGIN TRANSACTION;
924CREATE TABLE regionwindlight (
925 "region_id" varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000' PRIMARY KEY,
926 "water_color_r" double precision NOT NULL DEFAULT '4.000000',
927 water_color_g double precision NOT NULL DEFAULT '38.000000',
928 water_color_b double precision NOT NULL DEFAULT '64.000000',
929 water_fog_density_exponent double precision NOT NULL DEFAULT '4.0',
930 underwater_fog_modifier double precision NOT NULL DEFAULT '0.25',
931 reflection_wavelet_scale_1 double precision NOT NULL DEFAULT '2.0',
932 reflection_wavelet_scale_2 double precision NOT NULL DEFAULT '2.0',
933 reflection_wavelet_scale_3 double precision NOT NULL DEFAULT '2.0',
934 fresnel_scale double precision NOT NULL DEFAULT '0.40',
935 fresnel_offset double precision NOT NULL DEFAULT '0.50',
936 refract_scale_above double precision NOT NULL DEFAULT '0.03',
937 refract_scale_below double precision NOT NULL DEFAULT '0.20',
938 blur_multiplier double precision NOT NULL DEFAULT '0.040',
939 big_wave_direction_x double precision NOT NULL DEFAULT '1.05',
940 big_wave_direction_y double precision NOT NULL DEFAULT '-0.42',
941 little_wave_direction_x double precision NOT NULL DEFAULT '1.11',
942 little_wave_direction_y double precision NOT NULL DEFAULT '-1.16',
943 normal_map_texture varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4',
944 horizon_r double precision NOT NULL DEFAULT '0.25',
945 horizon_g double precision NOT NULL DEFAULT '0.25',
946 horizon_b double precision NOT NULL DEFAULT '0.32',
947 horizon_i double precision NOT NULL DEFAULT '0.32',
948 haze_horizon double precision NOT NULL DEFAULT '0.19',
949 blue_density_r double precision NOT NULL DEFAULT '0.12',
950 blue_density_g double precision NOT NULL DEFAULT '0.22',
951 blue_density_b double precision NOT NULL DEFAULT '0.38',
952 blue_density_i double precision NOT NULL DEFAULT '0.38',
953 haze_density double precision NOT NULL DEFAULT '0.70',
954 density_multiplier double precision NOT NULL DEFAULT '0.18',
955 distance_multiplier double precision NOT NULL DEFAULT '0.8',
956 max_altitude int NOT NULL DEFAULT '1605',
957 sun_moon_color_r double precision NOT NULL DEFAULT '0.24',
958 sun_moon_color_g double precision NOT NULL DEFAULT '0.26',
959 sun_moon_color_b double precision NOT NULL DEFAULT '0.30',
960 sun_moon_color_i double precision NOT NULL DEFAULT '0.30',
961 sun_moon_position double precision NOT NULL DEFAULT '0.317',
962 ambient_r double precision NOT NULL DEFAULT '0.35',
963 ambient_g double precision NOT NULL DEFAULT '0.35',
964 ambient_b double precision NOT NULL DEFAULT '0.35',
965 ambient_i double precision NOT NULL DEFAULT '0.35',
966 east_angle double precision NOT NULL DEFAULT '0.00',
967 sun_glow_focus double precision NOT NULL DEFAULT '0.10',
968 sun_glow_size double precision NOT NULL DEFAULT '1.75',
969 scene_gamma double precision NOT NULL DEFAULT '1.00',
970 star_brightness double precision NOT NULL DEFAULT '0.00',
971 cloud_color_r double precision NOT NULL DEFAULT '0.41',
972 cloud_color_g double precision NOT NULL DEFAULT '0.41',
973 cloud_color_b double precision NOT NULL DEFAULT '0.41',
974 cloud_color_i double precision NOT NULL DEFAULT '0.41',
975 cloud_x double precision NOT NULL DEFAULT '1.00',
976 cloud_y double precision NOT NULL DEFAULT '0.53',
977 cloud_density double precision NOT NULL DEFAULT '1.00',
978 cloud_coverage double precision NOT NULL DEFAULT '0.27',
979 cloud_scale double precision NOT NULL DEFAULT '0.42',
980 cloud_detail_x double precision NOT NULL DEFAULT '1.00',
981 cloud_detail_y double precision NOT NULL DEFAULT '0.53',
982 cloud_detail_density double precision NOT NULL DEFAULT '0.12',
983 cloud_scroll_x double precision NOT NULL DEFAULT '0.20',
984 cloud_scroll_x_lock smallint NOT NULL DEFAULT '0',
985 cloud_scroll_y double precision NOT NULL DEFAULT '0.01',
986 cloud_scroll_y_lock smallint NOT NULL DEFAULT '0',
987 draw_classic_clouds smallint NOT NULL DEFAULT '1'
988);
989
990COMMIT;
991
992:VERSION 26
993
994BEGIN TRANSACTION;
995
996ALTER TABLE regionsettings ADD "map_tile_ID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
997
998COMMIT;
999
1000:VERSION 27 #---------------------
1001
1002BEGIN TRANSACTION;
1003ALTER TABLE land ADD "MediaType" VARCHAR(32) NOT NULL DEFAULT 'none/none' ;
1004ALTER TABLE land ADD "MediaDescription" VARCHAR(255) NOT NULL DEFAULT '';
1005ALTER TABLE land ADD "MediaSize" VARCHAR(16) NOT NULL DEFAULT '0,0';
1006ALTER TABLE land ADD "MediaLoop" boolean NOT NULL DEFAULT false;
1007ALTER TABLE land ADD "ObscureMusic" boolean NOT NULL DEFAULT false;
1008ALTER TABLE land ADD "ObscureMedia" boolean NOT NULL DEFAULT false;
1009COMMIT;
1010
1011:VERSION 28 #---------------------
1012
1013BEGIN TRANSACTION;
1014
1015ALTER TABLE prims
1016alter column "CreatorID" set DEFAULT '00000000-0000-0000-0000-000000000000' ;
1017
1018ALTER TABLE prims ALTER COLUMN "CreatorID" set NOT NULL;
1019
1020ALTER TABLE primitems
1021alter column "creatorID" set DEFAULT '00000000-0000-0000-0000-000000000000' ;
1022
1023ALTER TABLE primitems ALTER COLUMN "creatorID" set NOT NULL;
1024
1025COMMIT;
1026
1027:VERSION 29 #----------------- Region Covenant changed time
1028
1029BEGIN TRANSACTION;
1030
1031ALTER TABLE regionsettings ADD "covenant_datetime" int NOT NULL default 0;
1032
1033COMMIT;
1034
1035:VERSION 30 #------------------Migrate "creatorID" storage to varchars instead of UUIDs for HG support
1036
1037BEGIN TRANSACTION;
1038
1039alter table prims rename column "CreatorID" to "CreatorIDOld";
1040alter table primitems rename column "creatorID" to "creatorIDOld";
1041
1042COMMIT;
1043
1044:VERSION 31 #---------------------
1045
1046BEGIN TRANSACTION;
1047
1048ALTER TABLE prims ADD "CreatorID" varchar(255);
1049ALTER TABLE primitems ADD "creatorID" varchar(255);
1050
1051COMMIT;
1052
1053:VERSION 32 #---------------------
1054
1055BEGIN TRANSACTION;
1056
1057UPDATE prims SET "CreatorID" = cast("CreatorIDOld" as varchar(255));
1058UPDATE primitems SET "creatorID" = cast("creatorIDOld" as varchar(255));
1059
1060COMMIT;
1061
1062:VERSION 33 #---------------------
1063
1064BEGIN TRANSACTION;
1065
1066ALTER TABLE prims alter column "CreatorID" set default '00000000-0000-0000-0000-000000000000' ;
1067
1068ALTER TABLE prims ALTER COLUMN "CreatorID" set NOT NULL;
1069
1070ALTER TABLE primitems alter column "creatorID" set DEFAULT '00000000-0000-0000-0000-000000000000' ;
1071
1072ALTER TABLE primitems ALTER COLUMN "creatorID" set NOT NULL;
1073
1074COMMIT;
1075
1076:VERSION 34 #--------------- Telehub support
1077
1078BEGIN TRANSACTION;
1079
1080CREATE TABLE spawn_points(
1081 "RegionUUID" uuid NOT NULL PRIMARY KEY,
1082 "Yaw" double precision NOT NULL,
1083 "Pitch" double precision NOT NULL,
1084 "Distance" double precision NOT NULL
1085);
1086
1087ALTER TABLE regionsettings ADD "TelehubObject" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
1088
1089COMMIT;
1090
1091:VERSION 35 #---------------- Parcels for sale
1092
1093BEGIN TRANSACTION;
1094
1095ALTER TABLE regionsettings ADD "parcel_tile_ID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
1096
1097COMMIT;
1098
1099:VERSION 36 #---------------- Timed bans/access
1100
1101BEGIN TRANSACTION;
1102
1103ALTER TABLE landaccesslist ADD "Expires" integer NOT NULL DEFAULT 0;
1104
1105COMMIT;
1106
1107:VERSION 37 #---------------- Environment Settings
1108
1109BEGIN TRANSACTION;
1110
1111CREATE TABLE regionenvironment(
1112 "region_id" uuid NOT NULL primary key,
1113 "llsd_settings" varchar NOT NULL
1114);
1115
1116COMMIT;
1117
1118:VERSION 38 #---------------- Dynamic attributes
1119
1120BEGIN TRANSACTION;
1121
1122ALTER TABLE prims ADD "DynAttrs" TEXT;
1123
1124COMMIT;
1125
1126:VERSION 39 #---------------- Extra physics params
1127
1128BEGIN TRANSACTION;
1129
1130ALTER TABLE prims ADD "PhysicsShapeType" smallint NOT NULL default '0';
1131ALTER TABLE prims ADD "Density" double precision NOT NULL default '1000';
1132ALTER TABLE prims ADD "GravityModifier" double precision NOT NULL default '1';
1133ALTER TABLE prims ADD "Friction" double precision NOT NULL default '0.6';
1134ALTER TABLE prims ADD "Restitution" double precision NOT NULL default '0.5';
1135
1136COMMIT;
1137
1138:VERSION 40 #-- regionwindlight changed type from smallint to bool
1139
1140BEGIN TRANSACTION;
1141
1142ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_x_lock DROP DEFAULT;
1143ALTER TABLE regionwindlight ALTER cloud_scroll_x_lock TYPE bool USING CASE WHEN cloud_scroll_x_lock=0 THEN FALSE ELSE TRUE END;
1144ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_x_lock SET DEFAULT FALSE;
1145
1146ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_y_lock DROP DEFAULT;
1147ALTER TABLE regionwindlight ALTER cloud_scroll_y_lock TYPE bool USING CASE WHEN cloud_scroll_y_lock=0 THEN FALSE ELSE TRUE END;
1148ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_y_lock SET DEFAULT FALSE;
1149
1150ALTER TABLE regionwindlight ALTER COLUMN draw_classic_clouds DROP DEFAULT;
1151ALTER TABLE regionwindlight ALTER draw_classic_clouds TYPE bool USING CASE WHEN draw_classic_clouds=0 THEN FALSE ELSE TRUE END;
1152ALTER TABLE regionwindlight ALTER COLUMN draw_classic_clouds SET DEFAULT FALSE;
1153
1154COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/UserAccount.migrations b/OpenSim/Data/PGSQL/Resources/UserAccount.migrations
new file mode 100644
index 0000000..c785463
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/UserAccount.migrations
@@ -0,0 +1,51 @@
1:VERSION 1
2
3CREATE TABLE UserAccounts (
4 "PrincipalID" uuid NOT NULL Primary key,
5 "ScopeID" uuid NOT NULL,
6 "FirstName" varchar(64) NOT NULL,
7 "LastName" varchar(64) NOT NULL,
8 "Email" varchar(64) NULL,
9 "ServiceURLs" text NULL,
10 "Created" int default NULL
11);
12
13
14:VERSION 2
15
16BEGIN TRANSACTION;
17
18INSERT INTO UserAccounts ("PrincipalID", "ScopeID", "FirstName", "LastName", "Email", "ServiceURLs", "Created")
19SELECT UUID AS "PrincipalID", '00000000-0000-0000-0000-000000000000' AS "ScopeID",
20username AS "FirstName",
21lastname AS "LastName",
22email as "Email", (
23'AssetServerURI=' +
24userAssetURI + ' InventoryServerURI=' + userInventoryURI + ' GatewayURI= HomeURI=') AS "ServiceURLs",
25created as "Created" FROM users;
26
27COMMIT;
28
29:VERSION 3
30
31BEGIN TRANSACTION;
32
33CREATE UNIQUE INDEX "PrincipalID" ON UserAccounts("PrincipalID");
34CREATE INDEX "Email" ON UserAccounts("Email");
35CREATE INDEX "FirstName" ON UserAccounts("FirstName");
36CREATE INDEX "LastName" ON UserAccounts("LastName");
37CREATE INDEX Name ON UserAccounts("FirstName","LastName");
38
39COMMIT;
40
41:VERSION 4
42
43BEGIN TRANSACTION;
44
45ALTER TABLE UserAccounts ADD "UserLevel" integer NOT NULL DEFAULT 0;
46ALTER TABLE UserAccounts ADD "UserFlags" integer NOT NULL DEFAULT 0;
47ALTER TABLE UserAccounts ADD "UserTitle" varchar(64) NOT NULL DEFAULT '';
48
49COMMIT;
50
51
diff --git a/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
new file mode 100644
index 0000000..f23c870
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
@@ -0,0 +1,83 @@
1:VERSION 1 # -------------------------------
2
3begin;
4
5CREATE TABLE classifieds (
6 "classifieduuid" char(36) NOT NULL,
7 "creatoruuid" char(36) NOT NULL,
8 "creationdate" integer NOT NULL,
9 "expirationdate" integer NOT NULL,
10 "category" varchar(20) NOT NULL,
11 "name" varchar(255) NOT NULL,
12 "description" text NOT NULL,
13 "parceluuid" char(36) NOT NULL,
14 "parentestate" integer NOT NULL,
15 "snapshotuuid" char(36) NOT NULL,
16 "simname" varchar(255) NOT NULL,
17 "posglobal" varchar(255) NOT NULL,
18 "parcelname" varchar(255) NOT NULL,
19 "classifiedflags" integer NOT NULL,
20 "priceforlisting" integer NOT NULL,
21 constraint classifiedspk PRIMARY KEY ("classifieduuid")
22);
23
24
25CREATE TABLE usernotes (
26 "useruuid" varchar(36) NOT NULL,
27 "targetuuid" varchar(36) NOT NULL,
28 "notes" text NOT NULL,
29 constraint usernoteuk UNIQUE ("useruuid","targetuuid")
30);
31
32
33CREATE TABLE userpicks (
34 "pickuuid" varchar(36) NOT NULL,
35 "creatoruuid" varchar(36) NOT NULL,
36 "toppick" boolean NOT NULL,
37 "parceluuid" varchar(36) NOT NULL,
38 "name" varchar(255) NOT NULL,
39 "description" text NOT NULL,
40 "snapshotuuid" varchar(36) NOT NULL,
41 "user" varchar(255) NOT NULL,
42 "originalname" varchar(255) NOT NULL,
43 "simname" varchar(255) NOT NULL,
44 "posglobal" varchar(255) NOT NULL,
45 "sortorder" integer NOT NULL,
46 "enabled" boolean NOT NULL,
47 PRIMARY KEY ("pickuuid")
48);
49
50
51CREATE TABLE userprofile (
52 "useruuid" varchar(36) NOT NULL,
53 "profilePartner" varchar(36) NOT NULL,
54 "profileAllowPublish" bytea NOT NULL,
55 "profileMaturePublish" bytea NOT NULL,
56 "profileURL" varchar(255) NOT NULL,
57 "profileWantToMask" integer NOT NULL,
58 "profileWantToText" text NOT NULL,
59 "profileSkillsMask" integer NOT NULL,
60 "profileSkillsText" text NOT NULL,
61 "profileLanguages" text NOT NULL,
62 "profileImage" varchar(36) NOT NULL,
63 "profileAboutText" text NOT NULL,
64 "profileFirstImage" varchar(36) NOT NULL,
65 "profileFirstText" text NOT NULL,
66 PRIMARY KEY ("useruuid")
67);
68
69commit;
70
71:VERSION 2 # -------------------------------
72
73begin;
74CREATE TABLE userdata (
75 "UserId" char(36) NOT NULL,
76 "TagId" varchar(64) NOT NULL,
77 "DataKey" varchar(255),
78 "DataVal" varchar(255),
79 PRIMARY KEY ("UserId","TagId")
80);
81
82commit;
83
diff --git a/OpenSim/Data/PGSQL/Resources/UserStore.migrations b/OpenSim/Data/PGSQL/Resources/UserStore.migrations
new file mode 100644
index 0000000..974d489
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/UserStore.migrations
@@ -0,0 +1,404 @@
1:VERSION 1
2
3CREATE TABLE users (
4 "UUID" varchar(36) NOT NULL default '' Primary Key,
5 "username" varchar(32) NOT NULL,
6 "lastname" varchar(32) NOT NULL,
7 "passwordHash" varchar(32) NOT NULL,
8 "passwordSalt" varchar(32) NOT NULL,
9 "homeRegion" bigint default NULL,
10 "homeLocationX" double precision default NULL,
11 "homeLocationY" double precision default NULL,
12 "homeLocationZ" double precision default NULL,
13 "homeLookAtX" double precision default NULL,
14 "homeLookAtY" double precision default NULL,
15 "homeLookAtZ" double precision default NULL,
16 "created" int NOT NULL,
17 "lastLogin" int NOT NULL,
18 "userInventoryURI" varchar(255) default NULL,
19 "userAssetURI" varchar(255) default NULL,
20 "profileCanDoMask" int default NULL,
21 "profileWantDoMask" int default NULL,
22 "profileAboutText" text,
23 "profileFirstText" text,
24 "profileImage" varchar(36) default NULL,
25 "profileFirstImage" varchar(36) default NULL,
26 "webLoginKey" varchar(36) default NULL
27);
28
29CREATE INDEX "usernames" ON users
30(
31 "username" ASC,
32 "lastname" ASC
33);
34
35
36CREATE TABLE agents (
37 "UUID" varchar(36) NOT NULL Primary Key,
38 "sessionID" varchar(36) NOT NULL,
39 "secureSessionID" varchar(36) NOT NULL,
40 "agentIP" varchar(16) NOT NULL,
41 "agentPort" int NOT NULL,
42 "agentOnline" smallint NOT NULL,
43 "loginTime" int NOT NULL,
44 "logoutTime" int NOT NULL,
45 "currentRegion" varchar(36) NOT NULL,
46 "currentHandle" bigint NOT NULL,
47 "currentPos" varchar(64) NOT NULL
48);
49
50CREATE INDEX session ON agents
51(
52 "sessionID" ASC
53);
54
55CREATE INDEX ssession ON agents
56(
57 "secureSessionID" ASC
58);
59
60
61CREATE TABLE userfriends(
62 "ownerID" varchar(50) NOT NULL,
63 "friendID" varchar(50) NOT NULL,
64 "friendPerms" varchar(50) NOT NULL,
65 "datetimestamp" varchar(50) NOT NULL
66);
67
68CREATE TABLE avatarappearance (
69 "Owner" varchar(36) NOT NULL primary key,
70 "Serial" int NOT NULL,
71 "Visual_Params" bytea NOT NULL,
72 "Texture" bytea NOT NULL,
73 "Avatar_Height" double precision NOT NULL,
74 "Body_Item" varchar(36) NOT NULL,
75 "Body_Asset" varchar(36) NOT NULL,
76 "Skin_Item" varchar(36) NOT NULL,
77 "Skin_Asset" varchar(36) NOT NULL,
78 "Hair_Item" varchar(36) NOT NULL,
79 "Hair_Asset" varchar(36) NOT NULL,
80 "Eyes_Item" varchar(36) NOT NULL,
81 "Eyes_Asset" varchar(36) NOT NULL,
82 "Shirt_Item" varchar(36) NOT NULL,
83 "Shirt_Asset" varchar(36) NOT NULL,
84 "Pants_Item" varchar(36) NOT NULL,
85 "Pants_Asset" varchar(36) NOT NULL,
86 "Shoes_Item" varchar(36) NOT NULL,
87 "Shoes_Asset" varchar(36) NOT NULL,
88 "Socks_Item" varchar(36) NOT NULL,
89 "Socks_Asset" varchar(36) NOT NULL,
90 "Jacket_Item" varchar(36) NOT NULL,
91 "Jacket_Asset" varchar(36) NOT NULL,
92 "Gloves_Item" varchar(36) NOT NULL,
93 "Gloves_Asset" varchar(36) NOT NULL,
94 "Undershirt_Item" varchar(36) NOT NULL,
95 "Undershirt_Asset" varchar(36) NOT NULL,
96 "Underpants_Item" varchar(36) NOT NULL,
97 "Underpants_Asset" varchar(36) NOT NULL,
98 "Skirt_Item" varchar(36) NOT NULL,
99 "Skirt_Asset" varchar(36) NOT NULL
100);
101
102:VERSION 2
103
104BEGIN TRANSACTION;
105
106ALTER TABLE users ADD "homeRegionID" varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000';
107ALTER TABLE users ADD "userFlags" int NOT NULL default 0;
108ALTER TABLE users ADD "godLevel" int NOT NULL default 0;
109ALTER TABLE users ADD "customType" varchar(32) not null default '';
110ALTER TABLE users ADD "partner" varchar(36) not null default '00000000-0000-0000-0000-000000000000';
111
112COMMIT;
113
114
115:VERSION 3
116
117BEGIN TRANSACTION;
118
119CREATE TABLE avatarattachments (
120 "UUID" varchar(36) NOT NULL
121 , "attachpoint" int NOT NULL
122 , item varchar(36) NOT NULL
123 , asset varchar(36) NOT NULL);
124
125CREATE INDEX IX_avatarattachments ON avatarattachments
126 (
127 "UUID"
128 );
129
130COMMIT;
131
132
133:VERSION 4
134
135BEGIN TRANSACTION;
136
137CREATE TABLE Tmp_userfriends
138 (
139 "ownerID" varchar(36) NOT NULL,
140 "friendID" varchar(36) NOT NULL,
141 "friendPerms" int NOT NULL,
142 "datetimestamp" int NOT NULL
143 );
144
145INSERT INTO Tmp_userfriends ("ownerID", "friendID", "friendPerms", "datetimestamp")
146 SELECT cast("ownerID" as varchar(36)), cast("friendID" as varchar(36)), cast("friendPerms" as int), cast("datetimestamp" as int)
147 FROM userfriends;
148
149DROP TABLE userfriends;
150
151alter table Tmp_userfriends rename to userfriends;
152
153CREATE INDEX IX_userfriends_ownerID ON userfriends
154 (
155 "ownerID"
156 );
157
158CREATE INDEX IX_userfriends_friendID ON userfriends
159 (
160 "friendID"
161 );
162
163COMMIT;
164
165
166:VERSION 5
167
168BEGIN TRANSACTION;
169
170 ALTER TABLE users add "email" varchar(250);
171
172COMMIT;
173
174
175:VERSION 6
176
177BEGIN TRANSACTION;
178
179CREATE TABLE Tmp_users
180 (
181 "UUID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
182 "username" varchar(32) NOT NULL,
183 "lastname" varchar(32) NOT NULL,
184 "passwordHash" varchar(32) NOT NULL,
185 "passwordSalt" varchar(32) NOT NULL,
186 "homeRegion" bigint NULL DEFAULT (NULL),
187 "homeLocationX" double precision NULL DEFAULT (NULL),
188 "homeLocationY" double precision NULL DEFAULT (NULL),
189 "homeLocationZ" double precision NULL DEFAULT (NULL),
190 "homeLookAtX" double precision NULL DEFAULT (NULL),
191 "homeLookAtY" double precision NULL DEFAULT (NULL),
192 "homeLookAtZ" double precision NULL DEFAULT (NULL),
193 "created" int NOT NULL,
194 "lastLogin" int NOT NULL,
195 "userInventoryURI" varchar(255) NULL DEFAULT (NULL),
196 "userAssetURI" varchar(255) NULL DEFAULT (NULL),
197 "profileCanDoMask" int NULL DEFAULT (NULL),
198 "profileWantDoMask" int NULL DEFAULT (NULL),
199 "profileAboutText" text NULL,
200 "profileFirstText" text NULL,
201 "profileImage" uuid NULL DEFAULT (NULL),
202 "profileFirstImage" uuid NULL DEFAULT (NULL),
203 "webLoginKey" uuid NULL DEFAULT (NULL),
204 "homeRegionID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
205 "userFlags" int NOT NULL DEFAULT ((0)),
206 "godLevel" int NOT NULL DEFAULT ((0)),
207 "customType" varchar(32) NOT NULL DEFAULT (''),
208 "partner" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
209 email varchar(250) NULL
210 );
211
212INSERT INTO Tmp_users ("UUID", "username", "lastname", "passwordHash", "passwordSalt", "homeRegion", "homeLocationX", "homeLocationY", "homeLocationZ", "homeLookAtX", "homeLookAtY", "homeLookAtZ", "created", "lastLogin", "userInventoryURI", "userAssetURI", "profileCanDoMask", "profileWantDoMask", "profileAboutText", "profileFirstText", "profileImage", "profileFirstImage", "webLoginKey", "homeRegionID", "userFlags", "godLevel", "customType", "partner", email)
213 SELECT cast("UUID" as uuid), "username", "lastname", "passwordHash", "passwordSalt", "homeRegion", "homeLocationX", "homeLocationY", "homeLocationZ", "homeLookAtX", "homeLookAtY", "homeLookAtZ", "created", "lastLogin", "userInventoryURI", "userAssetURI", "profileCanDoMask", "profileWantDoMask", "profileAboutText", "profileFirstText", cast("profileImage" as uuid), cast("profileFirstImage" as uuid), cast("webLoginKey" as uuid), cast("homeRegionID" as uuid), "userFlags", "godLevel", "customType", cast("partner" as uuid), email
214 FROM users ;
215
216DROP TABLE users;
217
218alter table Tmp_users rename to users;
219
220ALTER TABLE users ADD CONSTRAINT
221 PK__users__65A475E737A5467C PRIMARY KEY
222 (
223 "UUID"
224 );
225
226CREATE INDEX "usernames" ON users
227 (
228 "username",
229 "lastname"
230 );
231
232COMMIT;
233
234
235:VERSION 7
236
237BEGIN TRANSACTION;
238
239CREATE TABLE Tmp_agents
240 (
241 "UUID" uuid NOT NULL,
242 "sessionID" uuid NOT NULL,
243 "secureSessionID" uuid NOT NULL,
244 "agentIP" varchar(16) NOT NULL,
245 "agentPort" int NOT NULL,
246 "agentOnline" smallint NOT NULL,
247 "loginTime" int NOT NULL,
248 "logoutTime" int NOT NULL,
249 "currentRegion" uuid NOT NULL,
250 "currentHandle" bigint NOT NULL,
251 "currentPos" varchar(64) NOT NULL
252 );
253
254INSERT INTO Tmp_agents ("UUID", "sessionID", "secureSessionID", "agentIP", "agentPort", "agentOnline", "loginTime", "logoutTime", "currentRegion", "currentHandle", "currentPos")
255 SELECT cast("UUID" as uuid), cast("sessionID" as uuid), cast("secureSessionID" as uuid), "agentIP", "agentPort", "agentOnline", "loginTime", "logoutTime", cast("currentRegion" as uuid), "currentHandle", "currentPos"
256 FROM agents ;
257
258DROP TABLE agents;
259
260alter table Tmp_agents rename to agents;
261
262ALTER TABLE agents ADD CONSTRAINT
263 PK__agents__65A475E749C3F6B7 PRIMARY KEY
264 (
265 "UUID"
266 ) ;
267
268CREATE INDEX session ON agents
269 (
270 "sessionID"
271 );
272
273CREATE INDEX ssession ON agents
274 (
275 "secureSessionID"
276 );
277
278COMMIT;
279
280
281:VERSION 8
282
283BEGIN TRANSACTION;
284
285CREATE TABLE Tmp_userfriends
286 (
287 "ownerID" uuid NOT NULL,
288 "friendID" uuid NOT NULL,
289 "friendPerms" int NOT NULL,
290 "datetimestamp" int NOT NULL
291 );
292
293INSERT INTO Tmp_userfriends ("ownerID", "friendID", "friendPerms", "datetimestamp")
294 SELECT cast("ownerID" as uuid), cast( "friendID" as uuid), "friendPerms", "datetimestamp"
295 FROM userfriends;
296
297DROP TABLE userfriends;
298
299alter table Tmp_userfriends rename to userfriends;
300
301CREATE INDEX IX_userfriends_ownerID ON userfriends
302 (
303 "ownerID"
304 );
305
306CREATE INDEX IX_userfriends_friendID ON userfriends
307 (
308 "friendID"
309 );
310
311COMMIT;
312
313
314:VERSION 9
315
316BEGIN TRANSACTION;
317
318CREATE TABLE Tmp_avatarappearance
319 (
320 "Owner" uuid NOT NULL,
321 "Serial" int NOT NULL,
322 "Visual_Params" bytea NOT NULL,
323 "Texture" bytea NOT NULL,
324 "Avatar_Height" double precision NOT NULL,
325 "Body_Item" uuid NOT NULL,
326 "Body_Asset" uuid NOT NULL,
327 "Skin_Item" uuid NOT NULL,
328 "Skin_Asset" uuid NOT NULL,
329 "Hair_Item" uuid NOT NULL,
330 "Hair_Asset" uuid NOT NULL,
331 "Eyes_Item" uuid NOT NULL,
332 "Eyes_Asset" uuid NOT NULL,
333 "Shirt_Item" uuid NOT NULL,
334 "Shirt_Asset" uuid NOT NULL,
335 "Pants_Item" uuid NOT NULL,
336 "Pants_Asset" uuid NOT NULL,
337 "Shoes_Item" uuid NOT NULL,
338 "Shoes_Asset" uuid NOT NULL,
339 "Socks_Item" uuid NOT NULL,
340 "Socks_Asset" uuid NOT NULL,
341 "Jacket_Item" uuid NOT NULL,
342 "Jacket_Asset" uuid NOT NULL,
343 "Gloves_Item" uuid NOT NULL,
344 "Gloves_Asset" uuid NOT NULL,
345 "Undershirt_Item" uuid NOT NULL,
346 "Undershirt_Asset" uuid NOT NULL,
347 "Underpants_Item" uuid NOT NULL,
348 "Underpants_Asset" uuid NOT NULL,
349 "Skirt_Item" uuid NOT NULL,
350 "Skirt_Asset" uuid NOT NULL
351 );
352
353INSERT INTO Tmp_avatarappearance ("Owner", "Serial", "Visual_Params", "Texture", "Avatar_Height", "Body_Item", "Body_Asset", "Skin_Item", "Skin_Asset", "Hair_Item", "Hair_Asset", "Eyes_Item", "Eyes_Asset", "Shirt_Item", "Shirt_Asset", "Pants_Item", "Pants_Asset", "Shoes_Item", "Shoes_Asset", "Socks_Item", "Socks_Asset", "Jacket_Item", "Jacket_Asset", "Gloves_Item", "Gloves_Asset", "Undershirt_Item", "Undershirt_Asset", "Underpants_Item", "Underpants_Asset", "Skirt_Item", "Skirt_Asset")
354 SELECT cast("Owner" as uuid), "Serial", "Visual_Params", "Texture", "Avatar_Height", cast("Body_Item" as uuid), cast("Body_Asset" as uuid), cast("Skin_Item" as uuid), cast("Skin_Asset" as uuid), cast("Hair_Item" as uuid), cast("Hair_Asset" as uuid), cast("Eyes_Item" as uuid), cast("Eyes_Asset" as uuid), cast("Shirt_Item" as uuid), cast("Shirt_Asset" as uuid), cast("Pants_Item" as uuid), cast("Pants_Asset" as uuid), cast("Shoes_Item" as uuid), cast("Shoes_Asset" as uuid), cast("Socks_Item" as uuid), cast("Socks_Asset" as uuid), cast("Jacket_Item" as uuid), cast("Jacket_Asset" as uuid), cast("Gloves_Item" as uuid), cast("Gloves_Asset" as uuid), cast("Undershirt_Item" as uuid), cast("Undershirt_Asset" as uuid), cast("Underpants_Item" as uuid), cast("Underpants_Asset" as uuid), cast("Skirt_Item" as uuid), cast("Skirt_Asset" as uuid)
355 FROM avatarappearance ;
356
357DROP TABLE avatarappearance;
358
359alter table Tmp_avatarappearance rename to avatarappearance;
360
361ALTER TABLE avatarappearance ADD CONSTRAINT
362 PK__avatarap__7DD115CC4E88ABD4 PRIMARY KEY
363 (
364 "Owner"
365 );
366
367COMMIT;
368
369
370:VERSION 10
371
372BEGIN TRANSACTION;
373
374CREATE TABLE Tmp_avatarattachments
375 (
376 "UUID" uuid NOT NULL,
377 "attachpoint" int NOT NULL,
378 item uuid NOT NULL,
379 asset uuid NOT NULL
380 );
381
382INSERT INTO Tmp_avatarattachments ("UUID", "attachpoint", item, asset)
383 SELECT cast("UUID" as uuid), "attachpoint", cast(item as uuid), cast(asset as uuid)
384 FROM avatarattachments ;
385
386DROP TABLE avatarattachments;
387
388alter table Tmp_avatarattachments rename to avatarattachments;
389
390CREATE INDEX IX_avatarattachments ON avatarattachments
391 (
392 "UUID"
393 );
394
395COMMIT;
396
397
398:VERSION 11
399
400BEGIN TRANSACTION;
401
402ALTER TABLE users ADD "scopeID" uuid not null default '00000000-0000-0000-0000-000000000000';
403
404COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/XAssetStore.migrations b/OpenSim/Data/PGSQL/Resources/XAssetStore.migrations
new file mode 100644
index 0000000..325ed0d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/XAssetStore.migrations
@@ -0,0 +1,27 @@
1# -----------------
2:VERSION 1
3
4BEGIN;
5
6CREATE TABLE XAssetsMeta (
7 "ID" char(36) NOT NULL,
8 "Hash" char(32) NOT NULL,
9 "Name" varchar(64) NOT NULL,
10 "Description" varchar(64) NOT NULL,
11 "AssetType" smallint NOT NULL,
12 "Local" smallint NOT NULL,
13 "Temporary" smallint NOT NULL,
14 "CreateTime" integer NOT NULL,
15 "AccessTime" integer NOT NULL,
16 "AssetFlags" integer NOT NULL,
17 "CreatorID" varchar(128) NOT NULL,
18 PRIMARY KEY ("ID")
19);
20
21CREATE TABLE XAssetsData (
22 "Hash" char(32) NOT NULL,
23 "Data" bytea NOT NULL,
24 PRIMARY KEY ("Hash")
25);
26
27COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations b/OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations
new file mode 100644
index 0000000..4573f71
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations
@@ -0,0 +1,94 @@
1:VERSION 1 # --------------------------
2
3BEGIN;
4
5CREATE TABLE os_groups_groups (
6 "GroupID" char(36) Primary Key NOT NULL default '',
7 "Location" varchar(255) NOT NULL default '',
8 "Name" varchar(255) NOT NULL default '',
9 "Charter" text NOT NULL,
10 "InsigniaID" char(36) NOT NULL default '',
11 "FounderID" char(36) NOT NULL default '',
12 "MembershipFee" integer NOT NULL default '0',
13 "OpenEnrollment" varchar(255) NOT NULL default '',
14 "ShowInList" integer NOT NULL default '0',
15 "AllowPublish" integer NOT NULL default '0',
16 "MaturePublish" integer NOT NULL default '0',
17 "OwnerRoleID" char(36) NOT NULL default ''
18);
19
20
21CREATE TABLE os_groups_membership (
22 "GroupID"char(36) NOT NULL default '',
23 "PrincipalID" VARCHAR(255) NOT NULL default '',
24 "SelectedRoleID" char(36) NOT NULL default '',
25 "Contribution" integer NOT NULL default '0',
26 "ListInProfile" integer NOT NULL default '1',
27 "AcceptNotices" integer NOT NULL default '1',
28 "AccessToken" char(36) NOT NULL default '',
29 constraint os_groupmemberpk primary key ("GroupID", "PrincipalID")
30);
31
32
33
34CREATE TABLE os_groups_roles (
35 "GroupID" char(36) NOT NULL default '',
36 "RoleID" char(36) NOT NULL default '',
37 "Name" varchar(255) NOT NULL default '',
38 "Description" varchar(255) NOT NULL default '',
39 "Title" varchar(255) NOT NULL default '',
40 "Powers" bigint NOT NULL default 0,
41 constraint os_grouprolepk PRIMARY KEY ("GroupID","RoleID")
42);
43
44
45CREATE TABLE os_groups_rolemembership (
46 "GroupID" char(36) NOT NULL default '',
47 "RoleID" char(36) NOT NULL default '',
48 "PrincipalID" VARCHAR(255) NOT NULL default '',
49 constraint os_grouprolememberpk PRIMARY KEY ("GroupID","RoleID","PrincipalID")
50);
51
52
53CREATE TABLE os_groups_invites (
54 "InviteID" char(36) NOT NULL default '',
55 "GroupID" char(36) NOT NULL default '',
56 "RoleID" char(36) NOT NULL default '',
57 "PrincipalID" VARCHAR(255) NOT NULL default '',
58 "TMStamp" timestamp NOT NULL default now(),
59 constraint os_groupinvitespk PRIMARY KEY ("InviteID")
60);
61-- UNIQUE KEY "PrincipalGroup" ("GroupID","PrincipalID")
62
63
64CREATE TABLE os_groups_notices (
65 "GroupID" char(36) NOT NULL default '',
66 "NoticeID" char(36) NOT NULL default '',
67 "TMStamp" integer NOT NULL default '0',
68 "FromName" varchar(255) NOT NULL default '',
69 "Subject" varchar(255) NOT NULL default '',
70 "Message" text NOT NULL,
71 "HasAttachment" integer NOT NULL default '0',
72 "AttachmentType" integer NOT NULL default '0',
73 "AttachmentName" varchar(128) NOT NULL default '',
74 "AttachmentItemID" char(36) NOT NULL default '',
75 "AttachmentOwnerID" varchar(255) NOT NULL default '',
76 constraint os_groupsnoticespk PRIMARY KEY ("NoticeID")
77);
78-- KEY "GroupID" ("GroupID"),
79-- KEY "TMStamp" ("TMStamp")
80
81CREATE TABLE os_groups_principals (
82 "PrincipalID" VARCHAR(255) NOT NULL default '',
83 "ActiveGroupID" char(36) NOT NULL default '',
84 constraint os_groupprincpk PRIMARY KEY ("PrincipalID")
85);
86
87COMMIT;
88
89:VERSION 2 # --------------------------
90
91BEGIN;
92
93
94COMMIT;
diff --git a/OpenSim/Framework/BasicDOSProtector.cs b/OpenSim/Framework/BasicDOSProtector.cs
new file mode 100644
index 0000000..89bfa94
--- /dev/null
+++ b/OpenSim/Framework/BasicDOSProtector.cs
@@ -0,0 +1,275 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31
32namespace OpenSim.Framework
33{
34
35 public class BasicDOSProtector
36 {
37 public enum ThrottleAction
38 {
39 DoThrottledMethod,
40 DoThrow
41 }
42 private readonly CircularBuffer<int> _generalRequestTimes; // General request checker
43 private readonly BasicDosProtectorOptions _options;
44 private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; // per client request checker
45 private readonly Dictionary<string, int> _tempBlocked; // blocked list
46 private readonly Dictionary<string, int> _sessions;
47 private readonly System.Timers.Timer _forgetTimer; // Cleanup timer
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private readonly System.Threading.ReaderWriterLockSlim _blockLockSlim = new System.Threading.ReaderWriterLockSlim();
50 private readonly System.Threading.ReaderWriterLockSlim _sessionLockSlim = new System.Threading.ReaderWriterLockSlim();
51 public BasicDOSProtector(BasicDosProtectorOptions options)
52 {
53 _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true);
54 _generalRequestTimes.Put(0);
55 _options = options;
56 _deeperInspection = new Dictionary<string, CircularBuffer<int>>();
57 _tempBlocked = new Dictionary<string, int>();
58 _sessions = new Dictionary<string, int>();
59 _forgetTimer = new System.Timers.Timer();
60 _forgetTimer.Elapsed += delegate
61 {
62 _forgetTimer.Enabled = false;
63
64 List<string> removes = new List<string>();
65 _blockLockSlim.EnterReadLock();
66 foreach (string str in _tempBlocked.Keys)
67 {
68 if (
69 Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),
70 _tempBlocked[str]) > 0)
71 removes.Add(str);
72 }
73 _blockLockSlim.ExitReadLock();
74 lock (_deeperInspection)
75 {
76 _blockLockSlim.EnterWriteLock();
77 for (int i = 0; i < removes.Count; i++)
78 {
79 _tempBlocked.Remove(removes[i]);
80 _deeperInspection.Remove(removes[i]);
81 _sessions.Remove(removes[i]);
82 }
83 _blockLockSlim.ExitWriteLock();
84 }
85 foreach (string str in removes)
86 {
87 m_log.InfoFormat("[{0}] client: {1} is no longer blocked.",
88 _options.ReportingName, str);
89 }
90 _blockLockSlim.EnterReadLock();
91 if (_tempBlocked.Count > 0)
92 _forgetTimer.Enabled = true;
93 _blockLockSlim.ExitReadLock();
94 };
95
96 _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds;
97 }
98
99 /// <summary>
100 /// Given a string Key, Returns if that context is blocked
101 /// </summary>
102 /// <param name="key">A Key identifying the context</param>
103 /// <returns>bool Yes or No, True or False for blocked</returns>
104 public bool IsBlocked(string key)
105 {
106 bool ret = false;
107 _blockLockSlim.EnterReadLock();
108 ret = _tempBlocked.ContainsKey(key);
109 _blockLockSlim.ExitReadLock();
110 return ret;
111 }
112
113 /// <summary>
114 /// Process the velocity of this context
115 /// </summary>
116 /// <param name="key"></param>
117 /// <param name="endpoint"></param>
118 /// <returns></returns>
119 public bool Process(string key, string endpoint)
120 {
121 if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1)
122 return true;
123
124 string clientstring = key;
125
126 _blockLockSlim.EnterReadLock();
127 if (_tempBlocked.ContainsKey(clientstring))
128 {
129 _blockLockSlim.ExitReadLock();
130
131 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
132 return false;
133 else
134 throw new System.Security.SecurityException("Throttled");
135 }
136
137 _blockLockSlim.ExitReadLock();
138
139 lock (_generalRequestTimes)
140 _generalRequestTimes.Put(Util.EnvironmentTickCount());
141
142 if (_options.MaxConcurrentSessions > 0)
143 {
144 int sessionscount = 0;
145
146 _sessionLockSlim.EnterReadLock();
147 if (_sessions.ContainsKey(key))
148 sessionscount = _sessions[key];
149 _sessionLockSlim.ExitReadLock();
150
151 if (sessionscount > _options.MaxConcurrentSessions)
152 {
153 // Add to blocking and cleanup methods
154 lock (_deeperInspection)
155 {
156 _blockLockSlim.EnterWriteLock();
157 if (!_tempBlocked.ContainsKey(clientstring))
158 {
159 _tempBlocked.Add(clientstring,
160 Util.EnvironmentTickCount() +
161 (int) _options.ForgetTimeSpan.TotalMilliseconds);
162 _forgetTimer.Enabled = true;
163 m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds based on concurrency, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
164
165 }
166 else
167 _tempBlocked[clientstring] = Util.EnvironmentTickCount() +
168 (int) _options.ForgetTimeSpan.TotalMilliseconds;
169 _blockLockSlim.ExitWriteLock();
170
171 }
172
173
174 }
175 else
176 ProcessConcurrency(key, endpoint);
177 }
178 if (_generalRequestTimes.Size == _generalRequestTimes.Capacity &&
179 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) <
180 _options.RequestTimeSpan.TotalMilliseconds))
181 {
182 //Trigger deeper inspection
183 if (DeeperInspection(key, endpoint))
184 return true;
185 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
186 return false;
187 else
188 throw new System.Security.SecurityException("Throttled");
189 }
190 return true;
191 }
192 private void ProcessConcurrency(string key, string endpoint)
193 {
194 _sessionLockSlim.EnterWriteLock();
195 if (_sessions.ContainsKey(key))
196 _sessions[key] = _sessions[key] + 1;
197 else
198 _sessions.Add(key,1);
199 _sessionLockSlim.ExitWriteLock();
200 }
201 public void ProcessEnd(string key, string endpoint)
202 {
203 _sessionLockSlim.EnterWriteLock();
204 if (_sessions.ContainsKey(key))
205 {
206 _sessions[key]--;
207 if (_sessions[key] <= 0)
208 _sessions.Remove(key);
209 }
210 else
211 _sessions.Add(key, 1);
212
213 _sessionLockSlim.ExitWriteLock();
214 }
215
216 /// <summary>
217 /// At this point, the rate limiting code needs to track 'per user' velocity.
218 /// </summary>
219 /// <param name="key">Context Key, string representing a rate limiting context</param>
220 /// <param name="endpoint"></param>
221 /// <returns></returns>
222 private bool DeeperInspection(string key, string endpoint)
223 {
224 lock (_deeperInspection)
225 {
226 string clientstring = key;
227
228
229 if (_deeperInspection.ContainsKey(clientstring))
230 {
231 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
232 if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity &&
233 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) <
234 _options.RequestTimeSpan.TotalMilliseconds))
235 {
236 //Looks like we're over the limit
237 _blockLockSlim.EnterWriteLock();
238 if (!_tempBlocked.ContainsKey(clientstring))
239 _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds);
240 else
241 _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds;
242 _blockLockSlim.ExitWriteLock();
243
244 m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
245
246 return false;
247 }
248 //else
249 // return true;
250 }
251 else
252 {
253 _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true));
254 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
255 _forgetTimer.Enabled = true;
256 }
257
258 }
259 return true;
260 }
261
262 }
263
264
265 public class BasicDosProtectorOptions
266 {
267 public int MaxRequestsInTimeframe;
268 public TimeSpan RequestTimeSpan;
269 public TimeSpan ForgetTimeSpan;
270 public bool AllowXForwardedFor;
271 public string ReportingName = "BASICDOSPROTECTOR";
272 public BasicDOSProtector.ThrottleAction ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod;
273 public int MaxConcurrentSessions;
274 }
275}
diff --git a/OpenSim/Framework/CircularBuffer.cs b/OpenSim/Framework/CircularBuffer.cs
new file mode 100644
index 0000000..e919337
--- /dev/null
+++ b/OpenSim/Framework/CircularBuffer.cs
@@ -0,0 +1,312 @@
1/*
2Copyright (c) 2012, Alex Regueiro
3All rights reserved.
4Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
5following conditions are met:
6
7Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
9in the documentation and/or other materials provided with the distribution.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
12BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
13IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
14OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
15OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
16OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17POSSIBILITY OF SUCH DAMAGE.
18*/
19using System;
20using System.Collections;
21using System.Collections.Generic;
22using System.Threading;
23
24namespace OpenSim.Framework
25{
26 public class CircularBuffer<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
27 {
28 private int capacity;
29 private int size;
30 private int head;
31 private int tail;
32 private T[] buffer;
33
34 [NonSerialized()]
35 private object syncRoot;
36
37 public CircularBuffer(int capacity)
38 : this(capacity, false)
39 {
40 }
41
42 public CircularBuffer(int capacity, bool allowOverflow)
43 {
44 if (capacity < 0)
45 throw new ArgumentException("Needs to have at least 1","capacity");
46
47 this.capacity = capacity;
48 size = 0;
49 head = 0;
50 tail = 0;
51 buffer = new T[capacity];
52 AllowOverflow = allowOverflow;
53 }
54
55 public bool AllowOverflow
56 {
57 get;
58 set;
59 }
60
61 public int Capacity
62 {
63 get { return capacity; }
64 set
65 {
66 if (value == capacity)
67 return;
68
69 if (value < size)
70 throw new ArgumentOutOfRangeException("value","Capacity is too small.");
71
72 var dst = new T[value];
73 if (size > 0)
74 CopyTo(dst);
75 buffer = dst;
76
77 capacity = value;
78 }
79 }
80
81 public int Size
82 {
83 get { return size; }
84 }
85
86 public bool Contains(T item)
87 {
88 int bufferIndex = head;
89 var comparer = EqualityComparer<T>.Default;
90 for (int i = 0; i < size; i++, bufferIndex++)
91 {
92 if (bufferIndex == capacity)
93 bufferIndex = 0;
94
95 if (item == null && buffer[bufferIndex] == null)
96 return true;
97 else if ((buffer[bufferIndex] != null) &&
98 comparer.Equals(buffer[bufferIndex], item))
99 return true;
100 }
101
102 return false;
103 }
104
105 public void Clear()
106 {
107 size = 0;
108 head = 0;
109 tail = 0;
110 }
111
112 public int Put(T[] src)
113 {
114 return Put(src, 0, src.Length);
115 }
116
117 public int Put(T[] src, int offset, int count)
118 {
119 if (!AllowOverflow && count > capacity - size)
120 throw new InvalidOperationException("Buffer Overflow");
121
122 int srcIndex = offset;
123 for (int i = 0; i < count; i++, tail++, srcIndex++)
124 {
125 if (tail == capacity)
126 tail = 0;
127 buffer[tail] = src[srcIndex];
128 }
129 size = Math.Min(size + count, capacity);
130 return count;
131 }
132
133 public void Put(T item)
134 {
135 if (!AllowOverflow && size == capacity)
136 throw new InvalidOperationException("Buffer Overflow");
137
138 buffer[tail] = item;
139 if (++tail == capacity)
140 tail = 0;
141 size++;
142 }
143
144 public void Skip(int count)
145 {
146 head += count;
147 if (head >= capacity)
148 head -= capacity;
149 }
150
151 public T[] Get(int count)
152 {
153 var dst = new T[count];
154 Get(dst);
155 return dst;
156 }
157
158 public int Get(T[] dst)
159 {
160 return Get(dst, 0, dst.Length);
161 }
162
163 public int Get(T[] dst, int offset, int count)
164 {
165 int realCount = Math.Min(count, size);
166 int dstIndex = offset;
167 for (int i = 0; i < realCount; i++, head++, dstIndex++)
168 {
169 if (head == capacity)
170 head = 0;
171 dst[dstIndex] = buffer[head];
172 }
173 size -= realCount;
174 return realCount;
175 }
176
177 public T Get()
178 {
179 if (size == 0)
180 throw new InvalidOperationException("Buffer Empty");
181
182 var item = buffer[head];
183 if (++head == capacity)
184 head = 0;
185 size--;
186 return item;
187 }
188
189 public void CopyTo(T[] array)
190 {
191 CopyTo(array, 0);
192 }
193
194 public void CopyTo(T[] array, int arrayIndex)
195 {
196 CopyTo(0, array, arrayIndex, size);
197 }
198
199 public void CopyTo(int index, T[] array, int arrayIndex, int count)
200 {
201 if (count > size)
202 throw new ArgumentOutOfRangeException("count", "Count Too Large");
203
204 int bufferIndex = head;
205 for (int i = 0; i < count; i++, bufferIndex++, arrayIndex++)
206 {
207 if (bufferIndex == capacity)
208 bufferIndex = 0;
209 array[arrayIndex] = buffer[bufferIndex];
210 }
211 }
212
213 public IEnumerator<T> GetEnumerator()
214 {
215 int bufferIndex = head;
216 for (int i = 0; i < size; i++, bufferIndex++)
217 {
218 if (bufferIndex == capacity)
219 bufferIndex = 0;
220
221 yield return buffer[bufferIndex];
222 }
223 }
224
225 public T[] GetBuffer()
226 {
227 return buffer;
228 }
229
230 public T[] ToArray()
231 {
232 var dst = new T[size];
233 CopyTo(dst);
234 return dst;
235 }
236
237 #region ICollection<T> Members
238
239 int ICollection<T>.Count
240 {
241 get { return Size; }
242 }
243
244 bool ICollection<T>.IsReadOnly
245 {
246 get { return false; }
247 }
248
249 void ICollection<T>.Add(T item)
250 {
251 Put(item);
252 }
253
254 bool ICollection<T>.Remove(T item)
255 {
256 if (size == 0)
257 return false;
258
259 Get();
260 return true;
261 }
262
263 #endregion
264
265 #region IEnumerable<T> Members
266
267 IEnumerator<T> IEnumerable<T>.GetEnumerator()
268 {
269 return GetEnumerator();
270 }
271
272 #endregion
273
274 #region ICollection Members
275
276 int ICollection.Count
277 {
278 get { return Size; }
279 }
280
281 bool ICollection.IsSynchronized
282 {
283 get { return false; }
284 }
285
286 object ICollection.SyncRoot
287 {
288 get
289 {
290 if (syncRoot == null)
291 Interlocked.CompareExchange(ref syncRoot, new object(), null);
292 return syncRoot;
293 }
294 }
295
296 void ICollection.CopyTo(Array array, int arrayIndex)
297 {
298 CopyTo((T[])array, arrayIndex);
299 }
300
301 #endregion
302
303 #region IEnumerable Members
304
305 IEnumerator IEnumerable.GetEnumerator()
306 {
307 return (IEnumerator)GetEnumerator();
308 }
309
310 #endregion
311 }
312}
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
new file mode 100644
index 0000000..1b88545
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
@@ -0,0 +1,107 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using OpenSim.Framework;
28using System.IO;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 /// <summary>
33 /// BaseStreamHandlerBasicDOSProtector Base streamed request handler.
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
38 public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler
39 {
40
41 private readonly BasicDosProtectorOptions _options;
42 private readonly BasicDOSProtector _dosProtector;
43
44 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {}
45
46 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options)
47 : base(httpMethod, path, name, description)
48 {
49 _options = options;
50 _dosProtector = new BasicDOSProtector(_options);
51 }
52
53 public virtual byte[] Handle(
54 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
55 {
56 byte[] result;
57 RequestsReceived++;
58 string clientstring = GetClientString(httpRequest);
59 string endpoint = GetRemoteAddr(httpRequest);
60 if (_dosProtector.Process(clientstring, endpoint))
61 result = ProcessRequest(path, request, httpRequest, httpResponse);
62 else
63 result = ThrottledRequest(path, request, httpRequest, httpResponse);
64 if (_options.MaxConcurrentSessions > 0)
65 _dosProtector.ProcessEnd(clientstring, endpoint);
66
67 RequestsHandled++;
68
69 return result;
70 }
71
72 protected virtual byte[] ProcessRequest(
73 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
74 {
75 return null;
76 }
77
78 protected virtual byte[] ThrottledRequest(
79 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 {
81 return new byte[0];
82 }
83
84
85 private string GetRemoteAddr(IOSHttpRequest httpRequest)
86 {
87 string remoteaddr = string.Empty;
88 if (httpRequest.Headers["remote_addr"] != null)
89 remoteaddr = httpRequest.Headers["remote_addr"];
90
91 return remoteaddr;
92 }
93
94 private string GetClientString(IOSHttpRequest httpRequest)
95 {
96 string clientstring = string.Empty;
97
98 if (_options.AllowXForwardedFor && httpRequest.Headers["x-forwarded-for"] != null)
99 clientstring = httpRequest.Headers["x-forwarded-for"];
100 else
101 clientstring = GetRemoteAddr(httpRequest);
102
103 return clientstring;
104
105 }
106 }
107}
diff --git a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
new file mode 100644
index 0000000..cd4b8ff
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
@@ -0,0 +1,119 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 public class GenericHTTPDOSProtector
33 {
34 private readonly GenericHTTPMethod _normalMethod;
35 private readonly GenericHTTPMethod _throttledMethod;
36
37 private readonly BasicDosProtectorOptions _options;
38 private readonly BasicDOSProtector _dosProtector;
39
40 public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options)
41 {
42 _normalMethod = normalMethod;
43 _throttledMethod = throttledMethod;
44
45 _options = options;
46 _dosProtector = new BasicDOSProtector(_options);
47 }
48 public Hashtable Process(Hashtable request)
49 {
50 Hashtable process = null;
51 string clientstring= GetClientString(request);
52 string endpoint = GetRemoteAddr(request);
53 if (_dosProtector.Process(clientstring, endpoint))
54 process = _normalMethod(request);
55 else
56 process = _throttledMethod(request);
57
58 if (_options.MaxConcurrentSessions>0)
59 _dosProtector.ProcessEnd(clientstring, endpoint);
60
61 return process;
62 }
63
64 private string GetRemoteAddr(Hashtable request)
65 {
66 string remoteaddr = "";
67 if (!request.ContainsKey("headers"))
68 return remoteaddr;
69 Hashtable requestinfo = (Hashtable)request["headers"];
70 if (!requestinfo.ContainsKey("remote_addr"))
71 return remoteaddr;
72 object remote_addrobj = requestinfo["remote_addr"];
73 if (remote_addrobj != null)
74 {
75 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
76 {
77 remoteaddr = remote_addrobj.ToString();
78 }
79
80 }
81 return remoteaddr;
82 }
83
84 private string GetClientString(Hashtable request)
85 {
86 string clientstring = "";
87 if (!request.ContainsKey("headers"))
88 return clientstring;
89
90 Hashtable requestinfo = (Hashtable)request["headers"];
91 if (_options.AllowXForwardedFor && requestinfo.ContainsKey("x-forwarded-for"))
92 {
93 object str = requestinfo["x-forwarded-for"];
94 if (str != null)
95 {
96 if (!string.IsNullOrEmpty(str.ToString()))
97 {
98 return str.ToString();
99 }
100 }
101 }
102 if (!requestinfo.ContainsKey("remote_addr"))
103 return clientstring;
104
105 object remote_addrobj = requestinfo["remote_addr"];
106 if (remote_addrobj != null)
107 {
108 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
109 {
110 clientstring = remote_addrobj.ToString();
111 }
112 }
113
114 return clientstring;
115
116 }
117
118 }
119}
diff --git a/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
new file mode 100644
index 0000000..f212208
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
@@ -0,0 +1,91 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Net;
29using Nwc.XmlRpc;
30using OpenSim.Framework;
31
32
33namespace OpenSim.Framework.Servers.HttpServer
34{
35 public class XmlRpcBasicDOSProtector
36 {
37 private readonly XmlRpcMethod _normalMethod;
38 private readonly XmlRpcMethod _throttledMethod;
39
40 private readonly BasicDosProtectorOptions _options;
41 private readonly BasicDOSProtector _dosProtector;
42
43 public XmlRpcBasicDOSProtector(XmlRpcMethod normalMethod, XmlRpcMethod throttledMethod,BasicDosProtectorOptions options)
44 {
45 _normalMethod = normalMethod;
46 _throttledMethod = throttledMethod;
47
48 _options = options;
49 _dosProtector = new BasicDOSProtector(_options);
50
51 }
52 public XmlRpcResponse Process(XmlRpcRequest request, IPEndPoint client)
53 {
54
55 XmlRpcResponse resp = null;
56 string clientstring = GetClientString(request, client);
57 string endpoint = GetEndPoint(request, client);
58 if (_dosProtector.Process(clientstring, endpoint))
59 resp = _normalMethod(request, client);
60 else
61 resp = _throttledMethod(request, client);
62 if (_options.MaxConcurrentSessions > 0)
63 _dosProtector.ProcessEnd(clientstring, endpoint);
64 return resp;
65 }
66
67 private string GetClientString(XmlRpcRequest request, IPEndPoint client)
68 {
69 string clientstring;
70 if (_options.AllowXForwardedFor && request.Params.Count > 3)
71 {
72 object headerstr = request.Params[3];
73 if (headerstr != null && !string.IsNullOrEmpty(headerstr.ToString()))
74 clientstring = request.Params[3].ToString();
75 else
76 clientstring = client.Address.ToString();
77 }
78 else
79 clientstring = client.Address.ToString();
80 return clientstring;
81 }
82
83 private string GetEndPoint(XmlRpcRequest request, IPEndPoint client)
84 {
85 return client.Address.ToString();
86 }
87
88 }
89
90
91}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index da1ff2e..1e14f45 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework;
33 33
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
36using OpenSim.Region.Framework.Interfaces;
36 37
37namespace OpenSim.Region.CoreModules.Agent.AssetTransaction 38namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
38{ 39{
@@ -119,6 +120,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
119 } 120 }
120 else 121 else
121 { 122 {
123 // Check if the xfer is a terrain xfer
124 IEstateModule estateModule = m_Scene.RequestModuleInterface<IEstateModule>();
125 if (estateModule != null)
126 {
127 if (estateModule.IsTerrainXfer(xferID))
128 return;
129 }
130
122 m_log.ErrorFormat( 131 m_log.ErrorFormat(
123 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", 132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
124 xferID, packetID, data.Length); 133 xferID, packetID, data.Length);
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 2116605..ff87ece 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -42,14 +42,22 @@ using log4net;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.Friends 43namespace OpenSim.Region.CoreModules.Avatar.Friends
44{ 44{
45 public class FriendsRequestHandler : BaseStreamHandler 45 public class FriendsRequestHandler : BaseStreamHandlerBasicDOSProtector
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private FriendsModule m_FriendsModule; 49 private FriendsModule m_FriendsModule;
50 50
51 public FriendsRequestHandler(FriendsModule fmodule) 51 public FriendsRequestHandler(FriendsModule fmodule)
52 : base("POST", "/friends") 52 : base("POST", "/friends", new BasicDosProtectorOptions()
53 {
54 AllowXForwardedFor = true,
55 ForgetTimeSpan = TimeSpan.FromMinutes(2),
56 MaxRequestsInTimeframe = 20,
57 ReportingName = "FRIENDSDOSPROTECTOR",
58 RequestTimeSpan = TimeSpan.FromSeconds(5),
59 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
60 })
53 { 61 {
54 m_FriendsModule = fmodule; 62 m_FriendsModule = fmodule;
55 } 63 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index ac4203f..6251266 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -789,83 +789,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
789 789
790 SceneObjectGroup group = null; 790 SceneObjectGroup group = null;
791 791
792 string xmlData = Utils.BytesToString(rezAsset.Data); 792 List<SceneObjectGroup> objlist;
793 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); 793 List<Vector3> veclist;
794 List<Vector3> veclist = new List<Vector3>(); 794 Vector3 bbox;
795 float offsetHeight;
795 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 796 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
796 Vector3 pos; 797 Vector3 pos;
797 798
798 XmlDocument doc = new XmlDocument(); 799 bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
799 doc.LoadXml(xmlData);
800 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
801 Vector3 rez_pos;
802 if (e == null || attachment) // Single
803 {
804 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
805 if (!attachment)
806 {
807 g.RootPart.AttachPoint = g.RootPart.Shape.State;
808 g.RootPart.AttachOffset = g.AbsolutePosition;
809 g.RootPart.AttachRotation = g.GroupRotation;
810 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
811 g.RootPart.Shape.PCode != (byte)PCode.Tree)
812 g.RootPart.Shape.State = 0;
813 }
814
815 objlist.Add(g);
816 veclist.Add(Vector3.Zero);
817 800
818 float offsetHeight = 0; 801 if (single)
802 {
819 pos = m_Scene.GetNewRezLocation( 803 pos = m_Scene.GetNewRezLocation(
820 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 804 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
821 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); 805 BypassRayCast, bRayEndIsIntersection, true, bbox, false);
822 pos.Z += offsetHeight; 806 pos.Z += offsetHeight;
823 rez_pos = pos;
824 } 807 }
825 else 808 else
826 { 809 {
827 XmlElement coll = (XmlElement)e;
828 float bx = Convert.ToSingle(coll.GetAttribute("x"));
829 float by = Convert.ToSingle(coll.GetAttribute("y"));
830 float bz = Convert.ToSingle(coll.GetAttribute("z"));
831 Vector3 bbox = new Vector3(bx, by, bz);
832
833 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, 810 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
834 RayTargetID, Quaternion.Identity, 811 RayTargetID, Quaternion.Identity,
835 BypassRayCast, bRayEndIsIntersection, true, 812 BypassRayCast, bRayEndIsIntersection, true,
836 bbox, false); 813 bbox, false);
837
838 rez_pos = pos;
839
840 pos -= bbox / 2; 814 pos -= bbox / 2;
841
842 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
843 foreach (XmlNode n in groups)
844 {
845 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
846 g.RootPart.AttachPoint = g.RootPart.Shape.State;
847 g.RootPart.AttachOffset = g.AbsolutePosition;
848 g.RootPart.AttachRotation = g.GroupRotation;
849 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
850 g.RootPart.Shape.PCode != (byte)PCode.Tree)
851 g.RootPart.Shape.State = 0;
852
853 objlist.Add(g);
854 XmlElement el = (XmlElement)n;
855
856 string rawX = el.GetAttribute("offsetx");
857 string rawY = el.GetAttribute("offsety");
858 string rawZ = el.GetAttribute("offsetz");
859//
860// m_log.DebugFormat(
861// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
862// g.Name, rawX, rawY, rawZ);
863
864 float x = Convert.ToSingle(rawX);
865 float y = Convert.ToSingle(rawY);
866 float z = Convert.ToSingle(rawZ);
867 veclist.Add(new Vector3(x, y, z));
868 }
869 } 815 }
870 816
871 int primcount = 0; 817 int primcount = 0;
@@ -873,7 +819,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
873 primcount += g.PrimCount; 819 primcount += g.PrimCount;
874 820
875 if (!m_Scene.Permissions.CanRezObject( 821 if (!m_Scene.Permissions.CanRezObject(
876 primcount, remoteClient.AgentId, rez_pos) 822 primcount, remoteClient.AgentId, pos)
877 && !attachment) 823 && !attachment)
878 { 824 {
879 // The client operates in no fail mode. It will 825 // The client operates in no fail mode. It will
@@ -890,7 +836,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
890 return null; 836 return null;
891 } 837 }
892 838
893 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, rez_pos, veclist, attachment)) 839 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
894 return null; 840 return null;
895 841
896 for (int i = 0; i < objlist.Count; i++) 842 for (int i = 0; i < objlist.Count; i++)
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 487aa09..4750b46 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -839,26 +839,23 @@ namespace OpenSim.Region.CoreModules.World.Estate
839 839
840 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) 840 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
841 { 841 {
842 if (TerrainUploader != null) 842 lock (this)
843 { 843 {
844 lock (TerrainUploader) 844 if ((TerrainUploader != null) && (XferID == TerrainUploader.XferID))
845 { 845 {
846 if (XferID == TerrainUploader.XferID) 846 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
847 { 847 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
848 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 848 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
849 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
850 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
851 849
852 TerrainUploader = null; 850 TerrainUploader = null;
853 remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); 851 remoteClient.SendAlertMessage("Terrain Upload aborted by the client");
854 }
855 } 852 }
856 } 853 }
857
858 } 854 }
855
859 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) 856 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient)
860 { 857 {
861 lock (TerrainUploader) 858 lock (this)
862 { 859 {
863 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 860 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
864 remoteClient.OnAbortXfer -= AbortTerrainXferHandler; 861 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
@@ -917,22 +914,32 @@ namespace OpenSim.Region.CoreModules.World.Estate
917 914
918 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) 915 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName)
919 { 916 {
920 if (TerrainUploader == null) 917 lock (this)
921 { 918 {
922 919 if (TerrainUploader == null)
923 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
924 lock (TerrainUploader)
925 { 920 {
921 m_log.DebugFormat("Starting to receive uploaded terrain");
922 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
926 remote_client.OnXferReceive += TerrainUploader.XferReceive; 923 remote_client.OnXferReceive += TerrainUploader.XferReceive;
927 remote_client.OnAbortXfer += AbortTerrainXferHandler; 924 remote_client.OnAbortXfer += AbortTerrainXferHandler;
928 TerrainUploader.TerrainUploadDone += HandleTerrainApplication; 925 TerrainUploader.TerrainUploadDone += HandleTerrainApplication;
926 TerrainUploader.RequestStartXfer(remote_client);
927 }
928 else
929 {
930 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!");
929 } 931 }
930 TerrainUploader.RequestStartXfer(remote_client);
931
932 } 932 }
933 else 933 }
934
935 public bool IsTerrainXfer(ulong xferID)
936 {
937 lock (this)
934 { 938 {
935 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); 939 if (TerrainUploader == null)
940 return false;
941 else
942 return TerrainUploader.XferID == xferID;
936 } 943 }
937 } 944 }
938 945
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
index b8d8b10..2d74eaf 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
@@ -78,7 +78,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
78 /// <param name="data"></param> 78 /// <param name="data"></param>
79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) 79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
80 { 80 {
81 if (mXferID == xferID) 81 if (mXferID != xferID)
82 return;
83
84 lock (this)
82 { 85 {
83 if (m_asset.Data.Length > 1) 86 if (m_asset.Data.Length > 1)
84 { 87 {
@@ -99,7 +102,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
99 if ((packetID & 0x80000000) != 0) 102 if ((packetID & 0x80000000) != 0)
100 { 103 {
101 SendCompleteMessage(remoteClient); 104 SendCompleteMessage(remoteClient);
102
103 } 105 }
104 } 106 }
105 } 107 }
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index bf18616..98fa763 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -162,7 +162,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
162 regionimage = regionimage.Replace("-", ""); 162 regionimage = regionimage.Replace("-", "");
163 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage); 163 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage);
164 164
165 MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); 165 MainServer.Instance.AddHTTPHandler(regionimage,
166 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
167 {
168 AllowXForwardedFor = false,
169 ForgetTimeSpan = TimeSpan.FromMinutes(2),
170 MaxRequestsInTimeframe = 4,
171 ReportingName = "MAPDOSPROTECTOR",
172 RequestTimeSpan = TimeSpan.FromSeconds(10),
173 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
174 }).Process);
166 MainServer.Instance.AddLLSDHandler( 175 MainServer.Instance.AddLLSDHandler(
167 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 176 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
168 177
@@ -1131,6 +1140,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1131 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); 1140 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1132 } 1141 }
1133 1142
1143 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1144 {
1145 Hashtable reply = new Hashtable();
1146 int statuscode = 500;
1147 reply["str_response_string"] = "";
1148 reply["int_response_code"] = statuscode;
1149 reply["content_type"] = "text/plain";
1150 return reply;
1151 }
1152
1134 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1153 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1135 { 1154 {
1136 m_log.Debug("[WORLD MAP]: Sending map image jpeg"); 1155 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 8028d87..eba881f 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -236,15 +236,17 @@ namespace OpenSim.Region.Framework.Interfaces
236 List<TaskInventoryItem> GetInventoryItems(InventoryType type); 236 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
237 237
238 /// <summary> 238 /// <summary>
239 /// Get the scene object referenced by an inventory item. 239 /// Get the scene object(s) referenced by an inventory item.
240 /// </summary> 240 /// </summary>
241 /// 241 ///
242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have 242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
243 /// been adjusted to reflect the part and item from which it originates. 243 /// been adjusted to reflect the part and item from which it originates.
244 /// 244 ///
245 /// <param name="item"></param> 245 /// <param name="item">Inventory item</param>
246 /// <returns>The scene object. Null if the scene object asset couldn't be found</returns> 246 /// <param name="objlist">The scene objects</param>
247 SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item); 247 /// <param name="veclist">Relative offsets for each object</param>
248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index d49b24e..944c66b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
54 54
55 void setEstateTerrainBaseTexture(int level, UUID texture); 55 void setEstateTerrainBaseTexture(int level, UUID texture);
56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); 56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
57
58 /// <summary>
59 /// Returns whether the transfer ID is being used for a terrain transfer.
60 /// </summary>
61 bool IsTerrainXfer(ulong xferID);
57 } 62 }
58} 63}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 659bde9..f384462 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -31,6 +31,7 @@ using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36using log4net; 37using log4net;
@@ -2301,6 +2302,85 @@ namespace OpenSim.Region.Framework.Scenes
2301 } 2302 }
2302 2303
2303 /// <summary> 2304 /// <summary>
2305 /// Returns the list of Scene Objects in an asset.
2306 /// </summary>
2307 /// <remarks>
2308 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2309 /// </remarks>
2310 /// <param name="assetData">Asset data</param>
2311 /// <param name="attachment">Whether the item is an attachment</param>
2312 /// <param name="objlist">The objects included in the asset</param>
2313 /// <param name="veclist">Relative positions of the objects</param>
2314 /// <param name="bbox">Bounding box of all the objects</param>
2315 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2316 /// to the centre of the root prim (relevant only when returning a single object)</param>
2317 /// <returns>true = returning a single object; false = multiple objects</returns>
2318 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2319 out Vector3 bbox, out float offsetHeight)
2320 {
2321 objlist = new List<SceneObjectGroup>();
2322 veclist = new List<Vector3>();
2323
2324 XmlDocument doc = new XmlDocument();
2325 string xmlData = Utils.BytesToString(assetData);
2326 doc.LoadXml(xmlData);
2327 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2328
2329 if (e == null || attachment) // Single
2330 {
2331 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2332
2333 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2334 g.RootPart.AttachOffset = g.AbsolutePosition;
2335 g.RootPart.AttachRotation = g.GroupRotation;
2336 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2337 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2338 g.RootPart.Shape.State = 0;
2339
2340 objlist.Add(g);
2341 veclist.Add(new Vector3(0, 0, 0));
2342 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2343 return true;
2344 }
2345 else
2346 {
2347 XmlElement coll = (XmlElement)e;
2348 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2349 float by = Convert.ToSingle(coll.GetAttribute("y"));
2350 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2351 bbox = new Vector3(bx, by, bz);
2352 offsetHeight = 0;
2353
2354 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2355 foreach (XmlNode n in groups)
2356 {
2357 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2358
2359 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2360 g.RootPart.AttachOffset = g.AbsolutePosition;
2361 g.RootPart.AttachRotation = g.GroupRotation;
2362 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2363 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2364 g.RootPart.Shape.State = 0;
2365
2366 objlist.Add(g);
2367
2368 XmlElement el = (XmlElement)n;
2369 string rawX = el.GetAttribute("offsetx");
2370 string rawY = el.GetAttribute("offsety");
2371 string rawZ = el.GetAttribute("offsetz");
2372
2373 float x = Convert.ToSingle(rawX);
2374 float y = Convert.ToSingle(rawY);
2375 float z = Convert.ToSingle(rawZ);
2376 veclist.Add(new Vector3(x, y, z));
2377 }
2378 }
2379
2380 return false;
2381 }
2382
2383 /// <summary>
2304 /// Event Handler Rez an object into a scene 2384 /// Event Handler Rez an object into a scene
2305 /// Calls the non-void event handler 2385 /// Calls the non-void event handler
2306 /// </summary> 2386 /// </summary>
@@ -2375,19 +2455,25 @@ namespace OpenSim.Region.Framework.Scenes
2375 /// will be used if it exists.</param> 2455 /// will be used if it exists.</param>
2376 /// <param name="vel">The velocity of the rezzed object.</param> 2456 /// <param name="vel">The velocity of the rezzed object.</param>
2377 /// <param name="param"></param> 2457 /// <param name="param"></param>
2378 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2458 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2379 public virtual SceneObjectGroup RezObject( 2459 public virtual List<SceneObjectGroup> RezObject(
2380 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2460 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2381 { 2461 {
2382 if (null == item) 2462 if (null == item)
2383 return null; 2463 return null;
2464
2465 List<SceneObjectGroup> objlist;
2466 List<Vector3> veclist;
2384 2467
2385 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2468 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2386 2469 if (!success)
2387 if (null == group)
2388 return null; 2470 return null;
2389 2471
2390 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2472 int totalPrims = 0;
2473 foreach (SceneObjectGroup group in objlist)
2474 totalPrims += group.PrimCount;
2475
2476 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2391 return null; 2477 return null;
2392 2478
2393 if (!Permissions.BypassPermissions()) 2479 if (!Permissions.BypassPermissions())
@@ -2396,23 +2482,28 @@ namespace OpenSim.Region.Framework.Scenes
2396 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2482 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2397 } 2483 }
2398 2484
2399 2485 for (int i = 0; i < objlist.Count; i++)
2400 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2401 { 2486 {
2402 group.RootPart.AttachedPos = group.AbsolutePosition; 2487 SceneObjectGroup group = objlist[i];
2403 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; 2488 Vector3 curpos = pos + veclist[i];
2489
2490 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2491 {
2492 group.RootPart.AttachedPos = group.AbsolutePosition;
2493 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2494 }
2495
2496 group.FromPartID = sourcePart.UUID;
2497 AddNewSceneObject(group, true, curpos, rot, vel);
2498
2499 // We can only call this after adding the scene object, since the scene object references the scene
2500 // to find out if scripts should be activated at all.
2501 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2502
2503 group.ScheduleGroupForFullUpdate();
2404 } 2504 }
2405 2505
2406 group.FromPartID = sourcePart.UUID; 2506 return objlist;
2407 AddNewSceneObject(group, true, pos, rot, vel);
2408
2409 // We can only call this after adding the scene object, since the scene object references the scene
2410 // to find out if scripts should be activated at all.
2411 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2412
2413 group.ScheduleGroupForFullUpdate();
2414
2415 return group;
2416 } 2507 }
2417 2508
2418 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2509 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 421cb08..46b2d2e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
252 if (part.ParentGroup.RootPart.LocalId != part.LocalId) 252 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
253 return; 253 return;
254 254
255 bool isAttachment = false;
256
257 // This is wrong, wrong, wrong. Selection should not be 255 // This is wrong, wrong, wrong. Selection should not be
258 // handled by group, but by prim. Legacy cruft. 256 // handled by group, but by prim. Legacy cruft.
259 // TODO: Make selection flagging per prim! 257 // TODO: Make selection flagging per prim!
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes
262 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) 260 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
263 part.ParentGroup.IsSelected = false; 261 part.ParentGroup.IsSelected = false;
264 262
265 if (part.ParentGroup.IsAttachment) 263 part.ParentGroup.ScheduleGroupForFullUpdate();
266 isAttachment = true;
267 else
268 part.ParentGroup.ScheduleGroupForFullUpdate();
269 264
270 // If it's not an attachment, and we are allowed to move it, 265 // If it's not an attachment, and we are allowed to move it,
271 // then we might have done so. If we moved across a parcel 266 // then we might have done so. If we moved across a parcel
272 // boundary, we will need to recount prims on the parcels. 267 // boundary, we will need to recount prims on the parcels.
273 // For attachments, that makes no sense. 268 // For attachments, that makes no sense.
274 // 269 //
275 if (!isAttachment) 270 if (!part.ParentGroup.IsAttachment)
276 { 271 {
277 if (Permissions.CanEditObject( 272 if (Permissions.CanEditObject(
278 part.UUID, remoteClient.AgentId) 273 part.UUID, remoteClient.AgentId)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 66b42a1..f5cb84b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -3158,7 +3158,8 @@ namespace OpenSim.Region.Framework.Scenes
3158 return; 3158 return;
3159 3159
3160 // This was pulled from SceneViewer. Attachments always receive full updates. 3160 // This was pulled from SceneViewer. Attachments always receive full updates.
3161 // I could not verify if this is a requirement but this maintains existing behavior 3161 // This is needed because otherwise if only the root prim changes position, then
3162 // it looks as if the entire object has moved (including the other prims).
3162 if (ParentGroup.IsAttachment) 3163 if (ParentGroup.IsAttachment)
3163 { 3164 {
3164 ScheduleFullUpdate(); 3165 ScheduleFullUpdate();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3be0623..b4fc472 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -881,8 +881,8 @@ namespace OpenSim.Region.Framework.Scenes
881 881
882 return items; 882 return items;
883 } 883 }
884 884
885 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) 885 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
886 { 886 {
887 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 887 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
888 888
@@ -891,70 +891,79 @@ namespace OpenSim.Region.Framework.Scenes
891 m_log.WarnFormat( 891 m_log.WarnFormat(
892 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 892 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
893 item.AssetID, item.Name, m_part.Name); 893 item.AssetID, item.Name, m_part.Name);
894 return null; 894 objlist = null;
895 veclist = null;
896 return false;
895 } 897 }
896 898
897 string xmlData = Utils.BytesToString(rezAsset.Data); 899 Vector3 bbox;
898 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 900 float offsetHeight;
899 901
900 group.RootPart.AttachPoint = group.RootPart.Shape.State; 902 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
901 group.RootPart.AttachOffset = group.AbsolutePosition;
902 group.RootPart.AttachRotation = group.GroupRotation;
903 903
904 group.ResetIDs(); 904 for (int i = 0; i < objlist.Count; i++)
905 {
906 SceneObjectGroup group = objlist[i];
905 907
906 SceneObjectPart rootPart = group.GetPart(group.UUID); 908 group.RootPart.AttachPoint = group.RootPart.Shape.State;
909 group.RootPart.AttachOffset = group.AbsolutePosition;
910 group.RootPart.AttachRotation = group.GroupRotation;
907 911
908 // Since renaming the item in the inventory does not affect the name stored 912 group.ResetIDs();
909 // in the serialization, transfer the correct name from the inventory to the
910 // object itself before we rez.
911 rootPart.Name = item.Name;
912 rootPart.Description = item.Description;
913 913
914 SceneObjectPart[] partList = group.Parts; 914 SceneObjectPart rootPart = group.GetPart(group.UUID);
915 915
916 group.SetGroup(m_part.GroupID, null); 916 // Since renaming the item in the inventory does not affect the name stored
917 // in the serialization, transfer the correct name from the inventory to the
918 // object itself before we rez.
919 rootPart.Name = item.Name;
920 rootPart.Description = item.Description;
917 921
918 // TODO: Remove magic number badness 922 SceneObjectPart[] partList = group.Parts;
919 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 923
920 { 924 group.SetGroup(m_part.GroupID, null);
921 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) 925
926 // TODO: Remove magic number badness
927 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
922 { 928 {
923 foreach (SceneObjectPart part in partList) 929 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
924 { 930 {
925 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 931 foreach (SceneObjectPart part in partList)
926 part.EveryoneMask = item.EveryonePermissions; 932 {
927 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0) 933 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
928 part.NextOwnerMask = item.NextPermissions; 934 part.EveryoneMask = item.EveryonePermissions;
929 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0) 935 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
930 part.GroupMask = item.GroupPermissions; 936 part.NextOwnerMask = item.NextPermissions;
937 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
938 part.GroupMask = item.GroupPermissions;
939 }
940
941 group.ApplyNextOwnerPermissions();
931 } 942 }
932
933 group.ApplyNextOwnerPermissions();
934 } 943 }
935 }
936 944
937 foreach (SceneObjectPart part in partList) 945 foreach (SceneObjectPart part in partList)
938 {
939 // TODO: Remove magic number badness
940 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
941 { 946 {
942 part.LastOwnerID = part.OwnerID; 947 // TODO: Remove magic number badness
943 part.OwnerID = item.OwnerID; 948 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
944 part.Inventory.ChangeInventoryOwner(item.OwnerID); 949 {
950 part.LastOwnerID = part.OwnerID;
951 part.OwnerID = item.OwnerID;
952 part.Inventory.ChangeInventoryOwner(item.OwnerID);
953 }
954
955 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
956 part.EveryoneMask = item.EveryonePermissions;
957 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
958 part.NextOwnerMask = item.NextPermissions;
959 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
960 part.GroupMask = item.GroupPermissions;
945 } 961 }
946 962
947 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 963 rootPart.TrimPermissions();
948 part.EveryoneMask = item.EveryonePermissions;
949 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
950 part.NextOwnerMask = item.NextPermissions;
951 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
952 part.GroupMask = item.GroupPermissions;
953 } 964 }
954 965
955 rootPart.TrimPermissions(); 966 return true;
956
957 return group;
958 } 967 }
959 968
960 /// <summary> 969 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 8a734e1..d2a6828 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -39,6 +39,7 @@ using OpenSim.Framework.Communications;
39using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using System.Text;
42using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; 43using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
43 44
44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 45namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
@@ -421,44 +422,75 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
421 string Subject = im.message.Substring(0, im.message.IndexOf('|')); 422 string Subject = im.message.Substring(0, im.message.IndexOf('|'));
422 string Message = im.message.Substring(Subject.Length + 1); 423 string Message = im.message.Substring(Subject.Length + 1);
423 424
425 InventoryItemBase item = null;
426 bool hasAttachment = false;
427 UUID itemID = UUID.Zero; //Assignment to quiet compiler
428 UUID ownerID = UUID.Zero; //Assignment to quiet compiler
424 byte[] bucket; 429 byte[] bucket;
425 430
426 if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) 431 if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
427 {
428 bucket = new byte[19];
429 bucket[0] = 0; //dunno
430 bucket[1] = 0; //dunno
431 GroupID.ToBytes(bucket, 2);
432 bucket[18] = 0; //dunno
433 }
434 else
435 { 432 {
436 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); 433 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
437 binBucket = binBucket.Remove(0, 14).Trim(); 434 binBucket = binBucket.Remove(0, 14).Trim();
438 if (m_debugEnabled) 435
436 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
437 if (binBucketOSD is OSD)
439 { 438 {
440 m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket); 439 OSDMap binBucketMap = (OSDMap)binBucketOSD;
440
441 itemID = binBucketMap["item_id"].AsUUID();
442 ownerID = binBucketMap["owner_id"].AsUUID();
441 443
442 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); 444 //Attempt to get the details of the attached item.
443 445 //If sender doesn't own the attachment, the item
444 foreach (string key in binBucketOSD.Keys) 446 //variable will be set to null and attachment will
447 //not be included with the group notice.
448 Scene scene = (Scene)remoteClient.Scene;
449 item = new InventoryItemBase(itemID, ownerID);
450 item = scene.InventoryService.GetItem(item);
451
452 if (item != null)
445 { 453 {
446 if (binBucketOSD.ContainsKey(key)) 454 //Got item details so include the attachment.
447 { 455 hasAttachment = true;
448 m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString());
449 }
450 } 456 }
451 } 457 }
452 458 else
453 // treat as if no attachment 459 {
460 m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
461 }
462 }
463
464 if (hasAttachment)
465 {
466 //Bucket contains information about attachment.
467 //
468 //Byte offset and description of bucket data:
469 //0: 1 byte indicating if attachment is present
470 //1: 1 byte indicating the type of attachment
471 //2: 16 bytes - Group UUID
472 //18: 16 bytes - UUID of the attachment owner
473 //34: 16 bytes - UUID of the attachment
474 //50: variable - Name of the attachment
475 //??: NUL byte to terminate the attachment name
476 byte[] name = Encoding.UTF8.GetBytes(item.Name);
477 bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name
478 bucket[0] = 1; //Has attachment flag
479 bucket[1] = (byte)item.InvType; //Type of Attachment
480 GroupID.ToBytes(bucket, 2);
481 ownerID.ToBytes(bucket, 18);
482 itemID.ToBytes(bucket, 34);
483 name.CopyTo(bucket, 50);
484 }
485 else
486 {
454 bucket = new byte[19]; 487 bucket = new byte[19];
455 bucket[0] = 0; //dunno 488 bucket[0] = 0; //Has attachment flag
456 bucket[1] = 0; //dunno 489 bucket[1] = 0; //Type of attachment
457 GroupID.ToBytes(bucket, 2); 490 GroupID.ToBytes(bucket, 2);
458 bucket[18] = 0; //dunno 491 bucket[18] = 0; //NUL terminate name of attachment
459 } 492 }
460 493
461
462 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); 494 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
463 if (OnNewGroupNotice != null) 495 if (OnNewGroupNotice != null)
464 { 496 {
@@ -483,7 +515,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
483 515
484 if (member.AcceptNotices) 516 if (member.AcceptNotices)
485 { 517 {
486 // Build notice IIM 518 // Build notice IM
487 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); 519 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
488 520
489 msg.toAgentID = member.AgentID.Guid; 521 msg.toAgentID = member.AgentID.Guid;
@@ -492,10 +524,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
492 } 524 }
493 } 525 }
494 } 526 }
495 527
528 if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
529 {
530 //Is bucket large enough to hold UUID of the attachment?
531 if (im.binaryBucket.Length < 16)
532 return;
533
534 UUID noticeID = new UUID(im.imSessionID);
535
536 GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID);
537 if (notice != null)
538 {
539 UUID giver = new UUID(notice.BinaryBucket, 18);
540 UUID attachmentUUID = new UUID(notice.BinaryBucket, 34);
541
542 if (m_debugEnabled)
543 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
544
545 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
546 giver, attachmentUUID);
547
548 if (itemCopy == null)
549 {
550 remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
551 return;
552 }
553
554 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
555 }
556 }
557
496 // Interop, received special 210 code for ejecting a group member 558 // Interop, received special 210 code for ejecting a group member
497 // this only works within the comms servers domain, and won't work hypergrid 559 // this only works within the comms servers domain, and won't work hypergrid
498 // TODO:FIXME: Use a presense server of some kind to find out where the 560 // TODO:FIXME: Use a presence server of some kind to find out where the
499 // client actually is, and try contacting that region directly to notify them, 561 // client actually is, and try contacting that region directly to notify them,
500 // or provide the notification via xmlrpc update queue 562 // or provide the notification via xmlrpc update queue
501 if ((im.dialog == 210)) 563 if ((im.dialog == 210))
@@ -873,26 +935,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
873 935
874 if (data != null) 936 if (data != null)
875 { 937 {
876 GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); 938 GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested);
877
878 GridInstantMessage msg = new GridInstantMessage();
879 msg.imSessionID = UUID.Zero.Guid;
880 msg.fromAgentID = data.GroupID.Guid;
881 msg.toAgentID = GetRequestingAgentID(remoteClient).Guid;
882 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
883 msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName;
884 msg.message = data.noticeData.Subject + "|" + data.Message;
885 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
886 msg.fromGroup = true;
887 msg.offline = (byte)0;
888 msg.ParentEstateID = 0;
889 msg.Position = Vector3.Zero;
890 msg.RegionID = UUID.Zero.Guid;
891 msg.binaryBucket = data.BinaryBucket;
892 939
893 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); 940 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient));
894 } 941 }
895
896 } 942 }
897 943
898 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) 944 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog)
@@ -900,10 +946,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
900 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 946 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
901 947
902 GridInstantMessage msg = new GridInstantMessage(); 948 GridInstantMessage msg = new GridInstantMessage();
903 msg.imSessionID = UUID.Zero.Guid; 949 byte[] bucket;
950
951 msg.imSessionID = groupNoticeID.Guid;
904 msg.toAgentID = agentID.Guid; 952 msg.toAgentID = agentID.Guid;
905 msg.dialog = dialog; 953 msg.dialog = dialog;
906 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
907 msg.fromGroup = true; 954 msg.fromGroup = true;
908 msg.offline = (byte)1; // Allow this message to be stored for offline use 955 msg.offline = (byte)1; // Allow this message to be stored for offline use
909 msg.ParentEstateID = 0; 956 msg.ParentEstateID = 0;
@@ -917,13 +964,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
917 msg.timestamp = info.noticeData.Timestamp; 964 msg.timestamp = info.noticeData.Timestamp;
918 msg.fromAgentName = info.noticeData.FromName; 965 msg.fromAgentName = info.noticeData.FromName;
919 msg.message = info.noticeData.Subject + "|" + info.Message; 966 msg.message = info.noticeData.Subject + "|" + info.Message;
920 msg.binaryBucket = info.BinaryBucket; 967
968 if (info.BinaryBucket[0] > 0)
969 {
970 //32 is due to not needing space for two of the UUIDs.
971 //(Don't need UUID of attachment or its owner in IM)
972 //50 offset gets us to start of attachment name.
973 //We are skipping the attachment flag, type, and
974 //the three UUID fields at the start of the bucket.
975 bucket = new byte[info.BinaryBucket.Length-32];
976 bucket[0] = 1; //Has attachment
977 bucket[1] = info.BinaryBucket[1];
978 Array.Copy(info.BinaryBucket, 50,
979 bucket, 18, info.BinaryBucket.Length-50);
980 }
981 else
982 {
983 bucket = new byte[19];
984 bucket[0] = 0; //No attachment
985 bucket[1] = 0; //Attachment type
986 bucket[18] = 0; //NUL terminate name
987 }
988
989 info.GroupID.ToBytes(bucket, 2);
990 msg.binaryBucket = bucket;
921 } 991 }
922 else 992 else
923 { 993 {
924 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); 994 if (m_debugEnabled)
995 m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID);
996
925 msg.fromAgentID = UUID.Zero.Guid; 997 msg.fromAgentID = UUID.Zero.Guid;
926 msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; 998 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
927 msg.fromAgentName = string.Empty; 999 msg.fromAgentName = string.Empty;
928 msg.message = string.Empty; 1000 msg.message = string.Empty;
929 msg.binaryBucket = new byte[0]; 1001 msg.binaryBucket = new byte[0];
@@ -1047,7 +1119,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1047 // Message to ejector 1119 // Message to ejector
1048 // Interop, received special 210 code for ejecting a group member 1120 // Interop, received special 210 code for ejecting a group member
1049 // this only works within the comms servers domain, and won't work hypergrid 1121 // this only works within the comms servers domain, and won't work hypergrid
1050 // TODO:FIXME: Use a presense server of some kind to find out where the 1122 // TODO:FIXME: Use a presence server of some kind to find out where the
1051 // client actually is, and try contacting that region directly to notify them, 1123 // client actually is, and try contacting that region directly to notify them,
1052 // or provide the notification via xmlrpc update queue 1124 // or provide the notification via xmlrpc update queue
1053 1125
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index f0d17d3..7b98f9d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -1125,7 +1125,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1125 { 1125 {
1126 // If body is already heigher, use its height as target height 1126 // If body is already heigher, use its height as target height
1127 if (VehiclePosition.Z > m_VhoverTargetHeight) 1127 if (VehiclePosition.Z > m_VhoverTargetHeight)
1128 {
1128 m_VhoverTargetHeight = VehiclePosition.Z; 1129 m_VhoverTargetHeight = VehiclePosition.Z;
1130
1131 // A 'misfeature' of this flag is that if the vehicle is above it's hover height,
1132 // the vehicle's buoyancy goes away. This is an SL bug that got used by so many
1133 // scripts that it could not be changed.
1134 // So, if above the height, reapply gravity if buoyancy had it turned off.
1135 if (m_VehicleBuoyancy != 0)
1136 {
1137 Vector3 appliedGravity = ControllingPrim.ComputeGravity(ControllingPrim.Buoyancy) * m_vehicleMass;
1138 VehicleAddForce(appliedGravity);
1139 }
1140 }
1129 } 1141 }
1130 1142
1131 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1143 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index c4807c4..c016eed 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -354,6 +354,8 @@ public sealed class BSTerrainManager : IDisposable
354 // Return a new position that is over known terrain if the position is outside our terrain. 354 // Return a new position that is over known terrain if the position is outside our terrain.
355 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) 355 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos)
356 { 356 {
357 float edgeEpsilon = 0.1f;
358
357 Vector3 ret = pPos; 359 Vector3 ret = pPos;
358 360
359 // First, base addresses are never negative so correct for that possible problem. 361 // First, base addresses are never negative so correct for that possible problem.
@@ -378,10 +380,19 @@ public sealed class BSTerrainManager : IDisposable
378 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region. 380 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region.
379 381
380 // Must be off the top of a region. Find an adjacent region to move into. 382 // Must be off the top of a region. Find an adjacent region to move into.
383 // The returned terrain is always 'lower'. That is, closer to <0,0>.
381 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); 384 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
382 385
383 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + (ret.X % DefaultRegionSize.X)); 386 if (adjacentTerrainBase.X < terrainBaseXYZ.X)
384 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y)); 387 {
388 // moving down into a new region in the X dimension. New position will be the max in the new base.
389 ret.X = adjacentTerrainBase.X + DefaultRegionSize.X - edgeEpsilon;
390 }
391 if (adjacentTerrainBase.Y < terrainBaseXYZ.Y)
392 {
393 // moving down into a new region in the X dimension. New position will be the max in the new base.
394 ret.Y = adjacentTerrainBase.Y + DefaultRegionSize.Y - edgeEpsilon;
395 }
385 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", 396 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
386 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); 397 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
387 398
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 8892b69..89f4706 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3247,46 +3247,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3247 // need the magnitude later 3247 // need the magnitude later
3248 // float velmag = (float)Util.GetMagnitude(llvel); 3248 // float velmag = (float)Util.GetMagnitude(llvel);
3249 3249
3250 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); 3250 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
3251 3251
3252 // If either of these are null, then there was an unknown error. 3252 // If either of these are null, then there was an unknown error.
3253 if (new_group == null) 3253 if (new_groups == null)
3254 return; 3254 return;
3255 3255
3256 // objects rezzed with this method are die_at_edge by default. 3256 foreach (SceneObjectGroup group in new_groups)
3257 new_group.RootPart.SetDieAtEdge(true); 3257 {
3258 3258 // objects rezzed with this method are die_at_edge by default.
3259 new_group.ResumeScripts(); 3259 group.RootPart.SetDieAtEdge(true);
3260 3260
3261 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3261 group.ResumeScripts();
3262 "object_rez", new Object[] {
3263 new LSL_String(
3264 new_group.RootPart.UUID.ToString()) },
3265 new DetectParams[0]));
3266 3262
3267 // do recoil 3263 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
3268 SceneObjectGroup hostgrp = m_host.ParentGroup; 3264 "object_rez", new Object[] {
3269 if (hostgrp == null) 3265 new LSL_String(
3270 return; 3266 group.RootPart.UUID.ToString()) },
3267 new DetectParams[0]));
3271 3268
3272 if (hostgrp.IsAttachment) // don't recoil avatars 3269 float groupmass = group.GetMass();
3273 return;
3274 3270
3275 PhysicsActor pa = new_group.RootPart.PhysActor; 3271 PhysicsActor pa = group.RootPart.PhysActor;
3276 3272
3277 //Recoil. 3273 //Recoil.
3278 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3274 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3279 {
3280 float groupmass = new_group.GetMass();
3281 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3282 if (recoil != Vector3.Zero)
3283 { 3275 {
3284 llApplyImpulse(recoil, 0); 3276 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3277 if (recoil != Vector3.Zero)
3278 {
3279 llApplyImpulse(recoil, 0);
3280 }
3285 } 3281 }
3282 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3286 } 3283 }
3287 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3288 return; 3284 return;
3289
3290 }); 3285 });
3291 3286
3292 //ScriptSleep((int)((groupmass * velmag) / 10)); 3287 //ScriptSleep((int)((groupmass * velmag) / 10));
diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
index e4a0ffa..f2a5678 100644
--- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
+++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
@@ -145,6 +145,17 @@ namespace OpenSim.Server.Handlers.Login
145 return FailedXMLRPCResponse(); 145 return FailedXMLRPCResponse();
146 146
147 } 147 }
148 public XmlRpcResponse HandleXMLRPCLoginBlocked(XmlRpcRequest request, IPEndPoint client)
149 {
150 XmlRpcResponse response = new XmlRpcResponse();
151 Hashtable resp = new Hashtable();
152
153 resp["reason"] = "presence";
154 resp["message"] = "Logins are currently restricted. Please try again later.";
155 resp["login"] = "false";
156 response.Value = resp;
157 return response;
158 }
148 159
149 public XmlRpcResponse HandleXMLRPCSetLoginLevel(XmlRpcRequest request, IPEndPoint remoteClient) 160 public XmlRpcResponse HandleXMLRPCSetLoginLevel(XmlRpcRequest request, IPEndPoint remoteClient)
150 { 161 {
diff --git a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs
index 97e8295..f60e892 100644
--- a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs
+++ b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs
@@ -44,6 +44,7 @@ namespace OpenSim.Server.Handlers.Login
44 44
45 private ILoginService m_LoginService; 45 private ILoginService m_LoginService;
46 private bool m_Proxy; 46 private bool m_Proxy;
47 private BasicDosProtectorOptions m_DosProtectionOptions;
47 48
48 public LLLoginServiceInConnector(IConfigSource config, IHttpServer server, IScene scene) : 49 public LLLoginServiceInConnector(IConfigSource config, IHttpServer server, IScene scene) :
49 base(config, server, String.Empty) 50 base(config, server, String.Empty)
@@ -88,6 +89,16 @@ namespace OpenSim.Server.Handlers.Login
88 throw new Exception(String.Format("No LocalServiceModule for LoginService in config file")); 89 throw new Exception(String.Format("No LocalServiceModule for LoginService in config file"));
89 90
90 m_Proxy = serverConfig.GetBoolean("HasProxy", false); 91 m_Proxy = serverConfig.GetBoolean("HasProxy", false);
92 m_DosProtectionOptions = new BasicDosProtectorOptions();
93 // Dos Protection Options
94 m_DosProtectionOptions.AllowXForwardedFor = serverConfig.GetBoolean("DOSAllowXForwardedForHeader", false);
95 m_DosProtectionOptions.RequestTimeSpan =
96 TimeSpan.FromMilliseconds(serverConfig.GetInt("DOSRequestTimeFrameMS", 10000));
97 m_DosProtectionOptions.MaxRequestsInTimeframe = serverConfig.GetInt("DOSMaxRequestsInTimeFrame", 5);
98 m_DosProtectionOptions.ForgetTimeSpan =
99 TimeSpan.FromMilliseconds(serverConfig.GetInt("DOSForgiveClientAfterMS", 120000));
100 m_DosProtectionOptions.ReportingName = "LOGINDOSPROTECTION";
101
91 102
92 return loginService; 103 return loginService;
93 } 104 }
@@ -95,7 +106,9 @@ namespace OpenSim.Server.Handlers.Login
95 private void InitializeHandlers(IHttpServer server) 106 private void InitializeHandlers(IHttpServer server)
96 { 107 {
97 LLLoginHandlers loginHandlers = new LLLoginHandlers(m_LoginService, m_Proxy); 108 LLLoginHandlers loginHandlers = new LLLoginHandlers(m_LoginService, m_Proxy);
98 server.AddXmlRPCHandler("login_to_simulator", loginHandlers.HandleXMLRPCLogin, false); 109 server.AddXmlRPCHandler("login_to_simulator",
110 new XmlRpcBasicDOSProtector(loginHandlers.HandleXMLRPCLogin,loginHandlers.HandleXMLRPCLoginBlocked,
111 m_DosProtectionOptions).Process, false);
99 server.AddXmlRPCHandler("set_login_level", loginHandlers.HandleXMLRPCSetLoginLevel, false); 112 server.AddXmlRPCHandler("set_login_level", loginHandlers.HandleXMLRPCSetLoginLevel, false);
100 server.SetDefaultLLSDHandler(loginHandlers.HandleLLSDLogin); 113 server.SetDefaultLLSDHandler(loginHandlers.HandleLLSDLogin);
101 server.AddWebSocketHandler("/WebSocket/GridLogin", loginHandlers.HandleWebSocketLoginEvents); 114 server.AddWebSocketHandler("/WebSocket/GridLogin", loginHandlers.HandleWebSocketLoginEvents);