From c52c68f314c67c76c7181a6d0828f476290fbd66 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Wed, 2 Apr 2008 15:24:31 +0000 Subject: whole lot more moving --- OpenSim/Data/MySQL/MySQLGridData.cs | 402 ++++++++++++++++++++++++++++++++++++ 1 file changed, 402 insertions(+) create mode 100644 OpenSim/Data/MySQL/MySQLGridData.cs (limited to 'OpenSim/Data/MySQL/MySQLGridData.cs') 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 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using libsecondlife; +using OpenSim.Framework.Console; + +namespace OpenSim.Framework.Data.MySQL +{ + /// + /// A MySQL Interface for the Grid Server + /// + public class MySQLGridData : GridDataBase + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// MySQL Database Manager + /// + private MySQLManager database; + + /// + /// Initialises the Grid Interface + /// + override public void Initialise() + { + IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini"); + string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname"); + string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database"); + string settingUsername = GridDataMySqlFile.ParseFileReadValue("username"); + string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); + string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling"); + string settingPort = GridDataMySqlFile.ParseFileReadValue("port"); + + database = + new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling, + settingPort); + + TestTables(); + } + + #region Test and initialization code + + /// + /// Ensure that the user related tables exists and are at the latest version + /// + private void TestTables() + { + Dictionary tableList = new Dictionary(); + + tableList["regions"] = null; + database.GetTableVersion(tableList); + + UpgradeRegionsTable(tableList["regions"]); + } + + /// + /// Create or upgrade the table if necessary + /// + /// A null indicates that the table does not + /// currently exist + private void UpgradeRegionsTable(string oldVersion) + { + // null as the version, indicates that the table didn't exist + if (oldVersion == null) + { + database.ExecuteResourceSql("CreateRegionsTable.sql"); + return; + } + if (oldVersion.Contains("Rev. 1")) + { + database.ExecuteResourceSql("UpgradeRegionsTableToVersion2.sql"); + return; + } + if (oldVersion.Contains("Rev. 2")) + { + database.ExecuteResourceSql("UpgradeRegionsTableToVersion3.sql"); + return; + } + } + + #endregion + + /// + /// Shuts down the grid interface + /// + override public void Close() + { + database.Close(); + } + + /// + /// Returns the plugin name + /// + /// Plugin name + override public string getName() + { + return "MySql OpenGridData"; + } + + /// + /// Returns the plugin version + /// + /// Plugin version + override public string getVersion() + { + return "0.1"; + } + + /// + /// Returns all the specified region profiles within coordates -- coordinates are inclusive + /// + /// Minimum X coordinate + /// Minimum Y coordinate + /// Maximum X coordinate + /// Maximum Y coordinate + /// + override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?xmin"] = xmin.ToString(); + param["?ymin"] = ymin.ToString(); + param["?xmax"] = xmax.ToString(); + param["?ymax"] = ymax.ToString(); + + IDbCommand result = + database.Query( + "SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax", + param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row; + + List rows = new List(); + + while ((row = database.readSimRow(reader)) != null) + { + rows.Add(row); + } + reader.Close(); + result.Dispose(); + + return rows.ToArray(); + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a sim profile from it's location + /// + /// Region location handle + /// Sim profile + override public RegionProfileData GetProfileByHandle(ulong handle) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?handle"] = handle.ToString(); + + IDbCommand result = database.Query("SELECT * FROM regions WHERE regionHandle = ?handle", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.readSimRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a sim profile from it's UUID + /// + /// The region UUID + /// The sim profile + override public RegionProfileData GetProfileByLLUUID(LLUUID uuid) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?uuid"] = uuid.ToString(); + + IDbCommand result = database.Query("SELECT * FROM regions WHERE uuid = ?uuid", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.readSimRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + + /// + /// Returns a sim profile from it's Region name string + /// + /// The region name search query + /// The sim profile + override public RegionProfileData GetProfileByString(string regionName) + { + if (regionName.Length > 2) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + // Add % because this is a like query. + param["?regionName"] = regionName + "%"; + // Order by statement will return shorter matches first. Only returns one record or no record. + IDbCommand result = database.Query("SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1", param); + IDataReader reader = result.ExecuteReader(); + + RegionProfileData row = database.readSimRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + else + { + m_log.Error("[DATABASE]: Searched for a Region Name shorter then 3 characters"); + return null; + } + } + + /// + /// Adds a new profile to the database + /// + /// The profile to add + /// Successful? + override public DataResponse AddProfile(RegionProfileData profile) + { + lock (database) + { + if (database.insertRegion(profile)) + { + return DataResponse.RESPONSE_OK; + } + else + { + return DataResponse.RESPONSE_ERROR; + } + } + } + + /// + /// Deletes a profile from the database + /// + /// The profile to delete + /// Successful? + //public DataResponse DeleteProfile(RegionProfileData profile) + public DataResponse DeleteProfile(string uuid) + { + lock (database) + { + if (database.deleteRegion(uuid)) + { + return DataResponse.RESPONSE_OK; + } + else + { + return DataResponse.RESPONSE_ERROR; + } + } + } + + /// + /// DEPRECATED. Attempts to authenticate a region by comparing a shared secret. + /// + /// The UUID of the challenger + /// The attempted regionHandle of the challenger + /// The secret + /// Whether the secret and regionhandle match the database entry for UUID + override public bool AuthenticateSim(LLUUID uuid, ulong handle, string authkey) + { + bool throwHissyFit = false; // Should be true by 1.0 + + if (throwHissyFit) + throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential."); + + RegionProfileData data = GetProfileByLLUUID(uuid); + + return (handle == data.regionHandle && authkey == data.regionSecret); + } + + /// + /// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region + /// + /// This requires a security audit. + /// + /// + /// + /// + /// + public bool AuthenticateSim(LLUUID uuid, ulong handle, string authhash, string challenge) + { + SHA512Managed HashProvider = new SHA512Managed(); + ASCIIEncoding TextProvider = new ASCIIEncoding(); + + byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge); + byte[] hash = HashProvider.ComputeHash(stream); + + return false; + } + + override public ReservationData GetReservationAtPoint(uint x, uint y) + { + try + { + lock (database) + { + Dictionary param = new Dictionary(); + param["?x"] = x.ToString(); + param["?y"] = y.ToString(); + IDbCommand result = + database.Query( + "SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y", + param); + IDataReader reader = result.ExecuteReader(); + + ReservationData row = database.readReservationRow(reader); + reader.Close(); + result.Dispose(); + + return row; + } + } + catch (Exception e) + { + database.Reconnect(); + m_log.Error(e.ToString()); + return null; + } + } + } +} -- cgit v1.1