aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/MySQL/MySQLGridData.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Data/MySQL/MySQLGridData.cs')
-rw-r--r--OpenSim/Data/MySQL/MySQLGridData.cs402
1 files changed, 402 insertions, 0 deletions
diff --git a/OpenSim/Data/MySQL/MySQLGridData.cs b/OpenSim/Data/MySQL/MySQLGridData.cs
new file mode 100644
index 0000000..61ab067
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLGridData.cs
@@ -0,0 +1,402 @@
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 OpenSim 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.Security.Cryptography;
32using System.Text;
33using System.Text.RegularExpressions;
34using libsecondlife;
35using OpenSim.Framework.Console;
36
37namespace OpenSim.Framework.Data.MySQL
38{
39 /// <summary>
40 /// A MySQL Interface for the Grid Server
41 /// </summary>
42 public class MySQLGridData : GridDataBase
43 {
44 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
45
46 /// <summary>
47 /// MySQL Database Manager
48 /// </summary>
49 private MySQLManager database;
50
51 /// <summary>
52 /// Initialises the Grid Interface
53 /// </summary>
54 override public void Initialise()
55 {
56 IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini");
57 string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname");
58 string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database");
59 string settingUsername = GridDataMySqlFile.ParseFileReadValue("username");
60 string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
61 string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling");
62 string settingPort = GridDataMySqlFile.ParseFileReadValue("port");
63
64 database =
65 new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling,
66 settingPort);
67
68 TestTables();
69 }
70
71 #region Test and initialization code
72
73 /// <summary>
74 /// Ensure that the user related tables exists and are at the latest version
75 /// </summary>
76 private void TestTables()
77 {
78 Dictionary<string, string> tableList = new Dictionary<string, string>();
79
80 tableList["regions"] = null;
81 database.GetTableVersion(tableList);
82
83 UpgradeRegionsTable(tableList["regions"]);
84 }
85
86 /// <summary>
87 /// Create or upgrade the table if necessary
88 /// </summary>
89 /// <param name="oldVersion">A null indicates that the table does not
90 /// currently exist</param>
91 private void UpgradeRegionsTable(string oldVersion)
92 {
93 // null as the version, indicates that the table didn't exist
94 if (oldVersion == null)
95 {
96 database.ExecuteResourceSql("CreateRegionsTable.sql");
97 return;
98 }
99 if (oldVersion.Contains("Rev. 1"))
100 {
101 database.ExecuteResourceSql("UpgradeRegionsTableToVersion2.sql");
102 return;
103 }
104 if (oldVersion.Contains("Rev. 2"))
105 {
106 database.ExecuteResourceSql("UpgradeRegionsTableToVersion3.sql");
107 return;
108 }
109 }
110
111 #endregion
112
113 /// <summary>
114 /// Shuts down the grid interface
115 /// </summary>
116 override public void Close()
117 {
118 database.Close();
119 }
120
121 /// <summary>
122 /// Returns the plugin name
123 /// </summary>
124 /// <returns>Plugin name</returns>
125 override public string getName()
126 {
127 return "MySql OpenGridData";
128 }
129
130 /// <summary>
131 /// Returns the plugin version
132 /// </summary>
133 /// <returns>Plugin version</returns>
134 override public string getVersion()
135 {
136 return "0.1";
137 }
138
139 /// <summary>
140 /// Returns all the specified region profiles within coordates -- coordinates are inclusive
141 /// </summary>
142 /// <param name="xmin">Minimum X coordinate</param>
143 /// <param name="ymin">Minimum Y coordinate</param>
144 /// <param name="xmax">Maximum X coordinate</param>
145 /// <param name="ymax">Maximum Y coordinate</param>
146 /// <returns></returns>
147 override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax)
148 {
149 try
150 {
151 lock (database)
152 {
153 Dictionary<string, string> param = new Dictionary<string, string>();
154 param["?xmin"] = xmin.ToString();
155 param["?ymin"] = ymin.ToString();
156 param["?xmax"] = xmax.ToString();
157 param["?ymax"] = ymax.ToString();
158
159 IDbCommand result =
160 database.Query(
161 "SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax",
162 param);
163 IDataReader reader = result.ExecuteReader();
164
165 RegionProfileData row;
166
167 List<RegionProfileData> rows = new List<RegionProfileData>();
168
169 while ((row = database.readSimRow(reader)) != null)
170 {
171 rows.Add(row);
172 }
173 reader.Close();
174 result.Dispose();
175
176 return rows.ToArray();
177 }
178 }
179 catch (Exception e)
180 {
181 database.Reconnect();
182 m_log.Error(e.ToString());
183 return null;
184 }
185 }
186
187 /// <summary>
188 /// Returns a sim profile from it's location
189 /// </summary>
190 /// <param name="handle">Region location handle</param>
191 /// <returns>Sim profile</returns>
192 override public RegionProfileData GetProfileByHandle(ulong handle)
193 {
194 try
195 {
196 lock (database)
197 {
198 Dictionary<string, string> param = new Dictionary<string, string>();
199 param["?handle"] = handle.ToString();
200
201 IDbCommand result = database.Query("SELECT * FROM regions WHERE regionHandle = ?handle", param);
202 IDataReader reader = result.ExecuteReader();
203
204 RegionProfileData row = database.readSimRow(reader);
205 reader.Close();
206 result.Dispose();
207
208 return row;
209 }
210 }
211 catch (Exception e)
212 {
213 database.Reconnect();
214 m_log.Error(e.ToString());
215 return null;
216 }
217 }
218
219 /// <summary>
220 /// Returns a sim profile from it's UUID
221 /// </summary>
222 /// <param name="uuid">The region UUID</param>
223 /// <returns>The sim profile</returns>
224 override public RegionProfileData GetProfileByLLUUID(LLUUID uuid)
225 {
226 try
227 {
228 lock (database)
229 {
230 Dictionary<string, string> param = new Dictionary<string, string>();
231 param["?uuid"] = uuid.ToString();
232
233 IDbCommand result = database.Query("SELECT * FROM regions WHERE uuid = ?uuid", param);
234 IDataReader reader = result.ExecuteReader();
235
236 RegionProfileData row = database.readSimRow(reader);
237 reader.Close();
238 result.Dispose();
239
240 return row;
241 }
242 }
243 catch (Exception e)
244 {
245 database.Reconnect();
246 m_log.Error(e.ToString());
247 return null;
248 }
249 }
250
251 /// <summary>
252 /// Returns a sim profile from it's Region name string
253 /// </summary>
254 /// <param name="uuid">The region name search query</param>
255 /// <returns>The sim profile</returns>
256 override public RegionProfileData GetProfileByString(string regionName)
257 {
258 if (regionName.Length > 2)
259 {
260 try
261 {
262 lock (database)
263 {
264 Dictionary<string, string> param = new Dictionary<string, string>();
265 // Add % because this is a like query.
266 param["?regionName"] = regionName + "%";
267 // Order by statement will return shorter matches first. Only returns one record or no record.
268 IDbCommand result = database.Query("SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1", param);
269 IDataReader reader = result.ExecuteReader();
270
271 RegionProfileData row = database.readSimRow(reader);
272 reader.Close();
273 result.Dispose();
274
275 return row;
276 }
277 }
278 catch (Exception e)
279 {
280 database.Reconnect();
281 m_log.Error(e.ToString());
282 return null;
283 }
284 }
285 else
286 {
287 m_log.Error("[DATABASE]: Searched for a Region Name shorter then 3 characters");
288 return null;
289 }
290 }
291
292 /// <summary>
293 /// Adds a new profile to the database
294 /// </summary>
295 /// <param name="profile">The profile to add</param>
296 /// <returns>Successful?</returns>
297 override public DataResponse AddProfile(RegionProfileData profile)
298 {
299 lock (database)
300 {
301 if (database.insertRegion(profile))
302 {
303 return DataResponse.RESPONSE_OK;
304 }
305 else
306 {
307 return DataResponse.RESPONSE_ERROR;
308 }
309 }
310 }
311
312 /// <summary>
313 /// Deletes a profile from the database
314 /// </summary>
315 /// <param name="profile">The profile to delete</param>
316 /// <returns>Successful?</returns>
317 //public DataResponse DeleteProfile(RegionProfileData profile)
318 public DataResponse DeleteProfile(string uuid)
319 {
320 lock (database)
321 {
322 if (database.deleteRegion(uuid))
323 {
324 return DataResponse.RESPONSE_OK;
325 }
326 else
327 {
328 return DataResponse.RESPONSE_ERROR;
329 }
330 }
331 }
332
333 /// <summary>
334 /// DEPRECATED. Attempts to authenticate a region by comparing a shared secret.
335 /// </summary>
336 /// <param name="uuid">The UUID of the challenger</param>
337 /// <param name="handle">The attempted regionHandle of the challenger</param>
338 /// <param name="authkey">The secret</param>
339 /// <returns>Whether the secret and regionhandle match the database entry for UUID</returns>
340 override public bool AuthenticateSim(LLUUID uuid, ulong handle, string authkey)
341 {
342 bool throwHissyFit = false; // Should be true by 1.0
343
344 if (throwHissyFit)
345 throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential.");
346
347 RegionProfileData data = GetProfileByLLUUID(uuid);
348
349 return (handle == data.regionHandle && authkey == data.regionSecret);
350 }
351
352 /// <summary>
353 /// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region
354 /// </summary>
355 /// <remarks>This requires a security audit.</remarks>
356 /// <param name="uuid"></param>
357 /// <param name="handle"></param>
358 /// <param name="authhash"></param>
359 /// <param name="challenge"></param>
360 /// <returns></returns>
361 public bool AuthenticateSim(LLUUID uuid, ulong handle, string authhash, string challenge)
362 {
363 SHA512Managed HashProvider = new SHA512Managed();
364 ASCIIEncoding TextProvider = new ASCIIEncoding();
365
366 byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge);
367 byte[] hash = HashProvider.ComputeHash(stream);
368
369 return false;
370 }
371
372 override public ReservationData GetReservationAtPoint(uint x, uint y)
373 {
374 try
375 {
376 lock (database)
377 {
378 Dictionary<string, string> param = new Dictionary<string, string>();
379 param["?x"] = x.ToString();
380 param["?y"] = y.ToString();
381 IDbCommand result =
382 database.Query(
383 "SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
384 param);
385 IDataReader reader = result.ExecuteReader();
386
387 ReservationData row = database.readReservationRow(reader);
388 reader.Close();
389 result.Dispose();
390
391 return row;
392 }
393 }
394 catch (Exception e)
395 {
396 database.Reconnect();
397 m_log.Error(e.ToString());
398 return null;
399 }
400 }
401 }
402}