diff --git a/OpenSim/Data/IFriendsData.cs b/OpenSim/Data/IFriendsData.cs index 1f1a0316f6..3fdf87b51a 100644 --- a/OpenSim/Data/IFriendsData.cs +++ b/OpenSim/Data/IFriendsData.cs @@ -34,7 +34,7 @@ namespace OpenSim.Data { public class FriendsData { - public UUID PrincipalID; + public string PrincipalID; public string Friend; public Dictionary Data; } @@ -46,6 +46,8 @@ namespace OpenSim.Data { bool Store(FriendsData data); bool Delete(UUID ownerID, string friend); + bool Delete(string ownerID, string friend); FriendsData[] GetFriends(UUID principalID); + FriendsData[] GetFriends(string principalID); } } diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index d85a7efb8f..85a5c08d37 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -74,9 +74,38 @@ namespace OpenSim.Data bool StoreFolder(XInventoryFolder folder); bool StoreItem(XInventoryItem item); + /// + /// Delete folders where field == val + /// + /// + /// + /// true if the delete was successful, false if it was not bool DeleteFolders(string field, string val); + + /// + /// Delete folders where field1 == val1, field2 == val2... + /// + /// + /// + /// true if the delete was successful, false if it was not + bool DeleteFolders(string[] fields, string[] vals); + + /// + /// Delete items where field == val + /// + /// + /// + /// true if the delete was successful, false if it was not bool DeleteItems(string field, string val); + /// + /// Delete items where field1 == val1, field2 == val2... + /// + /// + /// + /// true if the delete was successful, false if it was not + bool DeleteItems(string[] fields, string[] vals); + bool MoveItem(string id, string newParent); XInventoryItem[] GetActiveGestures(UUID principalID); int GetAssetPermissions(UUID principalID, UUID assetID); diff --git a/OpenSim/Data/MSSQL/MSSQLEstateData.cs b/OpenSim/Data/MSSQL/MSSQLEstateData.cs index d10ebe4f48..9c54e77a23 100644 --- a/OpenSim/Data/MSSQL/MSSQLEstateData.cs +++ b/OpenSim/Data/MSSQL/MSSQLEstateData.cs @@ -41,7 +41,7 @@ namespace OpenSim.Data.MSSQL { private const string _migrationStore = "EstateStore"; - private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private MSSQLManager _Database; private string m_connectionString; @@ -72,7 +72,12 @@ namespace OpenSim.Data.MSSQL } //Migration settings - _Database.CheckMigration(_migrationStore); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + Migration m = new Migration(conn, GetType().Assembly, "EstateStore"); + m.Update(); + } //Interesting way to get parameters! Maybe implement that also with other types Type t = typeof(EstateSettings); @@ -112,19 +117,19 @@ namespace OpenSim.Data.MSSQL { FieldInfo f = _FieldMap[name]; object v = reader[name]; - if (f.FieldType == typeof(bool) ) + if (f.FieldType == typeof(bool)) { f.SetValue(es, Convert.ToInt32(v) != 0); } - else if (f.FieldType == typeof(UUID) ) + else if (f.FieldType == typeof(UUID)) { f.SetValue(es, new UUID((Guid)v)); // uuid); } - else if (f.FieldType == typeof(string)) + else if (f.FieldType == typeof(string)) { f.SetValue(es, v.ToString()); } - else if (f.FieldType == typeof(UInt32)) + else if (f.FieldType == typeof(UInt32)) { f.SetValue(es, Convert.ToUInt32(v)); } @@ -186,7 +191,7 @@ namespace OpenSim.Data.MSSQL } catch (Exception e) { - _Log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e); + m_log.DebugFormat("[ESTATE DB]: Error inserting regionID and EstateID in estate_map: {0}", e); } } @@ -310,12 +315,12 @@ namespace OpenSim.Data.MSSQL conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { - cmd.CommandText = "delete from estateban where EstateID = @EstateID"; + cmd.CommandText = "delete from estateban where EstateID = @EstateID"; cmd.Parameters.AddWithValue("@EstateID", (int)es.EstateID); cmd.ExecuteNonQuery(); //Insert after - cmd.CommandText = "insert into estateban (EstateID, bannedUUID) values ( @EstateID, @bannedUUID )"; + cmd.CommandText = "insert into estateban (EstateID, bannedUUID,bannedIp, bannedIpHostMask, bannedNameMask) values ( @EstateID, @bannedUUID, '','','' )"; cmd.Parameters.AddWithValue("@bannedUUID", Guid.Empty); foreach (EstateBan b in es.EstateBans) { @@ -350,43 +355,195 @@ namespace OpenSim.Data.MSSQL public EstateSettings LoadEstateSettings(int estateID) { - // TODO: Implementation! - return new EstateSettings(); + EstateSettings es = new EstateSettings(); + string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_settings where EstateID = @EstateID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateID", (int)estateID); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + foreach (string name in FieldList) + { + FieldInfo f = _FieldMap[name]; + object v = reader[name]; + if (f.FieldType == typeof(bool)) + { + f.SetValue(es, Convert.ToInt32(v) != 0); + } + else if (f.FieldType == typeof(UUID)) + { + f.SetValue(es, new UUID((Guid)v)); // uuid); + } + else if (f.FieldType == typeof(string)) + { + f.SetValue(es, v.ToString()); + } + else if (f.FieldType == typeof(UInt32)) + { + f.SetValue(es, Convert.ToUInt32(v)); + } + else if (f.FieldType == typeof(Single)) + { + f.SetValue(es, Convert.ToSingle(v)); + } + else + f.SetValue(es, v); + } + } + + } + } + } + LoadBanList(es); + + es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); + es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); + es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); + + //Set event + es.OnSave += StoreEstateSettings; + return es; + } - + public List LoadEstateSettingsAll() { - // TODO: Implementation! - return new List(); + List allEstateSettings = new List(); + + List allEstateIds = GetEstatesAll(); + + foreach (int estateId in allEstateIds) + allEstateSettings.Add(LoadEstateSettings(estateId)); + + return allEstateSettings; } public List GetEstates(string search) { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings where EstateName = @EstateName"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateName", search); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } - + public List GetEstatesAll() { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } public List GetEstatesByOwner(UUID ownerID) { - return new List(); + List result = new List(); + string sql = "select estateID from estate_settings where EstateOwner = @EstateOwner"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateOwner", ownerID); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(Convert.ToInt32(reader["EstateID"])); + } + reader.Close(); + } + } + } + + return result; } public bool LinkRegion(UUID regionID, int estateID) { - // TODO: Implementation! + string sql = "insert into estate_map values (@RegionID, @EstateID)"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + try + { + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@RegionID", regionID); + cmd.Parameters.AddWithValue("@EstateID", estateID); + + int ret = cmd.ExecuteNonQuery(); + return (ret != 0); + } + } + catch (Exception ex) + { + m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message); + } + } return false; } public List GetRegions(int estateID) { - // TODO: Implementation! - return new List(); + List result = new List(); + string sql = "select RegionID from estate_map where EstateID = @EstateID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.AddWithValue("@EstateID", estateID); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + result.Add(DBGuid.FromDB(reader["RegionID"])); + } + reader.Close(); + } + } + } + + return result; } public bool DeleteEstate(int estateID) diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs index af4fd9ba55..09dde5e182 100644 --- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs +++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs @@ -51,6 +51,11 @@ namespace OpenSim.Data.MSSQL } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) @@ -67,6 +72,11 @@ namespace OpenSim.Data.MSSQL } public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string principalID) { using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs index f5492b3050..4145d957ba 100644 --- a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -168,14 +168,13 @@ namespace OpenSim.Data.MSSQL protected T[] DoQuery(SqlCommand cmd) { + List result = new List(); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader == null) return new T[0]; - CheckColumnNames(reader); - - List result = new List(); + CheckColumnNames(reader); while (reader.Read()) { @@ -262,6 +261,15 @@ namespace OpenSim.Data.MSSQL { names.Add(fi.Name); values.Add("@" + fi.Name); + // Temporarily return more information about what field is unexpectedly null for + // http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the + // InventoryTransferModule or we may be required to substitute a DBNull here. + if (fi.GetValue(row) == null) + throw new NullReferenceException( + string.Format( + "[MSSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null", + fi.Name, row)); + if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name)) { constraints.Add(new KeyValuePair(fi.Name, fi.GetValue(row).ToString())); @@ -335,16 +343,33 @@ namespace OpenSim.Data.MSSQL } } - public virtual bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public virtual bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) { - string deleteCommand = String.Format("DELETE FROM {0} WHERE [{1}] = @{1}", m_Realm, field); - cmd.CommandText = deleteCommand; - - cmd.Parameters.Add(m_database.CreateParameter(field, val)); + for (int i = 0; i < fields.Length; i++) + { + cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i])); + terms.Add("[" + fields[i] + "] = @" + fields[i]); + } + + string where = String.Join(" AND ", terms.ToArray()); + + string query = String.Format("DELETE FROM {0} WHERE {1}", m_Realm, where); + cmd.Connection = conn; + cmd.CommandText = query; conn.Open(); if (cmd.ExecuteNonQuery() > 0) diff --git a/OpenSim/Data/MSSQL/MSSQLMigration.cs b/OpenSim/Data/MSSQL/MSSQLMigration.cs index cd395b84d1..1aa96c7ff0 100644 --- a/OpenSim/Data/MSSQL/MSSQLMigration.cs +++ b/OpenSim/Data/MSSQL/MSSQLMigration.cs @@ -29,16 +29,19 @@ using System; using System.Data; using System.Data.Common; using System.Reflection; +using System.Data.SqlClient; namespace OpenSim.Data.MSSQL { public class MSSQLMigration : Migration { - public MSSQLMigration(DbConnection conn, Assembly assem, string type) : base(conn, assem, type) + public MSSQLMigration(DbConnection conn, Assembly assem, string type) + : base(conn, assem, type) { } - public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type) : base(conn, assem, subtype, type) + public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type) + : base(conn, assem, subtype, type) { } @@ -67,5 +70,30 @@ namespace OpenSim.Data.MSSQL } return version; } + + protected override void ExecuteScript(DbConnection conn, string[] script) + { + if (!(conn is SqlConnection)) + { + base.ExecuteScript(conn, script); + return; + } + + foreach (string sql in script) + { + try + { + using (SqlCommand cmd = new SqlCommand(sql, (SqlConnection)conn)) + { + cmd.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + throw new Exception(sql); + + } + } + } } } diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs index cdf8ec09fb..3ae87c3804 100644 --- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs @@ -70,6 +70,7 @@ namespace OpenSim.Data.MSSQL string sql = "select * from ["+m_Realm+"] where regionName like @regionName"; if (scopeID != UUID.Zero) sql += " and ScopeID = @scopeID"; + sql += " order by regionName"; using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs index 8f5ee35983..8b1e046033 100644 --- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs @@ -55,6 +55,10 @@ namespace OpenSim.Data.MSSQL /// private MSSQLManager _Database; private string m_connectionString; + protected virtual Assembly Assembly + { + get { return GetType().Assembly; } + } public MSSQLSimulationData() { @@ -74,9 +78,28 @@ namespace OpenSim.Data.MSSQL m_connectionString = connectionString; _Database = new MSSQLManager(connectionString); + using (SqlConnection conn = new SqlConnection(connectionString)) + { + conn.Open(); + //New Migration settings + Migration m = new Migration(conn, Assembly, "RegionStore"); + m.Update(); - //Migration settings - _Database.CheckMigration(_migrationStore); + // Clean dropped attachments + // + try + { + using (SqlCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = "delete from prims where prims.UUID in (select UUID from primshapes where PCode = 9 and State <> 0); delete from primshapes where PCode = 9 and State <> 0"; + cmd.ExecuteNonQuery(); + } + } + catch (Exception ex) + { + _Log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message); + } + } } /// @@ -214,7 +237,7 @@ namespace OpenSim.Data.MSSQL { command.Parameters.Clear(); command.Parameters.Add(_Database.CreateParameter("@PrimID", objectPart.UUID)); - + List inventory = new List(); using (SqlDataReader reader = command.ExecuteReader()) @@ -241,6 +264,14 @@ namespace OpenSim.Data.MSSQL /// public void StoreObject(SceneObjectGroup obj, UUID regionUUID) { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length); using (SqlConnection conn = new SqlConnection(m_connectionString)) @@ -700,16 +731,470 @@ VALUES } public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); + RegionLightShareData nWP = new RegionLightShareData(); + nWP.OnSave += StoreRegionWindlightSettings; + string sql = "select * from [regionwindlight] where region_id = @regionID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@regionID", regionUUID)); + conn.Open(); + using (SqlDataReader result = cmd.ExecuteReader()) + { + if (!result.Read()) + { + //No result, so store our default windlight profile and return it + nWP.regionID = regionUUID; + StoreRegionWindlightSettings(nWP); + return nWP; + } + else + { + nWP.regionID = DBGuid.FromDB(result["region_id"]); + nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); + nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); + nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); + nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); + nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); + nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); + nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); + nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); + nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); + nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); + nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); + nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); + nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); + nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); + nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); + nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); + nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); + UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); + nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); + nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); + nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); + nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); + nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); + nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); + nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); + nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); + nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); + nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); + nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); + nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); + nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); + nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); + nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); + nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); + nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); + nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); + nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); + nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); + nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); + nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); + nWP.eastAngle = Convert.ToSingle(result["east_angle"]); + nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); + nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); + nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); + nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); + nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); + nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); + nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); + nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); + nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); + nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); + nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); + nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); + nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); + nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); + nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); + nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); + nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); + nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); + nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); + nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); + nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + nWP.valid = true; + } + } + } + return nWP; } + public void RemoveRegionWindlightSettings(UUID regionID) { + string sql = "delete from [regionwindlight] where region_id = @region_id"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + cmd.Parameters.Add(_Database.CreateParameter("@region_id", regionID)); + cmd.ExecuteNonQuery(); + } } + public void StoreRegionWindlightSettings(RegionLightShareData wl) { - //This connector doesn't support the windlight module yet + string sql = "select count (region_id) from regionwindlight where region_id = @region_id"; + bool exists = false; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("@region_id", wl.regionID)); + exists = (int)cmd.ExecuteScalar() > 0; + } + } + if (exists) + { + RemoveRegionWindlightSettings(wl.regionID); + } + + // sql insert + sql = @"INSERT INTO [regionwindlight] + ([region_id] + ,[water_color_r] + ,[water_color_g] + ,[water_color_b] + ,[water_fog_density_exponent] + ,[underwater_fog_modifier] + ,[reflection_wavelet_scale_1] + ,[reflection_wavelet_scale_2] + ,[reflection_wavelet_scale_3] + ,[fresnel_scale] + ,[fresnel_offset] + ,[refract_scale_above] + ,[refract_scale_below] + ,[blur_multiplier] + ,[big_wave_direction_x] + ,[big_wave_direction_y] + ,[little_wave_direction_x] + ,[little_wave_direction_y] + ,[normal_map_texture] + ,[horizon_r] + ,[horizon_g] + ,[horizon_b] + ,[horizon_i] + ,[haze_horizon] + ,[blue_density_r] + ,[blue_density_g] + ,[blue_density_b] + ,[blue_density_i] + ,[haze_density] + ,[density_multiplier] + ,[distance_multiplier] + ,[max_altitude] + ,[sun_moon_color_r] + ,[sun_moon_color_g] + ,[sun_moon_color_b] + ,[sun_moon_color_i] + ,[sun_moon_position] + ,[ambient_r] + ,[ambient_g] + ,[ambient_b] + ,[ambient_i] + ,[east_angle] + ,[sun_glow_focus] + ,[sun_glow_size] + ,[scene_gamma] + ,[star_brightness] + ,[cloud_color_r] + ,[cloud_color_g] + ,[cloud_color_b] + ,[cloud_color_i] + ,[cloud_x] + ,[cloud_y] + ,[cloud_density] + ,[cloud_coverage] + ,[cloud_scale] + ,[cloud_detail_x] + ,[cloud_detail_y] + ,[cloud_detail_density] + ,[cloud_scroll_x] + ,[cloud_scroll_x_lock] + ,[cloud_scroll_y] + ,[cloud_scroll_y_lock] + ,[draw_classic_clouds]) + VALUES + (@region_id + ,@water_color_r + ,@water_color_g + ,@water_color_b + ,@water_fog_density_exponent + ,@underwater_fog_modifier + ,@reflection_wavelet_scale_1 + ,@reflection_wavelet_scale_2 + ,@reflection_wavelet_scale_3 + ,@fresnel_scale + ,@fresnel_offset + ,@refract_scale_above + ,@refract_scale_below + ,@blur_multiplier + ,@big_wave_direction_x + ,@big_wave_direction_y + ,@little_wave_direction_x + ,@little_wave_direction_y + ,@normal_map_texture + ,@horizon_r + ,@horizon_g + ,@horizon_b + ,@horizon_i + ,@haze_horizon + ,@blue_density_r + ,@blue_density_g + ,@blue_density_b + ,@blue_density_i + ,@haze_density + ,@density_multiplier + ,@distance_multiplier + ,@max_altitude + ,@sun_moon_color_r + ,@sun_moon_color_g + ,@sun_moon_color_b + ,@sun_moon_color_i + ,@sun_moon_position + ,@ambient_r + ,@ambient_g + ,@ambient_b + ,@ambient_i + ,@east_angle + ,@sun_glow_focus + ,@sun_glow_size + ,@scene_gamma + ,@star_brightness + ,@cloud_color_r + ,@cloud_color_g + ,@cloud_color_b + ,@cloud_color_i + ,@cloud_x + ,@cloud_y + ,@cloud_density + ,@cloud_coverage + ,@cloud_scale + ,@cloud_detail_x + ,@cloud_detail_y + ,@cloud_detail_density + ,@cloud_scroll_x + ,@cloud_scroll_x_lock + ,@cloud_scroll_y + ,@cloud_scroll_y_lock + ,@draw_classic_clouds)"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + { + conn.Open(); + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(_Database.CreateParameter("region_id", wl.regionID)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_r", wl.waterColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_g", wl.waterColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("water_color_b", wl.waterColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("water_fog_density_exponent", wl.waterFogDensityExponent)); + cmd.Parameters.Add(_Database.CreateParameter("underwater_fog_modifier", wl.underwaterFogModifier)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y)); + cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z)); + cmd.Parameters.Add(_Database.CreateParameter("fresnel_scale", wl.fresnelScale)); + cmd.Parameters.Add(_Database.CreateParameter("fresnel_offset", wl.fresnelOffset)); + cmd.Parameters.Add(_Database.CreateParameter("refract_scale_above", wl.refractScaleAbove)); + cmd.Parameters.Add(_Database.CreateParameter("refract_scale_below", wl.refractScaleBelow)); + cmd.Parameters.Add(_Database.CreateParameter("blur_multiplier", wl.blurMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_x", wl.bigWaveDirection.X)); + cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_y", wl.bigWaveDirection.Y)); + cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_x", wl.littleWaveDirection.X)); + cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_y", wl.littleWaveDirection.Y)); + cmd.Parameters.Add(_Database.CreateParameter("normal_map_texture", wl.normalMapTexture)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_r", wl.horizon.X)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_g", wl.horizon.Y)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_b", wl.horizon.Z)); + cmd.Parameters.Add(_Database.CreateParameter("horizon_i", wl.horizon.W)); + cmd.Parameters.Add(_Database.CreateParameter("haze_horizon", wl.hazeHorizon)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_r", wl.blueDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_g", wl.blueDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_b", wl.blueDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("blue_density_i", wl.blueDensity.W)); + cmd.Parameters.Add(_Database.CreateParameter("haze_density", wl.hazeDensity)); + cmd.Parameters.Add(_Database.CreateParameter("density_multiplier", wl.densityMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("distance_multiplier", wl.distanceMultiplier)); + cmd.Parameters.Add(_Database.CreateParameter("max_altitude", wl.maxAltitude)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_r", wl.sunMoonColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_g", wl.sunMoonColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_b", wl.sunMoonColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_i", wl.sunMoonColor.W)); + cmd.Parameters.Add(_Database.CreateParameter("sun_moon_position", wl.sunMoonPosition)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_r", wl.ambient.X)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_g", wl.ambient.Y)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_b", wl.ambient.Z)); + cmd.Parameters.Add(_Database.CreateParameter("ambient_i", wl.ambient.W)); + cmd.Parameters.Add(_Database.CreateParameter("east_angle", wl.eastAngle)); + cmd.Parameters.Add(_Database.CreateParameter("sun_glow_focus", wl.sunGlowFocus)); + cmd.Parameters.Add(_Database.CreateParameter("sun_glow_size", wl.sunGlowSize)); + cmd.Parameters.Add(_Database.CreateParameter("scene_gamma", wl.sceneGamma)); + cmd.Parameters.Add(_Database.CreateParameter("star_brightness", wl.starBrightness)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_r", wl.cloudColor.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_g", wl.cloudColor.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_b", wl.cloudColor.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_color_i", wl.cloudColor.W)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_x", wl.cloudXYDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_y", wl.cloudXYDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_density", wl.cloudXYDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_coverage", wl.cloudCoverage)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scale", wl.cloudScale)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_x", wl.cloudDetailXYDensity.X)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_y", wl.cloudDetailXYDensity.Y)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_density", wl.cloudDetailXYDensity.Z)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x", wl.cloudScrollX)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x_lock", wl.cloudScrollXLock)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y", wl.cloudScrollY)); + cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y_lock", wl.cloudScrollYLock)); + cmd.Parameters.Add(_Database.CreateParameter("draw_classic_clouds", wl.drawClassicClouds)); + + cmd.ExecuteNonQuery(); + } + } + #region update + // } + // else + // { + // // sql update + // sql = @"UPDATE [OpenSim].[dbo].[regionwindlight] + // SET [region_id] = @region_id + // ,[water_color_r] = @water_color_r + // ,[water_color_g] = @water_color_g + // ,[water_color_b] = @water_color_b + // ,[water_fog_density_exponent] = @water_fog_density_exponent + // ,[underwater_fog_modifier] = @underwater_fog_modifier + // ,[reflection_wavelet_scale_1] = @reflection_wavelet_scale_1 + // ,[reflection_wavelet_scale_2] = @reflection_wavelet_scale_2 + // ,[reflection_wavelet_scale_3] = @reflection_wavelet_scale_3 + // ,[fresnel_scale] = @fresnel_scale + // ,[fresnel_offset] = @fresnel_offset + // ,[refract_scale_above] = @refract_scale_above + // ,[refract_scale_below] = @refract_scale_below + // ,[blur_multiplier] = @blur_multiplier + // ,[big_wave_direction_x] = @big_wave_direction_x + // ,[big_wave_direction_y] = @big_wave_direction_y + // ,[little_wave_direction_x] = @little_wave_direction_x + // ,[little_wave_direction_y] = @little_wave_direction_y + // ,[normal_map_texture] = @normal_map_texture + // ,[horizon_r] = @horizon_r + // ,[horizon_g] = @horizon_g + // ,[horizon_b] = @horizon_b + // ,[horizon_i] = @horizon_i + // ,[haze_horizon] = @haze_horizon + // ,[blue_density_r] = @blue_density_r + // ,[blue_density_g] = @blue_density_g + // ,[blue_density_b] = @blue_density_b + // ,[blue_density_i] = @blue_density_i + // ,[haze_density] = @haze_density + // ,[density_multiplier] = @density_multiplier + // ,[distance_multiplier] = @distance_multiplier + // ,[max_altitude] = @max_altitude + // ,[sun_moon_color_r] = @sun_moon_color_r + // ,[sun_moon_color_g] = @sun_moon_color_g + // ,[sun_moon_color_b] = @sun_moon_color_b + // ,[sun_moon_color_i] = @sun_moon_color_i + // ,[sun_moon_position] = @sun_moon_position + // ,[ambient_r] = @ambient_r + // ,[ambient_g] = @ambient_g + // ,[ambient_b] = @ambient_b + // ,[ambient_i] = @ambient_i + // ,[east_angle] = @east_angle + // ,[sun_glow_focus] = @sun_glow_focus + // ,[sun_glow_size] = @sun_glow_size + // ,[scene_gamma] = @scene_gamma + // ,[star_brightness] = @star_brightness + // ,[cloud_color_r] = @cloud_color_r + // ,[cloud_color_g] = @cloud_color_g + // ,[cloud_color_b] = @cloud_color_b + // ,[cloud_color_i] = @cloud_color_i + // ,[cloud_x] = @cloud_x + // ,[cloud_y] = @cloud_y + // ,[cloud_density] = @cloud_density + // ,[cloud_coverage] = @cloud_coverage + // ,[cloud_scale] = @cloud_scale + // ,[cloud_detail_x] = @cloud_detail_x + // ,[cloud_detail_y] = @cloud_detail_y + // ,[cloud_detail_density] = @cloud_detail_density + // ,[cloud_scroll_x] = @cloud_scroll_x + // ,[cloud_scroll_x_lock] = @cloud_scroll_x_lock + // ,[cloud_scroll_y] = @cloud_scroll_y + // ,[cloud_scroll_y_lock] = @cloud_scroll_y_lock + // ,[draw_classic_clouds] = @draw_classic_clouds + // WHERE region_id = @region_id"; + // using (SqlConnection conn = new SqlConnection(m_connectionString)) + // { + // conn.Open(); + // using (SqlCommand cmd = new SqlCommand(sql, conn)) + // { + // cmd.Parameters.AddWithValue("region_id", wl.regionID); + // cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); + // cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); + // cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); + // cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); + // cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); + // cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); + // cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); + // cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); + // cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); + // cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); + // cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); + // cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); + // cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); + // cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); + // cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); + // cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); + // cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); + // cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); + // cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); + // cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); + // cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); + // cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); + // cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); + // cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); + // cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); + // cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); + // cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); + // cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); + // cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); + // cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); + // cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); + // cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); + // cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); + // cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); + // cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); + // cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); + // cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); + // cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); + // cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); + // cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); + // cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); + // cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); + // cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); + // cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); + // cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); + // cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); + // cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); + // cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); + // cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); + // cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); + // cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); + // cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); + // cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); + // cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); + // cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); + // cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); + // cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); + // cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); + // cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); + // cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); + + // cmd.ExecuteNonQuery(); + // } + // } + // } + #endregion } /// /// Loads the settings of a region. @@ -1136,7 +1621,7 @@ VALUES if (Convert.ToInt16(primRow["PassTouches"]) != 0) prim.PassTouches = true; prim.LinkNum = Convert.ToInt32(primRow["LinkNumber"]); - + if (!(primRow["MediaURL"] is System.DBNull)) prim.MediaUrl = (string)primRow["MediaURL"]; @@ -1192,11 +1677,11 @@ VALUES { } - if (!(shapeRow["Media"] is System.DBNull) ) + if (!(shapeRow["Media"] is System.DBNull)) { baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]); } - + return baseShape; } @@ -1576,15 +2061,15 @@ VALUES parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); parameters.Add(_Database.CreateParameter("State", s.State)); - if(null == s.Media ) + if (null == s.Media) { - parameters.Add(_Database.CreateParameter("Media", DBNull.Value)); + parameters.Add(_Database.CreateParameter("Media", DBNull.Value)); } else { - parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); + parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml())); } - + return parameters.ToArray(); } diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs index 5bc4fe41e5..10b0f2938f 100644 --- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs @@ -66,11 +66,18 @@ namespace OpenSim.Data.MSSQL public bool StoreFolder(XInventoryFolder folder) { + if (folder.folderName.Length > 64) + folder.folderName = folder.folderName.Substring(0, 64); return m_Folders.Store(folder); } public bool StoreItem(XInventoryItem item) { + if (item.inventoryName.Length > 64) + item.inventoryName = item.inventoryName.Substring(0, 64); + if (item.inventoryDescription.Length > 128) + item.inventoryDescription = item.inventoryDescription.Substring(0, 128); + return m_Items.Store(item); } @@ -78,12 +85,19 @@ namespace OpenSim.Data.MSSQL { return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } - + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); @@ -162,5 +176,27 @@ namespace OpenSim.Data.MSSQL } } + public override bool Store(XInventoryItem item) + { + if (!base.Store(item)) + return false; + string sql = "update inventoryfolders set version=version+1 where folderID = @folderID"; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + conn.Open(); + + cmd.Parameters.AddWithValue("@folderID", item.parentFolderID.ToString()); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + return false; + } + } + return true; + } } } diff --git a/OpenSim/Data/MSSQL/Resources/Avatar.migrations b/OpenSim/Data/MSSQL/Resources/Avatar.migrations index 5364153363..61f7b562d2 100644 --- a/OpenSim/Data/MSSQL/Resources/Avatar.migrations +++ b/OpenSim/Data/MSSQL/Resources/Avatar.migrations @@ -37,4 +37,28 @@ EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT' COMMIT +:VERSION 3 + +BEGIN TRANSACTION + +CREATE TABLE dbo.Tmp_Avatars + ( + PrincipalID uniqueidentifier NOT NULL, + [Name] varchar(32) NOT NULL, + Value text NOT NULL DEFAULT '', + PRIMARY KEY CLUSTERED +( + [PrincipalID] ASC, [Name] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + TEXTIMAGE_ON [PRIMARY] + +IF EXISTS(SELECT * FROM dbo.Avatars) + EXEC('INSERT INTO dbo.Tmp_Avatars (PrincipalID, Name, Value) + SELECT PrincipalID, CONVERT(text, Name), Value FROM dbo.Avatars WITH (HOLDLOCK TABLOCKX)') + +DROP TABLE dbo.Avatars + +EXECUTE sp_rename N'dbo.Tmp_Avatars', N'Avatars', 'OBJECT' +COMMIT diff --git a/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations b/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations index 7a7cecdb40..ecd3f4dbda 100644 --- a/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/GridUserStore.migrations @@ -17,3 +17,49 @@ CREATE TABLE "GridUser" ( ) COMMIT + +:VERSION 2 # -------------------------- + +BEGIN TRANSACTION + +CREATE TABLE [GridUser_tmp] ( + [UserID] VARCHAR(255) NOT NULL, + [HomeRegionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', + [HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [LastRegionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', + [LastPosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [LastLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', + [Online] CHAR(5) NOT NULL DEFAULT 'false', + [Login] CHAR(16) NOT NULL DEFAULT '0', + [Logout] CHAR(16) NOT NULL DEFAULT '0', + + PRIMARY KEY CLUSTERED + ( + [UserID] ASC + )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] + ) ON [PRIMARY] + +COMMIT + +IF EXISTS(SELECT * FROM dbo.GridUser) + EXEC('INSERT INTO dbo.GridUser_tmp ([UserID] + ,[HomeRegionID] + ,[HomePosition] + ,[HomeLookAt] + ,[LastRegionID] + ,[LastPosition] + ,[LastLookAt] + ,[Online] + ,[Login] + ,[Logout]) + SELECT CONVERT(varchar(36), [HomeRegionID]), [HomePosition] ,[HomeLookAt] , CONVERT(varchar(36),[LastRegionID]) + ,[LastPosition] + ,[LastLookAt] + ,[Online] + ,[Login] + ,[Logout] FROM dbo.GridUser WITH (HOLDLOCK TABLOCKX)') + +DROP TABLE dbo.GridUser + +EXECUTE sp_rename N'dbo.GridUser_tmp', N'GridUser', 'OBJECT' \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations index 340b63dec3..3995e6ce2c 100644 --- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations @@ -1003,7 +1003,7 @@ CREATE TABLE "regionwindlight" ( PRIMARY KEY ("region_id") ) -COMMIT TRANSACTION +COMMIT :VERSION 26 diff --git a/OpenSim/Data/MySQL/MySQLFriendsData.cs b/OpenSim/Data/MySQL/MySQLFriendsData.cs index 663fad6603..130ba5e9c2 100644 --- a/OpenSim/Data/MySQL/MySQLFriendsData.cs +++ b/OpenSim/Data/MySQL/MySQLFriendsData.cs @@ -43,6 +43,11 @@ namespace OpenSim.Data.MySQL } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { MySqlCommand cmd = new MySqlCommand(); @@ -64,5 +69,14 @@ namespace OpenSim.Data.MySQL return DoQuery(cmd); } + + public FriendsData[] GetFriends(string principalID) + { + MySqlCommand cmd = new MySqlCommand(); + + cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID LIKE ?PrincipalID", m_Realm); + cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString() + '%'); + return DoQuery(cmd); + } } } diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index cfffbd8739..754cf725f0 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -264,18 +264,33 @@ namespace OpenSim.Data.MySQL } } - public virtual bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public virtual bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + using (MySqlCommand cmd = new MySqlCommand()) { + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.AddWithValue(fields[i], keys[i]); + terms.Add("`" + fields[i] + "` = ?" + fields[i]); + } - cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field); - cmd.Parameters.AddWithValue(field, val); + string where = String.Join(" and ", terms.ToArray()); - if (ExecuteNonQuery(cmd) > 0) - return true; + string query = String.Format("delete from {0} where {1}", m_Realm, where); - return false; + cmd.CommandText = query; + + return ExecuteNonQuery(cmd) > 0; } } } diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index 481da493a3..caf18a4780 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -85,11 +85,21 @@ namespace OpenSim.Data.MySQL return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index ce713bdb89..7848e49955 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -21,5 +21,12 @@ INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userf COMMIT; +:VERSION 3 # ------------------------- +BEGIN; +ALTER TABLE `Friends` DROP PRIMARY KEY; +ALTER TABLE `Friends` ADD PRIMARY KEY(PrincipalID(36), Friend(36)); +ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index ba8d5388a6..987625bbf0 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -826,3 +826,19 @@ ALTER TABLE `prims` MODIFY COLUMN `CreatorID` VARCHAR(255) NOT NULL DEFAULT ''; ALTER TABLE `primitems` MODIFY COLUMN `CreatorID` VARCHAR(255) NOT NULL DEFAULT ''; COMMIT; + +:VERSION 38 #--------------------- + +BEGIN; + +alter table land ENGINE = MyISAM; +alter table landaccesslist ENGINE = MyISAM; +alter table migrations ENGINE = MyISAM; +alter table primitems ENGINE = MyISAM; +alter table prims ENGINE = MyISAM; +alter table primshapes ENGINE = MyISAM; +alter table regionban ENGINE = MyISAM; +alter table regionsettings ENGINE = MyISAM; +alter table terrain ENGINE = MyISAM; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index e7f7fd3738..d90788a111 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -42,6 +42,11 @@ namespace OpenSim.Data.Null { } + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + /// /// Tries to implement the Get [] semantics, but it cuts corners. /// Specifically, it gets all friendships even if they weren't accepted yet. @@ -49,11 +54,11 @@ namespace OpenSim.Data.Null /// /// /// - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(string userID) { List lst = m_Data.FindAll(delegate (FriendsData fdata) { - return fdata.PrincipalID == userID; + return fdata.PrincipalID == userID.ToString(); }); if (lst != null) @@ -72,9 +77,14 @@ namespace OpenSim.Data.Null return true; } - public bool Delete(UUID userID, string friendID) + public bool Delete(UUID principalID, string friend) { - List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID; }); + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string userID, string friendID) + { + List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); if (lst != null) { FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs index 4bfd228364..b14c3482bb 100644 --- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs +++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs @@ -46,7 +46,12 @@ namespace OpenSim.Data.SQLite { } - public FriendsData[] GetFriends(UUID userID) + public FriendsData[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendsData[] GetFriends(string userID) { SqliteCommand cmd = new SqliteCommand(); @@ -58,6 +63,11 @@ namespace OpenSim.Data.SQLite } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { SqliteCommand cmd = new SqliteCommand(); diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 0d7b001e3f..0d7ae1fc93 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -258,17 +258,33 @@ namespace OpenSim.Data.SQLite return false; } - public bool Delete(string field, string val) + public virtual bool Delete(string field, string key) { + return Delete(new string[] { field }, new string[] { key }); + } + + public bool Delete(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return false; + + List terms = new List(); + SqliteCommand cmd = new SqliteCommand(); - cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field); - cmd.Parameters.Add(new SqliteParameter(field, val)); + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); + terms.Add("`" + fields[i] + "` = :" + fields[i]); + } - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; + string where = String.Join(" and ", terms.ToArray()); - return false; + string query = String.Format("delete from {0} where {1}", m_Realm, where); + + cmd.CommandText = query; + + return ExecuteNonQuery(cmd, m_Connection) > 0; } } } diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index ccbd86e119..02edc30707 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -91,11 +91,21 @@ namespace OpenSim.Data.SQLite return m_Folders.Delete(field, val); } + public bool DeleteFolders(string[] fields, string[] vals) + { + return m_Folders.Delete(fields, vals); + } + public bool DeleteItems(string field, string val) { return m_Items.Delete(field, val); } + public bool DeleteItems(string[] fields, string[] vals) + { + return m_Items.Delete(fields, vals); + } + public bool MoveItem(string id, string newParent) { return m_Items.MoveItem(id, newParent); diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index dbd47d392a..125910e5bc 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -345,6 +345,7 @@ namespace OpenSim.Framework } } } + } diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs index 53d28be088..5f68cdaabf 100644 --- a/OpenSim/Framework/AssetBase.cs +++ b/OpenSim/Framework/AssetBase.cs @@ -215,6 +215,12 @@ namespace OpenSim.Framework set { m_metadata.Temporary = value; } } + public string CreatorID + { + get { return m_metadata.CreatorID; } + set { m_metadata.CreatorID = value; } + } + public AssetFlags Flags { get { return m_metadata.Flags; } diff --git a/OpenSim/Framework/AssetLandmark.cs b/OpenSim/Framework/AssetLandmark.cs index f433235ec8..103f75676c 100644 --- a/OpenSim/Framework/AssetLandmark.cs +++ b/OpenSim/Framework/AssetLandmark.cs @@ -35,6 +35,7 @@ namespace OpenSim.Framework public Vector3 Position; public ulong RegionHandle; public UUID RegionID; + public string Gatekeeper = string.Empty; public int Version; public AssetLandmark(AssetBase a) @@ -51,6 +52,8 @@ namespace OpenSim.Framework string[] parts = temp.Split('\n'); int.TryParse(parts[0].Substring(17, 1), out Version); UUID.TryParse(parts[1].Substring(10, 36), out RegionID); + if (parts.Length >= 5) + Gatekeeper = parts[4].Replace("gatekeeper ", ""); // The position is a vector with spaces as separators ("10.3 32.5 43"). // Parse each scalar separately to take into account the system's culture setting. string[] scalars = parts[2].Substring(10, parts[2].Length - 10).Split(' '); diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1568ee67f2..8fe7cdc165 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -87,7 +87,7 @@ namespace OpenSim.Framework public delegate void SameRegionTeleportlRequest(IClientAPI remoteClient, byte[] tpLocReq); public delegate void TeleportLandmarkRequest( - IClientAPI remoteClient, UUID regionID, Vector3 position); + IClientAPI remoteClient, AssetLandmark lm); public delegate void DisconnectUser(); @@ -1171,7 +1171,19 @@ namespace OpenSim.Framework void SendAgentAlertMessage(string message, bool modal); void SendLoadURL(string objectname, UUID objectID, UUID ownerID, bool groupOwned, string message, string url); - void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, + /// + /// Open a dialog box on the client. + /// + /// + /// + /// /param> + /// + /// + /// + /// + /// + /// + void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels); bool AddMoney(int debit); diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index 5a55b02f8e..0316944072 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs @@ -35,8 +35,8 @@ namespace OpenSim.Framework public interface ILandObject { - int GetParcelMaxPrimCount(ILandObject thisObject); - int GetSimulatorMaxPrimCount(ILandObject thisObject); + int GetParcelMaxPrimCount(); + int GetSimulatorMaxPrimCount(); int GetPrimsFree(); LandData LandData { get; set; } diff --git a/OpenSim/Framework/Tests/AnimationTests.cs b/OpenSim/Framework/Tests/AnimationTests.cs index 9aa95afa43..aa4c6aa1a7 100644 --- a/OpenSim/Framework/Tests/AnimationTests.cs +++ b/OpenSim/Framework/Tests/AnimationTests.cs @@ -33,7 +33,6 @@ using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using Animation = OpenSim.Framework.Animation; namespace OpenSim.Framework.Tests diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index aaa2724532..e5ff27a6d8 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1694,5 +1694,68 @@ namespace OpenSim.Framework return (T)Enum.Parse(typeof(T), value); ; } #endregion + + #region Universal User Identifiers + /// + /// + /// uuid[;endpoint[;name]] + /// + /// + /// + /// + public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) + { + uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; + + string[] parts = value.Split(';'); + if (parts.Length >= 1) + if (!UUID.TryParse(parts[0], out uuid)) + return false; + + if (parts.Length >= 2) + url = parts[1]; + + if (parts.Length >= 3) + { + string[] name = parts[2].Split(); + if (name.Length == 2) + { + firstname = name[0]; + lastname = name[1]; + } + } + if (parts.Length >= 4) + secret = parts[3]; + + return true; + } + + /// + /// + /// + /// + /// uuid[;endpoint[;name]] + public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit) + { + if (acircuit.ServiceURLs.ContainsKey("HomeURI")) + { + string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString(); + if (!agentsURI.EndsWith("/")) + agentsURI += "/"; + + // This is ugly, but there's no other way, given that the name is changed + // in the agent circuit data for foreigners + if (acircuit.lastname.Contains("@")) + { + string[] parts = acircuit.firstname.Split(new char[] { '.' }); + if (parts.Length == 2) + return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1]; + } + return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " + acircuit.lastname; + } + else + return acircuit.AgentID.ToString(); + } + #endregion } } diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 27a646aad1..147a0110c0 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -251,11 +251,11 @@ namespace OpenSim.Framework // This just dumps a warning for any operation that takes more than 100 ms int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); if (tickdiff > LongCallTime) - m_log.InfoFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", + m_log.DebugFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", reqnum,url,method,tickdiff,tickdata); } - m_log.WarnFormat("[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); + m_log.DebugFormat("[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); return ErrorResponseMap(errorMessage); } @@ -967,7 +967,7 @@ namespace OpenSim.Framework } catch (Exception e) { - m_log.WarnFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e); + m_log.DebugFormat("[SynchronousRestObjectRequester]: exception in sending data to {0}: {1}", requestUrl, e); return deserial; } finally @@ -979,8 +979,11 @@ namespace OpenSim.Framework try { - using (WebResponse resp = request.GetResponse()) + using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse()) { + if (resp.StatusCode == HttpStatusCode.NotFound) + return deserial; + if (resp.ContentLength != 0) { Stream respStream = resp.GetResponseStream(); @@ -989,18 +992,18 @@ namespace OpenSim.Framework respStream.Close(); } else - m_log.WarnFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb); + m_log.DebugFormat("[SynchronousRestObjectRequester]: Oops! no content found in response stream from {0} {1}", requestUrl, verb); } } catch (System.InvalidOperationException) { // This is what happens when there is invalid XML - m_log.WarnFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString()); + m_log.DebugFormat("[SynchronousRestObjectRequester]: Invalid XML {0} {1}", requestUrl, typeof(TResponse).ToString()); } catch (Exception e) { - m_log.WarnFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e); + m_log.DebugFormat("[SynchronousRestObjectRequester]: Exception on response from {0} {1}", requestUrl, e); } return deserial; diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 7e320e6798..3b261e77dd 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -231,6 +231,8 @@ namespace OpenSim configSource.Alias.AddAlias("Off", false); configSource.Alias.AddAlias("True", true); configSource.Alias.AddAlias("False", false); + configSource.Alias.AddAlias("Yes", true); + configSource.Alias.AddAlias("No", false); configSource.AddSwitch("Startup", "background"); configSource.AddSwitch("Startup", "inifile"); @@ -239,6 +241,8 @@ namespace OpenSim configSource.AddSwitch("Startup", "physics"); configSource.AddSwitch("Startup", "gui"); configSource.AddSwitch("Startup", "console"); + configSource.AddSwitch("Startup", "save_crashes"); + configSource.AddSwitch("Startup", "crash_dir"); configSource.AddConfig("StandAlone"); configSource.AddConfig("Network"); diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 728fa7b685..2fc3c18ab7 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -267,12 +267,13 @@ namespace OpenSim m_console.Commands.AddCommand("region", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-p|--profile=] []", + "save oar [-p|--profile=] [--noassets] []", "Save a region's data to an OAR archive.", // "-v|--version= generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine - "-p|--profile= adds the url of the profile service to the saved user information" + Environment.NewLine - + "The OAR path must be a filesystem path." - + " If this is not given then the oar is saved to region.oar in the current directory.", + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + + " The OAR path must be a filesystem path." + + " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine + + "--noassets stops assets being saved to the OAR.", SaveOar); m_console.Commands.AddCommand("region", false, "edit scale", diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 14d8543714..109dbce823 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -842,7 +842,7 @@ namespace OpenSim if (regInfo.EstateSettings.EstateID == 0) // No record at all { - MainConsole.Instance.OutputFormat("Region {0} is not part of an estate.", regInfo.RegionName); + m_log.WarnFormat("[ESTATE] Region {0} is not part of an estate.", regInfo.RegionName); List estates = EstateDataService.LoadEstateSettingsAll(); List estateNames = new List(); @@ -853,7 +853,7 @@ namespace OpenSim { if (estates.Count == 0) { - MainConsole.Instance.Output("No existing estates found. You must create a new one."); + m_log.Info("[ESTATE] No existing estates found. You must create a new one."); if (CreateEstate(regInfo, estateNames)) break; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 614fa77c0d..9bf2fceda5 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -504,6 +504,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Properties +// ~LLClientView() +// { +// m_log.DebugFormat("[LLCLIENTVIEW]: Destructor called for {0}, circuit code {1}", Name, CircuitCode); +// } + /// /// Constructor /// @@ -1545,6 +1550,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP money.MoneyData.TransactionSuccess = success; money.MoneyData.Description = description; money.MoneyData.MoneyBalance = balance; + money.TransactionInfo.ItemDescription = Util.StringToBytes256("NONE"); OutPacket(money, ThrottleOutPacketType.Task); } @@ -2289,7 +2295,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(loadURL, ThrottleOutPacketType.Task); } - public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public void SendDialog( + string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, + UUID textureID, int ch, string[] buttonlabels) { ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); dialog.Data.ObjectID = objectID; @@ -2307,6 +2315,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]); } dialog.Buttons = buttons; + + dialog.OwnerData = new ScriptDialogPacket.OwnerDataBlock[1]; + dialog.OwnerData[0] = new ScriptDialogPacket.OwnerDataBlock(); + dialog.OwnerData[0].OwnerID = ownerID; + OutPacket(dialog, ThrottleOutPacketType.Task); } @@ -2369,8 +2382,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OrbitalPosition = (OrbitalPosition - m_sunPainDaHalfOrbitalCutoff) * 0.6666666667f + m_sunPainDaHalfOrbitalCutoff; } - - SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage); viewertime.TimeInfo.SunDirection = Position; viewertime.TimeInfo.SunAngVelocity = Velocity; @@ -8403,16 +8414,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP AssetLandmark lm; if (lmid != UUID.Zero) { + //AssetBase lma = m_assetCache.GetAsset(lmid, false); AssetBase lma = m_assetService.Get(lmid.ToString()); if (lma == null) { // Failed to find landmark - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); - tpCancel.Info.SessionID = tpReq.Info.SessionID; - tpCancel.Info.AgentID = tpReq.Info.AgentID; - OutPacket(tpCancel, ThrottleOutPacketType.Task); + + // Let's try to search in the user's home asset server + lma = FindAssetInUserAssetServer(lmid.ToString()); + + if (lma == null) + { + // Really doesn't exist + TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); + tpCancel.Info.SessionID = tpReq.Info.SessionID; + tpCancel.Info.AgentID = tpReq.Info.AgentID; + OutPacket(tpCancel, ThrottleOutPacketType.Task); + } } try @@ -8443,13 +8463,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; if (handlerTeleportLandmarkRequest != null) { - handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); + handlerTeleportLandmarkRequest(this, lm); } else { //no event handler so cancel request - - TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel); tpCancel.Info.AgentID = tpReq.Info.AgentID; tpCancel.Info.SessionID = tpReq.Info.SessionID; @@ -8459,6 +8477,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + private AssetBase FindAssetInUserAssetServer(string id) + { + AgentCircuitData aCircuit = ((Scene)Scene).AuthenticateHandler.GetAgentCircuitData(CircuitCode); + if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) + { + string assetServer = aCircuit.ServiceURLs["AssetServerURI"].ToString(); + return ((Scene)Scene).AssetService.Get(assetServer + "/" + id); + } + + return null; + } + private bool HandleTeleportLocationRequest(IClientAPI sender, Packet Pack) { TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack; diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index 3c91ec956b..181d76596d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -131,7 +131,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog ScenePresence sp = m_scene.GetScenePresence(avatarID); if (sp != null) - sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); + sp.ControllingClient.SendDialog( + objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); } public void SendUrlToUser( diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 5baf0785f4..daee4ca3fc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { public class FriendsModule : ISharedRegionModule, IFriendsModule { + protected bool m_Enabled = false; + protected class UserFriendData { public UUID PrincipalID; @@ -67,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; + protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected List m_Scenes = new List(); @@ -130,7 +132,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } + #region ISharedRegionModule public void Initialise(IConfigSource config) + { + IConfig moduleConfig = config.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("FriendsModule", "FriendsModule"); + if (name == Name) + { + InitModule(config); + + m_Enabled = true; + m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name); + } + } + } + + protected void InitModule(IConfigSource config) { IConfig friendsConfig = config.Configs["Friends"]; if (friendsConfig != null) @@ -153,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue"); throw new Exception("Connector load error"); } - } public void PostInitialise() @@ -164,8 +182,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { } - public void AddRegion(Scene scene) + public virtual void AddRegion(Scene scene) { + if (!m_Enabled) + return; + m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); + m_Scenes.Add(scene); scene.RegisterModuleInterface(this); @@ -181,10 +203,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public void RemoveRegion(Scene scene) { + if (!m_Enabled) + return; + m_Scenes.Remove(scene); } - public string Name + public virtual string Name { get { return "FriendsModule"; } } @@ -194,13 +219,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends get { return null; } } - public uint GetFriendPerms(UUID principalID, UUID friendID) + #endregion + + public virtual uint GetFriendPerms(UUID principalID, UUID friendID) { FriendInfo[] friends = GetFriends(principalID); - foreach (FriendInfo fi in friends) + FriendInfo finfo = GetFriend(friends, friendID); + if (finfo != null) { - if (fi.Friend == friendID.ToString()) - return (uint)fi.TheirFlags; + return (uint)finfo.TheirFlags; } return 0; @@ -214,30 +241,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnTerminateFriendship += OnTerminateFriendship; client.OnGrantUserRights += OnGrantUserRights; - // Asynchronously fetch the friends list or increment the refcount for the existing - // friends list - Util.FireAndForget( - delegate(object o) - { - lock (m_Friends) - { - UserFriendData friendsData; - if (m_Friends.TryGetValue(client.AgentId, out friendsData)) - { - friendsData.Refcount++; - } - else - { - friendsData = new UserFriendData(); - friendsData.PrincipalID = client.AgentId; - friendsData.Friends = FriendsService.GetFriends(client.AgentId); - friendsData.Refcount = 1; + Util.FireAndForget(delegate { FetchFriendslist(client); }); + } - m_Friends[client.AgentId] = friendsData; - } - } + /// Fetch the friends list or increment the refcount for the existing + /// friends list + /// Returns true if the list was fetched, false if it wasn't + protected virtual bool FetchFriendslist(IClientAPI client) + { + UUID agentID = client.AgentId; + lock (m_Friends) + { + UserFriendData friendsData; + if (m_Friends.TryGetValue(agentID, out friendsData)) + { + friendsData.Refcount++; + return false; } - ); + else + { + friendsData = new UserFriendData(); + friendsData.PrincipalID = agentID; + friendsData.Friends = GetFriendsFromService(client); + friendsData.Refcount = 1; + + m_Friends[agentID] = friendsData; + return true; + } + } } private void OnClientClosed(UUID agentID, Scene scene) @@ -263,14 +294,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnMakeRootAgent(ScenePresence sp) { - UUID agentID = sp.ControllingClient.AgentId; - UpdateFriendsCache(agentID); + RefetchFriends(sp.ControllingClient); } private void OnClientLogin(IClientAPI client) { UUID agentID = client.AgentId; + //m_log.DebugFormat("[XXX]: OnClientLogin!"); // Inform the friends that this user is online StatusChange(agentID, true); @@ -279,7 +310,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_NeedsListOfFriends.Add(agentID); } - public void SendFriendsOnlineIfNeeded(IClientAPI client) + public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) { UUID agentID = client.AgentId; @@ -287,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends lock (m_NeedsListOfFriends) { if (!m_NeedsListOfFriends.Remove(agentID)) - return; + return false; } // Send the friends online @@ -313,10 +344,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends foreach (string fid in outstanding) { UUID fromAgentID; - if (!UUID.TryParse(fid, out fromAgentID)) + string firstname = "Unknown", lastname = "User"; + if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) + { + m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); continue; - - UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); + } PresenceInfo presence = null; PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); @@ -326,13 +359,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends im.offline = 0; im.fromAgentID = fromAgentID.Guid; - im.fromAgentName = account.FirstName + " " + account.LastName; + im.fromAgentName = firstname + " " + lastname; im.offline = (byte)((presence == null) ? 1 : 0); im.imSessionID = im.fromAgentID; + im.message = FriendshipMessage(fid); // Finally LocalFriendshipOffered(agentID, im); } + + return true; + } + + protected virtual string FriendshipMessage(string friendID) + { + return "Will you be my friend?"; + } + + protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) + { + first = "Unknown"; last = "User"; + if (!UUID.TryParse(fid, out agentID)) + return false; + + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID); + if (account != null) + { + first = account.FirstName; + last = account.LastName; + } + + return true; } List GetOnlineFriends(UUID userID) @@ -348,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } if (friendList.Count > 0) - { - PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); - foreach (PresenceInfo pi in presence) - { - UUID presenceID; - if (UUID.TryParse(pi.UserID, out presenceID)) - online.Add(presenceID); - } - } + GetOnlineFriends(userID, friendList, online); return online; } + protected virtual void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + { + PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); + foreach (PresenceInfo pi in presence) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + /// /// Find the client for a ID /// @@ -415,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends Util.FireAndForget( delegate { - foreach (FriendInfo fi in friendList) - { - //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); - // Notify about this user status - StatusNotify(fi, agentID, online); - } + m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count); + // Notify about this user status + StatusNotify(friendList, agentID, online); } ); } } - private void StatusNotify(FriendInfo friend, UUID userID, bool online) + protected virtual void StatusNotify(List friendList, UUID userID, bool online) { - UUID friendID; - if (UUID.TryParse(friend.Friend, out friendID)) + foreach (FriendInfo friend in friendList) { - // Try local - if (LocalStatusNotification(userID, friendID, online)) - return; - - // The friend is not here [as root]. Let's forward. - PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); - if (friendSessions != null && friendSessions.Length > 0) + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) { - PresenceInfo friendSession = null; - foreach (PresenceInfo pinfo in friendSessions) - if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad - { - friendSession = pinfo; - break; - } + // Try local + if (LocalStatusNotification(userID, friendID, online)) + return; - if (friendSession != null) + // The friend is not here [as root]. Let's forward. + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); - } - } + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } - // Friend is not online. Ignore. - } - else - { - m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + } + } + + // Friend is not online. Ignore. + } + else + { + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); + } } } @@ -475,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // This user wants to be friends with the other user. // Let's add the relation backwards, in case the other is not online - FriendsService.StoreFriend(friendID, principalID.ToString(), 0); + StoreBackwards(friendID, principalID); // Now let's ask the other user to be friends with this user ForwardFriendshipOffer(principalID, friendID, im); @@ -487,11 +547,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID) // We stick this agent's ID as imSession, so that it's directly available on the receiving end im.imSessionID = im.fromAgentID; + im.fromAgentName = GetFriendshipRequesterName(agentID); - // Try the local sim - UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID); - im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; - + // Try the local sim if (LocalFriendshipOffered(friendID, im)) return; @@ -509,15 +567,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // If the prospective friend is not online, he'll get the message upon login. } + protected virtual string GetFriendshipRequesterName(UUID agentID) + { + UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID); + return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; + } + private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); - - FriendsService.StoreFriend(agentID, friendID.ToString(), 1); - FriendsService.StoreFriend(friendID, agentID.ToString(), 1); + + StoreFriendships(agentID, friendID); // Update the local cache - UpdateFriendsCache(agentID); + RefetchFriends(client); // // Notify the friend @@ -548,8 +611,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); - FriendsService.Delete(agentID, friendID.ToString()); - FriendsService.Delete(friendID, agentID.ToString()); + DeleteFriendship(agentID, friendID); // // Notify the friend @@ -576,11 +638,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) { - FriendsService.Delete(agentID, exfriendID.ToString()); - FriendsService.Delete(exfriendID, agentID.ToString()); + if (!DeleteFriendship(agentID, exfriendID)) + client.SendAlertMessage("Unable to terminate friendship on this sim."); // Update local cache - UpdateFriendsCache(agentID); + RefetchFriends(client); client.SendTerminateFriend(exfriendID); @@ -606,23 +668,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) { + m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); + FriendInfo[] friends = GetFriends(remoteClient.AgentId); if (friends.Length == 0) - return; - - m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); - // Let's find the friend in this user's friend list - FriendInfo friend = null; - foreach (FriendInfo fi in friends) { - if (fi.Friend == target.ToString()) - friend = fi; + return; } + // Let's find the friend in this user's friend list + FriendInfo friend = GetFriend(friends, target); + if (friend != null) // Found it { // Store it on the DB - FriendsService.StoreFriend(requester, target.ToString(), rights); + if (!StoreRights(requester, target, rights)) + { + remoteClient.SendAlertMessage("Unable to grant rights."); + return; + } // Store it in the local cache int myFlags = friend.MyFlags; @@ -652,6 +716,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } } + else + m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); + } + + protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + { + foreach (FriendInfo fi in friends) + { + if (fi.Friend == friendID.ToString()) + return fi; + } + return null; } #region Local @@ -680,7 +756,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends friendClient.SendInstantMessage(im); // Update the local cache - UpdateFriendsCache(friendID); + RefetchFriends(friendClient); // we're done return true; @@ -713,7 +789,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // the friend in this sim as root agent friendClient.SendTerminateFriend(exfriendID); // update local cache - UpdateFriendsCache(exfriendID); + RefetchFriends(friendClient); // we're done return true; } @@ -743,15 +819,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // Update local cache - lock (m_Friends) - { - FriendInfo[] friends = GetFriends(friendID); - foreach (FriendInfo finfo in friends) - { - if (finfo.Friend == userID.ToString()) - finfo.TheirFlags = rights; - } - } + UpdateLocalCache(userID, friendID, rights); return true; } @@ -762,10 +830,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public bool LocalStatusNotification(UUID userID, UUID friendID, bool online) { + m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); IClientAPI friendClient = LocateClientObject(friendID); if (friendClient != null) { - //m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); // the friend in this sim as root agent if (online) friendClient.SendAgentOnline(new UUID[] { userID }); @@ -780,7 +848,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - private FriendInfo[] GetFriends(UUID agentID) + #region Get / Set friends in several flavours + /// + /// Get friends from local cache only + /// + /// + /// + protected FriendInfo[] GetFriends(UUID agentID) { UserFriendData friendsData; @@ -793,14 +867,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return EMPTY_FRIENDS; } - private void UpdateFriendsCache(UUID agentID) + /// + /// Update loca cache only + /// + /// + /// + /// + protected void UpdateLocalCache(UUID userID, UUID friendID, int rights) { + // Update local cache + lock (m_Friends) + { + FriendInfo[] friends = GetFriends(friendID); + FriendInfo finfo = GetFriend(friends, userID); + finfo.TheirFlags = rights; + } + } + + protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client) + { + return FriendsService.GetFriends(client.AgentId); + } + + private void RefetchFriends(IClientAPI client) + { + UUID agentID = client.AgentId; lock (m_Friends) { UserFriendData friendsData; if (m_Friends.TryGetValue(agentID, out friendsData)) - friendsData.Friends = FriendsService.GetFriends(agentID); + friendsData.Friends = GetFriendsFromService(client); } } + + protected virtual bool StoreRights(UUID agentID, UUID friendID, int rights) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights); + return true; + } + + protected virtual void StoreBackwards(UUID friendID, UUID agentID) + { + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); + } + + protected virtual void StoreFriendships(UUID agentID, UUID friendID) + { + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1); + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1); + } + + protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID) + { + FriendsService.Delete(agentID, exfriendID.ToString()); + FriendsService.Delete(exfriendID, agentID.ToString()); + return true; + } + + #endregion } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs new file mode 100644 index 0000000000..b9d67193ab --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -0,0 +1,628 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Hypergrid; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.Avatar.Friends +{ + public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + #region ISharedRegionModule + public override string Name + { + get { return "HGFriendsModule"; } + } + + public override void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + base.AddRegion(scene); + scene.RegisterModuleInterface(this); + } + + #endregion + + #region IFriendsSimConnector + + /// + /// Notify the user that the friend's status changed + /// + /// user to be notified + /// friend whose status changed + /// status + /// + public bool StatusNotify(UUID friendID, UUID userID, bool online) + { + return LocalStatusNotification(friendID, userID, online); + } + + #endregion + + protected override bool FetchFriendslist(IClientAPI client) + { + if (base.FetchFriendslist(client)) + { + UUID agentID = client.AgentId; + // we do this only for the root agent + if (m_Friends[agentID].Refcount == 1) + { + // We need to preload the user management cache with the names + // of foreign friends, just like we do with SOPs' creators + foreach (FriendInfo finfo in m_Friends[agentID].Friends) + { + if (finfo.TheirFlags != -1) + { + UUID id; + if (!UUID.TryParse(finfo.Friend, out id)) + { + string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) + { + IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); + uMan.AddUser(id, url + ";" + first + " " + last); + } + } + } + } + return true; + } + } + return false; + } + + public override bool SendFriendsOnlineIfNeeded(IClientAPI client) + { + if (base.SendFriendsOnlineIfNeeded(client)) + { + AgentCircuitData aCircuit = ((Scene)client.Scene).AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); + if (account == null) // foreign + { + FriendInfo[] friends = GetFriends(client.AgentId); + foreach (FriendInfo f in friends) + { + client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); + } + } + } + } + return false; + } + + protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + { + List fList = new List(); + foreach (string s in friendList) + fList.Add(s.Substring(0, 36)); + + PresenceInfo[] presence = PresenceService.GetAgents(fList.ToArray()); + foreach (PresenceInfo pi in presence) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + + //protected override void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) + //{ + // // Let's single out the UUIs + // List localFriends = new List(); + // List foreignFriends = new List(); + // string tmp = string.Empty; + + // foreach (string s in friendList) + // { + // UUID id; + // if (UUID.TryParse(s, out id)) + // localFriends.Add(s); + // else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp)) + // { + // foreignFriends.Add(s); + // // add it here too, who knows maybe the foreign friends happens to be on this grid + // localFriends.Add(id.ToString()); + // } + // } + + // // OK, see who's present on this grid + // List toBeRemoved = new List(); + // PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray()); + // foreach (PresenceInfo pi in presence) + // { + // UUID presenceID; + // if (UUID.TryParse(pi.UserID, out presenceID)) + // { + // online.Add(presenceID); + // foreach (string s in foreignFriends) + // if (s.StartsWith(pi.UserID)) + // toBeRemoved.Add(s); + // } + // } + + // foreach (string s in toBeRemoved) + // foreignFriends.Remove(s); + + // // OK, let's send this up the stack, and leave a closure here + // // collecting online friends in other grids + // Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); }); + + //} + + private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) + { + // let's divide the friends on a per-domain basis + Dictionary> friendsPerDomain = new Dictionary>(); + foreach (string friend in foreignFriends) + { + UUID friendID; + if (!UUID.TryParse(friend, out friendID)) + { + // it's a foreign friend + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) + { + if (!friendsPerDomain.ContainsKey(url)) + friendsPerDomain[url] = new List(); + friendsPerDomain[url].Add(friend); + } + } + } + + // Now, call those worlds + + foreach (KeyValuePair> kvp in friendsPerDomain) + { + List ids = new List(); + foreach (string f in kvp.Value) + ids.Add(f); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + List online = uConn.GetOnlineFriends(userID, ids); + // Finally send the notifications to the user + // this whole process may take a while, so let's check at every + // iteration that the user is still here + IClientAPI client = LocateClientObject(userID); + if (client != null) + client.SendAgentOnline(online.ToArray()); + else + break; + } + + } + + protected override void StatusNotify(List friendList, UUID userID, bool online) + { + // First, let's divide the friends on a per-domain basis + Dictionary> friendsPerDomain = new Dictionary>(); + foreach (FriendInfo friend in friendList) + { + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) + { + if (!friendsPerDomain.ContainsKey("local")) + friendsPerDomain["local"] = new List(); + friendsPerDomain["local"].Add(friend); + } + else + { + // it's a foreign friend + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp)) + { + // Let's try our luck in the local sim. Who knows, maybe it's here + if (LocalStatusNotification(userID, friendID, online)) + continue; + + if (!friendsPerDomain.ContainsKey(url)) + friendsPerDomain[url] = new List(); + friendsPerDomain[url].Add(friend); + } + } + } + + // For the local friends, just call the base method + // Let's do this first of all + if (friendsPerDomain.ContainsKey("local")) + base.StatusNotify(friendsPerDomain["local"], userID, online); + + foreach (KeyValuePair> kvp in friendsPerDomain) + { + if (kvp.Key != "local") + { + // For the others, call the user agent service + List ids = new List(); + foreach (FriendInfo f in kvp.Value) + ids.Add(f.Friend); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + List friendsOnline = uConn.StatusNotification(ids, userID, online); + // need to debug this here + if (online) + { + IClientAPI client = LocateClientObject(userID); + if (client != null) + client.SendAgentOnline(friendsOnline.ToArray()); + } + } + } + } + + protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) + { + first = "Unknown"; last = "User"; + if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) + return true; + + // fid is not a UUID... + string url = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp)) + { + IUserManagement userMan = m_Scenes[0].RequestModuleInterface(); + userMan.AddUser(agentID, url + ";" + first + " " + last); + + try // our best + { + string[] parts = userMan.GetUserName(agentID).Split(); + first = parts[0]; + last = parts[1]; + } + catch { } + return true; + } + return false; + } + + protected override string GetFriendshipRequesterName(UUID agentID) + { + // For the time being we assume that HG friendship requests can only happen + // when avies are on the same region. + IClientAPI client = LocateClientObject(agentID); + if (client != null) + return client.FirstName + " " + client.LastName; + else + return base.GetFriendshipRequesterName(agentID); + } + + protected override string FriendshipMessage(string friendID) + { + UUID id; + if (UUID.TryParse(friendID, out id)) + return base.FriendshipMessage(friendID); + + return "Please confirm this friendship you made while you were away."; + } + + protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) + { + foreach (FriendInfo fi in friends) + { + if (fi.Friend.StartsWith(friendID.ToString())) + return fi; + } + return null; + } + + + protected override FriendInfo[] GetFriendsFromService(IClientAPI client) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId); + if (account1 != null) + return base.GetFriendsFromService(client); + + FriendInfo[] finfos = new FriendInfo[0]; + // Foreigner + AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); + if (agentClientCircuit != null) + { + string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); + + finfos = FriendsService.GetFriends(agentUUI); + m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); + } + return finfos; + } + + protected override bool StoreRights(UUID agentID, UUID friendID, int rights) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (account1 != null && account2 != null) + { + // local grid users + return base.StoreRights(agentID, friendID, rights); + } + + if (account1 != null) // agent is local, friend is foreigner + { + FriendInfo[] finfos = GetFriends(agentID); + FriendInfo finfo = GetFriend(finfos, friendID); + if (finfo != null) + { + FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights); + return true; + } + } + + if (account2 != null) // agent is foreigner, friend is local + { + string agentUUI = GetUUI(friendID, agentID); + if (agentUUI != string.Empty) + { + FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights); + return true; + } + } + + return false; + + } + + protected override void StoreBackwards(UUID friendID, UUID agentID) + { + UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (account1 != null && account2 != null) + { + // local grid users + m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); + base.StoreBackwards(friendID, agentID); + return; + } + + // no provision for this temporary friendship state + //FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0); + } + + protected override void StoreFriendships(UUID agentID, UUID friendID) + { + UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID); + // Are they both local users? + if (agentAccount != null && friendAccount != null) + { + // local grid users + m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local"); + base.StoreFriendships(agentID, friendID); + return; + } + + // ok, at least one of them is foreigner, let's get their data + IClientAPI agentClient = LocateClientObject(agentID); + IClientAPI friendClient = LocateClientObject(friendID); + AgentCircuitData agentClientCircuit = null; + AgentCircuitData friendClientCircuit = null; + string agentUUI = string.Empty; + string friendUUI = string.Empty; + string agentFriendService = string.Empty; + string friendFriendService = string.Empty; + + if (agentClient != null) + { + agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode); + agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); + agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); + } + if (friendClient != null) + { + friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode); + friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit); + friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); + } + + m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", + agentUUI, friendUUI, agentFriendService, friendFriendService); + + // Generate a random 8-character hex number that will sign this friendship + string secret = UUID.Random().ToString().Substring(0, 8); + + if (agentAccount != null) // agent is local, 'friend' is foreigner + { + // This may happen when the agent returned home, in which case the friend is not there + // We need to look for its information in the friends list itself + bool confirming = false; + if (friendUUI == string.Empty) + { + FriendInfo[] finfos = GetFriends(agentID); + foreach (FriendInfo finfo in finfos) + { + if (finfo.TheirFlags == -1) + { + if (finfo.Friend.StartsWith(friendID.ToString())) + { + friendUUI = finfo.Friend; + confirming = true; + } + } + } + } + + // If it's confirming the friendship, we already have the full friendUUI with the secret + string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret; + + // store in the local friends service a reference to the foreign friend + FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1); + // and also the converse + FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1); + + if (!confirming && friendClientCircuit != null) + { + // store in the foreign friends service a reference to the local agent + HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(friendID, agentUUI + ";" + secret); + } + } + else if (friendAccount != null) // 'friend' is local, agent is foreigner + { + // store in the local friends service a reference to the foreign agent + FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1); + // and also the converse + FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1); + + if (agentClientCircuit != null) + { + // store in the foreign friends service a reference to the local agent + HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(agentID, friendUUI + ";" + secret); + } + } + else // They're both foreigners! + { + HGFriendsServicesConnector friendsConn; + if (agentClientCircuit != null) + { + friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(agentID, friendUUI + ";" + secret); + } + if (friendClientCircuit != null) + { + friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID); + friendsConn.NewFriendship(friendID, agentUUI + ";" + secret); + } + } + // my brain hurts now + } + + protected override bool DeleteFriendship(UUID agentID, UUID exfriendID) + { + UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID); + UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, exfriendID); + // Are they both local users? + if (agentAccount != null && friendAccount != null) + { + // local grid users + return base.DeleteFriendship(agentID, exfriendID); + } + + // ok, at least one of them is foreigner, let's get their data + string agentUUI = string.Empty; + string friendUUI = string.Empty; + + if (agentAccount != null) // agent is local, 'friend' is foreigner + { + // We need to look for its information in the friends list itself + FriendInfo[] finfos = GetFriends(agentID); + FriendInfo finfo = GetFriend(finfos, exfriendID); + if (finfo != null) + { + friendUUI = finfo.Friend; + + // delete in the local friends service the reference to the foreign friend + FriendsService.Delete(agentID, friendUUI); + // and also the converse + FriendsService.Delete(friendUUI, agentID.ToString()); + + // notify the exfriend's service + Util.FireAndForget(delegate { Delete(exfriendID, agentID, friendUUI); }); + + m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI); + return true; + } + } + else if (friendAccount != null) // agent is foreigner, 'friend' is local + { + agentUUI = GetUUI(exfriendID, agentID); + + if (agentUUI != string.Empty) + { + // delete in the local friends service the reference to the foreign agent + FriendsService.Delete(exfriendID, agentUUI); + // and also the converse + FriendsService.Delete(agentUUI, exfriendID.ToString()); + + // notify the agent's service? + Util.FireAndForget(delegate { Delete(agentID, exfriendID, agentUUI); }); + + m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID); + return true; + } + } + //else They're both foreigners! Can't handle this + + return false; + } + + private string GetUUI(UUID localUser, UUID foreignUser) + { + // Let's see if the user is here by any chance + FriendInfo[] finfos = GetFriends(localUser); + if (finfos != EMPTY_FRIENDS) // friend is here, cool + { + FriendInfo finfo = GetFriend(finfos, foreignUser); + if (finfo != null) + { + return finfo.Friend; + } + } + else // user is not currently on this sim, need to get from the service + { + finfos = FriendsService.GetFriends(localUser); + foreach (FriendInfo finfo in finfos) + { + if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it! + { + return finfo.Friend; + } + } + } + return string.Empty; + } + + private void Delete(UUID foreignUser, UUID localUser, string uui) + { + UUID id; + string url = string.Empty, secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret)) + { + m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url); + HGFriendsServicesConnector friendConn = new HGFriendsServicesConnector(url); + friendConn.DeleteFriendship(foreignUser, localUser, secret); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs new file mode 100644 index 0000000000..7753c259b3 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -0,0 +1,350 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; +using OpenSim.Services.Connectors.Hypergrid; +using OpenSim.Server.Handlers.Hypergrid; + +namespace OpenSim.Region.CoreModules.Avatar.InstantMessage +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected bool m_Enabled = false; + protected List m_Scenes = new List(); + + protected IInstantMessage m_IMService; + protected Dictionary m_UserLocationMap = new Dictionary(); + + public event UndeliveredMessage OnUndeliveredMessage; + + IUserManagement m_uMan; + IUserManagement UserManagementModule + { + get + { + if (m_uMan == null) + m_uMan = m_Scenes[0].RequestModuleInterface(); + return m_uMan; + } + } + + public virtual void Initialise(IConfigSource config) + { + IConfig cnf = config.Configs["Messaging"]; + if (cnf != null && cnf.GetString( + "MessageTransferModule", "MessageTransferModule") != Name) + { + m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration"); + return; + } + + InstantMessageServerConnector imServer = new InstantMessageServerConnector(config, MainServer.Instance, this); + m_IMService = imServer.GetService(); + m_Enabled = true; + } + + public virtual void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name); + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + } + } + + public virtual void PostInitialise() + { + if (!m_Enabled) + return; + + } + + public virtual void RegionLoaded(Scene scene) + { + } + + public virtual void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_Scenes.Remove(scene); + } + } + + public virtual void Close() + { + } + + public virtual string Name + { + get { return "HGMessageTransferModule"; } + } + + public virtual Type ReplaceableInterface + { + get { return null; } + } + + public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) + { + UUID toAgentID = new UUID(im.toAgentID); + + // Try root avatar only first + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { +// m_log.DebugFormat( +// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", +// toAgentID.ToString(), scene.RegionInfo.RegionName); + + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + if (!user.IsChildAgent) + { + // Local message +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); + user.ControllingClient.SendInstantMessage(im); + + // Message sent + result(true); + return; + } + } + } + + // try child avatar second + foreach (Scene scene in m_Scenes) + { +// m_log.DebugFormat( +// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); + + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; + +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); + user.ControllingClient.SendInstantMessage(im); + + // Message sent + result(true); + return; + } + } + +// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); + // Is the user a local user? + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); + string url = string.Empty; + bool foreigner = false; + if (account == null) // foreign user + { + url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI"); + foreigner = true; + } + + Util.FireAndForget(delegate + { + bool success = false; + if (foreigner && url == string.Empty) // we don't know about this user + { + string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI); + if (recipientUUI != string.Empty) + { + UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret)) + { + success = m_IMService.OutgoingInstantMessage(im, u, true); + if (success) + UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last); + } + } + } + else + success = m_IMService.OutgoingInstantMessage(im, url, foreigner); + + if (!success && !foreigner) + HandleUndeliveredMessage(im, result); + else + result(success); + }); + + return; + } + + protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID) + { + bool successful = false; + foreach (Scene scene in m_Scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && + scene.Entities[toAgentID] is ScenePresence) + { + ScenePresence user = + (ScenePresence)scene.Entities[toAgentID]; + + if (!user.IsChildAgent) + { + scene.EventManager.TriggerIncomingInstantMessage(gim); + successful = true; + } + } + } + if (!successful) + { + // If the message can't be delivered to an agent, it + // is likely to be a group IM. On a group IM, the + // imSessionID = toAgentID = group id. Raise the + // unhandled IM event to give the groups module + // a chance to pick it up. We raise that in a random + // scene, since the groups module is shared. + // + m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim); + } + + return successful; + } + + protected void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) + { + UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; + + // If this event has handlers, then an IM from an agent will be + // considered delivered. This will suppress the error message. + // + if (handlerUndeliveredMessage != null) + { + handlerUndeliveredMessage(im); + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + result(true); + else + result(false); + return; + } + + //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); + result(false); + } + + private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent) + { + // Let's call back the fromAgent's user agent service + // Maybe that service knows about the toAgent + IClientAPI client = LocateClientObject(fromAgent); + if (client != null) + { + AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (circuit != null) + { + if (circuit.ServiceURLs.ContainsKey("HomeURI")) + { + string uasURL = circuit.ServiceURLs["HomeURI"].ToString(); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL); + UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL); + return uasConn.GetUUI(fromAgent, toAgent); + } + } + } + + return string.Empty; + } + + + /// + /// Find the scene for an agent + /// + private Scene GetClientScene(UUID agentId) + { + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null && !presence.IsChildAgent) + return scene; + } + } + + return null; + } + + /// + /// Find the client for a ID + /// + public IClientAPI LocateClientObject(UUID agentID) + { + Scene scene = GetClientScene(agentID); + if (scene != null) + { + ScenePresence presence = scene.GetScenePresence(agentID); + if (presence != null) + return presence.ControllingClient; + } + + return null; + } + + #region IInstantMessageSimConnector + public bool SendInstantMessage(GridInstantMessage im) + { + //m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message); + UUID agentID = new UUID(im.toAgentID); + return SendIMToScene(im, agentID); + } + #endregion + + + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index 47e34dcdd6..0d90a158c3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -149,14 +149,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Find an item given a PATH_DELIMITOR delimited path starting from the user's root folder. - /// + /// + /// /// This method does not handle paths that contain multiple delimitors /// /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some /// XPath like expression /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. - /// + /// /// /// /// Inventory service to query @@ -178,32 +179,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return FindItemByPath(inventoryService, rootFolder, path); } - + /// /// Find an item given a PATH_DELIMITOR delimited path starting from this folder. - /// - /// This method does not handle paths that contain multiple delimitors + /// + /// + /// This method does not handle paths that contain multiple delimiters /// /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some /// XPath like expression /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. - /// - /// - /// - /// Inventory service to query - /// - /// - /// The folder from which the path starts - /// - /// - /// - /// The path to the required item. - /// + /// + /// + /// Inventory service to query + /// The folder from which the path starts + /// The path to the required item. /// null if the item is not found public static InventoryItemBase FindItemByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) { + List foundItems = FindItemsByPath(inventoryService, startFolder, path); + + if (foundItems.Count != 0) + return foundItems[0]; + else + return null; + } + + public static List FindItemsByPath( + IInventoryService inventoryService, UUID userId, string path) + { + InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); + + if (null == rootFolder) + return new List(); + + return FindItemsByPath(inventoryService, rootFolder, path); + } + + /// + /// Find items that match a given PATH_DELIMITOR delimited path starting from this folder. + /// + /// + /// This method does not handle paths that contain multiple delimiters + /// + /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some + /// XPath like expression + /// + /// FIXME: Delimitors which occur in names themselves are not currently escapable. + /// + /// + /// Inventory service to query + /// The folder from which the path starts + /// The path to the required item. + /// The items that were found with this path. An empty list if no items were found. + public static List FindItemsByPath( + IInventoryService inventoryService, InventoryFolderBase startFolder, string path) + { + List foundItems = new List(); + // If the path isn't just / then trim any starting extraneous slashes path = path.TrimStart(new char[] { PATH_DELIMITER }); @@ -215,11 +250,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (components.Length == 1) { // m_log.DebugFormat( -// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", +// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", // components[0], startFolder.Name, startFolder.ID); List items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); - + // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); foreach (InventoryItemBase item in items) @@ -227,24 +262,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); if (item.Name == components[0]) - return item; + foundItems.Add(item); } } else { // m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); - + InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); foreach (InventoryFolderBase folder in contents.Folders) { if (folder.Name == components[0]) - return FindItemByPath(inventoryService, folder, components[1]); + foundItems.AddRange(FindItemsByPath(inventoryService, folder, components[1])); } } - // We didn't find an item or intermediate folder with the given name - return null; + return foundItems; } /// diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index c039b5a387..c2ad079536 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -46,6 +46,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// + /// Determine whether this archive will save assets. Default is true. + /// + public bool SaveAssets { get; set; } + /// /// Used to select all inventory nodes in a folder but not the folder itself /// @@ -112,6 +117,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_invPath = invPath; m_saveStream = saveStream; m_assetGatherer = new UuidGatherer(m_scene.AssetService); + + SaveAssets = true; } protected void ReceivedAllAssets(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) @@ -150,7 +157,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); m_archiveWriter.WriteFile(filename, serialization); - m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); + AssetType itemAssetType = (AssetType)inventoryItem.AssetType; + + // Don't chase down link asset items as they actually point to their target item IDs rather than an asset + if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) + m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); } /// @@ -195,6 +206,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public void Execute(Dictionary options, IUserAccountService userAccountService) { + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + try { InventoryFolderBase inventoryFolder = null; @@ -241,10 +255,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // The path may point to an item instead if (inventoryFolder == null) - { inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); - //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); - } if (null == inventoryFolder && null == inventoryItem) { @@ -285,12 +296,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Don't put all this profile information into the archive right now. //SaveUsers(); - - new AssetsRequest( - new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, - m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, - options, ReceivedAllAssets).Execute(); + + if (SaveAssets) + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); + + new AssetsRequest( + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets).Execute(); + } + else + { + m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified"); + + ReceivedAllAssets(new List(), new List()); + } } catch (Exception) { @@ -387,19 +409,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// /// - public static string CreateControlFile(Dictionary options) + public string CreateControlFile(Dictionary options) { int majorVersion, minorVersion; if (options.ContainsKey("profile")) { majorVersion = 1; - minorVersion = 1; + minorVersion = 2; } else { majorVersion = 0; - minorVersion = 2; + minorVersion = 3; } m_log.InfoFormat("[INVENTORY ARCHIVER]: Creating version {0}.{1} IAR", majorVersion, minorVersion); @@ -411,6 +433,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver xtw.WriteStartElement("archive"); xtw.WriteAttributeString("major_version", majorVersion.ToString()); xtw.WriteAttributeString("minor_version", minorVersion.ToString()); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + xtw.WriteEndElement(); xtw.Flush(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 576a154719..e0b02aac46 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -122,7 +122,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "save iar", - "save iar [--p|-profile=] [] [--v|-verbose]", + "save iar [--p|-profile=] [--noassets] [] [--v|-verbose]", "Save user inventory archive (IAR).", " is the user's first name." + Environment.NewLine + " is the user's last name." + Environment.NewLine @@ -130,6 +130,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + "-c|--creators preserves information about foreign creators." + Environment.NewLine + "-v|--verbose extra debug messages." + Environment.NewLine + + "--noassets stops assets being saved to the IAR." + " is the filesystem path at which to save the IAR." + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME), HandleSaveInvConsoleCommand); @@ -398,6 +399,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; }); ops.Add("c|creators", delegate(string v) { options["creators"] = v; }); + ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); List mainParams = ops.Parse(cmdparams); @@ -406,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (mainParams.Count < 6) { m_log.Error( - "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=] []"); + "[INVENTORY ARCHIVER]: usage is save iar [--p|-profile=] [--noassets] []"); return; } @@ -423,16 +425,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_log.InfoFormat( "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", savePath, invPath, firstName, lastName); - + + lock (m_pendingConsoleSaves) + m_pendingConsoleSaves.Add(id); + ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options); } catch (InventoryArchiverException e) { m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); } - - lock (m_pendingConsoleSaves) - m_pendingConsoleSaves.Add(id); } private void SaveInvConsoleCommandCompleted( diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 5ba08ee094..aadeedb337 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -44,7 +44,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { @@ -104,7 +103,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); MemoryStream archiveWriteStream = new MemoryStream(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 52232a0c9e..ae3ab21b18 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -44,7 +44,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { @@ -72,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "password"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); InventoryItemBase coaItem @@ -124,11 +123,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } /// - /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive + /// Test saving a single inventory item to an IAR /// (subject to change since there is no fixed format yet). /// [Test] - public void TestSaveItemToIarV0_1() + public void TestSaveItemToIar() { TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -138,7 +137,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); + UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); // Create asset UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); @@ -212,6 +211,106 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } } +// Assert.That(gotControlFile, Is.True, "No control file in archive"); + Assert.That(gotObject1File, Is.True, "No item1 file in archive"); +// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); + + // TODO: Test presence of more files and contents of files. + } + + /// + /// Test saving a single inventory item to an IAR without its asset + /// + [Test] + public void TestSaveItemToIarNoAssets() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, userId, userPassword); + + // Create asset + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + SceneObjectGroup object1 = SceneSetupHelpers.CreateSceneObject(1, ownerId, "My Little Dog Object", 0x50); + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + m_scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + string item1Name = "My Little Dog"; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = item1Name; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + m_scene.AddInventoryItem(item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + + Dictionary options = new Dictionary(); + options.Add("noassets", true); + + // When we're not saving assets, archiving is being done synchronously. + m_archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream, options); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + //bool gotControlFile = false; + bool gotObject1File = false; + //bool gotObject2File = false; + string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); + string expectedObject1FilePath = string.Format( + "{0}{1}", + ArchiveConstants.INVENTORY_PATH, + expectedObject1FileName); + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + +// Console.WriteLine("Reading archive"); + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + Console.WriteLine("Got {0}", filePath); + +// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) +// { +// gotControlFile = true; +// } + + if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) + { +// string fileName = filePath.Remove(0, "Objects/".Length); +// +// if (fileName.StartsWith(part1.Name)) +// { + Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); + gotObject1File = true; +// } +// else if (fileName.StartsWith(part2.Name)) +// { +// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); +// gotObject2File = true; +// } + } + else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + Assert.Fail("Found asset path in TestSaveItemToIarNoAssets()"); + } + } + // Assert.That(gotControlFile, Is.True, "No control file in archive"); Assert.That(gotObject1File, Is.True, "No item1 file in archive"); // Assert.That(gotObject2File, Is.True, "No object2 file in archive"); @@ -229,7 +328,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "meowfood"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 @@ -261,8 +360,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 @@ -294,7 +393,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests TestHelper.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - UserProfileTestUtils.CreateUserWithInventory(m_scene, m_uaMT, "password"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "password"); m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "password", m_iarStream); InventoryItemBase foundItem1 diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs index c7dae5276b..127d5f81f1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/PathTests.cs @@ -44,7 +44,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { @@ -71,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string userLastName = "Stirrup"; string userPassword = "troll"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); + UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); // Create asset SceneObjectGroup object1; @@ -184,8 +183,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "meowfood"); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaLL1, "hampshire"); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); InventoryItemBase foundItem1 @@ -194,7 +193,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); // Now try loading to a root child folder - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xA"); MemoryStream archiveReadStream = new MemoryStream(m_iarStream.ToArray()); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xA", "meowfood", archiveReadStream); @@ -203,7 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); // Now try loading to a more deeply nested folder - UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); + UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, m_uaMT.PrincipalID, "xB/xC"); archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "xB/xC", "meowfood", archiveReadStream); @@ -226,7 +225,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Scene scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); - UserProfileTestUtils.CreateUserWithInventory(scene, m_uaMT, "password"); + UserAccountHelpers.CreateUserWithInventory(scene, m_uaMT, "password"); archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/Objects", "password", m_iarStream); InventoryItemBase foundItem1 @@ -255,7 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests string userFirstName = "Jock"; string userLastName = "Stirrup"; UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); // Create asset SceneObjectGroup object1; @@ -328,7 +327,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); Dictionary foldersCreated = new Dictionary(); HashSet nodesLoaded = new HashSet(); @@ -395,13 +394,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests //log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); string folder1ExistingName = "a"; string folder2Name = "b"; InventoryFolderBase folder1 - = UserInventoryTestUtils.CreateInventoryFolder( + = UserInventoryHelpers.CreateInventoryFolder( scene.InventoryService, ua1.PrincipalID, folder1ExistingName); string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); @@ -446,13 +445,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene); string folder1ExistingName = "a"; string folder2Name = "b"; InventoryFolderBase folder1 - = UserInventoryTestUtils.CreateInventoryFolder( + = UserInventoryHelpers.CreateInventoryFolder( scene.InventoryService, ua1.PrincipalID, folder1ExistingName); string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs new file mode 100644 index 0000000000..c82cfd2d75 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -0,0 +1,244 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using Mono.Addins; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Connectors.Hypergrid; + +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +namespace OpenSim.Region.CoreModules.Avatar.Lure +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class HGLureModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private readonly List m_scenes = new List(); + + private IMessageTransferModule m_TransferModule = null; + private bool m_Enabled = false; + + private string m_ThisGridURL; + + private ExpiringCache m_PendingLures = new ExpiringCache(); + + public void Initialise(IConfigSource config) + { + if (config.Configs["Messaging"] != null) + { + if (config.Configs["Messaging"].GetString("LureModule", string.Empty) == "HGLureModule") + { + m_Enabled = true; + + m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty); + m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); + } + } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_scenes) + { + m_scenes.Add(scene); + scene.EventManager.OnIncomingInstantMessage += OnIncomingInstantMessage; + scene.EventManager.OnNewClient += OnNewClient; + } + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + if (m_TransferModule == null) + { + m_TransferModule = + scene.RequestModuleInterface(); + + if (m_TransferModule == null) + { + m_log.Error("[LURE MODULE]: No message transfer module, lures will not work!"); + + m_Enabled = false; + m_scenes.Clear(); + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage; + } + } + + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_scenes) + { + m_scenes.Remove(scene); + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage; + } + } + + void OnNewClient(IClientAPI client) + { + client.OnInstantMessage += OnInstantMessage; + client.OnStartLure += OnStartLure; + client.OnTeleportLureRequest += OnTeleportLureRequest; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "HGLureModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + } + + void OnIncomingInstantMessage(GridInstantMessage im) + { + if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) + { + UUID sessionID = new UUID(im.imSessionID); + m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); + m_PendingLures.Add(sessionID, im, 7200); // 2 hours + + // Forward. We do this, because the IM module explicitly rejects + // IMs of this type + if (m_TransferModule != null) + m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); + + } + } + + public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + ScenePresence presence = scene.GetScenePresence(client.AgentId); + + message += "@" + m_ThisGridURL; + + m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); + + GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, + client.FirstName+" "+client.LastName, targetid, + (byte)InstantMessageDialog.RequestTeleport, false, + message, UUID.Random(), false, presence.AbsolutePosition, + new Byte[0]); + m.RegionID = client.Scene.RegionInfo.RegionID.Guid; + + if (m_TransferModule != null) + { + m_TransferModule.SendInstantMessage(m, + delegate(bool success) { }); + } + } + + public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)(client.Scene); + + GridInstantMessage im = null; + if (m_PendingLures.TryGetValue(lureID, out im)) + { + m_PendingLures.Remove(lureID); + Lure(client, teleportFlags, im); + } + else + m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID); + + } + + private void Lure(IClientAPI client, uint teleportflags, GridInstantMessage im) + { + Scene scene = (Scene)(client.Scene); + GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(im.RegionID)); + if (region != null) + scene.RequestTeleportLocation(client, region.RegionHandle, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags); + else // we don't have that region here. Check if it's HG + { + string[] parts = im.message.Split(new char[] { '@' }); + if (parts.Length > 1) + { + string url = parts[parts.Length - 1]; // the last part + if (url.Trim(new char[] {'/'}) != m_ThisGridURL.Trim(new char[] {'/'})) + { + m_log.DebugFormat("[HG LURE MODULE]: Luring agent to grid {0} region {1} position {2}", url, im.RegionID, im.Position); + GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); + GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = url; + GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(im.RegionID)); + if (finalDestination != null) + { + ScenePresence sp = scene.GetScenePresence(client.AgentId); + IEntityTransferModule transferMod = scene.RequestModuleInterface(); + IEventQueue eq = sp.Scene.RequestModuleInterface(); + if (transferMod != null && sp != null && eq != null) + transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq); + } + } + } + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index d1d7df2d9e..d295384279 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -45,16 +45,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure private readonly List m_scenes = new List(); private IMessageTransferModule m_TransferModule = null; - private bool m_Enabled = true; + private bool m_Enabled = false; public void Initialise(IConfigSource config) { if (config.Configs["Messaging"] != null) { if (config.Configs["Messaging"].GetString( - "LureModule", "LureModule") != + "LureModule", "LureModule") == "LureModule") - m_Enabled = false; + { + m_Enabled = true; + m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); + } } } @@ -74,6 +77,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure public void RegionLoaded(Scene scene) { + if (!m_Enabled) + return; + if (m_TransferModule == null) { m_TransferModule = @@ -96,6 +102,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure public void RemoveRegion(Scene scene) { + if (!m_Enabled) + return; + lock (m_scenes) { m_scenes.Remove(scene); diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs new file mode 100644 index 0000000000..079e1b6b0a --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs @@ -0,0 +1,173 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Reflection; + +using OpenMetaverse; +using log4net; +using Nini.Config; +using Mono.Addins; + +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.Avatar.Profile +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class BasicProfileModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // + // Module vars + // + private List m_Scenes = new List(); + private bool m_Enabled = false; + + #region ISharedRegionModule + + public void Initialise(IConfigSource config) + { + if (config.Configs["Profile"] != null) + { + if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule") + return; + } + + m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); + m_Enabled = true; + + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + if (!m_Scenes.Contains(scene)) + { + m_Scenes.Add(scene); + // Hook up events + scene.EventManager.OnNewClient += OnNewClient; + } + } + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + lock (m_Scenes) + { + m_Scenes.Remove(scene); + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "BasicProfileModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + /// New Client Event Handler + private void OnNewClient(IClientAPI client) + { + //Profile + client.OnRequestAvatarProperties += RequestAvatarProperties; + } + + public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) + { + IScene s = remoteClient.Scene; + if (!(s is Scene)) + return; + + Scene scene = (Scene)s; + + string profileUrl = String.Empty; + string aboutText = String.Empty; + string firstLifeAboutText = String.Empty; + UUID image = UUID.Zero; + UUID firstLifeImage = UUID.Zero; + UUID partner = UUID.Zero; + uint wantMask = 0; + string wantText = String.Empty; + uint skillsMask = 0; + string skillsText = String.Empty; + string languages = String.Empty; + + Byte[] charterMember = Utils.StringToBytes("Avatar"); + + profileUrl = "No profile data"; + aboutText = string.Empty; + firstLifeAboutText = string.Empty; + image = UUID.Zero; + firstLifeImage = UUID.Zero; + partner = UUID.Zero; + + remoteClient.SendAvatarProperties(avatarID, aboutText, + Util.ToDateTime(0).ToString( + "M/d/yyyy", CultureInfo.InvariantCulture), + charterMember, firstLifeAboutText, + (uint)(0 & 0xff), + firstLifeImage, image, profileUrl, partner); + + //Viewer expects interest data when it asks for properties. + remoteClient.SendAvatarInterestsReply(avatarID, wantMask, wantText, + skillsMask, skillsText, languages); + } + + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index d07eb23633..ac4b4f4ca3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected bool m_Enabled = false; protected Scene m_aScene; + protected List m_Scenes = new List(); protected List m_agentsInTransit; private ExpiringCache> m_bannedRegions = new ExpiringCache>(); @@ -96,6 +97,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_aScene == null) m_aScene = scene; + m_Scenes.Add(scene); scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; } @@ -103,6 +105,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void OnNewClient(IClientAPI client) { client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportLandmarkRequest += RequestTeleportLandmark; } public virtual void Close() @@ -118,6 +121,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; if (scene == m_aScene) m_aScene = null; + + m_Scenes.Remove(scene); } public virtual void RegionLoaded(Scene scene) @@ -127,7 +132,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } - #endregion #region Agent Teleports @@ -248,7 +252,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) + public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) { if (reg == null || finalDestination == null) { @@ -556,6 +560,29 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion + #region Landmark Teleport + /// + /// Tries to teleport agent to landmark. + /// + /// + /// + /// + public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) + { + GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); + + if (info == null) + { + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The teleport destination could not be found."); + return; + } + ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, + Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); + } + + #endregion + #region Teleport Home public virtual void TeleportHome(UUID id, IClientAPI client) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 5c53f787bf..8df89adfdb 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -87,6 +87,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override void OnNewClient(IClientAPI client) { client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnConnectionClosed += new Action(OnConnectionClosed); } @@ -146,8 +147,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { base.AgentHasMovedAway(sp, logout); if (logout) + { + // Reset the map + ResetMap(sp); + // Log them out of this grid m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); + } } protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) @@ -228,6 +234,79 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); } + + /// + /// Tries to teleport agent to landmark. + /// + /// + /// + /// + public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}", + (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position); + if (lm.Gatekeeper == string.Empty) + { + base.RequestTeleportLandmark(remoteClient, lm); + return; + } + + GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID); + + // Local region? + if (info != null) + { + ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position, + Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark)); + return; + } + else + { + // Foreign region + Scene scene = (Scene)(remoteClient.Scene); + GatekeeperServiceConnector gConn = new GatekeeperServiceConnector(); + GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = lm.Gatekeeper; + GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID)); + if (finalDestination != null) + { + ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId); + IEntityTransferModule transferMod = scene.RequestModuleInterface(); + IEventQueue eq = sp.Scene.RequestModuleInterface(); + if (transferMod != null && sp != null && eq != null) + transferMod.DoTeleport(sp, gatekeeper, finalDestination, lm.Position, + Vector3.UnitX, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark), eq); + } + + } + + // can't find the region: Tell viewer and abort + remoteClient.SendTeleportFailed("The teleport destination could not be found."); + + } + + protected void ResetMap(ScenePresence sp) + { + List regions = m_Scenes[0].GridService.GetRegionRange(m_Scenes[0].RegionInfo.ScopeID, 0, 17000 * (int)Constants.RegionSize, 0, 17000 * (int)Constants.RegionSize); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Resetting {0} tiles on the map", regions.Count); + if (regions != null) + { + List mapBlocks = new List(); + foreach (GridRegion r in regions) + { + MapBlockData mblock = new MapBlockData(); + mblock.X = (ushort)(r.RegionLocX / Constants.RegionSize); + mblock.Y = (ushort)(r.RegionLocY / Constants.RegionSize); + mblock.Name = ""; + mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's + mblock.MapImageId = UUID.Zero; + mapBlocks.Add(mblock); + } + sp.ControllingClient.SendMapBlock(mapBlocks, 0); + } + + } + #endregion #region IUserAgentVerificationModule diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 52791cb046..49d484b0e8 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private string m_ProfileServerURI; private bool m_OutboundPermission; + private string m_ThisGatekeeper; // private bool m_Initialized = false; @@ -85,6 +86,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { m_ProfileServerURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); + m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); @@ -110,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) { string userAssetServer = string.Empty; - if (IsForeignUser(avatarID, out userAssetServer) && m_OutboundPermission) + if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) { Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); }); } @@ -119,6 +121,24 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #endregion #region Overrides of Basic Inventory Access methods + + protected override string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) + { + UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.ScopeID, presence.UUID); + if (account == null) + prefix = "HG "; + else + prefix = string.Empty; + suffix = " @ " + m_ThisGatekeeper; + Vector3 pos = presence.AbsolutePosition; + return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}\n", + presence.Scene.RegionInfo.RegionID, + pos.X, pos.Y, pos.Z, + presence.RegionHandle, + m_ThisGatekeeper); + } + + /// /// CapsUpdateInventoryItemAsset /// @@ -180,10 +200,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) { string userAssetServer = string.Empty; - if (IsForeignUser(sender, out userAssetServer)) + if (IsForeignUser(sender, out userAssetServer) && userAssetServer != string.Empty) m_assMapper.Get(item.AssetID, sender, userAssetServer); - if (IsForeignUser(receiver, out userAssetServer) && m_OutboundPermission) + if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) m_assMapper.Post(item.AssetID, receiver, userAssetServer); } @@ -203,9 +223,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) { assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); - assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true; + assetServerURL = assetServerURL.Trim(new char[] { '/' }); } } + else + { + assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI"); + assetServerURL = assetServerURL.Trim(new char[] { '/' }); + } + return true; } return false; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index b85d713f51..5d08f457fd 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Net; using System.Xml; using System.Reflection; +using System.Text; using System.Threading; using OpenSim.Framework; @@ -128,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected virtual void OnNewClient(IClientAPI client) { - + client.OnCreateNewInventoryItem += CreateNewInventoryItem; } public virtual void Close() @@ -156,6 +157,87 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Inventory Access + /// + /// Create a new inventory item. Called when the client creates a new item directly within their + /// inventory (e.g. by selecting a context inventory menu option). + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, + uint callbackID, string description, string name, sbyte invType, + sbyte assetType, + byte wearableType, uint nextOwnerMask, int creationDate) + { + m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); + + if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) + return; + + InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId); + InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f); + + if (folder == null || folder.Owner != remoteClient.AgentId) + return; + + if (transactionID == UUID.Zero) + { + ScenePresence presence; + if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + { + byte[] data = null; + + if (invType == (sbyte)InventoryType.Landmark && presence != null) + { + string suffix = string.Empty, prefix = string.Empty; + string strdata = GenerateLandmark(presence, out prefix, out suffix); + data = Encoding.ASCII.GetBytes(strdata); + name = prefix + name; + description += suffix; + } + + AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); + m_Scene.AssetService.Store(asset); + + m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); + } + else + { + m_log.ErrorFormat( + "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", + remoteClient.AgentId); + } + } + else + { + IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface(); + if (agentTransactions != null) + { + agentTransactions.HandleItemCreationFromTransaction( + remoteClient, transactionID, folderID, callbackID, description, + name, invType, assetType, wearableType, nextOwnerMask); + } + } + } + + protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix) + { + prefix = string.Empty; + suffix = string.Empty; + Vector3 pos = presence.AbsolutePosition; + return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", + presence.Scene.RegionInfo.RegionID, + pos.X, pos.Y, pos.Z, + presence.RegionHandle); + } + /// /// Capability originating call to update the asset of an item in an agent's inventory /// diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs index 8d53cf1542..733ad25843 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs @@ -45,7 +45,6 @@ using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests { @@ -73,7 +72,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests string userFirstName = "Jock"; string userLastName = "Stirrup"; string userPassword = "troll"; - UserProfileTestUtils.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword); + UserAccountHelpers.CreateUserWithInventory(m_scene, userFirstName, userLastName, m_userId, userPassword); AgentCircuitData acd = new AgentCircuitData(); acd.AgentID = m_userId; diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 4cc6905a0f..accd09443c 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -30,11 +30,13 @@ using System.IO; using System.Reflection; using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Hypergrid; using OpenMetaverse; using log4net; @@ -47,7 +49,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public UUID Id; public string FirstName; public string LastName; - public string ProfileURL; + public string HomeURL; + public Dictionary ServerURLs; } public class UserManagementModule : ISharedRegionModule, IUserManagement @@ -78,6 +81,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement // } // } //} + MainConsole.Instance.Commands.AddCommand("grid", true, + "show names", + "show names", + "Show the bindings between user UUIDs and user names", + String.Empty, + HandleShowUsers); + + } public bool IsSharedModule @@ -101,6 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); + scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); } public void RemoveRegion(Scene scene) @@ -109,18 +121,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_Scenes.Remove(scene); } - public void RegionLoaded(Scene scene) + public void RegionLoaded(Scene s) { } public void PostInitialise() { - foreach (Scene s in m_Scenes) - { - // let's sniff all the user names referenced by objects in the scene - m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length); - s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); - } } public void Close() @@ -134,6 +140,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement #region Event Handlers + void EventManager_OnPrimsLoaded(Scene s) + { + // let's sniff all the user names referenced by objects in the scene + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length); + s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); + } + + void EventManager_OnNewClient(IClientAPI client) { client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest); @@ -150,6 +164,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string[] names = GetUserNames(uuid); if (names.Length == 2) { + //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); remote_client.SendNameReply(uuid, names[0], names[1]); } @@ -210,6 +225,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public string GetUserName(UUID uuid) { + //m_log.DebugFormat("[XXX] GetUserName {0}", uuid); string[] names = GetUserNames(uuid); if (names.Length == 2) { @@ -222,6 +238,60 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return "(hippos)"; } + public string GetUserHomeURL(UUID userID) + { + if (m_UserCache.ContainsKey(userID)) + return m_UserCache[userID].HomeURL; + + return string.Empty; + } + + public string GetUserServerURL(UUID userID, string serverType) + { + if (m_UserCache.ContainsKey(userID)) + { + UserData userdata = m_UserCache[userID]; + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) + return userdata.ServerURLs[serverType].ToString(); + + if (userdata.HomeURL != string.Empty) + { + UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL); + userdata.ServerURLs = uConn.GetServerURLs(userID); + if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null) + return userdata.ServerURLs[serverType].ToString(); + } + } + + return string.Empty; + } + + public string GetUserUUI(UUID userID) + { + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID); + if (account != null) + return userID.ToString(); + + if (m_UserCache.ContainsKey(userID)) + { + UserData ud = m_UserCache[userID]; + string homeURL = ud.HomeURL; + string first = ud.FirstName, last = ud.LastName; + if (ud.LastName.StartsWith("@")) + { + string[] parts = ud.FirstName.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + return userID + ";" + homeURL + ";" + first + " " + last; + } + } + + return userID.ToString(); + } + public void AddUser(UUID id, string creatorData) { if (m_UserCache.ContainsKey(id)) @@ -247,13 +317,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement string[] parts = creatorData.Split(';'); if (parts.Length >= 1) { - user.ProfileURL = parts[0]; + user.HomeURL = parts[0]; try { Uri uri = new Uri(parts[0]); user.LastName = "@" + uri.Authority; } - catch + catch (UriFormatException) { m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]); user.LastName = "@unknown"; @@ -272,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement lock (m_UserCache) m_UserCache[id] = user; - m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL); + m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.HomeURL); } public void AddUser(UUID uuid, string first, string last, string profileURL) @@ -311,5 +381,25 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement //} #endregion IUserManagement + + private void HandleShowUsers(string module, string[] cmd) + { + if (m_UserCache.Count == 0) + { + MainConsole.Instance.Output("No users not found"); + return; + } + + MainConsole.Instance.Output("UUID User Name"); + MainConsole.Instance.Output("-----------------------------------------------------------------------------"); + foreach (KeyValuePair kvp in m_UserCache) + { + MainConsole.Instance.Output(String.Format("{0} {1} {2}", + kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); + } + return; + } + + } } diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index 5ab334ffaf..fd2cc20a1a 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.Reflection; using log4net; @@ -58,26 +59,44 @@ namespace OpenSim.Region.CoreModules.Hypergrid #endregion - protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) - { - List mapBlocks = new List(); - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, - minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize); + //protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + //{ + // List mapBlocks = new List(); + // List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + // minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, + // minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize); - foreach (GridRegion r in regions) - { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); - } + // foreach (GridRegion r in regions) + // { + // uint x = 0, y = 0; + // long handle = 0; + // if (r.RegionSecret != null && r.RegionSecret != string.Empty) + // { + // if (long.TryParse(r.RegionSecret, out handle)) + // { + // Utils.LongToUInts((ulong)handle, out x, out y); + // x = x / Constants.RegionSize; + // y = y / Constants.RegionSize; + // } + // } - // Different from super - FillInMap(mapBlocks, minX, minY, maxX, maxY); - // + // if (handle == 0 || + // // Check the distance from the current region + // (handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096)) + // { + // MapBlockData block = new MapBlockData(); + // MapBlockFromGridRegion(block, r); + // mapBlocks.Add(block); + // } + // } - remoteClient.SendMapBlock(mapBlocks, 0); - } + // // Different from super + // //FillInMap(mapBlocks, minX, minY, maxX, maxY); + // // + + // remoteClient.SendMapBlock(mapBlocks, 0); + + //} private void FillInMap(List mapBlocks, int minX, int minY, int maxX, int maxY) diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 8a6735f378..e22fd38107 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -24,6 +24,7 @@ + diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs index d2343c994e..a5b5637961 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs @@ -113,8 +113,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid ISimulationService simService = scene.RequestModuleInterface(); m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); - new UserAgentServerConnector(m_Config, MainServer.Instance); + IFriendsSimConnector friendsConn = scene.RequestModuleInterface(); + new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn); new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); + new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService"); } scene.RegisterModuleInterface(m_HypergridHandler.GateKeeper); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index 18db9fa0e3..c044407d99 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid; using OpenSim.Region.Framework.Scenes; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 3f63db371f..698fd569e4 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -58,6 +58,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory private List m_Scenes = new List(); + protected IUserManagement m_UserManagement; + protected IUserManagement UserManagementModule + { + get + { + if (m_UserManagement == null) + m_UserManagement = m_Scenes[0].RequestModuleInterface(); + return m_UserManagement; + } + } + public Type ReplaceableInterface { get { return null; } @@ -207,6 +218,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory } } } + if (sp == null) + { + inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); + if (inventoryURL != null && inventoryURL != string.Empty) + { + inventoryURL = inventoryURL.Trim(new char[] { '/' }); + m_InventoryURLs.Add(userID, inventoryURL); + m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL); + } + + } + } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs index e471f756d0..4556df3535 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; using OpenSim.Region.Framework.Scenes; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests { diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 82bef48c8c..64616365f4 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -347,12 +347,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver landData.Add(parcel); } - - if (!m_merge) - m_scene.LandChannel.Clear(false); + + if (!m_merge) + { + bool setupDefaultParcel = (landData.Count == 0); + m_scene.LandChannel.Clear(setupDefaultParcel); + } m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); - m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); + m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); } /// diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 597b7809e5..10a83ee826 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public class ArchiveWriteRequestPreparation { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + /// /// The minimum major version of OAR that we can write. /// @@ -58,7 +58,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// The maximum major version of OAR that we can write. /// - public static int MAX_MAJOR_VERSION = 0; + public static int MAX_MAJOR_VERSION = 0; + + /// + /// Determine whether this archive will save assets. Default is true. + /// + public bool SaveAssets { get; set; } protected Scene m_scene; protected Stream m_saveStream; @@ -73,10 +78,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// If there was a problem opening a stream for the file specified by the savePath /// - public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) + public ArchiveWriteRequestPreparation(Scene scene, string savePath, Guid requestId) : this(scene, requestId) { - m_scene = scene; - try { m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress); @@ -86,10 +89,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.ErrorFormat( "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); - m_log.Error(e); + m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); } - - m_requestId = requestId; } /// @@ -98,11 +99,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// The stream to which to save data. /// The id associated with this request - public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) + public ArchiveWriteRequestPreparation(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) + { + m_saveStream = saveStream; + } + + protected ArchiveWriteRequestPreparation(Scene scene, Guid requestId) { m_scene = scene; - m_saveStream = saveStream; m_requestId = requestId; + + SaveAssets = true; } /// @@ -111,22 +118,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// if there was an io problem with creating the file public void ArchiveRegion(Dictionary options) { + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + try { Dictionary assetUuids = new Dictionary(); EntityBase[] entities = m_scene.GetEntities(); List sceneObjects = new List(); - - /* - foreach (ILandObject lo in m_scene.LandChannel.AllParcels()) - { - if (name == lo.LandData.Name) - { - // This is the parcel we want - } - } - */ // Filter entities so that we only have scene objects. // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods @@ -141,17 +141,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver sceneObjects.Add((SceneObjectGroup)entity); } } - - UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); - - foreach (SceneObjectGroup sceneObject in sceneObjects) + + if (SaveAssets) { - assetGatherer.GatherAssetUuids(sceneObject, assetUuids); + UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); + + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + assetGatherer.GatherAssetUuids(sceneObject, assetUuids); + } + + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", + sceneObjects.Count, assetUuids.Count); + } + else + { + m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); } - - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count); // Make sure that we also request terrain texture assets RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; @@ -187,11 +194,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - - new AssetsRequest( - new AssetsArchiver(archiveWriter), assetUuids, - m_scene.AssetService, m_scene.UserAccountService, - m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets).Execute(); + + if (SaveAssets) + new AssetsRequest( + new AssetsArchiver(archiveWriter), assetUuids, + m_scene.AssetService, m_scene.UserAccountService, + m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets).Execute(); + else + awre.ReceivedAllAssets(new List(), new List()); } catch (Exception) { @@ -204,9 +214,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// Create the control file for the most up to date archive /// /// - public static string CreateControlFile(Dictionary options) + public string CreateControlFile(Dictionary options) { - int majorVersion = MAX_MAJOR_VERSION, minorVersion = 6; + int majorVersion = MAX_MAJOR_VERSION, minorVersion = 7; // // if (options.ContainsKey("version")) // { @@ -258,6 +268,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); xtw.WriteElementString("id", UUID.Random().ToString()); xtw.WriteEndElement(); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + xtw.WriteEndElement(); xtw.Flush(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 9277c594f0..08eb80cc2e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -127,6 +127,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver OptionSet ops = new OptionSet(); // ops.Add("v|version=", delegate(string v) { options["version"] = v; }); ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); + ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); List mainParams = ops.Parse(cmdparams); @@ -160,7 +161,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void ArchiveRegion(Stream saveStream, Guid requestId) { - new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(new Dictionary()); + ArchiveRegion(saveStream, requestId, new Dictionary()); + } + + public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options) + { + new ArchiveWriteRequestPreparation(m_scene, saveStream, requestId).ArchiveRegion(options); } public void DearchiveRegion(string loadPath) diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index b88869882f..3078ab384e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -230,6 +230,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// public void AssetRequestCallback(string id, object sender, AssetBase asset) { + Culture.SetCurrentCulture(); + try { lock (this) @@ -293,6 +295,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// protected void PerformAssetsRequestCallback(object o) { + Culture.SetCurrentCulture(); + try { m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 2307c8e585..34e2e23a01 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -43,7 +43,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; @@ -212,6 +211,89 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } + /// + /// Test saving an OpenSim Region Archive with the no assets option + /// + [Test] + public void TestSaveOarNoAssets() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + SceneObjectPart part1 = CreateSceneObjectPart1(); + SceneObjectGroup sog1 = new SceneObjectGroup(part1); + m_scene.AddNewSceneObject(sog1, false); + + SceneObjectPart part2 = CreateSceneObjectPart2(); + + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + m_scene.AssetService.Store(ncAsset); + SceneObjectGroup sog2 = new SceneObjectGroup(part2); + TaskInventoryItem ncItem + = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; + part2.Inventory.AddInventoryItem(ncItem, true); + + m_scene.AddNewSceneObject(sog2, false); + + MemoryStream archiveWriteStream = new MemoryStream(); + + Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); + + Dictionary options = new Dictionary(); + options.Add("noassets", true); + m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); + //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; + //while (assetServer.HasWaitingRequests()) + // assetServer.ProcessNextRequest(); + + // Don't wait for completion - with --noassets save oar happens synchronously +// Monitor.Wait(this, 60000); + + Assert.That(m_lastRequestId, Is.EqualTo(requestId)); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + List foundPaths = new List(); + List expectedPaths = new List(); + expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog1)); + expectedPaths.Add(ArchiveHelpers.CreateObjectPath(sog2)); + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + + byte[] data = tar.ReadEntry(out filePath, out tarEntryType); + Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); + + ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); + arr.LoadControlFile(filePath, data); + + Assert.That(arr.ControlFileLoaded, Is.True); + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) + { + Assert.Fail("Asset was found in saved oar of TestSaveOarNoAssets()"); + } + else if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) + { + foundPaths.Add(filePath); + } + } + + Assert.That(foundPaths, Is.EquivalentTo(expectedPaths)); + + // TODO: Test presence of more files and contents of files. + } + /// /// Test loading an OpenSim Region Archive. /// @@ -231,7 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // upset load tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary())); + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); SceneObjectPart part1 = CreateSceneObjectPart1(); SceneObjectGroup object1 = new SceneObjectGroup(part1); @@ -313,6 +397,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); + Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); + // Temporary Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); } @@ -330,7 +416,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestPreparation.CreateControlFile(new Dictionary())); + tar.WriteFile( + ArchiveConstants.CONTROL_FILE_PATH, + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); RegionSettings rs = new RegionSettings(); rs.AgentLimit = 17; diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index bfab7b88e4..63dec1516f 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -520,8 +520,12 @@ namespace OpenSim.Region.CoreModules.World.Land } } + /// + /// Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. + /// + /// public void EventManagerOnClientMovement(ScenePresence avatar) - //Like handleEventManagerOnSignificantClientMovement, but called with an AgentUpdate regardless of distance. + // { ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); if (over != null) @@ -534,7 +538,6 @@ namespace OpenSim.Region.CoreModules.World.Land } } - public void ClientOnParcelAccessListRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID, int landLocalID, IClientAPI remote_client) { @@ -668,14 +671,14 @@ namespace OpenSim.Region.CoreModules.World.Land //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); } - + m_landList.Clear(); + + ResetSimLandObjects(); + + if (setupDefaultParcel) + CreateDefaultParcel(); } - - ResetSimLandObjects(); - - if (setupDefaultParcel) - CreateDefaultParcel(); } private void performFinalLandJoin(ILandObject master, ILandObject slave) @@ -1391,8 +1394,11 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnNoLandDataFromStorage() { - ResetSimLandObjects(); - CreateDefaultParcel(); + lock (m_landList) + { + ResetSimLandObjects(); + CreateDefaultParcel(); + } } #endregion diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index c2f104e370..560b862625 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.World.Land public int GetPrimsFree() { m_scene.EventManager.TriggerParcelPrimCountUpdate(); - int free = GetSimulatorMaxPrimCount(this) - m_landData.SimwidePrims; + int free = GetSimulatorMaxPrimCount() - m_landData.SimwidePrims; return free; } @@ -181,11 +181,11 @@ namespace OpenSim.Region.CoreModules.World.Land overrideSimulatorMaxPrimCount = overrideDel; } - public int GetParcelMaxPrimCount(ILandObject thisObject) + public int GetParcelMaxPrimCount() { if (overrideParcelMaxPrimCount != null) { - return overrideParcelMaxPrimCount(thisObject); + return overrideParcelMaxPrimCount(this); } else { @@ -197,11 +197,12 @@ namespace OpenSim.Region.CoreModules.World.Land return parcelMax; } } - public int GetSimulatorMaxPrimCount(ILandObject thisObject) + + public int GetSimulatorMaxPrimCount() { if (overrideSimulatorMaxPrimCount != null) { - return overrideSimulatorMaxPrimCount(thisObject); + return overrideSimulatorMaxPrimCount(this); } else { @@ -244,8 +245,8 @@ namespace OpenSim.Region.CoreModules.World.Land remote_client.SendLandProperties(seq_id, snap_selection, request_result, this, (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, - GetParcelMaxPrimCount(this), - GetSimulatorMaxPrimCount(this), regionFlags); + GetParcelMaxPrimCount(), + GetSimulatorMaxPrimCount(), regionFlags); } public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs index 67b00ac759..a3aa38de94 100644 --- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs +++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs @@ -37,7 +37,6 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.World.Land.Tests { diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs index 5b85830f5f..d5b708229a 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests { diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 170c35f814..d7324c6c55 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions // libomv will moan about PrimFlags.ObjectYouOfficer being // deprecated - #pragma warning disable 0612 +#pragma warning disable 0612 objflags &= (uint) ~(PrimFlags.ObjectCopy | // Tells client you can copy the object - PrimFlags.ObjectModify | // tells client you can modify the object - PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) - PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it - PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object - PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object - PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object - PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object + PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set ); - #pragma warning restore 0612 +#pragma warning restore 0612 // Creating the three ObjectFlags options for this method to choose from. // Customize the OwnerMask @@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_bypassPermissions) return objectOwnerMask; - + // Object owners should be able to edit their own content if (user == objectOwner) return objectOwnerMask; - - if (IsFriendWithPerms(user, objectOwner)) - return objectOwnerMask; + if (IsFriendWithPerms(user, objectOwner)) + { + return objectOwnerMask; + } // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) + { return objectOwnerMask; + } // Admin should be able to edit anything in the sim (including admin objects) if (IsAdministrator(user)) + { return objectOwnerMask; - + } + // Users should be able to edit what is over their land. Vector3 taskPos = task.AbsolutePosition; ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); @@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions { // Admin objects should not be editable by the above if (!IsAdministrator(objectOwner)) + { return objectOwnerMask; + } } // Group permissions if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) return objectGroupMask | objectEveryoneMask; - + return objectEveryoneMask; } @@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions // // Nobody but the object owner can set permissions on an object // - if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) { return false; @@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions // Return immediately, so that the administrator can shares group objects return true; } + + // Friends with benefits should be able to edit the objects too + if (IsFriendWithPerms(currentUser, objectOwner)) + // Return immediately, so that the administrator can share objects with friends + return true; // Users should be able to edit what is over their land. ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs index e983239b4a..0f37dddc86 100644 --- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs @@ -70,14 +70,14 @@ namespace OpenSim.Region.CoreModules.World.Region false, "region restart bluebox", "region restart bluebox +", "Schedule a region restart", - "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.", + "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.", HandleRegionRestart); MainConsole.Instance.Commands.AddCommand("RestartModule", false, "region restart notice", "region restart notice +", "Schedule a region restart", - "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a dismissable bluebox notice. If multiple deltas are given then a notice is sent when we reach each delta.", + "Schedule a region restart after a given number of seconds. If one delta is given then the region is restarted in delta seconds time. A time to restart is sent to users in the region as a transient notice. If multiple deltas are given then a notice is sent when we reach each delta.", HandleRegionRestart); MainConsole.Instance.Commands.AddCommand("RestartModule", diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs index a866fd938c..4f752ab82b 100644 --- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs +++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs @@ -35,7 +35,6 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.CoreModules.World.Serialiser.Tests { diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 0cacf2dce1..69d300553c 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -208,52 +208,65 @@ namespace OpenSim.Region.CoreModules.World.WorldMap //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", // path, param, agentID.ToString()); - // this is here because CAPS map requests work even beyond the 10,000 limit. - ScenePresence avatarPresence = null; + // There is a major hack going on in this method. The viewer doesn't request + // map blocks (RequestMapBlocks) above 2048. That means that if we don't hack, + // grids above that cell don't have a map at all. So, here's the hack: we wait + // for this CAP request to come, and we inject the map blocks at this point. + // In a normal scenario, this request simply sends back the MapLayer (the blue color). + // In the hacked scenario, it also sends the map blocks via UDP. + // + // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is + // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. - m_scene.TryGetScenePresence(agentID, out avatarPresence); - - if (avatarPresence != null) + if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) { - bool lookup = false; + ScenePresence avatarPresence = null; - lock (cachedMapBlocks) + m_scene.TryGetScenePresence(agentID, out avatarPresence); + + if (avatarPresence != null) { - if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) - { - List mapBlocks; - - mapBlocks = cachedMapBlocks; - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); - } - else - { - lookup = true; - } - } - if (lookup) - { - List mapBlocks = new List(); ; - - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); - foreach (GridRegion r in regions) - { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); - mapBlocks.Add(block); - } - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + bool lookup = false; lock (cachedMapBlocks) - cachedMapBlocks = mapBlocks; + { + if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) + { + List mapBlocks; - cachedTime = Util.UnixTimeSinceEpoch(); + mapBlocks = cachedMapBlocks; + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + } + else + { + lookup = true; + } + } + if (lookup) + { + List mapBlocks = new List(); ; + + List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, + (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); + foreach (GridRegion r in regions) + { + MapBlockData block = new MapBlockData(); + MapBlockFromGridRegion(block, r); + mapBlocks.Add(block); + } + avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + + lock (cachedMapBlocks) + cachedMapBlocks = mapBlocks; + + cachedTime = Util.UnixTimeSinceEpoch(); + } } } + LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); return mapResponse.ToString(); diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index e17226966c..3835ced11c 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -550,7 +550,7 @@ namespace OpenSim.Region.Examples.SimpleModule { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 8b96de46fd..07e97d5630 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -40,6 +40,9 @@ namespace OpenSim.Region.Framework.Interfaces void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); + void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, + Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); + void TeleportHome(UUID id, IClientAPI client); bool Cross(ScenePresence agent, bool isFlying); diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs index 0ff7deeb30..d4a6857188 100644 --- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs @@ -34,6 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces public interface IFriendsModule { uint GetFriendPerms(UUID PrincipalID, UUID FriendID); - void SendFriendsOnlineIfNeeded(IClientAPI client); + bool SendFriendsOnlineIfNeeded(IClientAPI client); } } diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs index d8229de5a5..3fafc47648 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs @@ -52,31 +52,44 @@ namespace OpenSim.Region.Framework.Interfaces /// /// Archive the region to the given path /// - /// + /// /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to /// the EventManager.OnOarFileSaved event. - /// + /// /// /// If supplied, this request Id is later returned in the saved event + /// Options for the save void ArchiveRegion(string savePath, Guid requestId, Dictionary options); /// /// Archive the region to a stream. /// - /// + /// /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to /// the EventManager.OnOarFileSaved event. - /// + /// /// /// If supplied, this request Id is later returned in the saved event void ArchiveRegion(Stream saveStream, Guid requestId); + /// + /// Archive the region to a stream. + /// + /// + /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to + /// the EventManager.OnOarFileSaved event. + /// + /// + /// If supplied, this request Id is later returned in the saved event + /// Options for the save + void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options); + /// /// Dearchive the given region archive. This replaces the existing scene. /// - /// + /// /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. - /// + /// /// void DearchiveRegion(string loadPath); diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index fecdd1b9b8..d9752e64a5 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -50,5 +50,7 @@ namespace OpenSim.Region.Framework.Interfaces void ResumeScript(UUID itemID); ArrayList GetScriptErrors(UUID itemID); + + void SaveAllState(); } } diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index 2904ee87dc..5d30aa8e24 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -8,6 +8,9 @@ namespace OpenSim.Region.Framework.Interfaces public interface IUserManagement { string GetUserName(UUID uuid); + string GetUserHomeURL(UUID uuid); + string GetUserUUI(UUID uuid); + string GetUserServerURL(UUID uuid, string serverType); void AddUser(UUID uuid, string userData); void AddUser(UUID uuid, string firstName, string lastName, string profileURL); } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index c530eeed40..b1000176e8 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -373,6 +373,10 @@ namespace OpenSim.Region.Framework.Scenes public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + public delegate void SceneShuttingDownDelegate(Scene scene); + + public event SceneShuttingDownDelegate OnSceneShuttingDown; + /// /// Fired when an object is touched/grabbed. /// @@ -647,6 +651,12 @@ namespace OpenSim.Region.Framework.Scenes public delegate void RegionUp(GridRegion region); public event RegionUp OnRegionUp; + public delegate void LoginsEnabled(string regionName); + public event LoginsEnabled OnLoginsEnabled; + + public delegate void PrimsLoaded(Scene s); + public event PrimsLoaded OnPrimsLoaded; + public class MoneyTransferArgs : EventArgs { public UUID sender; @@ -2470,6 +2480,69 @@ namespace OpenSim.Region.Framework.Scenes } } + public void TriggerSceneShuttingDown(Scene s) + { + SceneShuttingDownDelegate handler = OnSceneShuttingDown; + if (handler != null) + { + foreach (SceneShuttingDownDelegate d in handler.GetInvocationList()) + { + try + { + d(s); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerSceneShuttingDown failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } + + public void TriggerLoginsEnabled (string regionName) + { + LoginsEnabled handler = OnLoginsEnabled; + + if ( handler != null) + { + foreach (LoginsEnabled d in handler.GetInvocationList()) + { + try + { + d(regionName); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + + public void TriggerPrimsLoaded(Scene s) + { + PrimsLoaded handler = OnPrimsLoaded; + + if (handler != null) + { + foreach (PrimsLoaded d in handler.GetInvocationList()) + { + try + { + d(s); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for PrimsLoaded failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + //REGION SYNC #region REGION SYNC RELATED EVENTS //OnScriptEngineSyncStop: triggered when user types "sync stop" on the script engine's console diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6c7a359934..19bd58d944 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -591,192 +591,198 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemId, senderId); item = InventoryService.GetItem(item); - if ((item != null) && (item.Owner == senderId)) + if (item == null) { - IUserManagement uman = RequestModuleInterface(); - if (uman != null) - uman.AddUser(item.CreatorIdAsUuid, item.CreatorData); - - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) - return null; - } - - // Insert a copy of the item into the recipient - InventoryItemBase itemCopy = new InventoryItemBase(); - itemCopy.Owner = recipient; - itemCopy.CreatorId = item.CreatorId; - itemCopy.CreatorData = item.CreatorData; - itemCopy.ID = UUID.Random(); - itemCopy.AssetID = item.AssetID; - itemCopy.Description = item.Description; - itemCopy.Name = item.Name; - itemCopy.AssetType = item.AssetType; - itemCopy.InvType = item.InvType; - itemCopy.Folder = recipientFolderId; - - if (Permissions.PropagatePermissions() && recipient != senderId) - { - // Trying to do this right this time. This is evil. If - // you believe in Good, go elsewhere. Vampires and other - // evil creatores only beyond this point. You have been - // warned. - - // We're going to mask a lot of things by the next perms - // Tweak the next perms to be nicer to our data - // - // In this mask, all the bits we do NOT want to mess - // with are set. These are: - // - // Transfer - // Copy - // Modufy - uint permsMask = ~ ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify); - - // Now, reduce the next perms to the mask bits - // relevant to the operation - uint nextPerms = permsMask | (item.NextPermissions & - ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify)); - - // nextPerms now has all bits set, except for the actual - // next permission bits. - - // This checks for no mod, no copy, no trans. - // This indicates an error or messed up item. Do it like - // SL and assume trans - if (nextPerms == permsMask) - nextPerms |= (uint)PermissionMask.Transfer; - - // Inventory owner perms are the logical AND of the - // folded perms and the root prim perms, however, if - // the root prim is mod, the inventory perms will be - // mod. This happens on "take" and is of little concern - // here, save for preventing escalation - - // This hack ensures that items previously permalocked - // get unlocked when they're passed or rezzed - uint basePerms = item.BasePermissions | - (uint)PermissionMask.Move; - uint ownerPerms = item.CurrentPermissions; - - // If this is an object, root prim perms may be more - // permissive than folded perms. Use folded perms as - // a mask - if (item.InvType == (int)InventoryType.Object) - { - // Create a safe mask for the current perms - uint foldedPerms = (item.CurrentPermissions & 7) << 13; - foldedPerms |= permsMask; - - bool isRootMod = (item.CurrentPermissions & - (uint)PermissionMask.Modify) != 0 ? - true : false; - - // Mask the owner perms to the folded perms - ownerPerms &= foldedPerms; - basePerms &= foldedPerms; - - // If the root was mod, let the mask reflect that - // We also need to adjust the base here, because - // we should be able to edit in-inventory perms - // for the root prim, if it's mod. - if (isRootMod) - { - ownerPerms |= (uint)PermissionMask.Modify; - basePerms |= (uint)PermissionMask.Modify; - } - } - - // These will be applied to the root prim at next rez. - // The slam bit (bit 3) and folded permission (bits 0-2) - // are preserved due to the above mangling - ownerPerms &= nextPerms; - - // Mask the base permissions. This is a conservative - // approach altering only the three main perms - basePerms &= nextPerms; - - // Assign to the actual item. Make sure the slam bit is - // set, if it wasn't set before. - itemCopy.BasePermissions = basePerms; - itemCopy.CurrentPermissions = ownerPerms; - itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; - - itemCopy.NextPermissions = item.NextPermissions; - - // This preserves "everyone can move" - itemCopy.EveryOnePermissions = item.EveryOnePermissions & - nextPerms; - - // Intentionally killing "share with group" here, as - // the recipient will not have the group this is - // set to - itemCopy.GroupPermissions = 0; - } - else - { - itemCopy.CurrentPermissions = item.CurrentPermissions; - itemCopy.NextPermissions = item.NextPermissions; - itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; - itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; - itemCopy.BasePermissions = item.BasePermissions; - } - - if (itemCopy.Folder == UUID.Zero) - { - InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType); - - if (folder != null) - { - itemCopy.Folder = folder.ID; - } - else - { - InventoryFolderBase root = InventoryService.GetRootFolder(recipient); - - if (root != null) - itemCopy.Folder = root.ID; - else - return null; // No destination - } - } - - itemCopy.GroupID = UUID.Zero; - itemCopy.GroupOwned = false; - itemCopy.Flags = item.Flags; - itemCopy.SalePrice = item.SalePrice; - itemCopy.SaleType = item.SaleType; - - if (AddInventoryItem(itemCopy)) - { - IInventoryAccessModule invAccess = RequestModuleInterface(); - if (invAccess != null) - invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); - } - - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - { - List items = new List(); - items.Add(itemId); - InventoryService.DeleteItems(senderId, items); - } - } - - return itemCopy; - } - else - { - m_log.WarnFormat("[AGENT INVENTORY]: Failed to find item {0} or item does not belong to giver ", itemId); + m_log.WarnFormat( + "[AGENT INVENTORY]: Failed to find item {0} sent by {1} to {2}", itemId, senderId, recipient); return null; } + if (item.Owner != senderId) + { + m_log.WarnFormat( + "[AGENT INVENTORY]: Attempt to send item {0} {1} to {2} failed because sender {3} did not match item owner {4}", + item.Name, item.ID, recipient, senderId, item.Owner); + return null; + } + + IUserManagement uman = RequestModuleInterface(); + if (uman != null) + uman.AddUser(item.CreatorIdAsUuid, item.CreatorData); + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + return null; + } + + // Insert a copy of the item into the recipient + InventoryItemBase itemCopy = new InventoryItemBase(); + itemCopy.Owner = recipient; + itemCopy.CreatorId = item.CreatorId; + itemCopy.CreatorData = item.CreatorData; + itemCopy.ID = UUID.Random(); + itemCopy.AssetID = item.AssetID; + itemCopy.Description = item.Description; + itemCopy.Name = item.Name; + itemCopy.AssetType = item.AssetType; + itemCopy.InvType = item.InvType; + itemCopy.Folder = recipientFolderId; + + if (Permissions.PropagatePermissions() && recipient != senderId) + { + // Trying to do this right this time. This is evil. If + // you believe in Good, go elsewhere. Vampires and other + // evil creatores only beyond this point. You have been + // warned. + + // We're going to mask a lot of things by the next perms + // Tweak the next perms to be nicer to our data + // + // In this mask, all the bits we do NOT want to mess + // with are set. These are: + // + // Transfer + // Copy + // Modufy + uint permsMask = ~ ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + + // Now, reduce the next perms to the mask bits + // relevant to the operation + uint nextPerms = permsMask | (item.NextPermissions & + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify)); + + // nextPerms now has all bits set, except for the actual + // next permission bits. + + // This checks for no mod, no copy, no trans. + // This indicates an error or messed up item. Do it like + // SL and assume trans + if (nextPerms == permsMask) + nextPerms |= (uint)PermissionMask.Transfer; + + // Inventory owner perms are the logical AND of the + // folded perms and the root prim perms, however, if + // the root prim is mod, the inventory perms will be + // mod. This happens on "take" and is of little concern + // here, save for preventing escalation + + // This hack ensures that items previously permalocked + // get unlocked when they're passed or rezzed + uint basePerms = item.BasePermissions | + (uint)PermissionMask.Move; + uint ownerPerms = item.CurrentPermissions; + + // If this is an object, root prim perms may be more + // permissive than folded perms. Use folded perms as + // a mask + if (item.InvType == (int)InventoryType.Object) + { + // Create a safe mask for the current perms + uint foldedPerms = (item.CurrentPermissions & 7) << 13; + foldedPerms |= permsMask; + + bool isRootMod = (item.CurrentPermissions & + (uint)PermissionMask.Modify) != 0 ? + true : false; + + // Mask the owner perms to the folded perms + ownerPerms &= foldedPerms; + basePerms &= foldedPerms; + + // If the root was mod, let the mask reflect that + // We also need to adjust the base here, because + // we should be able to edit in-inventory perms + // for the root prim, if it's mod. + if (isRootMod) + { + ownerPerms |= (uint)PermissionMask.Modify; + basePerms |= (uint)PermissionMask.Modify; + } + } + + // These will be applied to the root prim at next rez. + // The slam bit (bit 3) and folded permission (bits 0-2) + // are preserved due to the above mangling + ownerPerms &= nextPerms; + + // Mask the base permissions. This is a conservative + // approach altering only the three main perms + basePerms &= nextPerms; + + // Assign to the actual item. Make sure the slam bit is + // set, if it wasn't set before. + itemCopy.BasePermissions = basePerms; + itemCopy.CurrentPermissions = ownerPerms; + itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; + + itemCopy.NextPermissions = item.NextPermissions; + + // This preserves "everyone can move" + itemCopy.EveryOnePermissions = item.EveryOnePermissions & + nextPerms; + + // Intentionally killing "share with group" here, as + // the recipient will not have the group this is + // set to + itemCopy.GroupPermissions = 0; + } + else + { + itemCopy.CurrentPermissions = item.CurrentPermissions; + itemCopy.NextPermissions = item.NextPermissions; + itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; + itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; + itemCopy.BasePermissions = item.BasePermissions; + } + + if (itemCopy.Folder == UUID.Zero) + { + InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType); + + if (folder != null) + { + itemCopy.Folder = folder.ID; + } + else + { + InventoryFolderBase root = InventoryService.GetRootFolder(recipient); + + if (root != null) + itemCopy.Folder = root.ID; + else + return null; // No destination + } + } + + itemCopy.GroupID = UUID.Zero; + itemCopy.GroupOwned = false; + itemCopy.Flags = item.Flags; + itemCopy.SalePrice = item.SalePrice; + itemCopy.SaleType = item.SaleType; + + if (AddInventoryItem(itemCopy)) + { + IInventoryAccessModule invAccess = RequestModuleInterface(); + if (invAccess != null) + invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); + } + + if (!Permissions.BypassPermissions()) + { + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + { + List items = new List(); + items.Add(itemId); + InventoryService.DeleteItems(senderId, items); + } + } + + return itemCopy; } /// @@ -944,7 +950,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - private void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, + public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) { CreateNewInventoryItem( @@ -998,78 +1004,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Create a new inventory item. Called when the client creates a new item directly within their - /// inventory (e.g. by selecting a context inventory menu option). - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID, - uint callbackID, string description, string name, sbyte invType, - sbyte assetType, - byte wearableType, uint nextOwnerMask, int creationDate) - { - m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); - - if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) - return; - - InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId); - InventoryFolderBase folder = InventoryService.GetFolder(f); - - if (folder == null || folder.Owner != remoteClient.AgentId) - return; - - if (transactionID == UUID.Zero) - { - ScenePresence presence; - if (TryGetScenePresence(remoteClient.AgentId, out presence)) - { - byte[] data = null; - - if (invType == (sbyte)InventoryType.Landmark && presence != null) - { - Vector3 pos = presence.AbsolutePosition; - string strdata = String.Format( - "Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n", - presence.Scene.RegionInfo.RegionID, - pos.X, pos.Y, pos.Z, - presence.RegionHandle); - data = Encoding.ASCII.GetBytes(strdata); - } - - AssetBase asset = CreateAsset(name, description, assetType, data, remoteClient.AgentId); - AssetService.Store(asset); - - CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); - } - else - { - m_log.ErrorFormat( - "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", - remoteClient.AgentId); - } - } - else - { - IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); - if (agentTransactions != null) - { - agentTransactions.HandleItemCreationFromTransaction( - remoteClient, transactionID, folderID, callbackID, description, - name, invType, assetType, wearableType, nextOwnerMask); - } - } - } - /// /// Link an inventory item to an existing item. /// @@ -1090,9 +1024,9 @@ namespace OpenSim.Region.Framework.Scenes uint callbackID, string description, string name, sbyte invType, sbyte type, UUID olditemID) { - m_log.DebugFormat( - "[AGENT INVENTORY]: Received request from {0} to create inventory item link {1} in folder {2} pointing to {3}", - remoteClient.Name, name, folderID, olditemID); +// m_log.DebugFormat( +// "[AGENT INVENTORY]: Received request from {0} to create inventory item link {1} in folder {2} pointing to {3}", +// remoteClient.Name, name, folderID, olditemID); if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) return; @@ -1100,20 +1034,25 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence presence; if (TryGetScenePresence(remoteClient.AgentId, out presence)) { - bool linkAlreadyExists = false; - List existingItems = InventoryService.GetFolderItems(remoteClient.AgentId, folderID); - foreach (InventoryItemBase item in existingItems) - if (item.AssetID == olditemID) - linkAlreadyExists = true; - - if (linkAlreadyExists) - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Ignoring request from {0} to create item link {1} in folder {2} pointing to {3} since a link already exists", - remoteClient.Name, name, folderID, olditemID); - - return; - } + // Disabled the check for duplicate links. + // + // When outfits are being adjusted, the viewer rapidly sends delete link messages followed by + // create links. However, since these are handled asynchronously, the deletes do not complete before + // the creates are handled. Therefore, we cannot enforce a duplicate link check. +// InventoryItemBase existingLink = null; +// List existingItems = InventoryService.GetFolderItems(remoteClient.AgentId, folderID); +// foreach (InventoryItemBase item in existingItems) +// if (item.AssetID == olditemID) +// existingLink = item; +// +// if (existingLink != null) +// { +// m_log.WarnFormat( +// "[AGENT INVENTORY]: Ignoring request from {0} to create item link {1} in folder {2} pointing to {3} since a link named {4} with id {5} already exists", +// remoteClient.Name, name, folderID, olditemID, existingLink.Name, existingLink.ID); +// +// return; +// } AssetBase asset = new AssetBase(); asset.FullID = olditemID; @@ -1141,7 +1080,11 @@ namespace OpenSim.Region.Framework.Scenes /// private void RemoveInventoryItem(IClientAPI remoteClient, List itemIDs) { - //m_log.Debug("[SCENE INVENTORY]: user " + remoteClient.AgentId); +// m_log.DebugFormat( +// "[AGENT INVENTORY]: Removing inventory items {0} for {1}", +// string.Join(",", itemIDs.ConvertAll(uuid => uuid.ToString()).ToArray()), +// remoteClient.Name); + InventoryService.DeleteItems(remoteClient.AgentId, itemIDs); } @@ -1561,7 +1504,10 @@ namespace OpenSim.Region.Framework.Scenes if (item.AssetType == (int)AssetType.Link) { InventoryItemBase linkedItem = InventoryService.GetItem(new InventoryItemBase(item.AssetID)); - linkedItemFolderIdsToSend.Add(linkedItem.Folder); + + // Take care of genuinely broken links where the target doesn't exist + if (linkedItem != null) + linkedItemFolderIdsToSend.Add(linkedItem.Folder); } } @@ -2288,7 +2234,7 @@ namespace OpenSim.Region.Framework.Scenes sourcePart.Inventory.RemoveInventoryItem(item.ItemID); } - //AddNewSceneObject(group, true); + //AddNewSceneObject(group, true, pos, rot, vel); //DSG SYNC bool triggerSyncNewObject = false; AddNewSceneObjectByRez(group, true, true, triggerSyncNewObject); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 38b996d75a..f5c145b2b5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -94,7 +94,10 @@ namespace OpenSim.Region.Framework.Scenes // root agents when ACL denies access to root agent public bool m_strictAccessControl = true; public int MaxUndoCount = 5; + // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; + public bool LoginLock = false; public bool LoginsDisabled = true; + public bool StartDisabled = false; public bool LoadingPrims; public IXfer XferManager; @@ -204,6 +207,7 @@ namespace OpenSim.Region.Framework.Scenes private Timer m_mapGenerationTimer = new Timer(); private bool m_generateMaptiles; + private bool m_useBackup = true; // private Dictionary m_UserNamesCache = new Dictionary(); @@ -975,6 +979,11 @@ namespace OpenSim.Region.Framework.Scenes get { return m_sceneGraph; } } + public bool UseBackup + { + get { return m_useBackup; } + } + // an instance to the physics plugin's Scene object. public PhysicsScene PhysicsScene { @@ -1116,7 +1125,7 @@ namespace OpenSim.Region.Framework.Scenes "delete object uuid ", "Delete object by uuid", HandleDeleteObject); MainConsole.Instance.Commands.AddCommand("region", false, "delete object name", - "delete object name ", + "delete object name ", "Delete object by name", HandleDeleteObject); //Bind Storage Manager functions to some land manager functions for this scene @@ -1166,6 +1175,9 @@ namespace OpenSim.Region.Framework.Scenes IConfig startupConfig = m_config.Configs["Startup"]; m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); + m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); + if (!m_useBackup) + m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); //Animation states m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); @@ -1587,6 +1599,8 @@ namespace OpenSim.Region.Framework.Scenes shuttingdown = true; m_log.Debug("[SCENE]: Persisting changed objects for region " + m_regionName); + EventManager.TriggerSceneShuttingDown(this); + EntityBase[] entities = GetEntities(); foreach (EntityBase entity in entities) { @@ -1935,10 +1949,26 @@ namespace OpenSim.Region.Framework.Scenes IConfig startupConfig = m_config.Configs["Startup"]; if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) { + // This handles a case of a region having no scripts for the RegionReady module + if (m_sceneGraph.GetActiveScriptsCount() == 0) + { + // need to be able to tell these have changed in RegionReady + LoginLock = false; + EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); + } m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); - LoginsDisabled = false; + // For RegionReady lockouts + if( LoginLock == false) + { + LoginsDisabled = false; + } m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); } + else + { + StartDisabled = true; + LoginsDisabled = true; + } } } catch (NotImplementedException) @@ -2344,6 +2374,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.InfoFormat("[SCENE ({0})]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)", m_regionName); LoadingPrims = false; + EventManager.TriggerPrimsLoaded(this); } @@ -2499,6 +2530,10 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.SetGroup(groupID, null); } + IUserManagement uman = RequestModuleInterface(); + if (uman != null) + sceneObject.RootPart.CreatorIdentification = uman.GetUserUUI(ownerID); + //sceneObject.ScheduleGroupForFullUpdate(); sceneObject.ScheduleGroupForFullUpdate(new List(){SceneObjectPartSyncProperties.FullUpdate}); //new object, all properties have new value @@ -2592,16 +2627,17 @@ namespace OpenSim.Region.Framework.Scenes /// /// Add a newly created object to the scene. /// - /// + /// /// This method does not send updates to the client - callers need to handle this themselves. + /// /// /// - /// Position of the object - /// Rotation of the object + /// Position of the object. If null then the position stored in the object is used. + /// Rotation of the object. If null then the rotation stored in the object is used. /// Velocity of the object. This parameter only has an effect if the object is physical /// public bool AddNewSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) + SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel)) { @@ -3187,12 +3223,38 @@ namespace OpenSim.Region.Framework.Scenes if (GetScenePresence(client.AgentId) != null) { m_LastLogin = Util.EnvironmentTickCount(); + + // Cache the user's name + CacheUserName(aCircuit); + EventManager.TriggerOnNewClient(client); if (vialogin) EventManager.TriggerOnClientLogin(client); } } + private void CacheUserName(AgentCircuitData aCircuit) + { + IUserManagement uMan = RequestModuleInterface(); + if (uMan != null) + { + string homeURL = string.Empty; + string first = aCircuit.firstname, last = aCircuit.lastname; + if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) + homeURL = aCircuit.ServiceURLs["HomeURI"].ToString(); + if (aCircuit.lastname.StartsWith("@")) + { + string[] parts = aCircuit.firstname.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + } + uMan.AddUser(aCircuit.AgentID, first, last, homeURL); + } + } + private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) { vialogin = false; @@ -3346,7 +3408,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientInventoryEvents(IClientAPI client) { - client.OnCreateNewInventoryItem += CreateNewInventoryItem; + client.OnLinkInventoryItem += HandleLinkInventoryItem; client.OnCreateNewInventoryFolder += HandleCreateInventoryFolder; client.OnUpdateInventoryFolder += HandleUpdateInventoryFolder; @@ -3369,7 +3431,6 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientTeleportEvents(IClientAPI client) { client.OnTeleportLocationRequest += RequestTeleportLocation; - client.OnTeleportLandmarkRequest += RequestTeleportLandmark; } public virtual void SubscribeToClientScriptEvents(IClientAPI client) @@ -3473,7 +3534,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientInventoryEvents(IClientAPI client) { - client.OnCreateNewInventoryItem -= CreateNewInventoryItem; + client.OnCreateNewInventoryFolder -= HandleCreateInventoryFolder; client.OnUpdateInventoryFolder -= HandleUpdateInventoryFolder; client.OnMoveInventoryFolder -= HandleMoveInventoryFolder; // 2; //!! @@ -3495,7 +3556,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client) { client.OnTeleportLocationRequest -= RequestTeleportLocation; - client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; + //client.OnTeleportLandmarkRequest -= RequestTeleportLandmark; //client.OnTeleportHomeRequest -= TeleportClientHome; } @@ -4576,26 +4637,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Tries to teleport agent to landmark. - /// - /// - /// - /// - public void RequestTeleportLandmark(IClientAPI remoteClient, UUID regionID, Vector3 position) - { - GridRegion info = GridService.GetRegionByUUID(UUID.Zero, regionID); - - if (info == null) - { - // can't find the region: Tell viewer and abort - remoteClient.SendTeleportFailed("The teleport destination could not be found."); - return; - } - - RequestTeleportLocation(remoteClient, info.RegionHandle, position, Vector3.Zero, (uint)(TPFlags.SetLastToTarget | TPFlags.ViaLandmark)); - } - public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) { if (m_teleportModule != null) @@ -4965,7 +5006,28 @@ namespace OpenSim.Region.Framework.Scenes // } /// - /// Get a named prim contained in this scene (will return the first + /// Get a group via its UUID + /// + /// + /// null if no group with that name exists + public SceneObjectGroup GetSceneObjectGroup(UUID fullID) + { + return m_sceneGraph.GetSceneObjectGroup(fullID); + } + + /// + /// Get a group by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// null if no group with that name exists + public SceneObjectGroup GetSceneObjectGroup(string name) + { + return m_sceneGraph.GetSceneObjectGroup(name); + } + + /// + /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 4d179077c6..2cd4198123 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -321,23 +321,26 @@ namespace OpenSim.Region.Framework.Scenes /// This method does not send updates to the client - callers need to handle this themselves. /// /// - /// Position of the object - /// Rotation of the object + /// Position of the object. If null then the position stored in the object is used. + /// Rotation of the object. If null then the rotation stored in the object is used. /// Velocity of the object. This parameter only has an effect if the object is physical /// public bool AddNewSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) + SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { - // we set it's position in world. - sceneObject.AbsolutePosition = pos; + AddNewSceneObject(sceneObject, true, false); + + if (pos != null) + sceneObject.AbsolutePosition = (Vector3)pos; if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) { sceneObject.ClearPartAttachmentData(); } - - sceneObject.UpdateGroupRotationR(rot); - + + if (rot != null) + sceneObject.UpdateGroupRotationR((Quaternion)rot); + //group.ApplyPhysics(m_physicalPrim); if (sceneObject.RootPart.PhysActor != null && sceneObject.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero) { @@ -357,6 +360,9 @@ namespace OpenSim.Region.Framework.Scenes /// Add an object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. /// + /// + /// The object's stored position, rotation and velocity are used. + /// /// /// /// If true, the object is made persistent into the scene. @@ -1005,6 +1011,51 @@ namespace OpenSim.Region.Framework.Scenes return result; } + /// + /// Get a group in the scene + /// + /// UUID of the group + /// null if no such group was found + protected internal SceneObjectGroup GetSceneObjectGroup(UUID fullID) + { + lock (SceneObjectGroupsByFullID) + { + if (SceneObjectGroupsByFullID.ContainsKey(fullID)) + return SceneObjectGroupsByFullID[fullID]; + } + + return null; + } + + /// + /// Get a group by name from the scene (will return the first + /// found, if there are more than one prim with the same name) + /// + /// + /// null if the part was not found + protected internal SceneObjectGroup GetSceneObjectGroup(string name) + { + SceneObjectGroup so = null; + + Entities.Find( + delegate(EntityBase entity) + { + if (entity is SceneObjectGroup) + { + if (entity.Name == name) + { + so = (SceneObjectGroup)entity; + return true; + } + } + + return false; + } + ); + + return so; + } + /// /// Get a part contained in this scene. /// @@ -1019,7 +1070,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Get a named prim contained in this scene (will return the first + /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) /// /// @@ -1488,7 +1539,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// + /// Handle a prim description set request from a viewer. /// /// /// @@ -1505,8 +1556,17 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Set a click action for the prim. + /// + /// + /// + /// protected internal void PrimClickAction(IClientAPI remoteClient, uint primLocalID, string clickAction) { +// m_log.DebugFormat( +// "[SCENEGRAPH]: User {0} set click action for {1} to {2}", remoteClient.Name, primLocalID, clickAction); + SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 883481ae5e..72b8405df7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -471,6 +471,11 @@ namespace OpenSim.Region.Framework.Scenes #endregion +// ~SceneObjectGroup() +// { +// m_log.DebugFormat("[SCENE OBJECT GROUP]: Destructor called for {0}, local id {1}", Name, LocalId); +// } + #region Constructors //DSG SYNC @@ -1375,7 +1380,7 @@ namespace OpenSim.Region.Framework.Scenes } } - if (HasGroupChanged) + if (m_scene.UseBackup && HasGroupChanged) { // don't backup while it's selected or you're asking for changes mid stream. if (isTimeToPersist() || forcedBackup) @@ -3949,4 +3954,4 @@ namespace OpenSim.Region.Framework.Scenes #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 31e8164580..f0cf627de9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -157,11 +157,10 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 StatusSandboxPos; - // TODO: This needs to be persisted in next XML version update! - - public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; - - + [XmlIgnore] + public int[] PayPrice = {-2,-2,-2,-2,-2}; + + [XmlIgnore] public PhysicsActor PhysActor { get { return m_physActor; } @@ -391,6 +390,13 @@ namespace OpenSim.Region.Framework.Scenes #endregion Fields +// ~SceneObjectPart() +// { +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Destructor called for {0}, local id {1}, parent {2} {3}", +// Name, LocalId, ParentGroup.Name, ParentGroup.LocalId); +// } + #region Constructors /// diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 18b4a4cb85..66aafd5428 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -121,7 +121,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } - /// /// Serialize a scene object to the original xml format /// @@ -341,6 +340,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); + m_SOPXmlProcessors.Add("PayPrice0", ProcessPayPrice0); + m_SOPXmlProcessors.Add("PayPrice1", ProcessPayPrice1); + m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); + m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); + m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); #endregion #region TaskInventoryXmlProcessors initialization @@ -570,7 +574,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) { - obj.Shape = ReadShape(reader, "Shape"); + bool errors = false; + obj.Shape = ReadShape(reader, "Shape", out errors); + + if (errors) + m_log.DebugFormat( + "[SceneObjectSerializer]: Parsing PrimitiveBaseShape for object part {0} {1} encountered errors. Please see earlier log entries.", + obj.Name, obj.UUID); } private static void ProcessScale(SceneObjectPart obj, XmlTextReader reader) @@ -704,6 +714,31 @@ namespace OpenSim.Region.Framework.Scenes.Serialization obj.ParticleSystem = Convert.FromBase64String(reader.ReadElementContentAsString("ParticleSystem", String.Empty)); } + private static void ProcessPayPrice0(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[0] = (int)reader.ReadElementContentAsInt("PayPrice0", String.Empty); + } + + private static void ProcessPayPrice1(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[1] = (int)reader.ReadElementContentAsInt("PayPrice1", String.Empty); + } + + private static void ProcessPayPrice2(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[2] = (int)reader.ReadElementContentAsInt("PayPrice2", String.Empty); + } + + private static void ProcessPayPrice3(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[3] = (int)reader.ReadElementContentAsInt("PayPrice3", String.Empty); + } + + private static void ProcessPayPrice4(SceneObjectPart obj, XmlTextReader reader) + { + obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); + } + #endregion #region TaskInventoryXmlProcessors @@ -1075,7 +1110,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); } - #endregion ////////// Write ///////// @@ -1181,6 +1215,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); WriteBytes(writer, "TextureAnimation", sop.TextureAnimation); WriteBytes(writer, "ParticleSystem", sop.ParticleSystem); + writer.WriteElementString("PayPrice0", sop.PayPrice[0].ToString()); + writer.WriteElementString("PayPrice1", sop.PayPrice[1].ToString()); + writer.WriteElementString("PayPrice2", sop.PayPrice[2].ToString()); + writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); + writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); writer.WriteEndElement(); } @@ -1448,7 +1487,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } catch (Exception e) { - m_log.DebugFormat("[SceneObjectSerializer]: exception while parsing {0}: {1}", nodeName, e); + m_log.DebugFormat( + "[SceneObjectSerializer]: exception while parsing {0} in object {1} {2}: {3}{4}", + obj.Name, obj.UUID, nodeName, e.Message, e.StackTrace); if (reader.NodeType == XmlNodeType.EndElement) reader.Read(); } @@ -1508,10 +1549,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization return tinv; } + /// + /// Read a shape from xml input + /// + /// + /// The name of the xml element containing the shape + /// true if any errors were encountered during parsing, false otherwise + /// The shape parsed //DSG SYNC: make it public to be called outside - //static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name) - public static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name) + //static PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) + public PrimitiveBaseShape ReadShape(XmlTextReader reader, string name, out bool errors) { + errors = false; + PrimitiveBaseShape shape = new PrimitiveBaseShape(); if (reader.IsEmptyElement) @@ -1536,7 +1586,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } catch (Exception e) { - m_log.DebugFormat("[SceneObjectSerializer]: exception while parsing Shape {0}: {1}", nodeName, e); + errors = true; + m_log.DebugFormat( + "[SceneObjectSerializer]: exception while parsing Shape property {0}: {1}{2}", + nodeName, e.Message, e.StackTrace); + if (reader.NodeType == XmlNodeType.EndElement) reader.Read(); } diff --git a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs index 855b5894b6..cff649b33f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/AttachmentTests.cs @@ -43,7 +43,6 @@ using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs index 667b74ea95..f69a4b430c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs @@ -37,7 +37,6 @@ using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs index ca635d708d..895f2bb4ec 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs @@ -34,7 +34,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index a6a95ef885..0a82c4f574 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -34,7 +34,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs index 0d260266ef..5357a06bb6 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs @@ -37,7 +37,6 @@ using OpenSim.Region.CoreModules.World.Permissions; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs index bdfcd1dc29..cb1d531ab9 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs @@ -35,7 +35,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using log4net; namespace OpenSim.Region.Framework.Scenes.Tests diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs index 8876a435b6..77bd4c2022 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs @@ -40,7 +40,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs index efb757fa6c..03ac252967 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTests.cs @@ -44,7 +44,6 @@ using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index abcce66e23..13d93f943f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -43,7 +43,6 @@ using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Scenes.Tests { diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs index dd28416788..1b5a54ec3c 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs @@ -36,7 +36,6 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; using System.Threading; namespace OpenSim.Region.Framework.Scenes.Tests diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 2aef4b0d19..f4e14d4424 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -46,55 +46,55 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.Framework.Tests { [TestFixture] public class TaskInventoryTests { - protected UserAccount CreateUser(Scene scene) + [Test] + public void TestRezObjectFromInventoryItem() { - string userFirstName = "Jock"; - string userLastName = "Stirrup"; - string userPassword = "troll"; - UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - return UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); - } - - protected SceneObjectGroup CreateSO1(Scene scene, UUID ownerId) - { - string part1Name = "part1"; - UUID part1Id = UUID.Parse("10000000-0000-0000-0000-000000000000"); - SceneObjectPart part1 - = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) - { Name = part1Name, UUID = part1Id }; - return new SceneObjectGroup(part1); - } - - protected TaskInventoryItem CreateSOItem1(Scene scene, SceneObjectPart part) - { - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); - UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - scene.AssetService.Store(ncAsset); - TaskInventoryItem ncItem - = new TaskInventoryItem - { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid, - Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; - part.Inventory.AddInventoryItem(ncItem, true); + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); - return ncItem; + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); + SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); + SceneObjectPart sop1 = sog1.RootPart; + + // Create an object embedded inside the first + UUID taskSceneObjectItemId = UUID.Parse("00000000-0000-0000-0000-100000000000"); + TaskInventoryItem taskSceneObjectItem + = TaskInventoryHelpers.AddSceneObject(scene, sop1, "tso", taskSceneObjectItemId); + + scene.AddSceneObject(sog1); + + Vector3 rezPos = new Vector3(10, 10, 10); + Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f); + Vector3 rezVel = new Vector3(2, 2, 2); + + scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0); + + SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso"); + + Assert.That(rezzedObject, Is.Not.Null); + Assert.That(rezzedObject.AbsolutePosition, Is.EqualTo(rezPos)); + + // Velocity doesn't get applied, probably because there is no physics in tests (yet) +// Assert.That(rezzedObject.Velocity, Is.EqualTo(rezVel)); + Assert.That(rezzedObject.Velocity, Is.EqualTo(Vector3.Zero)); + + // Confusingly, this isn't the rezzedObject.Rotation + Assert.That(rezzedObject.RootPart.RotationOffset, Is.EqualTo(rezRot)); } - + /// /// Test MoveTaskInventoryItem where the item has no parent folder assigned. /// + /// /// This should place it in the most suitable user folder. + /// [Test] public void TestMoveTaskInventoryItem() { @@ -102,10 +102,11 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = CreateUser(scene); - SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); + SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; - TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); + TaskInventoryItem sopItem1 = TaskInventoryHelpers.AddNotecard(scene, sop1); + InventoryFolderBase folder = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; @@ -128,10 +129,10 @@ namespace OpenSim.Region.Framework.Tests // log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene(); - UserAccount user1 = CreateUser(scene); - SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); + SceneObjectGroup sog1 = SceneSetupHelpers.CreateSceneObject(1, user1.PrincipalID); SceneObjectPart sop1 = sog1.RootPart; - TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1); + TaskInventoryItem sopItem1 = TaskInventoryHelpers.AddNotecard(scene, sop1); // Perform test scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID); diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs new file mode 100644 index 0000000000..abca792b8d --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -0,0 +1,110 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Timers; +using Timer=System.Timers.Timer; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; +using OpenSim.Region.CoreModules.World.Serialiser; +using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Tests +{ + [TestFixture] + public class UserInventoryTests + { + [Test] + public void TestGiveInventoryItem() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, 1001); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, 1002); + InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID); + + scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID); + + InventoryItemBase retrievedItem1 + = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Notecards/item1"); + + Assert.That(retrievedItem1, Is.Not.Null); + + // Try giving back the freshly received item + scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID); + + List reretrievedItems + = UserInventoryHelpers.GetInventoryItems(scene.InventoryService, user1.PrincipalID, "Notecards/item1"); + + Assert.That(reretrievedItems.Count, Is.EqualTo(2)); + } + + [Test] + public void TestGiveInventoryFolder() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene(); + UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, 1001); + UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, 1002); + InventoryFolderBase folder1 + = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, "folder1"); + + scene.GiveInventoryFolder(user2.PrincipalID, user1.PrincipalID, folder1.ID, UUID.Zero); + + InventoryFolderBase retrievedFolder1 + = UserInventoryHelpers.GetInventoryFolder(scene.InventoryService, user2.PrincipalID, "folder1"); + + Assert.That(retrievedFolder1, Is.Not.Null); + + // Try giving back the freshly received folder + scene.GiveInventoryFolder(user1.PrincipalID, user2.PrincipalID, retrievedFolder1.ID, UUID.Zero); + + List reretrievedFolders + = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, "folder1"); + + Assert.That(reretrievedFolders.Count, Is.EqualTo(2)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs index dbf9e0f550..4da8df135f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs @@ -33,7 +33,6 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Setup; using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.Framework.Scenes.Tests diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 3fba662338..8ecf80f689 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1187,7 +1187,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server IRC_SendChannelPrivmsg(objectname,url); } - public void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 8589901947..7304145c1b 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -95,8 +95,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance scene.AddCommand( this, "appearance show", "appearance show", - "Show appearance information for each avatar in the simulator. At the moment, ", - ShowAppearanceInfo); + "Show appearance information for each avatar in the simulator.", + "At the moment this actually just checks that we have all the required baked textures. If not, then appearance is 'corrupt' and other avatars will continue to see a cloud.", + ShowAppearanceInfo); } protected void ShowAppearanceInfo(string module, string[] cmd) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 1c791b9d36..630fcabac3 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1223,6 +1223,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Get a list of groups memberships for the agent that are marked "ListInProfile" + /// (unless that agent has a godLike aspect, in which case get all groups) /// /// /// @@ -1231,20 +1232,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; - if (requestingClient.AgentId != dataForAgentID) - { - Predicate showInProfile = delegate(GroupMembershipData membership) - { - return membership.ListInProfile; - }; + // cScene and property accessor 'isGod' are in support of the opertions to bypass 'hidden' group attributes for + // those with a GodLike aspect. + Scene cScene = (Scene)requestingClient.Scene; + bool isGod = cScene.Permissions.IsGod(requestingClient.AgentId); - membershipArray = membershipData.FindAll(showInProfile).ToArray(); - } - else + if (isGod) { membershipArray = membershipData.ToArray(); } + else + { + if (requestingClient.AgentId != dataForAgentID) + { + Predicate showInProfile = delegate(GroupMembershipData membership) + { + return membership.ListInProfile; + }; + membershipArray = membershipData.FindAll(showInProfile).ToArray(); + } + else + { + membershipArray = membershipData.ToArray(); + } + } + if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1257,6 +1270,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } + private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs index 6de97b7269..ee52a39170 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs @@ -35,7 +35,6 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; -using OpenSim.Tests.Common.Setup; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests { diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs deleted file mode 100644 index 4a402bf2bd..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// AuraMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class AuraMetaEntity : PointMetaEntity - { - #region Constructors - - //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. - public AuraMetaEntity(Scene scene, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, groupPos, transparency) - { - SetAura(color, scale); - } - - public AuraMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) - : base(scene, uuid, groupPos, transparency) - { - SetAura(color, scale); - } - - #endregion Constructors - - #region Private Methods - - private float Average(Vector3 values) - { - return (values.X + values.Y + values.Z)/3f; - } - - #endregion Private Methods - - #region Public Methods - - public void SetAura(Vector3 color, Vector3 scale) - { - SetAura(color, Average(scale) * 2.0f); - } - - public void SetAura(Vector3 color, float radius) - { - SceneObjectPart From = m_Entity.RootPart; - - //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); - float burstRadius = 0.1f; - Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; - float age = 1.5f; - float burstRate = 0.4f; - if (radius >= 8.0f) - { - //float sizeOfObject = radius / 2.0f; - burstRadius = (radius - 8.0f)/3f; - burstRate = 1.5f; - radius = 7.99f; - patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; - age = 4.0f; - } - SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); - } - - public void SetAura(SceneObjectPart From, Vector3 color, float radius, float burstRadius, float age, float burstRate, Primitive.ParticleSystem.SourcePattern patternFlags) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency - /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE - prules.PartStartScaleY = 0.5f; - prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE - prules.PartEndScaleY = 0.5f; - */ - prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE - prules.PartStartScaleY = radius; - prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE - prules.PartEndScaleY = radius; - prules.PartMaxAge = age; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - prules.Pattern = patternFlags; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT - //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS - prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - //prules.Target = To; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs deleted file mode 100644 index 6966de0cab..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// BeamMetaEntity.cs created with MonoDevelop -// User: bongiojp at 3:03 PM 8/6/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class BeamMetaEntity : PointMetaEntity - { - #region Constructors - - public BeamMetaEntity(Scene scene, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - public BeamMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) - : base(scene, uuid, groupPos, transparency) - { - SetBeamToUUID(To, color); - } - - #endregion Constructors - - #region Public Methods - - public void SetBeamToUUID(SceneObjectPart To, Vector3 color) - { - SceneObjectPart From = m_Entity.RootPart; - //Scale size of particles to distance objects are apart (for better visibility) - Vector3 FromPos = From.GetWorldPosition(); - Vector3 ToPos = From.GetWorldPosition(); - // UUID toUUID = To.UUID; - float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + - Math.Pow(FromPos.X-ToPos.Y, 2) + - Math.Pow(FromPos.X-ToPos.Z, 2) - ) - ); - //float rate = (float) (distance/4f); - float rate = 0.5f; - float scale = (float) (distance/128f); - float speed = (float) (2.0f - distance/128f); - - SetBeamToUUID(From, To, color, rate, scale, speed); - } - - public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, Vector3 color, float rate, float scale, float speed) - { - Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); - //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | - // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS - prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | - Primitive.ParticleSystem.ParticleDataFlags.TargetPos; - prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR - prules.PartStartColor.G = color.Y; - prules.PartStartColor.B = color.Z; - prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency - prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR - prules.PartEndColor.G = color.Y; - prules.PartEndColor.B = color.Z; - prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency - prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE - prules.PartStartScaleY = scale; - prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE - prules.PartEndScaleY = scale; - prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE - prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL - prules.PartAcceleration.Y = 0.0f; - prules.PartAcceleration.Z = 0.0f; - //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN - //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank - prules.BurstRate = rate; //PSYS_SRC_BURST_RATE - prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT - prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS - prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN - prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX - prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE - prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY - prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA - prules.AngularVelocity.Y = 0.0f; - prules.AngularVelocity.Z = 0.0f; - prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN - prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END - - prules.CRC = 1; //activates the particle system?? - From.AddNewParticleSystem(prules); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs deleted file mode 100644 index 8d6c41df63..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// CMController.cs -// User: bongiojp -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - /// - /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread, - /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system. - /// - public class CMController - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. - /// - private static OpenSim.Framework.BlockingQueue m_WorkQueue = new OpenSim.Framework.BlockingQueue(); - - #endregion Static Fields - - #region Fields - - //bool init = false; - int m_channel = -1; - - /// - /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. - /// - IEstateModule m_estateModule = null; - - //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) - CMModel m_model = null; - - /// - /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. - /// - Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); - State m_state = State.NONE; - CMView m_view = null; - - #endregion Fields - - #region Constructors - - /// - /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. - /// - /// - /// - /// - /// - /// - /// - /// - /// The first scene to keep track of. - /// - /// - /// The simchat channel number to listen to for instructions - /// - public CMController(CMModel model, CMView view, Scene scene, int channel) - { - m_model = model; m_view = view; m_channel = channel; - RegisterNewRegion(scene); - Initialize(model, view, scene, channel); - } - - #endregion Constructors - - #region Private Methods - - //------------------------------------------------ EVENTS ----------------------------------------------------// -// private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) -// { -// } - - /// - /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned. - /// - private SceneObjectGroup GetGroupByPrim(uint localID) - { - foreach (Object currScene in m_sceneList.Values) - { - foreach (EntityBase ent in ((Scene)currScene).GetEntities()) - { - if (ent is SceneObjectGroup) - { - if (((SceneObjectGroup)ent).HasChildPrim(localID)) - return (SceneObjectGroup)ent; - } - } - } - return null; - } - - private void Initialize(CMModel model, CMView view, Scene scene, int channel) - { - lock (this) - { - m_estateModule = scene.RequestModuleInterface(); - Watchdog.StartThread(MainLoop, "Content Management", ThreadPriority.Normal, true); - m_state = State.NONE; - } - } - - /// - /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions. - /// - private void MainLoop() - { - try - { - CMModel model = m_model; CMView view = m_view; int channel = m_channel; - Work currentJob = new Work(); - while (true) - { - currentJob = m_WorkQueue.Dequeue(); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); - switch (currentJob.Type) - { - case WorkType.NONE: - break; - case WorkType.OBJECTATTRIBUTECHANGE: - ObjectAttributeChanged(model, view, currentJob.LocalId); - break; - case WorkType.PRIMITIVEADDED: - PrimitiveAdded(model, view, currentJob); - break; - case WorkType.OBJECTDUPLICATED: - ObjectDuplicated(model, view, currentJob.LocalId); - break; - case WorkType.OBJECTKILLED: - ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); - break; - case WorkType.UNDODID: - UndoDid(model, view, currentJob.UUID); - break; - case WorkType.NEWCLIENT: - NewClient(view, (IClientAPI) currentJob.Data1); - break; - case WorkType.SIMCHAT: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); - SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); - break; - default: - m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); - break; - } - - Watchdog.UpdateThread(); - } - } - catch (Exception e) - { - // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened - m_log.ErrorFormat( - "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", - e); - } - - Watchdog.RemoveThread(); - } - - /// - /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. - /// - private void NewClient(CMView view, IClientAPI client) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.SendMetaEntitiesToNewClient(client); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) - { - SceneObjectGroup group = null; - if ((m_state & State.SHOWING_CHANGES) > 0) - { - group = GetGroupByPrim(LocalId); - if (group != null) - { - view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura) - m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) - } - } - } - - /// - /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. - /// - private void ObjectDuplicated(CMModel model, CMView view, uint localId) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); - } - - /// - /// Only called by the MainLoop. - /// - private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.RemoveOrUpdateDeletedEntity(group); - model.RemoveOrUpdateDeletedEntity(group); - } - } - - /// - /// Only called by the MainLoop. - /// - private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - foreach (Object scene in m_sceneList.Values) - m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); - } - } - - /// - /// Only called by the MainLoop. - /// - private void UndoDid(CMModel model, CMView view, UUID uuid) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); - if (ent != null) - view.DisplayEntity(ent); - } - } - - #endregion Private Methods - - #region Protected Methods - - protected void GroupBeingDeleted(SceneObjectGroup group) - { - m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTKILLED; - moreWork.Data1 = group.Copy(); - m_WorkQueue.Enqueue(moreWork); - } - - protected void ObjectDuplicated(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, - UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, - bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTDUPLICATED; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] dup queue"); - } - - protected void OnNewClient(IClientAPI client) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.NEWCLIENT; - moreWork.Data1 = client; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new client"); - } - - protected void OnUnDid(IClientAPI remoteClient, UUID primId) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.UNDODID; - moreWork.UUID = primId; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] undid"); - } - - /// - /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. - /// - protected static System.Collections.Generic.List ScenesInOrderOfProximity(Hashtable sceneList, Scene scene) - { - int somethingAddedToList = 1; - System.Collections.Generic.List newList = new List(); - newList.Add(scene); - - if (!sceneList.ContainsValue(scene)) - { - foreach (Object sceneObj in sceneList) - newList.Add((Scene) sceneObj); - return newList; - } - - while (somethingAddedToList > 0) - { - somethingAddedToList = 0; - for (int i = 0; i < newList.Count; i++) - { - foreach (Object sceneObj in sceneList.Values) - { - if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (!newList.Contains((Scene)sceneObj))) - { - newList.Add((Scene)sceneObj); - somethingAddedToList++; - } - } - } - } - - foreach (Object sceneObj in sceneList.Values) - if (!newList.Contains((Scene)sceneObj)) - newList.Add((Scene)sceneObj); - - return newList; - } - - //This is stupid, the same information is contained in the first and second argument - protected void SimChatSent(Object x, OSChatMessage e) - { - m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); - m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); - Work moreWork = new Work(); - moreWork.Type = WorkType.SIMCHAT; - moreWork.Data1 = e; - m_WorkQueue.Enqueue(moreWork); - } - - /// - /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. - /// - protected void StartManaging(IClientAPI client) - { - m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); - // client.OnChatFromClient += SimChatSent; - //init = true; - - OnNewClient(client); - - m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); - client.OnUpdatePrimScale += UpdateSingleScale; - client.OnUpdatePrimGroupScale += UpdateMultipleScale; - client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition += UpdateSinglePosition; - client.OnUpdatePrimGroupRotation += UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation += UpdateSingleRotation; - client.OnAddPrim += UpdateNewParts; - client.OnObjectDuplicate += ObjectDuplicated; - client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay; - client.OnUndo += OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - } - - /// - /// - /// - protected void StopManaging(UUID clientUUID) - { - foreach (Object sceneobj in m_sceneList.Values) - { - ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); - if (presence != null) - { - IClientAPI client = presence.ControllingClient; - m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); - // client.OnChatFromViewer -= SimChatSent; - - m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); - client.OnUpdatePrimScale -= UpdateSingleScale; - client.OnUpdatePrimGroupScale -= UpdateMultipleScale; - client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; - client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; - client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; - client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; - client.OnAddPrim -= UpdateNewParts; - client.OnObjectDuplicate -= ObjectDuplicated; - client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; - client.OnUndo -= OnUnDid; - //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; - return; - } - } - } - - protected void UpdateMultiplePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] pos"); - } - - protected void UpdateMultipleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateMultipleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT]scale"); - } - - protected void UpdateNewParts(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, - byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, - byte RayEndIsIntersection) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.PRIMITIVEADDED; - moreWork.UUID = ownerID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] new parts"); - } - - protected void UpdateSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] move"); - } - - /// - /// - /// - protected void UpdateSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] rot"); - } - - protected void UpdateSingleScale(uint localID, Vector3 scale, IClientAPI remoteClient) - { - Work moreWork = new Work(); - moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; - moreWork.LocalId = localID; - m_WorkQueue.Enqueue(moreWork); - m_log.Debug("[CONTENT MANAGEMENT] scale"); - } - - /// - /// Only called from within the SimChat method. - /// - protected void commit(string message, Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - string[] args = message.Split(new char[] {' '}); - - char[] logMessage = {' '}; - if (args.Length > 1) - { - logMessage = new char[message.Length - (args[0].Length)]; - message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); - } - - m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); - foreach (Scene currScene in proximitySceneList) - { - model.CommitRegion(currScene, new String(logMessage)); - view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); - } - - view.SendSimChatMessage(scene, "Successfully saved all regions."); - m_state |= State.DIRTY; - - if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES - { - view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - - //Recreate them from backend files - foreach (Scene currScene in proximitySceneList) - { - model.UpdateCMEntities(currScene); - view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); - } - - //Display new objects to users1 - view.DisplayRecentChanges(); - view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); - m_state &= ~(State.DIRTY); - m_state |= State.SHOWING_CHANGES; - } - } - - /// - /// Only called from within the SimChat method. - /// - protected void diffmode(Scene scene, CMModel model, CMView view) - { - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - - if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF - { - view.SendSimChatMessage(scene, "Hiding all meta objects."); - view.HideAllMetaEntities(); - view.HideAllAuras(); - view.SendSimChatMessage(scene, "Diff-mode = OFF"); - - m_state &= ~State.SHOWING_CHANGES; - return; - } - else // TURN ON - { - if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) - { - view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); - //Hide objects from users and Forget about them - view.HideAllMetaEntities(); - view.HideAllAuras(); - model.DeleteAllMetaObjects(); - //Recreate them from backend files - foreach (Object currScene in m_sceneList.Values) - model.UpdateCMEntities((Scene) currScene); - } - else if ((m_state & State.DIRTY) != 0) { - view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); - foreach (Scene currScene in proximitySceneList) - model.CheckForNewEntitiesMissingAuras(currScene); - view.DisplayRecentChanges(); - - view.SendSimChatMessage(scene, "Diff-mode = ON"); - m_state |= State.SHOWING_CHANGES; - m_state &= ~State.DIRTY; - } - } - - /// - /// Only called from within the SimChat method. Hides all auras and meta entities, - /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, - /// then lets the view update the clients of the new objects. - /// - protected void rollback(Scene scene, CMModel model, CMView view) - { - if ((m_state & State.SHOWING_CHANGES) > 0) - { - view.HideAllAuras(); - view.HideAllMetaEntities(); - } - - System.Collections.Generic.List proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); - foreach (Scene currScene in proximitySceneList) - model.RollbackRegion(currScene); - - if ((m_state & State.DIRTY) != 0) - { - model.DeleteAllMetaObjects(); - foreach (Scene currScene in proximitySceneList) - model.UpdateCMEntities(currScene); - } - - if ((m_state & State.SHOWING_CHANGES) > 0) - view.DisplayRecentChanges(); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. - /// - /// - /// A - /// - public void RegisterNewRegion(Scene scene) - { - m_sceneList.Add(scene.RegionInfo.RegionID, scene); - - m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); - m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); - - scene.EventManager.OnNewClient += StartManaging; - scene.EventManager.OnChatFromClient += SimChatSent; - scene.EventManager.OnRemovePresence += StopManaging; - // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; - scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; - } - - /// - /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. - /// - public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) - { - if (e.Channel != channel) - return; - if (e.Sender == null) - return; - - m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); - - IClientAPI client = e.Sender; - Scene scene = (Scene) e.Scene; - string message = e.Message; - string[] args = e.Message.Split(new char[] {' '}); - - ScenePresence avatar = scene.GetScenePresence(client.AgentId); - - if (!(m_estateModule.IsManager(avatar.UUID))) - { - m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); - view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); - return; - } - - switch (args[0]) - { - case "ci": - case "commit": - commit(message, scene, model, view); - break; - case "dm": - case "diff-mode": - diffmode(scene, model, view); - break; - case "rb": - case "rollback": - rollback(scene, model, view); - break; - case "help": - m_view.DisplayHelpMenu(scene); - break; - default: - view.SendSimChatMessage(scene, "Command not found: " + args[0]); - break; - } - } - - #endregion Public Methods - - #region Other - - /// - /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk. - /// - [Flags] - private enum State - { - NONE = 0, - DIRTY = 1, // The meta entities may not correctly represent the last revision. - SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. - } - - /// - /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. - /// - private struct Work - { - #region Fields - - public Object Data1; //Just space for holding data. - public Object Data2; //Just more space for holding data. - public uint LocalId; //Convenient - public WorkType Type; - public UUID UUID; //Convenient - - #endregion Fields - } - - /// - /// Identifies what the data in struct Work should be used for. - /// - private enum WorkType - { - NONE, - OBJECTATTRIBUTECHANGE, - PRIMITIVEADDED, - OBJECTDUPLICATED, - OBJECTKILLED, - UNDODID, - NEWCLIENT, - SIMCHAT - } - - #endregion Other - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs deleted file mode 100644 index 7f64ebdbf7..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// CMEntityCollection.cs created with MonoDevelop -// User: bongiojp at 10:09 AM 7/7/2008 -// -// Creates, Deletes, Stores ContentManagementEntities -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMEntityCollection - { - #region Fields - - // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or - // old versions of deleted SceneObjectGroups will be stored in this hash table. - // The UUID keys are from the SceneObjectGroup RootPart UUIDs - protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //UUID to ContentManagementEntity - - // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable - // The UUID keys are from the SceneObjectPart that they are supposed to be on. - protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //UUID to AuraMetaEntity - - #endregion Fields - - #region Constructors - - public CMEntityCollection() - { - } - - #endregion Constructors - - #region Public Properties - - public Hashtable Auras - { - get {return m_NewlyCreatedEntityAura; } - } - - public Hashtable Entities - { - get { return m_CMEntityHash; } - } - - #endregion Public Properties - - #region Public Methods - - public bool AddAura(ContentManagementEntity aura) - { - if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) - return false; - m_NewlyCreatedEntityAura.Add(aura.UUID, aura); - return true; - } - - public bool AddEntity(ContentManagementEntity ent) - { - if (m_CMEntityHash.ContainsKey(ent.UUID)) - return false; - m_CMEntityHash.Add(ent.UUID, ent); - return true; - } - - // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash - public System.Collections.ArrayList CheckForMissingEntities(EntityBase[] currList) - { - System.Collections.ArrayList missingList = new System.Collections.ArrayList(); - SceneObjectGroup temp = null; - foreach (EntityBase currObj in currList) - { - if (!(currObj is SceneObjectGroup)) - continue; - temp = (SceneObjectGroup) currObj; - - if (m_CMEntityHash.ContainsKey(temp.UUID)) - { - foreach (SceneObjectPart part in temp.Parts) - if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) - missingList.Add(part); - } - else //Entire group is missing from revision. (and is a new part in region) - { - foreach (SceneObjectPart part in temp.Parts) - missingList.Add(part); - } - } - return missingList; - } - - public void ClearAll() - { - m_CMEntityHash.Clear(); - m_NewlyCreatedEntityAura.Clear(); - } - - // Old uuid and new sceneobjectgroup - public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) - { - AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0,254,0), - part.Scale - ); - m_NewlyCreatedEntityAura.Add(part.UUID, ent); - return ent; - } - - // Old uuid and new sceneobjectgroup - public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) - { - ContentManagementEntity ent = new ContentManagementEntity(group, false); - m_CMEntityHash.Add(group.UUID, ent); - return ent; - } - - public ContentManagementEntity CreateNewEntity(String xml, Scene scene) - { - ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); - if (ent == null) - return null; - m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); - return ent; - } - - public bool RemoveEntity(UUID uuid) - { - if (!m_CMEntityHash.ContainsKey(uuid)) - return false; - m_CMEntityHash.Remove(uuid); - return true; - } - - public bool RemoveNewlyCreatedEntityAura(UUID uuid) - { - if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) - return false; - m_NewlyCreatedEntityAura.Remove(uuid); - return true; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs deleted file mode 100644 index 2fcacddfef..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMModel - { - #region Static Fields - - static float TimeToUpdate = 0; - static float TimeToConvertXml = 0; - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - /// - /// The class that contains all auras and metaentities used in the CMS. - /// - CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); - IContentDatabase m_database = null; - - #endregion Fields - - #region Constructors - - public CMModel() - { - } - - #endregion Constructors - - #region Public Properties - - public CMEntityCollection MetaEntityCollection - { - get { return m_MetaEntityCollection; } - } - - #endregion Public Properties - - #region Public Methods - - /// - /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity - /// it is a new part that must have a green aura (for diff mode). - /// Returns list of ContentManagementEntities - /// - public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) - { - ArrayList missingList = null; - ArrayList newList = new ArrayList(); - - m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); - - //Check if the current scene has groups not included in the current list of MetaEntities - //If so, then the current scene's parts that are new should be marked green. - missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); - - foreach (Object missingPart in missingList) - { - if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) - continue; - newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); - } - m_log.Info("Number of missing objects found: " + newList.Count); - return newList; - } - - /// - /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. - /// - public void CommitRegion(Scene scene, String logMessage) - { - m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); - m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); - m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName); - } - - public void DeleteAllMetaObjects() - { - m_MetaEntityCollection.ClearAll(); - } - - public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid) - { - ContentManagementEntity ent = GetMetaGroupByPrim(uuid); - return ent; - } - - //-------------------------------- HELPERS --------------------------------------------------------------------// - public ContentManagementEntity GetMetaGroupByPrim(UUID uuid) - { - foreach (Object ent in m_MetaEntityCollection.Entities.Values) - { - if (((ContentManagementEntity)ent).HasChildPrim(uuid)) - return (ContentManagementEntity)ent; - } - return null; - } - - public void Initialise(string database) - { - if (database == "FileSystemDatabase") - m_database = new FileSystemDatabase(); - else if (database == "GitDatabase") - m_database = new GitDatabase(); - } - - public void InitialiseDatabase(Scene scene, string dir) - { - m_database.Initialise(scene, dir); - } - - /// - /// Should be called just once to finish initializing the database. - /// - public void PostInitialise() - { - m_database.PostInitialise(); - } - - /// - /// Removes the green aura when an a new scene object group is deleted. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with new parts not revisioned that have been deleted. - SceneObjectPart[] parts = group.Parts; - for (int i = 0; i < parts.Length; i++) - { - if (m_MetaEntityCollection.Auras.ContainsKey(parts[i].UUID)) - m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(parts[i].UUID); - } - } - - /// - /// Retrieves the latest revision of a region in xml form, - /// converts it to scene object groups and scene presences, - /// swaps the current scene's entity list with the revision's list. - /// Note: Since deleted objects while - /// - public void RollbackRegion(Scene scene) - { - System.Collections.ArrayList xmllist = null; - SceneObjectGroup temp = null; - System.Collections.Hashtable deleteListUUIDs = new Hashtable(); -// Dictionary SearchList = new Dictionary(); - Dictionary ReplacementList = new Dictionary(); - int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); -// EntityBase[] searchArray; - - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); - if (xmllist == null) - { - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); - return; - } - - m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); - m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); - m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); - - m_log.ErrorFormat("[CMMODEL]: 1"); - - foreach (string xml in xmllist) - { - try - { - temp = SceneObjectSerializer.FromXml2Format(xml); - temp.SetScene(scene); - - SceneObjectPart[] parts = temp.Parts; - for (int i = 0; i < parts.Length; i++) - parts[i].RegionHandle = scene.RegionInfo.RegionHandle; - - ReplacementList.Add(temp.UUID, (EntityBase)temp); - } - catch (Exception e) - { - m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e); - } - } - - //If in scene but not in revision and not a client, remove them - while (true) - { - try - { - foreach (EntityBase entity in scene.GetEntities()) - { - if (entity == null) - continue; - - if (entity is ScenePresence) - { - ReplacementList.Add(entity.UUID, entity); - continue; - } - else //if (!ReplacementList.ContainsKey(entity.UUID)) - deleteListUUIDs.Add(entity.UUID, 0); - } - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: " + e); - deleteListUUIDs.Clear(); - ReplacementList.Clear(); - continue; - } - break; - } - - foreach (UUID uuid in deleteListUUIDs.Keys) - { - try - { - // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. - ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); - scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); - scene.SendKillObject(scene.Entities[uuid].LocalId); - scene.SceneGraph.DeleteSceneObject(uuid, false); - ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroupFromScene(false); - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); - } - } - - lock (scene) - { - scene.Entities.Clear(); - - foreach (KeyValuePair kvp in ReplacementList) - { - scene.Entities.Add(kvp.Value); - } - } - - foreach (EntityBase ent in ReplacementList.Values) - { - try - { - if (!(ent is SceneObjectGroup)) - continue; - - if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0) - ((SceneObjectGroup)ent).ApplyPhysics(true); - ((SceneObjectGroup)ent).AttachToBackup(); - ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. - //((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); - ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(new List(){SceneObjectPartSyncProperties.FullUpdate}); //don't know what properties to taint, so just taint all - } - catch(Exception e) - { - m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e); - } - } - m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); - scene.Backup(true); - } - - /// - /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences - /// and display the differences to clients. - /// - public void UpdateCMEntities(Scene scene) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - System.Collections.ArrayList xmllist = null; - m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID); - xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID); - m_log.Info("[FSDB]: got list"); - if (xmllist == null) - return; - - Stopwatch y = new Stopwatch(); - y.Start(); - foreach (string xml in xmllist) - m_MetaEntityCollection.CreateNewEntity(xml, scene); - y.Stop(); - TimeToConvertXml += y.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); - - m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); - CheckForNewEntitiesMissingAuras(scene); - - x.Stop(); - TimeToUpdate += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); - } - - /// - /// Detects if a scene object group from the scene list has moved or changed scale. The green aura - /// that surrounds the object is then moved or scaled with the group. - /// - public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) - { - System.Collections.ArrayList auraList = new System.Collections.ArrayList(); - if (group == null) - return null; - - SceneObjectPart[] parts = group.Parts; - for (int i = 0; i < parts.Length; i++) - { - SceneObjectPart part = parts[i]; - if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) - { - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0, 254, 0), part.Scale); - ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); - auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); - } - } - - return auraList; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs deleted file mode 100644 index 3807ccda47..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// CMView.cs created with MonoDevelop -// User: bongiojp at 11:57 AM 7/3/2008 -// -// To change standard headers go to Edit->Preferences->Coding->Standard Headers -// - -#endregion Header - -using System; -using System.Collections; -using System.Collections.Generic; - -using OpenMetaverse; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class CMView - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - CMModel m_model = null; - - #endregion Fields - - #region Constructors - - public CMView() - { - } - - #endregion Constructors - - #region Public Methods - - // Auras To - public void DisplayAuras(CMEntityCollection auraCollection) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - - // Auras To Client - public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) - { - foreach (Object ent in auraCollection.Auras.Values) - ((AuraMetaEntity)ent).SendFullUpdate(client); - } - - // Auras from List To ALL - public void DisplayAuras(ArrayList list) - { - foreach (Object ent in list) - { - m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); - ((AuraMetaEntity)ent).SendFullUpdateToAll(); - } - } - - // Entities to ALL - public void DisplayEntities(CMEntityCollection entityCollection) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entities to Client - public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) - { - foreach (Object ent in entityCollection.Entities.Values) - ((ContentManagementEntity)ent).SendFullDiffUpdate(client); - } - - // Entities from List to ALL - public void DisplayEntities(ArrayList list) - { - foreach (Object ent in list) - ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); - } - - // Entity to ALL - public void DisplayEntity(ContentManagementEntity ent) - { - ent.SendFullDiffUpdateToAll(); - } - - public void DisplayHelpMenu(Scene scene) - { - string menu = "Menu:\n"; - menu += "commit (ci) - saves current state of the region to a database on the server\n"; - menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n"; - SendSimChatMessage(scene, menu); - } - - public void DisplayMetaEntity(UUID uuid) - { - ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); - if (group != null) - group.SendFullDiffUpdateToAll(); - } - - /// - /// update all clients of red/green/blue auras and meta entities that the model knows about. - /// - public void DisplayRecentChanges() - { - m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); - DisplayEntities(m_model.MetaEntityCollection); - DisplayAuras(m_model.MetaEntityCollection); - } - - public void Hide(ContentManagementEntity ent) - { - ent.HideFromAll(); - } - - public void HideAllAuras() - { - foreach (Object obj in m_model.MetaEntityCollection.Auras.Values) - ((MetaEntity)obj).HideFromAll(); - } - - public void HideAllMetaEntities() - { - foreach (Object obj in m_model.MetaEntityCollection.Entities.Values) - ((ContentManagementEntity)obj).HideFromAll(); - } - - public void Initialise(CMModel model) - { - m_model = model; - } - - /// - /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. - /// If it's a new scene object, any green aura attached to it is deleted. - /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will - /// figure out that there should be a red aura and not a blue aura/beam. - /// - public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) - { - // Deal with revisioned parts that have been deleted. - if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) - ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); - - // Deal with new parts not revisioned that have been deleted. - foreach (SceneObjectPart part in group.Parts) - if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) - ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); - } - - public void SendMetaEntitiesToNewClient(IClientAPI client) - { - } - - public void SendSimChatMessage(Scene scene, string message) - { - scene.SimChat(Utils.StringToBytes(message), - ChatTypeEnum.Broadcast, 0, new Vector3(0,0,0), "Content Manager", UUID.Zero, false); - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs deleted file mode 100644 index 0248f368f2..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class ContentManagementEntity : MetaEntity - { - #region Static Fields - -// static float TimeToDiff = 0; -// static float TimeToCreateEntities = 0; - - #endregion Static Fields - - #region Fields - - protected Dictionary m_AuraEntities = new Dictionary(); - protected Dictionary m_BeamEntities = new Dictionary(); - - // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. - // This can come in handy. - protected SceneObjectGroup m_UnchangedEntity = null; - - /// - /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. - /// - bool DiffersFromSceneGroup = false; - - #endregion Fields - - #region Constructors - - public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) - : base(Unchanged, false) - { - m_UnchangedEntity = Unchanged.Copy(false); - } - - public ContentManagementEntity(string objectXML, Scene scene, bool physics) - : base(objectXML, scene, false) - { - m_UnchangedEntity = SceneObjectSerializer.FromXml2Format(objectXML); - } - - #endregion Constructors - - #region Public Properties - - public SceneObjectGroup UnchangedEntity - { - get { return m_UnchangedEntity; } - } - - #endregion Public Properties - - #region Private Methods - - /// - /// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid. - /// - private bool ContainsKey(List list, UUID uuid) - { - foreach (EntityBase part in list) - if (part.UUID == uuid) - return true; - return false; - } - - private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List list, UUID uuid) - { - foreach (EntityBase ent in list) - { - if (ent is SceneObjectGroup) - if (ent.UUID == uuid) - return (SceneObjectGroup)ent; - } - return null; - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately. - /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. - /// - public void FindDifferences() - { - List sceneEntityList = new List(m_Entity.Scene.GetEntities()); - DiffersFromSceneGroup = false; - // if group is not contained in scene's list - if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Parts) - { - // if scene list no longer contains this part, display translucent part and mark with red aura - if (!ContainsKey(sceneEntityList, part.UUID)) - { - // if already displaying a red aura over part, make sure its red - if (m_AuraEntities.ContainsKey(part.UUID)) - { - m_AuraEntities[part.UUID].SetAura(new Vector3(254, 0, 0), part.Scale); - } - else - { - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - part.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254, 0, 0), - part.Scale - ); - m_AuraEntities.Add(part.UUID, auraGroup); - } - SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); - SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); - } - // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id - } - - // a deleted part has no where to point a beam particle system, - // if a metapart had a particle system (maybe it represented a moved part) remove it - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - - DiffersFromSceneGroup = true; - } - // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately - else - { - MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); - } - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. - /// - public bool HasChildPrim(UUID uuid) - { - return m_UnchangedEntity.ContainsPart(uuid); - } - - /// - /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. - /// - public bool HasChildPrim(uint localID) - { - foreach (SceneObjectPart part in m_UnchangedEntity.Parts) - if (part.LocalId == localID) - return true; - - return false; - } - - public override void Hide(IClientAPI client) - { - base.Hide(client); - foreach (MetaEntity group in m_AuraEntities.Values) - group.Hide(client); - foreach (MetaEntity group in m_BeamEntities.Values) - group.Hide(client); - } - - public override void HideFromAll() - { - base.HideFromAll(); - foreach (MetaEntity group in m_AuraEntities.Values) - group.HideFromAll(); - foreach (MetaEntity group in m_BeamEntities.Values) - group.HideFromAll(); - } - - /// - /// Returns true if there was a change between meta entity and the entity group, false otherwise. - /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). - /// - public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) - { - SceneObjectPart sceneEntityPart; - SceneObjectPart metaEntityPart; - Diff differences; - bool changed = false; - - // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user - // had originally saved. - // m_Entity will NOT necessarily be the same entity as the user had saved. - foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Parts) - { - //This is the part that we use to show changes. - metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); - if (sceneEntityGroup.ContainsPart(UnchangedPart.UUID)) - { - sceneEntityPart = sceneEntityGroup.GetChildPart(UnchangedPart.UUID); - differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); - if (differences != Diff.NONE) - metaEntityPart.Text = "CHANGE: " + differences.ToString(); - if (differences != 0) - { - // Root Part that has been modified - if ((differences & Diff.POSITION) > 0) - { - // If the position of any part has changed, make sure the RootPart of the - // meta entity is pointing with a beam particle system - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, - m_UnchangedEntity.RootPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - sceneEntityPart, - new Vector3(0, 0, 254) - ); - m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); - } - - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(0, 0, 254), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - else // no differences between scene part and meta part - { - if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) - { - m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); - m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); - } - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - SetPartTransparency(metaEntityPart, MetaEntity.NONE); - } - } - else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. - { - if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) - { - m_AuraEntities[UnchangedPart.UUID].HideFromAll(); - m_AuraEntities.Remove(UnchangedPart.UUID); - } - AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, - UnchangedPart.GetWorldPosition(), - MetaEntity.TRANSLUCENT, - new Vector3(254, 0, 0), - UnchangedPart.Scale - ); - m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); - SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); - - DiffersFromSceneGroup = true; - } - } - - return changed; - } - - public void SendFullAuraUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullAuraUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (AuraMetaEntity group in m_AuraEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullBeamUpdate(IClientAPI client) - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdate(client); - } - } - - public void SendFullBeamUpdateToAll() - { - if (DiffersFromSceneGroup) - { - foreach (BeamMetaEntity group in m_BeamEntities.Values) - group.SendFullUpdateToAll(); - } - } - - public void SendFullDiffUpdate(IClientAPI client) - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdate(client); - SendFullAuraUpdate(client); - SendFullBeamUpdate(client); - } - } - - public void SendFullDiffUpdateToAll() - { - FindDifferences(); - if (DiffersFromSceneGroup) - { - SendFullUpdateToAll(); - SendFullAuraUpdateToAll(); - SendFullBeamUpdateToAll(); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs deleted file mode 100644 index 3d1c346dc8..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// ContentManagementModule.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Threading; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class ContentManagementModule : IRegionModule - { - #region Static Fields - - private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - bool initialised = false; - CMController m_control = null; - bool m_enabled = false; - CMModel m_model = null; - bool m_posted = false; - CMView m_view = null; - - #endregion Fields - - #region Public Properties - - public bool IsSharedModule - { - get { return true; } - } - - public string Name - { - get { return "ContentManagementModule"; } - } - - #endregion Public Properties - - #region Public Methods - - public void Close() - { - } - - public void Initialise(Scene scene, IConfigSource source) - { - string databaseDir = "./"; - string database = "FileSystemDatabase"; - int channel = 345; - try - { - if (source.Configs["CMS"] == null) - return; - - m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); - databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); - database = source.Configs["CMS"].GetString("database", database); - channel = source.Configs["CMS"].GetInt("channel", channel); - - if (database != "FileSystemDatabase" && database != "GitDatabase") - { - m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); - m_enabled = false; - } - } - catch (Exception e) - { - m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); - m_enabled = false; - } - - if (!m_enabled) - { - m_log.Info("[Content Management]: Content Management System is not Enabled."); - return; - } - - lock (this) - { - if (!initialised) //only init once - { - m_view = new CMView(); - m_model = new CMModel(); - m_control = new CMController(m_model, m_view, scene, channel); - m_model.Initialise(database); - m_view.Initialise(m_model); - - initialised = true; - m_model.InitialiseDatabase(scene, databaseDir); - } - else - { - m_model.InitialiseDatabase(scene, databaseDir); - m_control.RegisterNewRegion(scene); - } - } - } - - public void PostInitialise() - { - if (! m_enabled) - return; - - lock (this) - { - if (!m_posted) //only post once - { - m_model.PostInitialise(); - m_posted = true; - } - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs deleted file mode 100644 index a3d7977006..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// FileSystemDatabase.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class FileSystemDatabase : IContentDatabase - { - #region Static Fields - - public static float TimeToDownload = 0; - public static float TimeToSave = 0; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - private string m_repodir = null; - private Dictionary m_scenes = new Dictionary(); - private Dictionary m_serialiser = new Dictionary(); - - #endregion Fields - - #region Constructors - - public FileSystemDatabase() - { - } - - #endregion Constructors - - #region Private Methods - - // called by postinitialise - private void CreateDirectory() - { - string scenedir; - if (!Directory.Exists(m_repodir)) - Directory.CreateDirectory(m_repodir); - - foreach (UUID region in m_scenes.Keys) - { - scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - } - } - - // called by postinitialise - private void SetupSerialiser() - { - if (m_serialiser.Count == 0) - { - foreach (UUID region in m_scenes.Keys) - { - m_serialiser.Add(region, m_scenes[region].RequestModuleInterface()); - } - } - } - - #endregion Private Methods - - #region Public Methods - - public int GetMostRecentRevision(UUID regionid) - { - return NumOfRegionRev(regionid); - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream(filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + - Slash.DirectorySeparatorChar + "heightmap.r32"; - FileStream fs = new FileStream(filename, FileMode.Open); - StreamReader sr = new StreamReader(fs); - String result = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - return result; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - System.Collections.ArrayList objectList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - //int primCount = 0; - //SceneObjectGroup obj = null; - - if (File.Exists(filename)) - { - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - objectList.Add(aPrimNode.OuterXml); - } - return objectList; - } - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - int revision = NumOfRegionRev(regionid); - m_log.Info("[FSDB]: found revisions:" + revision); - System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); - string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + - + revision + Slash.DirectorySeparatorChar + "objects.xml"; - XmlDocument doc = new XmlDocument(); - XmlNode rootNode; - - m_log.Info("[FSDB]: Checking if " + filename + " exists."); - if (File.Exists(filename)) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - XmlTextReader reader = new XmlTextReader(filename); - reader.WhitespaceHandling = WhitespaceHandling.None; - doc.Load(reader); - reader.Close(); - rootNode = doc.FirstChild; - - foreach (XmlNode aPrimNode in rootNode.ChildNodes) - { - xmlList.Add(aPrimNode.OuterXml); - } - - x.Stop(); - TimeToDownload += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); - - return xmlList; - } - return null; - } - - public void Initialise(Scene scene, string dir) - { - lock (this) - { - if (m_repodir == null) - m_repodir = dir; - } - lock (m_scenes) - m_scenes.Add(scene.RegionInfo.RegionID, scene); - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID regionid) - { - SortedDictionary revisionDict = new SortedDictionary(); - - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - string[] directories = Directory.GetDirectories(scenedir); - - FileStream fs = null; - StreamReader sr = null; - String logMessage = ""; - String logLocation = ""; - foreach (string revisionDir in directories) - { - try - { - logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; - fs = new FileStream(logLocation, FileMode.Open); - sr = new StreamReader(fs); - logMessage = sr.ReadToEnd(); - sr.Close(); - fs.Close(); - revisionDict.Add(revisionDir, logMessage); - } - catch (Exception) - { - } - } - - return revisionDict; - } - - public int NumOfRegionRev(UUID regionid) - { - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - m_log.Info("[FSDB]: Reading scene dir: " + scenedir); - string[] directories = Directory.GetDirectories(scenedir); - return directories.Length; - } - - // Run once and only once. - public void PostInitialise() - { - SetupSerialiser(); - - m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); - CreateDirectory(); - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - m_log.Info("[FSDB]: ..............................."); - string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); - if (!Directory.Exists(scenedir)) - Directory.CreateDirectory(scenedir); - - int newRevisionNum = GetMostRecentRevision(regionid)+1; - string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; - - m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); - if (!Directory.Exists(revisiondir)) - Directory.CreateDirectory(revisiondir); - - try { - Stopwatch x = new Stopwatch(); - x.Start(); - if (m_scenes.ContainsKey(regionid)) - { - m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); - } - x.Stop(); - TimeToSave += x.ElapsedMilliseconds; - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); - m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); - return; - } - - try { - // Finish by writing log message. - FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); - StreamWriter sw = new StreamWriter(file); - sw.Write(logMessage); - sw.Close(); - } - catch (Exception e) - { - m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); - return; - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs deleted file mode 100644 index 80a0a939d9..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// GitDatabase.cs -// -// -// - -#endregion Header - -using System; -using System.Collections.Generic; -using System.IO; -using Slash = System.IO.Path; -using System.Reflection; -using System.Xml; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.World.Serialiser; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - /// - /// Just a stub :-( - /// - public class GitDatabase : IContentDatabase - { - #region Constructors - - public GitDatabase() - { - } - - #endregion Constructors - - #region Public Methods - - public SceneObjectGroup GetMostRecentObjectRevision(UUID id) - { - return null; - } - - public int GetMostRecentRevision(UUID regionid) - { - return 0; - } - - public SceneObjectGroup GetObjectRevision(UUID id, int revision) - { - return null; - } - - public System.Collections.ArrayList GetObjectsFromRegion(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid) - { - return null; - } - - public string GetRegionObjectHeightMap(UUID regionid, int revision) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid) - { - return null; - } - - public string GetRegionObjectXML(UUID regionid, int revision) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) - { - return null; - } - - public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) - { - return null; - } - - public bool InRepository(UUID id) - { - return false; - } - - public void Initialise(Scene scene, String dir) - { - } - - public System.Collections.Generic.SortedDictionary ListOfObjectRevisions(UUID id) - { - return null; - } - - public System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id) - { - return null; - } - - public int NumOfObjectRev(UUID id) - { - return 0; - } - - public int NumOfRegionRev(UUID regionid) - { - return 0; - } - - public void PostInitialise() - { - } - - public void SaveObject(SceneObjectGroup entity) - { - } - - public void SaveRegion(UUID regionid, string regionName, string logMessage) - { - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs deleted file mode 100644 index fc1f1156ca..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// IContentDatabase.cs -// User: bongiojp -// -// -// - -#endregion Header - -using System; -using OpenMetaverse; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public interface IContentDatabase - { - #region Methods - - /// - /// Returns the most recent revision number of a region. - /// - int GetMostRecentRevision(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid); - - string GetRegionObjectHeightMap(UUID regionid, int revision); - - /// - /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. - /// - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid); - - System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision); - - /// - /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. - /// Initialise should be called one for each region to be contained in the database. The directory should be the full path - /// to the repository and will only be defined once, regardless of how many times the method is called. - /// - void Initialise(Scene scene, String dir); - - /// - /// Returns a list of the revision numbers and corresponding log messages for a given region. - /// - System.Collections.Generic.SortedDictionary ListOfRegionRevisions(UUID id); - - /// - /// Returns the total number of revisions saved for a specific region. - /// - int NumOfRegionRev(UUID regionid); - - /// - /// Should be called once after Initialise has been called. - /// - void PostInitialise(); - - /// - /// Saves the Region terrain map and objects within the region as xml to the database. - /// - void SaveRegion(UUID regionid, string regionName, string logMessage); - - #endregion Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs deleted file mode 100644 index c7b1ed79cc..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class MetaEntity - { - #region Constants - - public const float INVISIBLE = .95f; - - // Settings for transparency of metaentity - public const float NONE = 0f; - public const float TRANSLUCENT = .5f; - - #endregion Constants - - #region Static Fields - - //private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Fields - - protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. - protected uint m_metaLocalid; - - #endregion Fields - - #region Constructors - - public MetaEntity() - { - } - - /// - /// Makes a new meta entity by copying the given scene object group. - /// The physics boolean is just a stub right now. - /// - public MetaEntity(SceneObjectGroup orig, bool physics) - { - m_Entity = orig.Copy(false); - Initialize(physics); - } - - /// - /// Takes an XML description of a scene object group and converts it to a meta entity. - /// - public MetaEntity(string objectXML, Scene scene, bool physics) - { - m_Entity = SceneObjectSerializer.FromXml2Format(objectXML); - m_Entity.SetScene(scene); - Initialize(physics); - } - - #endregion Constructors - - #region Public Properties - - public SceneObjectPart[] Parts - { - get { return m_Entity.Parts; } - } - - public uint LocalId - { - get { return m_Entity.LocalId; } - set { m_Entity.LocalId = value; } - } - - public SceneObjectGroup ObjectGroup - { - get { return m_Entity; } - } - - public int PrimCount - { - get { return m_Entity.PrimCount; } - } - - public SceneObjectPart RootPart - { - get { return m_Entity.RootPart; } - } - - public Scene Scene - { - get { return m_Entity.Scene; } - } - - public UUID UUID - { - get { return m_Entity.UUID; } - set { m_Entity.UUID = value; } - } - - #endregion Public Properties - - #region Protected Methods - - // The metaentity objectgroup must have unique localids as well as unique uuids. - // localids are used by the client to refer to parts. - // uuids are sent to the client and back to the server to identify parts on the server side. - /// - /// Changes localids and uuids of m_Entity. - /// - protected void Initialize(bool physics) - { - //make new uuids - Dictionary parts = new Dictionary(); - - foreach (SceneObjectPart part in m_Entity.Parts) - { - part.ResetIDs(part.LinkNum); - parts.Add(part.UUID, part); - } - - //finalize - m_Entity.RootPart.PhysActor = null; - foreach (SceneObjectPart part in parts.Values) - m_Entity.AddPart(part); - } - - #endregion Protected Methods - - #region Public Methods - - /// - /// Hides the metaentity from a single client. - /// - public virtual void Hide(IClientAPI client) - { - //This deletes the group without removing from any databases. - //This is important because we are not IN any database. - //m_Entity.FakeDeleteGroup(); - foreach (SceneObjectPart part in m_Entity.Parts) - client.SendKillObject(m_Entity.RegionHandle, part.LocalId); - } - - /// - /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. - /// - public virtual void HideFromAll() - { - foreach (SceneObjectPart part in m_Entity.Parts) - { - m_Entity.Scene.ForEachClient( - delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } - ); - } - } - - public void SendFullUpdate(IClientAPI client) - { - // Not sure what clientFlags should be but 0 seems to work - SendFullUpdate(client, 0); - } - - public void SendFullUpdate(IClientAPI client, uint clientFlags) - { - m_Entity.SendFullUpdateToClient(client); - } - - public void SendFullUpdateToAll() - { - m_Entity.Scene.ForEachClient( - delegate(IClientAPI controller) - { m_Entity.SendFullUpdateToClient(controller); } - ); - } - - /// - /// Makes a single SceneObjectPart see through. - /// - /// - /// A - /// The part to make see through - /// - /// - /// A - /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. - /// - public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) - { - Primitive.TextureEntry tex = null; - Color4 texcolor; - try - { - tex = part.Shape.Textures; - texcolor = new Color4(); - } - catch(Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); - return; - } - - for (uint i = 0; i < tex.FaceTextures.Length; i++) - { - try { - if (tex.FaceTextures[i] != null) - { - texcolor = tex.FaceTextures[i].RGBA; - texcolor.A = transparencyAmount; - tex.FaceTextures[i].RGBA = texcolor; - } - } - catch (Exception) - { - //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); - continue; - } - } - try { - texcolor = tex.DefaultTexture.RGBA; - texcolor.A = transparencyAmount; - tex.DefaultTexture.RGBA = texcolor; - part.Shape.TextureEntry = tex.GetBytes(); - } - catch (Exception) - { - //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); - } - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs deleted file mode 100644 index 2c5093f58d..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - public class PointMetaEntity : MetaEntity - { - #region Constructors - - public PointMetaEntity(Scene scene, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, UUID.Random(), groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - public PointMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency) - : base() - { - CreatePointEntity(scene, uuid, groupPos); - SetPartTransparency(m_Entity.RootPart, transparency); - } - - #endregion Constructors - - #region Private Methods - - private void CreatePointEntity(Scene scene, UUID uuid, Vector3 groupPos) - { - SceneObjectPart y = new SceneObjectPart(); - - //Initialize part - y.Name = "Very Small Point"; - y.RegionHandle = scene.RegionInfo.RegionHandle; - y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; - y.OwnerID = UUID.Zero; - y.CreatorID = UUID.Zero; - y.LastOwnerID = UUID.Zero; - y.UUID = uuid; - - y.Shape = PrimitiveBaseShape.CreateBox(); - y.Scale = new Vector3(0.01f,0.01f,0.01f); - y.LastOwnerID = UUID.Zero; - y.GroupPosition = groupPos; - y.OffsetPosition = Vector3.Zero; - y.RotationOffset = Quaternion.Identity; - y.Velocity = Vector3.Zero; - y.AngularVelocity = Vector3.Zero; - y.Acceleration = Vector3.Zero; - - y.Flags = 0; - y.TrimPermissions(); - - //Initialize group and add part as root part - SceneObjectGroup x = new SceneObjectGroup(y); - x.SetScene(scene); - x.RegionHandle = scene.RegionInfo.RegionHandle; - x.SetScene(scene); - - m_Entity = x; - } - - #endregion Private Methods - } -} diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/README b/OpenSim/Region/OptionalModules/ContentManagementSystem/README deleted file mode 100644 index 1a69fef231..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/README +++ /dev/null @@ -1,52 +0,0 @@ -This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a -reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/ -directory. - -To compile: nant -To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory. - - --------------------------------------------------------------------------------------------------------------------- -To build the libgit.so file: - -#Download GIT git repository -$ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git -$ cd git - -#Compile GIT -#Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC) -$ autoconf -$ ./configure -$ CFLAGS="-g -O2 -Wall -c -fPIC" make - -#Copy necessary object files (and some not so necessary) to their own directory for shared object file creation -$ mkdir ../libgit-objects -$ cp builtin*.o ../libgit-objects -$ cp xdiff/*.o ../libgit-objects -$ cp libgit.a ../libgit-objects - -#Remove the main symbol from any object files (like git.o) -$ cd ../libgit-objects -$ strip -N main *.o - -#Uncompress the plumbing objects from archive created by git -$ ar x libgit.a - -#Create shared object file from all objects (including the zlib library) -$ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o - - -#You can also just copy the following commands into a file and run as a script inside the git directory - -make clean -autoconf -./configure -CFLAGS="-g -O2 -Wall -c -fPIC" make -mkdir libgit-objects -cp builtin*.o libgit-objects -cp xdiff/*.o libgit-objects -cp libgit.a libgit-objects -cd libgit-objects -strip -N main *.o -ar x libgit.a -ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs deleted file mode 100644 index a6afa5ac74..0000000000 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#region Header - -// SceneObjectGroupDiff.cs -// User: bongiojp - -#endregion Header - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; - -using OpenMetaverse; - -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; - -using log4net; - -namespace OpenSim.Region.OptionalModules.ContentManagement -{ - #region Enumerations - - [Flags] - public enum Diff - { - NONE = 0, - FACECOLOR = 1, - SHAPE = 1<<1, - MATERIAL = 1<<2, - TEXTURE = 1<<3, - SCALE = 1<<4, - POSITION = 1<<5, - OFFSETPOSITION = 1<<6, - ROTATIONOFFSET = 1<<7, - ROTATIONALVELOCITY = 1<<8, - ACCELERATION = 1<<9, - ANGULARVELOCITY = 1<<10, - VELOCITY = 1<<11, - OBJECTOWNER = 1<<12, - PERMISSIONS = 1<<13, - DESCRIPTION = 1<<14, - NAME = 1<<15, - SCRIPT = 1<<16, - CLICKACTION = 1<<17, - PARTICLESYSTEM = 1<<18, - GLOW = 1<<19, - SALEPRICE = 1<<20, - SITNAME = 1<<21, - SITTARGETORIENTATION = 1<<22, - SITTARGETPOSITION = 1<<23, - TEXT = 1<<24, - TOUCHNAME = 1<<25 - } - - #endregion Enumerations - - public static class Difference - { - #region Static Fields - - static float TimeToDiff = 0; -// private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - #endregion Static Fields - - #region Private Methods - - private static bool AreQuaternionsEquivalent(Quaternion first, Quaternion second) - { - Vector3 firstVector = llRot2Euler(first); - Vector3 secondVector = llRot2Euler(second); - return AreVectorsEquivalent(firstVector, secondVector); - } - - private static bool AreVectorsEquivalent(Vector3 first, Vector3 second) - { - if (TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) - && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) - && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) - ) - return true; - else - return false; - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - private static double NormalizeAngle(double angle) - { - angle = angle % (Math.PI * 2); - if (angle < 0) angle = angle + Math.PI * 2; - return angle; - } - - private static int TruncateSignificant(float num, int digits) - { - return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); - // return (int) ((num * (10*digits))/10*digits); - } - - // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs - // Also changed the original function from LSL_Types to LL types - private static Vector3 llRot2Euler(Quaternion r) - { - Quaternion t = new Quaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W); - double m = (t.X + t.Y + t.Z + t.W); - if (m == 0) return new Vector3(); - double n = 2 * (r.Y * r.W + r.X * r.Z); - double p = m * m - n * n; - if (p > 0) - return new Vector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))), - (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), - (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W)))); - else if (n > 0) - return new Vector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - else - return new Vector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); - } - - #endregion Private Methods - - #region Public Methods - - /// - /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts - /// and returns a Diff bitmask which details what the differences are. - /// - public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) - { - Stopwatch x = new Stopwatch(); - x.Start(); - - Diff result = 0; - - // VECTOR COMPARISONS - if (!AreVectorsEquivalent(first.Acceleration, second.Acceleration)) - result |= Diff.ACCELERATION; - if (!AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) - result |= Diff.POSITION; - if (!AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) - result |= Diff.ANGULARVELOCITY; - if (!AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) - result |= Diff.OFFSETPOSITION; - if (!AreVectorsEquivalent(first.Scale, second.Scale)) - result |= Diff.SCALE; - if (!AreVectorsEquivalent(first.Velocity, second.Velocity)) - result |= Diff.VELOCITY; - - - // QUATERNION COMPARISONS - if (!AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) - result |= Diff.ROTATIONOFFSET; - - - // MISC COMPARISONS (UUID, Byte) - if (first.ClickAction != second.ClickAction) - result |= Diff.CLICKACTION; - if (first.OwnerID != second.OwnerID) - result |= Diff.OBJECTOWNER; - - - // STRING COMPARISONS - if (first.Description != second.Description) - result |= Diff.DESCRIPTION; - if (first.Material != second.Material) - result |= Diff.MATERIAL; - if (first.Name != second.Name) - result |= Diff.NAME; - if (first.SitName != second.SitName) - result |= Diff.SITNAME; - if (first.Text != second.Text) - result |= Diff.TEXT; - if (first.TouchName != second.TouchName) - result |= Diff.TOUCHNAME; - - x.Stop(); - TimeToDiff += x.ElapsedMilliseconds; - //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); - - return result; - } - - #endregion Public Methods - } -} diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs index 471b90f0e1..c1957e2cb8 100644 --- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs +++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs @@ -76,22 +76,24 @@ namespace OpenSim.Region.OptionalModules public void AddRegion(Scene scene) { - if(!m_enabled) + if (!m_enabled) { return; } scene.Permissions.OnRezObject += CanRezObject; scene.Permissions.OnObjectEntry += CanObjectEnter; scene.Permissions.OnDuplicateObject += CanDuplicateObject; + m_log.DebugFormat("[PRIM LIMITS]: Region {0} added", scene.RegionInfo.RegionName); } public void RemoveRegion(Scene scene) { - if(m_enabled) + if (m_enabled) { return; } + scene.Permissions.OnRezObject -= CanRezObject; scene.Permissions.OnObjectEntry -= CanObjectEnter; scene.Permissions.OnDuplicateObject -= CanDuplicateObject; @@ -104,13 +106,11 @@ namespace OpenSim.Region.OptionalModules private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) { - // This may be a little long winded and can probably be optomized - int usedPrims = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).PrimCounts.Total; - LandData landData = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).LandData; - int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * - (float)scene.RegionInfo.ObjectCapacity * (float)scene.RegionInfo.RegionSettings.ObjectBonus); + ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); + int usedPrims = lo.PrimCounts.Total; + int simulatorCapacity = lo.GetSimulatorMaxPrimCount(); - if(objectCount + usedPrims > simulatorCapacity) + if (objectCount + usedPrims > simulatorCapacity) { m_dialogModule.SendAlertToUser(owner, "Unable to rez object because the parcel is too full"); return false; @@ -118,7 +118,7 @@ namespace OpenSim.Region.OptionalModules return true; } - //OnMoveObject + private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) { SceneObjectPart obj = scene.GetSceneObjectPart(objectID); @@ -126,11 +126,9 @@ namespace OpenSim.Region.OptionalModules int objectCount = obj.ParentGroup.PrimCount; ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); - - int usedPrims=newParcel.PrimCounts.Total; - LandData landData = newParcel.LandData; - int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * - (float)scene.RegionInfo.ObjectCapacity * (float)scene.RegionInfo.RegionSettings.ObjectBonus); + + int usedPrims = newParcel.PrimCounts.Total; + int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount(); // The prim hasn't crossed a region boundry so we don't need to worry // about prim counts here @@ -138,36 +136,39 @@ namespace OpenSim.Region.OptionalModules { return true; } + // Prim counts are determined by the location of the root prim. if we're // moving a child prim, just let it pass if(!obj.IsRoot) { return true; } - // Add Special Case here for temporary prims + + // TODO: Add Special Case here for temporary prims if(objectCount + usedPrims > simulatorCapacity) { m_dialogModule.SendAlertToUser(obj.OwnerID, "Unable to move object because the destination parcel is too full"); return false; } + return true; } + //OnDuplicateObject private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition) { - // This may be a little long winded and can probably be optomized - int usedPrims = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).PrimCounts.Total; - LandData landData = scene.LandChannel.GetLandObject(objectPosition.X,objectPosition.Y).LandData; - int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * - (float)scene.RegionInfo.ObjectCapacity * (float)scene.RegionInfo.RegionSettings.ObjectBonus); + ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); + int usedPrims = lo.PrimCounts.Total; + int simulatorCapacity = lo.GetSimulatorMaxPrimCount(); if(objectCount + usedPrims > simulatorCapacity) { m_dialogModule.SendAlertToUser(owner, "Unable to duplicate object because the parcel is too full"); return false; } + return true; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 122ad40719..eed64506ac 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -28,10 +28,14 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Net; +using System.IO; +using System.Text; using log4net; using Nini.Config; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -50,6 +54,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady private bool m_lastOarLoadedOk; private int m_channelNotify = -1000; private bool m_enabled = false; + private bool m_disable_logins = false; + private string m_uri = string.Empty; Scene m_scene = null; @@ -68,10 +74,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (m_config != null) { m_enabled = m_config.GetBoolean("enabled", false); + if (m_enabled) { m_channelNotify = m_config.GetInt("channel_notify", m_channelNotify); - } + m_disable_logins = m_config.GetBoolean("login_disable", false); + m_uri = m_config.GetString("alert_uri",string.Empty); + } } // if (!m_enabled) @@ -91,8 +100,21 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; + m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); + + if(m_disable_logins == true) + { + scene.LoginLock = true; + scene.LoginsDisabled = true; + m_log.InfoFormat("[RegionReady]: Logins disabled for {0}",m_scene.RegionInfo.RegionName); + + if(m_uri != string.Empty) + { + RRAlert("disabled"); + } + } } public void RemoveRegion(Scene scene) @@ -150,7 +172,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_log.InfoFormat("[RegionReady]: Region \"{0}\" is ready: \"{1}\" on channel {2}", m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); - m_scene.EventManager.TriggerOnChatBroadcast(this, c); + + m_scene.EventManager.TriggerOnChatBroadcast(this, c); + m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); } } @@ -165,5 +189,69 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_lastOarLoadedOk = false; } } + + void OnLoginsEnabled(string regionName) + { + if (m_disable_logins == true) + { + if (m_scene.StartDisabled == false) + { + m_scene.LoginsDisabled = false; + m_scene.LoginLock = false; + m_log.InfoFormat("[RegionReady]: Logins enabled for {0}", m_scene.RegionInfo.RegionName); + if ( m_uri != string.Empty ) + { + RRAlert("enabled"); + } + } + } + } + + public void RRAlert(string status) + { + string request_method = "POST"; + string content_type = "application/json"; + OSDMap RRAlert = new OSDMap(); + + RRAlert["alert"] = "region_ready"; + RRAlert["login"] = status; + RRAlert["region_name"] = m_scene.RegionInfo.RegionName; + RRAlert["region_id"] = m_scene.RegionInfo.RegionID; + + string strBuffer = ""; + byte[] buffer = new byte[1]; + try + { + strBuffer = OSDParser.SerializeJsonString(RRAlert); + Encoding str = Util.UTF8; + buffer = str.GetBytes(strBuffer); + + } + catch (Exception e) + { + m_log.WarnFormat("[RegionReady]: Exception thrown on alert: {0}", e.Message); + } + + WebRequest request = WebRequest.Create(m_uri); + request.Method = request_method; + request.ContentType = content_type; + + Stream os = null; + try + { + request.ContentLength = buffer.Length; + os = request.GetRequestStream(); + os.Write(buffer, 0, strBuffer.Length); + } + catch(Exception e) + { + m_log.WarnFormat("[RegionReady]: Exception thrown sending alert: {0}", e.Message); + } + finally + { + if (os != null) + os.Close(); + } + } } } diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index ce9a4481ea..ec9f1578e7 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -58,12 +58,9 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// /// /// Config Settings Documentation. - /// At the TOP LEVEL, e.g. in OpenSim.ini, we have the following options: - /// EACH REGION, in OpenSim.ini, can have the following settings under the [AutoBackupModule] section. - /// IMPORTANT: You may optionally specify the key name as follows for a per-region key: [Region Name].[Key Name] - /// Example: My region is named Foo. - /// If I wanted to specify the "AutoBackupInterval" key just for this region, I would name my key "Foo.AutoBackupInterval", under the [AutoBackupModule] section of OpenSim.ini. - /// Instead of specifying them on a per-region basis, you can also omit the region name to specify the default setting for all regions. + /// Each configuration setting can be specified in two places: OpenSim.ini or Regions.ini. + /// If specified in Regions.ini, the settings should be within the region's section name. + /// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section. /// Region-specific settings take precedence. /// /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis. @@ -71,7 +68,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// AutoBackup: True/False. Default: False. If True, activate auto backup functionality. /// This is the only required option for enabling auto-backup; the other options have sane defaults. /// If False for a particular region, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored. - /// If False globally (the default), only regions that specifically override this with "FooRegion.AutoBackup = true" will get AutoBackup functionality. + /// If False globally (the default), only regions that specifically override it in Regions.ini will get AutoBackup functionality. /// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours). /// The number of minutes between each backup attempt. /// If a negative or zero value is given, it is equivalent to setting AutoBackup = False. @@ -281,21 +278,21 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup { string sRegionName; string sRegionLabel; - string prepend; +// string prepend; AutoBackupModuleState state; if (parseDefault) { sRegionName = null; sRegionLabel = "DEFAULT"; - prepend = ""; +// prepend = ""; state = this.m_defaultState; } else { sRegionName = scene.RegionInfo.RegionName; sRegionLabel = sRegionName; - prepend = sRegionName + "."; +// prepend = sRegionName + "."; state = null; } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 551e33b106..0f505ca896 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -638,7 +638,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index f89b824614..99b2d8477a 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -303,7 +303,11 @@ namespace OpenSim.Region.Physics.Meshing if (meshOsd is OSDMap) { OSDMap map = (OSDMap)meshOsd; - OSDMap physicsParms = (OSDMap)map["physics_shape"]; + OSDMap physicsParms = (OSDMap)map["physics_shape"]; // old asset format + + if (physicsParms.Count == 0) + physicsParms = (OSDMap)map["physics_mesh"]; // new asset format + int physOffset = physicsParms["offset"].AsInteger() + (int)start; int physSize = physicsParms["size"].AsInteger(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 24b755db9f..4824a72042 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3340,12 +3340,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return m_ScriptEngine.GetStartParameter(m_itemID); } - public void llGodLikeRezObject(string inventory, LSL_Vector pos) - { - m_host.AddScriptLPS(1); - NotImplemented("llGodLikeRezObject"); - } - public void llRequestPermissions(string agent, int perm) { UUID agentID = new UUID(); @@ -3966,9 +3960,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); } - // check if destination is an avatar - if (World.GetScenePresence(destId) != null) + // check if destination is an object + if (World.GetSceneObjectPart(destId) != null) { + // destination is an object + World.MoveTaskInventoryItem(destId, m_host, objId); + } + else + { + ScenePresence presence = World.GetScenePresence(destId); + + if (presence == null) + { + UserAccount account = + World.UserAccountService.GetUserAccount( + World.RegionInfo.ScopeID, + destId); + + if (account == null) + { + llSay(0, "Can't find destination "+destId.ToString()); + return; + } + } // destination is an avatar InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); @@ -3989,16 +4003,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, bucket); - if (m_TransferModule != null) m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); + ScriptSleep(3000); } - else - { - // destination is an object - World.MoveTaskInventoryItem(destId, m_host, objId); - } - ScriptSleep(3000); } public void llRemoveInventory(string name) @@ -4286,12 +4294,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.CollisionSoundVolume = (float)impact_volume; } - public void llCollisionSprite(string impact_sprite) - { - m_host.AddScriptLPS(1); - NotImplemented("llCollisionSprite"); - } - public LSL_String llGetAnimation(string id) { // This should only return a value if the avatar is in the same region @@ -4555,6 +4557,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return result; } + public LSL_Integer llGetLinkNumberOfSides(int link) + { + m_host.AddScriptLPS(1); + + SceneObjectPart linkedPart; + + if (link == ScriptBaseClass.LINK_ROOT) + linkedPart = m_host.ParentGroup.RootPart; + else if (link == ScriptBaseClass.LINK_THIS) + linkedPart = m_host; + else + linkedPart = m_host.ParentGroup.GetLinkNumPart(link); + + return GetNumberOfSides(linkedPart); + } + public LSL_Integer llGetNumberOfSides() { m_host.AddScriptLPS(1); @@ -5611,12 +5629,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(100); } - public void llSetSoundQueueing(int queue) - { - m_host.AddScriptLPS(1); - NotImplemented("llSetSoundQueueing"); - } - public void llSetSoundRadius(double radius) { m_host.AddScriptLPS(1); @@ -10017,31 +10029,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide) { m_host.AddScriptLPS(1); - // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation - // Which probably will be irrelevent in OpenSim.... - LandData land = World.GetLandData((float)pos.x, (float)pos.y); - float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus; + ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); - if (land == null) - { + if (lo == null) return 0; - } if (sim_wide != 0) - { - decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor; - - return (int)v; - } - + return lo.GetSimulatorMaxPrimCount(); else - { - decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor; - - return (int)v; - } - + return lo.GetParcelMaxPrimCount(); } public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) @@ -10420,6 +10417,73 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return rq.ToString(); } + + #region Not Implemented + // + // Listing the unimplemented lsl functions here, please move + // them from this region as they are completed + // + public void llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) + { + m_host.AddScriptLPS(1); + NotImplemented("llCastRay"); + + } + + public void llGetEnv(LSL_String name) + { + m_host.AddScriptLPS(1); + NotImplemented("llGetEnv"); + + } + + public void llGetSPMaxMemory() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetSPMaxMemory"); + + } + + public void llGetUsedMemory() + { + m_host.AddScriptLPS(1); + NotImplemented("llGetUsedMemory"); + + } + + public void llRegionSayTo( LSL_Key target, LSL_Integer channel, LSL_String msg ) + { + m_host.AddScriptLPS(1); + NotImplemented("llRegionSayTo"); + + } + + public void llScriptProfiler( LSL_Integer flags ) + { + m_host.AddScriptLPS(1); + NotImplemented("llScriptProfiler"); + + } + + public void llSetSoundQueueing(int queue) + { + m_host.AddScriptLPS(1); + NotImplemented("llSetSoundQueueing"); + } + + public void llCollisionSprite(string impact_sprite) + { + m_host.AddScriptLPS(1); + NotImplemented("llCollisionSprite"); + } + + public void llGodLikeRezObject(string inventory, LSL_Vector pos) + { + m_host.AddScriptLPS(1); + NotImplemented("llGodLikeRezObject"); + } + + #endregion } public class NotecardCache diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 47c7915a3e..e53a61ad47 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -308,7 +308,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // In attachments, the sensor cone always orients with the // avatar rotation. This may include a nonzero elevation if // in mouselook. - ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); q = avatar.Rotation; } @@ -422,7 +421,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins SceneObjectPart SensePoint = ts.host; Vector3 fromRegionPos = SensePoint.AbsolutePosition; + Quaternion q = SensePoint.RotationOffset; + if (SensePoint.ParentGroup.RootPart.IsAttachment) + { + // In attachments, the sensor cone always orients with the + // avatar rotation. This may include a nonzero elevation if + // in mouselook. + ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); + q = avatar.Rotation; + } + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 298d664a64..461b473608 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -1536,6 +1536,7 @@ namespace OpenSim.Region.ScriptEngine.Shared public struct LSLInteger { public int value; + private static readonly Regex castRegex = new Regex(@"(^[ ]*0[xX][0-9A-Fa-f][0-9A-Fa-f]*)|(^[ ]*(-?|\+?)[0-9][0-9]*)"); #region Constructors public LSLInteger(int i) @@ -1555,9 +1556,10 @@ namespace OpenSim.Region.ScriptEngine.Shared public LSLInteger(string s) { - Regex r = new Regex("(^[ ]*0[xX][0-9A-Fa-f][0-9A-Fa-f]*)|(^[ ]*-?[0-9][0-9]*)"); - Match m = r.Match(s); + Match m = castRegex.Match(s); string v = m.Groups[0].Value; + // Leading plus sign is allowed, but ignored + v = v.Replace("+", ""); if (v == String.Empty) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs index 1d55b95f30..80b60a4976 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs @@ -29,7 +29,6 @@ using System.Collections.Generic; using NUnit.Framework; using OpenSim.Tests.Common; using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Tests.Common.Setup; using OpenSim.Region.Framework.Scenes; using Nini.Config; using OpenSim.Region.ScriptEngine.Shared.Api; diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index 045abb4490..b635d5c604 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using Nini.Config; using NUnit.Framework; -using OpenSim.Tests.Common.Setup; using OpenSim.Tests.Common.Mock; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 7e8f31592f..de33b35b4b 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -397,11 +397,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine return 0; } - public object DoMaintenance(object p) + public void SaveAllState() { - object[] parms = (object[])p; - int sleepTime = (int)parms[0]; - foreach (IScriptInstance inst in m_Scripts.Values) { if (inst.EventTime() > m_EventLimit) @@ -411,6 +408,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine inst.Start(); } } + } + + public object DoMaintenance(object p) + { + object[] parms = (object[])p; + int sleepTime = (int)parms[0]; + + SaveAllState(); System.Threading.Thread.Sleep(sleepTime); diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index f4472c7dc0..8effdd2d1b 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -65,6 +65,10 @@ namespace OpenSim.Server.Base /// public static T LoadPlugin(string dllName, Object[] args) where T:class { + // This is good to debug configuration problems + //if (dllName == string.Empty) + // Util.PrintCallStack(); + string[] parts = dllName.Split(new char[] {':'}); dllName = parts[0]; @@ -124,6 +128,13 @@ namespace OpenSim.Server.Base return null; } + catch (ReflectionTypeLoadException rtle) + { + m_log.Error(string.Format("Error loading plugin from {0}:\n{1}", dllName, + String.Join("\n", Array.ConvertAll(rtle.LoaderExceptions, e => e.ToString()))), + rtle); + return null; + } catch (Exception e) { m_log.Error(string.Format("Error loading plugin from {0}", dllName), e); diff --git a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs index 074f8690a5..5784bdf652 100644 --- a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs +++ b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs @@ -46,14 +46,14 @@ namespace OpenSim.Server.Handlers.Friends if (serverConfig == null) throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); - string gridService = serverConfig.GetString("LocalServiceModule", + string theService = serverConfig.GetString("LocalServiceModule", String.Empty); - if (gridService == String.Empty) + if (theService == String.Empty) throw new Exception("No LocalServiceModule in config file"); Object[] args = new Object[] { config }; - m_FriendsService = ServerUtils.LoadPlugin(gridService, args); + m_FriendsService = ServerUtils.LoadPlugin(theService, args); server.AddStreamHandler(new FriendsServerPostHandler(m_FriendsService)); } diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index b168bb35c9..fc97d8c221 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -82,12 +82,18 @@ namespace OpenSim.Server.Handlers.Friends case "getfriends": return GetFriends(request); + case "getfriends_string": + return GetFriendsString(request); + case "storefriend": return StoreFriend(request); case "deletefriend": return DeleteFriend(request); + case "deletefriend_string": + return DeleteFriendString(request); + } m_log.DebugFormat("[FRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); } @@ -111,7 +117,25 @@ namespace OpenSim.Server.Handlers.Friends m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); - //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); + + return PackageFriends(finfos); + } + + byte[] GetFriendsString(Dictionary request) + { + string principalID = string.Empty; + if (request.ContainsKey("PRINCIPALID")) + principalID = request["PRINCIPALID"].ToString(); + else + m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); + + FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); + + return PackageFriends(finfos); + } + + private byte[] PackageFriends(FriendInfo[] finfos) + { Dictionary result = new Dictionary(); if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) @@ -136,9 +160,9 @@ namespace OpenSim.Server.Handlers.Friends byte[] StoreFriend(Dictionary request) { - FriendInfo friend = new FriendInfo(request); - - bool success = m_FriendsService.StoreFriend(friend.PrincipalID, friend.Friend, friend.MyFlags); + string principalID = string.Empty, friend = string.Empty; int flags = 0; + FromKeyValuePairs(request, out principalID, out friend, out flags); + bool success = m_FriendsService.StoreFriend(principalID, friend, flags); if (success) return SuccessResult(); @@ -163,7 +187,25 @@ namespace OpenSim.Server.Handlers.Friends else return FailureResult(); } - + + byte[] DeleteFriendString(Dictionary request) + { + string principalID = string.Empty; + if (request.ContainsKey("PRINCIPALID")) + principalID = request["PRINCIPALID"].ToString(); + else + m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to delete friend"); + string friend = string.Empty; + if (request.ContainsKey("FRIEND")) + friend = request["FRIEND"].ToString(); + + bool success = m_FriendsService.Delete(principalID, friend); + if (success) + return SuccessResult(); + else + return FailureResult(); + } + #endregion #region Misc @@ -233,6 +275,19 @@ namespace OpenSim.Server.Handlers.Friends return ms.ToArray(); } + void FromKeyValuePairs(Dictionary kvp, out string principalID, out string friend, out int flags) + { + principalID = string.Empty; + if (kvp.ContainsKey("PrincipalID") && kvp["PrincipalID"] != null) + principalID = kvp["PrincipalID"].ToString(); + friend = string.Empty; + if (kvp.ContainsKey("Friend") && kvp["Friend"] != null) + friend = kvp["Friend"].ToString(); + flags = 0; + if (kvp.ContainsKey("MyFlags") && kvp["MyFlags"] != null) + Int32.TryParse(kvp["MyFlags"].ToString(), out flags); + } + #endregion } } diff --git a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs index cdab49ed6b..0da9fc112a 100644 --- a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs +++ b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs @@ -30,6 +30,7 @@ using System.Collections; using System.IO; using System.Net; using System.Reflection; +using System.Security; using System.Text; using log4net; using Nini.Config; @@ -143,7 +144,7 @@ namespace OpenSim.Server.Handlers.Grid sb.Append("\n"); foreach (string k in _info.Keys) { - sb.AppendFormat("<{0}>{1}\n", k, _info[k]); + sb.AppendFormat("<{0}>{1}\n", k, SecurityElement.Escape(_info[k].ToString())); } sb.Append("\n"); diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs new file mode 100644 index 0000000000..82a72206d3 --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using Nini.Config; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class HGFriendsServerConnector : ServiceConnector + { + private IFriendsService m_FriendsService; + private IUserAgentService m_UserAgentService; + private string m_ConfigName = "HGFriendsService"; + + public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + if (configName != string.Empty) + m_ConfigName = configName; + + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string theService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (theService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_FriendsService = ServerUtils.LoadPlugin(theService, args); + + theService = serverConfig.GetString("UserAgentService", string.Empty); + if (theService == String.Empty) + throw new Exception("No UserAgentService in " + m_ConfigName); + + m_UserAgentService = ServerUtils.LoadPlugin(theService, args); + + server.AddStreamHandler(new HGFriendsServerPostHandler(m_FriendsService, m_UserAgentService)); + } + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs new file mode 100644 index 0000000000..5c89d0fd75 --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -0,0 +1,320 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using Nini.Config; +using log4net; +using System; +using System.Reflection; +using System.IO; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Serialization; +using System.Collections.Generic; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class HGFriendsServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IFriendsService m_FriendsService; + private IUserAgentService m_UserAgentService; + + public HGFriendsServerPostHandler(IFriendsService service, IUserAgentService uservice) : + base("POST", "/hgfriends") + { + m_FriendsService = service; + m_UserAgentService = uservice; + m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On"); + } + + public override byte[] Handle(string path, Stream requestData, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + //m_log.DebugFormat("[XXX]: query String: {0}", body); + + try + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + + switch (method) + { + case "getfriendperms": + return GetFriendPerms(request); + + case "newfriendship": + return NewFriendship(request); + + case "deletefriendship": + return DeleteFriendship(request); + } + m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS HANDLER]: Exception {0}", e); + } + + return FailureResult(); + + } + + #region Method-specific handlers + + byte[] GetFriendPerms(Dictionary request) + { + if (!VerifyServiceKey(request)) + return FailureResult(); + + UUID principalID = UUID.Zero; + if (request.ContainsKey("PRINCIPALID")) + UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID); + else + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friend perms"); + return FailureResult(); + } + + UUID friendID = UUID.Zero; + if (request.ContainsKey("FRIENDID")) + UUID.TryParse(request["FRIENDID"].ToString(), out friendID); + else + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: no friendID in request to get friend perms"); + return FailureResult(); + } + + string perms = "0"; + FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID); + foreach (FriendInfo finfo in friendsInfo) + { + if (finfo.Friend.StartsWith(friendID.ToString())) + return SuccessResult(finfo.TheirFlags.ToString()); + } + + return FailureResult("Friend not found"); + } + + byte[] NewFriendship(Dictionary request) + { + if (!VerifyServiceKey(request)) + return FailureResult(); + + // OK, can proceed + FriendInfo friend = new FriendInfo(request); + UUID friendID; + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) + return FailureResult(); + + + m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend); + + // If the friendship already exists, return fail + FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID); + foreach (FriendInfo finfo in finfos) + if (finfo.Friend.StartsWith(friendID.ToString())) + return FailureResult(); + + // the user needs to confirm when he gets home + bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0); + + if (success) + return SuccessResult(); + else + return FailureResult(); + } + + byte[] DeleteFriendship(Dictionary request) + { + FriendInfo friend = new FriendInfo(request); + string secret = string.Empty; + if (request.ContainsKey("SECRET")) + secret = request["SECRET"].ToString(); + + if (secret == string.Empty) + return FailureResult(); + + FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID); + foreach (FriendInfo finfo in finfos) + { + // We check the secret here + if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret)) + { + m_log.DebugFormat("[HGFRIENDS HANDLER]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend); + m_FriendsService.Delete(friend.PrincipalID, finfo.Friend); + m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString()); + + return SuccessResult(); + } + } + + return FailureResult(); + } + + #endregion + + #region Misc + + private bool VerifyServiceKey(Dictionary request) + { + if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID")) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID"); + return false; + } + + string serviceKey = request["KEY"].ToString(); + string sessionStr = request["SESSIONID"].ToString(); + UUID sessionID; + UUID.TryParse(sessionStr, out sessionID); + + if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey)) + { + m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID); + return false; + } + + m_log.DebugFormat("[HGFRIENDS HANDLER]: Verification ok"); + return true; + } + + private byte[] SuccessResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] SuccessResult(string value) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Value", ""); + message.AppendChild(doc.CreateTextNode(value)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + + private byte[] FailureResult() + { + return FailureResult(String.Empty); + } + + private byte[] FailureResult(string msg) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); + } + + #endregion + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs new file mode 100644 index 0000000000..80eb5d2faf --- /dev/null +++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs @@ -0,0 +1,243 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; + +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +using log4net; +using Nwc.XmlRpc; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.Hypergrid +{ + public class InstantMessageServerConnector : ServiceConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private IInstantMessage m_IMService; + + public InstantMessageServerConnector(IConfigSource config, IHttpServer server) : + this(config, server, null) + { + } + + public InstantMessageServerConnector(IConfigSource config, IHttpServer server, IInstantMessageSimConnector simConnector) : + base(config, server, String.Empty) + { + IConfig gridConfig = config.Configs["HGInstantMessageService"]; + if (gridConfig != null) + { + string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); + + Object[] args = new Object[] { config, simConnector }; + m_IMService = ServerUtils.LoadPlugin(serviceDll, args); + } + if (m_IMService == null) + throw new Exception("InstantMessage server connector cannot proceed because of missing service"); + + server.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false); + + } + + public IInstantMessage GetService() + { + return m_IMService; + } + + protected virtual XmlRpcResponse ProcessInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient) + { + bool successful = false; + + try + { + // various rational defaults + UUID fromAgentID = UUID.Zero; + UUID toAgentID = UUID.Zero; + UUID imSessionID = UUID.Zero; + uint timestamp = 0; + string fromAgentName = ""; + string message = ""; + byte dialog = (byte)0; + bool fromGroup = false; + byte offline = (byte)0; + uint ParentEstateID = 0; + Vector3 Position = Vector3.Zero; + UUID RegionID = UUID.Zero; + byte[] binaryBucket = new byte[0]; + + float pos_x = 0; + float pos_y = 0; + float pos_z = 0; + //m_log.Info("Processing IM"); + + + Hashtable requestData = (Hashtable)request.Params[0]; + // Check if it's got all the data + if (requestData.ContainsKey("from_agent_id") + && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id") + && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name") + && requestData.ContainsKey("message") && requestData.ContainsKey("dialog") + && requestData.ContainsKey("from_group") + && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id") + && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y") + && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") + && requestData.ContainsKey("binary_bucket")) + { + // Do the easy way of validating the UUIDs + UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); + UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); + UUID.TryParse((string)requestData["im_session_id"], out imSessionID); + UUID.TryParse((string)requestData["region_id"], out RegionID); + try + { + timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + fromAgentName = (string)requestData["from_agent_name"]; + message = (string)requestData["message"]; + if (message == null) + message = string.Empty; + + // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them. + string requestData1 = (string)requestData["dialog"]; + if (string.IsNullOrEmpty(requestData1)) + { + dialog = 0; + } + else + { + byte[] dialogdata = Convert.FromBase64String(requestData1); + dialog = dialogdata[0]; + } + + if ((string)requestData["from_group"] == "TRUE") + fromGroup = true; + + string requestData2 = (string)requestData["offline"]; + if (String.IsNullOrEmpty(requestData2)) + { + offline = 0; + } + else + { + byte[] offlinedata = Convert.FromBase64String(requestData2); + offline = offlinedata[0]; + } + + try + { + ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]); + } + catch (ArgumentException) + { + } + catch (FormatException) + { + } + catch (OverflowException) + { + } + + float.TryParse((string)requestData["position_x"], out pos_x); + float.TryParse((string)requestData["position_y"], out pos_y); + float.TryParse((string)requestData["position_z"], out pos_z); + + Position = new Vector3(pos_x, pos_y, pos_z); + + string requestData3 = (string)requestData["binary_bucket"]; + if (string.IsNullOrEmpty(requestData3)) + { + binaryBucket = new byte[0]; + } + else + { + binaryBucket = Convert.FromBase64String(requestData3); + } + + // Create a New GridInstantMessageObject the the data + GridInstantMessage gim = new GridInstantMessage(); + gim.fromAgentID = fromAgentID.Guid; + gim.fromAgentName = fromAgentName; + gim.fromGroup = fromGroup; + gim.imSessionID = imSessionID.Guid; + gim.RegionID = RegionID.Guid; + gim.timestamp = timestamp; + gim.toAgentID = toAgentID.Guid; + gim.message = message; + gim.dialog = dialog; + gim.offline = offline; + gim.ParentEstateID = ParentEstateID; + gim.Position = Position; + gim.binaryBucket = binaryBucket; + + successful = m_IMService.IncomingInstantMessage(gim); + + } + } + catch (Exception e) + { + m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e); + successful = false; + } + + //Send response back to region calling if it was successful + // calling region uses this to know when to look up a user's location again. + XmlRpcResponse resp = new XmlRpcResponse(); + Hashtable respdata = new Hashtable(); + if (successful) + respdata["success"] = "TRUE"; + else + respdata["success"] = "FALSE"; + resp.Value = respdata; + + return resp; + } + + } +} diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 0e8ce800a7..72a4aeaa62 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -52,15 +52,24 @@ namespace OpenSim.Server.Handlers.Hypergrid // MethodBase.GetCurrentMethod().DeclaringType); private IUserAgentService m_HomeUsersService; + private string[] m_AuthorizedCallers; + + private bool m_VerifyCallers = false; public UserAgentServerConnector(IConfigSource config, IHttpServer server) : + this(config, server, null) + { + } + + public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) : base(config, server, String.Empty) { IConfig gridConfig = config.Configs["UserAgentService"]; if (gridConfig != null) { string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); - Object[] args = new Object[] { config }; + + Object[] args = new Object[] { config, friendsConnector }; m_HomeUsersService = ServerUtils.LoadPlugin(serviceDll, args); } if (m_HomeUsersService == null) @@ -69,12 +78,24 @@ namespace OpenSim.Server.Handlers.Hypergrid string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1"); bool proxy = gridConfig.GetBoolean("HasProxy", false); + m_VerifyCallers = gridConfig.GetBoolean("VerifyCallers", false); + string csv = gridConfig.GetString("AuthorizedCallers", "127.0.0.1"); + csv = csv.Replace(" ", ""); + m_AuthorizedCallers = csv.Split(','); + server.AddXmlRPCHandler("agent_is_coming_home", AgentIsComingHome, false); server.AddXmlRPCHandler("get_home_region", GetHomeRegion, false); server.AddXmlRPCHandler("verify_agent", VerifyAgent, false); server.AddXmlRPCHandler("verify_client", VerifyClient, false); server.AddXmlRPCHandler("logout_agent", LogoutAgent, false); + server.AddXmlRPCHandler("status_notification", StatusNotification, false); + server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false); + server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false); + + server.AddXmlRPCHandler("locate_user", LocateUser, false); + server.AddXmlRPCHandler("get_uui", GetUUI, false); + server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); } @@ -194,5 +215,201 @@ namespace OpenSim.Server.Handlers.Hypergrid } + public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + hash["result"] = "false"; + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID") && requestData.ContainsKey("online")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + List ids = new List(); + foreach (object key in requestData.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null) + ids.Add(requestData[key].ToString()); + } + bool online = false; + bool.TryParse(requestData["online"].ToString(), out online); + + // let's spawn a thread for this, because it may take a long time... + List friendsOnline = m_HomeUsersService.StatusNotification(ids, userID, online); + if (friendsOnline.Count > 0) + { + int i = 0; + foreach (UUID id in friendsOnline) + { + hash["friend_" + i.ToString()] = id.ToString(); + i++; + } + } + else + hash["result"] = "No Friends Online"; + + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + public XmlRpcResponse GetOnlineFriends(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + List ids = new List(); + foreach (object key in requestData.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null) + ids.Add(requestData[key].ToString()); + } + + //List online = m_HomeUsersService.GetOnlineFriends(userID, ids); + //if (online.Count > 0) + //{ + // int i = 0; + // foreach (UUID id in online) + // { + // hash["friend_" + i.ToString()] = id.ToString(); + // i++; + // } + //} + //else + // hash["result"] = "No Friends Online"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + public XmlRpcResponse GetServerURLs(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + Dictionary serverURLs = m_HomeUsersService.GetServerURLs(userID); + if (serverURLs.Count > 0) + { + foreach (KeyValuePair kvp in serverURLs) + hash["SRV_" + kvp.Key] = kvp.Value.ToString(); + } + else + hash["result"] = "No Service URLs"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + /// + /// Locates the user. + /// This is a sensitive operation, only authorized IP addresses can perform it. + /// + /// + /// + /// + public XmlRpcResponse LocateUser(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + bool authorized = true; + if (m_VerifyCallers) + { + authorized = false; + foreach (string s in m_AuthorizedCallers) + if (s == remoteClient.Address.ToString()) + { + authorized = true; + break; + } + } + + if (authorized) + { + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + string url = m_HomeUsersService.LocateUser(userID); + if (url != string.Empty) + hash["URL"] = url; + else + hash["result"] = "Unable to locate user"; + } + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + + /// + /// Locates the user. + /// This is a sensitive operation, only authorized IP addresses can perform it. + /// + /// + /// + /// + public XmlRpcResponse GetUUI(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID") && requestData.ContainsKey("targetUserID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + string tuserID_str = (string)requestData["targetUserID"]; + UUID targetUserID = UUID.Zero; + UUID.TryParse(tuserID_str, out targetUserID); + string uui = m_HomeUsersService.GetUUI(userID, targetUserID); + if (uui != string.Empty) + hash["UUI"] = uui; + else + hash["result"] = "User unknown"; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + } } diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs index 861c4759a3..c5ae0c056e 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs @@ -38,7 +38,7 @@ using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenSim.Server.Base; using OpenMetaverse; -namespace OpenSim.Services.Connectors +namespace OpenSim.Services.Connectors.Friends { public class FriendsServicesConnector : IFriendsService { @@ -84,7 +84,7 @@ namespace OpenSim.Services.Connectors #region IFriendsService - + public FriendInfo[] GetFriends(UUID PrincipalID) { Dictionary sendData = new Dictionary(); @@ -92,6 +92,21 @@ namespace OpenSim.Services.Connectors sendData["PRINCIPALID"] = PrincipalID.ToString(); sendData["METHOD"] = "getfriends"; + return GetFriends(sendData, PrincipalID.ToString()); + } + + public FriendInfo[] GetFriends(string PrincipalID) + { + Dictionary sendData = new Dictionary(); + + sendData["PRINCIPALID"] = PrincipalID; + sendData["METHOD"] = "getfriends_string"; + + return GetFriends(sendData, PrincipalID); + } + + protected FriendInfo[] GetFriends(Dictionary sendData, string PrincipalID) + { string reqString = ServerUtils.BuildQueryString(sendData); try @@ -144,14 +159,10 @@ namespace OpenSim.Services.Connectors } - public bool StoreFriend(UUID PrincipalID, string Friend, int flags) + public bool StoreFriend(string PrincipalID, string Friend, int flags) { - FriendInfo finfo = new FriendInfo(); - finfo.PrincipalID = PrincipalID; - finfo.Friend = Friend; - finfo.MyFlags = flags; - Dictionary sendData = finfo.ToKeyValuePairs(); + Dictionary sendData = ToKeyValuePairs(PrincipalID, Friend, flags); sendData["METHOD"] = "storefriend"; @@ -189,6 +200,16 @@ namespace OpenSim.Services.Connectors } + public bool Delete(string PrincipalID, string Friend) + { + Dictionary sendData = new Dictionary(); + sendData["PRINCIPALID"] = PrincipalID.ToString(); + sendData["FRIEND"] = Friend; + sendData["METHOD"] = "deletefriend_string"; + + return Delete(sendData, PrincipalID, Friend); + } + public bool Delete(UUID PrincipalID, string Friend) { Dictionary sendData = new Dictionary(); @@ -196,6 +217,11 @@ namespace OpenSim.Services.Connectors sendData["FRIEND"] = Friend; sendData["METHOD"] = "deletefriend"; + return Delete(sendData, PrincipalID.ToString(), Friend); + } + + public bool Delete(Dictionary sendData, string PrincipalID, string Friend) + { string reply = string.Empty; try { @@ -230,5 +256,16 @@ namespace OpenSim.Services.Connectors } #endregion + + public Dictionary ToKeyValuePairs(string principalID, string friend, int flags) + { + Dictionary result = new Dictionary(); + result["PrincipalID"] = principalID; + result["Friend"] = friend; + result["MyFlags"] = flags; + + return result; + } + } } \ No newline at end of file diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs new file mode 100644 index 0000000000..d699f596a2 --- /dev/null +++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs @@ -0,0 +1,206 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using log4net; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.Friends; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using OpenSim.Server.Base; +using OpenMetaverse; + +namespace OpenSim.Services.Connectors.Hypergrid +{ + public class HGFriendsServicesConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + private string m_ServiceKey = String.Empty; + private UUID m_SessionID; + + public HGFriendsServicesConnector() + { + } + + public HGFriendsServicesConnector(string serverURI) + { + m_ServerURI = serverURI.TrimEnd('/'); + } + + public HGFriendsServicesConnector(string serverURI, UUID sessionID, string serviceKey) + { + m_ServerURI = serverURI.TrimEnd('/'); + m_ServiceKey = serviceKey; + m_SessionID = sessionID; + } + + #region IFriendsService + + public uint GetFriendPerms(UUID PrincipalID, UUID friendID) + { + Dictionary sendData = new Dictionary(); + + sendData["PRINCIPALID"] = PrincipalID.ToString(); + sendData["FRIENDID"] = friendID.ToString(); + sendData["METHOD"] = "getfriendperms"; + sendData["KEY"] = m_ServiceKey; + sendData["SESSIONID"] = m_SessionID.ToString(); + + string reqString = ServerUtils.BuildQueryString(sendData); + + try + { + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + reqString); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Value") && (replyData["Value"] != null)) + { + uint perms = 0; + uint.TryParse(replyData["Value"].ToString(), out perms); + return perms; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriendPerms {0} received null response", + PrincipalID); + + } + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + } + + return 0; + + } + + public bool NewFriendship(UUID PrincipalID, string Friend) + { + FriendInfo finfo = new FriendInfo(); + finfo.PrincipalID = PrincipalID; + finfo.Friend = Friend; + + Dictionary sendData = finfo.ToKeyValuePairs(); + + sendData["METHOD"] = "newfriendship"; + sendData["KEY"] = m_ServiceKey; + sendData["SESSIONID"] = m_SessionID.ToString(); + + string reply = string.Empty; + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + ServerUtils.BuildQueryString(sendData)); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + return false; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null)) + { + bool success = false; + Boolean.TryParse(replyData["Result"].ToString(), out success); + return success; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend {0} {1} received null response", + PrincipalID, Friend); + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend received null reply"); + + return false; + + } + + public bool DeleteFriendship(UUID PrincipalID, UUID Friend, string secret) + { + FriendInfo finfo = new FriendInfo(); + finfo.PrincipalID = PrincipalID; + finfo.Friend = Friend.ToString(); + + Dictionary sendData = finfo.ToKeyValuePairs(); + + sendData["METHOD"] = "deletefriendship"; + sendData["SECRET"] = secret; + + string reply = string.Empty; + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/hgfriends", + ServerUtils.BuildQueryString(sendData)); + } + catch (Exception e) + { + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message); + return false; + } + + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null)) + { + bool success = false; + Boolean.TryParse(replyData["Result"].ToString(), out success); + return success; + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Delete {0} {1} received null response", + PrincipalID, Friend); + } + else + m_log.DebugFormat("[HGFRIENDS CONNECTOR]: DeleteFriend received null reply"); + + return false; + + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index c40a3474a3..853e5243ab 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -404,6 +404,329 @@ namespace OpenSim.Services.Connectors.Hypergrid GetBoolResponse(request, out reason); } + public List StatusNotification(List friends, UUID userID, bool online) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + hash["online"] = online.ToString(); + int i = 0; + foreach (string s in friends) + { + hash["friend_" + i.ToString()] = s; + i++; + } + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList); + string reason = string.Empty; + + // Send and get reply + List friendsOnline = new List(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return friendsOnline; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return friendsOnline; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return friendsOnline; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null) + { + UUID uuid; + if (UUID.TryParse(hash[key].ToString(), out uuid)) + friendsOnline.Add(uuid); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return friendsOnline; + } + + public List GetOnlineFriends(UUID userID, List friends) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + int i = 0; + foreach (string s in friends) + { + hash["friend_" + i.ToString()] = s; + i++; + } + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList); + string reason = string.Empty; + + // Send and get reply + List online = new List(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return online; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return online; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return online; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null) + { + UUID uuid; + if (UUID.TryParse(hash[key].ToString(), out uuid)) + online.Add(uuid); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return online; + } + + public Dictionary GetServerURLs(UUID userID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_server_urls", paramList); + string reason = string.Empty; + + // Send and get reply + Dictionary serverURLs = new Dictionary(); + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return serverURLs; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return serverURLs; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetServerURLs Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return serverURLs; + } + + // Here is the actual response + foreach (object key in hash.Keys) + { + if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null) + { + string serverType = key.ToString().Substring(4); // remove "SRV_" + serverURLs.Add(serverType, hash[key].ToString()); + } + } + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response."); + reason = "Exception: " + e.Message; + } + + return serverURLs; + } + + public string LocateUser(UUID userID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("locate_user", paramList); + string reason = string.Empty; + + // Send and get reply + string url = string.Empty; + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return url; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return url; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: LocateUser Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return url; + } + + // Here's the actual response + if (hash.ContainsKey("URL")) + url = hash["URL"].ToString(); + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); + reason = "Exception: " + e.Message; + } + + return url; + } + + public string GetUUI(UUID userID, UUID targetUserID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + hash["targetUserID"] = targetUserID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_uui", paramList); + string reason = string.Empty; + + // Send and get reply + string uui = string.Empty; + XmlRpcResponse response = null; + try + { + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return uui; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return uui; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUI Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return uui; + } + + // Here's the actual response + if (hash.ContainsKey("UUI")) + uui = hash["UUI"].ToString(); + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); + reason = "Exception: " + e.Message; + } + + return uui; + } private bool GetBoolResponse(XmlRpcRequest request, out string reason) { diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs new file mode 100644 index 0000000000..dbce9f613c --- /dev/null +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -0,0 +1,131 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; + +using OpenMetaverse; +using Nwc.XmlRpc; +using log4net; + +using OpenSim.Framework; + +namespace OpenSim.Services.Connectors.InstantMessage +{ + public class InstantMessageServiceConnector + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// This actually does the XMLRPC Request + /// + /// URL we pull the data out of to send the request to + /// The Instant Message + /// Bool if the message was successfully delivered at the other side. + public static bool SendInstantMessage(string url, GridInstantMessage im) + { + Hashtable xmlrpcdata = ConvertGridInstantMessageToXMLRPC(im); + xmlrpcdata["region_handle"] = 0; + + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); + try + { + + XmlRpcResponse GridResp = GridReq.Send(url, 10000); + + Hashtable responseData = (Hashtable)GridResp.Value; + + if (responseData.ContainsKey("success")) + { + if ((string)responseData["success"] == "TRUE") + { + //m_log.DebugFormat("[XXX] Success"); + return true; + } + else + { + //m_log.DebugFormat("[XXX] Fail"); + return false; + } + } + else + { + m_log.DebugFormat("[GRID INSTANT MESSAGE]: No response from {0}", url); + return false; + } + } + catch (WebException e) + { + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), url); + } + + return false; + } + + /// + /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC + /// + /// The GridInstantMessage object + /// Hashtable containing the XMLRPC request + protected static Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg) + { + Hashtable gim = new Hashtable(); + gim["from_agent_id"] = msg.fromAgentID.ToString(); + // Kept for compatibility + gim["from_agent_session"] = UUID.Zero.ToString(); + gim["to_agent_id"] = msg.toAgentID.ToString(); + gim["im_session_id"] = msg.imSessionID.ToString(); + gim["timestamp"] = msg.timestamp.ToString(); + gim["from_agent_name"] = msg.fromAgentName; + gim["message"] = msg.message; + byte[] dialogdata = new byte[1]; dialogdata[0] = msg.dialog; + gim["dialog"] = Convert.ToBase64String(dialogdata, Base64FormattingOptions.None); + + if (msg.fromGroup) + gim["from_group"] = "TRUE"; + else + gim["from_group"] = "FALSE"; + byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline; + gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None); + gim["parent_estate_id"] = msg.ParentEstateID.ToString(); + gim["position_x"] = msg.Position.X.ToString(); + gim["position_y"] = msg.Position.Y.ToString(); + gim["position_z"] = msg.Position.Z.ToString(); + gim["region_id"] = msg.RegionID.ToString(); + gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None); + + return gim; + } + + } +} diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs index 6f2d73559b..7422d94b44 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs @@ -77,6 +77,11 @@ namespace OpenSim.Services.Connectors.SimianGrid #region IFriendsService public FriendInfo[] GetFriends(UUID principalID) + { + return GetFriends(principalID.ToString()); + } + + public FriendInfo[] GetFriends(string principalID) { if (String.IsNullOrEmpty(m_serverUrl)) return new FriendInfo[0]; @@ -95,7 +100,14 @@ namespace OpenSim.Services.Connectors.SimianGrid UUID friendID = friendEntry["Key"].AsUUID(); FriendInfo friend = new FriendInfo(); - friend.PrincipalID = principalID; + if (!UUID.TryParse(principalID, out friend.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + friend.Friend = friendID.ToString(); friend.MyFlags = friendEntry["Value"].AsInteger(); friend.TheirFlags = -1; @@ -127,7 +139,7 @@ namespace OpenSim.Services.Connectors.SimianGrid return array; } - public bool StoreFriend(UUID principalID, string friend, int flags) + public bool StoreFriend(string principalID, string friend, int flags) { if (String.IsNullOrEmpty(m_serverUrl)) return true; @@ -151,6 +163,11 @@ namespace OpenSim.Services.Connectors.SimianGrid } public bool Delete(UUID principalID, string friend) + { + return Delete(principalID.ToString(), friend); + } + + public bool Delete(string principalID, string friend) { if (String.IsNullOrEmpty(m_serverUrl)) return true; @@ -174,7 +191,7 @@ namespace OpenSim.Services.Connectors.SimianGrid #endregion IFriendsService - private OSDArray GetFriended(UUID ownerID) + private OSDArray GetFriended(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { @@ -195,7 +212,7 @@ namespace OpenSim.Services.Connectors.SimianGrid } } - private OSDArray GetFriendedBy(UUID ownerID) + private OSDArray GetFriendedBy(string ownerID) { NameValueCollection requestArgs = new NameValueCollection { diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index f38087383c..7cbd361f68 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -103,16 +103,31 @@ namespace OpenSim.Services.Connectors.Simulation args["teleport_flags"] = OSD.FromString(flags.ToString()); OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); - if (result["Success"].AsBoolean()) - return true; - + bool success = result["success"].AsBoolean(); + if (success && result.ContainsKey("_Result")) + { + OSDMap data = (OSDMap)result["_Result"]; + + reason = data["reason"].AsString(); + success = data["success"].AsBoolean(); + return success; + } + + // Try the old version, uncompressed result = WebUtil.PostToService(uri, args, 30000); if (result["Success"].AsBoolean()) { - m_log.WarnFormat( - "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); - return true; + if (result.ContainsKey("_Result")) + { + OSDMap data = (OSDMap)result["_Result"]; + + reason = data["reason"].AsString(); + success = data["success"].AsBoolean(); + m_log.WarnFormat( + "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); + return success; + } } m_log.WarnFormat( diff --git a/OpenSim/Services/FreeswitchService/FreeswitchService.cs b/OpenSim/Services/FreeswitchService/FreeswitchService.cs index c3f10560d7..201e72f511 100644 --- a/OpenSim/Services/FreeswitchService/FreeswitchService.cs +++ b/OpenSim/Services/FreeswitchService/FreeswitchService.cs @@ -54,10 +54,10 @@ namespace OpenSim.Services.FreeswitchService Hashtable response = new Hashtable(); - foreach (DictionaryEntry item in request) - { -// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); - } +// foreach (DictionaryEntry item in request) +// { +//// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value); +// } string requestcontext = (string) request["Hunt-Context"]; response["content_type"] = "text/xml"; diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs index 3c64eccdf6..e2033ac93d 100644 --- a/OpenSim/Services/Friends/FriendsService.cs +++ b/OpenSim/Services/Friends/FriendsService.cs @@ -43,17 +43,16 @@ namespace OpenSim.Services.Friends { } - public FriendInfo[] GetFriends(UUID PrincipalID) + public virtual FriendInfo[] GetFriends(UUID PrincipalID) { FriendsData[] data = m_Database.GetFriends(PrincipalID); - List info = new List(); foreach (FriendsData d in data) { FriendInfo i = new FriendInfo(); - i.PrincipalID = d.PrincipalID; + i.PrincipalID = new UUID(d.PrincipalID); i.Friend = d.Friend; i.MyFlags = Convert.ToInt32(d.Data["Flags"]); i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); @@ -64,7 +63,33 @@ namespace OpenSim.Services.Friends return info.ToArray(); } - public bool StoreFriend(UUID PrincipalID, string Friend, int flags) + public virtual FriendInfo[] GetFriends(string PrincipalID) + { + FriendsData[] data = m_Database.GetFriends(PrincipalID); + List info = new List(); + + foreach (FriendsData d in data) + { + FriendInfo i = new FriendInfo(); + + if (!UUID.TryParse(d.PrincipalID, out i.PrincipalID)) + { + string tmp = string.Empty; + if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp, out tmp)) + // bad record. ignore this entry + continue; + } + i.Friend = d.Friend; + i.MyFlags = Convert.ToInt32(d.Data["Flags"]); + i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); + + info.Add(i); + } + + return info.ToArray(); + } + + public virtual bool StoreFriend(string PrincipalID, string Friend, int flags) { FriendsData d = new FriendsData(); @@ -76,7 +101,12 @@ namespace OpenSim.Services.Friends return m_Database.Store(d); } - public bool Delete(UUID PrincipalID, string Friend) + public bool Delete(string principalID, string friend) + { + return m_Database.Delete(principalID, friend); + } + + public virtual bool Delete(UUID PrincipalID, string Friend) { return m_Database.Delete(PrincipalID, Friend); } diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs index c5390475f2..52625980cc 100644 --- a/OpenSim/Services/GridService/HypergridLinker.cs +++ b/OpenSim/Services/GridService/HypergridLinker.cs @@ -363,10 +363,13 @@ namespace OpenSim.Services.GridService else regInfo.RegionName = externalName; - m_log.Debug("[HYPERGRID LINKER]: naming linked region " + regInfo.RegionName); + m_log.DebugFormat("[HYPERGRID LINKER]: naming linked region {0}, handle {1}", regInfo.RegionName, handle.ToString()); // Get the map image - regInfo.TerrainImage = m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory); + regInfo.TerrainImage = GetMapImage(regionID, imageURL); + + // Store the origin's coordinates somewhere + regInfo.RegionSecret = handle.ToString(); AddHyperlinkRegion(regInfo, handle); m_log.InfoFormat("[HYPERGRID LINKER]: Successfully linked to region {0} with image {1}", regInfo.RegionName, regInfo.TerrainImage); @@ -463,6 +466,10 @@ namespace OpenSim.Services.GridService m_Database.Delete(regionID); } + public UUID GetMapImage(UUID regionID, string imageURL) + { + return m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory); + } #endregion diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs new file mode 100644 index 0000000000..ded589de2d --- /dev/null +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -0,0 +1,349 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using System.Reflection; + +using OpenSim.Framework; +using OpenSim.Services.Connectors.Friends; +using OpenSim.Services.Connectors.Hypergrid; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Server.Base; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; + +using OpenMetaverse; +using log4net; +using Nini.Config; + +namespace OpenSim.Services.HypergridService +{ + /// + /// Inter-grid IM + /// + public class HGInstantMessageService : IInstantMessage + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours + + static bool m_Initialized = false; + + protected static IGridService m_GridService; + protected static IPresenceService m_PresenceService; + protected static IUserAgentService m_UserAgentService; + + protected static IInstantMessageSimConnector m_IMSimConnector; + + protected static Dictionary m_UserLocationMap = new Dictionary(); + private static ExpiringCache m_RegionCache; + + private static string m_RestURL; + private static bool m_ForwardOfflineGroupMessages; + private static bool m_InGatekeeper; + + public HGInstantMessageService(IConfigSource config) + : this(config, null) + { + } + + public HGInstantMessageService(IConfigSource config, IInstantMessageSimConnector imConnector) + { + if (imConnector != null) + m_IMSimConnector = imConnector; + + if (!m_Initialized) + { + m_Initialized = true; + + IConfig serverConfig = config.Configs["HGInstantMessageService"]; + if (serverConfig == null) + throw new Exception(String.Format("No section HGInstantMessageService in config file")); + + string gridService = serverConfig.GetString("GridService", String.Empty); + string presenceService = serverConfig.GetString("PresenceService", String.Empty); + string userAgentService = serverConfig.GetString("UserAgentService", String.Empty); + m_InGatekeeper = serverConfig.GetBoolean("InGatekeeper", false); + m_log.DebugFormat("[HG IM SERVICE]: Starting... InRobust? {0}", m_InGatekeeper); + + + if (gridService == string.Empty || presenceService == string.Empty) + throw new Exception(String.Format("Incomplete specifications, InstantMessage Service cannot function.")); + + Object[] args = new Object[] { config }; + m_GridService = ServerUtils.LoadPlugin(gridService, args); + m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); + m_UserAgentService = ServerUtils.LoadPlugin(userAgentService, args); + + m_RegionCache = new ExpiringCache(); + + IConfig cnf = config.Configs["Messaging"]; + if (cnf == null) + { + return; + } + + m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty); + m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false); + + } + } + + public bool IncomingInstantMessage(GridInstantMessage im) + { + m_log.DebugFormat("[HG IM SERVICE]: Received message from {0} to {1}", im.fromAgentID, im.toAgentID); + UUID toAgentID = new UUID(im.toAgentID); + + bool success = false; + if (m_IMSimConnector != null) + { + //m_log.DebugFormat("[XXX] SendIMToRegion local im connector"); + success = m_IMSimConnector.SendInstantMessage(im); + } + else + { + success = TrySendInstantMessage(im, "", true, false); + } + + if (!success && m_InGatekeeper) // we do this only in the Gatekeeper IM service + UndeliveredMessage(im); + + return success; + } + + public bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner) + { + m_log.DebugFormat("[HG IM SERVICE]: Sending message from {0} to {1}@{2}", im.fromAgentID, im.toAgentID, url); + if (url != string.Empty) + return TrySendInstantMessage(im, url, true, foreigner); + else + { + PresenceInfo upd = new PresenceInfo(); + upd.RegionID = UUID.Zero; + return TrySendInstantMessage(im, upd, true, foreigner); + } + + } + + protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime, bool foreigner) + { + UUID toAgentID = new UUID(im.toAgentID); + + PresenceInfo upd = null; + string url = string.Empty; + + bool lookupAgent = false; + + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + object o = m_UserLocationMap[toAgentID]; + if (o is PresenceInfo) + upd = (PresenceInfo)o; + else if (o is string) + url = (string)o; + + // We need to compare the current location with the previous + // or the recursive loop will never end because it will never try to lookup the agent again + if (!firstTime) + { + lookupAgent = true; + upd = null; + } + } + else + { + lookupAgent = true; + } + } + + //m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no")); + + // Are we needing to look-up an agent? + if (lookupAgent) + { + // Non-cached user agent lookup. + PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + if (presences != null && presences.Length > 0) + { + foreach (PresenceInfo p in presences) + { + if (p.RegionID != UUID.Zero) + { + //m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID); + upd = p; + break; + } + } + } + + if (upd == null && !foreigner) + { + // Let's check with the UAS if the user is elsewhere + m_log.DebugFormat("[HG IM SERVICE]: User is not present. Checking location with User Agent service"); + url = m_UserAgentService.LocateUser(toAgentID); + } + + // check if we've tried this before.. + // This is one way to end the recursive loop + // + if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) || + (previousLocation is string && upd == null && previousLocation.Equals(url)))) + { + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url); + + return false; + } + } + + if (upd != null) + { + // ok, the user is around somewhere. Let's send back the reply with "success" + // even though the IM may still fail. Just don't keep the caller waiting for + // the entire time we're trying to deliver the IM + return SendIMToRegion(upd, im, toAgentID, foreigner); + } + else if (url != string.Empty) + { + // ok, the user is around somewhere. Let's send back the reply with "success" + // even though the IM may still fail. Just don't keep the caller waiting for + // the entire time we're trying to deliver the IM + return ForwardIMToGrid(url, im, toAgentID, foreigner); + } + else if (firstTime && previousLocation is string && (string)previousLocation != string.Empty) + { + return ForwardIMToGrid((string)previousLocation, im, toAgentID, foreigner); + } + else + m_log.DebugFormat("[HG IM SERVICE]: Unable to locate user {0}", toAgentID); + return false; + } + + bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID, bool foreigner) + { + bool imresult = false; + GridRegion reginfo = null; + if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo)) + { + reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID); + if (reginfo != null) + m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS); + } + + if (reginfo != null) + { + imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im); + } + else + { + m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI); + return false; + } + + if (imresult) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + m_UserLocationMap[toAgentID] = upd; + } + else + { + m_UserLocationMap.Add(toAgentID, upd); + } + } + return true; + } + else + { + // try again, but lookup user this time. + // Warning, this must call the Async version + // of this method or we'll be making thousands of threads + // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync + // The version that spawns the thread is SendGridInstantMessageViaXMLRPC + + // This is recursive!!!!! + return TrySendInstantMessage(im, upd, false, foreigner); + } + } + + bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID, bool foreigner) + { + if (InstantMessageServiceConnector.SendInstantMessage(url, im)) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserLocationMap) + { + if (m_UserLocationMap.ContainsKey(toAgentID)) + { + m_UserLocationMap[toAgentID] = url; + } + else + { + m_UserLocationMap.Add(toAgentID, url); + } + } + + return true; + } + else + { + // try again, but lookup user this time. + + // This is recursive!!!!! + return TrySendInstantMessage(im, url, false, foreigner); + } + + } + + private bool UndeliveredMessage(GridInstantMessage im) + { + if (m_RestURL != string.Empty && (im.offline != 0) + && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) + { + m_log.DebugFormat("[HG IM SERVICE]: Message saved"); + return SynchronousRestObjectPoster.BeginPostObject( + "POST", m_RestURL + "/SaveMessage/", im); + + } + + else + { + return false; + } + } + } +} diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index 9ee1ae4c5f..4eb61ba6b9 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -134,6 +134,7 @@ namespace OpenSim.Services.HypergridService public override InventoryFolderBase GetRootFolder(UUID principalID) { + //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID); // Warp! Root folder for travelers XInventoryFolder[] folders = m_Database.GetFolders( new string[] { "agentID", "folderName"}, @@ -171,6 +172,7 @@ namespace OpenSim.Services.HypergridService public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) { + //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); return GetRootFolder(principalID); } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 445d45e250..1559cf3205 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -31,10 +31,12 @@ using System.Net; using System.Reflection; using OpenSim.Framework; +using OpenSim.Services.Connectors.Friends; using OpenSim.Services.Connectors.Hypergrid; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; using OpenMetaverse; using log4net; @@ -63,19 +65,35 @@ namespace OpenSim.Services.HypergridService protected static IGridService m_GridService; protected static GatekeeperServiceConnector m_GatekeeperConnector; protected static IGatekeeperService m_GatekeeperService; + protected static IFriendsService m_FriendsService; + protected static IPresenceService m_PresenceService; + protected static IUserAccountService m_UserAccountService; + protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule + protected static FriendsSimConnector m_FriendsSimConnector; // grid protected static string m_GridName; protected static bool m_BypassClientVerification; - public UserAgentService(IConfigSource config) + public UserAgentService(IConfigSource config) : this(config, null) { + } + + public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector) + { + // Let's set this always, because we don't know the sequence + // of instantiations + if (friendsConnector != null) + m_FriendsLocalSimConnector = friendsConnector; + if (!m_Initialized) { m_Initialized = true; m_log.DebugFormat("[HOME USERS SECURITY]: Starting..."); - + + m_FriendsSimConnector = new FriendsSimConnector(); + IConfig serverConfig = config.Configs["UserAgentService"]; if (serverConfig == null) throw new Exception(String.Format("No section UserAgentService in config file")); @@ -83,6 +101,9 @@ namespace OpenSim.Services.HypergridService string gridService = serverConfig.GetString("GridService", String.Empty); string gridUserService = serverConfig.GetString("GridUserService", String.Empty); string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty); + string friendsService = serverConfig.GetString("FriendsService", String.Empty); + string presenceService = serverConfig.GetString("PresenceService", String.Empty); + string userAccountService = serverConfig.GetString("UserAccountService", String.Empty); m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false); @@ -94,6 +115,9 @@ namespace OpenSim.Services.HypergridService m_GridUserService = ServerUtils.LoadPlugin(gridUserService, args); m_GatekeeperConnector = new GatekeeperServiceConnector(); m_GatekeeperService = ServerUtils.LoadPlugin(gatekeeperService, args); + m_FriendsService = ServerUtils.LoadPlugin(friendsService, args); + m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); + m_UserAccountService = ServerUtils.LoadPlugin(userAccountService, args); m_GridName = serverConfig.GetString("ExternalName", string.Empty); if (m_GridName == string.Empty) @@ -156,11 +180,16 @@ namespace OpenSim.Services.HypergridService string gridName = gatekeeper.ServerURI; m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); - + if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); else + { success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); + if (success) + // Report them as nowhere + m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero); + } if (!success) { @@ -169,7 +198,12 @@ namespace OpenSim.Services.HypergridService // restore the old travel info lock (m_TravelingAgents) - m_TravelingAgents[agentCircuit.SessionID] = old; + { + if (old == null) + m_TravelingAgents.Remove(agentCircuit.SessionID); + else + m_TravelingAgents[agentCircuit.SessionID] = old; + } return false; } @@ -179,6 +213,7 @@ namespace OpenSim.Services.HypergridService if (clientIP != null) m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; + return true; } @@ -291,6 +326,213 @@ namespace OpenSim.Services.HypergridService return false; } + public List StatusNotification(List friends, UUID foreignUserID, bool online) + { + if (m_FriendsService == null || m_PresenceService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing"); + return new List(); + } + + List localFriendsOnline = new List(); + + m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count); + + // First, let's double check that the reported friends are, indeed, friends of that user + // And let's check that the secret matches + List usersToBeNotified = new List(); + foreach (string uui in friends) + { + UUID localUserID; + string secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret)) + { + FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID); + foreach (FriendInfo finfo in friendInfos) + { + if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret)) + { + // great! + usersToBeNotified.Add(localUserID.ToString()); + } + } + } + } + + // Now, let's send the notifications + m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count); + + // First, let's send notifications to local users who are online in the home grid + PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray()); + if (friendSessions != null && friendSessions.Length > 0) + { + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents + { + friendSession = pinfo; + break; + } + + if (friendSession != null) + { + ForwardStatusNotificationToSim(friendSession.RegionID, foreignUserID, friendSession.UserID, online); + usersToBeNotified.Remove(friendSession.UserID.ToString()); + UUID id; + if (UUID.TryParse(friendSession.UserID, out id)) + localFriendsOnline.Add(id); + + } + } + + // Lastly, let's notify the rest who may be online somewhere else + foreach (string user in usersToBeNotified) + { + UUID id = new UUID(user); + if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName) + { + string url = m_TravelingAgents[id].GridExternalName; + // forward + m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url); + } + } + + // and finally, let's send the online friends + if (online) + { + return localFriendsOnline; + } + else + return new List(); + } + + protected void ForwardStatusNotificationToSim(UUID regionID, UUID foreignUserID, string user, bool online) + { + UUID userID; + if (UUID.TryParse(user, out userID)) + { + if (m_FriendsLocalSimConnector != null) + { + m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline")); + m_FriendsLocalSimConnector.StatusNotify(foreignUserID, userID, online); + } + else + { + GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID); + if (region != null) + { + m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); + m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online); + } + } + } + } + + public List GetOnlineFriends(UUID foreignUserID, List friends) + { + List online = new List(); + + if (m_FriendsService == null || m_PresenceService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing"); + return online; + } + + m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count); + + // First, let's double check that the reported friends are, indeed, friends of that user + // And let's check that the secret matches and the rights + List usersToBeNotified = new List(); + foreach (string uui in friends) + { + UUID localUserID; + string secret = string.Empty, tmp = string.Empty; + if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret)) + { + FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID); + foreach (FriendInfo finfo in friendInfos) + { + if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret) && + (finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1)) + { + // great! + usersToBeNotified.Add(localUserID.ToString()); + } + } + } + } + + // Now, let's find out their status + m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", usersToBeNotified.Count); + + // First, let's send notifications to local users who are online in the home grid + PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray()); + if (friendSessions != null && friendSessions.Length > 0) + { + foreach (PresenceInfo pi in friendSessions) + { + UUID presenceID; + if (UUID.TryParse(pi.UserID, out presenceID)) + online.Add(presenceID); + } + } + + return online; + } + + public Dictionary GetServerURLs(UUID userID) + { + if (m_UserAccountService == null) + { + m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get server URLs because user account service is missing"); + return new Dictionary(); + } + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero /*!!!*/, userID); + if (account != null) + return account.ServiceURLs; + + return new Dictionary(); + } + + public string LocateUser(UUID userID) + { + foreach (TravelingAgentInfo t in m_TravelingAgents.Values) + { + if (t == null) + { + m_log.ErrorFormat("[USER AGENT SERVICE]: Oops! Null TravelingAgentInfo. Please report this on mantis"); + continue; + } + if (t.UserID == userID && !m_GridName.Equals(t.GridExternalName)) + return t.GridExternalName; + } + + return string.Empty; + } + + public string GetUUI(UUID userID, UUID targetUserID) + { + // Let's see if it's a local user + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, targetUserID); + if (account != null) + return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ; + + // Let's try the list of friends + FriendInfo[] friends = m_FriendsService.GetFriends(userID); + if (friends != null && friends.Length > 0) + { + foreach (FriendInfo f in friends) + if (f.Friend.StartsWith(targetUserID.ToString())) + { + // Let's remove the secret + UUID id; string tmp = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret)) + return f.Friend.Replace(secret, "0"); + } + } + + return string.Empty; + } } class TravelingAgentInfo diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 0ddd5e53a9..1664f3b3e1 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -74,7 +74,9 @@ namespace OpenSim.Services.Interfaces public interface IFriendsService { FriendInfo[] GetFriends(UUID PrincipalID); - bool StoreFriend(UUID PrincipalID, string Friend, int flags); + FriendInfo[] GetFriends(string PrincipalID); + bool StoreFriend(string PrincipalID, string Friend, int flags); bool Delete(UUID PrincipalID, string Friend); + bool Delete(string PrincipalID, string Friend); } } diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs similarity index 76% rename from OpenSim/Services/Interfaces/IGatekeeperService.cs rename to OpenSim/Services/Interfaces/IHypergridServices.cs index aac82936b0..220caef007 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -54,9 +54,34 @@ namespace OpenSim.Services.Interfaces bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); void LogoutAgent(UUID userID, UUID sessionID); GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); + Dictionary GetServerURLs(UUID userID); + + string LocateUser(UUID userID); + // Tries to get the universal user identifier for the targetUserId + // on behalf of the userID + string GetUUI(UUID userID, UUID targetUserID); + + // Returns the local friends online + List StatusNotification(List friends, UUID userID, bool online); + //List GetOnlineFriends(UUID userID, List friends); bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); bool VerifyAgent(UUID sessionID, string token); bool VerifyClient(UUID sessionID, string reportedIP); } + + public interface IInstantMessage + { + bool IncomingInstantMessage(GridInstantMessage im); + bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner); + } + public interface IFriendsSimConnector + { + bool StatusNotify(UUID userID, UUID friendID, bool online); + } + + public interface IInstantMessageSimConnector + { + bool SendInstantMessage(GridInstantMessage im); + } } diff --git a/OpenSim/Services/InventoryService/InventoryService.cs b/OpenSim/Services/InventoryService/InventoryService.cs index e543337c71..73dd06ac3a 100644 --- a/OpenSim/Services/InventoryService/InventoryService.cs +++ b/OpenSim/Services/InventoryService/InventoryService.cs @@ -340,6 +340,9 @@ namespace OpenSim.Services.InventoryService List itemsList = new List(); itemsList.AddRange(m_Database.getInventoryInFolder(folderID)); + +// m_log.DebugFormat( +// "[INVENTORY SERVICE]: Found {0} items in folder {1} for {2}", itemsList.Count, folderID, userID); return itemsList; } @@ -385,8 +388,9 @@ namespace OpenSim.Services.InventoryService // See IInventoryServices public virtual bool AddItem(InventoryItemBase item) { - m_log.DebugFormat( - "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2}", item.Name, item.ID, item.Folder); +// m_log.DebugFormat( +// "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2} for {3}", +// item.Name, item.ID, item.Folder, item.Owner); m_Database.addInventoryItem(item); diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 0af35c84ac..eeab67a666 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService { public class XInventoryService : ServiceBase, IInventoryService { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); + //private static readonly ILog m_log = + // LogManager.GetLogger( + // MethodBase.GetCurrentMethod().DeclaringType); protected IXInventoryData m_Database; protected bool m_AllowDelete = true; @@ -385,14 +385,18 @@ namespace OpenSim.Services.InventoryService public virtual bool AddItem(InventoryItemBase item) { -// m_log.DebugFormat( -// "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); + //m_log.DebugFormat( + // "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner); return m_Database.StoreItem(ConvertFromOpenSim(item)); } public virtual bool UpdateItem(InventoryItemBase item) { + if (!m_AllowDelete) + if (item.AssetType == (sbyte)AssetType.Link || item.AssetType == (sbyte)AssetType.LinkFolder) + return false; + return m_Database.StoreItem(ConvertFromOpenSim(item)); } @@ -411,12 +415,30 @@ namespace OpenSim.Services.InventoryService public virtual bool DeleteItems(UUID principalID, List itemIDs) { if (!m_AllowDelete) - return false; - - // Just use the ID... *facepalms* - // - foreach (UUID id in itemIDs) - m_Database.DeleteItems("inventoryID", id.ToString()); + { + // We must still allow links and links to folders to be deleted, otherwise they will build up + // in the player's inventory until they can no longer log in. Deletions of links due to code bugs or + // similar is inconvenient but on a par with accidental movement of items. The original item is never + // touched. + foreach (UUID id in itemIDs) + { + if (!m_Database.DeleteItems( + new string[] { "inventoryID", "assetType" }, + new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() })) + { + m_Database.DeleteItems( + new string[] { "inventoryID", "assetType" }, + new string[] { id.ToString(), ((sbyte)AssetType.LinkFolder).ToString() }); + } + } + } + else + { + // Just use the ID... *facepalms* + // + foreach (UUID id in itemIDs) + m_Database.DeleteItems("inventoryID", id.ToString()); + } return true; } diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index ddc8855145..f68c078c39 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -621,7 +621,19 @@ namespace OpenSim.Services.LLLoginService if (finfo.TheirFlags == -1) continue; LLLoginResponse.BuddyList.BuddyInfo buddyitem = new LLLoginResponse.BuddyList.BuddyInfo(finfo.Friend); - buddyitem.BuddyID = finfo.Friend; + // finfo.Friend may not be a simple uuid + UUID friendID = UUID.Zero; + if (UUID.TryParse(finfo.Friend, out friendID)) + buddyitem.BuddyID = finfo.Friend; + else + { + string tmp; + if (Util.ParseUniversalUserIdentifier(finfo.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) + buddyitem.BuddyID = friendID.ToString(); + else + // junk entry + continue; + } buddyitem.BuddyRightsHave = (int)finfo.TheirFlags; buddyitem.BuddyRightsGiven = (int)finfo.MyFlags; buddylistreturn.AddNewBuddy(buddyitem); diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 2ca2d1566c..5d1779a15c 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -516,6 +516,7 @@ namespace OpenSim.Services.LLLoginService // free uri form // e.g. New Moon&135&46 New Moon@osgrid.org:8002&153&34 where = "url"; + GridRegion region = null; Regex reURI = new Regex(@"^uri:(?[^&]+)&(?\d+)&(?\d+)&(?\d+)$"); Match uriMatch = reURI.Match(startLocation); if (uriMatch == null) @@ -546,8 +547,18 @@ namespace OpenSim.Services.LLLoginService } else { - m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions.", startLocation); - return null; + m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region"); + region = FindAlternativeRegion(scopeID); + if (region != null) + { + where = "safe"; + return region; + } + else + { + m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions and no alternative found.", startLocation); + return null; + } } } return regions[0]; @@ -575,7 +586,8 @@ namespace OpenSim.Services.LLLoginService if (parts.Length > 1) UInt32.TryParse(parts[1], out port); - GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); +// GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); + region = FindForeignRegion(domainName, port, regionName, out gatekeeper); return region; } } @@ -804,16 +816,13 @@ namespace OpenSim.Services.LLLoginService // Old style: get the service keys from the DB foreach (KeyValuePair kvp in account.ServiceURLs) { - if (kvp.Value == null || (kvp.Value != null && kvp.Value.ToString() == string.Empty)) - { - aCircuit.ServiceURLs[kvp.Key] = m_LoginServerConfig.GetString(kvp.Key, string.Empty); - } - else + if (kvp.Value != null) { aCircuit.ServiceURLs[kvp.Key] = kvp.Value; + + if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/")) + aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/"; } - if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/")) - aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/"; } // New style: service keys start with SRV_; override the previous @@ -821,16 +830,29 @@ namespace OpenSim.Services.LLLoginService if (keys.Length > 0) { + bool newUrls = false; IEnumerable serviceKeys = keys.Where(value => value.StartsWith("SRV_")); foreach (string serviceKey in serviceKeys) { string keyName = serviceKey.Replace("SRV_", ""); - aCircuit.ServiceURLs[keyName] = m_LoginServerConfig.GetString(serviceKey, string.Empty); - if (!aCircuit.ServiceURLs[keyName].ToString().EndsWith("/")) - aCircuit.ServiceURLs[keyName] = aCircuit.ServiceURLs[keyName] + "/"; + string keyValue = m_LoginServerConfig.GetString(serviceKey, string.Empty); + if (!keyValue.EndsWith("/")) + keyValue = keyValue + "/"; + + if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && account.ServiceURLs[keyName] != keyValue)) + { + account.ServiceURLs[keyName] = keyValue; + newUrls = true; + } + aCircuit.ServiceURLs[keyName] = keyValue; m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]); } + + // The grid operator decided to override the defaults in the + // [LoginService] configuration. Let's store the correct ones. + if (newUrls) + m_UserAccountService.StoreUserAccount(account); } } diff --git a/OpenSim/Tests/Clients/InstantMessage/IMClient.cs b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs new file mode 100644 index 0000000000..e7304a24dc --- /dev/null +++ b/OpenSim/Tests/Clients/InstantMessage/IMClient.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; + +using OpenMetaverse; +using log4net; +using log4net.Appender; +using log4net.Layout; + +using OpenSim.Framework; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Connectors.InstantMessage; + +namespace OpenSim.Tests.Clients.InstantMessage +{ + public class IMClient + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + public static void Main(string[] args) + { + ConsoleAppender consoleAppender = new ConsoleAppender(); + consoleAppender.Layout = + new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"); + log4net.Config.BasicConfigurator.Configure(consoleAppender); + + string serverURI = "http://127.0.0.1:8002"; + GridInstantMessage im = new GridInstantMessage(); + im.fromAgentID = new Guid(); + im.toAgentID = new Guid(); + im.message = "Hello"; + im.imSessionID = new Guid(); + + bool success = InstantMessageServiceConnector.SendInstantMessage(serverURI, im); + + if (success) + m_log.InfoFormat("[IM CLIENT]: Successfully IMed {0}", serverURI); + else + m_log.InfoFormat("[IM CLIENT]: failed to IM {0}", serverURI); + + System.Console.WriteLine("\n"); + } + + } +} diff --git a/OpenSim/Tests/Common/Setup/AssetHelpers.cs b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs similarity index 88% rename from OpenSim/Tests/Common/Setup/AssetHelpers.cs rename to OpenSim/Tests/Common/Helpers/AssetHelpers.cs index d572249997..aa55bcdc69 100644 --- a/OpenSim/Tests/Common/Setup/AssetHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/AssetHelpers.cs @@ -56,10 +56,24 @@ namespace OpenSim.Tests.Common AssetBase asset = CreateAsset(UUID.Random(), AssetType.Notecard, "hello", creatorId); scene.AssetService.Store(asset); return asset; - } + } + + /// + /// Create an asset from the given object. + /// + /// + /// The hexadecimal last part of the UUID for the asset created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" + /// will be used. + /// + /// + /// + public static AssetBase CreateAsset(int assetUuidTail, SceneObjectGroup sog) + { + return CreateAsset(new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", assetUuidTail)), sog); + } /// - /// Create an asset from the given scene object. + /// Create an asset from the given object. /// /// /// @@ -76,7 +90,7 @@ namespace OpenSim.Tests.Common /// /// Create an asset from the given scene object. /// - /// + /// /// The hexadecimal last part of the UUID for the asset created. A UUID of the form "00000000-0000-0000-0000-{0:XD12}" /// will be used. /// diff --git a/OpenSim/Tests/Common/Setup/BaseRequestHandlerTestHelper.cs b/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs similarity index 97% rename from OpenSim/Tests/Common/Setup/BaseRequestHandlerTestHelper.cs rename to OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs index eaf8b39ac0..49c99c5de4 100644 --- a/OpenSim/Tests/Common/Setup/BaseRequestHandlerTestHelper.cs +++ b/OpenSim/Tests/Common/Helpers/BaseRequestHandlerHelpers.cs @@ -34,9 +34,9 @@ using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Tests.Common.Mock; -namespace OpenSim.Tests.Common.Setup +namespace OpenSim.Tests.Common { - public class BaseRequestHandlerTestHelper + public class BaseRequestHandlerHelpers { private static string[] m_emptyStringArray = new string[] { }; diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs similarity index 99% rename from OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs rename to OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs index d1224099e2..bef0481edf 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneSetupHelpers.cs @@ -49,7 +49,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; using OpenSim.Services.Interfaces; using OpenSim.Tests.Common.Mock; -namespace OpenSim.Tests.Common.Setup +namespace OpenSim.Tests.Common { /// /// Helpers for setting up scenes. diff --git a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs new file mode 100644 index 0000000000..5215c3404d --- /dev/null +++ b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs @@ -0,0 +1,89 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Tests.Common +{ + /// + /// Utility functions for carrying out task inventory tests. + /// + /// + public static class TaskInventoryHelpers + { + /// + /// Add a notecard item to the given part. + /// + /// + /// + /// The item that was added + public static TaskInventoryItem AddNotecard(Scene scene, SceneObjectPart part) + { + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + scene.AssetService.Store(ncAsset); + TaskInventoryItem ncItem + = new TaskInventoryItem + { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid, + Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard }; + part.Inventory.AddInventoryItem(ncItem, true); + + return ncItem; + } + + /// + /// Add a scene object item to the given part. + /// + /// + /// + /// + /// + public static TaskInventoryItem AddSceneObject(Scene scene, SceneObjectPart sop, string itemName, UUID id) + { + SceneObjectGroup taskSceneObject = SceneSetupHelpers.CreateSceneObject(1, UUID.Zero); + AssetBase taskSceneObjectAsset = AssetHelpers.CreateAsset(0x10, taskSceneObject); + scene.AssetService.Store(taskSceneObjectAsset); + TaskInventoryItem taskSceneObjectItem + = new TaskInventoryItem + { Name = itemName, AssetID = taskSceneObjectAsset.FullID, ItemID = id, + Type = (int)AssetType.Object, InvType = (int)InventoryType.Object }; + sop.Inventory.AddInventoryItem(taskSceneObjectItem, true); + + return taskSceneObjectItem; + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs similarity index 93% rename from OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs rename to OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs index d01521dbdb..d924ecd5c8 100644 --- a/OpenSim/Tests/Common/Setup/UserProfileTestUtils.cs +++ b/OpenSim/Tests/Common/Helpers/UserAccountHelpers.cs @@ -31,12 +31,12 @@ using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -namespace OpenSim.Tests.Common.Setup +namespace OpenSim.Tests.Common { /// /// Utility functions for carrying out user profile related tests. /// - public static class UserProfileTestUtils + public static class UserAccountHelpers { // /// // /// Create a test user with a standard inventory @@ -117,17 +117,20 @@ namespace OpenSim.Tests.Common.Setup // } public static UserAccount CreateUserWithInventory(Scene scene) + { + return CreateUserWithInventory(scene, 99); + } + + public static UserAccount CreateUserWithInventory(Scene scene, int uuidTail) { return CreateUserWithInventory( - scene, "Bill", "Bailey", UUID.Parse("00000000-0000-0000-0000-000000000099"), "troll"); + scene, "Bill", "Bailey", new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", uuidTail)), "troll"); } public static UserAccount CreateUserWithInventory( Scene scene, string firstName, string lastName, UUID userId, string pw) { - UserAccount ua - = new UserAccount(userId) - { FirstName = firstName, LastName = lastName }; + UserAccount ua = new UserAccount(userId) { FirstName = firstName, LastName = lastName }; CreateUserWithInventory(scene, ua, pw); return ua; } diff --git a/OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs similarity index 52% rename from OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs rename to OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index 135c50eb74..1703597549 100644 --- a/OpenSim/Tests/Common/Setup/UserInventoryTestUtils.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -26,32 +26,57 @@ */ using System; +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; namespace OpenSim.Tests.Common { /// - /// Utility functions for carrying out user inventory related tests. + /// Utility functions for carrying out user inventory tests. /// - public static class UserInventoryTestUtils + public static class UserInventoryHelpers { public static readonly string PATH_DELIMITER = "/"; - public static InventoryItemBase CreateInventoryItem( - Scene scene, string itemName, UUID itemId, string folderPath, UUID userId) + /// + /// Creates a notecard in the objects folder and specify an item id. + /// + /// + /// + /// + /// + /// + public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID userId) { + return CreateInventoryItem(scene, itemName, UUID.Random(), userId); + } + + /// + /// Creates a notecard in the objects folder and specify an item id. + /// + /// + /// + /// + /// + /// + public static InventoryItemBase CreateInventoryItem(Scene scene, string itemName, UUID itemId, UUID userId) + { + AssetBase asset = AssetHelpers.CreateAsset(scene, userId); InventoryItemBase item = new InventoryItemBase(); item.Name = itemName; - item.AssetID = AssetHelpers.CreateAsset(scene, userId).FullID; + item.AssetID = asset.FullID; item.ID = itemId; + item.Owner = userId; + item.AssetType = asset.Type; + item.InvType = (int)InventoryType.Notecard; + + InventoryFolderBase folder = scene.InventoryService.GetFolderForType(userId, AssetType.Notecard); - // Really quite bad since the objs folder could be moved in the future and confuse the tests - InventoryFolderBase objsFolder = scene.InventoryService.GetFolderForType(userId, AssetType.Object); - - item.Folder = objsFolder.ID; + item.Folder = folder.ID; scene.AddInventoryItem(item); return item; @@ -111,5 +136,60 @@ namespace OpenSim.Tests.Common else return newFolder; } + + /// + /// Get the inventory folder that matches the path name. If there are multiple folders then only the first + /// is returned. + /// + /// + /// + /// + /// null if no folder matching the path was found + public static InventoryFolderBase GetInventoryFolder(IInventoryService inventoryService, UUID userId, string path) + { + List folders = GetInventoryFolders(inventoryService, userId, path); + + if (folders.Count != 0) + return folders[0]; + else + return null; + } + + /// + /// Get the inventory folders that match the path name. + /// + /// + /// + /// + /// An empty list if no matching folders were found + public static List GetInventoryFolders(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindFolderByPath(inventoryService, userId, path); + } + + /// + /// Get the inventory item that matches the path name. If there are multiple items then only the first + /// is returned. + /// + /// + /// + /// + /// null if no item matching the path was found + public static InventoryItemBase GetInventoryItem(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindItemByPath(inventoryService, userId, path); + } + + /// + /// Get the inventory items that match the path name. + /// + /// + /// + /// + /// An empty list if no matching items were found. + public static List GetInventoryItems(IInventoryService inventoryService, UUID userId, string path) + { + return InventoryArchiveUtils.FindItemsByPath(inventoryService, userId, path); + } } } \ No newline at end of file diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 210a780f04..8f2f805547 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -647,7 +647,7 @@ namespace OpenSim.Tests.Common.Mock { } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) + public virtual void SendDialog(string objectname, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Tests/Common/Mock/TestLandChannel.cs b/OpenSim/Tests/Common/Mock/TestLandChannel.cs index c3134b3bc1..0e4dfb9eee 100644 --- a/OpenSim/Tests/Common/Mock/TestLandChannel.cs +++ b/OpenSim/Tests/Common/Mock/TestLandChannel.cs @@ -40,10 +40,12 @@ namespace OpenSim.Tests.Common.Mock public class TestLandChannel : ILandChannel { private Scene m_scene; + private List m_parcels; public TestLandChannel(Scene scene) { m_scene = scene; + m_parcels = new List(); } public List ParcelsNearPoint(Vector3 position) @@ -53,12 +55,19 @@ namespace OpenSim.Tests.Common.Mock public List AllParcels() { - return new List(); + return m_parcels; } public void Clear(bool setupDefaultParcel) { - // Intentionally blank since we don't save any parcel data in the test channel + m_parcels.Clear(); + + if (setupDefaultParcel) + { + ILandObject obj = new LandObject(UUID.Zero, false, m_scene); + obj.LandData.Name = "Your Parcel"; + m_parcels.Add(obj); + } } protected ILandObject GetNoLand() diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index 6139a9d5d9..a6dec04461 100755 Binary files a/bin/OpenMetaverse.Rendering.Meshmerizer.dll and b/bin/OpenMetaverse.Rendering.Meshmerizer.dll differ diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index e3b729c6ee..ed0a2d6446 100755 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index 69c4e9b9df..37ec47a7a8 100755 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index cab014d534..6f7fbacb5a 100755 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c5df0dba58..813c5b828c 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -635,50 +635,13 @@ ;; You need to load a local service for a standalone, and a remote service ;; for a grid region. Use one of the lines below, as appropriate - ;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section + ;; If you're using Freeswitch on a standalone then you will also need to configure the [FreeswitchService] section in config-include/StandaloneCommon.ini ; LocalServiceModule = OpenSim.Services.FreeswitchService.dll:FreeswitchService ; LocalServiceModule = OpenSim.Services.Connectors.dll:RemoteFreeswitchConnector ;; If using a remote connector, specify the server URL ; FreeswitchServiceURL = http://my.grid.server:8004/fsapi - -[FreeswitchService] - ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! - ;; !!!!!!STANDALONE ONLY!!!!!! - ;; !!!!!!!!!!!!!!!!!!!!!!!!!!! - ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone - ;; This has to be set for the FreeSWITCH service to work - ;ServerAddress = 127.0.0.1 - - ;; The following configuration parameters are optional - - ;; By default, this is the same as the ServerAddress - ; Realm = 127.0.0.1 - - ;; By default, this is the same as the ServerAddress on port 5060 - ; SIPProxy = 127.0.0.1:5060 - - ;; Default is 5000ms - ; DefaultTimeout = 5000 - - ;; The dial plan context. Default is "default" - ; Context = default - - ;; Currently unused - ; UserName = freeswitch - - ;; Currently unused - ; Password = password - - ;; The following parameters are for STUN = Simple Traversal of UDP through NATs - ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal - ;; stun.freeswitch.org is not guaranteed to be running so use it in - ;; production at your own risk - ; EchoServer = 127.0.0.1 - ; EchoPort = 50505 - ; AttemptSTUN = false - [Groups] ;# {Enabled} {} {Enable groups?} {true false} false ;; Enables the groups module diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index b32d198343..fa5392dc42 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1174,6 +1174,10 @@ ; - the third field is a number indicating how many scripts failed to compile ; - "oar error" if supplied, provides the error message from the OAR load channel_notify = -800 + ; - disallow logins while scripts are loading + login_disable = false + ; - send an alert as json to a service + ; alert_uri = "http://myappserver.net/my_handler/" [MRM] diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 0d79e77b7a..812d2659fa 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -21,7 +21,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -107,6 +107,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" ;; The IP address of your FreeSWITCH server. + ;; This address must be reachable by viewers. ; ServerAddress = 127.0.0.1 ;; The following configuration parameters are optional @@ -216,6 +217,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 SRV_InventoryServerURI = "http://127.0.0.1:8002" SRV_AssetServerURI = "http://127.0.0.1:8002" SRV_ProfileServerURI = "http://127.0.0.1:8002/user" + SRV_FriendsServerURI = "http://127.0.0.1:8002" + SRV_IMServerURI = "http://127.0.0.1:8002" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. @@ -316,7 +319,10 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" GridService = "OpenSim.Services.GridService.dll:GridService" GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" - + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" + ; If you run this user agent server behind a proxy, set this to true ; HasProxy = false @@ -344,3 +350,29 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" ProfileServerURI = "http://127.0.0.1:8002/user" + +[HGFriendsService] + LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + ; This should always be true in the Robust config + InGatekeeper = True + +[Messaging] + ; If you have an Offline IM server, set the vars in this section, so that + ; incomming IMs to local users from foreign grids can be saved + ; + ;# {OfflineMessageURL} {OfflineMessageModule:OfflineMessageModule} {URL of offline messaging service} {} + ;; URL of web service for offline message storage + ; OfflineMessageURL = http://yourserver/Offline.php + + ;; Control whether group messages are forwarded to offline users. + ;; Default is true. + ;; This applies to the core groups module (Flotsam) only. + ; ForwardOfflineGroupMessages = true + diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index cc018f8867..5d0ec09d7d 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -21,7 +21,6 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 [Network] port = 8003 - ; HTTPS for "Out of band" management applications such as the remote admin ; module. May specify https_main = True to make the main http server ; use https or "False" to make the main server HTTP @@ -92,6 +91,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" ;; The IP address of your FreeSWITCH server. + ;; This address must be reachable by viewers. ; ServerAddress = 127.0.0.1 ;; The following configuration parameters are optional diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index ce5588eb1b..52205732f0 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -27,6 +27,9 @@ SimulationServiceInConnector = true LibraryModule = true +[Profile] + Module = "BasicProfileModule" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index bc8bc0fdab..e2e6459c58 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -14,6 +14,14 @@ ; Uncomment this line if you are using MySQL and want to use a different database for estates ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ; MSSQL + ; Uncomment these lines if you want to use MSSQL storage + ; Change the connection string to your db details + ; The value for server property is shown in your SQL Server Management Studio login dialog. + ; (This sample is the default of express edition) + ;StorageProvider = "OpenSim.Data.MSSQL.dll" + ;ConnectionString = "Server=localhost\SQLEXPRESS;Database=opensim;User Id=opensim; password=***;" + [AssetService] DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" @@ -46,6 +54,13 @@ ;; Robust server in port 8002, but not always) Gatekeeper="http://mygridserver.com:8002" +[Messaging] + ; === HG ONLY === + ;; change this to the address of your Gatekeeper service + ;; (usually bundled with the rest of the services in one + ;; Robust server in port 8002, but not always) + Gatekeeper = "http://mygridserver.com:8002" + [AvatarService] ; ; change this to your grid-wide grid server @@ -85,14 +100,21 @@ [HGInventoryAccessModule] ; ; === HG ONLY === - ; Change this to your profile server + ; Change this to your server ; accessible from other grids ; ProfileServerURI = "http://mygridserver.com:8002/user" + Gatekeeper = "http://mygridserver.com:8002" ;; If you want to protect your assets from being copied by foreign visitors ;; uncomment the next line. You may want to do this on sims that have licensed content. ; OutboundPermission = False +[UserAgentService] + ; + ; === HG ONLY === + ; Change this to your user agent server (HG robust) + ; + UserAgentServerURI = "http://mygridserver.com:8002" [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index 5142d90eda..b8e66c2733 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -24,12 +24,16 @@ EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + FriendsModule = "HGFriendsModule" LandServiceInConnector = true NeighbourServiceInConnector = true SimulationServiceInConnector = true LibraryModule = true +[Profile] + Module = "BasicProfileModule" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -63,3 +67,13 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[Messaging] + MessageTransferModule = HGMessageTransferModule + LureModule = HGLureModule + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.Connectors.dll:GridServicesConnector" + PresenceService = "OpenSim.Services.Connectors.dll:PresenceServicesConnector" + UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" \ No newline at end of file diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 6355d09041..4ff1a269bf 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -22,6 +22,9 @@ LLLoginServiceInConnector = true GridInfoServiceInConnector = true +[Profile] + Module = "BasicProfileModule" + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 67efa11564..7359bba62f 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -16,6 +16,14 @@ ; Uncomment this line if you are using MySQL and want to use a different database for estates ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" + ; MSSQL + ; Uncomment these lines if you want to use MSSQL storage + ; Change the connection string to your db details + ; The value for server property is shown in your SQL Server Management Studio login dialog. + ; (This sample is the default of express edition) + ;StorageProvider = "OpenSim.Data.MSSQL.dll" + ;ConnectionString = "Server=localhost\SQLEXPRESS;Database=opensim;User Id=opensim; password=***;" + [AssetService] DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" AssetLoaderArgs = "assets/AssetSets.xml" @@ -28,6 +36,7 @@ [HGInventoryAccessModule] ProfileServerURI = "http://127.0.0.1:9000/profiles" + Gatekeeper = "http://127.0.0.1:9000" ;; If you want to protect your assets from being copied by foreign visitors ;; uncomment the next line. You may want to do this on sims that have licensed content. @@ -70,6 +79,11 @@ ;; change this to the address of your simulator Gatekeeper="http://127.0.0.1:9000" +[Messaging] + ; === HG ONLY === + ;; change this to the address of your simulator + Gatekeeper = "http://127.0.0.1:9000" + [LibraryModule] ; Set this if you want to change the name of the OpenSim Library ;LibraryName = "My World's Library" @@ -82,6 +96,8 @@ SRV_InventoryServerURI = "http://127.0.0.1:9000" SRV_AssetServerURI = "http://127.0.0.1:9000" SRV_ProfileServerURI = "http://127.0.0.1:9000" + SRV_FriendsServerURI = "http://127.0.0.1:9000" + SRV_IMServerURI = "http://127.0.0.1:9000" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. @@ -124,6 +140,42 @@ ;AllowedClients = "" ;DeniedClients = "" +[FreeswitchService] + ;; If FreeSWITCH is not being used then you don't need to set any of these parameters + ;; + ;; The IP address of your FreeSWITCH server. The common case is for this to be the same as the server running the OpenSim standalone + ;; This has to be set for the FreeSWITCH service to work + ;; This address must be reachable by viewers. + ;ServerAddress = 127.0.0.1 + + ;; The following configuration parameters are optional + + ;; By default, this is the same as the ServerAddress + ; Realm = 127.0.0.1 + + ;; By default, this is the same as the ServerAddress on port 5060 + ; SIPProxy = 127.0.0.1:5060 + + ;; Default is 5000ms + ; DefaultTimeout = 5000 + + ;; The dial plan context. Default is "default" + ; Context = default + + ;; Currently unused + ; UserName = freeswitch + + ;; Currently unused + ; Password = password + + ;; The following parameters are for STUN = Simple Traversal of UDP through NATs + ;; See http://wiki.freeswitch.org/wiki/NAT_Traversal + ;; stun.freeswitch.org is not guaranteed to be running so use it in + ;; production at your own risk + ; EchoServer = 127.0.0.1 + ; EchoPort = 50505 + ; AttemptSTUN = false + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 486f22e698..8480a77bbd 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -20,6 +20,7 @@ AvatarServices = "LocalAvatarServicesConnector" EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" + FriendsModule = "HGFriendsModule" InventoryServiceInConnector = true AssetServiceInConnector = true @@ -31,6 +32,13 @@ AuthenticationServiceInConnector = true SimulationServiceInConnector = true +[Profile] + Module = "BasicProfileModule" + +[Messaging] + MessageTransferModule = HGMessageTransferModule + LureModule = HGLureModule + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -125,6 +133,9 @@ GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" GridService = "OpenSim.Services.GridService.dll:GridService" GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" ;; The interface that local users get when they are in other grids @@ -140,6 +151,18 @@ LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" +[HGFriendsService] + LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + InGatekeeper = True + + ;; This should always be the very last thing on this file [Includes] Include-Common = "config-include/StandaloneCommon.ini" diff --git a/bin/mssql_connection.ini.example b/bin/mssql_connection.ini.example deleted file mode 100644 index e0ae7bace9..0000000000 --- a/bin/mssql_connection.ini.example +++ /dev/null @@ -1,18 +0,0 @@ -; The IniConfig.cs that parses this file by just finding the first key={value} in the whole text so comments aren't really honoured. -; Also, this algorithm can probably lead to 'amusing' results in unfortunate cases. - -[mssqlconnection] -data_source=\SQLEXPRESS -initial_catalog=database -persist_security_info=True -user_id=username -password=password - -; These entries are only for if you, for some reason, wish to customize your user server table names. -; Do note that if you change the table names, you might have to change the sql resources too manually -; If ommitted, default values will be used. - -userstablename=users -userfriendstablename=userfriends -agentstablename=agents -regionstablename=regions diff --git a/prebuild.xml b/prebuild.xml index f493035fae..fa2ece3d1f 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1291,6 +1291,7 @@ + @@ -1616,7 +1617,6 @@ - @@ -2679,6 +2679,32 @@ + + + + ../../../../bin/ + + + + + ../../../../bin/ + + + + ../../../../bin/ + + + + + + + + + + + + +